<?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/smartwatches" rel="self" type="application/rss+xml" />
                            <title><![CDATA[ Latest from Tom's Guide in Smartwatches ]]></title>
                <link>https://www.tomsguide.com/wellness/smartwatches</link>
        <description><![CDATA[ All the latest smartwatches content from the Tom's Guide team ]]></description>
                                    <lastBuildDate>Fri, 18 Sep 2026 10:30:00 +0000</lastBuildDate>
                            <language>en</language>
                                <item>
                                                            <title><![CDATA[ 3 reasons why the Pixel Watch 5 Stephen Curry edition is totally worth it ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The Pixel Watch 5 comes in several configurations, including the special edition Stephen Curry model with an upgraded woven sports strap and a custom watch face. </p><p>As of publication, Google only offers the Steph Curry edition in a 45mm case size with LTE connectivity. It costs $50 more than the standard <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review">Google Pixel Watch 5</a> 45mm LTE model. Sure, you can call me crazy, but I think the higher price is totally worth it. </p><p>Of course, this isn’t Google’s first collab with the basketball superstar. The brand also debuted a special edition Fitbit Air Steph Curry model for an extra $30 with a similar-style upgraded sports loop designed with athletes in mind. </p><div class="product"><a data-dimension112="b4f54c06-b2e9-11f1-8e5c-79003eb3fa33" data-action="Deal Block" data-label="Pixel Watch 5 Stephen Curry edition" data-dimension48="Pixel Watch 5 Stephen Curry edition" href="https://www.bestbuy.com/product/google-pixel-watch-5-45mm-lte-stephen-curry-special-edition-one-size-2026/J39TC8X3CS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:894px;"><p class="vanilla-image-block" style="padding-top:110.51%;"><img id="NY97woHcoSRJ2ym3vZ2jTU" name="Screenshot 2026-09-17 at 3.45.30 PM" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/NY97woHcoSRJ2ym3vZ2jTU-1920-80.png" mos="" align="middle" fullscreen="" width="894" height="988" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.bestbuy.com/product/google-pixel-watch-5-45mm-lte-stephen-curry-special-edition-one-size-2026/J39TC8X3CS" target="_blank" rel="nofollow" data-dimension112="b4f54c06-b2e9-11f1-8e5c-79003eb3fa33" data-action="Deal Block" data-label="Pixel Watch 5 Stephen Curry edition" data-dimension48="Pixel Watch 5 Stephen Curry edition" data-dimension25="">Pixel Watch 5 Stephen Curry edition:</a></strong><br>The Pixel Watch 5 Stephen Curry Special Edition model features an upgraded knit sports loop strap that’s specially designed to wick away moisture, stretch, flex, and breathe during workouts.<a class="view-deal button" href="https://www.bestbuy.com/product/google-pixel-watch-5-45mm-lte-stephen-curry-special-edition-one-size-2026/J39TC8X3CS" target="_blank" rel="nofollow" data-dimension112="b4f54c06-b2e9-11f1-8e5c-79003eb3fa33" data-action="Deal Block" data-label="Pixel Watch 5 Stephen Curry edition" data-dimension48="Pixel Watch 5 Stephen Curry edition" data-dimension25="">View Deal</a></p></div><p>When I reviewed the <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">Fitbit Air,</a> the Steph Curry strap quickly proved to be my favorite of the t<a href="https://www.tomsguide.com/wellness/fitness-trackers/i-tested-all-3-fitbit-air-accessory-bands-and-theres-a-clear-winner">hree Air straps I tested</a>. And the same things that made me fall in love with that strap also apply to the Pixel Watch 5 Steph Curry loop. </p><p>With that in mind, here are the three biggest reasons I prefer the Pixel Watch 5 Stephen Curry edition to the standard Pixel Watch 5. </p><h3 class="article-body__section" id="section-1-quicker-to-dry-and-better-breathability"><span>1. Quicker to dry and better breathability </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="XcATSWZtBRwGxfxvXmF75Z" name="PixelWatch5-Curry-02" alt="Close-up of the Google Pixel Watch 5 Stephen Curry special edition smartwatch next to the Fitbit Air Stephen Curry model" src="https://cdn.mos.cms.futurecdn.net/XcATSWZtBRwGxfxvXmF75Z-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>First, a quick clarification: Aside from the special watch face, there are no hardware or software differences between the Google Pixel Watch 5 and the Pixel Watch 5 Steph Curry edition. The cases are identical, as are the under-the-hood components. </p><p>What truly sets the two smartwatches apart is the quality of the included strap. The Steph Curry loop is made from a soft, flexible, sweat-wicking woven polyester-elastane mix. Unlike the silicone strap that comes with most of the standard Pixel Watch 5 options, the Steph Curry strap is <em>actually</em> comfortable to sweat in. </p><p>Not only is the woven material highly breathable, but the strap is also treated with a waterproof coating to further add to the sweat-wicking capabilities.</p><h3 class="article-body__section" id="section-2-infinitely-adjustable-and-all-around-comfier"><span>2. Infinitely adjustable and all-around comfier </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="kKDTmkxLubEQTC2TRMJtEZ" name="PixelWatch5-Curry-04" alt="Close-up of the Google Pixel Watch 5 Stephen Curry special edition smartwatch's Velcro strap next to a standard Pixel Watch 5 with a silicone strap" src="https://cdn.mos.cms.futurecdn.net/kKDTmkxLubEQTC2TRMJtEZ-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>Another key reason I prefer the Steph Curry Pixel Watch 5 over the standard version is how the straps attach to your wrist. Google’s standard silicone strap uses a variant of the traditional pin-and-buckle style strap, which relegates you to choosing one of nine tightness options.</p><p>The Steph Curry loop, on the other hand, is secured in place via Velcro, giving users a near-infinite degree of adjustability. The underside of the upgraded strap also features raised silicone “ribs” that run parallel along its length. </p><p>These help keep the Pixel Watch 5 from moving around on your wrist, even during intense workouts and/or when sweating profusely. </p><h3 class="article-body__section" id="section-3-it-looks-cool-on-the-wrist"><span>3. It looks cool on the wrist </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="Vn8jbc7yxFs7ojYyMZvD2Z" name="PixelWatch5-Curry-01" alt="Close-up of the Google Pixel Watch 5 Stephen Curry special edition smartwatch" src="https://cdn.mos.cms.futurecdn.net/Vn8jbc7yxFs7ojYyMZvD2Z-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>Last but not least, I prefer the Pixel Watch 5 Steph Curry special edition to the standard model because the strap simply looks a lot snazzier IMHO. I’m a big fan of the black, orange, and rye woven pattern (though a black, green, and rye would be my ultimate choice).</p><p>While this may sound superficial, at the end of the day, there’s no benefit in an unworn wearable, even if you own one of the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> of 2026 (like the Pixel Watch 5). This is to say, an aesthetically pleasing strap, in some ways, is just as important as reliable fitness tracking tech. </p><p>What are your thoughts on the Pixel Watch 5 Stephen Curry model? Do you think it’s worth the extra $50? Let me know in the comments below. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OR99yW"></div>                            </div>                            <script src="https://kwizly.com/embed/OR99yW.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/smartwatches/pixel-watch-5-vs-samsung-galaxy-watch-9-5-key-differences-you-need-to-know"><strong>Pixel Watch 5 vs Samsung Galaxy Watch 9 — 5 key differences you need to know</strong></a><strong></strong></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/exclusive-google-pm-says-the-pixel-watch-5-is-like-an-airbag-on-your-wrist-thanks-to-features-like-breathing-emergency-detection"><strong>Exclusive: Inside the Pixel Watch 5's breathing emergency detection — and why it's like an 'airbag on your wrist'</strong></a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-2026-vs-fitbit-flex-2013-how-much-has-wearable-tech-actually-progressed-in-13-years"><strong>Fitbit Air (2026) vs Fitbit Flex (2013) — how much has wearable tech actually progressed in 13 years?</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/3-reasons-why-the-pixel-watch-5-stephen-curry-edition-is-totally-worth-it</link>
                                                                            <description>
                            <![CDATA[ The Pixel Watch 5 Stephen Curry edition is $50 more than the standard model. Here's why I think it's worth the extra cost. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">sSdkCot2mX3rqkuJ3X2kPo</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/hZApiN6QFLUF6PAKDfYJ8Z-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 18 Sep 2026 10:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Google Gemini]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[AI]]></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/hZApiN6QFLUF6PAKDfYJ8Z-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Google Pixel Watch 5 Stephen Curry special edition smartwatch next to the standard Pixel Watch 5 model]]></media:description>                                                            <media:text><![CDATA[Close-up of the Google Pixel Watch 5 Stephen Curry special edition smartwatch next to the standard Pixel Watch 5 model]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Google Pixel Watch 5 Stephen Curry special edition smartwatch next to the standard Pixel Watch 5 model]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/hZApiN6QFLUF6PAKDfYJ8Z-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The Pixel Watch 5 comes in several configurations, including the special edition Stephen Curry model with an upgraded woven sports strap and a custom watch face. </p><p>As of publication, Google only offers the Steph Curry edition in a 45mm case size with LTE connectivity. It costs $50 more than the standard <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review">Google Pixel Watch 5</a> 45mm LTE model. Sure, you can call me crazy, but I think the higher price is totally worth it. </p><p>Of course, this isn’t Google’s first collab with the basketball superstar. The brand also debuted a special edition Fitbit Air Steph Curry model for an extra $30 with a similar-style upgraded sports loop designed with athletes in mind. </p><div class="product"><a data-dimension112="b4f54c06-b2e9-11f1-8e5c-79003eb3fa33" data-action="Deal Block" data-label="Pixel Watch 5 Stephen Curry edition" data-dimension48="Pixel Watch 5 Stephen Curry edition" href="https://www.bestbuy.com/product/google-pixel-watch-5-45mm-lte-stephen-curry-special-edition-one-size-2026/J39TC8X3CS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:894px;"><p class="vanilla-image-block" style="padding-top:110.51%;"><img id="NY97woHcoSRJ2ym3vZ2jTU" name="Screenshot 2026-09-17 at 3.45.30 PM" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/NY97woHcoSRJ2ym3vZ2jTU-1920-80.png" mos="" align="middle" fullscreen="" width="894" height="988" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.bestbuy.com/product/google-pixel-watch-5-45mm-lte-stephen-curry-special-edition-one-size-2026/J39TC8X3CS" target="_blank" rel="nofollow" data-dimension112="b4f54c06-b2e9-11f1-8e5c-79003eb3fa33" data-action="Deal Block" data-label="Pixel Watch 5 Stephen Curry edition" data-dimension48="Pixel Watch 5 Stephen Curry edition" data-dimension25="">Pixel Watch 5 Stephen Curry edition:</a></strong><br>The Pixel Watch 5 Stephen Curry Special Edition model features an upgraded knit sports loop strap that’s specially designed to wick away moisture, stretch, flex, and breathe during workouts.<a class="view-deal button" href="https://www.bestbuy.com/product/google-pixel-watch-5-45mm-lte-stephen-curry-special-edition-one-size-2026/J39TC8X3CS" target="_blank" rel="nofollow" data-dimension112="b4f54c06-b2e9-11f1-8e5c-79003eb3fa33" data-action="Deal Block" data-label="Pixel Watch 5 Stephen Curry edition" data-dimension48="Pixel Watch 5 Stephen Curry edition" data-dimension25="">View Deal</a></p></div><p>When I reviewed the <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">Fitbit Air,</a> the Steph Curry strap quickly proved to be my favorite of the t<a href="https://www.tomsguide.com/wellness/fitness-trackers/i-tested-all-3-fitbit-air-accessory-bands-and-theres-a-clear-winner">hree Air straps I tested</a>. And the same things that made me fall in love with that strap also apply to the Pixel Watch 5 Steph Curry loop. </p><p>With that in mind, here are the three biggest reasons I prefer the Pixel Watch 5 Stephen Curry edition to the standard Pixel Watch 5. </p><h3 class="article-body__section" id="section-1-quicker-to-dry-and-better-breathability"><span>1. Quicker to dry and better breathability </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="XcATSWZtBRwGxfxvXmF75Z" name="PixelWatch5-Curry-02" alt="Close-up of the Google Pixel Watch 5 Stephen Curry special edition smartwatch next to the Fitbit Air Stephen Curry model" src="https://cdn.mos.cms.futurecdn.net/XcATSWZtBRwGxfxvXmF75Z-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>First, a quick clarification: Aside from the special watch face, there are no hardware or software differences between the Google Pixel Watch 5 and the Pixel Watch 5 Steph Curry edition. The cases are identical, as are the under-the-hood components. </p><p>What truly sets the two smartwatches apart is the quality of the included strap. The Steph Curry loop is made from a soft, flexible, sweat-wicking woven polyester-elastane mix. Unlike the silicone strap that comes with most of the standard Pixel Watch 5 options, the Steph Curry strap is <em>actually</em> comfortable to sweat in. </p><p>Not only is the woven material highly breathable, but the strap is also treated with a waterproof coating to further add to the sweat-wicking capabilities.</p><h3 class="article-body__section" id="section-2-infinitely-adjustable-and-all-around-comfier"><span>2. Infinitely adjustable and all-around comfier </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="kKDTmkxLubEQTC2TRMJtEZ" name="PixelWatch5-Curry-04" alt="Close-up of the Google Pixel Watch 5 Stephen Curry special edition smartwatch's Velcro strap next to a standard Pixel Watch 5 with a silicone strap" src="https://cdn.mos.cms.futurecdn.net/kKDTmkxLubEQTC2TRMJtEZ-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>Another key reason I prefer the Steph Curry Pixel Watch 5 over the standard version is how the straps attach to your wrist. Google’s standard silicone strap uses a variant of the traditional pin-and-buckle style strap, which relegates you to choosing one of nine tightness options.</p><p>The Steph Curry loop, on the other hand, is secured in place via Velcro, giving users a near-infinite degree of adjustability. The underside of the upgraded strap also features raised silicone “ribs” that run parallel along its length. </p><p>These help keep the Pixel Watch 5 from moving around on your wrist, even during intense workouts and/or when sweating profusely. </p><h3 class="article-body__section" id="section-3-it-looks-cool-on-the-wrist"><span>3. It looks cool on the wrist </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="Vn8jbc7yxFs7ojYyMZvD2Z" name="PixelWatch5-Curry-01" alt="Close-up of the Google Pixel Watch 5 Stephen Curry special edition smartwatch" src="https://cdn.mos.cms.futurecdn.net/Vn8jbc7yxFs7ojYyMZvD2Z-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>Last but not least, I prefer the Pixel Watch 5 Steph Curry special edition to the standard model because the strap simply looks a lot snazzier IMHO. I’m a big fan of the black, orange, and rye woven pattern (though a black, green, and rye would be my ultimate choice).</p><p>While this may sound superficial, at the end of the day, there’s no benefit in an unworn wearable, even if you own one of the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> of 2026 (like the Pixel Watch 5). This is to say, an aesthetically pleasing strap, in some ways, is just as important as reliable fitness tracking tech. </p><p>What are your thoughts on the Pixel Watch 5 Stephen Curry model? Do you think it’s worth the extra $50? Let me know in the comments below. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OR99yW"></div>                            </div>                            <script src="https://kwizly.com/embed/OR99yW.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/smartwatches/pixel-watch-5-vs-samsung-galaxy-watch-9-5-key-differences-you-need-to-know"><strong>Pixel Watch 5 vs Samsung Galaxy Watch 9 — 5 key differences you need to know</strong></a><strong></strong></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/exclusive-google-pm-says-the-pixel-watch-5-is-like-an-airbag-on-your-wrist-thanks-to-features-like-breathing-emergency-detection"><strong>Exclusive: Inside the Pixel Watch 5's breathing emergency detection — and why it's like an 'airbag on your wrist'</strong></a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-2026-vs-fitbit-flex-2013-how-much-has-wearable-tech-actually-progressed-in-13-years"><strong>Fitbit Air (2026) vs Fitbit Flex (2013) — how much has wearable tech actually progressed in 13 years?</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Garmin Fenix 9 Pro review: a titanium titan for your biggest adventures ]]></title>
                                                                                                <dc:content><![CDATA[ <p>When it comes to high-end adventure watches, the Garmin Fenix has been in a league of its own for a while. No other sports watch or smartwatch can match the range and depth of features you get on a Fenix, and the strongest competition to the Garmin Fenix 9 Pro comes from past models of the watch.</p><p>The Fenix 9 Pro is the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watch</a> yet, with upgrades on the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-8-pro-review-the-greatest-fenix-yet">Fenix 8 Pro </a>including an all-titanium case and faster maps. These build on the best-in-class sports tracking, training analysis and navigation features you get on the Fenix 9 Pro, which also has some useful smart features and impressive battery life.</p><p>I’ve been testing the Garmin Fenix 9 Pro 51mm watch and it’s undoubtedly outstanding, but the high price means that the Garmin Fenix 8 Pro, and even the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-8-review">Garmin Fenix 8</a>, look better value to me in sales, especially as many new features on the Fenix 9 Pro are rolling back to those models.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-price-and-availability"><span>Garmin Fenix 9 Pro 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:2193px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="RBtqfRZWixw6rWG8yaNYCE" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:61,l:131,cw:2193,ch:1234,q:80/RBtqfRZWixw6rWG8yaNYCE.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 Garmin Fenix 9 Pro launched in August 2026 alongside the Garmin Fenix 9. There are a lot of different options in the Garmin Fenix 9 line-up, with three sizes and two display types to pick between, along with making the choice between a standard and Pro model of the watch.</p><p>For the standard Fenix 9, you’ll pay from $999/£859, whereas the Fenix 9 Pro costs from $1,029/£999, or $1,199/£1,029 if you want a watch with inReach connectivity.</p><p>The standard Fenix 9 only comes with an AMOLED display but you can choose from three sizes — 43mm, 47mm and 51mm.</p><p>You get the same three sizes options with the AMOLED Fenix 9 Pro, but if you want the Fenix 9 Pro Solar, which has a memory-in-pixel (MIP) screen, you can only pick from 47mm or 51mm sizes.</p><p>Along with the option of inReach connectivity, the main upgrades on the Fenix 9 Pro compared to the standard Fenix 9 are an all-titanium case, a brighter display, and a green mode on the built-in flashlight.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-specs-compared"><span>Garmin Fenix 9 Pro review: specs compared</span></h2><div ><table><caption>Garmin Fenix 9 AMOLED vs Garmin Fenix 9 Pro AMOLED vs Garmin Fenix 8 Pro AMOLED</caption><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Garmin Fenix 8 Pro </strong></p></td><td  ><p><strong>Garmin Fenix 9</strong></p></td><td  ><p><strong>Garmin Fenix 9 Pro </strong></p></td></tr><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p>$1,199-$1,299</p></td><td  ><p>$999-$1,149</p></td><td  ><p>$1,099-$1,399</p></td></tr><tr><td class="firstcol " ><p><strong>Size</strong></p></td><td  ><p>47mm or 51mm</p></td><td  ><p>43mm, 47mm or 51mm</p></td><td  ><p>43mm, 47mm or 51mm</p></td></tr><tr><td class="firstcol " ><p><strong>Thickness</strong></p></td><td  ><p>16mm (47mm), 16.5mm (51mm)</p></td><td  ><p>13.8mm (43mm & 47mm), 14.7mm (51mm)</p></td><td  ><p>13.3mm (43mm),<br>13.8mm (47mm), 15.8mm (51mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Case weight</strong></p></td><td  ><p>56g (47mm), 65g (51mm)</p></td><td  ><p>44g (47mm), 53g (47mm), 65g (51mm)</p></td><td  ><p>62g (43mm), 78g (47mm), 99g (51mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>Sapphire crystal</p></td><td  ><p>Sapphire crystal</p></td><td  ><p>Sapphire crystal</p></td></tr><tr><td class="firstcol " ><p><strong>Connectivity</strong></p></td><td  ><p>LTE & satellite</p></td><td  ><p>None</p></td><td  ><p>LTE & satellite</p></td></tr><tr><td class="firstcol " ><p><strong>Smartwatch battery life (raise to wake)</strong></p></td><td  ><p>15 days (47mm), 27 days (51m)</p></td><td  ><p>10 days (43mm), 16 days (47mm), 29 days (51mm)</p></td><td  ><p>10 days (43 mm), 18 days (47mm), 31 days (51mm)</p></td></tr><tr><td class="firstcol " ><p><strong>GPS battery life (multi-band/max accuracy)</strong></p></td><td  ><p>23 hours (47mm), 41 hours (51mm)</p></td><td  ><p>15 hours (43mm), 25 hours (47mm), 45 hours (51mm)</p></td><td  ><p>18 hours (43mm), 32 hours (47mm), 56 hours (51mm)</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-design-and-display"><span>Garmin Fenix 9 Pro review: design and display</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:1220px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="KRVb2p8ALEZZPff9P7UUhH" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/KRVb2p8ALEZZPff9P7UUhH-1920-80.jpg" mos="" align="middle" fullscreen="" width="1220" height="686" 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’ve tested every model of the Garmin Fenix since the Fenix 5 Pro, and the Fenix 9 Pro is the best-looking version of the watch yet.</p><p>The all-titanium case makes a much bigger difference than I expected when I saw the launch notes on the watch. It doesn’t add weight, but makes the Fenix 9 Pro look and feel more <em>impressive</em>, and boosts its appeal for all-day wear.</p><p>I’ve been testing the 51mm Fenix 9 Pro, which has the largest screen on a Garmin watch yet, and the 1.5in AMOLED is very bright and easy to read even at an angle in always-on mode. </p><p>It’s interesting that Garmin dropped the MicroLED model from the Fenix line-up, presumably because it required a thicker watch with shorter battery life, but it’s not hugely missed given the quality of the AMOLED screen on the Fenix 9 Pro.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="HsEvn6zkCC3qyFB7uE4uB7" name="Garmin Fenix 9 Pro flashlight" alt="Garmin Fenix 9 Pro flashlight" src="https://cdn.mos.cms.futurecdn.net/HsEvn6zkCC3qyFB7uE4uB7-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’s no denying this is a big watch though, and even if you opt for the 43mm or 47mm models of the watch the Fenix is still relatively thick and heavy compared with Garmin’s Forerunner and Venu watches.</p><p>Even with my skinny wrists, I did get used to the Fenix 9 Pro 51mm and didn’t mind wearing it all the time, but I prefer the fit and feel of a thinner watch like the <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-garmin-forerunner-970-for-six-months-here-are-my-long-term-pros-and-cons">Garmin Forerunner 970</a>, which also doesn’t catch on jacket sleeves as often.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="fGrGUfaLTVf2k5dJJNWLTo" name="Garmin Fenix 9 Pro flashlight" alt="Garmin Fenix 9 Pro flashlight" src="https://cdn.mos.cms.futurecdn.net/fGrGUfaLTVf2k5dJJNWLTo-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’s a built-in flashlight on top of the watch, which is one of the best features on Garmin watches in my opinion, and something that other brands are starting to introduce.</p><p>On top of the white and red modes you get on all Garmin watches with flashlights, the Fenix 9 Pro’s flashlight also has a green option, which can be useful when looking at maps and for certain sports like fishing.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-sports-tracking-and-training-analysis"><span>Garmin Fenix 9 Pro review: sports tracking and training analysis</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="fmyNQr5xEFmfBnspp9XLwC" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/fmyNQr5xEFmfBnspp9XLwC-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 not easy to find ways to upgrade Garmin’s sports features at this point, but there are some new updates on the Fenix 9 Pro, many of which will roll back to older models.</p><p>These include upgrades to the rowing support on the watch, with FTP and VO2 max scores for indoor rowing, and the option to add your pack weight when rucking. </p><p>You can now also combine multiple activities into a ‘Garmin Epic’, which collates all the data from workouts you select to be included. This can be useful for looking at an entire marathon training block, for example, or for a multi-day hike or ultramarathon.</p><p>Garmin has also upgraded the Stamina feature on the watch, which aims to show your energy reserves in real time during activities to help you work out how hard you can push.</p><p>I still find this is a hard metric to trust when pushing all-out during races myself, but it can be a useful tool to stop yourself going out too hard at the start of longer events.</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.29%;"><img id="VzUcM6wtvXKraohPwDUeaH" name="Garmin Fenix 9 Pro Readiness" alt="Garmin Fenix 9 Pro Readiness" src="https://cdn.mos.cms.futurecdn.net/VzUcM6wtvXKraohPwDUeaH-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1441" 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>These updates build upon what was already an incredible array of sports tracking modes and stats, and the most comprehensive suite of training analysis tools you’ll find on a sports watch.</p><p>Along with standard stuff like <a href="https://www.tomsguide.com/wellness/fitness/what-is-chronic-training-load-and-why-is-it-important-to-measure-i-asked-an-expert-to-find-out">chronic training load</a>, Garmin has some unique analysis stats, like running tolerance, which gives you a total mileage for the past week of running that takes into account the intensity of your runs, and an overall endurance score.</p><p>Not everyone will want or need all of this data, but it’s all there if you do, and Garmin offers more than other sports watches. I’m a fan of its well-established Training Readiness tool as a good way to collate a lot of information into one handy score to judge the state of your body each day.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-gps-and-heart-rate-accuracy"><span>Garmin Fenix 9 Pro review: GPS and heart rate accuracy</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:1494px;"><p class="vanilla-image-block" style="padding-top:56.29%;"><img id="72dr5XxQf9wqUucVszw9Ek" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/72dr5XxQf9wqUucVszw9Ek-1920-80.jpg" mos="" align="middle" fullscreen="" width="1494" height="841" 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 checked the accuracy of the optical heart rate monitor on the Fenix 9 Pro against a chest strap for a variety of workouts, and checked its GPS tracks after runs, including during a half marathon where it measured just about the exact race distance.</p><p>Garmin has changed how it labels its various GPS modes, but the Max Accuracy option is what I used, which uses the most accurate multi-band GPS mode on the watch when required.</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:2193px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="vNtZJAU3RmfcY4UTJdFYFm" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:66,l:164,cw:2193,ch:1234,q:80/vNtZJAU3RmfcY4UTJdFYFm.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 its GPS accuracy to be more or less spot on during my outdoor activities, and Garmin continues to be as good or better than everyone else in this area in my opinion.</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="A9a7vFYaji4r7ogFgowQ7E" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/A9a7vFYaji4r7ogFgowQ7E-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 heart rate accuracy on the Fenix 9 Pro was also very good, matching a chest strap closely on runs and bike rides. The optical sensor is not as good as a chest strap or upper arm band for strength workouts, but even there I saw mostly accurate results.</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:39.22%;"><img id="v8vUrxbNgyqjVPXDDfMFnj" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro HR" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro HR" src="https://cdn.mos.cms.futurecdn.net/v8vUrxbNgyqjVPXDDfMFnj-1920-80.jpg" mos="" align="middle" fullscreen="" width="1920" height="753" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: DC Rainmaker Analyzer)</span></figcaption></figure><p>One challenge for the heart rate accuracy of the watch could be its size if you opt for the 51mm watch, as sometimes I find it hard to get the snug fit required for reliable optical tracking with bigger watches, but I had no notable problems with the Fenix 9 Pro in my testing.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-connectivity"><span>Garmin Fenix 9 Pro review: connectivity</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="JzL85TmsbDndusgcZgihgG" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/JzL85TmsbDndusgcZgihgG-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 inReach model of the Fenix 9 Pro offers LTE and satellite connectivity, a feature introduced on the Garmin Fenix 8 Pro.</p><p>You need a Garmin subscription to use these services, which costs between $7.99 and $49.99 depending on the level you need, which mostly relates to how many messages you plan to send and calls you might make.</p><p>There’s a free trial available of the features, after which you get free SOS messaging for 12 months, but will have to pay for other services.</p><p>These connectivity features are one of the main reasons to look at the top Fenix models over older watches, or the Forerunner line-up, and will appeal greatly to those who like to take their adventures off the grid, as well as those who just like to leave their phone behind on a run while staying in touch if required.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-battery-life"><span>Garmin Fenix 9 Pro review: battery life</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:2288px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CRidumohi3kqmXdaEqr4dE" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:70,l:106,cw:2288,ch:1287,q:80/CRidumohi3kqmXdaEqr4dE.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 battery life of the Fenix 9 Pro varies greatly depending on which size you go for, but if you opt for the largest 51mm watch I tested, it’s incredibly long-lasting.</p><p>I had the screen set to always-on and used it for outdoor runs almost every day in the most accurate (and power intensive) GPS setting, and the Fenix 9 Pro 51mm lasted me 10-11 days on a charge.</p><p>This can easily be extended by setting the screen to raise to wake, or using the other GPS settings, or if you mainly exercise indoors and don’t use the GPS.</p><p>The only AMOLED sports watch I’ve tested that can outdo the Fenix 9 Pro on battery life is the <a href="https://www.tomsguide.com/wellness/smartwatches/i-swapped-my-garmin-fenix-8-pro-for-the-suunto-vertical-2-heres-5-things-i-liked-and-5-i-disliked">Suunto Vertical 2</a>, though some MIP options like the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-enduro-3-review">Garmin Enduro 3</a> and Coros Vertix 2S will last longer thanks to their less power-hungry displays.</p><p>If you opt for the 43mm or 47mm watch the battery life does drop off significantly, and the 43mm watch my colleague Jane McGuire has been testing will have you reaching for a charger every three or four days if you use the always-on screen.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-maps-and-navigation"><span>Garmin Fenix 9 Pro review: maps and navigation </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:2075px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="eZHBCPefduMUnbd4Z2jNq5" name="Garmin Fenix 9 Pro maps" alt="Garmin Fenix 9 Pro maps" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:86,l:279,cw:2075,ch:1167,q:80/eZHBCPefduMUnbd4Z2jNq5.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 lot of sports watches now offer maps, including on relatively affordable models like the<a href="https://www.tomsguide.com/wellness/smartwatches/coros-just-added-offline-maps-to-its-most-affordable-sports-watch-but-theres-a-catch"> Coros Pace 4</a>, but Garmin’s maps and navigation tools remain the best available.</p><p>That’s mainly because its watches have ‘routable’ maps that actually know where you are and can create routes for you on the fly. Other watch brands tend to have non-routable maps that just overlay your trail on an image of the map, which is more than good enough for most occasions, but not quite as handy if you’re out in the wilderness and get lost.</p><p>The Fenix 9 Pro has all of Garmin’s usual maps and navigation tools, but adds some upgrades you don’t get on other watches from the brand.</p><p>Firstly, the maps load faster when panning and zooming, and your heading updates more quickly too. Secondly, there’s a new perspective viewpoint, which tilts the maps slightly to make it clearer where you are.</p><p>These updates are useful, if not necessarily gamechangers. I don’t find that the maps load too slowly for me on other Garmins, but any boost in speed is appreciated, and I do prefer the perspective view.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-smart-features"><span>Garmin Fenix 9 Pro review: smart features</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:1138px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="wCwMhzAaLBBg23oxq7kGBJ" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/wCwMhzAaLBBg23oxq7kGBJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1138" height="640" 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>Along with its connectivity features, the Fenix 9 Pro packs in a lot of useful smart features. It’s not as impressive on this front as true smartwatch like the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-review">Apple Watch Ultra 4</a>, but Garmin does offer a lot more smart features than rival sports watches.</p><p>You get NFC payments through Garmin Pay, music storage with the ability to link up to several streaming services, including Spotify, for offline playback, and a lot of customization options for your watch face and widgets.</p><p>The Garmin Connect IQ app store is not as well-stocked as the App Store or Google Play, but it does contain a lot of watch faces, data fields and other widgets that can improve the experience on the watch.</p><p>While it’s still clearly a sports watch over a smartwatch, the Fenix 9 Pro does offer a lot of handy features for day to day use.</p><h2 class="article-body__section" id="section-should-you-buy-the-garmin-fenix-9-pro"><span>Should you buy the Garmin Fenix 9 Pro?</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:1468px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="v2G5yZakdCDJF4tSsFpyAJ" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 8 Pro and Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2G5yZakdCDJF4tSsFpyAJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1468" height="826" 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 simply want the best adventure watch available, regardless of price, then the Garmin Fenix 9 Pro is the watch to go for. The new design is great, its sports and navigation features are as good as it gets, and you can pick a size to suit your wrist and battery life requirements.</p><p>However, I’m not sure it’s a big enough update on the Garmin Fenix 8 Pro that I wouldn’t recommend going for the older watch instead, and if you don’t need the connectivity feature on those watches, the Garmin Fenix 8 might be an even better value buy.</p><p>Both older models are also regularly on sale, so you could save hundreds of dollars by buying one instead of the Fenix 9 Pro. Certainly if you have one of those watches I don’t see a pressing need to upgrade, but older Fenix owners will really notice the benefits of the newer model.</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="NmEaDfEmcWjvSpjY2JqRsj" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/NmEaDfEmcWjvSpjY2JqRsj-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 Garmin Forerunner 970 also offers most of the same great features, aside from connectivity, in a lighter, slimmer package that I prefer the fit of as a thin-wristed runner. </p><p>Outside the Garmin line-up, I think the Apple Watch Ultra 4 offers a strong alternative to the Garmin Fenix 9 Pro, providing you’re not put off by its three-day battery life. It has a rugged design, good sports tracking, and LTE and satellite connectivity, and better smart features than the Fenix 9 Pro.</p><p>The Fenix is now on a yearly update cycle and Garmin made some big updates to the watch last year by adding LTE and satellite connectivity, so a smaller refresh this year isn’t unexpected. </p><p>Next year’s Garmin Fenix 10 might see bigger changes, but right now the Fenix 9 Pro is the<a href="https://www.tomsguide.com/us/best-gps-watches,review-2638.html"> best sports watch </a>you can get for outdoor adventures.</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-pro-review-a-titanium-titan-for-your-biggest-adventures</link>
                                                                            <description>
                            <![CDATA[ The Garmin Fenix 9 Pro is not a major upgrade on the Fenix 8 Pro, but offers enough in the way of updates to ensure it’s the best version of the watch yet. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">7rA3rBpTo3b7iuTrZS7HZf</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/QnRCAqAvvyHFTsWhVNrKZ8-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 18 Sep 2026 06:30:00 +0000</pubDate>                                                                                                                                <updated>Fri, 18 Sep 2026 07:52:10 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Nick Harris-Fry ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/J5Jjp49GUVjLZEbjEkTex-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/QnRCAqAvvyHFTsWhVNrKZ8-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Garmin Fenix 9 Pro]]></media:description>                                                            <media:text><![CDATA[Garmin Fenix 9 Pro]]></media:text>
                                <media:title type="plain"><![CDATA[Garmin Fenix 9 Pro]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/QnRCAqAvvyHFTsWhVNrKZ8-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When it comes to high-end adventure watches, the Garmin Fenix has been in a league of its own for a while. No other sports watch or smartwatch can match the range and depth of features you get on a Fenix, and the strongest competition to the Garmin Fenix 9 Pro comes from past models of the watch.</p><p>The Fenix 9 Pro is the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watch</a> yet, with upgrades on the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-8-pro-review-the-greatest-fenix-yet">Fenix 8 Pro </a>including an all-titanium case and faster maps. These build on the best-in-class sports tracking, training analysis and navigation features you get on the Fenix 9 Pro, which also has some useful smart features and impressive battery life.</p><p>I’ve been testing the Garmin Fenix 9 Pro 51mm watch and it’s undoubtedly outstanding, but the high price means that the Garmin Fenix 8 Pro, and even the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-8-review">Garmin Fenix 8</a>, look better value to me in sales, especially as many new features on the Fenix 9 Pro are rolling back to those models.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-price-and-availability"><span>Garmin Fenix 9 Pro 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:2193px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="RBtqfRZWixw6rWG8yaNYCE" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:61,l:131,cw:2193,ch:1234,q:80/RBtqfRZWixw6rWG8yaNYCE.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 Garmin Fenix 9 Pro launched in August 2026 alongside the Garmin Fenix 9. There are a lot of different options in the Garmin Fenix 9 line-up, with three sizes and two display types to pick between, along with making the choice between a standard and Pro model of the watch.</p><p>For the standard Fenix 9, you’ll pay from $999/£859, whereas the Fenix 9 Pro costs from $1,029/£999, or $1,199/£1,029 if you want a watch with inReach connectivity.</p><p>The standard Fenix 9 only comes with an AMOLED display but you can choose from three sizes — 43mm, 47mm and 51mm.</p><p>You get the same three sizes options with the AMOLED Fenix 9 Pro, but if you want the Fenix 9 Pro Solar, which has a memory-in-pixel (MIP) screen, you can only pick from 47mm or 51mm sizes.</p><p>Along with the option of inReach connectivity, the main upgrades on the Fenix 9 Pro compared to the standard Fenix 9 are an all-titanium case, a brighter display, and a green mode on the built-in flashlight.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-specs-compared"><span>Garmin Fenix 9 Pro review: specs compared</span></h2><div ><table><caption>Garmin Fenix 9 AMOLED vs Garmin Fenix 9 Pro AMOLED vs Garmin Fenix 8 Pro AMOLED</caption><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Garmin Fenix 8 Pro </strong></p></td><td  ><p><strong>Garmin Fenix 9</strong></p></td><td  ><p><strong>Garmin Fenix 9 Pro </strong></p></td></tr><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p>$1,199-$1,299</p></td><td  ><p>$999-$1,149</p></td><td  ><p>$1,099-$1,399</p></td></tr><tr><td class="firstcol " ><p><strong>Size</strong></p></td><td  ><p>47mm or 51mm</p></td><td  ><p>43mm, 47mm or 51mm</p></td><td  ><p>43mm, 47mm or 51mm</p></td></tr><tr><td class="firstcol " ><p><strong>Thickness</strong></p></td><td  ><p>16mm (47mm), 16.5mm (51mm)</p></td><td  ><p>13.8mm (43mm & 47mm), 14.7mm (51mm)</p></td><td  ><p>13.3mm (43mm),<br>13.8mm (47mm), 15.8mm (51mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Case weight</strong></p></td><td  ><p>56g (47mm), 65g (51mm)</p></td><td  ><p>44g (47mm), 53g (47mm), 65g (51mm)</p></td><td  ><p>62g (43mm), 78g (47mm), 99g (51mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>Sapphire crystal</p></td><td  ><p>Sapphire crystal</p></td><td  ><p>Sapphire crystal</p></td></tr><tr><td class="firstcol " ><p><strong>Connectivity</strong></p></td><td  ><p>LTE & satellite</p></td><td  ><p>None</p></td><td  ><p>LTE & satellite</p></td></tr><tr><td class="firstcol " ><p><strong>Smartwatch battery life (raise to wake)</strong></p></td><td  ><p>15 days (47mm), 27 days (51m)</p></td><td  ><p>10 days (43mm), 16 days (47mm), 29 days (51mm)</p></td><td  ><p>10 days (43 mm), 18 days (47mm), 31 days (51mm)</p></td></tr><tr><td class="firstcol " ><p><strong>GPS battery life (multi-band/max accuracy)</strong></p></td><td  ><p>23 hours (47mm), 41 hours (51mm)</p></td><td  ><p>15 hours (43mm), 25 hours (47mm), 45 hours (51mm)</p></td><td  ><p>18 hours (43mm), 32 hours (47mm), 56 hours (51mm)</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-design-and-display"><span>Garmin Fenix 9 Pro review: design and display</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:1220px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="KRVb2p8ALEZZPff9P7UUhH" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/KRVb2p8ALEZZPff9P7UUhH-1920-80.jpg" mos="" align="middle" fullscreen="" width="1220" height="686" 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’ve tested every model of the Garmin Fenix since the Fenix 5 Pro, and the Fenix 9 Pro is the best-looking version of the watch yet.</p><p>The all-titanium case makes a much bigger difference than I expected when I saw the launch notes on the watch. It doesn’t add weight, but makes the Fenix 9 Pro look and feel more <em>impressive</em>, and boosts its appeal for all-day wear.</p><p>I’ve been testing the 51mm Fenix 9 Pro, which has the largest screen on a Garmin watch yet, and the 1.5in AMOLED is very bright and easy to read even at an angle in always-on mode. </p><p>It’s interesting that Garmin dropped the MicroLED model from the Fenix line-up, presumably because it required a thicker watch with shorter battery life, but it’s not hugely missed given the quality of the AMOLED screen on the Fenix 9 Pro.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="HsEvn6zkCC3qyFB7uE4uB7" name="Garmin Fenix 9 Pro flashlight" alt="Garmin Fenix 9 Pro flashlight" src="https://cdn.mos.cms.futurecdn.net/HsEvn6zkCC3qyFB7uE4uB7-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’s no denying this is a big watch though, and even if you opt for the 43mm or 47mm models of the watch the Fenix is still relatively thick and heavy compared with Garmin’s Forerunner and Venu watches.</p><p>Even with my skinny wrists, I did get used to the Fenix 9 Pro 51mm and didn’t mind wearing it all the time, but I prefer the fit and feel of a thinner watch like the <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-garmin-forerunner-970-for-six-months-here-are-my-long-term-pros-and-cons">Garmin Forerunner 970</a>, which also doesn’t catch on jacket sleeves as often.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="fGrGUfaLTVf2k5dJJNWLTo" name="Garmin Fenix 9 Pro flashlight" alt="Garmin Fenix 9 Pro flashlight" src="https://cdn.mos.cms.futurecdn.net/fGrGUfaLTVf2k5dJJNWLTo-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’s a built-in flashlight on top of the watch, which is one of the best features on Garmin watches in my opinion, and something that other brands are starting to introduce.</p><p>On top of the white and red modes you get on all Garmin watches with flashlights, the Fenix 9 Pro’s flashlight also has a green option, which can be useful when looking at maps and for certain sports like fishing.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-sports-tracking-and-training-analysis"><span>Garmin Fenix 9 Pro review: sports tracking and training analysis</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="fmyNQr5xEFmfBnspp9XLwC" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/fmyNQr5xEFmfBnspp9XLwC-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 not easy to find ways to upgrade Garmin’s sports features at this point, but there are some new updates on the Fenix 9 Pro, many of which will roll back to older models.</p><p>These include upgrades to the rowing support on the watch, with FTP and VO2 max scores for indoor rowing, and the option to add your pack weight when rucking. </p><p>You can now also combine multiple activities into a ‘Garmin Epic’, which collates all the data from workouts you select to be included. This can be useful for looking at an entire marathon training block, for example, or for a multi-day hike or ultramarathon.</p><p>Garmin has also upgraded the Stamina feature on the watch, which aims to show your energy reserves in real time during activities to help you work out how hard you can push.</p><p>I still find this is a hard metric to trust when pushing all-out during races myself, but it can be a useful tool to stop yourself going out too hard at the start of longer events.</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.29%;"><img id="VzUcM6wtvXKraohPwDUeaH" name="Garmin Fenix 9 Pro Readiness" alt="Garmin Fenix 9 Pro Readiness" src="https://cdn.mos.cms.futurecdn.net/VzUcM6wtvXKraohPwDUeaH-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1441" 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>These updates build upon what was already an incredible array of sports tracking modes and stats, and the most comprehensive suite of training analysis tools you’ll find on a sports watch.</p><p>Along with standard stuff like <a href="https://www.tomsguide.com/wellness/fitness/what-is-chronic-training-load-and-why-is-it-important-to-measure-i-asked-an-expert-to-find-out">chronic training load</a>, Garmin has some unique analysis stats, like running tolerance, which gives you a total mileage for the past week of running that takes into account the intensity of your runs, and an overall endurance score.</p><p>Not everyone will want or need all of this data, but it’s all there if you do, and Garmin offers more than other sports watches. I’m a fan of its well-established Training Readiness tool as a good way to collate a lot of information into one handy score to judge the state of your body each day.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-gps-and-heart-rate-accuracy"><span>Garmin Fenix 9 Pro review: GPS and heart rate accuracy</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:1494px;"><p class="vanilla-image-block" style="padding-top:56.29%;"><img id="72dr5XxQf9wqUucVszw9Ek" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/72dr5XxQf9wqUucVszw9Ek-1920-80.jpg" mos="" align="middle" fullscreen="" width="1494" height="841" 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 checked the accuracy of the optical heart rate monitor on the Fenix 9 Pro against a chest strap for a variety of workouts, and checked its GPS tracks after runs, including during a half marathon where it measured just about the exact race distance.</p><p>Garmin has changed how it labels its various GPS modes, but the Max Accuracy option is what I used, which uses the most accurate multi-band GPS mode on the watch when required.</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:2193px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="vNtZJAU3RmfcY4UTJdFYFm" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:66,l:164,cw:2193,ch:1234,q:80/vNtZJAU3RmfcY4UTJdFYFm.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 its GPS accuracy to be more or less spot on during my outdoor activities, and Garmin continues to be as good or better than everyone else in this area in my opinion.</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="A9a7vFYaji4r7ogFgowQ7E" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/A9a7vFYaji4r7ogFgowQ7E-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 heart rate accuracy on the Fenix 9 Pro was also very good, matching a chest strap closely on runs and bike rides. The optical sensor is not as good as a chest strap or upper arm band for strength workouts, but even there I saw mostly accurate results.</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:39.22%;"><img id="v8vUrxbNgyqjVPXDDfMFnj" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro HR" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro HR" src="https://cdn.mos.cms.futurecdn.net/v8vUrxbNgyqjVPXDDfMFnj-1920-80.jpg" mos="" align="middle" fullscreen="" width="1920" height="753" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: DC Rainmaker Analyzer)</span></figcaption></figure><p>One challenge for the heart rate accuracy of the watch could be its size if you opt for the 51mm watch, as sometimes I find it hard to get the snug fit required for reliable optical tracking with bigger watches, but I had no notable problems with the Fenix 9 Pro in my testing.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-connectivity"><span>Garmin Fenix 9 Pro review: connectivity</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="JzL85TmsbDndusgcZgihgG" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/JzL85TmsbDndusgcZgihgG-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 inReach model of the Fenix 9 Pro offers LTE and satellite connectivity, a feature introduced on the Garmin Fenix 8 Pro.</p><p>You need a Garmin subscription to use these services, which costs between $7.99 and $49.99 depending on the level you need, which mostly relates to how many messages you plan to send and calls you might make.</p><p>There’s a free trial available of the features, after which you get free SOS messaging for 12 months, but will have to pay for other services.</p><p>These connectivity features are one of the main reasons to look at the top Fenix models over older watches, or the Forerunner line-up, and will appeal greatly to those who like to take their adventures off the grid, as well as those who just like to leave their phone behind on a run while staying in touch if required.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-battery-life"><span>Garmin Fenix 9 Pro review: battery life</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:2288px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CRidumohi3kqmXdaEqr4dE" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:70,l:106,cw:2288,ch:1287,q:80/CRidumohi3kqmXdaEqr4dE.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 battery life of the Fenix 9 Pro varies greatly depending on which size you go for, but if you opt for the largest 51mm watch I tested, it’s incredibly long-lasting.</p><p>I had the screen set to always-on and used it for outdoor runs almost every day in the most accurate (and power intensive) GPS setting, and the Fenix 9 Pro 51mm lasted me 10-11 days on a charge.</p><p>This can easily be extended by setting the screen to raise to wake, or using the other GPS settings, or if you mainly exercise indoors and don’t use the GPS.</p><p>The only AMOLED sports watch I’ve tested that can outdo the Fenix 9 Pro on battery life is the <a href="https://www.tomsguide.com/wellness/smartwatches/i-swapped-my-garmin-fenix-8-pro-for-the-suunto-vertical-2-heres-5-things-i-liked-and-5-i-disliked">Suunto Vertical 2</a>, though some MIP options like the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-enduro-3-review">Garmin Enduro 3</a> and Coros Vertix 2S will last longer thanks to their less power-hungry displays.</p><p>If you opt for the 43mm or 47mm watch the battery life does drop off significantly, and the 43mm watch my colleague Jane McGuire has been testing will have you reaching for a charger every three or four days if you use the always-on screen.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-maps-and-navigation"><span>Garmin Fenix 9 Pro review: maps and navigation </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:2075px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="eZHBCPefduMUnbd4Z2jNq5" name="Garmin Fenix 9 Pro maps" alt="Garmin Fenix 9 Pro maps" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:86,l:279,cw:2075,ch:1167,q:80/eZHBCPefduMUnbd4Z2jNq5.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 lot of sports watches now offer maps, including on relatively affordable models like the<a href="https://www.tomsguide.com/wellness/smartwatches/coros-just-added-offline-maps-to-its-most-affordable-sports-watch-but-theres-a-catch"> Coros Pace 4</a>, but Garmin’s maps and navigation tools remain the best available.</p><p>That’s mainly because its watches have ‘routable’ maps that actually know where you are and can create routes for you on the fly. Other watch brands tend to have non-routable maps that just overlay your trail on an image of the map, which is more than good enough for most occasions, but not quite as handy if you’re out in the wilderness and get lost.</p><p>The Fenix 9 Pro has all of Garmin’s usual maps and navigation tools, but adds some upgrades you don’t get on other watches from the brand.</p><p>Firstly, the maps load faster when panning and zooming, and your heading updates more quickly too. Secondly, there’s a new perspective viewpoint, which tilts the maps slightly to make it clearer where you are.</p><p>These updates are useful, if not necessarily gamechangers. I don’t find that the maps load too slowly for me on other Garmins, but any boost in speed is appreciated, and I do prefer the perspective view.</p><h2 class="article-body__section" id="section-garmin-fenix-9-pro-review-smart-features"><span>Garmin Fenix 9 Pro review: smart features</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:1138px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="wCwMhzAaLBBg23oxq7kGBJ" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/wCwMhzAaLBBg23oxq7kGBJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1138" height="640" 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>Along with its connectivity features, the Fenix 9 Pro packs in a lot of useful smart features. It’s not as impressive on this front as true smartwatch like the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-review">Apple Watch Ultra 4</a>, but Garmin does offer a lot more smart features than rival sports watches.</p><p>You get NFC payments through Garmin Pay, music storage with the ability to link up to several streaming services, including Spotify, for offline playback, and a lot of customization options for your watch face and widgets.</p><p>The Garmin Connect IQ app store is not as well-stocked as the App Store or Google Play, but it does contain a lot of watch faces, data fields and other widgets that can improve the experience on the watch.</p><p>While it’s still clearly a sports watch over a smartwatch, the Fenix 9 Pro does offer a lot of handy features for day to day use.</p><h2 class="article-body__section" id="section-should-you-buy-the-garmin-fenix-9-pro"><span>Should you buy the Garmin Fenix 9 Pro?</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:1468px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="v2G5yZakdCDJF4tSsFpyAJ" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 8 Pro and Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2G5yZakdCDJF4tSsFpyAJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1468" height="826" 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 simply want the best adventure watch available, regardless of price, then the Garmin Fenix 9 Pro is the watch to go for. The new design is great, its sports and navigation features are as good as it gets, and you can pick a size to suit your wrist and battery life requirements.</p><p>However, I’m not sure it’s a big enough update on the Garmin Fenix 8 Pro that I wouldn’t recommend going for the older watch instead, and if you don’t need the connectivity feature on those watches, the Garmin Fenix 8 might be an even better value buy.</p><p>Both older models are also regularly on sale, so you could save hundreds of dollars by buying one instead of the Fenix 9 Pro. Certainly if you have one of those watches I don’t see a pressing need to upgrade, but older Fenix owners will really notice the benefits of the newer model.</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="NmEaDfEmcWjvSpjY2JqRsj" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/NmEaDfEmcWjvSpjY2JqRsj-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 Garmin Forerunner 970 also offers most of the same great features, aside from connectivity, in a lighter, slimmer package that I prefer the fit of as a thin-wristed runner. </p><p>Outside the Garmin line-up, I think the Apple Watch Ultra 4 offers a strong alternative to the Garmin Fenix 9 Pro, providing you’re not put off by its three-day battery life. It has a rugged design, good sports tracking, and LTE and satellite connectivity, and better smart features than the Fenix 9 Pro.</p><p>The Fenix is now on a yearly update cycle and Garmin made some big updates to the watch last year by adding LTE and satellite connectivity, so a smaller refresh this year isn’t unexpected. </p><p>Next year’s Garmin Fenix 10 might see bigger changes, but right now the Fenix 9 Pro is the<a href="https://www.tomsguide.com/us/best-gps-watches,review-2638.html"> best sports watch </a>you can get for outdoor adventures.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch Series 12 review: A new heart rate sensor and a readiness score make this the best smartwatch on the market ]]></title>
                                                                                                <dc:content><![CDATA[ <p>"Your heart tells a story of your health, and it’s a story worth hearing," said Apple, as it announced the updated Apple Watch Series 12, with the most accurate heart rate sensor yet. It's not often a tech keynote makes me emotional, but as a health writer, this one did. Maybe I was jet-lagged, or maybe I believe that these huge health updates might make this the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatch</a> on the market.</p><p>I spend my days writing about how the best prediction of longevity is how healthy your heart is. With a new heart rate sensor, the Apple Watch Series 12 gives you a heart rate reading every five seconds, 60 times more frequent than the<a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review"> <u>Apple Watch Series 11</u></a>. This supports HRV readings, a new readiness score that gives you deeper insights into when to push and when to recover, and longevity features in the updated Health app.</p><p>The downsides? Everyone I talk to hates the fact that the watch has a built-in microphone for new audio intelligence features coming later this year, but I’ll get into that below. I’ve been wearing it for the past week, and I’m impressed — read my full Apple Watch Series 12 review to find out more. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oT6oCzSHKMc5NiqrCAVtt4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/oT6oCzSHKMc5NiqrCAVtt4-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-apple-watch-series-12-quick-facts"><span>Apple Watch Series 12: Quick facts </span></h3><ul><li><strong>Same 24-hour battery life</strong>: Despite the addition of continuous heart rate monitoring, the Apple Watch Series 12 has the same 24-hour battery life as the Series 11</li><li><strong>New S11 chip: </strong>Faster, more efficient processing with support for Siri AI features</li><li><strong>Redesigned holistic sensors:</strong> Apple says this is the most accurate heart rate sensor on a wearable; heart rate and HRV are sampled more frequently than before; HRV insights are now more readily displayed in the Health app</li><li><strong>New health metrics:</strong> Series 12 supports a new Readiness score and Health Age metric</li><li><strong>Siri AI features: </strong>The watch ships with support for Siri AI voice assistance; new "Audio Intelligence" features help you better remember life's important details</li></ul><h3 class="article-body__section" id="section-apple-watch-series-12-specs"><span>Apple Watch Series 12: Specs</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Apple Watch Series 12</p></th><th  ><p>Apple Watch Series 11</p></th><th  ><p>Apple Watch Ultra 4</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$399</p></td><td  ><p>$399</p></td><td  ><p>$799</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>46mm: 46 x 40 x 9.7mm / 42mm: 42 x 37 x 9.7mm</p></td><td  ><p>46mm: 46 x 39 x 9.7mm / 42mm: 42 x 36 x 9.7mm</p></td><td  ><p>49 x 44 x 12 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Case colors</strong></p></td><td  ><p>Aluminum: Dark Bronze, Light Gold, Black, Space Gray / Titanium: Radiant Gold, Natural / Ceramic: Pearl White, Night Blue</p><p></p></td><td  ><p>Aluminum: Rose Gold, Silver, Space Gray, Jet Black / Titanium: Gold, Natural, Slate</p></td><td  ><p>Titanium: Natural, Black</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>46mm:  416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p><p></p></td><td  ><p>46mm: 416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td></tr><tr><td class="firstcol " ><p><strong>Display brightness</strong></p><p></p><p></p><p></p></td><td  ><p>2,000 nits</p></td><td  ><p>2,000 nits</p></td><td  ><p>3,000 nits</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>46mm: ~ 39 g / 44mm: ~32 g</p></td><td  ><p>46mm: 37.8 g / 44mm: 30.3 g</p></td><td  ><p>~63 g</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>S11</p></td><td  ><p>S10</p></td><td  ><p>S11</p></td></tr><tr><td class="firstcol " ><p><strong>Cellular </strong></p></td><td  ><p>5G</p></td><td  ><p>5G</p></td><td  ><p>56</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>50 meters</p></td><td  ><p>50 meters</p></td><td  ><p>100 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life with always-on display (rated)</strong></p></td><td  ><p>24 hours</p></td><td  ><p>24 hours</p></td><td  ><p>50 hours</p></td></tr><tr><td class="firstcol " ><p><strong>Compatibility</strong></p></td><td  ><p>iOS 27 or later</p></td><td  ><p>iOS 26 or later</p></td><td  ><p>iOS 27 or later</p></td></tr><tr><td class="firstcol empty" ></td><td  ></td><td  ></td><td  ></td></tr></tbody></table></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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="h9pUCaivgXc2tpjF4BPEu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/h9pUCaivgXc2tpjF4BPEu4-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-apple-watch-series-12-review-price-and-availability"><span>Apple Watch Series 12 review: Price and availability </span></h3><p>The Apple Watch Series 12 is available for preorder starting September 9, with units expected to arrive on September 18. The Series 12 has the same starting cost as the Series 11 — $399. </p><p>In addition to the standard aluminum and upgraded titanium case options, the Apple Watch Series 12 is also available in two ceramic finishes: Pearl White and Night Blue. </p><p>See a full breakdown of pricing for all the case options and sizes below:</p><ul><li><strong>Apple Watch Series 12, 42mm, GPS (Aluminum): $399</strong></li><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Aluminum): $499</strong></li><li><strong>Apple Watch Series 12, 46mm, GPS (Aluminum): $449</strong></li><li><strong>Apple Watch Series 12, 46mm, GPS+5G (Aluminum): $549</strong></li></ul><ul><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Titanium): $699</strong></li><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Titanium): $749</strong></li></ul><ul><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Ceramic): $899</strong></li><li><strong>Apple Watch Series 12, 42mm, GPS+5 (Ceramic): $949</strong></li></ul><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/5s6knEOHZAQ" allowfullscreen></iframe></div></div><h3 class="article-body__section" id="section-apple-watch-series-12-review-design-and-display"><span>Apple Watch Series 12 review: Design and display </span></h3><p>Design-wise, the Apple Watch Series 12 looks pretty identical to the Apple Watch Series 11: it comes in two different sizes, 42mm and 46mm, but with the newer watch, there are more color and casing options to choose from. The Apple Watch 11 came in rose gold, silver, space gray, and jet black in an aluminum case, and gold, natural, or slate in titanium. You get more choices with the Apple Watch 12, which comes in dark bronze, light gold, black, and space gray in the aluminum case, radiant gold and natural in the titanium case, and pearl white or night blue in the ceramic case. </p><p>I’ve been wearing the 42 mm dark bronze aluminum Apple Watch, and I love how lightweight and comfortable it is on the wrist. In real life, the light gold Apple Watch looks like jewelry, and the ceramic cases really are beautiful. </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="bd5vDcnqwz3fKbSyLKpmr4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/bd5vDcnqwz3fKbSyLKpmr4-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 biggest difference, design-wise, is on the back of the watch — the heart rate sensor has been completely redesigned, but more on that below. The Apple Watch Series 12 also has that built-in microphone I mentioned above for all of the audio intelligence features coming later this year. </p><h3 class="article-body__section" id="section-apple-watch-series-review-health-and-fitness-tracking"><span>Apple Watch Series review: Health and fitness tracking</span></h3><p>There’s no doubt about it: as a <a href="https://www.tomsguide.com/us/best-fitness-trackers,review-2066.html">fitness tracker</a>, the Apple Watch Series 12 is more accurate than its predecessor, and that’s down to the new heart rate sensor. When looking at the two monitors side-by-side, the Series 12 and Ultra 4 have a “32-petal design,” whereas the older watches had a two-petal design. This refers to the spoke-like lines coming out of the electrode. The green LED lights, which measure your heart rate by shining light into the skin, are bigger and more powerful.</p><p>If you’ve ever worn an Apple Watch to bed and woken up in the night to a harsh green glow underneath your wrist, you’ll love this update. That glaring light is finally gone — and so is the feeling that you’re about to be abducted by a UFO.</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="4YYDurEio6KwxxwFQqqB8j" name="IMG_0163" alt="heart rate sensor on Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/4YYDurEio6KwxxwFQqqB8j-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>But more than that, heart rate data lies at the heart of a lot of health features on the Apple Watch, including HRV, workouts, and ovulation prediction, so a better heart rate sensor means the watch is doing all of these, well, better. Apple also said the new heart rate monitor works better on certain skin tones, though it will still likely struggle to read heavily tattooed wrists. Your heart-rate complication can update every five seconds, 60 times more frequently than it did on the Apple Watch Series 11. Inside the Heart Rate app, there's a rolling two-minute chart. And HRV, including overnight and recovery data, is much easier to surface directly from the watch.</p><p>Previously, Apple only allowed continuous heart rate monitoring during a workout, so this is a huge step in the right direction. On the Apple Watch Series 12, you’ll be able to see your Recovery HRV score, which shows signs of stress and recovery, as well as your overall HRV, which offers insights into your overall health. You can now see from your wrist if your heart rate suddenly spiked, and through the new daytime Vitals app, you're getting a much more immediate picture of what's happening, rather than having to wait till you’re asleep.</p><p>I’ve been testing the new heart rate sensor alongside a Garmin chest strap, and have found the Apple Watch Series 12 to be pretty much spot on. Here’s a graph from my recent run:</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1600px;"><p class="vanilla-image-block" style="padding-top:38.31%;"><img id="efx45TDcn3ACcDoQBFxAtA" name="WhatsApp Image 2026-09-16 at 5.41.57 PM" alt="a heart rate graph of Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/efx45TDcn3ACcDoQBFxAtA-1920-80.jpg" mos="" align="middle" fullscreen="" width="1600" height="613" 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 new sensors also feed into the new daily Readiness score, which is only available on the Apple Watch Series 12 and Apple Watch Ultra 4. Readiness provides a single score out of ten with one of four different recommendations: Recover, Pace Yourself, Ready, or Go For It. Readiness updates throughout the day as new data comes in, and is based on your overnight vitals, sleep score, recent physical activity, and training load. </p><p>To get a Readiness score, you need to wear the watch for seven nights and get at least four hours of sleep per night. I <em>have </em>done that, but sadly, my Apple Watch 12 got as confused as my internal body clock was on my flight back from Cupertino, and only registered two hours of sleep for my night of travel. I’ll update this review as soon as I get a score. </p><p>There are also new changes coming to the Health app later this year, including a new Health Age score that compares your physical fitness to the average for your age range, and a greater emphasis on things like sleep trends, heart data, and longevity metrics. Again, I’ll be testing them as soon as they drop. </p><p>One very minor, but exciting update I’ve found during my testing is the Steps watch face compilation you can now get on the Apple Watch 12. Again, Apple isn’t reinventing the wheel, but you can now see your daily step count from your watch face, without the need for any third-party app. Unfortunately for folks with an older Apple Watch, this is a hardware thing, as Apple says it relies on the more accurate S11 chip, so older watches won’t get the updated pedometer.</p><h3 class="article-body__section" id="section-apple-watch-series-12-review-audio-intelligence"><span>Apple Watch Series 12 review: Audio Intelligence </span></h3><p>Now to address the elephant in the room — the Audio Intelligence features launching on the Series 12 and Ultra 4. Here’s everything you need to know about the new <a href="https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained"><u>Audio Intelligence features</u></a>, but in a nutshell, the two features everyone is talking about are Live Rewind and Siri Recap. </p><p>Neither are available for me to test just yet; they are coming later in the year, but essentially, Live Rewind allows you to double-click on the Digital Crown of your Apple Watch and get a 15-second recap of what was just said around you. The Watch will play an audible chime even if your watch is on silent and puts a microphone indicator on screen, so people around you will know you’re recording. The example Apple gave was if you’d missed the specials at a restaurant, or missed a colleague's name, you could read it from your watch. I think there’s a compelling reason here, say, if you have ADHD or struggle with auditory processing. </p><p>The trickier sell, for me and most people I’ve spoken to, is Siri Recap. This records ambient audio every 15 minutes to create an itemized summary of your day. Yep, you heard that correctly. Apple put a lot of stress on privacy when demoing this new feature — raw audio isn’t saved, uploaded, or retrievable, and Siri Recap doesn’t identify individual speakers. It’s also designed to exclude sensitive information or hate speech. </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="W5QaBdWA6ZqoxGfUz3gDu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/W5QaBdWA6ZqoxGfUz3gDu4-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>However, even with these features, there’s still the slightly blurred line around the fact that my conversation could, in theory, appear on someone else’s Siri Recap without my consent to being recorded. Although this isn’t an Apple problem, it’s a living-in-2026 problem, as the same questions are being leveled at the ambient AI, cameras, and microphones in smart glasses and other wearable devices.</p><p>Personally, I can’t think of a situation where I’d need a computer to give me a summary of my day, but I’ll reserve judgment until I’ve been able to go hands-on with the features later in the year. I’d also add that these are all features that you have to opt in to — they are automatically disabled when you unbox the watch. </p><h3 class="article-body__section" id="section-apple-watch-series-12-review-battery-life"><span>Apple Watch Series 12 review: Battery life</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="TcB6zQB7QASMX5YmQu3mR9" name="IMG_0173" alt="Apple Watch Series 12 on wrist" src="https://cdn.mos.cms.futurecdn.net/TcB6zQB7QASMX5YmQu3mR9-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 Apple Watch Series 12 has the same 24 hours of battery life as the Series 11, but Apple has given us faster charging as well as a bunch of new sensors. You can now get up to 80% charge in about 30 minutes, 15 minutes for up to 12 hours of normal use, and 5 minutes for up to 10 hours of sleep tracking.</p><p>If, like me, you’re a runner, you will get slightly longer GPS-mode battery life — 10 hours instead of 8 on the Series 11.</p><p>I’ve found Apple’s battery life claims to be pretty accurate, and, as someone who frequently forgets to charge her watch before bed, I have definitely noticed how much faster the Series 12 charges.</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="ywtdSV5nn5QyfA2Sq5jM6f" name="IMG_0188" alt="A photo of the Apple Watch Ultra 12 on wrist" src="https://cdn.mos.cms.futurecdn.net/ywtdSV5nn5QyfA2Sq5jM6f-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-apple-watch-series-12-review-should-you-buy"><span>Apple Watch Series 12 review: Should you buy? </span></h3><p>A week later, I can confidently say that it wasn’t just the jet lag making me emotional in the keynote — as someone who writes about health and fitness for a living, this is the best Apple Watch on the market for most people. In fact, it’s the first year since the Ultra launched in 2022 that I’d be torn about which to shop for. </p><p>Between the upgraded heart rate sensor, the new Readiness score — because knowing when to rest is just as important as closing your rings — and an actual dedicated step-counting app, this watch completely outclasses the Series 11. I know other brands have been doing all of the above for years, but none of them are also like having an extension of your iPhone on your wrist, and that’s why when Apple does it, it feels different. </p><p>Audio Intelligence is the flashy upgrade and Siri Recap is going to generate headlines, but personally, I think it’s the continuous heart-rate sensing and better recovery information that have changed the day-to-day feel of the Apple Watch on my wrist when testing the Series 12. Buy the Ultra 4 if you want 50 hours of battery life, you’re into diving, or you just want to make a statement, but if you’re looking for a smartwatch that’ll help you make actionable changes to your health, the Apple Watch Series 12 is a good place to start.  </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-review</link>
                                                                            <description>
                            <![CDATA[ I've been testing Apple's new flagship watch for the past week - here's everything you need to know. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">ebWhXafxFy3YJXPTnZArSk</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/XG65JfrPPHjBjSi27BWeVY-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 17 Sep 2026 12:00:00 +0000</pubDate>                                                                                                                                <updated>Thu, 17 Sep 2026 12:50:51 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></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/XG65JfrPPHjBjSi27BWeVY-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Series 12]]></media:description>                                                            <media:text><![CDATA[Apple Watch Series 12]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Series 12]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/XG65JfrPPHjBjSi27BWeVY-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>"Your heart tells a story of your health, and it’s a story worth hearing," said Apple, as it announced the updated Apple Watch Series 12, with the most accurate heart rate sensor yet. It's not often a tech keynote makes me emotional, but as a health writer, this one did. Maybe I was jet-lagged, or maybe I believe that these huge health updates might make this the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatch</a> on the market.</p><p>I spend my days writing about how the best prediction of longevity is how healthy your heart is. With a new heart rate sensor, the Apple Watch Series 12 gives you a heart rate reading every five seconds, 60 times more frequent than the<a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review"> <u>Apple Watch Series 11</u></a>. This supports HRV readings, a new readiness score that gives you deeper insights into when to push and when to recover, and longevity features in the updated Health app.</p><p>The downsides? Everyone I talk to hates the fact that the watch has a built-in microphone for new audio intelligence features coming later this year, but I’ll get into that below. I’ve been wearing it for the past week, and I’m impressed — read my full Apple Watch Series 12 review to find out more. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oT6oCzSHKMc5NiqrCAVtt4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/oT6oCzSHKMc5NiqrCAVtt4-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-apple-watch-series-12-quick-facts"><span>Apple Watch Series 12: Quick facts </span></h3><ul><li><strong>Same 24-hour battery life</strong>: Despite the addition of continuous heart rate monitoring, the Apple Watch Series 12 has the same 24-hour battery life as the Series 11</li><li><strong>New S11 chip: </strong>Faster, more efficient processing with support for Siri AI features</li><li><strong>Redesigned holistic sensors:</strong> Apple says this is the most accurate heart rate sensor on a wearable; heart rate and HRV are sampled more frequently than before; HRV insights are now more readily displayed in the Health app</li><li><strong>New health metrics:</strong> Series 12 supports a new Readiness score and Health Age metric</li><li><strong>Siri AI features: </strong>The watch ships with support for Siri AI voice assistance; new "Audio Intelligence" features help you better remember life's important details</li></ul><h3 class="article-body__section" id="section-apple-watch-series-12-specs"><span>Apple Watch Series 12: Specs</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Apple Watch Series 12</p></th><th  ><p>Apple Watch Series 11</p></th><th  ><p>Apple Watch Ultra 4</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$399</p></td><td  ><p>$399</p></td><td  ><p>$799</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>46mm: 46 x 40 x 9.7mm / 42mm: 42 x 37 x 9.7mm</p></td><td  ><p>46mm: 46 x 39 x 9.7mm / 42mm: 42 x 36 x 9.7mm</p></td><td  ><p>49 x 44 x 12 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Case colors</strong></p></td><td  ><p>Aluminum: Dark Bronze, Light Gold, Black, Space Gray / Titanium: Radiant Gold, Natural / Ceramic: Pearl White, Night Blue</p><p></p></td><td  ><p>Aluminum: Rose Gold, Silver, Space Gray, Jet Black / Titanium: Gold, Natural, Slate</p></td><td  ><p>Titanium: Natural, Black</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>46mm:  416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p><p></p></td><td  ><p>46mm: 416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td></tr><tr><td class="firstcol " ><p><strong>Display brightness</strong></p><p></p><p></p><p></p></td><td  ><p>2,000 nits</p></td><td  ><p>2,000 nits</p></td><td  ><p>3,000 nits</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>46mm: ~ 39 g / 44mm: ~32 g</p></td><td  ><p>46mm: 37.8 g / 44mm: 30.3 g</p></td><td  ><p>~63 g</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>S11</p></td><td  ><p>S10</p></td><td  ><p>S11</p></td></tr><tr><td class="firstcol " ><p><strong>Cellular </strong></p></td><td  ><p>5G</p></td><td  ><p>5G</p></td><td  ><p>56</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>50 meters</p></td><td  ><p>50 meters</p></td><td  ><p>100 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life with always-on display (rated)</strong></p></td><td  ><p>24 hours</p></td><td  ><p>24 hours</p></td><td  ><p>50 hours</p></td></tr><tr><td class="firstcol " ><p><strong>Compatibility</strong></p></td><td  ><p>iOS 27 or later</p></td><td  ><p>iOS 26 or later</p></td><td  ><p>iOS 27 or later</p></td></tr><tr><td class="firstcol empty" ></td><td  ></td><td  ></td><td  ></td></tr></tbody></table></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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="h9pUCaivgXc2tpjF4BPEu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/h9pUCaivgXc2tpjF4BPEu4-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-apple-watch-series-12-review-price-and-availability"><span>Apple Watch Series 12 review: Price and availability </span></h3><p>The Apple Watch Series 12 is available for preorder starting September 9, with units expected to arrive on September 18. The Series 12 has the same starting cost as the Series 11 — $399. </p><p>In addition to the standard aluminum and upgraded titanium case options, the Apple Watch Series 12 is also available in two ceramic finishes: Pearl White and Night Blue. </p><p>See a full breakdown of pricing for all the case options and sizes below:</p><ul><li><strong>Apple Watch Series 12, 42mm, GPS (Aluminum): $399</strong></li><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Aluminum): $499</strong></li><li><strong>Apple Watch Series 12, 46mm, GPS (Aluminum): $449</strong></li><li><strong>Apple Watch Series 12, 46mm, GPS+5G (Aluminum): $549</strong></li></ul><ul><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Titanium): $699</strong></li><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Titanium): $749</strong></li></ul><ul><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Ceramic): $899</strong></li><li><strong>Apple Watch Series 12, 42mm, GPS+5 (Ceramic): $949</strong></li></ul><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/5s6knEOHZAQ" allowfullscreen></iframe></div></div><h3 class="article-body__section" id="section-apple-watch-series-12-review-design-and-display"><span>Apple Watch Series 12 review: Design and display </span></h3><p>Design-wise, the Apple Watch Series 12 looks pretty identical to the Apple Watch Series 11: it comes in two different sizes, 42mm and 46mm, but with the newer watch, there are more color and casing options to choose from. The Apple Watch 11 came in rose gold, silver, space gray, and jet black in an aluminum case, and gold, natural, or slate in titanium. You get more choices with the Apple Watch 12, which comes in dark bronze, light gold, black, and space gray in the aluminum case, radiant gold and natural in the titanium case, and pearl white or night blue in the ceramic case. </p><p>I’ve been wearing the 42 mm dark bronze aluminum Apple Watch, and I love how lightweight and comfortable it is on the wrist. In real life, the light gold Apple Watch looks like jewelry, and the ceramic cases really are beautiful. </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="bd5vDcnqwz3fKbSyLKpmr4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/bd5vDcnqwz3fKbSyLKpmr4-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 biggest difference, design-wise, is on the back of the watch — the heart rate sensor has been completely redesigned, but more on that below. The Apple Watch Series 12 also has that built-in microphone I mentioned above for all of the audio intelligence features coming later this year. </p><h3 class="article-body__section" id="section-apple-watch-series-review-health-and-fitness-tracking"><span>Apple Watch Series review: Health and fitness tracking</span></h3><p>There’s no doubt about it: as a <a href="https://www.tomsguide.com/us/best-fitness-trackers,review-2066.html">fitness tracker</a>, the Apple Watch Series 12 is more accurate than its predecessor, and that’s down to the new heart rate sensor. When looking at the two monitors side-by-side, the Series 12 and Ultra 4 have a “32-petal design,” whereas the older watches had a two-petal design. This refers to the spoke-like lines coming out of the electrode. The green LED lights, which measure your heart rate by shining light into the skin, are bigger and more powerful.</p><p>If you’ve ever worn an Apple Watch to bed and woken up in the night to a harsh green glow underneath your wrist, you’ll love this update. That glaring light is finally gone — and so is the feeling that you’re about to be abducted by a UFO.</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="4YYDurEio6KwxxwFQqqB8j" name="IMG_0163" alt="heart rate sensor on Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/4YYDurEio6KwxxwFQqqB8j-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>But more than that, heart rate data lies at the heart of a lot of health features on the Apple Watch, including HRV, workouts, and ovulation prediction, so a better heart rate sensor means the watch is doing all of these, well, better. Apple also said the new heart rate monitor works better on certain skin tones, though it will still likely struggle to read heavily tattooed wrists. Your heart-rate complication can update every five seconds, 60 times more frequently than it did on the Apple Watch Series 11. Inside the Heart Rate app, there's a rolling two-minute chart. And HRV, including overnight and recovery data, is much easier to surface directly from the watch.</p><p>Previously, Apple only allowed continuous heart rate monitoring during a workout, so this is a huge step in the right direction. On the Apple Watch Series 12, you’ll be able to see your Recovery HRV score, which shows signs of stress and recovery, as well as your overall HRV, which offers insights into your overall health. You can now see from your wrist if your heart rate suddenly spiked, and through the new daytime Vitals app, you're getting a much more immediate picture of what's happening, rather than having to wait till you’re asleep.</p><p>I’ve been testing the new heart rate sensor alongside a Garmin chest strap, and have found the Apple Watch Series 12 to be pretty much spot on. Here’s a graph from my recent run:</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1600px;"><p class="vanilla-image-block" style="padding-top:38.31%;"><img id="efx45TDcn3ACcDoQBFxAtA" name="WhatsApp Image 2026-09-16 at 5.41.57 PM" alt="a heart rate graph of Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/efx45TDcn3ACcDoQBFxAtA-1920-80.jpg" mos="" align="middle" fullscreen="" width="1600" height="613" 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 new sensors also feed into the new daily Readiness score, which is only available on the Apple Watch Series 12 and Apple Watch Ultra 4. Readiness provides a single score out of ten with one of four different recommendations: Recover, Pace Yourself, Ready, or Go For It. Readiness updates throughout the day as new data comes in, and is based on your overnight vitals, sleep score, recent physical activity, and training load. </p><p>To get a Readiness score, you need to wear the watch for seven nights and get at least four hours of sleep per night. I <em>have </em>done that, but sadly, my Apple Watch 12 got as confused as my internal body clock was on my flight back from Cupertino, and only registered two hours of sleep for my night of travel. I’ll update this review as soon as I get a score. </p><p>There are also new changes coming to the Health app later this year, including a new Health Age score that compares your physical fitness to the average for your age range, and a greater emphasis on things like sleep trends, heart data, and longevity metrics. Again, I’ll be testing them as soon as they drop. </p><p>One very minor, but exciting update I’ve found during my testing is the Steps watch face compilation you can now get on the Apple Watch 12. Again, Apple isn’t reinventing the wheel, but you can now see your daily step count from your watch face, without the need for any third-party app. Unfortunately for folks with an older Apple Watch, this is a hardware thing, as Apple says it relies on the more accurate S11 chip, so older watches won’t get the updated pedometer.</p><h3 class="article-body__section" id="section-apple-watch-series-12-review-audio-intelligence"><span>Apple Watch Series 12 review: Audio Intelligence </span></h3><p>Now to address the elephant in the room — the Audio Intelligence features launching on the Series 12 and Ultra 4. Here’s everything you need to know about the new <a href="https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained"><u>Audio Intelligence features</u></a>, but in a nutshell, the two features everyone is talking about are Live Rewind and Siri Recap. </p><p>Neither are available for me to test just yet; they are coming later in the year, but essentially, Live Rewind allows you to double-click on the Digital Crown of your Apple Watch and get a 15-second recap of what was just said around you. The Watch will play an audible chime even if your watch is on silent and puts a microphone indicator on screen, so people around you will know you’re recording. The example Apple gave was if you’d missed the specials at a restaurant, or missed a colleague's name, you could read it from your watch. I think there’s a compelling reason here, say, if you have ADHD or struggle with auditory processing. </p><p>The trickier sell, for me and most people I’ve spoken to, is Siri Recap. This records ambient audio every 15 minutes to create an itemized summary of your day. Yep, you heard that correctly. Apple put a lot of stress on privacy when demoing this new feature — raw audio isn’t saved, uploaded, or retrievable, and Siri Recap doesn’t identify individual speakers. It’s also designed to exclude sensitive information or hate speech. </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="W5QaBdWA6ZqoxGfUz3gDu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/W5QaBdWA6ZqoxGfUz3gDu4-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>However, even with these features, there’s still the slightly blurred line around the fact that my conversation could, in theory, appear on someone else’s Siri Recap without my consent to being recorded. Although this isn’t an Apple problem, it’s a living-in-2026 problem, as the same questions are being leveled at the ambient AI, cameras, and microphones in smart glasses and other wearable devices.</p><p>Personally, I can’t think of a situation where I’d need a computer to give me a summary of my day, but I’ll reserve judgment until I’ve been able to go hands-on with the features later in the year. I’d also add that these are all features that you have to opt in to — they are automatically disabled when you unbox the watch. </p><h3 class="article-body__section" id="section-apple-watch-series-12-review-battery-life"><span>Apple Watch Series 12 review: Battery life</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="TcB6zQB7QASMX5YmQu3mR9" name="IMG_0173" alt="Apple Watch Series 12 on wrist" src="https://cdn.mos.cms.futurecdn.net/TcB6zQB7QASMX5YmQu3mR9-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 Apple Watch Series 12 has the same 24 hours of battery life as the Series 11, but Apple has given us faster charging as well as a bunch of new sensors. You can now get up to 80% charge in about 30 minutes, 15 minutes for up to 12 hours of normal use, and 5 minutes for up to 10 hours of sleep tracking.</p><p>If, like me, you’re a runner, you will get slightly longer GPS-mode battery life — 10 hours instead of 8 on the Series 11.</p><p>I’ve found Apple’s battery life claims to be pretty accurate, and, as someone who frequently forgets to charge her watch before bed, I have definitely noticed how much faster the Series 12 charges.</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="ywtdSV5nn5QyfA2Sq5jM6f" name="IMG_0188" alt="A photo of the Apple Watch Ultra 12 on wrist" src="https://cdn.mos.cms.futurecdn.net/ywtdSV5nn5QyfA2Sq5jM6f-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-apple-watch-series-12-review-should-you-buy"><span>Apple Watch Series 12 review: Should you buy? </span></h3><p>A week later, I can confidently say that it wasn’t just the jet lag making me emotional in the keynote — as someone who writes about health and fitness for a living, this is the best Apple Watch on the market for most people. In fact, it’s the first year since the Ultra launched in 2022 that I’d be torn about which to shop for. </p><p>Between the upgraded heart rate sensor, the new Readiness score — because knowing when to rest is just as important as closing your rings — and an actual dedicated step-counting app, this watch completely outclasses the Series 11. I know other brands have been doing all of the above for years, but none of them are also like having an extension of your iPhone on your wrist, and that’s why when Apple does it, it feels different. </p><p>Audio Intelligence is the flashy upgrade and Siri Recap is going to generate headlines, but personally, I think it’s the continuous heart-rate sensing and better recovery information that have changed the day-to-day feel of the Apple Watch on my wrist when testing the Series 12. Buy the Ultra 4 if you want 50 hours of battery life, you’re into diving, or you just want to make a statement, but if you’re looking for a smartwatch that’ll help you make actionable changes to your health, the Apple Watch Series 12 is a good place to start.  </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch Ultra 4 review: I ran 22 miles to test Apple’s ultimate adventure watch ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple designed the Ultra for summiting mountains and diving reefs. In reality? Most of us wearing one are weekend warriors chained to a 9-to-5, using an $800 rugged watch to track our steps on our commutes. With the Apple Watch Ultra 4, Apple makes having the watch on your wrist even better, whether you're working out or not. </p><p>The big headlines with the Apple Watch Ultra 4 are a new heart rate monitor, a readiness score to help you know when to push and when to rest, two days of battery life for the first time, and new Audio Intelligence features that will come later this year. Physically, it looks the same, but under the hood, this is a smarter watch. </p><p>But is it worth the upgrade if you already have the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3 </a>on your wrist? I’ve been wearing the Apple Watch Ultra 4 for the past week and wore it for a 22-mile run this morning to see how the heart rate monitor compares to a physical chest strap. Read my full Apple Watch Ultra 4 review to find out more. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-quick-facts"><span>Apple Watch Ultra 4: Quick facts </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="ksjEAsDzPnVz4PFiyS54Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/ksjEAsDzPnVz4PFiyS54Rj-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><ul><li><strong>Improved battery life:</strong> lasts up to 50 hours per charge compared to 42 hours for the Ultra 3</li><li><strong>New S11 chip: </strong>Faster, more efficient processing with support for Siri AI features</li><li><strong>Redesigned holistic sensors:</strong> Apple says this is the most accurate heart rate sensor on a wearable; heart rate and HRV are sampled more frequently than before; HRV insights are now more readily displayed in the Health app</li><li><strong>New health metrics:</strong> the Ultra 4 supports a new Readiness score and Health Age metric</li><li><strong>Siri AI features: </strong>the Ultra 4 ships with support for Siri AI voice assistance; new  "Audio Intelligence" features help you better recall life's important details</li></ul><h3 class="article-body__section" id="section-apple-watch-ultra-4-specs"><span>Apple Watch Ultra 4: Specs</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Apple Watch Ultra 4</p></th><th  ><p>Apple Watch Ultra 3</p></th><th  ><p>Apple Watch Series 12</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$799 / AU$1,349</p></td><td  ><p>$799 / AU$1,399</p></td><td  ><p>$399 / AU$649</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>49 x 44 x 12 mm</p></td><td  ><p>49 x 44 x 12 mm</p></td><td  ><p>46mm: 46 x 40 x 9.7mm / 42mm: 42 x 37 x 9.7mm</p></td></tr><tr><td class="firstcol " ><p><strong>Case colors</strong></p></td><td  ><p>Titanium: Natural, Black</p></td><td  ><p>Titanium: Natural, Black</p></td><td  ><p>Aluminum: Dark Bronze, Light Gold, Black, Space Gray / Titanium: Radiant Gold, Natural / Ceramic: Pearl White, Night Blue</p><p></p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td><td  ><p>46mm:  416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p><p></p></td></tr><tr><td class="firstcol " ><p><strong>Display brightness</strong></p><p></p><p></p><p></p></td><td  ><p>3,000 nits</p></td><td  ><p>3,000 nits</p></td><td  ><p>2,000 nits</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>~63 g</p></td><td  ><p>~61 g</p></td><td  ><p>46mm: ~ 39 g / 44mm: ~32 g</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>S11</p></td><td  ><p>S10</p></td><td  ><p>S11</p></td></tr><tr><td class="firstcol " ><p><strong>Cellular </strong></p></td><td  ><p>56</p></td><td  ><p>5G</p></td><td  ><p>5G</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>100 meters</p></td><td  ><p>100 meters</p></td><td  ><p>50 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life with always-on display (rated)</strong></p></td><td  ><p>50 hours</p></td><td  ><p>42 hours</p></td><td  ><p>24 hours</p></td></tr><tr><td class="firstcol " ><p><strong>Compatibility</strong></p></td><td  ><p>iOS 27 or later</p></td><td  ><p>iOS 26 or later</p></td><td  ><p>iOS 27 or later</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-apple-watch-ultra-4-review-price-and-availability"><span>Apple Watch Ultra 4 review: Price and availability </span></h3><p>The Apple Watch Ultra 4 is available for preorder from September 9, 2026. Units should hit store shelves and your hands starting on September 18. </p><p>The Apple Watch Ultra 4 is $799 / AU$1,349, the same price as the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a> and prior models. </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/5s6knEOHZAQ" allowfullscreen></iframe></div></div><h3 class="article-body__section" id="section-apple-watch-ultra-4-review-design-and-display"><span>Apple Watch Ultra 4 review: Design and display </span></h3><p>The Apple Watch Ultra 4 looks physically identical to the Ultra 3, boasting the same dimensions, oversized display with 3,000 nits of max brightness, an all-titanium case, and 100 meters of water resistance. It’s still available in black and natural titanium. </p><p>There are slightly more bands to choose from: the Trail Loop is now available in dark umber, sand, and Apple’s color of the year, burgundy. The Alpine Loop comes in desert, dark olive, and also burgundy. Ocean Bands are now made from translucent silicone and come in three new colors: translucent gray, translucent kelp, and translucent black.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="q6RPuprHDQb5uHVE6hD8Cj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/q6RPuprHDQb5uHVE6hD8Cj-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 big difference between the Apple Watch Ultra 3 and Apple Watch Ultra 4 from a design perspective is when you flip the watch over. The heart rate sensor has been completely redesigned, but more on that below. The Apple Watch Ultra 4 also has a built-in microphone for all of the audio intelligence features coming later this year. </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="VLq9FtKKTYZpBzEqFLvGk9" name="IMG_0127" alt="Apple Watch Ultra 4 on wrist" src="https://cdn.mos.cms.futurecdn.net/VLq9FtKKTYZpBzEqFLvGk9-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-apple-watch-ultra-4-review-health-and-fitness-tracking"><span>Apple Watch Ultra 4 review: Health and fitness tracking </span></h3><p>The biggest difference, and the reason I think this is the best Apple Watch Ultra yet, is the new heart rate monitor loaded onto the watch. When looking at the two monitors side-by-side, the Ultra 4 and the Apple Watch Series 12 have a “32-petal design,” whereas older watches had a two-petal design. This refers to the spoke-like lines coming out of the electrode.</p><p>The green LED lights, which measure your heart rate by shining light into the skin, are bigger and more powerful. Apple says it also makes the heart rate monitor more accurate on certain skin tones, although it might still struggle if you have tattoos on your wrist. </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="SjN282csQtBMb6DaeDKsKG" name="IMG_0166" alt="HR monitor on Apple Watch Ultra 3 and Ultra 4" src="https://cdn.mos.cms.futurecdn.net/SjN282csQtBMb6DaeDKsKG-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’ve always found the heart rate monitor on my Apple Watch Ultra 3 to be a little sketchy, and while I often put this down to how it sits on my wrist, I was keen to see how things might have changed on the Ultra 4. It’s worth noting that if, like me, you have petite wrists, you’ll need to ensure the Ultra is really tight against your wrist. I’ve found that if my watch strap isn’t tight enough, the watch just doesn’t give me a heart rate reading. </p><p>Heart rate data lies at the heart of a lot of health features on the Apple Watch, including HRV, workouts, and ovulation prediction. With the Apple Watch Ultra 4, the new heart rate monitor, along with the S-11 chip, measures your heart rate every five seconds, all day long. On the Apple Watch Ultra 3, Apple only allowed continuous heart rate monitoring during a workout, but this is a huge step in the right direction. Inside the Heart Rate app, there's a rolling two-minute chart. </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="nMisA2bBjx2DUYFYKuha5M" name="IMG_0153" alt="Continious heart rate monitoring on Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/nMisA2bBjx2DUYFYKuha5M-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>On the Apple Watch Ultra 4, you’ll be able to see your Recovery HRV score, which shows signs of stress and recovery, as well as your overall HRV, which offers insights into your overall health. You can now see from your wrist if your heart rate suddenly spikes, and through the new daytime Vitals app, you're getting a much more immediate picture of what's happening, rather than having to wait till you’re asleep.</p><p>I’ve been testing the new heart rate sensor alongside a chest strap and my Oura Ring 5, and have found the Apple Watch Ultra 4 to be pretty much spot on. Here’s a graph from my recent run:</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1600px;"><p class="vanilla-image-block" style="padding-top:41.63%;"><img id="TGaCp9nPJDiHWNan4rLuwQ" name="WhatsApp Image 2026-09-16 at 5.19.12 PM" alt="a heart rate graph from Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/TGaCp9nPJDiHWNan4rLuwQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1600" height="666" 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 new sensors also feed into the new daily Readiness score, which is only available on the Apple Watch Series 12 and Apple Watch Ultra 4. Readiness provides a single score out of ten with one of four different recommendations: Recover, Pace Yourself, Ready, or Go For It. Readiness updates throughout the day as new data comes in, and is based on your overnight vitals, sleep score, recent physical activity, and training load. </p><p>To get a Readiness score, you need to wear the watch for seven nights and get at least four hours of sleep per night. While I have done that, my Apple Watch got a little confused by moving time zones, so it only registered two hours of sleep as I travelled back to London from Cupertino. I’ll update this review soon when I’ve had a few days of Readiness scores. I’ll also look at how these scores compare to the likes of Body Battery on Garmin, and the Readiness score on the Oura Ring 5. </p><p>Later this year, the Health App will see big changes, including a new Health Age score that compares your physical fitness to the average for your age. There will also be a greater emphasis on things like sleep trends, heart data, and other longevity metrics. Again, I’ll be testing these as soon as they drop, but I’m excited to hear about these updates to make the Health app more useful to users.</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="jc8nWCpY62gd8Tbt9Vu7cV" name="IMG_0119" alt="a photo of the Apple Watch Ultra 4 on wrist" src="https://cdn.mos.cms.futurecdn.net/jc8nWCpY62gd8Tbt9Vu7cV-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>Of course, it's worth noting that Apple isn’t reinventing the wheel — Garmin has had a Fitness Age score forever, but wearing a Garmin isn’t like having an extension of your iPhone on your wrist. While these little changes might not sound like a lot, a Readiness score can show you at a glance if you’re overtraining and putting yourself at risk of injury. Whether you’re a weekend warrior or training for your seventh marathon, knowing how well you’re coping with your training is imperative, and Apple makes this easier with the Apple Watch Ultra 4.</p><p>Another minor but exciting update I’ve found during my testing is the Steps watch face. At last, you can see your daily step count from your watch face. Sure, steps aren’t the biggest health metric to keep an eye on, but on rest days, I still like to make sure I’m closing my rings and keeping my legs moving. Unfortunately for folks with an older Apple Watch, this is a hardware thing, as Apple says it relies on the more accurate S-11 chip, so older watches won’t get the updated pedometer.</p><h3 class="article-body__section" id="section-apple-watch-ultra-4-review-audio-intelligence"><span>Apple Watch Ultra 4 review: Audio Intelligence </span></h3><p>Now, to address the parts of the watch that are probably going to get headlines — the Audio Intelligence features. Here’s everything you need to know about the new <a href="https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained"><u>Audio Intelligence features</u></a>, but in a nutshell, the two features everyone is talking about are Live Rewind and Siri Recap. </p><p>Neither is available for me to test just yet; they are coming later in the year, but essentially, Live Rewind allows you to double-click on the Digital Crown of your Apple Watch Ultra 4 and get a 15-second recap of what was just said around you. The Watch will play an audible chime even if your watch is on silent and puts a microphone indicator on screen, so people around you will know you’re recording.</p><p>One example is if you’d missed the specials at a restaurant, or missed a colleague's name, you could read it from your watch. I think there’s a compelling reason here, say, if you have ADHD or struggle with auditory processing. </p><p>The trickier sell, for me and most people I’ve spoken to, is Siri Recap. This records ambient audio every 15 minutes to create an itemized CliffsNotes of your day. You can set this to record at certain times or locations, say only at work, or only after 6 pm. Apple put a lot of stress on privacy when demoing this new feature — raw audio isn’t saved, uploaded, or retrievable, and Siri Recap doesn’t identify individual speakers. It’s also designed to exclude sensitive information or hate speech. </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="KtwHnVBdCbgYP4SrxZSxBb" name="IMG_0160" alt="daytime vitals on Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/KtwHnVBdCbgYP4SrxZSxBb-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>Even with these features, there’s still the slightly blurred line around the fact that other people’s snippets of conversation could appear in my Siri Recap, without them knowing they were being recorded. This isn’t a problem Apple faces alone — the same questions can be leveled at the ambient AI, cameras, and microphones in smart glasses and other wearable devices.</p><p>Personally, I don’t think I’d ever want my watch to be silently recording in the background, but I’ll reserve judgment until I go hands-on with the features later this year. It’s also worth noting that all of these features you’ll have to opt in to — they are automatically disabled when you unbox the watch. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-review-battery-life"><span>Apple Watch Ultra 4 review: Battery life </span></h3><p>Even with continuous heart rate monitoring every five seconds, Apple has improved the battery life on the Apple Watch Ultra 4. You’re now getting more than two days of battery life in smartwatch mode, with 50 hours of battery life, up from 42 hours of battery life in the Ultra 3. In low power mode, you’ll get 84 hours of battery life in the Apple Watch Ultra 4, compared to 72 hours in the Ultra 3. </p><p>In workout tracking, the battery is better on the Ultra 4 too. You’ll get 25 hours of battery life for tracking workouts with full GPS and heart rate tracking. This is up from 20 hours on the Ultra 3. There’s also a Max Extended Workout mode that allows the Apple Watch Ultra 4 to track outdoor runs, walks, and hikes for up to 45 hours. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="fBWgWF9dtbNxW7XaoppFXf" name="IMG_0137" alt="battery life on Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/fBWgWF9dtbNxW7XaoppFXf-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’ve found these numbers to be pretty accurate. I’m easily getting two days of battery life on my Ultra 4. It’s 5 pm right now, and I have worn the watch all day, replying to messages from my wrist and tracking three and a half hours of workouts, and my watch has gone from 82% at 6 am to 61%. </p><p>You also get faster charging on the Apple Watch Ultra 4 — 15 minutes of charge will give you up to 18 hours of battery life.</p><h3 class="article-body__section" id="section-apple-watch-ultra-4-review-should-you-buy"><span>Apple Watch Ultra 4 review: Should you buy? </span></h3><p>This is, without question, the best Apple Watch Ultra yet. Sure, there are still things missing: I’d love a built-in LED flashlight or a second size option for smaller wrists, but the health improvements made to this watch with the continuous heart rate sensing and recovery information help you train smarter. Little things like a Readiness score and Daytime Vitals help me see, at a glance, how much my long run has impacted my body. </p><p>Would I upgrade if I had an Apple Watch Ultra 3 on my wrist? I’m not sure, as the heart rate monitoring isn’t <em>bad </em>on the older watch, but if you’re wearing an older Ultra, you want longer battery life, or you’re intrigued by the Audio Intelligence features, this is a watch worth buying. </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="AYP57Su3Eno7XWdwUbPfJj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-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 on a budget, I’ve also been wearing the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a>, which is similarly excellent and has all the same sensors and features as the Ultra 4. It’s also smaller, lighter, and more comfortable to wear for 24/7 sleep tracking. </p><p>With the Apple Watch Ultra 4, you’re getting Apple’s extreme durability, the best battery life on an Apple Watch, and that all-important Action Button, which really does make using your watch with sweaty fingers better, along with the native recovery metrics long requested by serious athletes. This stands out as Apple’s most competitive endurance wearable to date. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-review</link>
                                                                            <description>
                            <![CDATA[ We've been testing the new Apple Watch Ultra 4. Here's everything you need to know about Apple's latest rugged adventure watch. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">BZsXWwWzKJQ4HrKPpsiYPU</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/UvQUGHhvPtKv7vPHykmh83-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 17 Sep 2026 12:00:00 +0000</pubDate>                                                                                                                                <updated>Thu, 17 Sep 2026 17:44:24 +0000</updated>
                                                                                                                                            <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Smartwatches]]></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/UvQUGHhvPtKv7vPHykmh83-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Ultra 4 on wrist ]]></media:description>                                                            <media:text><![CDATA[Apple Watch Ultra 4 on wrist ]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Ultra 4 on wrist ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/UvQUGHhvPtKv7vPHykmh83-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple designed the Ultra for summiting mountains and diving reefs. In reality? Most of us wearing one are weekend warriors chained to a 9-to-5, using an $800 rugged watch to track our steps on our commutes. With the Apple Watch Ultra 4, Apple makes having the watch on your wrist even better, whether you're working out or not. </p><p>The big headlines with the Apple Watch Ultra 4 are a new heart rate monitor, a readiness score to help you know when to push and when to rest, two days of battery life for the first time, and new Audio Intelligence features that will come later this year. Physically, it looks the same, but under the hood, this is a smarter watch. </p><p>But is it worth the upgrade if you already have the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3 </a>on your wrist? I’ve been wearing the Apple Watch Ultra 4 for the past week and wore it for a 22-mile run this morning to see how the heart rate monitor compares to a physical chest strap. Read my full Apple Watch Ultra 4 review to find out more. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-quick-facts"><span>Apple Watch Ultra 4: Quick facts </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="ksjEAsDzPnVz4PFiyS54Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/ksjEAsDzPnVz4PFiyS54Rj-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><ul><li><strong>Improved battery life:</strong> lasts up to 50 hours per charge compared to 42 hours for the Ultra 3</li><li><strong>New S11 chip: </strong>Faster, more efficient processing with support for Siri AI features</li><li><strong>Redesigned holistic sensors:</strong> Apple says this is the most accurate heart rate sensor on a wearable; heart rate and HRV are sampled more frequently than before; HRV insights are now more readily displayed in the Health app</li><li><strong>New health metrics:</strong> the Ultra 4 supports a new Readiness score and Health Age metric</li><li><strong>Siri AI features: </strong>the Ultra 4 ships with support for Siri AI voice assistance; new  "Audio Intelligence" features help you better recall life's important details</li></ul><h3 class="article-body__section" id="section-apple-watch-ultra-4-specs"><span>Apple Watch Ultra 4: Specs</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Apple Watch Ultra 4</p></th><th  ><p>Apple Watch Ultra 3</p></th><th  ><p>Apple Watch Series 12</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$799 / AU$1,349</p></td><td  ><p>$799 / AU$1,399</p></td><td  ><p>$399 / AU$649</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>49 x 44 x 12 mm</p></td><td  ><p>49 x 44 x 12 mm</p></td><td  ><p>46mm: 46 x 40 x 9.7mm / 42mm: 42 x 37 x 9.7mm</p></td></tr><tr><td class="firstcol " ><p><strong>Case colors</strong></p></td><td  ><p>Titanium: Natural, Black</p></td><td  ><p>Titanium: Natural, Black</p></td><td  ><p>Aluminum: Dark Bronze, Light Gold, Black, Space Gray / Titanium: Radiant Gold, Natural / Ceramic: Pearl White, Night Blue</p><p></p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td><td  ><p>46mm:  416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p><p></p></td></tr><tr><td class="firstcol " ><p><strong>Display brightness</strong></p><p></p><p></p><p></p></td><td  ><p>3,000 nits</p></td><td  ><p>3,000 nits</p></td><td  ><p>2,000 nits</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>~63 g</p></td><td  ><p>~61 g</p></td><td  ><p>46mm: ~ 39 g / 44mm: ~32 g</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>S11</p></td><td  ><p>S10</p></td><td  ><p>S11</p></td></tr><tr><td class="firstcol " ><p><strong>Cellular </strong></p></td><td  ><p>56</p></td><td  ><p>5G</p></td><td  ><p>5G</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>100 meters</p></td><td  ><p>100 meters</p></td><td  ><p>50 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life with always-on display (rated)</strong></p></td><td  ><p>50 hours</p></td><td  ><p>42 hours</p></td><td  ><p>24 hours</p></td></tr><tr><td class="firstcol " ><p><strong>Compatibility</strong></p></td><td  ><p>iOS 27 or later</p></td><td  ><p>iOS 26 or later</p></td><td  ><p>iOS 27 or later</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-apple-watch-ultra-4-review-price-and-availability"><span>Apple Watch Ultra 4 review: Price and availability </span></h3><p>The Apple Watch Ultra 4 is available for preorder from September 9, 2026. Units should hit store shelves and your hands starting on September 18. </p><p>The Apple Watch Ultra 4 is $799 / AU$1,349, the same price as the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a> and prior models. </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/5s6knEOHZAQ" allowfullscreen></iframe></div></div><h3 class="article-body__section" id="section-apple-watch-ultra-4-review-design-and-display"><span>Apple Watch Ultra 4 review: Design and display </span></h3><p>The Apple Watch Ultra 4 looks physically identical to the Ultra 3, boasting the same dimensions, oversized display with 3,000 nits of max brightness, an all-titanium case, and 100 meters of water resistance. It’s still available in black and natural titanium. </p><p>There are slightly more bands to choose from: the Trail Loop is now available in dark umber, sand, and Apple’s color of the year, burgundy. The Alpine Loop comes in desert, dark olive, and also burgundy. Ocean Bands are now made from translucent silicone and come in three new colors: translucent gray, translucent kelp, and translucent black.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="q6RPuprHDQb5uHVE6hD8Cj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/q6RPuprHDQb5uHVE6hD8Cj-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 big difference between the Apple Watch Ultra 3 and Apple Watch Ultra 4 from a design perspective is when you flip the watch over. The heart rate sensor has been completely redesigned, but more on that below. The Apple Watch Ultra 4 also has a built-in microphone for all of the audio intelligence features coming later this year. </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="VLq9FtKKTYZpBzEqFLvGk9" name="IMG_0127" alt="Apple Watch Ultra 4 on wrist" src="https://cdn.mos.cms.futurecdn.net/VLq9FtKKTYZpBzEqFLvGk9-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-apple-watch-ultra-4-review-health-and-fitness-tracking"><span>Apple Watch Ultra 4 review: Health and fitness tracking </span></h3><p>The biggest difference, and the reason I think this is the best Apple Watch Ultra yet, is the new heart rate monitor loaded onto the watch. When looking at the two monitors side-by-side, the Ultra 4 and the Apple Watch Series 12 have a “32-petal design,” whereas older watches had a two-petal design. This refers to the spoke-like lines coming out of the electrode.</p><p>The green LED lights, which measure your heart rate by shining light into the skin, are bigger and more powerful. Apple says it also makes the heart rate monitor more accurate on certain skin tones, although it might still struggle if you have tattoos on your wrist. </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="SjN282csQtBMb6DaeDKsKG" name="IMG_0166" alt="HR monitor on Apple Watch Ultra 3 and Ultra 4" src="https://cdn.mos.cms.futurecdn.net/SjN282csQtBMb6DaeDKsKG-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’ve always found the heart rate monitor on my Apple Watch Ultra 3 to be a little sketchy, and while I often put this down to how it sits on my wrist, I was keen to see how things might have changed on the Ultra 4. It’s worth noting that if, like me, you have petite wrists, you’ll need to ensure the Ultra is really tight against your wrist. I’ve found that if my watch strap isn’t tight enough, the watch just doesn’t give me a heart rate reading. </p><p>Heart rate data lies at the heart of a lot of health features on the Apple Watch, including HRV, workouts, and ovulation prediction. With the Apple Watch Ultra 4, the new heart rate monitor, along with the S-11 chip, measures your heart rate every five seconds, all day long. On the Apple Watch Ultra 3, Apple only allowed continuous heart rate monitoring during a workout, but this is a huge step in the right direction. Inside the Heart Rate app, there's a rolling two-minute chart. </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="nMisA2bBjx2DUYFYKuha5M" name="IMG_0153" alt="Continious heart rate monitoring on Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/nMisA2bBjx2DUYFYKuha5M-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>On the Apple Watch Ultra 4, you’ll be able to see your Recovery HRV score, which shows signs of stress and recovery, as well as your overall HRV, which offers insights into your overall health. You can now see from your wrist if your heart rate suddenly spikes, and through the new daytime Vitals app, you're getting a much more immediate picture of what's happening, rather than having to wait till you’re asleep.</p><p>I’ve been testing the new heart rate sensor alongside a chest strap and my Oura Ring 5, and have found the Apple Watch Ultra 4 to be pretty much spot on. Here’s a graph from my recent run:</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1600px;"><p class="vanilla-image-block" style="padding-top:41.63%;"><img id="TGaCp9nPJDiHWNan4rLuwQ" name="WhatsApp Image 2026-09-16 at 5.19.12 PM" alt="a heart rate graph from Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/TGaCp9nPJDiHWNan4rLuwQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1600" height="666" 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 new sensors also feed into the new daily Readiness score, which is only available on the Apple Watch Series 12 and Apple Watch Ultra 4. Readiness provides a single score out of ten with one of four different recommendations: Recover, Pace Yourself, Ready, or Go For It. Readiness updates throughout the day as new data comes in, and is based on your overnight vitals, sleep score, recent physical activity, and training load. </p><p>To get a Readiness score, you need to wear the watch for seven nights and get at least four hours of sleep per night. While I have done that, my Apple Watch got a little confused by moving time zones, so it only registered two hours of sleep as I travelled back to London from Cupertino. I’ll update this review soon when I’ve had a few days of Readiness scores. I’ll also look at how these scores compare to the likes of Body Battery on Garmin, and the Readiness score on the Oura Ring 5. </p><p>Later this year, the Health App will see big changes, including a new Health Age score that compares your physical fitness to the average for your age. There will also be a greater emphasis on things like sleep trends, heart data, and other longevity metrics. Again, I’ll be testing these as soon as they drop, but I’m excited to hear about these updates to make the Health app more useful to users.</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="jc8nWCpY62gd8Tbt9Vu7cV" name="IMG_0119" alt="a photo of the Apple Watch Ultra 4 on wrist" src="https://cdn.mos.cms.futurecdn.net/jc8nWCpY62gd8Tbt9Vu7cV-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>Of course, it's worth noting that Apple isn’t reinventing the wheel — Garmin has had a Fitness Age score forever, but wearing a Garmin isn’t like having an extension of your iPhone on your wrist. While these little changes might not sound like a lot, a Readiness score can show you at a glance if you’re overtraining and putting yourself at risk of injury. Whether you’re a weekend warrior or training for your seventh marathon, knowing how well you’re coping with your training is imperative, and Apple makes this easier with the Apple Watch Ultra 4.</p><p>Another minor but exciting update I’ve found during my testing is the Steps watch face. At last, you can see your daily step count from your watch face. Sure, steps aren’t the biggest health metric to keep an eye on, but on rest days, I still like to make sure I’m closing my rings and keeping my legs moving. Unfortunately for folks with an older Apple Watch, this is a hardware thing, as Apple says it relies on the more accurate S-11 chip, so older watches won’t get the updated pedometer.</p><h3 class="article-body__section" id="section-apple-watch-ultra-4-review-audio-intelligence"><span>Apple Watch Ultra 4 review: Audio Intelligence </span></h3><p>Now, to address the parts of the watch that are probably going to get headlines — the Audio Intelligence features. Here’s everything you need to know about the new <a href="https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained"><u>Audio Intelligence features</u></a>, but in a nutshell, the two features everyone is talking about are Live Rewind and Siri Recap. </p><p>Neither is available for me to test just yet; they are coming later in the year, but essentially, Live Rewind allows you to double-click on the Digital Crown of your Apple Watch Ultra 4 and get a 15-second recap of what was just said around you. The Watch will play an audible chime even if your watch is on silent and puts a microphone indicator on screen, so people around you will know you’re recording.</p><p>One example is if you’d missed the specials at a restaurant, or missed a colleague's name, you could read it from your watch. I think there’s a compelling reason here, say, if you have ADHD or struggle with auditory processing. </p><p>The trickier sell, for me and most people I’ve spoken to, is Siri Recap. This records ambient audio every 15 minutes to create an itemized CliffsNotes of your day. You can set this to record at certain times or locations, say only at work, or only after 6 pm. Apple put a lot of stress on privacy when demoing this new feature — raw audio isn’t saved, uploaded, or retrievable, and Siri Recap doesn’t identify individual speakers. It’s also designed to exclude sensitive information or hate speech. </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="KtwHnVBdCbgYP4SrxZSxBb" name="IMG_0160" alt="daytime vitals on Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/KtwHnVBdCbgYP4SrxZSxBb-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>Even with these features, there’s still the slightly blurred line around the fact that other people’s snippets of conversation could appear in my Siri Recap, without them knowing they were being recorded. This isn’t a problem Apple faces alone — the same questions can be leveled at the ambient AI, cameras, and microphones in smart glasses and other wearable devices.</p><p>Personally, I don’t think I’d ever want my watch to be silently recording in the background, but I’ll reserve judgment until I go hands-on with the features later this year. It’s also worth noting that all of these features you’ll have to opt in to — they are automatically disabled when you unbox the watch. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-review-battery-life"><span>Apple Watch Ultra 4 review: Battery life </span></h3><p>Even with continuous heart rate monitoring every five seconds, Apple has improved the battery life on the Apple Watch Ultra 4. You’re now getting more than two days of battery life in smartwatch mode, with 50 hours of battery life, up from 42 hours of battery life in the Ultra 3. In low power mode, you’ll get 84 hours of battery life in the Apple Watch Ultra 4, compared to 72 hours in the Ultra 3. </p><p>In workout tracking, the battery is better on the Ultra 4 too. You’ll get 25 hours of battery life for tracking workouts with full GPS and heart rate tracking. This is up from 20 hours on the Ultra 3. There’s also a Max Extended Workout mode that allows the Apple Watch Ultra 4 to track outdoor runs, walks, and hikes for up to 45 hours. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="fBWgWF9dtbNxW7XaoppFXf" name="IMG_0137" alt="battery life on Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/fBWgWF9dtbNxW7XaoppFXf-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’ve found these numbers to be pretty accurate. I’m easily getting two days of battery life on my Ultra 4. It’s 5 pm right now, and I have worn the watch all day, replying to messages from my wrist and tracking three and a half hours of workouts, and my watch has gone from 82% at 6 am to 61%. </p><p>You also get faster charging on the Apple Watch Ultra 4 — 15 minutes of charge will give you up to 18 hours of battery life.</p><h3 class="article-body__section" id="section-apple-watch-ultra-4-review-should-you-buy"><span>Apple Watch Ultra 4 review: Should you buy? </span></h3><p>This is, without question, the best Apple Watch Ultra yet. Sure, there are still things missing: I’d love a built-in LED flashlight or a second size option for smaller wrists, but the health improvements made to this watch with the continuous heart rate sensing and recovery information help you train smarter. Little things like a Readiness score and Daytime Vitals help me see, at a glance, how much my long run has impacted my body. </p><p>Would I upgrade if I had an Apple Watch Ultra 3 on my wrist? I’m not sure, as the heart rate monitoring isn’t <em>bad </em>on the older watch, but if you’re wearing an older Ultra, you want longer battery life, or you’re intrigued by the Audio Intelligence features, this is a watch worth buying. </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="AYP57Su3Eno7XWdwUbPfJj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-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 on a budget, I’ve also been wearing the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a>, which is similarly excellent and has all the same sensors and features as the Ultra 4. It’s also smaller, lighter, and more comfortable to wear for 24/7 sleep tracking. </p><p>With the Apple Watch Ultra 4, you’re getting Apple’s extreme durability, the best battery life on an Apple Watch, and that all-important Action Button, which really does make using your watch with sweaty fingers better, along with the native recovery metrics long requested by serious athletes. This stands out as Apple’s most competitive endurance wearable to date. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Samsung Galaxy Watch Ultra 2 review: Android's toughest smartwatch is improved in nearly every way ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The Galaxy Watch Ultra series is Samsung's answer to the rugged, outdoor adventure-ready Apple Watch Ultra series, and the latest model, the Samsung Galaxy Watch Ultra 2, makes a strong case for being the best tough-built, full-featured smartwatch on the market today.</p><p>Two years after the launch of the original ultra-rugged <a href="https://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-ultra-review">Samsung Galaxy Watch</a>, the new model adds better battery life, tons of new health and fitness insights, a brighter screen, and improved water resistance, all in a familiar design.</p><p>But can the Samsung Galaxy Watch Ultra 2 <em>actually</em> keep up with the latest <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4</a> and/or the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches</a> when it comes to logging adrenaline-pumping activities like mountain bike rides, hikes, and more? I decided to find out by wearing the Galaxy Watch Ultra 2 for two weeks. Here's what I discovered. </p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-key-upgrades"><span>Galaxy Watch Ultra 2: Key upgrades</span></h3><p>But first, here’s a cheat sheet to all the most notable Galaxy Watch Ultra 2 stats and upgrades. </p><ul><li><strong>Price: </strong>At $699, the Galaxy Watch Ultra 2 is $50 more than its predecessor, which launched two years ago, but still $100 less than its nearest competitor, the Apple Watch Ultra 3.</li><li><strong>Design:</strong> The Galaxy Watch Ultra 2 is a tiny bit thinner than the original Galaxy Watch Ultra, but you may not notice the difference; the dimensions and weight are nearly identical to the original model</li><li><strong>Screen: </strong>Maximum screen brightness has been bumped up from 4,000 nits to 5,000 nits, making it remarkably visible in direct sunlight</li><li><strong>Health features:</strong> New 'Vitals' dashboard with key metrics including heart rate, HRV, Sp02, body temp, and breath rate in one place; new 'Heart Health' score</li><li><strong>Fitness features:</strong> New Cardio Load insights, new Fitness Index score out of 100 based on factors like daily step count average, V02 Max, average heart rate, BIA (Bioelectrical Impedance Analysis), and average workout recovery time</li><li><strong>Battery life:</strong> 800 mAh battery is the largest in an Android wearable and a 35% capacity increase over the original Galaxy Watch Ultra; battery life usage averages ~25% drain per day in testing so far</li></ul><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-versus-competition"><span>Galaxy Watch Ultra 2: Versus competition</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Samsung Galaxy Watch Ultra 2</p></th><th  ><p>Samsung Galaxy Watch Ultra </p></th><th  ><p>Apple Watch Ultra 4</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$699 / AU$1299</p></td><td  ><p>$649</p></td><td  ><p>$799</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>47 x 47 x 10 mm </p></td><td  ><p>47 x 47 x 12 mm </p></td><td  ><p>49 x 44 x 12 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>61.5 g</p></td><td  ><p>60.5 g</p></td><td  ><p>63 g</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>1.52-inch AMOLED, 5,000 nits max brightness </p></td><td  ><p>1.5-inch AMOLED, 3,000 nits max brightness </p></td><td  ><p>1.98-inch OLED, 3,000 nits max brightness</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>100 meters</p></td><td  ><p>100 meters (not approved for diving)</p></td><td  ><p>100 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life (tested)</strong></p></td><td  ><p>60 hours</p></td><td  ><p>48 hours </p></td><td  ><p>50 hours</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-value-3-5"><span>Galaxy Watch Ultra 2 value: 3/5</span></h3><ul><li><strong>At $699, the Ultra 2 is $50 more than its predecessor but still $100 cheaper than the Apple Watch Ultra 4</strong></li><li><strong>The more affordable Galaxy Watch 9 offers most of the same features as the Galaxy Watch Ultra 2, starting at $379</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4737px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="7RLoxSzFXxAzKQFchr6Qod" name="GalaxyWatchUltra2-v-AWU3-01" alt="Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch" src="https://cdn.mos.cms.futurecdn.net/7RLoxSzFXxAzKQFchr6Qod-1920-80.jpg" mos="" align="middle" fullscreen="" width="4737" height="2664" 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 Samsung Galaxy Watch Ultra 2 is priced at $699, a modest $50 increase over the launch price of its two-year-old predecessor. More notably, it's a hundred bucks cheaper than the latest Apple Watch Ultra 4, its nearest non-Android competitor. </p><p>Meanwhile, the latest <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-to-know-about-the-new-samsung-galaxy-watch-9https://www.tomsguide.com/wellness/smartwatches/i-wore-the-samsung-galaxy-watch-9-for-a-month-the-new-health-tools-impress-but-that-doesnt-mean-you-should-upgrade">Galaxy Watch 9</a> models —which share pretty much all the same features, just in a less beefy package — range from $379 to $459. </p><p>The <a href="https://www.amazon.com/Samsung-Galaxy-Ultra2-Titanium-Smartwatch/dp/B0H1D6V1BB/" target="_blank" rel="nofollow">$699 Galaxy Watch Ultra 2</a> is available now in stores and online. </p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-display-4-5-5"><span>Galaxy Watch Ultra 2 display: 4.5/5</span></h3><ul><li><strong>The Galaxy Watch Ultra 2 has one of the largest, brightest displays in any full-featured smartwatch</strong></li><li><strong>Max brightness is 5,000 nits, making the Ultra 2 a breeze to read in direct sunlight</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="tD4jVF3hN7MiivgZYydHDe" name="GalaxyWatchUltra2-08" alt="Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch" src="https://cdn.mos.cms.futurecdn.net/tD4jVF3hN7MiivgZYydHDe-1920-80.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>The new Samsung Galaxy Watch Ultra 2 sports a sizable 1.52-inch display that maxes out at an impressive 5,000 nits, making it one of the brightest displays in any full-featured wearable, including 2026's <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a>.</p><p>The Apple Watch Ultra 4, by comparison, also features a large, lovely display, but it only maxes out at 3,000 nits. Real-world translation: the new Galaxy Watch Ultra 2 is a lot easier to read in bright sunlight than the newest Apple Watch Ultra.</p><p>I also wore both the Galaxy Watch Ultra 2 and <a href="https://www.tomsguide.com/Garmin-Instinct-3-review">Garmin Instinct 3</a> — my go-to GPS sports watch — while e-mountain biking and also found the former more legible while on the move.</p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-design-and-durability-4-5"><span>Galaxy Watch Ultra 2 design and durability: 4/5</span></h3><ul><li><strong>Unlike its predecessor, the Galaxy Watch Ultra 2 is now officially scuba dive-certified</strong></li><li><strong>The case is a little slimmer than before, but you might not notice; ultimately, the Galaxy Watch Ultra feels pretty chunky on my 6.5-inch wrist</strong></li><li><strong>The included strap is softer and more flexible than the strap for the original model</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4613px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="u4HGWUFwc8QuKbaWkCz6NZ" name="GalaxyUltra2-dive-02" alt="Close-up of a water-soaked Samsung Galaxy Watch Ultra 2 on a bright blue background" src="https://cdn.mos.cms.futurecdn.net/u4HGWUFwc8QuKbaWkCz6NZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="4613" height="2595" 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 original Samsung Galaxy Watch Ultra promises 100 meters of water resistance, but unlike its Apple Watch Ultra counterpart, Samsung's rugged model wasn't intended for use while diving or even snorkeling.</p><p>Samsung no doubt caught some flak for this shortcoming. Thankfully, the new Galaxy Watch Ultra 2 is thoroughly dive-ready. In fact, Samsung partnered with the industry-trusted <a href="https://www.mares.com/en_US/mares-app" target="_blank">Mares diving app</a> to turn the Galaxy Watch Ultra 2 into a <a href="https://www.tomsguide.com/wellness/smartwatches/samsung-turned-the-galaxy-watch-ultra-2-into-a-fully-fledged-dive-computer-but-theres-a-catch">fully-fledged dive computer</a>, complete with speed monitoring and safety-stop alerts. The app costs $8.99 a month or $69.99 for the year. </p><p>The Ultra 2 is rated for 100 meters of water resistance and is EN13319-certified for scuba diving and IP69K-certified against dust and moisture.</p><p>Design-wise, the Galaxy Watch Ultra 2 looks nearly identical to its predecessor, with close-to-the-same dimensions and weight. That said, Samsung technically shaved 2mm off the case thickness, but I hardly noticed it. The case still feels very large on my 6.5-inch wrist.</p><p>There are three physical buttons along one side of the case; the center "Action" button can be customized to perform one of eight actions. I set it up to start a workout. </p><p>One less obvious but definitely welcome design change is the inclusion of a softer, more flexible strap. Also, the Ultra 2 uses the same attachment system as its predecessor, so if you prefer the older version, you can easily swap it onto the newer model.</p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-health-tools-4-5-5"><span>Galaxy Watch Ultra 2 Health tools: 4.5/5</span></h3><ul><li><strong>New Vitals tab in Samsung Health app provides useful insights into long-term health and fitness trends</strong></li><li><strong>Comprehensive sleep tracking reports on par with the best smartwatches</strong></li><li><strong>None of Samsung's holistic features are paywalled, unlike Google and Garmin</strong></li><li><strong>New Heart Health score for monitoring cardiovascular wellness</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4797px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="vHP2ZPZZ4Z6xQ2bKK5vYtZ" name="GalaxyWatchUltra2-06" alt="Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch" src="https://cdn.mos.cms.futurecdn.net/vHP2ZPZZ4Z6xQ2bKK5vYtZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="4797" height="2698" 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>Similar to the new Samsung Galaxy Watch 9, the Galaxy Watch Ultra 2 ships fully-loaded with all sorts of new health and fitness insights. </p><p>These features include a new Vitals dashboard in the Samsung Health app for viewing your most important up-to-the-minute health stats in one place, a new Cardio Load score to track your heart health, and a new Fitness Index score that compares your overall physical health to averages for your age and gender. </p><p>The Vitals tab shows your current heart rate, heart rate variability (HRV), blood oxygen saturation percentage (Sp02), body temperature, and breathing rate. </p><p>The new Heart Health score ranges from one to 100, with the upper end being better. This metric updates dynamically throughout the day, keeping users appraised of how their everyday decisions may be impacting cardiovascular health for better or worse.</p><p>Fitness Index, meanwhile, factors in loads of fitness and wellness metrics to figure out how your overall health compares to your peers in five key categories: strength, cardio, endurance, flexibility, and body composition. You also get a dynamic score from one to 100 (mine is currently 82, or "average"). </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:3515px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="LYfp9ZExt4wz8PuvGiRGJW" name="GalaxyWatchUltra2-03" alt="Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch" src="https://cdn.mos.cms.futurecdn.net/LYfp9ZExt4wz8PuvGiRGJW-1920-80.jpg" mos="" align="middle" fullscreen="" width="3515" height="1977" 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>Samsung's smartwatches deliver some of the most detailed and actionable sleep reports of any smartwatch brand, and even though there aren't any shiny new features, the Galaxy Watch Ultra 2 is a mighty fine sleep tracker. That is, assuming you can get over wearing something so chunky to bed.</p><p>Like its predecessor, the Galaxy Watch Ultra 2 is FDA-cleared for sleep apnea detection, something that can't be said for the newest Google Pixel Watch models. </p><p>Also, unlike some of the competition — cough, cough, Google and Garmin — Samsung doesn't make you pay a monthly or annual subscription to access the full suite of health insights, including AI-powered personalized training and recovery recommendations. </p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-fitness-tracking-3-5"><span>Galaxy Watch Ultra 2 fitness tracking: 3/5</span></h3><ul><li><strong>Reliable heart rate tracking </strong></li><li><strong>Nearly as reliable at logging workouts as the best outdoor adventure watches, with one exception... </strong></li><li><strong>The Ultra 2 tends to overinflate the 'Climb' metric when logging walks, runs, bike rides, and hikes</strong></li><li><strong>Lacks tracking modes for some of the more nuanced yet popular outdoor activities like mountain biking and e-biking</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="z4fwvXKWVZz3GTwNXzQkGV" name="GalaxyUltra2-Instinct3-02" alt="Close-up of the Samsung Galaxy Watch Ultra 2 next to the Garmin Instinct 3 against a bright blue background" src="https://cdn.mos.cms.futurecdn.net/z4fwvXKWVZz3GTwNXzQkGV-1920-80.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>The Galaxy Watch Ultra 2 is rightfully billed as a smartwatch for outdoor enthusiasts and lovers of extreme-style sports. However, I found two shortcomings in my testing.</p><p>First, the Galaxy Watch Ultra 2 sometimes struggles to accurately track elevation gain when logging an outdoor workout, with a tendency to noticeably inflate climb data. I encountered this when testing the <a href="https://www.tomsguide.com/wellness/smartwatches/i-biked-11-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-ultra-2-and-the-winner-is-clear">Galaxy Watch Ultra 2 vs. Garmin Instinct 3</a> while city cycling in hilly Seattle, Washington, and again when I went <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-went-e-mountain-biking-in-cougar-country-with-the-new-samsung-galaxy-watch-ultra-2-vs-garmin-instinct-3-and-the-winner-is-clear">e-mountain biking in Washington State's Cougar Country</a>.</p><p>That said, the Samsung Galaxy Watch Ultra 2 performed extremely well in a head-to-head walk test comparison <a href="https://www.tomsguide.com/wellness/smartwatches/i-manually-counted-4-000-steps-to-test-the-apple-watch-ultra-3-vs-samsung-galaxy-watch-ultra-2-and-samsung-wins-the-accuracy-battle-with-better-elevation-data-too">versus the Apple Watch Ultra 3.</a> However, it once again delivered highly inflated elevation data when I <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-trekked-the-cascade-mountains-with-the-apple-watch-ultra-3-vs-garmin-instinct-3-vs-samsung-galaxy-watch-ultra-2-this-is-the-one-id-take-on-my-next-hike">hiked the Cascade Mountains</a> with the Galaxy Watch Ultra 2 vs. Garmin Instinct 3 vs. Apple Watch Ultra 3.</p><p>Elevation tracking aside, the Samsung Galaxy Watch Ultra 2 largely performs as well as the best smartwatches and fitness trackers when it comes to reliably logging both moving and stationary workouts. Ultimately, as long as you wear the device tight enough, heart rate data should also be highly accurate. </p><p>My other criticism of the Galaxy Watch Ultra 2, which, again, is sold as an outdoor adventure-ready smartwatch, is a lack of tracking modes for popular activities, like mountain biking and e-biking.</p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-ai-features-3-5-5"><span>Galaxy Watch Ultra 2 AI features: 3.5/5</span></h3><ul><li><strong>Google's useful Gemini AI voice assistant is built-in and can be launched via a handy, new 'Raise to talk' gesture control </strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4043px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="epc4o6iQmt6rjHFos7nLnd" name="GalaxyWatchUltra2-Gemini" alt="Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch" src="https://cdn.mos.cms.futurecdn.net/epc4o6iQmt6rjHFos7nLnd-1920-80.jpg" mos="" align="middle" fullscreen="" width="4043" height="2275" 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 AI playing a part in some of Samsung's flagship new health features, the Galaxy Watch Ultra 2 ships with Google's Gemini AI voice assistant built-in. It's the best smartwatch voice assistant I've tested so far, though that may change after I thoroughly test the latest <a href="https://www.tomsguide.com/wellness/smartwatches/how-to-enable-siri-ai-on-your-apple-watch">Siri AI</a> on the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a>.</p><p>With access granted to apps like Gmail and Google Calendar, the Gemini assistant is more than capable of answering super-specific questions like, "When did my sister say her flight is landing next week?" as well as more generic ones like "What's the cheapest, easiest way to soften a stiff T-shirt?"</p><p>Better yet, you can launch the Gemini assistant using the Galaxy Watch Ultra 2 by simply raising your wrist (you will need to first turn it on in the settings menu).  Samsung's "Raise to talk" gesture control is remarkably effective, on par with Google's version for the Pixel Watch 4 and 5. </p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-battery-4-5-5"><span>Galaxy Watch Ultra 2 battery: 4.5/5</span></h3><ul><li><strong>The Galaxy Watch Ultra 2 exceeded its 60-hour-per-charge battery life rating in testing, lasting closer to 72 hours per charge with the always-on display enabled</strong></li><li><strong>This makes it one of the longest-lasting full-featured smartwatches for Android in 2026 and longer-lasting than the latest Apple Watch Ultra 4</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4187px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bymkGs65ruZkWfvJQAJDCe" name="GalaxyWatchUltra2-02" alt="Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch" src="https://cdn.mos.cms.futurecdn.net/bymkGs65ruZkWfvJQAJDCe-1920-80.jpg" mos="" align="middle" fullscreen="" width="4187" height="2355" 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>Not only did Samsung equip the Galaxy Watch Ultra 2 with a higher-capacity battery — 590 mAh for the old model vs. 800 mAh for the new one — but the Galaxy Watch Ultra 2 is also more power-efficient than its predecessor, despite a brighter display.</p><p>The original Galaxy Watch Ultra had a battery life rating of 48 hours per charge, a claim we verified in our testing. The new model is rated to last up to 60 hours per charge, but in my testing, it comfortably surpassed that, cruising for closer to 72 hours per charge. </p><p>By comparison, the Samsung <a href="https://www.tomsguide.com/wellness/smartwatches/i-wore-the-samsung-galaxy-watch-9-for-a-month-the-new-health-tools-impress-but-that-doesnt-mean-you-should-upgrade#section-samsung-galaxy-watch-9-battery-life-3-5">Galaxy Watch 9 gets 40 hours</a> per charge at best (44mm). Meanwhile, the latest <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model">Apple Watch Ultra 4</a>, the nearest competitor to the Galaxy Watch Ultra 2, lasts for about 50 hours per charge. </p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-review-verdict"><span>Galaxy Watch Ultra 2 review: Verdict</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3792px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="AZF7DPLYsQoJ9PLhoqBiNo" name="AWU3-GalaxyU2-Instinct3-03" alt="Close-up of the Samsung Galaxy Watch Ultra 2, Apple Watch Ultra 3 and Garmin Instinct 3 in nature" src="https://cdn.mos.cms.futurecdn.net/AZF7DPLYsQoJ9PLhoqBiNo-1920-80.jpg" mos="" align="middle" fullscreen="" width="3792" height="2134" 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 Samsung Galaxy Watch Ultra 2 is a meaningful update to the original Galaxy Watch Ultra. The newer model is even tougher, with legit scuba-diving-ready specs and features, longer-lasting, with up to three days of battery per charge, and ever-so-slightly more comfortable thanks to a thinner case and a softer, more flexible strap.</p><p>The screen brightness has also been increased, giving the Galaxy Watch Ultra 2 the brightest display in any full-featured smartwatch for Android. Plus, new health and fitness tracking metrics help to bring long-term holistic trends into sharper focus. </p><p>As an outdoor adventure watch, the Galaxy Watch Ultra 2 proved mighty capable, with one exception: faulty elevation data. However, I'm hoping this is just a minor hiccup that will eventually be fixed with future firmware. </p><p>Ultimately, the Galaxy Watch Ultra 2 is a tougher, smarter, longer-lasting take on what was already one of the best Android smartwatches ever made. That, I think, is worth the $50 price increase.</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-ultra-2-review</link>
                                                                            <description>
                            <![CDATA[ The toughest full-featured smartwatch for Android just got even better. The new Galaxy Watch Ultra 2 is better-built, longer-lasting, smarter, and even comfier than its predecessor. Here are my takeaways after two weeks wearing it. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">T7XTs9fChvvtVKkqzVKQfX</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/8B3oWg32u4GseBhhsnfnea-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 17 Sep 2026 08:30:00 +0000</pubDate>                                                                                                                                <updated>Thu, 17 Sep 2026 17:44:24 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/8B3oWg32u4GseBhhsnfnea-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch]]></media:description>                                                            <media:text><![CDATA[Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/8B3oWg32u4GseBhhsnfnea-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The Galaxy Watch Ultra series is Samsung's answer to the rugged, outdoor adventure-ready Apple Watch Ultra series, and the latest model, the Samsung Galaxy Watch Ultra 2, makes a strong case for being the best tough-built, full-featured smartwatch on the market today.</p><p>Two years after the launch of the original ultra-rugged <a href="https://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-ultra-review">Samsung Galaxy Watch</a>, the new model adds better battery life, tons of new health and fitness insights, a brighter screen, and improved water resistance, all in a familiar design.</p><p>But can the Samsung Galaxy Watch Ultra 2 <em>actually</em> keep up with the latest <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4</a> and/or the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches</a> when it comes to logging adrenaline-pumping activities like mountain bike rides, hikes, and more? I decided to find out by wearing the Galaxy Watch Ultra 2 for two weeks. Here's what I discovered. </p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-key-upgrades"><span>Galaxy Watch Ultra 2: Key upgrades</span></h3><p>But first, here’s a cheat sheet to all the most notable Galaxy Watch Ultra 2 stats and upgrades. </p><ul><li><strong>Price: </strong>At $699, the Galaxy Watch Ultra 2 is $50 more than its predecessor, which launched two years ago, but still $100 less than its nearest competitor, the Apple Watch Ultra 3.</li><li><strong>Design:</strong> The Galaxy Watch Ultra 2 is a tiny bit thinner than the original Galaxy Watch Ultra, but you may not notice the difference; the dimensions and weight are nearly identical to the original model</li><li><strong>Screen: </strong>Maximum screen brightness has been bumped up from 4,000 nits to 5,000 nits, making it remarkably visible in direct sunlight</li><li><strong>Health features:</strong> New 'Vitals' dashboard with key metrics including heart rate, HRV, Sp02, body temp, and breath rate in one place; new 'Heart Health' score</li><li><strong>Fitness features:</strong> New Cardio Load insights, new Fitness Index score out of 100 based on factors like daily step count average, V02 Max, average heart rate, BIA (Bioelectrical Impedance Analysis), and average workout recovery time</li><li><strong>Battery life:</strong> 800 mAh battery is the largest in an Android wearable and a 35% capacity increase over the original Galaxy Watch Ultra; battery life usage averages ~25% drain per day in testing so far</li></ul><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-versus-competition"><span>Galaxy Watch Ultra 2: Versus competition</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Samsung Galaxy Watch Ultra 2</p></th><th  ><p>Samsung Galaxy Watch Ultra </p></th><th  ><p>Apple Watch Ultra 4</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$699 / AU$1299</p></td><td  ><p>$649</p></td><td  ><p>$799</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>47 x 47 x 10 mm </p></td><td  ><p>47 x 47 x 12 mm </p></td><td  ><p>49 x 44 x 12 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>61.5 g</p></td><td  ><p>60.5 g</p></td><td  ><p>63 g</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>1.52-inch AMOLED, 5,000 nits max brightness </p></td><td  ><p>1.5-inch AMOLED, 3,000 nits max brightness </p></td><td  ><p>1.98-inch OLED, 3,000 nits max brightness</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>100 meters</p></td><td  ><p>100 meters (not approved for diving)</p></td><td  ><p>100 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life (tested)</strong></p></td><td  ><p>60 hours</p></td><td  ><p>48 hours </p></td><td  ><p>50 hours</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-value-3-5"><span>Galaxy Watch Ultra 2 value: 3/5</span></h3><ul><li><strong>At $699, the Ultra 2 is $50 more than its predecessor but still $100 cheaper than the Apple Watch Ultra 4</strong></li><li><strong>The more affordable Galaxy Watch 9 offers most of the same features as the Galaxy Watch Ultra 2, starting at $379</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4737px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="7RLoxSzFXxAzKQFchr6Qod" name="GalaxyWatchUltra2-v-AWU3-01" alt="Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch" src="https://cdn.mos.cms.futurecdn.net/7RLoxSzFXxAzKQFchr6Qod-1920-80.jpg" mos="" align="middle" fullscreen="" width="4737" height="2664" 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 Samsung Galaxy Watch Ultra 2 is priced at $699, a modest $50 increase over the launch price of its two-year-old predecessor. More notably, it's a hundred bucks cheaper than the latest Apple Watch Ultra 4, its nearest non-Android competitor. </p><p>Meanwhile, the latest <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-to-know-about-the-new-samsung-galaxy-watch-9https://www.tomsguide.com/wellness/smartwatches/i-wore-the-samsung-galaxy-watch-9-for-a-month-the-new-health-tools-impress-but-that-doesnt-mean-you-should-upgrade">Galaxy Watch 9</a> models —which share pretty much all the same features, just in a less beefy package — range from $379 to $459. </p><p>The <a href="https://www.amazon.com/Samsung-Galaxy-Ultra2-Titanium-Smartwatch/dp/B0H1D6V1BB/" target="_blank" rel="nofollow">$699 Galaxy Watch Ultra 2</a> is available now in stores and online. </p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-display-4-5-5"><span>Galaxy Watch Ultra 2 display: 4.5/5</span></h3><ul><li><strong>The Galaxy Watch Ultra 2 has one of the largest, brightest displays in any full-featured smartwatch</strong></li><li><strong>Max brightness is 5,000 nits, making the Ultra 2 a breeze to read in direct sunlight</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="tD4jVF3hN7MiivgZYydHDe" name="GalaxyWatchUltra2-08" alt="Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch" src="https://cdn.mos.cms.futurecdn.net/tD4jVF3hN7MiivgZYydHDe-1920-80.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>The new Samsung Galaxy Watch Ultra 2 sports a sizable 1.52-inch display that maxes out at an impressive 5,000 nits, making it one of the brightest displays in any full-featured wearable, including 2026's <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a>.</p><p>The Apple Watch Ultra 4, by comparison, also features a large, lovely display, but it only maxes out at 3,000 nits. Real-world translation: the new Galaxy Watch Ultra 2 is a lot easier to read in bright sunlight than the newest Apple Watch Ultra.</p><p>I also wore both the Galaxy Watch Ultra 2 and <a href="https://www.tomsguide.com/Garmin-Instinct-3-review">Garmin Instinct 3</a> — my go-to GPS sports watch — while e-mountain biking and also found the former more legible while on the move.</p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-design-and-durability-4-5"><span>Galaxy Watch Ultra 2 design and durability: 4/5</span></h3><ul><li><strong>Unlike its predecessor, the Galaxy Watch Ultra 2 is now officially scuba dive-certified</strong></li><li><strong>The case is a little slimmer than before, but you might not notice; ultimately, the Galaxy Watch Ultra feels pretty chunky on my 6.5-inch wrist</strong></li><li><strong>The included strap is softer and more flexible than the strap for the original model</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4613px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="u4HGWUFwc8QuKbaWkCz6NZ" name="GalaxyUltra2-dive-02" alt="Close-up of a water-soaked Samsung Galaxy Watch Ultra 2 on a bright blue background" src="https://cdn.mos.cms.futurecdn.net/u4HGWUFwc8QuKbaWkCz6NZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="4613" height="2595" 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 original Samsung Galaxy Watch Ultra promises 100 meters of water resistance, but unlike its Apple Watch Ultra counterpart, Samsung's rugged model wasn't intended for use while diving or even snorkeling.</p><p>Samsung no doubt caught some flak for this shortcoming. Thankfully, the new Galaxy Watch Ultra 2 is thoroughly dive-ready. In fact, Samsung partnered with the industry-trusted <a href="https://www.mares.com/en_US/mares-app" target="_blank">Mares diving app</a> to turn the Galaxy Watch Ultra 2 into a <a href="https://www.tomsguide.com/wellness/smartwatches/samsung-turned-the-galaxy-watch-ultra-2-into-a-fully-fledged-dive-computer-but-theres-a-catch">fully-fledged dive computer</a>, complete with speed monitoring and safety-stop alerts. The app costs $8.99 a month or $69.99 for the year. </p><p>The Ultra 2 is rated for 100 meters of water resistance and is EN13319-certified for scuba diving and IP69K-certified against dust and moisture.</p><p>Design-wise, the Galaxy Watch Ultra 2 looks nearly identical to its predecessor, with close-to-the-same dimensions and weight. That said, Samsung technically shaved 2mm off the case thickness, but I hardly noticed it. The case still feels very large on my 6.5-inch wrist.</p><p>There are three physical buttons along one side of the case; the center "Action" button can be customized to perform one of eight actions. I set it up to start a workout. </p><p>One less obvious but definitely welcome design change is the inclusion of a softer, more flexible strap. Also, the Ultra 2 uses the same attachment system as its predecessor, so if you prefer the older version, you can easily swap it onto the newer model.</p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-health-tools-4-5-5"><span>Galaxy Watch Ultra 2 Health tools: 4.5/5</span></h3><ul><li><strong>New Vitals tab in Samsung Health app provides useful insights into long-term health and fitness trends</strong></li><li><strong>Comprehensive sleep tracking reports on par with the best smartwatches</strong></li><li><strong>None of Samsung's holistic features are paywalled, unlike Google and Garmin</strong></li><li><strong>New Heart Health score for monitoring cardiovascular wellness</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4797px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="vHP2ZPZZ4Z6xQ2bKK5vYtZ" name="GalaxyWatchUltra2-06" alt="Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch" src="https://cdn.mos.cms.futurecdn.net/vHP2ZPZZ4Z6xQ2bKK5vYtZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="4797" height="2698" 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>Similar to the new Samsung Galaxy Watch 9, the Galaxy Watch Ultra 2 ships fully-loaded with all sorts of new health and fitness insights. </p><p>These features include a new Vitals dashboard in the Samsung Health app for viewing your most important up-to-the-minute health stats in one place, a new Cardio Load score to track your heart health, and a new Fitness Index score that compares your overall physical health to averages for your age and gender. </p><p>The Vitals tab shows your current heart rate, heart rate variability (HRV), blood oxygen saturation percentage (Sp02), body temperature, and breathing rate. </p><p>The new Heart Health score ranges from one to 100, with the upper end being better. This metric updates dynamically throughout the day, keeping users appraised of how their everyday decisions may be impacting cardiovascular health for better or worse.</p><p>Fitness Index, meanwhile, factors in loads of fitness and wellness metrics to figure out how your overall health compares to your peers in five key categories: strength, cardio, endurance, flexibility, and body composition. You also get a dynamic score from one to 100 (mine is currently 82, or "average"). </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:3515px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="LYfp9ZExt4wz8PuvGiRGJW" name="GalaxyWatchUltra2-03" alt="Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch" src="https://cdn.mos.cms.futurecdn.net/LYfp9ZExt4wz8PuvGiRGJW-1920-80.jpg" mos="" align="middle" fullscreen="" width="3515" height="1977" 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>Samsung's smartwatches deliver some of the most detailed and actionable sleep reports of any smartwatch brand, and even though there aren't any shiny new features, the Galaxy Watch Ultra 2 is a mighty fine sleep tracker. That is, assuming you can get over wearing something so chunky to bed.</p><p>Like its predecessor, the Galaxy Watch Ultra 2 is FDA-cleared for sleep apnea detection, something that can't be said for the newest Google Pixel Watch models. </p><p>Also, unlike some of the competition — cough, cough, Google and Garmin — Samsung doesn't make you pay a monthly or annual subscription to access the full suite of health insights, including AI-powered personalized training and recovery recommendations. </p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-fitness-tracking-3-5"><span>Galaxy Watch Ultra 2 fitness tracking: 3/5</span></h3><ul><li><strong>Reliable heart rate tracking </strong></li><li><strong>Nearly as reliable at logging workouts as the best outdoor adventure watches, with one exception... </strong></li><li><strong>The Ultra 2 tends to overinflate the 'Climb' metric when logging walks, runs, bike rides, and hikes</strong></li><li><strong>Lacks tracking modes for some of the more nuanced yet popular outdoor activities like mountain biking and e-biking</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="z4fwvXKWVZz3GTwNXzQkGV" name="GalaxyUltra2-Instinct3-02" alt="Close-up of the Samsung Galaxy Watch Ultra 2 next to the Garmin Instinct 3 against a bright blue background" src="https://cdn.mos.cms.futurecdn.net/z4fwvXKWVZz3GTwNXzQkGV-1920-80.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>The Galaxy Watch Ultra 2 is rightfully billed as a smartwatch for outdoor enthusiasts and lovers of extreme-style sports. However, I found two shortcomings in my testing.</p><p>First, the Galaxy Watch Ultra 2 sometimes struggles to accurately track elevation gain when logging an outdoor workout, with a tendency to noticeably inflate climb data. I encountered this when testing the <a href="https://www.tomsguide.com/wellness/smartwatches/i-biked-11-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-ultra-2-and-the-winner-is-clear">Galaxy Watch Ultra 2 vs. Garmin Instinct 3</a> while city cycling in hilly Seattle, Washington, and again when I went <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-went-e-mountain-biking-in-cougar-country-with-the-new-samsung-galaxy-watch-ultra-2-vs-garmin-instinct-3-and-the-winner-is-clear">e-mountain biking in Washington State's Cougar Country</a>.</p><p>That said, the Samsung Galaxy Watch Ultra 2 performed extremely well in a head-to-head walk test comparison <a href="https://www.tomsguide.com/wellness/smartwatches/i-manually-counted-4-000-steps-to-test-the-apple-watch-ultra-3-vs-samsung-galaxy-watch-ultra-2-and-samsung-wins-the-accuracy-battle-with-better-elevation-data-too">versus the Apple Watch Ultra 3.</a> However, it once again delivered highly inflated elevation data when I <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-trekked-the-cascade-mountains-with-the-apple-watch-ultra-3-vs-garmin-instinct-3-vs-samsung-galaxy-watch-ultra-2-this-is-the-one-id-take-on-my-next-hike">hiked the Cascade Mountains</a> with the Galaxy Watch Ultra 2 vs. Garmin Instinct 3 vs. Apple Watch Ultra 3.</p><p>Elevation tracking aside, the Samsung Galaxy Watch Ultra 2 largely performs as well as the best smartwatches and fitness trackers when it comes to reliably logging both moving and stationary workouts. Ultimately, as long as you wear the device tight enough, heart rate data should also be highly accurate. </p><p>My other criticism of the Galaxy Watch Ultra 2, which, again, is sold as an outdoor adventure-ready smartwatch, is a lack of tracking modes for popular activities, like mountain biking and e-biking.</p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-ai-features-3-5-5"><span>Galaxy Watch Ultra 2 AI features: 3.5/5</span></h3><ul><li><strong>Google's useful Gemini AI voice assistant is built-in and can be launched via a handy, new 'Raise to talk' gesture control </strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4043px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="epc4o6iQmt6rjHFos7nLnd" name="GalaxyWatchUltra2-Gemini" alt="Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch" src="https://cdn.mos.cms.futurecdn.net/epc4o6iQmt6rjHFos7nLnd-1920-80.jpg" mos="" align="middle" fullscreen="" width="4043" height="2275" 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 AI playing a part in some of Samsung's flagship new health features, the Galaxy Watch Ultra 2 ships with Google's Gemini AI voice assistant built-in. It's the best smartwatch voice assistant I've tested so far, though that may change after I thoroughly test the latest <a href="https://www.tomsguide.com/wellness/smartwatches/how-to-enable-siri-ai-on-your-apple-watch">Siri AI</a> on the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a>.</p><p>With access granted to apps like Gmail and Google Calendar, the Gemini assistant is more than capable of answering super-specific questions like, "When did my sister say her flight is landing next week?" as well as more generic ones like "What's the cheapest, easiest way to soften a stiff T-shirt?"</p><p>Better yet, you can launch the Gemini assistant using the Galaxy Watch Ultra 2 by simply raising your wrist (you will need to first turn it on in the settings menu).  Samsung's "Raise to talk" gesture control is remarkably effective, on par with Google's version for the Pixel Watch 4 and 5. </p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-battery-4-5-5"><span>Galaxy Watch Ultra 2 battery: 4.5/5</span></h3><ul><li><strong>The Galaxy Watch Ultra 2 exceeded its 60-hour-per-charge battery life rating in testing, lasting closer to 72 hours per charge with the always-on display enabled</strong></li><li><strong>This makes it one of the longest-lasting full-featured smartwatches for Android in 2026 and longer-lasting than the latest Apple Watch Ultra 4</strong></li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4187px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bymkGs65ruZkWfvJQAJDCe" name="GalaxyWatchUltra2-02" alt="Close-up look at the Samsung Galaxy Watch Ultra 2 smartwatch" src="https://cdn.mos.cms.futurecdn.net/bymkGs65ruZkWfvJQAJDCe-1920-80.jpg" mos="" align="middle" fullscreen="" width="4187" height="2355" 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>Not only did Samsung equip the Galaxy Watch Ultra 2 with a higher-capacity battery — 590 mAh for the old model vs. 800 mAh for the new one — but the Galaxy Watch Ultra 2 is also more power-efficient than its predecessor, despite a brighter display.</p><p>The original Galaxy Watch Ultra had a battery life rating of 48 hours per charge, a claim we verified in our testing. The new model is rated to last up to 60 hours per charge, but in my testing, it comfortably surpassed that, cruising for closer to 72 hours per charge. </p><p>By comparison, the Samsung <a href="https://www.tomsguide.com/wellness/smartwatches/i-wore-the-samsung-galaxy-watch-9-for-a-month-the-new-health-tools-impress-but-that-doesnt-mean-you-should-upgrade#section-samsung-galaxy-watch-9-battery-life-3-5">Galaxy Watch 9 gets 40 hours</a> per charge at best (44mm). Meanwhile, the latest <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model">Apple Watch Ultra 4</a>, the nearest competitor to the Galaxy Watch Ultra 2, lasts for about 50 hours per charge. </p><h3 class="article-body__section" id="section-galaxy-watch-ultra-2-review-verdict"><span>Galaxy Watch Ultra 2 review: Verdict</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3792px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="AZF7DPLYsQoJ9PLhoqBiNo" name="AWU3-GalaxyU2-Instinct3-03" alt="Close-up of the Samsung Galaxy Watch Ultra 2, Apple Watch Ultra 3 and Garmin Instinct 3 in nature" src="https://cdn.mos.cms.futurecdn.net/AZF7DPLYsQoJ9PLhoqBiNo-1920-80.jpg" mos="" align="middle" fullscreen="" width="3792" height="2134" 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 Samsung Galaxy Watch Ultra 2 is a meaningful update to the original Galaxy Watch Ultra. The newer model is even tougher, with legit scuba-diving-ready specs and features, longer-lasting, with up to three days of battery per charge, and ever-so-slightly more comfortable thanks to a thinner case and a softer, more flexible strap.</p><p>The screen brightness has also been increased, giving the Galaxy Watch Ultra 2 the brightest display in any full-featured smartwatch for Android. Plus, new health and fitness tracking metrics help to bring long-term holistic trends into sharper focus. </p><p>As an outdoor adventure watch, the Galaxy Watch Ultra 2 proved mighty capable, with one exception: faulty elevation data. However, I'm hoping this is just a minor hiccup that will eventually be fixed with future firmware. </p><p>Ultimately, the Galaxy Watch Ultra 2 is a tougher, smarter, longer-lasting take on what was already one of the best Android smartwatches ever made. That, I think, is worth the $50 price increase.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 9 best Garmin smartwatch deals perfect for fall adventures — up to 45% off on Amazon ]]></title>
                                                                                                <dc:content><![CDATA[ <p><a href="https://www.tomsguide.com/sales-events/amazon-october-prime-big-deal-days-2026-best-sales-now">Amazon Prime Big Deal Days</a> was confirmed this week — and although the event doesn't officially start until October 6, that hasn't stopped Amazon from rolling out incredible deals. One of the most impressive sales I've seen so far is courtesy of Garmin.</p><p>The Garmin Fenix 9 was just released, but let's be honest: a $1,099 price tag is pretty steep. The good news? <a href="https://www.amazon.com/stores/page/FF0DE967-3578-4FF5-9BB4-07591E715EEE" target="_blank" rel="nofollow">A bunch of older Garmin models are discounted by up to 45%</a>. They still have all the important features you need and they cost a whole lot less.</p><p>From the budget-friendly <a href="https://www.amazon.com/Garmin-v%C3%ADvoactive-Fitness-Smartwatch-Display/dp/B0CG6NBJ61" target="_blank" rel="nofollow">Garmin Vivoactive 5 on sale for $181</a> to the feature-packed <a href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD321" target="_blank" rel="nofollow">Garmin Fenix 8 for $749</a>, there's something for everybody here. Keep scrolling to see all my favorite Garmin deals. I also recommend checking out our <a href="https://www.tomsguide.com/coupons/amazon.com">Amazon promo codes</a> coverage.</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/FF0DE967-3578-4FF5-9BB4-07591E715EEE" target="_blank" rel="nofollow"><strong>shop all Garmin deals at Amazon</strong></a></li><li><strong>Garmin Vivoactive 5: </strong><a href="https://www.amazon.com/dp/B0CG6NBJ61" target="_blank" rel="nofollow"><strong>was $299 now $181</strong></a></li><li><strong>Garmin Forerunner 165: </strong><a href="https://www.amazon.com/dp/B0CT3SGHXL" target="_blank" rel="nofollow"><strong>was $249 now $199</strong></a></li><li><strong>Garmin Bounce 2: </strong><a href="https://www.amazon.com/Garmin-BounceTM-Smartwatch-Messaging-Location/dp/B0FRG6MXMM" target="_blank" rel="nofollow"><strong>was $299 now $249</strong></a></li><li><strong>Garmin Instinct Crossover Solar: </strong><a href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow"><strong>was $449 now $279</strong></a></li><li><strong>Garmin Venu 3S: </strong><a href="https://www.amazon.com/Garmin-Stainless-1-2-Inch-Touchscreen-Silicone/dp/B0CDC6Y617" target="_blank" rel="nofollow"><strong>was $449 now $288</strong></a></li><li><strong>Garmin Epix Pro: </strong><a href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow"><strong>was $1,099 now $603</strong></a></li><li><strong>Garmin Fenix 8: </strong><a href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R" target="_blank" rel="nofollow"><strong>was $999 now $739</strong></a></li></ul><h3 class="article-body__section" id="section-best-garmin-deals"><span>Best Garmin Deals</span></h3><div class="product"><a data-dimension112="dcde1cbe-b1dd-11f1-9a10-6160d877bed6" data-action="Deal Block" data-label="Vivoactive 5" data-dimension48="Vivoactive 5" data-dimension25="$181" href="https://www.amazon.com/dp/B0CG6NBJ61" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1004px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="VkZemqZBaA53K6cSfpqqgX" name="51zyaVCe-5L._AC_SL1000_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/VkZemqZBaA53K6cSfpqqgX-1920-80.jpg" mos="" align="middle" fullscreen="" width="1004" height="1004" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Garmin Vivoactive 5 is a comprehensive fitness tracker that comes in at an affordable price. In our <a href="https://www.tomsguide.com/reviews/garmin-vivoactive-5-review-is-it-ready-to-take-on-the-apple-watch" data-dimension112="dcde1cbe-b1dd-11f1-9a10-6160d877bed6" data-action="Deal Block" data-label="Vivoactive 5" data-dimension48="Vivoactive 5" data-dimension25="$181">Garmin Vivoactive 5 review</a>, we loved this device's gorgeous AMOLED display, access to multitude of sports apps and its advanced health stats like sleep and stress coaching.<a class="view-deal button" href="https://www.amazon.com/dp/B0CG6NBJ61" target="_blank" rel="nofollow" data-dimension112="dcde1cbe-b1dd-11f1-9a10-6160d877bed6" data-action="Deal Block" data-label="Vivoactive 5" data-dimension48="Vivoactive 5" data-dimension25="$181">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1d18-b1dd-11f1-ad75-e959fd2854bb" data-action="Deal Block" data-label="Forerunner 165" data-dimension48="Forerunner 165" data-dimension25="$199" href="https://www.amazon.com/dp/B0CT3SGHXL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:900px;"><p class="vanilla-image-block" style="padding-top:128.78%;"><img id="5kFqr4NPwzjapMdRURmKzG" name="Forerunner 165" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/5kFqr4NPwzjapMdRURmKzG-1920-80.png" mos="" align="middle" fullscreen="" width="900" height="1159" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Forerunner 165 is the perfect affordable option for runners and considerably cheaper than the newer Garmin Forerunner 170 thanks to this deal, which is on the standard model of the watch. It's a lightweight, attractive watch with an AMOLED display that offers equally accurate GPS and heart rate tracking. It also has support for NFC payments, but keep note that it lacks the music storage available on the <a href="https://www.amazon.com/Garmin-Forerunner%C2%AE-Smartwatch-Advanced-Training/dp/B0H1F79N52" target="_blank" rel="nofollow" data-dimension112="dcde1d18-b1dd-11f1-ad75-e959fd2854bb" data-action="Deal Block" data-label="Forerunner 165" data-dimension48="Forerunner 165" data-dimension25="$199">pricier Forerunner 170 Music ($319)</a>.<a class="view-deal button" href="https://www.amazon.com/dp/B0CT3SGHXL" target="_blank" rel="nofollow" data-dimension112="dcde1d18-b1dd-11f1-ad75-e959fd2854bb" data-action="Deal Block" data-label="Forerunner 165" data-dimension48="Forerunner 165" data-dimension25="$199">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1d7c-b1dd-11f1-9104-99f36a1c09eb" data-action="Deal Block" data-label="Bounce 2" data-dimension48="Bounce 2" data-dimension25="$249" href="https://www.amazon.com/Garmin-BounceTM-Smartwatch-Messaging-Location/dp/B0FRG6MXMM" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1201px;"><p class="vanilla-image-block" style="padding-top:118.65%;"><img id="FrygsjZiMXW4BGEfXuR8eD" name="Bounce 2" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FrygsjZiMXW4BGEfXuR8eD-1920-80.jpg" mos="" align="middle" fullscreen="" width="1201" height="1425" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>If you want your kids to stay connected, but don't want to get them a smartphone — the Garmin Bounce 2 is perfect. It's equipped with LTE support and offers real-time location tracking, two-way calling and voice messages. It'll also keep track of your kids activity, whether they're running, biking or swimming.<a class="view-deal button" href="https://www.amazon.com/Garmin-BounceTM-Smartwatch-Messaging-Location/dp/B0FRG6MXMM" target="_blank" rel="nofollow" data-dimension112="dcde1d7c-b1dd-11f1-9104-99f36a1c09eb" data-action="Deal Block" data-label="Bounce 2" data-dimension48="Bounce 2" data-dimension25="$249">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1dd6-b1dd-11f1-b332-9fe8bc89e534" data-action="Deal Block" data-label="Instinct Crossover Solar" data-dimension48="Instinct Crossover Solar" data-dimension25="$279" href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1226px;"><p class="vanilla-image-block" style="padding-top:122.35%;"><img id="TVqyZieEjXyFkdy9iivkcB" name="Instinct Crossover Solar" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/TVqyZieEjXyFkdy9iivkcB-1920-80.jpg" mos="" align="middle" fullscreen="" width="1226" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow" data-dimension112="dcde1dd6-b1dd-11f1-b332-9fe8bc89e534" data-action="Deal Block" data-label="Instinct Crossover Solar" data-dimension48="Instinct Crossover Solar" data-dimension25="$279">Instinct Crossover Solar: was $449 now $279</a></strong><br>The Garmin Instinct Crossover is a hybrid between a traditional watch and a smartwatch, with mechanical timekeeping and a digital display. You'll get access to smart features like GPS and NFC for payments, as well as incredible 70 day battery life thanks to the solar panel.<a class="view-deal button" href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow" data-dimension112="dcde1dd6-b1dd-11f1-b332-9fe8bc89e534" data-action="Deal Block" data-label="Instinct Crossover Solar" data-dimension48="Instinct Crossover Solar" data-dimension25="$279">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1e30-b1dd-11f1-8c68-97d932b3a65f" data-action="Deal Block" data-label="Venu 3S" data-dimension48="Venu 3S" data-dimension25="$288" href="https://www.amazon.com/Garmin-Stainless-1-2-Inch-Touchscreen-Silicone/dp/B0CDC6Y617" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1080px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Un7k8oR8kzi2SZoU3heUR4" name="Garmin Venu 3S" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Un7k8oR8kzi2SZoU3heUR4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1080" height="1080" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Garmin Venu 3S shares many of our favorite features of the <a href="https://www.tomsguide.com/reviews/garmin-venu-3" data-dimension112="dcde1e30-b1dd-11f1-8c68-97d932b3a65f" data-action="Deal Block" data-label="Venu 3S" data-dimension48="Venu 3S" data-dimension25="$288">Garmin Venu 3</a>, just in a smaller package. It has a 41mm OLED touch display, excellent fitness tracking features and its battery life lasts up to 10 days.<a class="view-deal button" href="https://www.amazon.com/Garmin-Stainless-1-2-Inch-Touchscreen-Silicone/dp/B0CDC6Y617" target="_blank" rel="nofollow" data-dimension112="dcde1e30-b1dd-11f1-8c68-97d932b3a65f" data-action="Deal Block" data-label="Venu 3S" data-dimension48="Venu 3S" data-dimension25="$288">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1e94-b1dd-11f1-bd98-7d844860c9ae" data-action="Deal Block" data-label="Instinct 2X Solar" data-dimension48="Instinct 2X Solar" data-dimension25="$296" href="https://www.amazon.com/Garmin-Smartwatch-Flashlight-Capability-Multi-Band/dp/B0BW34M77J" 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="PKeuvZCtnBFiCExNSfdtt8" name="Garmin Instinct 2X Solar" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PKeuvZCtnBFiCExNSfdtt8-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The rugged Instinct 2X Solar is built for adventure, with features like dual-band GPS tracking and a built-in flashlight helping you enjoy the great outdoors. It also has solar panels on the front to stretch the already impressive battery life even further in sunny conditions, and comes in a range of eye-catching colors. <a class="view-deal button" href="https://www.amazon.com/Garmin-Smartwatch-Flashlight-Capability-Multi-Band/dp/B0BW34M77J" target="_blank" rel="nofollow" data-dimension112="dcde1e94-b1dd-11f1-bd98-7d844860c9ae" data-action="Deal Block" data-label="Instinct 2X Solar" data-dimension48="Instinct 2X Solar" data-dimension25="$296">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1f52-b1dd-11f1-8be2-794e08ad7b90" data-action="Deal Block" data-label="Venu X1" data-dimension48="Venu X1" data-dimension25="$599" href="https://www.amazon.com/Lightweight-Smartwatch-Advanced-Features-ComfortFit/dp/B0FCYHNL3C" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:522px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="2zzw7A2SqZL4Bd6YxTYhgG" name="71xYhGgtVCL._SX522_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/2zzw7A2SqZL4Bd6YxTYhgG-1920-80.jpg" mos="" align="middle" fullscreen="" width="522" height="522" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Looking for something different? The <a href="https://www.tomsguide.com/wellness/smartwatches/my-job-is-testing-garmins-heres-why-the-new-venu-x1-shocked-me" data-dimension112="dcde1f52-b1dd-11f1-8be2-794e08ad7b90" data-action="Deal Block" data-label="Venu X1" data-dimension48="Venu X1" data-dimension25="$599">Garmin Venu X1</a> is a unique smartwatch with a super-large, bright AMOLED display and a super-slim design. It's a great rival to the Apple Watch Ultra for sports fans, with better tracking metrics and navigation tools.<a class="view-deal button" href="https://www.amazon.com/Lightweight-Smartwatch-Advanced-Features-ComfortFit/dp/B0FCYHNL3C" target="_blank" rel="nofollow" data-dimension112="dcde1f52-b1dd-11f1-8be2-794e08ad7b90" data-action="Deal Block" data-label="Venu X1" data-dimension48="Venu X1" data-dimension25="$599">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1ef8-b1dd-11f1-ae6f-b70c452abe77" data-action="Deal Block" data-label="Epix Pro (Gen 2)" data-dimension48="Epix Pro (Gen 2)" data-dimension25="$603" href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1080px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="qR6ajzg9uXied8yzHk82kM" name="Garmin Epix Pro (Gen 2) GPS Smartwatch" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/qR6ajzg9uXied8yzHk82kM-1920-80.jpg" mos="" align="middle" fullscreen="" width="1080" height="1080" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow" data-dimension112="dcde1ef8-b1dd-11f1-ae6f-b70c452abe77" data-action="Deal Block" data-label="Epix Pro (Gen 2)" data-dimension48="Epix Pro (Gen 2)" data-dimension25="$603">Epix Pro (Gen 2): was $1099 now $603</a></strong><br>This deal is on the 51mm Garmin Epix Pro Gen 2, the largest model in the Epix lineup. It also has the longest battery life. It's considerably cheaper than the newer Fenix 8, and having tested both, our Fitness Editor says the Epix Pro has all the same key sports tracking and training analysis features you really need, so this deal is worth considering.<a class="view-deal button" href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow" data-dimension112="dcde1ef8-b1dd-11f1-ae6f-b70c452abe77" data-action="Deal Block" data-label="Epix Pro (Gen 2)" data-dimension48="Epix Pro (Gen 2)" data-dimension25="$603">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1fac-b1dd-11f1-8050-4f66924bd5c3" data-action="Deal Block" data-label="Fenix 8" data-dimension48="Fenix 8" data-dimension25="$739" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:694px;"><p class="vanilla-image-block" style="padding-top:116.86%;"><img id="DUPZqNYp7WjoWX5YqacXLE" name="Garmin Fenix 8" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DUPZqNYp7WjoWX5YqacXLE-1920-80.png" mos="" align="middle" fullscreen="" width="694" height="811" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>All three sizes of the Garmin Fenix 8 are on sale at Amazon right now, and you can get them with either steel or titanium cases. The lowest price available is on the steel 43mm or 47mm watches, while titanium models cost $100 more.<a class="view-deal button" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R" target="_blank" rel="nofollow" data-dimension112="dcde1fac-b1dd-11f1-8050-4f66924bd5c3" data-action="Deal Block" data-label="Fenix 8" data-dimension48="Fenix 8" data-dimension25="$739">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&rows=6&view_mode=savings_squad&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/9-best-garmin-smartwatch-deals-perfect-for-fall-adventures-up-to-45-percent-off-on-amazon</link>
                                                                            <description>
                            <![CDATA[ I found a bunch of affordable Garmin deals to upgrade your fitness tracking and boost your game this fall. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">9iu6ynWZnFwwocrQuaQ5Kh</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/CK5fCDff6dkdb2zVQBQAbA-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 16 Sep 2026 15:15:41 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></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/CK5fCDff6dkdb2zVQBQAbA-1920-80.jpg">
                                                            <media:credit><![CDATA[Amazon]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Garmin Deals]]></media:description>                                                            <media:text><![CDATA[Garmin Deals]]></media:text>
                                <media:title type="plain"><![CDATA[Garmin Deals]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/CK5fCDff6dkdb2zVQBQAbA-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p><a href="https://www.tomsguide.com/sales-events/amazon-october-prime-big-deal-days-2026-best-sales-now">Amazon Prime Big Deal Days</a> was confirmed this week — and although the event doesn't officially start until October 6, that hasn't stopped Amazon from rolling out incredible deals. One of the most impressive sales I've seen so far is courtesy of Garmin.</p><p>The Garmin Fenix 9 was just released, but let's be honest: a $1,099 price tag is pretty steep. The good news? <a href="https://www.amazon.com/stores/page/FF0DE967-3578-4FF5-9BB4-07591E715EEE" target="_blank" rel="nofollow">A bunch of older Garmin models are discounted by up to 45%</a>. They still have all the important features you need and they cost a whole lot less.</p><p>From the budget-friendly <a href="https://www.amazon.com/Garmin-v%C3%ADvoactive-Fitness-Smartwatch-Display/dp/B0CG6NBJ61" target="_blank" rel="nofollow">Garmin Vivoactive 5 on sale for $181</a> to the feature-packed <a href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD321" target="_blank" rel="nofollow">Garmin Fenix 8 for $749</a>, there's something for everybody here. Keep scrolling to see all my favorite Garmin deals. I also recommend checking out our <a href="https://www.tomsguide.com/coupons/amazon.com">Amazon promo codes</a> coverage.</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/FF0DE967-3578-4FF5-9BB4-07591E715EEE" target="_blank" rel="nofollow"><strong>shop all Garmin deals at Amazon</strong></a></li><li><strong>Garmin Vivoactive 5: </strong><a href="https://www.amazon.com/dp/B0CG6NBJ61" target="_blank" rel="nofollow"><strong>was $299 now $181</strong></a></li><li><strong>Garmin Forerunner 165: </strong><a href="https://www.amazon.com/dp/B0CT3SGHXL" target="_blank" rel="nofollow"><strong>was $249 now $199</strong></a></li><li><strong>Garmin Bounce 2: </strong><a href="https://www.amazon.com/Garmin-BounceTM-Smartwatch-Messaging-Location/dp/B0FRG6MXMM" target="_blank" rel="nofollow"><strong>was $299 now $249</strong></a></li><li><strong>Garmin Instinct Crossover Solar: </strong><a href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow"><strong>was $449 now $279</strong></a></li><li><strong>Garmin Venu 3S: </strong><a href="https://www.amazon.com/Garmin-Stainless-1-2-Inch-Touchscreen-Silicone/dp/B0CDC6Y617" target="_blank" rel="nofollow"><strong>was $449 now $288</strong></a></li><li><strong>Garmin Epix Pro: </strong><a href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow"><strong>was $1,099 now $603</strong></a></li><li><strong>Garmin Fenix 8: </strong><a href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R" target="_blank" rel="nofollow"><strong>was $999 now $739</strong></a></li></ul><h3 class="article-body__section" id="section-best-garmin-deals"><span>Best Garmin Deals</span></h3><div class="product"><a data-dimension112="dcde1cbe-b1dd-11f1-9a10-6160d877bed6" data-action="Deal Block" data-label="Vivoactive 5" data-dimension48="Vivoactive 5" data-dimension25="$181" href="https://www.amazon.com/dp/B0CG6NBJ61" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1004px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="VkZemqZBaA53K6cSfpqqgX" name="51zyaVCe-5L._AC_SL1000_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/VkZemqZBaA53K6cSfpqqgX-1920-80.jpg" mos="" align="middle" fullscreen="" width="1004" height="1004" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Garmin Vivoactive 5 is a comprehensive fitness tracker that comes in at an affordable price. In our <a href="https://www.tomsguide.com/reviews/garmin-vivoactive-5-review-is-it-ready-to-take-on-the-apple-watch" data-dimension112="dcde1cbe-b1dd-11f1-9a10-6160d877bed6" data-action="Deal Block" data-label="Vivoactive 5" data-dimension48="Vivoactive 5" data-dimension25="$181">Garmin Vivoactive 5 review</a>, we loved this device's gorgeous AMOLED display, access to multitude of sports apps and its advanced health stats like sleep and stress coaching.<a class="view-deal button" href="https://www.amazon.com/dp/B0CG6NBJ61" target="_blank" rel="nofollow" data-dimension112="dcde1cbe-b1dd-11f1-9a10-6160d877bed6" data-action="Deal Block" data-label="Vivoactive 5" data-dimension48="Vivoactive 5" data-dimension25="$181">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1d18-b1dd-11f1-ad75-e959fd2854bb" data-action="Deal Block" data-label="Forerunner 165" data-dimension48="Forerunner 165" data-dimension25="$199" href="https://www.amazon.com/dp/B0CT3SGHXL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:900px;"><p class="vanilla-image-block" style="padding-top:128.78%;"><img id="5kFqr4NPwzjapMdRURmKzG" name="Forerunner 165" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/5kFqr4NPwzjapMdRURmKzG-1920-80.png" mos="" align="middle" fullscreen="" width="900" height="1159" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Forerunner 165 is the perfect affordable option for runners and considerably cheaper than the newer Garmin Forerunner 170 thanks to this deal, which is on the standard model of the watch. It's a lightweight, attractive watch with an AMOLED display that offers equally accurate GPS and heart rate tracking. It also has support for NFC payments, but keep note that it lacks the music storage available on the <a href="https://www.amazon.com/Garmin-Forerunner%C2%AE-Smartwatch-Advanced-Training/dp/B0H1F79N52" target="_blank" rel="nofollow" data-dimension112="dcde1d18-b1dd-11f1-ad75-e959fd2854bb" data-action="Deal Block" data-label="Forerunner 165" data-dimension48="Forerunner 165" data-dimension25="$199">pricier Forerunner 170 Music ($319)</a>.<a class="view-deal button" href="https://www.amazon.com/dp/B0CT3SGHXL" target="_blank" rel="nofollow" data-dimension112="dcde1d18-b1dd-11f1-ad75-e959fd2854bb" data-action="Deal Block" data-label="Forerunner 165" data-dimension48="Forerunner 165" data-dimension25="$199">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1d7c-b1dd-11f1-9104-99f36a1c09eb" data-action="Deal Block" data-label="Bounce 2" data-dimension48="Bounce 2" data-dimension25="$249" href="https://www.amazon.com/Garmin-BounceTM-Smartwatch-Messaging-Location/dp/B0FRG6MXMM" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1201px;"><p class="vanilla-image-block" style="padding-top:118.65%;"><img id="FrygsjZiMXW4BGEfXuR8eD" name="Bounce 2" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FrygsjZiMXW4BGEfXuR8eD-1920-80.jpg" mos="" align="middle" fullscreen="" width="1201" height="1425" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>If you want your kids to stay connected, but don't want to get them a smartphone — the Garmin Bounce 2 is perfect. It's equipped with LTE support and offers real-time location tracking, two-way calling and voice messages. It'll also keep track of your kids activity, whether they're running, biking or swimming.<a class="view-deal button" href="https://www.amazon.com/Garmin-BounceTM-Smartwatch-Messaging-Location/dp/B0FRG6MXMM" target="_blank" rel="nofollow" data-dimension112="dcde1d7c-b1dd-11f1-9104-99f36a1c09eb" data-action="Deal Block" data-label="Bounce 2" data-dimension48="Bounce 2" data-dimension25="$249">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1dd6-b1dd-11f1-b332-9fe8bc89e534" data-action="Deal Block" data-label="Instinct Crossover Solar" data-dimension48="Instinct Crossover Solar" data-dimension25="$279" href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1226px;"><p class="vanilla-image-block" style="padding-top:122.35%;"><img id="TVqyZieEjXyFkdy9iivkcB" name="Instinct Crossover Solar" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/TVqyZieEjXyFkdy9iivkcB-1920-80.jpg" mos="" align="middle" fullscreen="" width="1226" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow" data-dimension112="dcde1dd6-b1dd-11f1-b332-9fe8bc89e534" data-action="Deal Block" data-label="Instinct Crossover Solar" data-dimension48="Instinct Crossover Solar" data-dimension25="$279">Instinct Crossover Solar: was $449 now $279</a></strong><br>The Garmin Instinct Crossover is a hybrid between a traditional watch and a smartwatch, with mechanical timekeeping and a digital display. You'll get access to smart features like GPS and NFC for payments, as well as incredible 70 day battery life thanks to the solar panel.<a class="view-deal button" href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow" data-dimension112="dcde1dd6-b1dd-11f1-b332-9fe8bc89e534" data-action="Deal Block" data-label="Instinct Crossover Solar" data-dimension48="Instinct Crossover Solar" data-dimension25="$279">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1e30-b1dd-11f1-8c68-97d932b3a65f" data-action="Deal Block" data-label="Venu 3S" data-dimension48="Venu 3S" data-dimension25="$288" href="https://www.amazon.com/Garmin-Stainless-1-2-Inch-Touchscreen-Silicone/dp/B0CDC6Y617" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1080px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Un7k8oR8kzi2SZoU3heUR4" name="Garmin Venu 3S" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Un7k8oR8kzi2SZoU3heUR4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1080" height="1080" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Garmin Venu 3S shares many of our favorite features of the <a href="https://www.tomsguide.com/reviews/garmin-venu-3" data-dimension112="dcde1e30-b1dd-11f1-8c68-97d932b3a65f" data-action="Deal Block" data-label="Venu 3S" data-dimension48="Venu 3S" data-dimension25="$288">Garmin Venu 3</a>, just in a smaller package. It has a 41mm OLED touch display, excellent fitness tracking features and its battery life lasts up to 10 days.<a class="view-deal button" href="https://www.amazon.com/Garmin-Stainless-1-2-Inch-Touchscreen-Silicone/dp/B0CDC6Y617" target="_blank" rel="nofollow" data-dimension112="dcde1e30-b1dd-11f1-8c68-97d932b3a65f" data-action="Deal Block" data-label="Venu 3S" data-dimension48="Venu 3S" data-dimension25="$288">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1e94-b1dd-11f1-bd98-7d844860c9ae" data-action="Deal Block" data-label="Instinct 2X Solar" data-dimension48="Instinct 2X Solar" data-dimension25="$296" href="https://www.amazon.com/Garmin-Smartwatch-Flashlight-Capability-Multi-Band/dp/B0BW34M77J" 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="PKeuvZCtnBFiCExNSfdtt8" name="Garmin Instinct 2X Solar" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PKeuvZCtnBFiCExNSfdtt8-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The rugged Instinct 2X Solar is built for adventure, with features like dual-band GPS tracking and a built-in flashlight helping you enjoy the great outdoors. It also has solar panels on the front to stretch the already impressive battery life even further in sunny conditions, and comes in a range of eye-catching colors. <a class="view-deal button" href="https://www.amazon.com/Garmin-Smartwatch-Flashlight-Capability-Multi-Band/dp/B0BW34M77J" target="_blank" rel="nofollow" data-dimension112="dcde1e94-b1dd-11f1-bd98-7d844860c9ae" data-action="Deal Block" data-label="Instinct 2X Solar" data-dimension48="Instinct 2X Solar" data-dimension25="$296">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1f52-b1dd-11f1-8be2-794e08ad7b90" data-action="Deal Block" data-label="Venu X1" data-dimension48="Venu X1" data-dimension25="$599" href="https://www.amazon.com/Lightweight-Smartwatch-Advanced-Features-ComfortFit/dp/B0FCYHNL3C" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:522px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="2zzw7A2SqZL4Bd6YxTYhgG" name="71xYhGgtVCL._SX522_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/2zzw7A2SqZL4Bd6YxTYhgG-1920-80.jpg" mos="" align="middle" fullscreen="" width="522" height="522" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Looking for something different? The <a href="https://www.tomsguide.com/wellness/smartwatches/my-job-is-testing-garmins-heres-why-the-new-venu-x1-shocked-me" data-dimension112="dcde1f52-b1dd-11f1-8be2-794e08ad7b90" data-action="Deal Block" data-label="Venu X1" data-dimension48="Venu X1" data-dimension25="$599">Garmin Venu X1</a> is a unique smartwatch with a super-large, bright AMOLED display and a super-slim design. It's a great rival to the Apple Watch Ultra for sports fans, with better tracking metrics and navigation tools.<a class="view-deal button" href="https://www.amazon.com/Lightweight-Smartwatch-Advanced-Features-ComfortFit/dp/B0FCYHNL3C" target="_blank" rel="nofollow" data-dimension112="dcde1f52-b1dd-11f1-8be2-794e08ad7b90" data-action="Deal Block" data-label="Venu X1" data-dimension48="Venu X1" data-dimension25="$599">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1ef8-b1dd-11f1-ae6f-b70c452abe77" data-action="Deal Block" data-label="Epix Pro (Gen 2)" data-dimension48="Epix Pro (Gen 2)" data-dimension25="$603" href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1080px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="qR6ajzg9uXied8yzHk82kM" name="Garmin Epix Pro (Gen 2) GPS Smartwatch" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/qR6ajzg9uXied8yzHk82kM-1920-80.jpg" mos="" align="middle" fullscreen="" width="1080" height="1080" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow" data-dimension112="dcde1ef8-b1dd-11f1-ae6f-b70c452abe77" data-action="Deal Block" data-label="Epix Pro (Gen 2)" data-dimension48="Epix Pro (Gen 2)" data-dimension25="$603">Epix Pro (Gen 2): was $1099 now $603</a></strong><br>This deal is on the 51mm Garmin Epix Pro Gen 2, the largest model in the Epix lineup. It also has the longest battery life. It's considerably cheaper than the newer Fenix 8, and having tested both, our Fitness Editor says the Epix Pro has all the same key sports tracking and training analysis features you really need, so this deal is worth considering.<a class="view-deal button" href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow" data-dimension112="dcde1ef8-b1dd-11f1-ae6f-b70c452abe77" data-action="Deal Block" data-label="Epix Pro (Gen 2)" data-dimension48="Epix Pro (Gen 2)" data-dimension25="$603">View Deal</a></p></div><div class="product"><a data-dimension112="dcde1fac-b1dd-11f1-8050-4f66924bd5c3" data-action="Deal Block" data-label="Fenix 8" data-dimension48="Fenix 8" data-dimension25="$739" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:694px;"><p class="vanilla-image-block" style="padding-top:116.86%;"><img id="DUPZqNYp7WjoWX5YqacXLE" name="Garmin Fenix 8" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DUPZqNYp7WjoWX5YqacXLE-1920-80.png" mos="" align="middle" fullscreen="" width="694" height="811" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>All three sizes of the Garmin Fenix 8 are on sale at Amazon right now, and you can get them with either steel or titanium cases. The lowest price available is on the steel 43mm or 47mm watches, while titanium models cost $100 more.<a class="view-deal button" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R" target="_blank" rel="nofollow" data-dimension112="dcde1fac-b1dd-11f1-8050-4f66924bd5c3" data-action="Deal Block" data-label="Fenix 8" data-dimension48="Fenix 8" data-dimension25="$739">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&rows=6&view_mode=savings_squad&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Here's how to enable the new Siri AI on your Apple Watch ]]></title>
                                                                                                <dc:content><![CDATA[ <p>At last, an AI-powered version of Apple's Siri voice assistant is available for the Apple Watch thanks to the public release of <a href="https://www.tomsguide.com/wellness/smartwatches/watchos-27-is-live-7-new-features-to-try-first-on-your-apple-watch">watchOS 27</a>, the newest Apple Watch software. </p><p>In my experience so far, Siri AI is more natural in its tone, making conversing less awkward. More importantly, the feature is much better at answering complex, context-based questions with a reasonable degree of reliability. </p><p>Here's how to load Siri AI on your Apple Watch and add a dedicated Siri AI widget to your watch face in seven easy steps. Plus, a list of eligible models. </p><h2 id="how-to-enable-siri-ai-on-your-apple-watch">How to enable Siri AI on your Apple Watch </h2><ol start="1"><li><strong>Make sure your Apple Watch and iPhone are compatible with Siri AI</strong></li><li><strong>Update your phone to iOS 27; update your Apple Watch to watchOS 27</strong></li><li><strong>Turn on Siri in your phone’s settings and join the Siri beta waitlist </strong></li><li><strong>Turn on Siri in your Apple Watch’s settings </strong></li><li><strong>Open the Watch app on your iPhone, tap Display and Brightness > Face Gallery</strong></li><li><strong>Tap “New Watch Faces” and/or search for the “Siri Modular” face</strong></li><li><strong>Customize the Siri Modular face to your liking and tap “Add to Watch” when finished</strong></li></ol><p><em>Read on to see full illustrated instructions for each step.   </em></p><section class="howto-block">                    <h3>1. Make sure your Apple Watch and iPhone are compatible with Siri AI</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/ELbKVrkjoMo7GVVCaRVdgk.jpg"                                        alt="Apple Watch Series 9 on wrist "                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/ELbKVrkjoMo7GVVCaRVdgk.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>Before starting, first <strong>make sure both your Apple Watch and iPhone are compatible with Siri AI.</strong> For iPhones, the following models support Apple Intelligence tools: iPhone 15 Pro, iPhone 15 Pro Max, iPhone 16 series, iPhone 17 series, and iPhone 18 series.</p><p>Meanwhile, the following Apple Watch models are watchOS 27-eligible with support for Siri AI: <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-se-3-review">Apple Watch SE 3</a>, <a href="https://www.tomsguide.com/reviews/apple-watch-series-9">Apple Watch Series 9</a>, <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-10-review">Apple Watch Series 10</a>, <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch Series 11</a>, <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a>, <a href="https://www.tomsguide.com/reviews/apple-watch-ultra-2">Apple Watch Ultra 2</a>, A<a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">pple Watch Ultra 3</a>, and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model">Apple Watch Ultra 4</a>.</p></p>                </section><section class="howto-block">                    <h3>2. Update your phone to iOS 27; update your Appple Watch to watchOS 27</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/7aZCsBK5W8Hg6taWUZjYnN.jpg"                                        alt="Close-up of the Apple Watch Series 11 showing the latest watchOS 27 software"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/7aZCsBK5W8Hg6taWUZjYnN.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Dan Bracaglia/Tom's Guide)</div></figure>                    <p><p>Once you've confirmed Siri AI support for your Apple Watch and iPhone, it's time to <strong>update your iPhone to the latest iOS 27 software and then your Apple Watch to the newest watchOS 27 platform</strong>. </p><p>Need some help? Here's a detailed explainer on <a href="https://www.tomsguide.com/phones/iphones/ios-27-is-live-heres-how-to-download-and-install-it-now">how to upgrade to iOS 27</a>. Plus, here's <a href="https://www.tomsguide.com/wellness/smartwatches/watchos-27-is-live-7-new-features-to-try-first-on-your-apple-watch">how to upgrade to watchOS 27</a> in a couple of easy steps (scroll down a bit). Note: The software update process for each can take up to a few hours, so plan accordingly. </p></p>                </section><section class="howto-block">                    <h3>3. Turn on Siri in your phone’s settings and join the Siri beta waitlist </h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/dPneRHcue2Bezr8cgzVb4m.jpg"                                        alt="Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/dPneRHcue2Bezr8cgzVb4m.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Dan Bracaglia/Tom's Guide)</div></figure>                    <p><p>Once both your Apple Watch and iPhone are running the latest software, <strong>head to your phone's Settings Menu, scroll down, and tap on "Siri." </strong>Next, <strong>turn on Siri if it's off, then tap on "Siri AI (Beta)," and tap "Join Waitlist."</strong></p></p>                </section><section class="howto-block">                    <h3>4. Turn on Siri in your Apple Watch’s settings </h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/KsPrQsSEZEjygwK3rq8Pxk.jpg"                                        alt="Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/KsPrQsSEZEjygwK3rq8Pxk.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Dan Bracaglia/Tom's Guide)</div></figure>                    <p><p>Next, <strong>head to your Apple Watch's setting menu and open the Siri tab </strong>and ensure that Siri is turned on. If it's not, <strong>turn Siri on</strong>.</p></p>                </section><section class="howto-block">                    <h3>5. Open the Watch app on your iPhone, tap Display and Brightness > Face Gallery</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/XqfuD6HV4VnggQNDFTA4Gm.jpg"                                        alt="Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/XqfuD6HV4VnggQNDFTA4Gm.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Dan Bracaglia/Tom's Guide)</div></figure>                    <p><p>Now it's time to install Apple's new Siri Modular watch face on your Apple Watch, which adds a dedicated shortcut to the Siri AI voice assistant for easy access. </p><p>First, <strong>open the Watch app on your iPhone, scroll down, and click "Display and Brightness" followed by "Face Gallery."</strong></p></p>                </section><section class="howto-block">                    <h3>6. Tap 'New Watch Faces' and/or search for the 'Siri Modular' face</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/4ueK5kkJKC7NEcbNnbfDCm.jpg"                                        alt="Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/4ueK5kkJKC7NEcbNnbfDCm.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Dan Bracaglia/Tom's Guide)</div></figure>                    <p><p>To find the new Siri Modular watch face you can <strong>either tap on "new Watch Faces" category (Siri Modular should be one of the top options), or search for "Siri Modular" in the search field.</strong></p></p>                </section><section class="howto-block">                    <h3>7. Customize the Siri Modular face to your liking and tap 'Add to Watch' when finished</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/Ec3PktUzDPYLD2ZtovbTnk.jpg"                                        alt="Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/Ec3PktUzDPYLD2ZtovbTnk.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Dan Bracaglia/Tom's Guide)</div></figure>                    <p><p>Apple offers a lot of customization options for the Siri Modular face, including your choice of colors, the number of widgets, the style of the date/time, and more. Go ahead and <strong>fine-tune the Siri Modular watch face to your liking, and once you're done, tap "Add to Watch."</strong> In a matter of seconds, the new face should load. </p></p>                </section><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="MdEHPFrhrHA845ifCYXsYk" name="AW-SiriAI-07" alt="Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus" src="https://cdn.mos.cms.futurecdn.net/MdEHPFrhrHA845ifCYXsYk-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class=""></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>And there you have it. Siri AI is now enabled on your Apple Watch, and the Siri AI assistant app is now fixed on your watch face for easy access. Of course, you can also open Siri by double-tapping the Digital Crown or using a gesture control like wrist raise. </p><p>Siri AI is still in beta, so your experience with the AI assistant might not be as smooth as the final product. Moreover, getting off the Siri AI beta waitlist can take anywhere from a few minutes or hours to several days. So, be patient. </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/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model"><strong>Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4"><strong>I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/how-to-enable-siri-ai-on-your-apple-watch</link>
                                                                            <description>
                            <![CDATA[ With watchOS 27, Siri AI is finally wrist-ready. Here's everything you need to know about which Apple Watch models support Siri AI and how to unlock the feature in seven easy steps. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">epeRJtvHvbEqUy6QrB7AKS</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/jMVPmjsyJhiAYsSKDJzbwk-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 16 Sep 2026 11:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/jMVPmjsyJhiAYsSKDJzbwk-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus]]></media:description>                                                            <media:text><![CDATA[Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/jMVPmjsyJhiAYsSKDJzbwk-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>At last, an AI-powered version of Apple's Siri voice assistant is available for the Apple Watch thanks to the public release of <a href="https://www.tomsguide.com/wellness/smartwatches/watchos-27-is-live-7-new-features-to-try-first-on-your-apple-watch">watchOS 27</a>, the newest Apple Watch software. </p><p>In my experience so far, Siri AI is more natural in its tone, making conversing less awkward. More importantly, the feature is much better at answering complex, context-based questions with a reasonable degree of reliability. </p><p>Here's how to load Siri AI on your Apple Watch and add a dedicated Siri AI widget to your watch face in seven easy steps. Plus, a list of eligible models. </p><h2 id="how-to-enable-siri-ai-on-your-apple-watch">How to enable Siri AI on your Apple Watch </h2><ol start="1"><li><strong>Make sure your Apple Watch and iPhone are compatible with Siri AI</strong></li><li><strong>Update your phone to iOS 27; update your Apple Watch to watchOS 27</strong></li><li><strong>Turn on Siri in your phone’s settings and join the Siri beta waitlist </strong></li><li><strong>Turn on Siri in your Apple Watch’s settings </strong></li><li><strong>Open the Watch app on your iPhone, tap Display and Brightness > Face Gallery</strong></li><li><strong>Tap “New Watch Faces” and/or search for the “Siri Modular” face</strong></li><li><strong>Customize the Siri Modular face to your liking and tap “Add to Watch” when finished</strong></li></ol><p><em>Read on to see full illustrated instructions for each step.   </em></p><section class="howto-block">                    <h3>1. Make sure your Apple Watch and iPhone are compatible with Siri AI</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/ELbKVrkjoMo7GVVCaRVdgk.jpg"                                        alt="Apple Watch Series 9 on wrist "                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/ELbKVrkjoMo7GVVCaRVdgk.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>Before starting, first <strong>make sure both your Apple Watch and iPhone are compatible with Siri AI.</strong> For iPhones, the following models support Apple Intelligence tools: iPhone 15 Pro, iPhone 15 Pro Max, iPhone 16 series, iPhone 17 series, and iPhone 18 series.</p><p>Meanwhile, the following Apple Watch models are watchOS 27-eligible with support for Siri AI: <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-se-3-review">Apple Watch SE 3</a>, <a href="https://www.tomsguide.com/reviews/apple-watch-series-9">Apple Watch Series 9</a>, <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-10-review">Apple Watch Series 10</a>, <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch Series 11</a>, <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a>, <a href="https://www.tomsguide.com/reviews/apple-watch-ultra-2">Apple Watch Ultra 2</a>, A<a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">pple Watch Ultra 3</a>, and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model">Apple Watch Ultra 4</a>.</p></p>                </section><section class="howto-block">                    <h3>2. Update your phone to iOS 27; update your Appple Watch to watchOS 27</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/7aZCsBK5W8Hg6taWUZjYnN.jpg"                                        alt="Close-up of the Apple Watch Series 11 showing the latest watchOS 27 software"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/7aZCsBK5W8Hg6taWUZjYnN.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Dan Bracaglia/Tom's Guide)</div></figure>                    <p><p>Once you've confirmed Siri AI support for your Apple Watch and iPhone, it's time to <strong>update your iPhone to the latest iOS 27 software and then your Apple Watch to the newest watchOS 27 platform</strong>. </p><p>Need some help? Here's a detailed explainer on <a href="https://www.tomsguide.com/phones/iphones/ios-27-is-live-heres-how-to-download-and-install-it-now">how to upgrade to iOS 27</a>. Plus, here's <a href="https://www.tomsguide.com/wellness/smartwatches/watchos-27-is-live-7-new-features-to-try-first-on-your-apple-watch">how to upgrade to watchOS 27</a> in a couple of easy steps (scroll down a bit). Note: The software update process for each can take up to a few hours, so plan accordingly. </p></p>                </section><section class="howto-block">                    <h3>3. Turn on Siri in your phone’s settings and join the Siri beta waitlist </h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/dPneRHcue2Bezr8cgzVb4m.jpg"                                        alt="Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/dPneRHcue2Bezr8cgzVb4m.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Dan Bracaglia/Tom's Guide)</div></figure>                    <p><p>Once both your Apple Watch and iPhone are running the latest software, <strong>head to your phone's Settings Menu, scroll down, and tap on "Siri." </strong>Next, <strong>turn on Siri if it's off, then tap on "Siri AI (Beta)," and tap "Join Waitlist."</strong></p></p>                </section><section class="howto-block">                    <h3>4. Turn on Siri in your Apple Watch’s settings </h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/KsPrQsSEZEjygwK3rq8Pxk.jpg"                                        alt="Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/KsPrQsSEZEjygwK3rq8Pxk.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Dan Bracaglia/Tom's Guide)</div></figure>                    <p><p>Next, <strong>head to your Apple Watch's setting menu and open the Siri tab </strong>and ensure that Siri is turned on. If it's not, <strong>turn Siri on</strong>.</p></p>                </section><section class="howto-block">                    <h3>5. Open the Watch app on your iPhone, tap Display and Brightness > Face Gallery</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/XqfuD6HV4VnggQNDFTA4Gm.jpg"                                        alt="Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/XqfuD6HV4VnggQNDFTA4Gm.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Dan Bracaglia/Tom's Guide)</div></figure>                    <p><p>Now it's time to install Apple's new Siri Modular watch face on your Apple Watch, which adds a dedicated shortcut to the Siri AI voice assistant for easy access. </p><p>First, <strong>open the Watch app on your iPhone, scroll down, and click "Display and Brightness" followed by "Face Gallery."</strong></p></p>                </section><section class="howto-block">                    <h3>6. Tap 'New Watch Faces' and/or search for the 'Siri Modular' face</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/4ueK5kkJKC7NEcbNnbfDCm.jpg"                                        alt="Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/4ueK5kkJKC7NEcbNnbfDCm.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Dan Bracaglia/Tom's Guide)</div></figure>                    <p><p>To find the new Siri Modular watch face you can <strong>either tap on "new Watch Faces" category (Siri Modular should be one of the top options), or search for "Siri Modular" in the search field.</strong></p></p>                </section><section class="howto-block">                    <h3>7. Customize the Siri Modular face to your liking and tap 'Add to Watch' when finished</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/Ec3PktUzDPYLD2ZtovbTnk.jpg"                                        alt="Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/Ec3PktUzDPYLD2ZtovbTnk.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Dan Bracaglia/Tom's Guide)</div></figure>                    <p><p>Apple offers a lot of customization options for the Siri Modular face, including your choice of colors, the number of widgets, the style of the date/time, and more. Go ahead and <strong>fine-tune the Siri Modular watch face to your liking, and once you're done, tap "Add to Watch."</strong> In a matter of seconds, the new face should load. </p></p>                </section><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="MdEHPFrhrHA845ifCYXsYk" name="AW-SiriAI-07" alt="Close-up of the Siri AI setup process using an Apple Watch 11 and iPhone 16 Plus" src="https://cdn.mos.cms.futurecdn.net/MdEHPFrhrHA845ifCYXsYk-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class=""></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>And there you have it. Siri AI is now enabled on your Apple Watch, and the Siri AI assistant app is now fixed on your watch face for easy access. Of course, you can also open Siri by double-tapping the Digital Crown or using a gesture control like wrist raise. </p><p>Siri AI is still in beta, so your experience with the AI assistant might not be as smooth as the final product. Moreover, getting off the Siri AI beta waitlist can take anywhere from a few minutes or hours to several days. So, be patient. </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/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model"><strong>Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4"><strong>I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I raced a half marathon with the Garmin Fenix 9 Pro vs Garmin Forerunner 970 — here’s which one I’d buy ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor">Garmin Fenix 9 Pro</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-garmin-forerunner-970-for-six-months-here-are-my-long-term-pros-and-cons">Garmin Forerunner 970 </a>sit at the top of their respective trees within the Garmin line-up, and both are among the <a href="https://www.tomsguide.com/us/best-gps-watches,review-2638.html">best sports watches </a>available.</p><p>They’re pitched at slightly different athletes, with the Forerunner 970 being a lightweight, slim watch built for the keenest runners and triathletes, while the all-metal Fenix 9 Pro is aimed at adventurers, offering epic battery life, LTE and satellite connectivity.</p><p>However, they do share a lot of features, even including some of the new ones introduced with the Fenix 9 Pro that will roll back to the Forerunner 970, and many people will be picking between the two when buying one of the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches</a>.</p><p>I’ve worn the Garmin Forerunner 970 for over a year myself and have had the Fenix 9 Pro strapped on for a few weeks since its launch, and I tested the two head-to-head at a half marathon.</p><p>Here’s my full Garmin Fenix 9 Pro vs Garmin Forerunner 970 comparison, looking at price, accuracy, design, battery life and other key differences between the pair.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-price"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Price</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:2161px;"><p class="vanilla-image-block" style="padding-top:56.22%;"><img id="NmEaDfEmcWjvSpjY2JqRsj" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:98,l:225,cw:2161,ch:1215,q:80/NmEaDfEmcWjvSpjY2JqRsj.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 Garmin Forerunner 970 has been out for over a year, which means you can often find it for less than its full price of $749. It comes in one size and three colors, keeping things nice and simple compared with the sprawling Fenix 9 line-up.</p><div class="product"><a data-dimension112="c3821d50-b03f-11f1-9ca5-0749730caa84" data-action="Deal Block" data-label="Forerunner 970" data-dimension48="Forerunner 970" data-dimension25="$749" href="https://www.amazon.com/Forerunner%C2%AE-Smartwatch-Flashlight-Translucent-Whitestone/dp/B0F8QWPVNK?th=1" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1268px;"><p class="vanilla-image-block" style="padding-top:94.95%;"><img id="3GKnEu7CdhtxPMfnPCMCiA" name="Garmin Forerunner 970" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA-1920-80.png" mos="" align="middle" fullscreen="" width="1268" height="1204" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Garmin Forerunner 970 is the best running watch available, in my opinion, with a lightweight, attractive design and all the features you could ever need. In sales, it can drop as low as $649, but it's still cheaper than the Garmin Fenix 9 Pro at a full price of $749.<a class="view-deal button" href="https://www.amazon.com/Forerunner%C2%AE-Smartwatch-Flashlight-Translucent-Whitestone/dp/B0F8QWPVNK?th=1" target="_blank" rel="nofollow" data-dimension112="c3821d50-b03f-11f1-9ca5-0749730caa84" data-action="Deal Block" data-label="Forerunner 970" data-dimension48="Forerunner 970" data-dimension25="$749">View Deal</a></p></div><p>I’m testing the Garmin Fenix 9 Pro 51mm AMOLED with inReach, which costs $1,299, but you have three sizes and two display options to pick from with the Fenix 9.</p><div class="product"><a data-dimension112="c3821e36-b03f-11f1-a73c-9d5c1013a84c" data-action="Deal Block" data-label="Fenix 9 Pro 51mm" data-dimension48="Fenix 9 Pro 51mm" data-dimension25="$1299" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-inReach%C2%AE-Titanium-Pebble/dp/B0HGFW7SSB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:862px;"><p class="vanilla-image-block" style="padding-top:113.92%;"><img id="3FZh5UuTnmxHvnvAFuoaCU" name="Garmin Fenix 9 Pro 51mm" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3FZh5UuTnmxHvnvAFuoaCU-1920-80.png" mos="" align="middle" fullscreen="" width="862" height="982" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-inReach%C2%AE-Titanium-Pebble/dp/B0HGFW7SSB" target="_blank" rel="nofollow" data-dimension112="c3821e36-b03f-11f1-a73c-9d5c1013a84c" data-action="Deal Block" data-label="Fenix 9 Pro 51mm" data-dimension48="Fenix 9 Pro 51mm" data-dimension25="$1299">Fenix 9 Pro 51mm: $1299</a></strong><br>There are a lot of models to pick from the Garmin Fenix 9 line-up, but the 51mm Fenix 9 Pro with inReach is the one I've tested and offers unbelievable battery life, along with an all-titanium case and LTE and satellite connectivity.<a class="view-deal button" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-inReach%C2%AE-Titanium-Pebble/dp/B0HGFW7SSB" target="_blank" rel="nofollow" data-dimension112="c3821e36-b03f-11f1-a73c-9d5c1013a84c" data-action="Deal Block" data-label="Fenix 9 Pro 51mm" data-dimension48="Fenix 9 Pro 51mm" data-dimension25="$1299">View Deal</a></p></div><p>The standard Garmin Fenix 9 starts at $999, whereas the Fenix 9 Pro starts at $1,099. The Pro has an all-titanium case, the option to add inReach connectivity, plus a choice of an AMOLED or MIP display.</p><p>Whatever version of the Fenix 9 you go for, it’s going to be considerably more expensive than the Forerunner 970.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-specs"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Specs</span></h3><div ><table><caption>Garmin Fenix 9 Pro AMOLED vs Garmin Forerunner 970</caption><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Garmin Fenix 8 Pro AMOLED </strong></p></td><td  ><p><strong>Garmin Forerunner 970</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p>From $1,199 (with inReach)</p></td><td  ><p>$749</p></td></tr><tr><td class="firstcol " ><p><strong>Size</strong></p></td><td  ><p>43mm, 47mm or 51mm</p></td><td  ><p>47mm</p></td></tr><tr><td class="firstcol " ><p><strong>Thickness</strong></p></td><td  ><p>13.3mm (43mm),<br>13.8mm (47mm), 15.8mm (51mm)</p></td><td  ><p>12.9mm</p></td></tr><tr><td class="firstcol " ><p><strong>Weight (with strap)</strong></p></td><td  ><p>62g (43mm), 78g (47mm), 99g (51mm)</p></td><td  ><p>56g</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>Sapphire crystal</p></td><td  ><p>Sapphire crystal</p></td></tr><tr><td class="firstcol " ><p><strong>Connectivity</strong></p></td><td  ><p>LTE & satellite</p></td><td  ><p>None</p></td></tr><tr><td class="firstcol " ><p><strong>Smartwatch battery life </strong></p></td><td  ><p>10 days (43 mm), 18 days (47mm), 31 days (51mm)</p></td><td  ><p>15 days</p></td></tr><tr><td class="firstcol " ><p><strong>GPS battery life (multi-band)</strong></p></td><td  ><p>18 hours (43mm), 32 hours (47mm), 56 hours (51mm)</p></td><td  ><p>21 hours</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-design-and-display"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Design and display</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.29%;"><img id="E92Faqn2JY3gLrm7VBKDBJ" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/E92Faqn2JY3gLrm7VBKDBJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1441" 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 two watches share a lot of common design features, including a sapphire crystal screen, built-in flashlight, five buttons, and Garmin’s Elevate v5 heart rate sensors.</p><p>For me, the key difference is certainly the size and weight. The Forerunner 970 is slimmer and lighter than any Fenix model, especially the 51mm model of the Fenix I’m testing. </p><p>Having three options of the Fenix 9 to pick from is an advantage, though, with the 43mm model perhaps a little more suitable for thin wrists than the 47mm Forerunner 970, though the latter is still lighter and thinner.</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="stZ3cPNVMqnsjaS4AbX2LJ" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/stZ3cPNVMqnsjaS4AbX2LJ-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 Forerunner 970 has a titanium bezel but is mostly made from plastic, whereas the Fenix 9 Pro has a full titanium case, which gives it a premium look and feel that’s a little less sporty.</p><p>You also get a higher water resistance rating with the Fenix 9, which is diveproof to 40m and has a 10 ATM rating compared to 5 ATM for the Forerunner 970.</p><p>Other differences to note are that the Fenix 9 has a brighter display than the Forerunner 970, though this was rarely something I noticed when using both watches, and the flashlight on the Fenix 9 Pro has a green option, which you don’t get on the cheaper Fenix 9 or Forerunner 970.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-gps-and-heart-rate-accuracy"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: GPS and heart rate 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:2034px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="vNtZJAU3RmfcY4UTJdFYFm" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:119,l:225,cw:2034,ch:1144,q:80/vNtZJAU3RmfcY4UTJdFYFm.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>My testing of the accuracy of the watches extends well beyond the half marathon I ran wearing both, but it was representative of the results I’ve had with them, in that both were very accurate in the race.</p><p>The GPS tracks were nearly identical when I checked them after the event, and both watches measured almost the exact half marathon distance of 13.1094 miles. </p><p>This was a measured course for my local county’s championship race, and I was able to run the most direct line almost the entire time, so I expected the watches to be very close to the official distance, and they were.</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:2243px;"><p class="vanilla-image-block" style="padding-top:56.22%;"><img id="ytthqbsaVh3YJWeM3WHL7k" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:74,l:168,cw:2243,ch:1261,q:80/ytthqbsaVh3YJWeM3WHL7k.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>Things were similarly impressive with regard to heart rate, which I checked by comparing the watches’ measurements with a Garmin HRM 600 chest strap.</p><p>Aside from the Fenix 9 Pro having a short, erroneous spike near the start of the race, both watches matched the readings from the chest strap beat for beat throughout.</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:39.22%;"><img id="v8vUrxbNgyqjVPXDDfMFnj" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro HR" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro HR" src="https://cdn.mos.cms.futurecdn.net/v8vUrxbNgyqjVPXDDfMFnj-1920-80.jpg" mos="" align="middle" fullscreen="" width="1920" height="753" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: DC Rainmaker Analyzer)</span></figcaption></figure><p>I have run thousands of miles with the Garmin Forerunner 970 and have racked up almost 200 miles with the Fenix 9 Pro so far, as well as doing a lot of other workouts with the watches, and they have been consistently excellent for both GPS and heart rate accuracy.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-battery-life"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Battery life</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="D8oS6F6gNQx8ByPAQSggCJ" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/D8oS6F6gNQx8ByPAQSggCJ-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>Battery life is an area where the Fenix 9 Pro outdoes the Forerunner 970, especially with the largest 51mm model.</p><p>The Forerunner 970 generally lasts me four or five days on a charge with the screen always on, running outdoors every day, whereas the Feinx 9 Pro 51mm has been lasting me 10 or 11 days with the same use.</p><p>It’s closer when comparing the 47mm Fenix 9 to the Forerunner 970, but the Fenix is listed as lasting longer in watch and GPS modes. However, if you opt for the smaller 43mm Fenix 9, the Forerunner 970 will outlast it.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-connectivity"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Connectivity</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="JzL85TmsbDndusgcZgihgG" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/JzL85TmsbDndusgcZgihgG-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 inReach models of the Fenix 9 Pro offer LTE and satellite connectivity, which allow you to stay in touch with the world without carrying your phone, even when you’re in the wilderness and outside cellular coverage.</p><p>This is one of the biggest extra features you get on the Fenix 9 Pro compared with the Forerunner 970, and it will be a huge draw to the most adventurous athletes in particular.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-maps"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Maps</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="6wJJJx9dLQu88kXiwjHjAJ" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/6wJJJx9dLQu88kXiwjHjAJ-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>Both watches offer Garmin’s routable maps and navigation tools, which are the best in the business, but the Fenix 9 Pro has a couple of small upgrades in this area that won’t be coming to the Forerunner 970.</p><p>The first is simply that the maps load a little faster when panning and zooming, and the second is the new perspective view you can use on the Fenix 9, which tilts the map slightly in line with your perspective.</p><p>Both upgrades are welcome, but I wouldn’t classify them as dealbreakers when picking between the two watches myself.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-which-should-you-buy"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Which should you buy?</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Lch3kzEirPc4iesLe5WcpH" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/Lch3kzEirPc4iesLe5WcpH-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 Garmin Forerunner 970 remains my favorite sports watch overall, and I’d pick it over the Fenix 9 Pro because of its lighter, slimmer design and the fact that it’s a lot cheaper.</p><p>However, this is also because none of the feature upgrades you get on the Fenix 9 Pro are absolutely essential for me — if you need the extra connectivity in particular, then paying more for a Fenix will be worthwhile.</p><p>The design of the Fenix 9 Pro will also appeal to a lot of people. The all-metal design is gorgeous and means the watch is a better fit for smart settings than the sportier Forerunner 970.</p><p>On accuracy and key sports and navigation features, however, the two watches are pretty much a wash based on my testing, and clearly two of the best options on the market from any brand.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xj2xlX"></div>                            </div>                            <script src="https://kwizly.com/embed/Xj2xlX.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><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model">Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-11-vs-apple-watch-ultra-3-which-one-should-you-buy">Apple Watch 11 vs Apple Watch Ultra 3 — which one should you buy?</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai">We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/i-raced-a-half-marathon-with-the-garmin-fenix-9-pro-vs-garmin-forerunner-970-heres-which-one-id-buy</link>
                                                                            <description>
                            <![CDATA[ The Garmin Forerunner 970 and Garmin Fenix 9 Pro are two of the most impressive sports watches I’ve ever tested, but which is the better buy? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">zUo4NmkPwxniUCxHYbDqnc</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/72dr5XxQf9wqUucVszw9Ek-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 16 Sep 2026 09:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Nick Harris-Fry ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/J5Jjp49GUVjLZEbjEkTex-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/72dr5XxQf9wqUucVszw9Ek-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Garmin Forerunner 970 vs Garmin Fenix 9 Pro]]></media:description>                                                            <media:text><![CDATA[Garmin Forerunner 970 vs Garmin Fenix 9 Pro]]></media:text>
                                <media:title type="plain"><![CDATA[Garmin Forerunner 970 vs Garmin Fenix 9 Pro]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/72dr5XxQf9wqUucVszw9Ek-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor">Garmin Fenix 9 Pro</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-garmin-forerunner-970-for-six-months-here-are-my-long-term-pros-and-cons">Garmin Forerunner 970 </a>sit at the top of their respective trees within the Garmin line-up, and both are among the <a href="https://www.tomsguide.com/us/best-gps-watches,review-2638.html">best sports watches </a>available.</p><p>They’re pitched at slightly different athletes, with the Forerunner 970 being a lightweight, slim watch built for the keenest runners and triathletes, while the all-metal Fenix 9 Pro is aimed at adventurers, offering epic battery life, LTE and satellite connectivity.</p><p>However, they do share a lot of features, even including some of the new ones introduced with the Fenix 9 Pro that will roll back to the Forerunner 970, and many people will be picking between the two when buying one of the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches</a>.</p><p>I’ve worn the Garmin Forerunner 970 for over a year myself and have had the Fenix 9 Pro strapped on for a few weeks since its launch, and I tested the two head-to-head at a half marathon.</p><p>Here’s my full Garmin Fenix 9 Pro vs Garmin Forerunner 970 comparison, looking at price, accuracy, design, battery life and other key differences between the pair.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-price"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Price</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:2161px;"><p class="vanilla-image-block" style="padding-top:56.22%;"><img id="NmEaDfEmcWjvSpjY2JqRsj" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:98,l:225,cw:2161,ch:1215,q:80/NmEaDfEmcWjvSpjY2JqRsj.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 Garmin Forerunner 970 has been out for over a year, which means you can often find it for less than its full price of $749. It comes in one size and three colors, keeping things nice and simple compared with the sprawling Fenix 9 line-up.</p><div class="product"><a data-dimension112="c3821d50-b03f-11f1-9ca5-0749730caa84" data-action="Deal Block" data-label="Forerunner 970" data-dimension48="Forerunner 970" data-dimension25="$749" href="https://www.amazon.com/Forerunner%C2%AE-Smartwatch-Flashlight-Translucent-Whitestone/dp/B0F8QWPVNK?th=1" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1268px;"><p class="vanilla-image-block" style="padding-top:94.95%;"><img id="3GKnEu7CdhtxPMfnPCMCiA" name="Garmin Forerunner 970" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA-1920-80.png" mos="" align="middle" fullscreen="" width="1268" height="1204" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Garmin Forerunner 970 is the best running watch available, in my opinion, with a lightweight, attractive design and all the features you could ever need. In sales, it can drop as low as $649, but it's still cheaper than the Garmin Fenix 9 Pro at a full price of $749.<a class="view-deal button" href="https://www.amazon.com/Forerunner%C2%AE-Smartwatch-Flashlight-Translucent-Whitestone/dp/B0F8QWPVNK?th=1" target="_blank" rel="nofollow" data-dimension112="c3821d50-b03f-11f1-9ca5-0749730caa84" data-action="Deal Block" data-label="Forerunner 970" data-dimension48="Forerunner 970" data-dimension25="$749">View Deal</a></p></div><p>I’m testing the Garmin Fenix 9 Pro 51mm AMOLED with inReach, which costs $1,299, but you have three sizes and two display options to pick from with the Fenix 9.</p><div class="product"><a data-dimension112="c3821e36-b03f-11f1-a73c-9d5c1013a84c" data-action="Deal Block" data-label="Fenix 9 Pro 51mm" data-dimension48="Fenix 9 Pro 51mm" data-dimension25="$1299" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-inReach%C2%AE-Titanium-Pebble/dp/B0HGFW7SSB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:862px;"><p class="vanilla-image-block" style="padding-top:113.92%;"><img id="3FZh5UuTnmxHvnvAFuoaCU" name="Garmin Fenix 9 Pro 51mm" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3FZh5UuTnmxHvnvAFuoaCU-1920-80.png" mos="" align="middle" fullscreen="" width="862" height="982" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-inReach%C2%AE-Titanium-Pebble/dp/B0HGFW7SSB" target="_blank" rel="nofollow" data-dimension112="c3821e36-b03f-11f1-a73c-9d5c1013a84c" data-action="Deal Block" data-label="Fenix 9 Pro 51mm" data-dimension48="Fenix 9 Pro 51mm" data-dimension25="$1299">Fenix 9 Pro 51mm: $1299</a></strong><br>There are a lot of models to pick from the Garmin Fenix 9 line-up, but the 51mm Fenix 9 Pro with inReach is the one I've tested and offers unbelievable battery life, along with an all-titanium case and LTE and satellite connectivity.<a class="view-deal button" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-inReach%C2%AE-Titanium-Pebble/dp/B0HGFW7SSB" target="_blank" rel="nofollow" data-dimension112="c3821e36-b03f-11f1-a73c-9d5c1013a84c" data-action="Deal Block" data-label="Fenix 9 Pro 51mm" data-dimension48="Fenix 9 Pro 51mm" data-dimension25="$1299">View Deal</a></p></div><p>The standard Garmin Fenix 9 starts at $999, whereas the Fenix 9 Pro starts at $1,099. The Pro has an all-titanium case, the option to add inReach connectivity, plus a choice of an AMOLED or MIP display.</p><p>Whatever version of the Fenix 9 you go for, it’s going to be considerably more expensive than the Forerunner 970.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-specs"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Specs</span></h3><div ><table><caption>Garmin Fenix 9 Pro AMOLED vs Garmin Forerunner 970</caption><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Garmin Fenix 8 Pro AMOLED </strong></p></td><td  ><p><strong>Garmin Forerunner 970</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p>From $1,199 (with inReach)</p></td><td  ><p>$749</p></td></tr><tr><td class="firstcol " ><p><strong>Size</strong></p></td><td  ><p>43mm, 47mm or 51mm</p></td><td  ><p>47mm</p></td></tr><tr><td class="firstcol " ><p><strong>Thickness</strong></p></td><td  ><p>13.3mm (43mm),<br>13.8mm (47mm), 15.8mm (51mm)</p></td><td  ><p>12.9mm</p></td></tr><tr><td class="firstcol " ><p><strong>Weight (with strap)</strong></p></td><td  ><p>62g (43mm), 78g (47mm), 99g (51mm)</p></td><td  ><p>56g</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>Sapphire crystal</p></td><td  ><p>Sapphire crystal</p></td></tr><tr><td class="firstcol " ><p><strong>Connectivity</strong></p></td><td  ><p>LTE & satellite</p></td><td  ><p>None</p></td></tr><tr><td class="firstcol " ><p><strong>Smartwatch battery life </strong></p></td><td  ><p>10 days (43 mm), 18 days (47mm), 31 days (51mm)</p></td><td  ><p>15 days</p></td></tr><tr><td class="firstcol " ><p><strong>GPS battery life (multi-band)</strong></p></td><td  ><p>18 hours (43mm), 32 hours (47mm), 56 hours (51mm)</p></td><td  ><p>21 hours</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-design-and-display"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Design and display</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.29%;"><img id="E92Faqn2JY3gLrm7VBKDBJ" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/E92Faqn2JY3gLrm7VBKDBJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1441" 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 two watches share a lot of common design features, including a sapphire crystal screen, built-in flashlight, five buttons, and Garmin’s Elevate v5 heart rate sensors.</p><p>For me, the key difference is certainly the size and weight. The Forerunner 970 is slimmer and lighter than any Fenix model, especially the 51mm model of the Fenix I’m testing. </p><p>Having three options of the Fenix 9 to pick from is an advantage, though, with the 43mm model perhaps a little more suitable for thin wrists than the 47mm Forerunner 970, though the latter is still lighter and thinner.</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="stZ3cPNVMqnsjaS4AbX2LJ" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/stZ3cPNVMqnsjaS4AbX2LJ-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 Forerunner 970 has a titanium bezel but is mostly made from plastic, whereas the Fenix 9 Pro has a full titanium case, which gives it a premium look and feel that’s a little less sporty.</p><p>You also get a higher water resistance rating with the Fenix 9, which is diveproof to 40m and has a 10 ATM rating compared to 5 ATM for the Forerunner 970.</p><p>Other differences to note are that the Fenix 9 has a brighter display than the Forerunner 970, though this was rarely something I noticed when using both watches, and the flashlight on the Fenix 9 Pro has a green option, which you don’t get on the cheaper Fenix 9 or Forerunner 970.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-gps-and-heart-rate-accuracy"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: GPS and heart rate 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:2034px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="vNtZJAU3RmfcY4UTJdFYFm" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:119,l:225,cw:2034,ch:1144,q:80/vNtZJAU3RmfcY4UTJdFYFm.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>My testing of the accuracy of the watches extends well beyond the half marathon I ran wearing both, but it was representative of the results I’ve had with them, in that both were very accurate in the race.</p><p>The GPS tracks were nearly identical when I checked them after the event, and both watches measured almost the exact half marathon distance of 13.1094 miles. </p><p>This was a measured course for my local county’s championship race, and I was able to run the most direct line almost the entire time, so I expected the watches to be very close to the official distance, and they were.</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:2243px;"><p class="vanilla-image-block" style="padding-top:56.22%;"><img id="ytthqbsaVh3YJWeM3WHL7k" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:74,l:168,cw:2243,ch:1261,q:80/ytthqbsaVh3YJWeM3WHL7k.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>Things were similarly impressive with regard to heart rate, which I checked by comparing the watches’ measurements with a Garmin HRM 600 chest strap.</p><p>Aside from the Fenix 9 Pro having a short, erroneous spike near the start of the race, both watches matched the readings from the chest strap beat for beat throughout.</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:39.22%;"><img id="v8vUrxbNgyqjVPXDDfMFnj" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro HR" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro HR" src="https://cdn.mos.cms.futurecdn.net/v8vUrxbNgyqjVPXDDfMFnj-1920-80.jpg" mos="" align="middle" fullscreen="" width="1920" height="753" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: DC Rainmaker Analyzer)</span></figcaption></figure><p>I have run thousands of miles with the Garmin Forerunner 970 and have racked up almost 200 miles with the Fenix 9 Pro so far, as well as doing a lot of other workouts with the watches, and they have been consistently excellent for both GPS and heart rate accuracy.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-battery-life"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Battery life</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="D8oS6F6gNQx8ByPAQSggCJ" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/D8oS6F6gNQx8ByPAQSggCJ-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>Battery life is an area where the Fenix 9 Pro outdoes the Forerunner 970, especially with the largest 51mm model.</p><p>The Forerunner 970 generally lasts me four or five days on a charge with the screen always on, running outdoors every day, whereas the Feinx 9 Pro 51mm has been lasting me 10 or 11 days with the same use.</p><p>It’s closer when comparing the 47mm Fenix 9 to the Forerunner 970, but the Fenix is listed as lasting longer in watch and GPS modes. However, if you opt for the smaller 43mm Fenix 9, the Forerunner 970 will outlast it.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-connectivity"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Connectivity</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="JzL85TmsbDndusgcZgihgG" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/JzL85TmsbDndusgcZgihgG-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 inReach models of the Fenix 9 Pro offer LTE and satellite connectivity, which allow you to stay in touch with the world without carrying your phone, even when you’re in the wilderness and outside cellular coverage.</p><p>This is one of the biggest extra features you get on the Fenix 9 Pro compared with the Forerunner 970, and it will be a huge draw to the most adventurous athletes in particular.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-maps"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Maps</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="6wJJJx9dLQu88kXiwjHjAJ" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/6wJJJx9dLQu88kXiwjHjAJ-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>Both watches offer Garmin’s routable maps and navigation tools, which are the best in the business, but the Fenix 9 Pro has a couple of small upgrades in this area that won’t be coming to the Forerunner 970.</p><p>The first is simply that the maps load a little faster when panning and zooming, and the second is the new perspective view you can use on the Fenix 9, which tilts the map slightly in line with your perspective.</p><p>Both upgrades are welcome, but I wouldn’t classify them as dealbreakers when picking between the two watches myself.</p><h3 class="article-body__section" id="section-garmin-fenix-9-pro-vs-garmin-forerunner-970-which-should-you-buy"><span>Garmin Fenix 9 Pro vs Garmin Forerunner 970: Which should you buy?</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Lch3kzEirPc4iesLe5WcpH" name="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" alt="Garmin Forerunner 970 vs Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/Lch3kzEirPc4iesLe5WcpH-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 Garmin Forerunner 970 remains my favorite sports watch overall, and I’d pick it over the Fenix 9 Pro because of its lighter, slimmer design and the fact that it’s a lot cheaper.</p><p>However, this is also because none of the feature upgrades you get on the Fenix 9 Pro are absolutely essential for me — if you need the extra connectivity in particular, then paying more for a Fenix will be worthwhile.</p><p>The design of the Fenix 9 Pro will also appeal to a lot of people. The all-metal design is gorgeous and means the watch is a better fit for smart settings than the sportier Forerunner 970.</p><p>On accuracy and key sports and navigation features, however, the two watches are pretty much a wash based on my testing, and clearly two of the best options on the market from any brand.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xj2xlX"></div>                            </div>                            <script src="https://kwizly.com/embed/Xj2xlX.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><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model">Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-11-vs-apple-watch-ultra-3-which-one-should-you-buy">Apple Watch 11 vs Apple Watch Ultra 3 — which one should you buy?</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai">We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Fitbit Air (2026) vs Fitbit Flex (2013) — how much has wearable tech actually progressed in 13 years? ]]></title>
                                                                                                <dc:content><![CDATA[ <p>There’s a bit of a revolution happening in the wearable space right now because many of us realize we don’t want yet another screen vying for our attention. But we still need to know our metrics. That’s why the likes of 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>, <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-garmin-cirqa-and-it-strikes-a-near-perfect-balance-between-the-fitbit-air-and-whoop-5-0">Garmin Cirqa,</a> or <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a> have surged in popularity, and we get <a href="https://www.tomsguide.com/wellness/fitness-trackers/join-our-wearable-tech-live-q-and-a-should-you-ditch-the-smartwatch-for-an-oura-whoop-garmin-cirqa-or-fitbit-air">constant questions about which is the right one to buy</a>. </p><p>Casting the longest shadow, though, is the Fitbit Air, which was released for $99 / £84 and scored <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">4 stars when my colleague Jane reviewed it in March</a>.</p><p>The Fitbit Air is a simple, discreet tracker with no screen and no subscription, and it allows you to go about your routine and almost forget you’re wearing it. Of course, if you’re training for an Ironman, you need something a little more hardcore, but for the vast majority of us, the Fitbit Air feels like the right device at the right time. But the fact is, we’ve been here before.</p><p>Back in 2013, Fitbit was an up-and-coming wearable tech company that had yet to be swallowed up by the Google Empire. It made its name with the Fitbit Flex, a $99 wrist-worn pedometer and sleep tracker that landed alongside the likes of the Jawbone Up and Nike Fuelband as a way for people to track progress toward their 10,000 steps per day.</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="k8g7gfQRuHFKpzMDfEVuc5" name="Fitbit Air Vs Flex-6" alt="Fitbit Air vs Fitbit Flex" src="https://cdn.mos.cms.futurecdn.net/k8g7gfQRuHFKpzMDfEVuc5-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 / Jeff Parsons)</span></figcaption></figure><p>I had one of those trackers back in the day, and after a recent clear-out at home, I not only found it — but discovered it still held a charge. Earlier this year, my colleague Dan Bracaglia matched <a href="https://www.tomsguide.com/wellness/fitness-trackers/is-your-old-fitness-tracker-good-enough-i-tested-a-5-year-old-fitbit-vs-apple-watch-series-11-on-a-5-500-step-walk-to-find-out">a 5-year-old Fitbit vs Apple Watch Series 11 on a 5,500-step walk</a> to find out if your old fitness tracker is still good enough. So I decided to go one better and see how a 13-year-old fitness tracker holds up to <a href="https://www.tomsguide.com/wellness/fitness-trackers/exclusive-google-design-director-says-fitbit-air-reception-proves-they-made-the-right-decision-going-screen-free">Fitbit’s 2026 breakout success</a>.</p><p>I wore both trackers on my wrist for a day and a night and took their readings on steps and sleep. Back in 2013, the Flex couldn’t measure anything else. But even after all this time, the results from the two devices on those two metrics were pretty close:</p><div ><table><tbody><tr><td class="firstcol " ><p><strong>Wednesday, September 9, 2026</strong></p></td><td  ><p><strong>Fitbit Air (2026)</strong></p></td><td  ><p><strong>Fitbit Flex (2013)</strong></p></td></tr><tr><td class="firstcol " ><p>Steps</p></td><td  ><p>9,093</p></td><td  ><p>9,285</p></td></tr><tr><td class="firstcol " ><p>Sleep</p></td><td  ><p>6 hours 22m (83 sleep score)</p></td><td  ><p>6 hours 13m (No sleep score) </p></td></tr></tbody></table></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:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wmY7kpLvmY7dqqJsdmKfZP" name="Fitbit Air stats" alt="Fitbit Air vs Fitbit Flex stats" src="https://cdn.mos.cms.futurecdn.net/wmY7kpLvmY7dqqJsdmKfZP-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="caption-text">Fitbit Air (2026) steps and sleep metrics </span><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><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="PxbzZL6JkZCwYfVE4zXobP" name="Fitbit Flex stats" alt="Fitbit Air vs Fitbit Flex stats" src="https://cdn.mos.cms.futurecdn.net/PxbzZL6JkZCwYfVE4zXobP-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="caption-text">Fitbit Flex (2013) steps and sleep metrics </span><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I continued to wear the two devices alongside each other on my wrist for a couple of days. I would have gone longer, but the brittle rubber strap of the Flex embarrassingly broke as I went to shake someone’s hand. Even so, after spending some time with my fitness tracker of yesteryear, I’ve come to some conclusions about just how good the Fitbit Air is.</p><h2 id="fitbit-air-vs-fitbit-flex-all-the-improvements-for-the-same-99-price">Fitbit Air vs Fitbit Flex: All the improvements for the same $99 price</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="MkoXs2LUHRBEeywd4Nvtb5" name="Fitbit Air Vs Flex-7" alt="Fitbit Air vs Fitbit Flex" src="https://cdn.mos.cms.futurecdn.net/MkoXs2LUHRBEeywd4Nvtb5-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 / Jeff Parsons)</span></figcaption></figure><p>It's kind of incredible to think the Fitbit Flex launched with a $99 / £79 price back in the day, and now the Fitbit Air is here for that same $99. In the U.K., where I live, the £79 has ballooned to £84, but you can’t win ‘em all.</p><div><blockquote><p>13 years later, instead of just getting steps and sleep, you now get heart rate, blood oxygen, skin temperature, a sleep and readiness score, workout tracking and — if you want to pay for it — a full AI coach sitting inside the Google Health app.</p></blockquote></div><p>For that same price, 13 years later, instead of just getting steps and sleep, you now get heart rate, blood oxygen, skin temperature, a sleep and readiness score as well as workout tracking and — if you want to pay for it — a full AI coach sitting inside the <a href="https://www.tomsguide.com/wellness/fitness/the-fitbit-app-is-officially-dead-but-dont-panic-its-replacement-is-even-better">Google Health app</a>.</p><p>The improvements don’t just stop at the hardware: Google’s Fitbit Air woven loop is a breathable fabric strap that’s 10 times more comfortable than the bulky rubber strap the Fitbit Flex arrived with. And the Air will go for seven days without charge, while the Flex only manages five. After more than a decade in storage, my model lasted a little over two days before needing to be recharged.</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="wFetMg9qDeVKgkjqfC33b5" name="Fitbit Air Vs Flex-3" alt="Fitbit Air vs Fitbit Flex" src="https://cdn.mos.cms.futurecdn.net/wFetMg9qDeVKgkjqfC33b5-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 / Jeff Parsons)</span></figcaption></figure><p>Lastly, the fact that the Air will automatically track when you fall asleep or start a workout is a huge improvement. On the Flex, you had to remember to tap it firmly to put it in sleep mode, and it had no workout option. I remember missing many nights of sleep because I forgot to put my tracker into sleep mode before my head hit the pillow.</p><p>One thing I do like about the Flex is the little row of blinking LEDs that gives you some idea of your step progress. The Air is completely screen-free, but in a roundabout way, this might not be the panacea you think it is. If you want to see how you’re tracking against a goal, you need to pull out your phone and look — which ironically makes it all too easy to spiral into a screen-time rabbit hole if you’re not careful.</p><h2 id="fitbit-air-vs-fitbit-flex-step-counting-vs-true-health-tracking">Fitbit Air vs Fitbit Flex: Step counting vs true health tracking</h2><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="cBuBcoiJjpSobpVgSwDac5" name="Fitbit Air Vs Flex-2" alt="Fitbit Air vs Fitbit Flex" src="https://cdn.mos.cms.futurecdn.net/cBuBcoiJjpSobpVgSwDac5-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 / Jeff Parsons)</span></figcaption></figure><p>It was a simpler time back in 2013; all we really wanted to know was if we could hit 10,000 steps a day. Now we know that metrics aren’t as important as we thought they were, and the goal is overall holistic wellness. </p><p>That’s why the Air is powered by Gemini and can automatically provide you with a detailed sleep summary every morning or give you a cardio load score — which measures the strain on your system when you’re exercising.</p><p>But this is where we run into some of the Air’s downsides. There’s no onboard GPS for location data or altimeter for elevation insights. So if you want to go for a run or a cycle, you’ll need to bring a paired smartphone along with you. </p><p>It’s still better than what we had in 2013, though, as the Fitbit Air automatically tracks a small selection of workout types, including walks, bike rides, "sports," and other activities. It does so whether you carry your paired phone or not, but there's a catch. For an activity to be auto-logged, you have to do it for at least 15 consecutive minutes.</p><p>Also, as mentioned, to get the most from the tracker, you need to pay for the Google Health Premium subscription to unlock personalized AI-backed health and fitness insights, along with deeper dives into your holistic trends. That will cost you $9.99 a month or $99 a year.</p><h2 id="fitbit-air-vs-fitbit-flex-last-band-standing">Fitbit Air vs Fitbit Flex: Last band standing</h2><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="cgxaLCJUHYNcAfV6GegbZ5" name="Fitbit Air Vs Flex-4" alt="Fitbit Air vs Fitbit Flex" src="https://cdn.mos.cms.futurecdn.net/cgxaLCJUHYNcAfV6GegbZ5-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 / Jeff Parsons)</span></figcaption></figure><p>The point of this little experiment — beyond the novelty of finding an old piece of tech that still works — is the amount of value the Fitbit Air brings to the table as a tracker in 2026. If you’re a more established athlete and training toward a goal, I would personally recommend one of the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin smartwatches</a> or the <a href="https://www.tomsguide.com/best-picks/best-apple-watch">best Apple Watches </a>over the Fitbit Air. </p><p>But for those of us who want to keep an eye on our activity without it being intrusive — just like back in the day — the Air is hard to beat. And while the <a href="https://www.tomsguide.com/computing/the-ram-crisis-is-so-much-bigger-than-pcs-heres-the-rest-of-the-products-caught-in-the-crossfire">RAM crisis is pushing up prices across the board</a>, I was struck by how much more Google can offer with the Air for the same price as its predecessor was over a decade ago.</p><p>There are still some niggles, like having a proprietary charging port so you can’t charge either the Flex or the Air with a generic USB-C cable, but I know that’s due to the waterproofing requirements. Overall, despite initially thinking <a href="https://www.tomsguide.com/opinion/im-ditching-fitbit-for-the-apple-watch-after-10-years-heres-why">I was done with Fitbit after 10 years</a>, the simplicity and comfort of the Air have pulled me right back into it.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eP9JQW"></div>                            </div>                            <script src="https://kwizly.com/embed/eP9JQW.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/us/best-fitbit,review-3203.html">The best Fitbit trackers we've tested</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-spent-two-weeks-with-the-usd99-fitbit-air-here-are-my-3-reasons-to-buy-and-3-reasons-to-skip">I spent two weeks with the $99 Fitbit Air</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/exclusive-google-design-director-says-fitbit-air-reception-proves-they-made-the-right-decision-going-screen-free">Exclusive: Google design director says Fitbit Air reception proves they 'made the right decision'</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-2026-vs-fitbit-flex-2013-how-much-has-wearable-tech-actually-progressed-in-13-years</link>
                                                                            <description>
                            <![CDATA[ 13 years, one wrist: Here’s what it’s like to test the screenless Fitbit Air against the original Fitbit Flex. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">TzWkgB8he9cr4HFYFdHdCZ</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/a7CXnPu8NyFQAgWCTuZUd5-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 15 Sep 2026 10:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Smartwatches]]></category>
                                                                                                <author><![CDATA[ jeff.parsons@futurenet.com (Jeff Parsons) ]]></author>                    <dc:creator><![CDATA[ Jeff Parsons ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/7z3UTGGrmSokMKxTWHmhjX-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Jeff is U.K. Editor-in-Chief for Tom’s Guide looking after the day-to-day output of the site’s British contingent. &lt;/p&gt;&lt;p&gt;Rising early and heading straight for the coffee machine, Jeff loves nothing more than dialling into the zeitgeist of the day’s tech news. A journalist for over a decade, he&#039;s travelled around the world testing and reviewing any gadget he can get his hands on.&lt;/p&gt;&lt;p&gt;Before joining the team at Tom’s Guide, Jeff covered technology and science for two of the U.K.’s biggest national news sites: Metro.co.uk and the Daily Mirror. Memorable moments include getting lost in Vienna in an electric Audi, touring Lockheed Martin’s mile-long jet factory in Fort Worth and filming a Netflix documentary about Elon Musk in West London.&lt;/p&gt;&lt;p&gt;When not plugged into the current news agenda, editing or commissioning a series of articles or debating the merits of Apple vs Android, Jeff can usually be found out for a run trying to shave precious seconds off his PB. Or lifting weights in a vain attempt to offset the ageing process.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/a7CXnPu8NyFQAgWCTuZUd5-1920-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide / Jeff Parsons]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Fitbit Air vs Fitbit Flex]]></media:description>                                                            <media:text><![CDATA[Fitbit Air vs Fitbit Flex]]></media:text>
                                <media:title type="plain"><![CDATA[Fitbit Air vs Fitbit Flex]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/a7CXnPu8NyFQAgWCTuZUd5-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>There’s a bit of a revolution happening in the wearable space right now because many of us realize we don’t want yet another screen vying for our attention. But we still need to know our metrics. That’s why the likes of 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>, <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-garmin-cirqa-and-it-strikes-a-near-perfect-balance-between-the-fitbit-air-and-whoop-5-0">Garmin Cirqa,</a> or <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a> have surged in popularity, and we get <a href="https://www.tomsguide.com/wellness/fitness-trackers/join-our-wearable-tech-live-q-and-a-should-you-ditch-the-smartwatch-for-an-oura-whoop-garmin-cirqa-or-fitbit-air">constant questions about which is the right one to buy</a>. </p><p>Casting the longest shadow, though, is the Fitbit Air, which was released for $99 / £84 and scored <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">4 stars when my colleague Jane reviewed it in March</a>.</p><p>The Fitbit Air is a simple, discreet tracker with no screen and no subscription, and it allows you to go about your routine and almost forget you’re wearing it. Of course, if you’re training for an Ironman, you need something a little more hardcore, but for the vast majority of us, the Fitbit Air feels like the right device at the right time. But the fact is, we’ve been here before.</p><p>Back in 2013, Fitbit was an up-and-coming wearable tech company that had yet to be swallowed up by the Google Empire. It made its name with the Fitbit Flex, a $99 wrist-worn pedometer and sleep tracker that landed alongside the likes of the Jawbone Up and Nike Fuelband as a way for people to track progress toward their 10,000 steps per day.</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="k8g7gfQRuHFKpzMDfEVuc5" name="Fitbit Air Vs Flex-6" alt="Fitbit Air vs Fitbit Flex" src="https://cdn.mos.cms.futurecdn.net/k8g7gfQRuHFKpzMDfEVuc5-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 / Jeff Parsons)</span></figcaption></figure><p>I had one of those trackers back in the day, and after a recent clear-out at home, I not only found it — but discovered it still held a charge. Earlier this year, my colleague Dan Bracaglia matched <a href="https://www.tomsguide.com/wellness/fitness-trackers/is-your-old-fitness-tracker-good-enough-i-tested-a-5-year-old-fitbit-vs-apple-watch-series-11-on-a-5-500-step-walk-to-find-out">a 5-year-old Fitbit vs Apple Watch Series 11 on a 5,500-step walk</a> to find out if your old fitness tracker is still good enough. So I decided to go one better and see how a 13-year-old fitness tracker holds up to <a href="https://www.tomsguide.com/wellness/fitness-trackers/exclusive-google-design-director-says-fitbit-air-reception-proves-they-made-the-right-decision-going-screen-free">Fitbit’s 2026 breakout success</a>.</p><p>I wore both trackers on my wrist for a day and a night and took their readings on steps and sleep. Back in 2013, the Flex couldn’t measure anything else. But even after all this time, the results from the two devices on those two metrics were pretty close:</p><div ><table><tbody><tr><td class="firstcol " ><p><strong>Wednesday, September 9, 2026</strong></p></td><td  ><p><strong>Fitbit Air (2026)</strong></p></td><td  ><p><strong>Fitbit Flex (2013)</strong></p></td></tr><tr><td class="firstcol " ><p>Steps</p></td><td  ><p>9,093</p></td><td  ><p>9,285</p></td></tr><tr><td class="firstcol " ><p>Sleep</p></td><td  ><p>6 hours 22m (83 sleep score)</p></td><td  ><p>6 hours 13m (No sleep score) </p></td></tr></tbody></table></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:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wmY7kpLvmY7dqqJsdmKfZP" name="Fitbit Air stats" alt="Fitbit Air vs Fitbit Flex stats" src="https://cdn.mos.cms.futurecdn.net/wmY7kpLvmY7dqqJsdmKfZP-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="caption-text">Fitbit Air (2026) steps and sleep metrics </span><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><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="PxbzZL6JkZCwYfVE4zXobP" name="Fitbit Flex stats" alt="Fitbit Air vs Fitbit Flex stats" src="https://cdn.mos.cms.futurecdn.net/PxbzZL6JkZCwYfVE4zXobP-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="caption-text">Fitbit Flex (2013) steps and sleep metrics </span><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I continued to wear the two devices alongside each other on my wrist for a couple of days. I would have gone longer, but the brittle rubber strap of the Flex embarrassingly broke as I went to shake someone’s hand. Even so, after spending some time with my fitness tracker of yesteryear, I’ve come to some conclusions about just how good the Fitbit Air is.</p><h2 id="fitbit-air-vs-fitbit-flex-all-the-improvements-for-the-same-99-price">Fitbit Air vs Fitbit Flex: All the improvements for the same $99 price</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="MkoXs2LUHRBEeywd4Nvtb5" name="Fitbit Air Vs Flex-7" alt="Fitbit Air vs Fitbit Flex" src="https://cdn.mos.cms.futurecdn.net/MkoXs2LUHRBEeywd4Nvtb5-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 / Jeff Parsons)</span></figcaption></figure><p>It's kind of incredible to think the Fitbit Flex launched with a $99 / £79 price back in the day, and now the Fitbit Air is here for that same $99. In the U.K., where I live, the £79 has ballooned to £84, but you can’t win ‘em all.</p><div><blockquote><p>13 years later, instead of just getting steps and sleep, you now get heart rate, blood oxygen, skin temperature, a sleep and readiness score, workout tracking and — if you want to pay for it — a full AI coach sitting inside the Google Health app.</p></blockquote></div><p>For that same price, 13 years later, instead of just getting steps and sleep, you now get heart rate, blood oxygen, skin temperature, a sleep and readiness score as well as workout tracking and — if you want to pay for it — a full AI coach sitting inside the <a href="https://www.tomsguide.com/wellness/fitness/the-fitbit-app-is-officially-dead-but-dont-panic-its-replacement-is-even-better">Google Health app</a>.</p><p>The improvements don’t just stop at the hardware: Google’s Fitbit Air woven loop is a breathable fabric strap that’s 10 times more comfortable than the bulky rubber strap the Fitbit Flex arrived with. And the Air will go for seven days without charge, while the Flex only manages five. After more than a decade in storage, my model lasted a little over two days before needing to be recharged.</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="wFetMg9qDeVKgkjqfC33b5" name="Fitbit Air Vs Flex-3" alt="Fitbit Air vs Fitbit Flex" src="https://cdn.mos.cms.futurecdn.net/wFetMg9qDeVKgkjqfC33b5-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 / Jeff Parsons)</span></figcaption></figure><p>Lastly, the fact that the Air will automatically track when you fall asleep or start a workout is a huge improvement. On the Flex, you had to remember to tap it firmly to put it in sleep mode, and it had no workout option. I remember missing many nights of sleep because I forgot to put my tracker into sleep mode before my head hit the pillow.</p><p>One thing I do like about the Flex is the little row of blinking LEDs that gives you some idea of your step progress. The Air is completely screen-free, but in a roundabout way, this might not be the panacea you think it is. If you want to see how you’re tracking against a goal, you need to pull out your phone and look — which ironically makes it all too easy to spiral into a screen-time rabbit hole if you’re not careful.</p><h2 id="fitbit-air-vs-fitbit-flex-step-counting-vs-true-health-tracking">Fitbit Air vs Fitbit Flex: Step counting vs true health tracking</h2><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="cBuBcoiJjpSobpVgSwDac5" name="Fitbit Air Vs Flex-2" alt="Fitbit Air vs Fitbit Flex" src="https://cdn.mos.cms.futurecdn.net/cBuBcoiJjpSobpVgSwDac5-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 / Jeff Parsons)</span></figcaption></figure><p>It was a simpler time back in 2013; all we really wanted to know was if we could hit 10,000 steps a day. Now we know that metrics aren’t as important as we thought they were, and the goal is overall holistic wellness. </p><p>That’s why the Air is powered by Gemini and can automatically provide you with a detailed sleep summary every morning or give you a cardio load score — which measures the strain on your system when you’re exercising.</p><p>But this is where we run into some of the Air’s downsides. There’s no onboard GPS for location data or altimeter for elevation insights. So if you want to go for a run or a cycle, you’ll need to bring a paired smartphone along with you. </p><p>It’s still better than what we had in 2013, though, as the Fitbit Air automatically tracks a small selection of workout types, including walks, bike rides, "sports," and other activities. It does so whether you carry your paired phone or not, but there's a catch. For an activity to be auto-logged, you have to do it for at least 15 consecutive minutes.</p><p>Also, as mentioned, to get the most from the tracker, you need to pay for the Google Health Premium subscription to unlock personalized AI-backed health and fitness insights, along with deeper dives into your holistic trends. That will cost you $9.99 a month or $99 a year.</p><h2 id="fitbit-air-vs-fitbit-flex-last-band-standing">Fitbit Air vs Fitbit Flex: Last band standing</h2><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="cgxaLCJUHYNcAfV6GegbZ5" name="Fitbit Air Vs Flex-4" alt="Fitbit Air vs Fitbit Flex" src="https://cdn.mos.cms.futurecdn.net/cgxaLCJUHYNcAfV6GegbZ5-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 / Jeff Parsons)</span></figcaption></figure><p>The point of this little experiment — beyond the novelty of finding an old piece of tech that still works — is the amount of value the Fitbit Air brings to the table as a tracker in 2026. If you’re a more established athlete and training toward a goal, I would personally recommend one of the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin smartwatches</a> or the <a href="https://www.tomsguide.com/best-picks/best-apple-watch">best Apple Watches </a>over the Fitbit Air. </p><p>But for those of us who want to keep an eye on our activity without it being intrusive — just like back in the day — the Air is hard to beat. And while the <a href="https://www.tomsguide.com/computing/the-ram-crisis-is-so-much-bigger-than-pcs-heres-the-rest-of-the-products-caught-in-the-crossfire">RAM crisis is pushing up prices across the board</a>, I was struck by how much more Google can offer with the Air for the same price as its predecessor was over a decade ago.</p><p>There are still some niggles, like having a proprietary charging port so you can’t charge either the Flex or the Air with a generic USB-C cable, but I know that’s due to the waterproofing requirements. Overall, despite initially thinking <a href="https://www.tomsguide.com/opinion/im-ditching-fitbit-for-the-apple-watch-after-10-years-heres-why">I was done with Fitbit after 10 years</a>, the simplicity and comfort of the Air have pulled me right back into it.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eP9JQW"></div>                            </div>                            <script src="https://kwizly.com/embed/eP9JQW.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/us/best-fitbit,review-3203.html">The best Fitbit trackers we've tested</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-spent-two-weeks-with-the-usd99-fitbit-air-here-are-my-3-reasons-to-buy-and-3-reasons-to-skip">I spent two weeks with the $99 Fitbit Air</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/exclusive-google-design-director-says-fitbit-air-reception-proves-they-made-the-right-decision-going-screen-free">Exclusive: Google design director says Fitbit Air reception proves they 'made the right decision'</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ watchOS 27 is live: 7 new features to try first on your Apple Watch ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple’s latest watchOS 27 software is officially out and available for free download, as long as you have a compatible Apple Watch (more on that below). The new operating system adds all sorts of new health and fitness features, AI tools, and usability improvements.</p><p>I’ve been exploring watchOS 27 all day — loaded up on my <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-vs-11-here-are-the-6-biggest-differences">Apple Watch Series 11</a> — and it’s a modest yet welcome improvement to watchOS 26. That said, there is one notable downside to upgrading. </p><p>Read on for everything you need to know about watchOS 27, including compatible models, installation steps, the seven coolest new features to try first, and more.</p><h2 id="which-apple-watches-support-watchos-27">Which Apple Watches support watchOS 27?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2659px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="FJQDmsv347vjHMZCoFxV4T" name="AppleWatchUltra3-v-Series11" alt="Apple Watch Ultra 3 and Apple Watch Series 11" src="https://cdn.mos.cms.futurecdn.net/FJQDmsv347vjHMZCoFxV4T-1920-80.jpg" mos="" align="middle" fullscreen="" width="2659" height="1496" 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>Apple is generally pretty good about supporting older Apple Watch models with new software. Unfortunately, this time around, the list of models compatible with watchOS 27 is frustratingly short. It includes the latest <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4</a> (duh), along with:</p><ul><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-se-3-review"><strong>Apple Watch SE 3</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/reviews/apple-watch-series-9"><strong>Apple Watch Series 9</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-10-review"><strong>Apple Watch Series 10</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review"><strong>Apple Watch Series 11</strong></a><strong></strong></li><li><strong></strong><a href=""><strong>Apple Watch Ultra 2</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review"><strong>Apple Watch Ultra 3</strong></a></li></ul><p>Most notably missing from the list is 2022’s original <a href="https://www.tomsguide.com/reviews/apple-watch-ultra-review">Apple Watch Ultra</a> model</p><h2 id="how-to-update-to-watchos-27">How to update to watchOS 27</h2><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="E4V5TXM7JJES5HMnDyTpcW" name="ios 27 photos" alt="iOS 27 logo and Photos logo on iPhone" src="https://cdn.mos.cms.futurecdn.net/E4V5TXM7JJES5HMnDyTpcW-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: Future / edited with Gemini )</span></figcaption></figure><p>To update your Apple Watch to watchOS 27, you’ll first need to update your paired iPhone to the latest <a href="https://www.tomsguide.com/phones/iphones/ios-27-is-live-heres-how-to-download-and-install-it-now">iOS 27 software</a>. After that, navigate to the <strong>Settings</strong> menu, either on your Apple Watch or via the Watch app for iPhone, and open <strong>General> Software Update</strong>. </p><p>You might need to reload the update screen a few times by swiping down, but an option to download the latest watchOS 27 should eventually appear. When it does, tap <strong>Download</strong>, punch in your passcode if prompted, accept the TOS, and wait…</p><p>Depending on your internet connection, the whole installation process could take up to several hours. One more thing: Ensure your Apple Watch is on its charger during the update process and keep your paired phone close. </p><h2 id="7-new-watchos-27-feature-to-try-first-on-apple-watch">7 new watchOS 27 feature to try first on Apple Watch</h2><p>With watchOS 27 up and running on your Apple Watch, now it's time for the fun part: exploring all the cool new features. Here's what I recommend checking out first.</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:2008px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="ZxC3rWauVZymkkhUsAUCNm" name="watchOS27-Siri" alt="Close-up of an iPhone and Apple Watch showing a continuous Siri AI conversation" src="https://cdn.mos.cms.futurecdn.net/ZxC3rWauVZymkkhUsAUCNm-1920-80.jpg" mos="" align="middle" fullscreen="" width="2008" height="1130" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p><strong>1. Siri AI with dedicated Siri app</strong></p><p>Ladies and gentlemen, a true-blue <a href="https://www.tomsguide.com/phones/i-asked-siri-ai-and-gemini-a-series-of-increasingly-bizarre-questions-to-see-how-they-responded-heres-what-happened">AI-powered Siri</a> is finally available on the Apple Watch. With watchOS 27, your Apple Watch now has a dedicated Siri AI app that supports a more conversational style of interaction. The voice is also more natural and expressive, making interactions feel less awkward.</p><p>Perhaps most importantly, Siri is now actually good at answering even complex, context-based questions. The question is, can Apple's on-wrist Siri AI compete with Google Gemini AI voice assistant (as found on the latest <a href="https://www.tomsguide.com/wellness/smartwatches/i-just-tried-the-new-google-pixel-watch-5-and-its-new-health-and-safety-features-blow-the-apple-watch-out-of-the-water">Pixel Watch 5</a>)? I look forward to testing both head-to-head in a coming article. </p><p><strong>2. The Dynamic App Grid</strong></p><p>Meet your new default home screen, the Dynamic App Grid. When you press the Digital Crown once, your Apple Watch will automatically display your five most frequently used and/or relevant apps, saving you the effort of scrolling around. As the name suggests, these update dynamically throughout the day.</p><p>But what if the app you want isn't one of those five? Simply swipe down/scroll to view the full app view.</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:1929px;"><p class="vanilla-image-block" style="padding-top:56.19%;"><img id="fVx5Kn8PkKaDbr3GegBTN9" name="watchOS27-dynamic" alt="The new Dynamic App Grid available in watchOS 27" src="https://cdn.mos.cms.futurecdn.net/fVx5Kn8PkKaDbr3GegBTN9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1929" height="1084" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p><strong>3. New Siri Modular watch face</strong></p><p>Apple's latest Siri Modular watch face is a personal favorite. Highly customizable, it automatically displays a complication for quick access to the most recently used widget in your Smart Stack. Best of all, this complication also updates dynamically. The new watch face additionally offers a complication to open the Siri app with a tap. </p><p>Of course, users can further customize the appearance of the Siri Modular watch face to their heart's delight with the complications and time format of their choosing.</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:2099px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="pnFNUdRrz7PEPDCCdJABf3" name="Apple Watch Series 9-9.jpg" alt="Apple Watch Series 9" src="https://cdn.mos.cms.futurecdn.net/pnFNUdRrz7PEPDCCdJABf3-1920-80.jpg" mos="" align="middle" fullscreen="" width="2099" height="1181" 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>4. Single-tap gesture control to open Smart Stack</strong></p><p>The latest watchOS 27 introduces a handy new way to open the Apple Watch's Smart Stack and select one of the dynamic widgets: The Single Tap gesture control. Apple launched the <a href="https://www.tomsguide.com/how-to/how-to-use-the-apple-watch-double-tap-gesture">Double Tap gesture</a> in 2026, where users press their index finger and thumb together twice on their watch-worn hand to perform an action, like answering a call.</p><p>The new Single Tap gesture works exactly the same way, minus the second tap. </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="W5QaBdWA6ZqoxGfUz3gDu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/W5QaBdWA6ZqoxGfUz3gDu4-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><strong>5. Call Context and Smart Stack suggestions</strong></p><p>Apple's AI-powered Siri shows up in more places than just the dedicated Siri app. For instance, two new features, Call Context and Smart Stack suggestions, use Siri to automatically surface relevant information on the watch display when it might be useful.</p><p>The Call Context feature is designed to display relevant details when brought up during a phone call. For example, if I casually mention an upcoming flight while chatting with my mom, Call Context <em>should</em> then show my itinerary on the Apple Watch screen for me to reference (stay tuned for testing). </p><p>Smart Suggestions, meanwhile, generates reminders in your Smart Stack for things you might otherwise overlook/miss, like a friend's birthday, a low balance on a transit card, changes to an upcoming flight departure, and more.</p><div><blockquote><p>One of my favorite watchOS 27 improvements is the updated Find My app, where people, objects, and devices are all consolidated into one easy-to-navigate map view.</p></blockquote></div><p><strong>6. New Find My app</strong></p><p>One of my favorite watchOS 27 improvements is the updated Find My app, where people, objects, and devices are all consolidated into one easy-to-navigate map view. </p><p>I love to travel and use AirTags to keep tabs on all my luggage and bags. Now, instead of having to pull out my phone to make sure that my suitcase <em>actually</em> made it back home to Seattle and isn't still chilling in Amsterdam, I simply need to tap on my Apple Watch a few times and glance down at my wrist.</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:1024px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="FZSAaveAqhusQheKPr3rLi" name="Apple watch treadmill.jpg" alt="a photo of the Apple Watch 7 recording a treadmill workout" src="https://cdn.mos.cms.futurecdn.net/FZSAaveAqhusQheKPr3rLi-1920-80.jpg" mos="" align="middle" fullscreen="" width="1024" height="576" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future/Tom's Guide)</span></figcaption></figure><p><strong>7.  Improved indoor workout tracking </strong></p><p>Last but not least, workout tracking accuracy for indoor activities like walking and running should be improved with the latest watchOS 27 release. While I'm not much of a treadmill guy — I prefer to walk and run outdoors, weather be damned — you can count on us fully testing these claims in the coming weeks. </p><p>As a big fan of Apple's overall approach to on-wrist fitness tracking, any accuracy improvements are welcomed with open arms. </p><p>Now, if only Apple would provide individual step counts for logged workouts...</p><h3 class="article-body__section" id="section-watchos-27-goodbye-walkie-talkie-app"><span>watchOS 27: Goodbye Walkie-talkie app</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="XFPYYtuu56baJGNJYLkSf6" name="Apple Watch walkie talkie iPhone 15-2.jpg" alt="Apple watch walkie-talkie feature" src="https://cdn.mos.cms.futurecdn.net/XFPYYtuu56baJGNJYLkSf6-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>With the good comes the bad. While watchOS 27 is brimming with a lot of cool, new features and design improvements, Apple sadly killed off one fan-favorite app in the latest release: the <a href="https://www.tomsguide.com/wellness/smartwatches/how-to-use-apple-watch-walkie-talkie-mode">Walkie-Talkie app</a> for Apple Watch.</p><p>What are your thoughts on the new watchOS 27 software, and what features are you most excited to try? Let me know in the comments below. </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/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model"><strong>Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4"><strong>I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/watchos-27-is-live-7-new-features-to-try-first-on-your-apple-watch</link>
                                                                            <description>
                            <![CDATA[ watchOS 27 is officially live and available for download; I've spent all day testing it, and these are the coolest new features you should try first. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">yKb2zvG6Rfz2yv5jpjA9Nk</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/tmTqEW3THAbP2y2vpwpron-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 15 Sep 2026 04:30:00 +0000</pubDate>                                                                                                                                <updated>Tue, 15 Sep 2026 08:15:56 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/tmTqEW3THAbP2y2vpwpron-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Apple Watch 11 running the latest watchOS 27 software]]></media:description>                                                            <media:text><![CDATA[Close-up of the Apple Watch 11 running the latest watchOS 27 software]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Apple Watch 11 running the latest watchOS 27 software]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/tmTqEW3THAbP2y2vpwpron-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple’s latest watchOS 27 software is officially out and available for free download, as long as you have a compatible Apple Watch (more on that below). The new operating system adds all sorts of new health and fitness features, AI tools, and usability improvements.</p><p>I’ve been exploring watchOS 27 all day — loaded up on my <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-vs-11-here-are-the-6-biggest-differences">Apple Watch Series 11</a> — and it’s a modest yet welcome improvement to watchOS 26. That said, there is one notable downside to upgrading. </p><p>Read on for everything you need to know about watchOS 27, including compatible models, installation steps, the seven coolest new features to try first, and more.</p><h2 id="which-apple-watches-support-watchos-27">Which Apple Watches support watchOS 27?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2659px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="FJQDmsv347vjHMZCoFxV4T" name="AppleWatchUltra3-v-Series11" alt="Apple Watch Ultra 3 and Apple Watch Series 11" src="https://cdn.mos.cms.futurecdn.net/FJQDmsv347vjHMZCoFxV4T-1920-80.jpg" mos="" align="middle" fullscreen="" width="2659" height="1496" 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>Apple is generally pretty good about supporting older Apple Watch models with new software. Unfortunately, this time around, the list of models compatible with watchOS 27 is frustratingly short. It includes the latest <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4</a> (duh), along with:</p><ul><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-se-3-review"><strong>Apple Watch SE 3</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/reviews/apple-watch-series-9"><strong>Apple Watch Series 9</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-10-review"><strong>Apple Watch Series 10</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review"><strong>Apple Watch Series 11</strong></a><strong></strong></li><li><strong></strong><a href=""><strong>Apple Watch Ultra 2</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review"><strong>Apple Watch Ultra 3</strong></a></li></ul><p>Most notably missing from the list is 2022’s original <a href="https://www.tomsguide.com/reviews/apple-watch-ultra-review">Apple Watch Ultra</a> model</p><h2 id="how-to-update-to-watchos-27">How to update to watchOS 27</h2><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="E4V5TXM7JJES5HMnDyTpcW" name="ios 27 photos" alt="iOS 27 logo and Photos logo on iPhone" src="https://cdn.mos.cms.futurecdn.net/E4V5TXM7JJES5HMnDyTpcW-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: Future / edited with Gemini )</span></figcaption></figure><p>To update your Apple Watch to watchOS 27, you’ll first need to update your paired iPhone to the latest <a href="https://www.tomsguide.com/phones/iphones/ios-27-is-live-heres-how-to-download-and-install-it-now">iOS 27 software</a>. After that, navigate to the <strong>Settings</strong> menu, either on your Apple Watch or via the Watch app for iPhone, and open <strong>General> Software Update</strong>. </p><p>You might need to reload the update screen a few times by swiping down, but an option to download the latest watchOS 27 should eventually appear. When it does, tap <strong>Download</strong>, punch in your passcode if prompted, accept the TOS, and wait…</p><p>Depending on your internet connection, the whole installation process could take up to several hours. One more thing: Ensure your Apple Watch is on its charger during the update process and keep your paired phone close. </p><h2 id="7-new-watchos-27-feature-to-try-first-on-apple-watch">7 new watchOS 27 feature to try first on Apple Watch</h2><p>With watchOS 27 up and running on your Apple Watch, now it's time for the fun part: exploring all the cool new features. Here's what I recommend checking out first.</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:2008px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="ZxC3rWauVZymkkhUsAUCNm" name="watchOS27-Siri" alt="Close-up of an iPhone and Apple Watch showing a continuous Siri AI conversation" src="https://cdn.mos.cms.futurecdn.net/ZxC3rWauVZymkkhUsAUCNm-1920-80.jpg" mos="" align="middle" fullscreen="" width="2008" height="1130" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p><strong>1. Siri AI with dedicated Siri app</strong></p><p>Ladies and gentlemen, a true-blue <a href="https://www.tomsguide.com/phones/i-asked-siri-ai-and-gemini-a-series-of-increasingly-bizarre-questions-to-see-how-they-responded-heres-what-happened">AI-powered Siri</a> is finally available on the Apple Watch. With watchOS 27, your Apple Watch now has a dedicated Siri AI app that supports a more conversational style of interaction. The voice is also more natural and expressive, making interactions feel less awkward.</p><p>Perhaps most importantly, Siri is now actually good at answering even complex, context-based questions. The question is, can Apple's on-wrist Siri AI compete with Google Gemini AI voice assistant (as found on the latest <a href="https://www.tomsguide.com/wellness/smartwatches/i-just-tried-the-new-google-pixel-watch-5-and-its-new-health-and-safety-features-blow-the-apple-watch-out-of-the-water">Pixel Watch 5</a>)? I look forward to testing both head-to-head in a coming article. </p><p><strong>2. The Dynamic App Grid</strong></p><p>Meet your new default home screen, the Dynamic App Grid. When you press the Digital Crown once, your Apple Watch will automatically display your five most frequently used and/or relevant apps, saving you the effort of scrolling around. As the name suggests, these update dynamically throughout the day.</p><p>But what if the app you want isn't one of those five? Simply swipe down/scroll to view the full app view.</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:1929px;"><p class="vanilla-image-block" style="padding-top:56.19%;"><img id="fVx5Kn8PkKaDbr3GegBTN9" name="watchOS27-dynamic" alt="The new Dynamic App Grid available in watchOS 27" src="https://cdn.mos.cms.futurecdn.net/fVx5Kn8PkKaDbr3GegBTN9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1929" height="1084" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p><strong>3. New Siri Modular watch face</strong></p><p>Apple's latest Siri Modular watch face is a personal favorite. Highly customizable, it automatically displays a complication for quick access to the most recently used widget in your Smart Stack. Best of all, this complication also updates dynamically. The new watch face additionally offers a complication to open the Siri app with a tap. </p><p>Of course, users can further customize the appearance of the Siri Modular watch face to their heart's delight with the complications and time format of their choosing.</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:2099px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="pnFNUdRrz7PEPDCCdJABf3" name="Apple Watch Series 9-9.jpg" alt="Apple Watch Series 9" src="https://cdn.mos.cms.futurecdn.net/pnFNUdRrz7PEPDCCdJABf3-1920-80.jpg" mos="" align="middle" fullscreen="" width="2099" height="1181" 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>4. Single-tap gesture control to open Smart Stack</strong></p><p>The latest watchOS 27 introduces a handy new way to open the Apple Watch's Smart Stack and select one of the dynamic widgets: The Single Tap gesture control. Apple launched the <a href="https://www.tomsguide.com/how-to/how-to-use-the-apple-watch-double-tap-gesture">Double Tap gesture</a> in 2026, where users press their index finger and thumb together twice on their watch-worn hand to perform an action, like answering a call.</p><p>The new Single Tap gesture works exactly the same way, minus the second tap. </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="W5QaBdWA6ZqoxGfUz3gDu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/W5QaBdWA6ZqoxGfUz3gDu4-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><strong>5. Call Context and Smart Stack suggestions</strong></p><p>Apple's AI-powered Siri shows up in more places than just the dedicated Siri app. For instance, two new features, Call Context and Smart Stack suggestions, use Siri to automatically surface relevant information on the watch display when it might be useful.</p><p>The Call Context feature is designed to display relevant details when brought up during a phone call. For example, if I casually mention an upcoming flight while chatting with my mom, Call Context <em>should</em> then show my itinerary on the Apple Watch screen for me to reference (stay tuned for testing). </p><p>Smart Suggestions, meanwhile, generates reminders in your Smart Stack for things you might otherwise overlook/miss, like a friend's birthday, a low balance on a transit card, changes to an upcoming flight departure, and more.</p><div><blockquote><p>One of my favorite watchOS 27 improvements is the updated Find My app, where people, objects, and devices are all consolidated into one easy-to-navigate map view.</p></blockquote></div><p><strong>6. New Find My app</strong></p><p>One of my favorite watchOS 27 improvements is the updated Find My app, where people, objects, and devices are all consolidated into one easy-to-navigate map view. </p><p>I love to travel and use AirTags to keep tabs on all my luggage and bags. Now, instead of having to pull out my phone to make sure that my suitcase <em>actually</em> made it back home to Seattle and isn't still chilling in Amsterdam, I simply need to tap on my Apple Watch a few times and glance down at my wrist.</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:1024px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="FZSAaveAqhusQheKPr3rLi" name="Apple watch treadmill.jpg" alt="a photo of the Apple Watch 7 recording a treadmill workout" src="https://cdn.mos.cms.futurecdn.net/FZSAaveAqhusQheKPr3rLi-1920-80.jpg" mos="" align="middle" fullscreen="" width="1024" height="576" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future/Tom's Guide)</span></figcaption></figure><p><strong>7.  Improved indoor workout tracking </strong></p><p>Last but not least, workout tracking accuracy for indoor activities like walking and running should be improved with the latest watchOS 27 release. While I'm not much of a treadmill guy — I prefer to walk and run outdoors, weather be damned — you can count on us fully testing these claims in the coming weeks. </p><p>As a big fan of Apple's overall approach to on-wrist fitness tracking, any accuracy improvements are welcomed with open arms. </p><p>Now, if only Apple would provide individual step counts for logged workouts...</p><h3 class="article-body__section" id="section-watchos-27-goodbye-walkie-talkie-app"><span>watchOS 27: Goodbye Walkie-talkie app</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="XFPYYtuu56baJGNJYLkSf6" name="Apple Watch walkie talkie iPhone 15-2.jpg" alt="Apple watch walkie-talkie feature" src="https://cdn.mos.cms.futurecdn.net/XFPYYtuu56baJGNJYLkSf6-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>With the good comes the bad. While watchOS 27 is brimming with a lot of cool, new features and design improvements, Apple sadly killed off one fan-favorite app in the latest release: the <a href="https://www.tomsguide.com/wellness/smartwatches/how-to-use-apple-watch-walkie-talkie-mode">Walkie-Talkie app</a> for Apple Watch.</p><p>What are your thoughts on the new watchOS 27 software, and what features are you most excited to try? Let me know in the comments below. </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/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model"><strong>Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4"><strong>I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ It wasn’t till I ran at 5 am in Cupertino that I realized this key feature was missing from the Apple Watch Ultra 4 ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Like many female runners, I tend to avoid running in the dark, especially at 5 am. Yet, unlike a lot of tech journalists, I found myself needing to sneak in a marathon training session before Apple’s keynote last week. As I woke up at 5 am to meet a fellow running-mad colleague, I noticed one pretty key feature missing from the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4 </a>— a flashlight. </p><p>Sure, the Apple Watch Ultra 4 has a flashlight that’ll allow you to stumble to the bathroom in the dark or plug your charger in without waking anyone else up, but unlike my friend’s <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor">Garmin Fenix 9 Pro</a>, it’s not all that helpful in workout modes. </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="HsEvn6zkCC3qyFB7uE4uB7" name="Garmin Fenix 9 Pro flashlight" alt="Garmin Fenix 9 Pro flashlight" src="https://cdn.mos.cms.futurecdn.net/HsEvn6zkCC3qyFB7uE4uB7-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’s one key difference between the flashlights on the two watches — the Apple Watch Ultra 4, like the Apple Watch Ultra 3 I had on my wrist, only lights up the screen. The Garmin Fenix 9 Pro, on the other hand, has a dedicated physical LED flashlight built into the watch housing. This was amazingly effective when lighting our way in the pitch-black on the San Francisco Bay Trail. </p><p>In an attempt to add to our visibility, I switched the flashlight on, but it wasn’t all that helpful, and unlike my colleague’s Garmin, I couldn't see my workout stats with the flashlight on. </p><p>Of course, this isn’t a problem I’ll encounter all that often, but it is one worth mentioning if you are deciding between the Apple Watch Ultra 4 and the Garmin Fenix 9 Pro for an outdoor adventure. While the Apple Watch Ultra 4 offers far greater smartwatch capabilities, if you find yourself, like I did, training in the dark, you’ll probably want the Fenix 9 (or the Fenix 8, <a href="https://www.tomsguide.com/reviews/garmin-epix-pro">Epix Pro</a>, or <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-garmin-forerunner-970-for-six-months-here-are-my-long-term-pros-and-cons">Forerunner 970</a>) on your wrist. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-exg9aX"></div>                            </div>                            <script src="https://kwizly.com/embed/exg9aX.js" async></script><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OaLdGW"></div>                            </div>                            <script src="https://kwizly.com/embed/OaLdGW.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/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12"><strong>Apple Watch Series 12 hands-on: A new heart rate sensor and a readiness score (at last)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained"><strong>Apple Watch Ultra 4 is official: All the upgrades explained</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/it-wasnt-till-i-ran-at-5-am-in-cupertino-that-i-realized-this-key-feature-was-missing-from-the-apple-watch-ultra-4</link>
                                                                            <description>
                            <![CDATA[ Here's one feature I wish the Apple Watch Ultra 4 had on board. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">ZMhN7dXy7q9XPNRekv36Sk</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 14 Sep 2026 06:15:00 +0000</pubDate>                                                                                                                                <updated>Mon, 14 Sep 2026 08:47:18 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></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/AYP57Su3Eno7XWdwUbPfJj-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Ultra 4]]></media:description>                                                            <media:text><![CDATA[Apple Watch Ultra 4]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Ultra 4]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Like many female runners, I tend to avoid running in the dark, especially at 5 am. Yet, unlike a lot of tech journalists, I found myself needing to sneak in a marathon training session before Apple’s keynote last week. As I woke up at 5 am to meet a fellow running-mad colleague, I noticed one pretty key feature missing from the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4 </a>— a flashlight. </p><p>Sure, the Apple Watch Ultra 4 has a flashlight that’ll allow you to stumble to the bathroom in the dark or plug your charger in without waking anyone else up, but unlike my friend’s <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor">Garmin Fenix 9 Pro</a>, it’s not all that helpful in workout modes. </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="HsEvn6zkCC3qyFB7uE4uB7" name="Garmin Fenix 9 Pro flashlight" alt="Garmin Fenix 9 Pro flashlight" src="https://cdn.mos.cms.futurecdn.net/HsEvn6zkCC3qyFB7uE4uB7-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’s one key difference between the flashlights on the two watches — the Apple Watch Ultra 4, like the Apple Watch Ultra 3 I had on my wrist, only lights up the screen. The Garmin Fenix 9 Pro, on the other hand, has a dedicated physical LED flashlight built into the watch housing. This was amazingly effective when lighting our way in the pitch-black on the San Francisco Bay Trail. </p><p>In an attempt to add to our visibility, I switched the flashlight on, but it wasn’t all that helpful, and unlike my colleague’s Garmin, I couldn't see my workout stats with the flashlight on. </p><p>Of course, this isn’t a problem I’ll encounter all that often, but it is one worth mentioning if you are deciding between the Apple Watch Ultra 4 and the Garmin Fenix 9 Pro for an outdoor adventure. While the Apple Watch Ultra 4 offers far greater smartwatch capabilities, if you find yourself, like I did, training in the dark, you’ll probably want the Fenix 9 (or the Fenix 8, <a href="https://www.tomsguide.com/reviews/garmin-epix-pro">Epix Pro</a>, or <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-garmin-forerunner-970-for-six-months-here-are-my-long-term-pros-and-cons">Forerunner 970</a>) on your wrist. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-exg9aX"></div>                            </div>                            <script src="https://kwizly.com/embed/exg9aX.js" async></script><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OaLdGW"></div>                            </div>                            <script src="https://kwizly.com/embed/OaLdGW.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/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12"><strong>Apple Watch Series 12 hands-on: A new heart rate sensor and a readiness score (at last)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained"><strong>Apple Watch Ultra 4 is official: All the upgrades explained</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’m a smartwatch reviewer: This is the new Apple Watch 12 feature I’m most excited for ]]></title>
                                                                                                <dc:content><![CDATA[ <p>If you’re like me and sometimes struggle to remember names and other small bits of information on the fly, despite your best attempts, this article is for you. </p><p>At best, this shortcoming can lead to awkwardness; at worst, utter embarrassment. But what if some magical bit of tech solved this issue once and for all? Enter: Apple’s new Live Rewind feature for the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4</a>.</p><p>I’ve long dreamed of being important/wealthy enough to have a team of assistants that follow me around, whispering crucial details in my ear before I need them… like names of acquaintances. Unfortunately, rather than pursuing a career in politics or entertainment, my calling was journalism, an occupation where you’re very much your own assistant (and editor, photographer, etc.). </p><p>No worries; Apple has my back. Here’s why I’m super-excited to try out the Live Rewind <a href="https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained">Audio Intelligence feature</a> on the new Apple Watch 12 and Apple Watch Ultra 4. </p><h3 class="article-body__section" id="section-at-last-a-smartwatch-feature-for-the-short-term-memory-challenged"><span>At last, a smartwatch feature for the short-term memory-challenged </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="H4nJDVCkJRhdcJkJh9Hiv4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/H4nJDVCkJRhdcJkJh9Hiv4-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 whole concept behind Live Rewind is to allow users to easily and discreetly relisten to short snippets of conversations they may have missed, immediately after-the-fact. When active, Live Rewind continuously records the past 15 seconds of ambient sound from your wrist. </p><p>When you want to rewind and listen in on something that was just said, you simply need to double-tap the digital crown and hold your smartwatch to your ear (or simply listen if you’re wearing paired Bluetooth headphones). </p><p>Not only do I see this feature being useful when meeting new people and trying to remember names, but also in the presence of fast-talking servers at restaurants, when asking for directions from strangers, or when trying to recall book/movie/TV recommendations from friends. </p><h3 class="article-body__section" id="section-how-does-live-rewind-actually-work"><span>How does Live Rewind actually work?  </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="8bcbHKT8rtMP46JqtdXmRN" name="Apple Event — September 9 47-49 screenshot" alt="Live Rewind on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/8bcbHKT8rtMP46JqtdXmRN-1920-80.png" 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: Apple)</span></figcaption></figure><p>How exactly does Live Rewind on the Apple Watch work? The Apple Watch Series 12 and Apple Watch Ultra 4 sport an upgraded S11 processor, which unlocks the ability to continually buffer up to 15 seconds of audio capture, day and night. </p><p>In addition to being able to play back 15 seconds of audio at a moment’s notice, the feature can generate a transcription of the audio — something I appreciate as a visual learner — as well. Users can even save said transcription for later. </p><h3 class="article-body__section" id="section-privacy-isn-t-an-afterthought"><span>Privacy isn’t an afterthought </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="AYP57Su3Eno7XWdwUbPfJj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-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 idea of having your smartwatch continuously record your surroundings 24/7 might seem a bit unsettling, and frankly, it is. However, Cupertino has put several actions in place to guarantee the privacy of anyone recorded by the latest <a href="https://www.tomsguide.com/ai/apple-intelligence/people-are-freaking-out-about-the-new-always-listening-apple-watches-heres-what-apple-ceo-john-ternus-told-us">Audio Intelligence tools</a>.</p><p>For starters, the latest Apple Watches don’t actually save any audio files, on the device or in the cloud. Every 15 seconds of buffered audio is continuously replaced by new audio. Furthermore, the feature never identifies individual speakers (for better or worse). Finally, all the data used for this feature is encrypted end-to-end. </p><p>So, what are your thoughts on Apple’s new Live Rewind feature for the Apple Watch 12 and Apple Watch Ultra 4? Is this something you might benefit from? Do you have any hesitations? Let me know in the comments. </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/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model"><strong>Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4"><strong>I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/im-a-smartwatch-reviewer-this-is-the-new-apple-watch-12-feature-im-most-excited-for</link>
                                                                            <description>
                            <![CDATA[ As a sometimes forgetful guy, the new Live Rewind feature for the Apple Watch Series 12 and Apple Watch Ultra 4 could be a game changer. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">MgXBW5HGWMSXNdf6v9SLbS</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/m4WYYb9cwZa49jDrhG22RE-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 13 Sep 2026 05:00:00 +0000</pubDate>                                                                                                                                <updated>Sun, 13 Sep 2026 12:31:19 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/m4WYYb9cwZa49jDrhG22RE-1920-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Apple Watch Series 12 on a user&#039;s wrist at the Cupertino launch event on September 10, 2026]]></media:description>                                                            <media:text><![CDATA[Close-up of the Apple Watch Series 12 on a user&#039;s wrist at the Cupertino launch event on September 10, 2026]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Apple Watch Series 12 on a user&#039;s wrist at the Cupertino launch event on September 10, 2026]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/m4WYYb9cwZa49jDrhG22RE-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>If you’re like me and sometimes struggle to remember names and other small bits of information on the fly, despite your best attempts, this article is for you. </p><p>At best, this shortcoming can lead to awkwardness; at worst, utter embarrassment. But what if some magical bit of tech solved this issue once and for all? Enter: Apple’s new Live Rewind feature for the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4</a>.</p><p>I’ve long dreamed of being important/wealthy enough to have a team of assistants that follow me around, whispering crucial details in my ear before I need them… like names of acquaintances. Unfortunately, rather than pursuing a career in politics or entertainment, my calling was journalism, an occupation where you’re very much your own assistant (and editor, photographer, etc.). </p><p>No worries; Apple has my back. Here’s why I’m super-excited to try out the Live Rewind <a href="https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained">Audio Intelligence feature</a> on the new Apple Watch 12 and Apple Watch Ultra 4. </p><h3 class="article-body__section" id="section-at-last-a-smartwatch-feature-for-the-short-term-memory-challenged"><span>At last, a smartwatch feature for the short-term memory-challenged </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="H4nJDVCkJRhdcJkJh9Hiv4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/H4nJDVCkJRhdcJkJh9Hiv4-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 whole concept behind Live Rewind is to allow users to easily and discreetly relisten to short snippets of conversations they may have missed, immediately after-the-fact. When active, Live Rewind continuously records the past 15 seconds of ambient sound from your wrist. </p><p>When you want to rewind and listen in on something that was just said, you simply need to double-tap the digital crown and hold your smartwatch to your ear (or simply listen if you’re wearing paired Bluetooth headphones). </p><p>Not only do I see this feature being useful when meeting new people and trying to remember names, but also in the presence of fast-talking servers at restaurants, when asking for directions from strangers, or when trying to recall book/movie/TV recommendations from friends. </p><h3 class="article-body__section" id="section-how-does-live-rewind-actually-work"><span>How does Live Rewind actually work?  </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="8bcbHKT8rtMP46JqtdXmRN" name="Apple Event — September 9 47-49 screenshot" alt="Live Rewind on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/8bcbHKT8rtMP46JqtdXmRN-1920-80.png" 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: Apple)</span></figcaption></figure><p>How exactly does Live Rewind on the Apple Watch work? The Apple Watch Series 12 and Apple Watch Ultra 4 sport an upgraded S11 processor, which unlocks the ability to continually buffer up to 15 seconds of audio capture, day and night. </p><p>In addition to being able to play back 15 seconds of audio at a moment’s notice, the feature can generate a transcription of the audio — something I appreciate as a visual learner — as well. Users can even save said transcription for later. </p><h3 class="article-body__section" id="section-privacy-isn-t-an-afterthought"><span>Privacy isn’t an afterthought </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="AYP57Su3Eno7XWdwUbPfJj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-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 idea of having your smartwatch continuously record your surroundings 24/7 might seem a bit unsettling, and frankly, it is. However, Cupertino has put several actions in place to guarantee the privacy of anyone recorded by the latest <a href="https://www.tomsguide.com/ai/apple-intelligence/people-are-freaking-out-about-the-new-always-listening-apple-watches-heres-what-apple-ceo-john-ternus-told-us">Audio Intelligence tools</a>.</p><p>For starters, the latest Apple Watches don’t actually save any audio files, on the device or in the cloud. Every 15 seconds of buffered audio is continuously replaced by new audio. Furthermore, the feature never identifies individual speakers (for better or worse). Finally, all the data used for this feature is encrypted end-to-end. </p><p>So, what are your thoughts on Apple’s new Live Rewind feature for the Apple Watch 12 and Apple Watch Ultra 4? Is this something you might benefit from? Do you have any hesitations? Let me know in the comments. </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/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model"><strong>Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4"><strong>I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I walked 29,000 steps with the Garmin Cirqa in Berlin — 5 things I learned along the way ]]></title>
                                                                                                <dc:content><![CDATA[ <p>One of my favorite aspects of being a technology journalist is getting to cover the debut of exciting new products at events like the Consumer Electronics Show (CES) in Las Vegas, Mobile World Congress (MWC) in Barcelona, and most recently the Internationale Funkausstellung show, aka Innovation for All (IFA) in Berlin.</p><p>With no shortage of ground to cover at each of these tech conferences, I’ve made a habit of treating each day as a marathon of sorts, tracking my stats via one of the <a href="https://www.tomsguide.com/us/best-fitness-trackers,review-2066.html">best fitness trackers</a> or <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">top smartwatches</a> I can find. </p><p>For <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA 2026</a>, I opted to log my efforts using the new <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-garmin-cirqa-and-it-strikes-a-near-perfect-balance-between-the-fitbit-air-and-whoop-5-0">Garmin Cirqa</a>, a screen-free tracker that’s comfortable, long-lasting, and discreet. Ultimately, it proved to be a competent wearable for the task, with one notable exception (more on that below).</p><p>With that said, here are the five biggest takeaways from logging my steps at IFA 2026 on the Garmin Cirqa. </p><h3 class="article-body__section" id="section-i-logged-28k-steps-at-ifa-in-berlin-on-the-garmin-cirqa"><span>I logged 28k steps at IFA in Berlin on the Garmin Cirqa </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:1600px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="V8844e2pjd6QVLUUoh9FBn" name="ifa-lede-3" alt="A wide shot of Messe Berlin with an IFA 2026 badge" src="https://cdn.mos.cms.futurecdn.net/V8844e2pjd6QVLUUoh9FBn-1920-80.jpg" mos="" align="middle" fullscreen="" width="1600" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: IFA)</span></figcaption></figure><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Day 1</p></th><th  ><p>Day 2</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Steps</strong></p></td><td  ><p>17,902 steps</p></td><td  ><p>10,628 steps</p></td></tr><tr><td class="firstcol " ><p><strong>Average heart rate</strong></p></td><td  ><p>111 bpm</p></td><td  ><p>117 bpm</p></td></tr><tr><td class="firstcol " ><p><strong>Max heart rate</strong></p></td><td  ><p>151 bpm</p></td><td  ><p>148 bpm</p></td></tr><tr><td class="firstcol " ><p><strong>Calories burned (total)</strong></p></td><td  ><p>2,407 calories </p></td><td  ><p>1,121 calories</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-1-i-covered-way-more-ground-than-expected-especially-on-day-1"><span>1. I covered way more ground than expected, especially on day 1</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="TrVGT7FHzWykpwioYKi8yn" name="Luna-Cirqa-01" alt="Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/TrVGT7FHzWykpwioYKi8yn-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>Much to my surprise, I walked nearly 18,000 steps on my first day of IFA, which was technically a day before the show opened to the public (the press tends to get early access). </p><p>To be fair, the Berlin Messe is an absolutely sprawling conference complex, with no shortage of seemingly secret passages and tucked-away halls that are easy to stumble upon by accident but virtually impossible to find again when you’re <em>actually</em> looking for them.</p><p>This partially explains why my day one step count was so much higher than day two: I spent considerable time on the ground day one simply trying to get a lay of the land (in an admittedly very jet-lagged state). Day two, I had meetings scattered throughout the complex, and I didn’t want to be wandering around like a ding-dong.  </p><h3 class="article-body__section" id="section-2-i-logged-more-steps-on-day-1-of-ifa-than-any-single-day-covering-mwc"><span>2. I logged more steps on day 1 of IFA than any single day covering MWC</span></h3><p>At 17,902 steps, my day one of IFA coverage in Berlin beat my step count for any individual day of coverage at <a href="https://www.tomsguide.com/wellness/fitness/i-logged-37-miles-at-mwc-2026-on-my-garmin-instinct-3-here-are-5-things-i-learned">Mobile World Congress</a> in Barcelona back in March. That said, I spent a total of five days covering MWC compared to just two days covering IFA, for a total step count of 67,398 steps in Spain.</p><h3 class="article-body__section" id="section-3-but-ces-day-1-was-more-intense-than-both"><span>3. But CES day 1 was more intense than both</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="mnJPLoccAQFvxdEkQvxUQU" name="GarminCirqa-rev-02" alt="Close-up of the Garmin Cirqa on a user's wrist against a red background" src="https://cdn.mos.cms.futurecdn.net/mnJPLoccAQFvxdEkQvxUQU-1920-80.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>While day one of IFA may have been a leg-burner, it falls a bit short of my total step count from day one of the <a href="https://www.tomsguide.com/wellness/smartwatches/i-walked-65-000-steps-with-the-garmin-venu-4-5-things-i-learned">Consumer Electronics Show</a> held in Las Vegas back in early January, where I logged a dog-barking 20,253 steps, more than double my everyday average back home. </p><p>Then again, as anyone who has been to CES likely knows, things are very spread out in Las Vegas, which also just might be the least pedestrian-friendly city in the U.S... want to cross the street? You'll need to walk another half-mile down the strip and wander through multiple casinos to do so.</p><h3 class="article-body__section" id="section-4-commuting-on-the-u-bahn-seemingly-skewed-garmin-s-distance-and-pace-data"><span>4. Commuting on the U-Bahn seemingly skewed Garmin's distance and pace data</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:5025px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="J8gQGtirDrYBxfay2N35UX" name="Garmin Cirqa" alt="Garmin Cirqa" src="https://cdn.mos.cms.futurecdn.net/J8gQGtirDrYBxfay2N35UX-1920-80.jpg" mos="" align="middle" fullscreen="" width="5025" height="2827" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I didn’t include my distance or pace totals in the table above because it’s clear these figures are skewed. Both days of the show, I fired up a walking workout in the Cirqa upon leaving my hotel, trekked about half a mile to the nearest U-Bahn station — I am a nerd for experiencing public rail transit in new cities — and rode the metro roughly two miles to the show grounds. </p><p>Unfortunately, the Garmin Cirqa clearly interpreted this time spent riding the train as me moving at near-superhuman speed. For example, my average moving pace on day one of the show, according to Garmin, was 8 mins 41 secs per mile. Sure, I can maintain that pace when running a mile, but covering a trade show? Def not. </p><p>Garmin also said I walked 14.14 miles on day one, which would equal 1,266 steps per mile, way less than what I normally average, which is closer to 2,000 steps per mile. </p><h3 class="article-body__section" id="section-5-i-mostly-forgot-the-garmin-cirqa-was-even-there-but-might-not-wear-it-again"><span>5. I mostly forgot the Garmin Cirqa was even there, but might not wear it again</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:5144px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="Rr535PFKqQMmtZpT74z88e" name="GarminCirqa-03" alt="Close-up of the Garmin Cirqa screen-free fitness tracker" src="https://cdn.mos.cms.futurecdn.net/Rr535PFKqQMmtZpT74z88e-1920-80.jpg" mos="" align="middle" fullscreen="" width="5144" height="2893" 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>Ultimately, I opted to wear the Garmin Cirqa for two primary reasons. First, it’s comfortable and lightweight, so much so that I pretty much forgot it was even there. Second, I wanted to wear a mechanical watch on my left wrist to keep a constant eye on time; the nine-hour time difference between Seattle (where I live) and Berlin was my main rationale (also, I got a cool new watch I wanted to show off). </p><p>So, will I be wearing the Garmin Cirqa the next time I cover a major tech show? Honestly, probably not. While I appreciate how wrist-friendly it is, the lack of GPS means it has to piggyback off my smartphone’s signal, which isn’t necessarily ideal. Moreover, I’d rather opt for a wearable that’s capable of discerning time spent walking from time spent riding a subway. </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/smartwatches/i-biked-11-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-ultra-2-and-the-winner-is-clear"><strong>I biked 11 miles with the Garmin Instinct 3 vs Samsung Galaxy Watch Ultra 2 — and the winner is clear</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-walked-4-000-steps-with-the-pixel-watch-5-vs-samsung-galaxy-watch-9-and-we-have-a-new-android-champ"><strong>I walked 4,000 steps with the Pixel Watch 5 vs Samsung Galaxy Watch 9 — and we have a new Android champ</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-walked-7-miles-with-the-apple-watch-ultra-3-vs-pixel-watch-5-and-the-winner-is-nearly-too-close-to-call"><strong>I walked 7 miles with the Apple Watch Ultra 3 vs Pixel Watch 5 — here's the winner</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness-trackers/i-walked-29-000-steps-with-the-garmin-cirqa-in-berlin-5-things-i-learned-along-the-way</link>
                                                                            <description>
                            <![CDATA[ I logged my time covering the IFA tech show in Berlin using the new Garmin Cirqa screen-free fitness tracker. Here's what it did well and where it came up short. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">QHwqfVQwSFrpRdwkqY7RAY</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/sg3JXoV6C6r56Fnc9YzB6X-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 12 Sep 2026 11:30:00 +0000</pubDate>                                                                                                                                <updated>Sun, 13 Sep 2026 22:40:12 +0000</updated>
                                                                                                                                            <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Smartwatches]]></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/sg3JXoV6C6r56Fnc9YzB6X-1920-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Garmin Cirqa]]></media:description>                                                            <media:text><![CDATA[Garmin Cirqa]]></media:text>
                                <media:title type="plain"><![CDATA[Garmin Cirqa]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/sg3JXoV6C6r56Fnc9YzB6X-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>One of my favorite aspects of being a technology journalist is getting to cover the debut of exciting new products at events like the Consumer Electronics Show (CES) in Las Vegas, Mobile World Congress (MWC) in Barcelona, and most recently the Internationale Funkausstellung show, aka Innovation for All (IFA) in Berlin.</p><p>With no shortage of ground to cover at each of these tech conferences, I’ve made a habit of treating each day as a marathon of sorts, tracking my stats via one of the <a href="https://www.tomsguide.com/us/best-fitness-trackers,review-2066.html">best fitness trackers</a> or <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">top smartwatches</a> I can find. </p><p>For <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA 2026</a>, I opted to log my efforts using the new <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-garmin-cirqa-and-it-strikes-a-near-perfect-balance-between-the-fitbit-air-and-whoop-5-0">Garmin Cirqa</a>, a screen-free tracker that’s comfortable, long-lasting, and discreet. Ultimately, it proved to be a competent wearable for the task, with one notable exception (more on that below).</p><p>With that said, here are the five biggest takeaways from logging my steps at IFA 2026 on the Garmin Cirqa. </p><h3 class="article-body__section" id="section-i-logged-28k-steps-at-ifa-in-berlin-on-the-garmin-cirqa"><span>I logged 28k steps at IFA in Berlin on the Garmin Cirqa </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:1600px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="V8844e2pjd6QVLUUoh9FBn" name="ifa-lede-3" alt="A wide shot of Messe Berlin with an IFA 2026 badge" src="https://cdn.mos.cms.futurecdn.net/V8844e2pjd6QVLUUoh9FBn-1920-80.jpg" mos="" align="middle" fullscreen="" width="1600" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: IFA)</span></figcaption></figure><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Day 1</p></th><th  ><p>Day 2</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Steps</strong></p></td><td  ><p>17,902 steps</p></td><td  ><p>10,628 steps</p></td></tr><tr><td class="firstcol " ><p><strong>Average heart rate</strong></p></td><td  ><p>111 bpm</p></td><td  ><p>117 bpm</p></td></tr><tr><td class="firstcol " ><p><strong>Max heart rate</strong></p></td><td  ><p>151 bpm</p></td><td  ><p>148 bpm</p></td></tr><tr><td class="firstcol " ><p><strong>Calories burned (total)</strong></p></td><td  ><p>2,407 calories </p></td><td  ><p>1,121 calories</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-1-i-covered-way-more-ground-than-expected-especially-on-day-1"><span>1. I covered way more ground than expected, especially on day 1</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="TrVGT7FHzWykpwioYKi8yn" name="Luna-Cirqa-01" alt="Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/TrVGT7FHzWykpwioYKi8yn-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>Much to my surprise, I walked nearly 18,000 steps on my first day of IFA, which was technically a day before the show opened to the public (the press tends to get early access). </p><p>To be fair, the Berlin Messe is an absolutely sprawling conference complex, with no shortage of seemingly secret passages and tucked-away halls that are easy to stumble upon by accident but virtually impossible to find again when you’re <em>actually</em> looking for them.</p><p>This partially explains why my day one step count was so much higher than day two: I spent considerable time on the ground day one simply trying to get a lay of the land (in an admittedly very jet-lagged state). Day two, I had meetings scattered throughout the complex, and I didn’t want to be wandering around like a ding-dong.  </p><h3 class="article-body__section" id="section-2-i-logged-more-steps-on-day-1-of-ifa-than-any-single-day-covering-mwc"><span>2. I logged more steps on day 1 of IFA than any single day covering MWC</span></h3><p>At 17,902 steps, my day one of IFA coverage in Berlin beat my step count for any individual day of coverage at <a href="https://www.tomsguide.com/wellness/fitness/i-logged-37-miles-at-mwc-2026-on-my-garmin-instinct-3-here-are-5-things-i-learned">Mobile World Congress</a> in Barcelona back in March. That said, I spent a total of five days covering MWC compared to just two days covering IFA, for a total step count of 67,398 steps in Spain.</p><h3 class="article-body__section" id="section-3-but-ces-day-1-was-more-intense-than-both"><span>3. But CES day 1 was more intense than both</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="mnJPLoccAQFvxdEkQvxUQU" name="GarminCirqa-rev-02" alt="Close-up of the Garmin Cirqa on a user's wrist against a red background" src="https://cdn.mos.cms.futurecdn.net/mnJPLoccAQFvxdEkQvxUQU-1920-80.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>While day one of IFA may have been a leg-burner, it falls a bit short of my total step count from day one of the <a href="https://www.tomsguide.com/wellness/smartwatches/i-walked-65-000-steps-with-the-garmin-venu-4-5-things-i-learned">Consumer Electronics Show</a> held in Las Vegas back in early January, where I logged a dog-barking 20,253 steps, more than double my everyday average back home. </p><p>Then again, as anyone who has been to CES likely knows, things are very spread out in Las Vegas, which also just might be the least pedestrian-friendly city in the U.S... want to cross the street? You'll need to walk another half-mile down the strip and wander through multiple casinos to do so.</p><h3 class="article-body__section" id="section-4-commuting-on-the-u-bahn-seemingly-skewed-garmin-s-distance-and-pace-data"><span>4. Commuting on the U-Bahn seemingly skewed Garmin's distance and pace data</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:5025px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="J8gQGtirDrYBxfay2N35UX" name="Garmin Cirqa" alt="Garmin Cirqa" src="https://cdn.mos.cms.futurecdn.net/J8gQGtirDrYBxfay2N35UX-1920-80.jpg" mos="" align="middle" fullscreen="" width="5025" height="2827" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I didn’t include my distance or pace totals in the table above because it’s clear these figures are skewed. Both days of the show, I fired up a walking workout in the Cirqa upon leaving my hotel, trekked about half a mile to the nearest U-Bahn station — I am a nerd for experiencing public rail transit in new cities — and rode the metro roughly two miles to the show grounds. </p><p>Unfortunately, the Garmin Cirqa clearly interpreted this time spent riding the train as me moving at near-superhuman speed. For example, my average moving pace on day one of the show, according to Garmin, was 8 mins 41 secs per mile. Sure, I can maintain that pace when running a mile, but covering a trade show? Def not. </p><p>Garmin also said I walked 14.14 miles on day one, which would equal 1,266 steps per mile, way less than what I normally average, which is closer to 2,000 steps per mile. </p><h3 class="article-body__section" id="section-5-i-mostly-forgot-the-garmin-cirqa-was-even-there-but-might-not-wear-it-again"><span>5. I mostly forgot the Garmin Cirqa was even there, but might not wear it again</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:5144px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="Rr535PFKqQMmtZpT74z88e" name="GarminCirqa-03" alt="Close-up of the Garmin Cirqa screen-free fitness tracker" src="https://cdn.mos.cms.futurecdn.net/Rr535PFKqQMmtZpT74z88e-1920-80.jpg" mos="" align="middle" fullscreen="" width="5144" height="2893" 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>Ultimately, I opted to wear the Garmin Cirqa for two primary reasons. First, it’s comfortable and lightweight, so much so that I pretty much forgot it was even there. Second, I wanted to wear a mechanical watch on my left wrist to keep a constant eye on time; the nine-hour time difference between Seattle (where I live) and Berlin was my main rationale (also, I got a cool new watch I wanted to show off). </p><p>So, will I be wearing the Garmin Cirqa the next time I cover a major tech show? Honestly, probably not. While I appreciate how wrist-friendly it is, the lack of GPS means it has to piggyback off my smartphone’s signal, which isn’t necessarily ideal. Moreover, I’d rather opt for a wearable that’s capable of discerning time spent walking from time spent riding a subway. </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/smartwatches/i-biked-11-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-ultra-2-and-the-winner-is-clear"><strong>I biked 11 miles with the Garmin Instinct 3 vs Samsung Galaxy Watch Ultra 2 — and the winner is clear</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-walked-4-000-steps-with-the-pixel-watch-5-vs-samsung-galaxy-watch-9-and-we-have-a-new-android-champ"><strong>I walked 4,000 steps with the Pixel Watch 5 vs Samsung Galaxy Watch 9 — and we have a new Android champ</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-walked-7-miles-with-the-apple-watch-ultra-3-vs-pixel-watch-5-and-the-winner-is-nearly-too-close-to-call"><strong>I walked 7 miles with the Apple Watch Ultra 3 vs Pixel Watch 5 — here's the winner</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch Series 12 vs 11: Here are the 6 biggest differences ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a> just dropped, and you might be wondering whether to buy an <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review" target="_blank">Apple Watch Series 11 </a>on sale or wait and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-12-and-apple-watch-ultra-4-preorders-are-live-save-up-to-usd430">pre-order the new watch</a>. Both watches will run the new watchOS 27 software, both have the same battery life, and both look pretty much identical, but there are some key differences. We’ll dive into them below, so read this before adding either watch to your cart. </p>        <div class="featured_product_block featured_block_versus" data-id="8aacd1c8-ad60-11f1-9dbd-b9abbf6c6dad">            <a href="https://www.amazon.com/dp/B0HJ9ZXCSD/" data-model-name="Apple Watch Series 12" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:115.56%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/wWMW9gAfQecJBZLTmuhoEe.jpg" alt="a photo of the Apple Watch 12"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                            <div class='featured__brand'>Apple</div>                    <div class="featured__title">Watch Series 12</div>                                    </div>                <div class="subtitle__description">                                                            <p><p>The Apple Watch Series 12 is Apple's newest smartwatch, available to pre-order now. It has a new heart rate monitor and a helpful daily readiness score.</p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_versus" data-id="8aacd268-ad60-11f1-90d0-015f4bb6c01c">            <a href="https://www.amazon.com/Apple-Watch-Smartwatch-Aluminum-Always/dp/B0FQF5BZ8Z/" data-model-name="Apple Watch 11" 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/yxyXAq6w2EyXjcWeLctWaW.jpg" alt="Apple Watch 11"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                            <div class='featured__brand'>Apple</div>                    <div class="featured__title">Watch 11</div>                                    </div>                <div class="subtitle__description">                                                            <p><p>The Apple Watch Series 11 is now Apple's older flagship watch. It won't get some of Apple's new longevity features or Audio Intelligence, but it's still a fantastic smartwatch. </p></p>                </div>                            </div>        </div><h2 id="apple-watch-series-12-vs-apple-watch-series-11-6-biggest-differences">Apple Watch Series 12 vs Apple Watch Series 11: 6 biggest differences </h2><h3 class="article-body__section" id="section-heart-rate-monitor"><span>Heart rate monitor </span></h3><p>They might look the same, but flip the watches over and you’ll spot the biggest difference from a health and fitness-tracking perspective: the newer watch has a completely redesigned heart rate monitor. Apple says it’s the most accurate heart rate sensor in a wearable, with larger, more power-efficient green LEDs that measure your heart rate every five seconds, compared to every five minutes in the Apple Watch Series 11. </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="K8NYBa9eZYZYr94Vnmnqr4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/K8NYBa9eZYZYr94Vnmnqr4-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>But why does this even matter? Continuous heart rate monitoring lets the watch provide more accurate heart rate variability (HRV) data. On the Apple Watch Series 12, you’ll be able to see your Recovery HRV score, which shows signs of stress and recovery, as well as your overall HRV, which offers insights into your overall health.  </p><p>The new heart rate monitor also allows you to use Apple’s new Readiness score. More on that below. </p><h3 class="article-body__section" id="section-daily-readiness-score"><span>Daily Readiness score</span></h3><p>Readiness provides a single score out of ten with one of four different recommendations: Recover, Pace Yourself, Ready, or Go For It. Readiness updates throughout the day as new data comes in, and is based on your overnight vitals, sleep score, recent physical activity, and training load. </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="oT6oCzSHKMc5NiqrCAVtt4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/oT6oCzSHKMc5NiqrCAVtt4-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-charging-speed"><span>Charging speed </span></h3><p>Even with continuous heart rate monitoring, both watches have the same 24-hour battery life in smartwatch mode. That said, the Apple Watch Series 12 offers faster charging and slightly longer GPS-mode battery life — 10 hours instead of 8 on the Series 11. </p><p>With the Series 12, <strong>15 minutes of charging gives you 12 hours of battery life</strong>, making it easier to ensure you don’t miss any sleep-tracking data.</p><h3 class="article-body__section" id="section-audio-intelligence-features"><span>Audio Intelligence features </span></h3><p>The third huge difference between the two devices is that the Apple Watch Series 12 has Apple’s Audio Intelligence features on board. This uses Apple Intelligence to tell you what song is playing in the background in real time, detect important sounds you might have missed, get a transcript of the last 15 seconds of conversation with Live Rewind, and take notes of your conversations throughout the day with Siri Recap. </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="W5QaBdWA6ZqoxGfUz3gDu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/W5QaBdWA6ZqoxGfUz3gDu4-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>These features will drop later in the year, and you can read more about the <a href="https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained">Audio Intelligence features on the Apple Watch</a> here. </p><h3 class="article-body__section" id="section-processor"><span>Processor</span></h3><p>The Apple Watch Series 12 has the new S11 chip. As well as the features above, Apple says this chip has redesigned algorithms to improve the distance accuracy of indoor walk or run workouts, as well as a more accurate pedometer. With the Apple Watch Series 12, you’ll also be able to see how many steps you’ve taken each day from your home screen. </p><h3 class="article-body__section" id="section-durability-and-cases"><span>Durability and cases</span></h3><p>While the two watches look pretty much identical, the Apple Watch Series 12 watches with aluminum cases have a tougher screen. </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="h9pUCaivgXc2tpjF4BPEu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/h9pUCaivgXc2tpjF4BPEu4-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>Finally, you’ll also get new finishes with the Series 12 — there’s a new radiant gold titanium casing, as well as two new ceramic casings in pearl white and night blue. </p><h2 id="which-should-you-pick">Which should you pick? </h2><p>So, should you pre-order the Apple Watch Series 12, or save your money and buy the Series 11 when it goes on sale? We’re yet to fully test the Series 12, so stay tuned for our full review dropping later this month, but from the heart rate sensor alone, this seems like a worthy upgrade from a health and fitness tracking standpoint. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OaLdGW"></div>                            </div>                            <script src="https://kwizly.com/embed/OaLdGW.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><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai">We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12 hands-on: A new heart rate sensor and a readiness score (at last)</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4 is official: All the upgrades explained</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-vs-11-here-are-the-6-biggest-differences</link>
                                                                            <description>
                            <![CDATA[ Should you buy the Apple Watch Series 12 or Series 11? Read this before making your pick. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">pwEwATcv8gMmdxxcrXWVgS</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/oT6oCzSHKMc5NiqrCAVtt4-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 12 Sep 2026 06:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></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/oT6oCzSHKMc5NiqrCAVtt4-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Series 12]]></media:description>                                                            <media:text><![CDATA[Apple Watch Series 12]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Series 12]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/oT6oCzSHKMc5NiqrCAVtt4-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a> just dropped, and you might be wondering whether to buy an <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review" target="_blank">Apple Watch Series 11 </a>on sale or wait and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-12-and-apple-watch-ultra-4-preorders-are-live-save-up-to-usd430">pre-order the new watch</a>. Both watches will run the new watchOS 27 software, both have the same battery life, and both look pretty much identical, but there are some key differences. We’ll dive into them below, so read this before adding either watch to your cart. </p>        <div class="featured_product_block featured_block_versus" data-id="8aacd1c8-ad60-11f1-9dbd-b9abbf6c6dad">            <a href="https://www.amazon.com/dp/B0HJ9ZXCSD/" data-model-name="Apple Watch Series 12" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:115.56%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/wWMW9gAfQecJBZLTmuhoEe.jpg" alt="a photo of the Apple Watch 12"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                            <div class='featured__brand'>Apple</div>                    <div class="featured__title">Watch Series 12</div>                                    </div>                <div class="subtitle__description">                                                            <p><p>The Apple Watch Series 12 is Apple's newest smartwatch, available to pre-order now. It has a new heart rate monitor and a helpful daily readiness score.</p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_versus" data-id="8aacd268-ad60-11f1-90d0-015f4bb6c01c">            <a href="https://www.amazon.com/Apple-Watch-Smartwatch-Aluminum-Always/dp/B0FQF5BZ8Z/" data-model-name="Apple Watch 11" 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/yxyXAq6w2EyXjcWeLctWaW.jpg" alt="Apple Watch 11"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                            <div class='featured__brand'>Apple</div>                    <div class="featured__title">Watch 11</div>                                    </div>                <div class="subtitle__description">                                                            <p><p>The Apple Watch Series 11 is now Apple's older flagship watch. It won't get some of Apple's new longevity features or Audio Intelligence, but it's still a fantastic smartwatch. </p></p>                </div>                            </div>        </div><h2 id="apple-watch-series-12-vs-apple-watch-series-11-6-biggest-differences">Apple Watch Series 12 vs Apple Watch Series 11: 6 biggest differences </h2><h3 class="article-body__section" id="section-heart-rate-monitor"><span>Heart rate monitor </span></h3><p>They might look the same, but flip the watches over and you’ll spot the biggest difference from a health and fitness-tracking perspective: the newer watch has a completely redesigned heart rate monitor. Apple says it’s the most accurate heart rate sensor in a wearable, with larger, more power-efficient green LEDs that measure your heart rate every five seconds, compared to every five minutes in the Apple Watch Series 11. </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="K8NYBa9eZYZYr94Vnmnqr4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/K8NYBa9eZYZYr94Vnmnqr4-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>But why does this even matter? Continuous heart rate monitoring lets the watch provide more accurate heart rate variability (HRV) data. On the Apple Watch Series 12, you’ll be able to see your Recovery HRV score, which shows signs of stress and recovery, as well as your overall HRV, which offers insights into your overall health.  </p><p>The new heart rate monitor also allows you to use Apple’s new Readiness score. More on that below. </p><h3 class="article-body__section" id="section-daily-readiness-score"><span>Daily Readiness score</span></h3><p>Readiness provides a single score out of ten with one of four different recommendations: Recover, Pace Yourself, Ready, or Go For It. Readiness updates throughout the day as new data comes in, and is based on your overnight vitals, sleep score, recent physical activity, and training load. </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="oT6oCzSHKMc5NiqrCAVtt4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/oT6oCzSHKMc5NiqrCAVtt4-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-charging-speed"><span>Charging speed </span></h3><p>Even with continuous heart rate monitoring, both watches have the same 24-hour battery life in smartwatch mode. That said, the Apple Watch Series 12 offers faster charging and slightly longer GPS-mode battery life — 10 hours instead of 8 on the Series 11. </p><p>With the Series 12, <strong>15 minutes of charging gives you 12 hours of battery life</strong>, making it easier to ensure you don’t miss any sleep-tracking data.</p><h3 class="article-body__section" id="section-audio-intelligence-features"><span>Audio Intelligence features </span></h3><p>The third huge difference between the two devices is that the Apple Watch Series 12 has Apple’s Audio Intelligence features on board. This uses Apple Intelligence to tell you what song is playing in the background in real time, detect important sounds you might have missed, get a transcript of the last 15 seconds of conversation with Live Rewind, and take notes of your conversations throughout the day with Siri Recap. </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="W5QaBdWA6ZqoxGfUz3gDu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/W5QaBdWA6ZqoxGfUz3gDu4-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>These features will drop later in the year, and you can read more about the <a href="https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained">Audio Intelligence features on the Apple Watch</a> here. </p><h3 class="article-body__section" id="section-processor"><span>Processor</span></h3><p>The Apple Watch Series 12 has the new S11 chip. As well as the features above, Apple says this chip has redesigned algorithms to improve the distance accuracy of indoor walk or run workouts, as well as a more accurate pedometer. With the Apple Watch Series 12, you’ll also be able to see how many steps you’ve taken each day from your home screen. </p><h3 class="article-body__section" id="section-durability-and-cases"><span>Durability and cases</span></h3><p>While the two watches look pretty much identical, the Apple Watch Series 12 watches with aluminum cases have a tougher screen. </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="h9pUCaivgXc2tpjF4BPEu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/h9pUCaivgXc2tpjF4BPEu4-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>Finally, you’ll also get new finishes with the Series 12 — there’s a new radiant gold titanium casing, as well as two new ceramic casings in pearl white and night blue. </p><h2 id="which-should-you-pick">Which should you pick? </h2><p>So, should you pre-order the Apple Watch Series 12, or save your money and buy the Series 11 when it goes on sale? We’re yet to fully test the Series 12, so stay tuned for our full review dropping later this month, but from the heart rate sensor alone, this seems like a worthy upgrade from a health and fitness tracking standpoint. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OaLdGW"></div>                            </div>                            <script src="https://kwizly.com/embed/OaLdGW.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><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai">We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12 hands-on: A new heart rate sensor and a readiness score (at last)</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4 is official: All the upgrades explained</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: price, specs and features compared ]]></title>
                                                                                                <dc:content><![CDATA[ <p>If you’re a fan of the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a>, you’ve been treated in recent weeks with the launch of the latest models of the Garmin Fenix and Apple Watch Ultra.</p><p>The <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor">Garmin Fenix 9</a> line-up launched in late August, with the top-of-the-range Fenix 9 Pro being Garmin’s most advanced sports watch yet. </p><p>A couple of weeks later the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model">Apple Watch Ultra 4</a> was announced at Apple’s September event, boasting new features like continuous heart rate tracking and a readiness score.</p><p>We’ll thoroughly test both watches and compare them in our full reviews, but for now here’s a breakdown of how the pair stack up with regards to their key specs, features and price.</p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-specs-compared"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Specs compared</span></h2><div ><table><caption>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro AMOLED </caption><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Apple Watch Ultra 3</strong></p></td><td  ><p><strong>Garmin Fenix 8 Pro AMOLED </strong></p></td></tr><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p>$799</p></td><td  ><p>From $1,199 (with inReach)</p></td></tr><tr><td class="firstcol " ><p><strong>Size</strong></p></td><td  ><p>49mm</p></td><td  ><p>43mm, 47mm or 51mm</p></td></tr><tr><td class="firstcol " ><p><strong>Thickness</strong></p></td><td  ><p>12mm</p></td><td  ><p>13.3mm (43mm),<br>13.8mm (47mm), 15.8mm (51mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Case weight</strong></p></td><td  ><p>62g</p></td><td  ><p>45g (43mm), 56g (47mm), 73g (51mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>Sapphire crystal</p></td><td  ><p>Sapphire crystal</p></td></tr><tr><td class="firstcol " ><p><strong>Connectivity</strong></p></td><td  ><p>LTE & satellite</p></td><td  ><p>LTE & satellite</p></td></tr><tr><td class="firstcol " ><p><strong>Smartwatch battery life </strong></p></td><td  ><p>50 hours</p></td><td  ><p>10 days (43 mm), 18 days (47mm), 31 days (51mm)</p></td></tr><tr><td class="firstcol " ><p><strong>GPS battery life (multi-band)</strong></p></td><td  ><p>18 hours</p></td><td  ><p>18 hours (43mm), 32 hours (47mm), 56 hours (51mm)</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-price"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Price</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AYP57Su3Eno7XWdwUbPfJj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-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 price is simple when it comes to the Apple Watch Ultra 4; it will set you back $799, the same price as its predecessor. There’s also only one model of the watch, which comes in either black or natural titanium,</p><p>Things are a lot more complicated with the Garmin Fenix 9 line-up, with three sizes, two display options and standard and Pro models to consider.</p><p>The standard Garmin Fenix 9 costs from $999, whereas the Fenix 9 Pro costs from $1099 and has a full titanium case and the option to add inReach connectivity as its key upgrades. I’m going to focus on the Fenix 9 Pro for this comparison, because it’s the top model in Garmin’s line-up.</p><p>Whatever Fenix you opt for, however, the Apple Watch Ultra 4 is going to be the more affordable option, and it’s $400 cheaper than a Garmin Fenix 9 Pro with inReach.</p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-design-and-display"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Design and display</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="ksjEAsDzPnVz4PFiyS54Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/ksjEAsDzPnVz4PFiyS54Rj-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>Both watches have rugged, durable designs with full titanium cases and sapphire crystal displays. The Apple Watch Ultra has a square 49mm case, whereas with the Fenix 9 Pro you can choose between circular 43mm, 47mm and 51mm case sizes.</p><p>Another choice you get with the Fenix 9 Pro is the display type, because there is a memory-in-pixel Fenix 9 Pro Solar with solar panels on its face to boost battery life. </p><p>The standard Fenix 9 Pro has a 3,000 nit AMOLED display, matching the brightness of the Apple Watch Ultra 4’s Retina display.</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="HsEvn6zkCC3qyFB7uE4uB7" name="Garmin Fenix 9 Pro flashlight" alt="Garmin Fenix 9 Pro flashlight" src="https://cdn.mos.cms.futurecdn.net/HsEvn6zkCC3qyFB7uE4uB7-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>Both watches stick with their classic button layouts — the Ultra 4 has three buttons, one of which is a digital dial, while the Fenix 9 Pro has five buttons.</p><p>They have equivalent waterproof ratings and both can be used for diving to depths of 40m.</p><p>A big design advantage for the Fenix 9 Pro is its built-in flashlight, which has white, red and green modes and is brighter and more useful than the flashlight option on the Ultra 4, which uses the watch face itself to light the way.</p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-health-and-fitness-features"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Health and fitness features</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="wJzr9bqD5grXgaeqP9hXPj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/wJzr9bqD5grXgaeqP9hXPj-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>Both watches are packed with useful sports and activity tracking features, and the Apple Watch Ultra 4’s new continuous heart rate monitor and readiness feature are two big improvements that bring it into line with features that have been available on Garmin watches for some time.</p><p>We’ll be testing Apple’s claims that the new heart rate monitor on the Ultra 4 and Apple Watch Series 12 is the most accurate on the market, but I have been impressed by the heart rate accuracy on the Fenix 9 Pro so far in testing, and on past Apple Watch models.</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.29%;"><img id="VzUcM6wtvXKraohPwDUeaH" name="Garmin Fenix 9 Pro Readiness" alt="Garmin Fenix 9 Pro Readiness" src="https://cdn.mos.cms.futurecdn.net/VzUcM6wtvXKraohPwDUeaH-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1441" 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 Apple Watch Ultra 4 has more health tracking features, like alerts for signs of an irregular heart beat and hypertension, whereas the Garmin’s strengths are in more extensive training analysis, with additional metrics rating your overall endurance and predicted race times.</p><p>Both watches have all the sports modes and stats you need to track workouts, and are also comprehensive daily activity and sleep trackers. </p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-smart-features-and-connectivity"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Smart features and connectivity</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="JzL85TmsbDndusgcZgihgG" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/JzL85TmsbDndusgcZgihgG-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 Apple Watch Ultra 4 is a true smartwatch and offers more useful day-to-day features than the Fenix 9 Pro, especially with its new Siri AI-based features, like Live Rewind, Sound Recognition and Siri Recap.</p><p>There’s also a wealth of useful third-party apps available for the Apple Watch, whereas Garmin’s Connect IQ app store is much more limited, and Apple Pay is easier to set up and use than Garmin Pay.</p><p>The Fenix 9 Pro’s smart features do include music storage and the ability to link up with streaming services including Spotify, but the Apple Watch Ultra 4 is certainly smarter all round.</p><p>Both watches offer LTE and satellite connectivity though, which can be useful for staying in touch with others when you don’t have your phone, or to send SOS alerts if you get into trouble when adventuring off-the-grid. </p><p>This feature is only available on the more expensive Fenix 9 Pro model with inReach connectivity, and you will need a subscription with both watches to use these services, except for SOS alerts, which are free on both (for one year with the Fenix 9 Pro, for two years on the Apple Watch Ultra 4).</p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-navigation"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: navigation</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="eZHBCPefduMUnbd4Z2jNq5" name="Garmin Fenix 9 Pro maps" alt="Garmin Fenix 9 Pro maps" src="https://cdn.mos.cms.futurecdn.net/eZHBCPefduMUnbd4Z2jNq5-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>Garmin’s on-watch navigation tools are the best in the business, and you can quickly create and follow routes on the Fenix 9 Pro thanks to its routable maps, as well as getting specific info on what’s ahead of you when tackling long climbs or descents.</p><p>You can also view and use these maps with your sports modes, so you can see your activity stats and a map at the same time, unlike on the Apple Watch Ultra 4, which has its maps and routing features in a separate app to Workouts (though you can use third-party apps to shows maps during an activity).</p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-battery-life"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Battery life</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="q6RPuprHDQb5uHVE6hD8Cj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/q6RPuprHDQb5uHVE6hD8Cj-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 Apple Watch Ultra 4 got a battery life bump that means it now offers up to 50 hours on a charge with the always-on display enabled, and 18 hours of GPS tracking in its most accurate mode.</p><p>However, this is an area where the Garmin Fenix 9 Pro certainly has the edge, no matter what size of the watch you opt for.</p><p>The Fenix 9 Pro 43mm lasts up to 10 days in watch mode and has 18 hours of GPS tracking. The 47mm watch lasts up to 18 days in watch mode and has 32 hours of GPS tracking, and the biggest 51mm watch I’m testing can last a whopping 31 days in watch mode and has 56 hours of GPS tracking.</p><p>Both watches can extend these ratings by using various low-power modes during activities, but if it’s battery life you want, the Fenix is the watch to go for.</p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-which-should-you-buy"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Which should you buy?</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:1800px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="5JW8CVGH2XjNK8smMG6vjG" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:184,l:340,cw:1800,ch:1013,q:80/5JW8CVGH2XjNK8smMG6vjG.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 Garmin Fenix 9 Pro is built to be the ultimate adventure and sports watch and focuses more on battery life and training features than the Apple Watch Ultra 4, and it also offers more design choices and the flashlight, which I find invaluable.</p><p>For its part the Apple Watch Ultra 4 looks to be a very capable sports watch with more smarts and health features than the Fenix 9 Pro, and it also comes in a lot cheaper.</p><p>Both are among the best options in their category, but which suits you better will largely depend if you’re mainly looking for a sports watch, or a smartwatch.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xj2xlX"></div>                            </div>                            <script src="https://kwizly.com/embed/Xj2xlX.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><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model">Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-11-vs-apple-watch-ultra-3-which-one-should-you-buy">Apple Watch 11 vs Apple Watch Ultra 3 — which one should you buy?</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai">We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-vs-garmin-fenix-9-pro-price-specs-and-features-compared</link>
                                                                            <description>
                            <![CDATA[ Garmin and Apple have just launched the latest models of their flagship smartwatch, but how do the Apple Watch Ultra 4 and Garmin Fenix 9 Pro compare? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">gHEbV3YQUA8F8k82KHQC73</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/2tRBKcpvgdKbcbzzinxkgW-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 11 Sep 2026 11:57:09 +0000</pubDate>                                                                                                                                <updated>Fri, 11 Sep 2026 11:58:24 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Nick Harris-Fry ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/J5Jjp49GUVjLZEbjEkTex-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/2tRBKcpvgdKbcbzzinxkgW-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Ultra 4 vs Garmin Fenix 9 Pro]]></media:description>                                                            <media:text><![CDATA[Apple Watch Ultra 4 vs Garmin Fenix 9 Pro]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Ultra 4 vs Garmin Fenix 9 Pro]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/2tRBKcpvgdKbcbzzinxkgW-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>If you’re a fan of the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a>, you’ve been treated in recent weeks with the launch of the latest models of the Garmin Fenix and Apple Watch Ultra.</p><p>The <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor">Garmin Fenix 9</a> line-up launched in late August, with the top-of-the-range Fenix 9 Pro being Garmin’s most advanced sports watch yet. </p><p>A couple of weeks later the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model">Apple Watch Ultra 4</a> was announced at Apple’s September event, boasting new features like continuous heart rate tracking and a readiness score.</p><p>We’ll thoroughly test both watches and compare them in our full reviews, but for now here’s a breakdown of how the pair stack up with regards to their key specs, features and price.</p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-specs-compared"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Specs compared</span></h2><div ><table><caption>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro AMOLED </caption><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Apple Watch Ultra 3</strong></p></td><td  ><p><strong>Garmin Fenix 8 Pro AMOLED </strong></p></td></tr><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p>$799</p></td><td  ><p>From $1,199 (with inReach)</p></td></tr><tr><td class="firstcol " ><p><strong>Size</strong></p></td><td  ><p>49mm</p></td><td  ><p>43mm, 47mm or 51mm</p></td></tr><tr><td class="firstcol " ><p><strong>Thickness</strong></p></td><td  ><p>12mm</p></td><td  ><p>13.3mm (43mm),<br>13.8mm (47mm), 15.8mm (51mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Case weight</strong></p></td><td  ><p>62g</p></td><td  ><p>45g (43mm), 56g (47mm), 73g (51mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>Sapphire crystal</p></td><td  ><p>Sapphire crystal</p></td></tr><tr><td class="firstcol " ><p><strong>Connectivity</strong></p></td><td  ><p>LTE & satellite</p></td><td  ><p>LTE & satellite</p></td></tr><tr><td class="firstcol " ><p><strong>Smartwatch battery life </strong></p></td><td  ><p>50 hours</p></td><td  ><p>10 days (43 mm), 18 days (47mm), 31 days (51mm)</p></td></tr><tr><td class="firstcol " ><p><strong>GPS battery life (multi-band)</strong></p></td><td  ><p>18 hours</p></td><td  ><p>18 hours (43mm), 32 hours (47mm), 56 hours (51mm)</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-price"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Price</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AYP57Su3Eno7XWdwUbPfJj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-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 price is simple when it comes to the Apple Watch Ultra 4; it will set you back $799, the same price as its predecessor. There’s also only one model of the watch, which comes in either black or natural titanium,</p><p>Things are a lot more complicated with the Garmin Fenix 9 line-up, with three sizes, two display options and standard and Pro models to consider.</p><p>The standard Garmin Fenix 9 costs from $999, whereas the Fenix 9 Pro costs from $1099 and has a full titanium case and the option to add inReach connectivity as its key upgrades. I’m going to focus on the Fenix 9 Pro for this comparison, because it’s the top model in Garmin’s line-up.</p><p>Whatever Fenix you opt for, however, the Apple Watch Ultra 4 is going to be the more affordable option, and it’s $400 cheaper than a Garmin Fenix 9 Pro with inReach.</p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-design-and-display"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Design and display</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="ksjEAsDzPnVz4PFiyS54Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/ksjEAsDzPnVz4PFiyS54Rj-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>Both watches have rugged, durable designs with full titanium cases and sapphire crystal displays. The Apple Watch Ultra has a square 49mm case, whereas with the Fenix 9 Pro you can choose between circular 43mm, 47mm and 51mm case sizes.</p><p>Another choice you get with the Fenix 9 Pro is the display type, because there is a memory-in-pixel Fenix 9 Pro Solar with solar panels on its face to boost battery life. </p><p>The standard Fenix 9 Pro has a 3,000 nit AMOLED display, matching the brightness of the Apple Watch Ultra 4’s Retina display.</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="HsEvn6zkCC3qyFB7uE4uB7" name="Garmin Fenix 9 Pro flashlight" alt="Garmin Fenix 9 Pro flashlight" src="https://cdn.mos.cms.futurecdn.net/HsEvn6zkCC3qyFB7uE4uB7-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>Both watches stick with their classic button layouts — the Ultra 4 has three buttons, one of which is a digital dial, while the Fenix 9 Pro has five buttons.</p><p>They have equivalent waterproof ratings and both can be used for diving to depths of 40m.</p><p>A big design advantage for the Fenix 9 Pro is its built-in flashlight, which has white, red and green modes and is brighter and more useful than the flashlight option on the Ultra 4, which uses the watch face itself to light the way.</p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-health-and-fitness-features"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Health and fitness features</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="wJzr9bqD5grXgaeqP9hXPj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/wJzr9bqD5grXgaeqP9hXPj-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>Both watches are packed with useful sports and activity tracking features, and the Apple Watch Ultra 4’s new continuous heart rate monitor and readiness feature are two big improvements that bring it into line with features that have been available on Garmin watches for some time.</p><p>We’ll be testing Apple’s claims that the new heart rate monitor on the Ultra 4 and Apple Watch Series 12 is the most accurate on the market, but I have been impressed by the heart rate accuracy on the Fenix 9 Pro so far in testing, and on past Apple Watch models.</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.29%;"><img id="VzUcM6wtvXKraohPwDUeaH" name="Garmin Fenix 9 Pro Readiness" alt="Garmin Fenix 9 Pro Readiness" src="https://cdn.mos.cms.futurecdn.net/VzUcM6wtvXKraohPwDUeaH-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1441" 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 Apple Watch Ultra 4 has more health tracking features, like alerts for signs of an irregular heart beat and hypertension, whereas the Garmin’s strengths are in more extensive training analysis, with additional metrics rating your overall endurance and predicted race times.</p><p>Both watches have all the sports modes and stats you need to track workouts, and are also comprehensive daily activity and sleep trackers. </p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-smart-features-and-connectivity"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Smart features and connectivity</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="JzL85TmsbDndusgcZgihgG" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/JzL85TmsbDndusgcZgihgG-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 Apple Watch Ultra 4 is a true smartwatch and offers more useful day-to-day features than the Fenix 9 Pro, especially with its new Siri AI-based features, like Live Rewind, Sound Recognition and Siri Recap.</p><p>There’s also a wealth of useful third-party apps available for the Apple Watch, whereas Garmin’s Connect IQ app store is much more limited, and Apple Pay is easier to set up and use than Garmin Pay.</p><p>The Fenix 9 Pro’s smart features do include music storage and the ability to link up with streaming services including Spotify, but the Apple Watch Ultra 4 is certainly smarter all round.</p><p>Both watches offer LTE and satellite connectivity though, which can be useful for staying in touch with others when you don’t have your phone, or to send SOS alerts if you get into trouble when adventuring off-the-grid. </p><p>This feature is only available on the more expensive Fenix 9 Pro model with inReach connectivity, and you will need a subscription with both watches to use these services, except for SOS alerts, which are free on both (for one year with the Fenix 9 Pro, for two years on the Apple Watch Ultra 4).</p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-navigation"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: navigation</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="eZHBCPefduMUnbd4Z2jNq5" name="Garmin Fenix 9 Pro maps" alt="Garmin Fenix 9 Pro maps" src="https://cdn.mos.cms.futurecdn.net/eZHBCPefduMUnbd4Z2jNq5-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>Garmin’s on-watch navigation tools are the best in the business, and you can quickly create and follow routes on the Fenix 9 Pro thanks to its routable maps, as well as getting specific info on what’s ahead of you when tackling long climbs or descents.</p><p>You can also view and use these maps with your sports modes, so you can see your activity stats and a map at the same time, unlike on the Apple Watch Ultra 4, which has its maps and routing features in a separate app to Workouts (though you can use third-party apps to shows maps during an activity).</p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-battery-life"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Battery life</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="q6RPuprHDQb5uHVE6hD8Cj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/q6RPuprHDQb5uHVE6hD8Cj-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 Apple Watch Ultra 4 got a battery life bump that means it now offers up to 50 hours on a charge with the always-on display enabled, and 18 hours of GPS tracking in its most accurate mode.</p><p>However, this is an area where the Garmin Fenix 9 Pro certainly has the edge, no matter what size of the watch you opt for.</p><p>The Fenix 9 Pro 43mm lasts up to 10 days in watch mode and has 18 hours of GPS tracking. The 47mm watch lasts up to 18 days in watch mode and has 32 hours of GPS tracking, and the biggest 51mm watch I’m testing can last a whopping 31 days in watch mode and has 56 hours of GPS tracking.</p><p>Both watches can extend these ratings by using various low-power modes during activities, but if it’s battery life you want, the Fenix is the watch to go for.</p><h2 class="article-body__section" id="section-apple-watch-ultra-4-vs-garmin-fenix-9-pro-which-should-you-buy"><span>Apple Watch Ultra 4 vs Garmin Fenix 9 Pro: Which should you buy?</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:1800px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="5JW8CVGH2XjNK8smMG6vjG" name="Garmin Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:184,l:340,cw:1800,ch:1013,q:80/5JW8CVGH2XjNK8smMG6vjG.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 Garmin Fenix 9 Pro is built to be the ultimate adventure and sports watch and focuses more on battery life and training features than the Apple Watch Ultra 4, and it also offers more design choices and the flashlight, which I find invaluable.</p><p>For its part the Apple Watch Ultra 4 looks to be a very capable sports watch with more smarts and health features than the Fenix 9 Pro, and it also comes in a lot cheaper.</p><p>Both are among the best options in their category, but which suits you better will largely depend if you’re mainly looking for a sports watch, or a smartwatch.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xj2xlX"></div>                            </div>                            <script src="https://kwizly.com/embed/Xj2xlX.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><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model">Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-11-vs-apple-watch-ultra-3-which-one-should-you-buy">Apple Watch 11 vs Apple Watch Ultra 3 — which one should you buy?</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai">We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch Series 12 vs Apple Watch Ultra 4: Which new Apple Watch should you buy? ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple has once again launched new Apple Watches, including the flagship <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-announced-everything-you-need-to-know-about-the-new-flagship-apple-watchhttps://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a> and premium <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explainedhttps://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4</a>. The question is, which one is right for you?</p><p>I'm here to help you answer that. Below, I've compared the Apple Watch Series 12 vs. Apple Watch Ultra 4 across seven categories, including cost, design, display, health and fitness, safety, AI, and battery life. Here's everything you need to know before you buy.</p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-specs-compared"><span>Apple Watch 12 vs Apple Watch Ultra 4: Specs compared</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Apple Watch Series 12</p></th><th  ><p>Apple Watch Ultra 4</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$399</p></td><td  ><p>$799</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>46mm: 46 x 40 x 9.7mm / 42mm: 42 x 37 x 9.7mm</p></td><td  ><p>49 x 44 x 12 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Case colors</strong></p></td><td  ><p>Aluminum: Dark Bronze, Light Gold, Black, Space Gray / Titanium: Radiant Gold, Natural / Ceramic: Pearl White, Night Blue</p><p></p></td><td  ><p>Titanium: Natural, Black</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>46mm:  416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p><p></p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td></tr><tr><td class="firstcol " ><p><strong>Display brightness</strong></p><p></p><p></p><p></p></td><td  ><p>2,000 nits</p></td><td  ><p>3,000 nits</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>46mm: ~ 39 g / 44mm: ~32 g</p></td><td  ><p>~63 g</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>S11</p></td><td  ><p>S11</p></td></tr><tr><td class="firstcol " ><p><strong>Cellular </strong></p></td><td  ><p>5G</p></td><td  ><p>5G</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>50 meters</p></td><td  ><p>100 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life with always-on display (rated)</strong></p></td><td  ><p>24 hours</p></td><td  ><p>50 hours</p></td></tr><tr><td class="firstcol " ><p><strong>Compatibility</strong></p></td><td  ><p>iOS 27 or later</p></td><td  ><p>iOS 27 or later</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-price"><span>Apple Watch 12 vs Apple Watch Ultra 4: Price</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="h9pUCaivgXc2tpjF4BPEu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/h9pUCaivgXc2tpjF4BPEu4-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>This is an easy one; the Apple Watch Series 12 <a href="https://www.apple.com/shop/buy-watch/apple-watch" target="_blank" rel="nofollow">starts at $399</a>, half the $799 cost of the Apple Watch Ultra 4. Even the priciest Series 12 configuration, 46mm with 5G+GPS, is $250 less than the latest Ultra model.</p><p>That said, if you opt for the Series 12 with an upgraded ceramic case (vs standard aluminum), it surpasses the Ultra 4 in cost: $899 for the 42mm and $949 for the 46mm. Note: there is no ceramic Apple Watch Ultra 4.</p><p>Both the Apple Watch Ultra 4 and Apple Watch Series 12 are available for preorder from September 9 with a September 18 ship date.</p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-design-and-durability"><span>Apple Watch 12 vs Apple Watch Ultra 4: Design and durability</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="q6RPuprHDQb5uHVE6hD8Cj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/q6RPuprHDQb5uHVE6hD8Cj-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>Even though the Apple Watch Series 12 features an upgraded Ceramic Shield 2 screen coating — which is 60% tougher than the Ion-X glass used on the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Series 11</a> — the Apple Watch Ultra 4 is hands-down the more rugged model.</p><p>The Ultra 4, like those before it, boasts 100 meters of water resistance, enough for scuba diving and double that of the Series 12. Additionally, the Ultra 4 sports a sapphire crystal display, which is more scratch-resistant than even Ion-X glass.</p><p>From a usability standpoint, the Ultra 4's design includes an additional, customizable "Action" button on the side of the case opposite the digital crown and side button. </p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-display"><span>Apple Watch 12 vs Apple Watch Ultra 4: Display</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="xv7TVM8BxL5mYTJonKP7Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/xv7TVM8BxL5mYTJonKP7Rj-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 Apple Watch Ultra 4 and Apple Watch Series 12 each use the same display as their respective predecessors. Ultimately, the Ultra 4's display offers slightly more real estate than the 46mm Apple Watch Series 12, and a noticeable amount more than the 42mm model.</p><p>You'll find LTPO3 wide-angle OLED panels with 326 pixels per inch of resolution in both the latest flagship and Ultra models, but the latter's display is more powerful than the former's.</p><p>While the Series 12 maxes out at a respectable 2,000 nits, which is generally bright enough for viewing in bright sunlight, the Ultra 4 reaches 3,000 nits of max brightness. In my experience, that's bright enough to read the screen in even direct sunlight.</p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-health-and-fitness-features"><span>Apple Watch 12 vs Apple Watch Ultra 4: Health and fitness features</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="K8NYBa9eZYZYr94Vnmnqr4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/K8NYBa9eZYZYr94Vnmnqr4-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>When it comes to onboard health and fitness tech and features, the Apple Watch Series 12 and Apple Watch Ultra 4 are essentially a match. They both have Apple's new, redesigned holistic sensor array, which promises far more accurate heart rate tracking, ECGs, and heart rate variability insights compared to prior Apple Watches.</p><p>Both watches support a wide range of trackable workout types, along with onboard GPS for logging outdoor activities without a paired phone, but the Ultra 4 has a more advanced dual-band antenna compared to a single-band GPS on the Series 12. </p><p>Translation: In settings with obstructed skies, like cities or forests, the Ultra 4 will likely generate slightly more accurate location-based data than the Series 12.</p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-safety-features"><span>Apple Watch 12 vs Apple Watch Ultra 4: Safety features</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:870px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="HuR9pqp3Cwh6SZFZi9tMBE" name="AW12-ECG" alt="Close-up of an ECG reading being performed using the Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/HuR9pqp3Cwh6SZFZi9tMBE-1920-80.jpg" mos="" align="middle" fullscreen="" width="870" height="489" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>Apple's latest smartwatches are each jam-packed with useful safety features, including fall and crash detection, high/low heart rate alerts, Hypertension Alerts, and sleep apnea notifications. However, the Ultra 4 (and Ultra 3) have one unique safety tool not found on any other Apple Watch: Emergency SOS via satellite.</p><p>This feature allows users to connect to a satellite, even without a paired smartphone and/or a cellular signal, and send a message to friends and/or emergency responders with location and other details.</p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-ai-features"><span>Apple Watch 12 vs Apple Watch Ultra 4: AI features</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="8bcbHKT8rtMP46JqtdXmRN" name="Apple Event — September 9 47-49 screenshot" alt="Live Rewind on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/8bcbHKT8rtMP46JqtdXmRN-1920-80.png" 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: Apple)</span></figcaption></figure><p>The Apple Watch 12 and Ultra 4 support the latest, greatest Siri AI-based features, including the onboard voice assistant itself, along with Live Rewind (lets you ‘go back in time’ up to 15 seconds), Sound Recognition(alerts users to sounds like sirens and alarms), and Siri Recap (takes high-level notes of conversations and generates summaries).</p><p>Some are concerned about potential privacy issues, but Apple stresses that Live Rewind only activates when you deliberately double-press the Digital Crown. In addition, audio is not recorded or stored for either feature and Siri Recap offers only AI summaries and not transcripts or speaker names.</p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-battery-life"><span>Apple Watch 12 vs Apple Watch Ultra 4: Battery life</span></h3><p>If you want the best battery life in an Apple Watch, your best bet is the Apple Watch Ultra 4, which is rated to last up to 50 hours per charge, more than double the 24-hour rating of the Apple Watch Series 12. </p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-which-should-you-buy"><span>Apple Watch 12 vs Apple Watch Ultra 4: Which should you buy?</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AYP57Su3Eno7XWdwUbPfJj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-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>Apple has long been careful to differentiate the flagship Apple Watch series from the pricier Ultra series, and that's still the case in 2026. The Apple Watch Ultra 4 is tougher-built with double the water resistance, twice the battery life, a brighter screen, better GPS, and more impressive safety tools. </p><p>On the flip side, the Apple Watch Series 12 is much more affordable than the Ultra 4, with all the same cutting-edge health and fitness tools, AI features, and nearly the same-size screen (in the 46mm model). Oh, and it's also more comfortable on the wrist thanks to a slimmer case.</p><p>For most of us, the Apple Watch Series 12 is going to be the more sensible option. But if you fancy yourself to be a rugged, outdoor adventurer or hardcore athlete, then the extra cost of the Apple Watch Ultra 4 may be worth it.</p><p>Which new Apple Watch would you rather rock? Let me know in the comments.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xj2xlX"></div>                            </div>                            <script src="https://kwizly.com/embed/Xj2xlX.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><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model">Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-11-vs-apple-watch-ultra-3-which-one-should-you-buy">Apple Watch 11 vs Apple Watch Ultra 3 — which one should you buy?</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai">We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-vs-apple-watch-ultra-4-which-new-apple-watch-should-you-buy</link>
                                                                            <description>
                            <![CDATA[ Here's how the Apple Watch Series 12 and Apple Watch Ultra 4 compare across seven categories, including price, design, battery, AI features, and onboard health tech. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">bCvk38DAhGNR6jSHuAHMXD</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/gEo2Mdaja5cREBSCs9qh6S-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 11 Sep 2026 10:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/gEo2Mdaja5cREBSCs9qh6S-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Series 12 vs Apple Watch Ultra 4]]></media:description>                                                            <media:text><![CDATA[Apple Watch Series 12 vs Apple Watch Ultra 4]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Series 12 vs Apple Watch Ultra 4]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/gEo2Mdaja5cREBSCs9qh6S-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple has once again launched new Apple Watches, including the flagship <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-announced-everything-you-need-to-know-about-the-new-flagship-apple-watchhttps://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a> and premium <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explainedhttps://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4</a>. The question is, which one is right for you?</p><p>I'm here to help you answer that. Below, I've compared the Apple Watch Series 12 vs. Apple Watch Ultra 4 across seven categories, including cost, design, display, health and fitness, safety, AI, and battery life. Here's everything you need to know before you buy.</p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-specs-compared"><span>Apple Watch 12 vs Apple Watch Ultra 4: Specs compared</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Apple Watch Series 12</p></th><th  ><p>Apple Watch Ultra 4</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$399</p></td><td  ><p>$799</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>46mm: 46 x 40 x 9.7mm / 42mm: 42 x 37 x 9.7mm</p></td><td  ><p>49 x 44 x 12 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Case colors</strong></p></td><td  ><p>Aluminum: Dark Bronze, Light Gold, Black, Space Gray / Titanium: Radiant Gold, Natural / Ceramic: Pearl White, Night Blue</p><p></p></td><td  ><p>Titanium: Natural, Black</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>46mm:  416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p><p></p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td></tr><tr><td class="firstcol " ><p><strong>Display brightness</strong></p><p></p><p></p><p></p></td><td  ><p>2,000 nits</p></td><td  ><p>3,000 nits</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>46mm: ~ 39 g / 44mm: ~32 g</p></td><td  ><p>~63 g</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>S11</p></td><td  ><p>S11</p></td></tr><tr><td class="firstcol " ><p><strong>Cellular </strong></p></td><td  ><p>5G</p></td><td  ><p>5G</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>50 meters</p></td><td  ><p>100 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life with always-on display (rated)</strong></p></td><td  ><p>24 hours</p></td><td  ><p>50 hours</p></td></tr><tr><td class="firstcol " ><p><strong>Compatibility</strong></p></td><td  ><p>iOS 27 or later</p></td><td  ><p>iOS 27 or later</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-price"><span>Apple Watch 12 vs Apple Watch Ultra 4: Price</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="h9pUCaivgXc2tpjF4BPEu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/h9pUCaivgXc2tpjF4BPEu4-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>This is an easy one; the Apple Watch Series 12 <a href="https://www.apple.com/shop/buy-watch/apple-watch" target="_blank" rel="nofollow">starts at $399</a>, half the $799 cost of the Apple Watch Ultra 4. Even the priciest Series 12 configuration, 46mm with 5G+GPS, is $250 less than the latest Ultra model.</p><p>That said, if you opt for the Series 12 with an upgraded ceramic case (vs standard aluminum), it surpasses the Ultra 4 in cost: $899 for the 42mm and $949 for the 46mm. Note: there is no ceramic Apple Watch Ultra 4.</p><p>Both the Apple Watch Ultra 4 and Apple Watch Series 12 are available for preorder from September 9 with a September 18 ship date.</p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-design-and-durability"><span>Apple Watch 12 vs Apple Watch Ultra 4: Design and durability</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="q6RPuprHDQb5uHVE6hD8Cj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/q6RPuprHDQb5uHVE6hD8Cj-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>Even though the Apple Watch Series 12 features an upgraded Ceramic Shield 2 screen coating — which is 60% tougher than the Ion-X glass used on the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Series 11</a> — the Apple Watch Ultra 4 is hands-down the more rugged model.</p><p>The Ultra 4, like those before it, boasts 100 meters of water resistance, enough for scuba diving and double that of the Series 12. Additionally, the Ultra 4 sports a sapphire crystal display, which is more scratch-resistant than even Ion-X glass.</p><p>From a usability standpoint, the Ultra 4's design includes an additional, customizable "Action" button on the side of the case opposite the digital crown and side button. </p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-display"><span>Apple Watch 12 vs Apple Watch Ultra 4: Display</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="xv7TVM8BxL5mYTJonKP7Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/xv7TVM8BxL5mYTJonKP7Rj-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 Apple Watch Ultra 4 and Apple Watch Series 12 each use the same display as their respective predecessors. Ultimately, the Ultra 4's display offers slightly more real estate than the 46mm Apple Watch Series 12, and a noticeable amount more than the 42mm model.</p><p>You'll find LTPO3 wide-angle OLED panels with 326 pixels per inch of resolution in both the latest flagship and Ultra models, but the latter's display is more powerful than the former's.</p><p>While the Series 12 maxes out at a respectable 2,000 nits, which is generally bright enough for viewing in bright sunlight, the Ultra 4 reaches 3,000 nits of max brightness. In my experience, that's bright enough to read the screen in even direct sunlight.</p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-health-and-fitness-features"><span>Apple Watch 12 vs Apple Watch Ultra 4: Health and fitness features</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="K8NYBa9eZYZYr94Vnmnqr4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/K8NYBa9eZYZYr94Vnmnqr4-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>When it comes to onboard health and fitness tech and features, the Apple Watch Series 12 and Apple Watch Ultra 4 are essentially a match. They both have Apple's new, redesigned holistic sensor array, which promises far more accurate heart rate tracking, ECGs, and heart rate variability insights compared to prior Apple Watches.</p><p>Both watches support a wide range of trackable workout types, along with onboard GPS for logging outdoor activities without a paired phone, but the Ultra 4 has a more advanced dual-band antenna compared to a single-band GPS on the Series 12. </p><p>Translation: In settings with obstructed skies, like cities or forests, the Ultra 4 will likely generate slightly more accurate location-based data than the Series 12.</p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-safety-features"><span>Apple Watch 12 vs Apple Watch Ultra 4: Safety features</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:870px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="HuR9pqp3Cwh6SZFZi9tMBE" name="AW12-ECG" alt="Close-up of an ECG reading being performed using the Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/HuR9pqp3Cwh6SZFZi9tMBE-1920-80.jpg" mos="" align="middle" fullscreen="" width="870" height="489" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>Apple's latest smartwatches are each jam-packed with useful safety features, including fall and crash detection, high/low heart rate alerts, Hypertension Alerts, and sleep apnea notifications. However, the Ultra 4 (and Ultra 3) have one unique safety tool not found on any other Apple Watch: Emergency SOS via satellite.</p><p>This feature allows users to connect to a satellite, even without a paired smartphone and/or a cellular signal, and send a message to friends and/or emergency responders with location and other details.</p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-ai-features"><span>Apple Watch 12 vs Apple Watch Ultra 4: AI features</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="8bcbHKT8rtMP46JqtdXmRN" name="Apple Event — September 9 47-49 screenshot" alt="Live Rewind on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/8bcbHKT8rtMP46JqtdXmRN-1920-80.png" 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: Apple)</span></figcaption></figure><p>The Apple Watch 12 and Ultra 4 support the latest, greatest Siri AI-based features, including the onboard voice assistant itself, along with Live Rewind (lets you ‘go back in time’ up to 15 seconds), Sound Recognition(alerts users to sounds like sirens and alarms), and Siri Recap (takes high-level notes of conversations and generates summaries).</p><p>Some are concerned about potential privacy issues, but Apple stresses that Live Rewind only activates when you deliberately double-press the Digital Crown. In addition, audio is not recorded or stored for either feature and Siri Recap offers only AI summaries and not transcripts or speaker names.</p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-battery-life"><span>Apple Watch 12 vs Apple Watch Ultra 4: Battery life</span></h3><p>If you want the best battery life in an Apple Watch, your best bet is the Apple Watch Ultra 4, which is rated to last up to 50 hours per charge, more than double the 24-hour rating of the Apple Watch Series 12. </p><h3 class="article-body__section" id="section-apple-watch-12-vs-apple-watch-ultra-4-which-should-you-buy"><span>Apple Watch 12 vs Apple Watch Ultra 4: Which should you buy?</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AYP57Su3Eno7XWdwUbPfJj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-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>Apple has long been careful to differentiate the flagship Apple Watch series from the pricier Ultra series, and that's still the case in 2026. The Apple Watch Ultra 4 is tougher-built with double the water resistance, twice the battery life, a brighter screen, better GPS, and more impressive safety tools. </p><p>On the flip side, the Apple Watch Series 12 is much more affordable than the Ultra 4, with all the same cutting-edge health and fitness tools, AI features, and nearly the same-size screen (in the 46mm model). Oh, and it's also more comfortable on the wrist thanks to a slimmer case.</p><p>For most of us, the Apple Watch Series 12 is going to be the more sensible option. But if you fancy yourself to be a rugged, outdoor adventurer or hardcore athlete, then the extra cost of the Apple Watch Ultra 4 may be worth it.</p><p>Which new Apple Watch would you rather rock? Let me know in the comments.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xj2xlX"></div>                            </div>                            <script src="https://kwizly.com/embed/Xj2xlX.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><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model">Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-11-vs-apple-watch-ultra-3-which-one-should-you-buy">Apple Watch 11 vs Apple Watch Ultra 3 — which one should you buy?</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai">We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ All the new audio features on Apple Watch explained ]]></title>
                                                                                                <dc:content><![CDATA[ <p>One of the big revelations at yesterday's <a href="https://www.tomsguide.com/news/live/apple-event-live-foldable-iphone-iphone-18-pro-max-apple-watch-12-and-all-the-big-news">Apple event</a> was the new Siri AI features, and in particular, what these features mean for the new <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4</a>. The two new watches have built-in microphones and can now automatically detect music playing in the background and silently take notes on your conversations throughout the day to give you a recap. </p><p>Let's dive into all the new audio features coming to Apple Watch: </p><h3 class="article-body__section" id="section-sound-recognition"><span>Sound recognition </span></h3><p>Arguably the most helpful feature — especially for anyone hard of hearing or deaf — is the sound recognition feature. This allows your watch to detect important sounds like sirens, alarms, and doorbells and alert you, even if you don’t have your iPhone nearby. </p><h3 class="article-body__section" id="section-automatic-music-recognition"><span>Automatic music recognition </span></h3><p>If you’ve ever tried to Shazam a song and not been fast enough to catch it, this feature is for you. Music recognition automatically detects the song playing in the background and displays the name of the artist and the title in the Smart Stack. </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="ksjEAsDzPnVz4PFiyS54Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/ksjEAsDzPnVz4PFiyS54Rj-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-live-rewind"><span>Live Rewind </span></h3><p>Live Rewind allows you to double click on the Digital Crown and receive a transcript of what was said in the last 15 seconds. It’s designed to allow you to catch something you missed in a conversation, or to save yourself from awkwardness when you immediately forget your colleague’s name. Once recalled, you can ask Siri for more information, or save it to the Siri app. </p><p>When you press the Digital Crown for this feature, a chime will sound, even if your watch is on silent or you’re wearing headphones. Apple says this is to alert those nearby that you are using the feature.</p><h3 class="article-body__section" id="section-siri-recap"><span>Siri Recap </span></h3><p>Finally, when turned on, Siri recap will take notes of your conversations throughout the day and create Apple Intelligence-generated summaries you can use later. Summaries auto-delete after seven days if you haven’t saved them and you can set Siri recap to only record in certain locations, like at work, or during particular times of the day. </p><p>If all of this sounds like something you’d rather not use, Apple have stressed that each Audio Intelligence feature is automatically disabled on the watch: you have to opt-in to the ones you want to use. </p><p>The company also stressed that any data collected using Live Rewind or Siri Recap will be encrypted — you won’t be able to see who said what, and it doesn’t store voice recordings. Siri Recaps will also omit potentially harmful content, such as language promoting self-harm or hateful speech, and sensitive information, such as financial data.</p><p>These features will be available later in the year, and we’ll be sure to test them and bring you our verdict.</p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai">We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12 hands-on: A new heart rate sensor and a readiness score (at last)</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4 is official: All the upgrades explained</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained</link>
                                                                            <description>
                            <![CDATA[ Here's everything you need to know about the new audio features coming to the Apple Watch ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">se5wrxwDWrpuo8PK5wuXz4</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/W5QaBdWA6ZqoxGfUz3gDu4-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 11 Sep 2026 08:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></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/W5QaBdWA6ZqoxGfUz3gDu4-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Series 12]]></media:description>                                                            <media:text><![CDATA[Apple Watch Series 12]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Series 12]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/W5QaBdWA6ZqoxGfUz3gDu4-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>One of the big revelations at yesterday's <a href="https://www.tomsguide.com/news/live/apple-event-live-foldable-iphone-iphone-18-pro-max-apple-watch-12-and-all-the-big-news">Apple event</a> was the new Siri AI features, and in particular, what these features mean for the new <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4</a>. The two new watches have built-in microphones and can now automatically detect music playing in the background and silently take notes on your conversations throughout the day to give you a recap. </p><p>Let's dive into all the new audio features coming to Apple Watch: </p><h3 class="article-body__section" id="section-sound-recognition"><span>Sound recognition </span></h3><p>Arguably the most helpful feature — especially for anyone hard of hearing or deaf — is the sound recognition feature. This allows your watch to detect important sounds like sirens, alarms, and doorbells and alert you, even if you don’t have your iPhone nearby. </p><h3 class="article-body__section" id="section-automatic-music-recognition"><span>Automatic music recognition </span></h3><p>If you’ve ever tried to Shazam a song and not been fast enough to catch it, this feature is for you. Music recognition automatically detects the song playing in the background and displays the name of the artist and the title in the Smart Stack. </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="ksjEAsDzPnVz4PFiyS54Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/ksjEAsDzPnVz4PFiyS54Rj-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-live-rewind"><span>Live Rewind </span></h3><p>Live Rewind allows you to double click on the Digital Crown and receive a transcript of what was said in the last 15 seconds. It’s designed to allow you to catch something you missed in a conversation, or to save yourself from awkwardness when you immediately forget your colleague’s name. Once recalled, you can ask Siri for more information, or save it to the Siri app. </p><p>When you press the Digital Crown for this feature, a chime will sound, even if your watch is on silent or you’re wearing headphones. Apple says this is to alert those nearby that you are using the feature.</p><h3 class="article-body__section" id="section-siri-recap"><span>Siri Recap </span></h3><p>Finally, when turned on, Siri recap will take notes of your conversations throughout the day and create Apple Intelligence-generated summaries you can use later. Summaries auto-delete after seven days if you haven’t saved them and you can set Siri recap to only record in certain locations, like at work, or during particular times of the day. </p><p>If all of this sounds like something you’d rather not use, Apple have stressed that each Audio Intelligence feature is automatically disabled on the watch: you have to opt-in to the ones you want to use. </p><p>The company also stressed that any data collected using Live Rewind or Siri Recap will be encrypted — you won’t be able to see who said what, and it doesn’t store voice recordings. Siri Recaps will also omit potentially harmful content, such as language promoting self-harm or hateful speech, and sensitive information, such as financial data.</p><p>These features will be available later in the year, and we’ll be sure to test them and bring you our verdict.</p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai">We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">Apple Watch Series 12 hands-on: A new heart rate sensor and a readiness score (at last)</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4 is official: All the upgrades explained</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch Ultra 4 first impressions: 5 reasons to buy and 2 reasons to skip Apple’s new rugged model ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Shiny and new, shiny and new, we all love things that are shiny and new. Then again, just because something is fresh on the scene doesn’t necessarily mean it’s meaningfully better than its predecessor.</p><p>Hi, I’m Dan, and I review smartwatches. I’ve been covering the Apple Watch Ultra series ever since the first model launched. As you might expect, I had a long wishlist of upgrades for the fourth generation, many of which came to fruition!</p><p>Of course, not all my desires were fulfilled by the cult of Cupertino. With that in mind, here are the five biggest reasons I’m excited about the new <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a> (i.e., the five biggest reasons to buy it). </p><p>And for all the contrarians out there, I've also included the two biggest letdowns, aka why you might want to skip the Ultra 4.  </p><h3 class="article-body__section" id="section-buy-better-heart-rate-tracking"><span>Buy: Better heart rate tracking </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="wJzr9bqD5grXgaeqP9hXPj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/wJzr9bqD5grXgaeqP9hXPj-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>Apple went ahead and completely overhauled every aspect of the on-wrist holistic sensor array, including making the heart rate tracking LEDS more powerful and increasing the size of the electrode surface used for ECG readings.</p><p>Moreover, after extensive internal testing against the competition and a traditional chest-mounted heart rate monitor, Apple says that the Ultra 4 and Series 12 (which share the new holistic tech) are the most accurate heart trackers in any wearable on the market. </p><p>That’s not all; the new tech now takes heart rate readings every five minutes (60x times more frequently than the Ultra 3) and HRV readings every 15 minutes (24x more frequently than its predecessor) to better understand your long-term health trends. </p><h3 class="article-body__section" id="section-buy-new-live-rewind-feature"><span>Buy: New ‘Live Rewind’ feature</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="8bcbHKT8rtMP46JqtdXmRN" name="Apple Event — September 9 47-49 screenshot" alt="Live Rewind on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/8bcbHKT8rtMP46JqtdXmRN-1920-80.png" 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: Apple)</span></figcaption></figure><p>The <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-announced-everything-you-need-to-know-about-the-new-flagship-apple-watch">Apple Watch Series 12</a> are the first two Apple Watch models to ship with true-blue Siri AI features built-in, including my personal favorite, Live Rewind.</p><p>Are you someone who forgets names moments after they're told to you? Did you just zone out while the server read off tonight’s specials? Live Rewind allows you to discreetly listen back to the past 15 seconds of audio at any given moment with a double-tap of the digital crown. </p><p>Essentially, the watch is constantly buffering 15 seconds of ambient audio from your wrist. However, actual recordings are never saved, individual voices aren’t identified, and all of the data used for the feature is encrypted end-to-end. </p><h3 class="article-body__section" id="section-buy-improved-battery-life"><span>Buy: Improved battery life</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="AYP57Su3Eno7XWdwUbPfJj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-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>This is a biggie and an upgrade that tends to top my wishlist for pretty much every anticipated smartwatch release. The Apple Watch Ultra 4 is now rated to last up to 50 hours per charge, a noteworthy increase over its predecessor’s 42-hour rating. </p><p>For extreme athletes, there’s also a new Max Extended workout tracking mode that increases longevity from around 18 hours with full-time GPS and continuous heart rate tracking to a whopping 45 hours without sacrificing cardiovascular and location insights.</p><h3 class="article-body__section" id="section-buy-more-accurate-distance-and-step-count-tracking"><span>Buy: More accurate distance and step count tracking</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="xv7TVM8BxL5mYTJonKP7Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/xv7TVM8BxL5mYTJonKP7Rj-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><div><blockquote><p>Let me know in the comments which smartwatch I should test it against first!</p></blockquote></div><p>As one of TG’s <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-trekked-the-cascade-mountains-with-the-apple-watch-ultra-3-vs-garmin-instinct-3-vs-samsung-galaxy-watch-ultra-2-this-is-the-one-id-take-on-my-next-hike">resident smartwatch walk testers</a>, I couldn’t help but smile when I saw that the Apple Watch Ultra 4’s onboard pedometer software has been completely overhauled for better step count and distance tracking accuracy, thanks in part to machine learning. </p><p>Stay tuned for countless head-to-head walk test comparisons with the Ultra 4 versus the competition; let me know in the comments which smartwatch I should test it against first!</p><h3 class="article-body__section" id="section-buy-no-price-increase"><span>Buy: No price increase</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="qDRmPHVEoKiiwKKRJc9QVB" name="Apple Event — September 9 52-43 screenshot" alt="Apple Watch Ultra 4 pricing" src="https://cdn.mos.cms.futurecdn.net/qDRmPHVEoKiiwKKRJc9QVB-1920-80.png" 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: Apple)</span></figcaption></figure><p>Unlike those nerds over at Google and Samsung, Apple opted to keep its pricing for the 2026 line of smartwatches exactly the same as before, inflation and RAM crisis be damned! </p><p>This is commendable and, frankly, not very Apple-like. But, hey, there’s a new CEO in charge, so maybe the Apple of today and tomorrow will be a little more budget-minded than the Apple of yesterday. </p><h3 class="article-body__section" id="section-skip-same-display"><span>Skip: Same display</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="pZ83Xgm3USZxuey6qEgDuK" name="Apple Event — September 9 54-44 screenshot" alt="Ternus with Apple Watch 12 series" src="https://cdn.mos.cms.futurecdn.net/pZ83Xgm3USZxuey6qEgDuK-1920-80.png" 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: Apple)</span></figcaption></figure><p>The Apple Watch Ultra 4 sports the same exact display as its predecessor. Don’t get me wrong, it’s a fantastic panel that’s easy to read at just about any angle. It also boasts an impressive max brightness of 3,000 nits. </p><p>That said, the Apple Watch Ultra 4’s nearest competitor, the <a href="https://www.tomsguide.com/wellness/smartwatches/galaxy-watch-ultra-2-hands-on-review">Samsung Galaxy Watch Ultra 2</a>, boasts a max screen brightness of 5,000 nits. Ultimately, it would’ve been nice to see some sort of upgrade to the display in the Ultra 4, if only to keep up with its rivals.</p><h3 class="article-body__section" id="section-skip-it-s-still-gigantic"><span>Skip: It’s still gigantic </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="q6RPuprHDQb5uHVE6hD8Cj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/q6RPuprHDQb5uHVE6hD8Cj-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>Every year, come late August, I close my eyes and pray to Steve Jobs, asking him for the <em>one</em> thing that would make the latest Apple Watch Ultra a total slam-dunk: A smaller size option. And every year, I’m disappointed. </p><p>The Apple Watch Ultra 4 is the same dimensions as its predecessor, and even though it isn’t quite as chunky as the Samsung Galaxy Watch Ultra 2, it still wears rather large on my fairly average-sized 6.5-inch wrist. </p><p>Ultimately, in addition to the 49 x 44mm standard Ultra model, I’d loooove to see a second 45 x 40mm offering for those who prefer smaller wrist candy and/or have daintier extremities. </p><p>What are your thoughts on the new Apple Watch Ultra 4? What do you love, and what do you hate? Let me know below. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">I went hands-on with the Apple Watch Series 12: A new heart rate sensor, ceramic colors and a readiness score, at last</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai">We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4">I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-first-impressions-5-reasons-to-buy-and-2-reasons-to-skip-apples-new-rugged-model</link>
                                                                            <description>
                            <![CDATA[ I’ve covered every Apple Watch Ultra model, and here’s what I really think of the latest Ultra 4, including my biggest likes and dislikes. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">eZV8tw7cLVFtwEDZWq6MC</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/ksjEAsDzPnVz4PFiyS54Rj-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 10 Sep 2026 08:30:13 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/ksjEAsDzPnVz4PFiyS54Rj-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Ultra 4]]></media:description>                                                            <media:text><![CDATA[Apple Watch Ultra 4]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Ultra 4]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/ksjEAsDzPnVz4PFiyS54Rj-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Shiny and new, shiny and new, we all love things that are shiny and new. Then again, just because something is fresh on the scene doesn’t necessarily mean it’s meaningfully better than its predecessor.</p><p>Hi, I’m Dan, and I review smartwatches. I’ve been covering the Apple Watch Ultra series ever since the first model launched. As you might expect, I had a long wishlist of upgrades for the fourth generation, many of which came to fruition!</p><p>Of course, not all my desires were fulfilled by the cult of Cupertino. With that in mind, here are the five biggest reasons I’m excited about the new <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a> (i.e., the five biggest reasons to buy it). </p><p>And for all the contrarians out there, I've also included the two biggest letdowns, aka why you might want to skip the Ultra 4.  </p><h3 class="article-body__section" id="section-buy-better-heart-rate-tracking"><span>Buy: Better heart rate tracking </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="wJzr9bqD5grXgaeqP9hXPj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/wJzr9bqD5grXgaeqP9hXPj-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>Apple went ahead and completely overhauled every aspect of the on-wrist holistic sensor array, including making the heart rate tracking LEDS more powerful and increasing the size of the electrode surface used for ECG readings.</p><p>Moreover, after extensive internal testing against the competition and a traditional chest-mounted heart rate monitor, Apple says that the Ultra 4 and Series 12 (which share the new holistic tech) are the most accurate heart trackers in any wearable on the market. </p><p>That’s not all; the new tech now takes heart rate readings every five minutes (60x times more frequently than the Ultra 3) and HRV readings every 15 minutes (24x more frequently than its predecessor) to better understand your long-term health trends. </p><h3 class="article-body__section" id="section-buy-new-live-rewind-feature"><span>Buy: New ‘Live Rewind’ feature</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="8bcbHKT8rtMP46JqtdXmRN" name="Apple Event — September 9 47-49 screenshot" alt="Live Rewind on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/8bcbHKT8rtMP46JqtdXmRN-1920-80.png" 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: Apple)</span></figcaption></figure><p>The <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4">Apple Watch Ultra 4</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-announced-everything-you-need-to-know-about-the-new-flagship-apple-watch">Apple Watch Series 12</a> are the first two Apple Watch models to ship with true-blue Siri AI features built-in, including my personal favorite, Live Rewind.</p><p>Are you someone who forgets names moments after they're told to you? Did you just zone out while the server read off tonight’s specials? Live Rewind allows you to discreetly listen back to the past 15 seconds of audio at any given moment with a double-tap of the digital crown. </p><p>Essentially, the watch is constantly buffering 15 seconds of ambient audio from your wrist. However, actual recordings are never saved, individual voices aren’t identified, and all of the data used for the feature is encrypted end-to-end. </p><h3 class="article-body__section" id="section-buy-improved-battery-life"><span>Buy: Improved battery life</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="AYP57Su3Eno7XWdwUbPfJj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-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>This is a biggie and an upgrade that tends to top my wishlist for pretty much every anticipated smartwatch release. The Apple Watch Ultra 4 is now rated to last up to 50 hours per charge, a noteworthy increase over its predecessor’s 42-hour rating. </p><p>For extreme athletes, there’s also a new Max Extended workout tracking mode that increases longevity from around 18 hours with full-time GPS and continuous heart rate tracking to a whopping 45 hours without sacrificing cardiovascular and location insights.</p><h3 class="article-body__section" id="section-buy-more-accurate-distance-and-step-count-tracking"><span>Buy: More accurate distance and step count tracking</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="xv7TVM8BxL5mYTJonKP7Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/xv7TVM8BxL5mYTJonKP7Rj-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><div><blockquote><p>Let me know in the comments which smartwatch I should test it against first!</p></blockquote></div><p>As one of TG’s <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-trekked-the-cascade-mountains-with-the-apple-watch-ultra-3-vs-garmin-instinct-3-vs-samsung-galaxy-watch-ultra-2-this-is-the-one-id-take-on-my-next-hike">resident smartwatch walk testers</a>, I couldn’t help but smile when I saw that the Apple Watch Ultra 4’s onboard pedometer software has been completely overhauled for better step count and distance tracking accuracy, thanks in part to machine learning. </p><p>Stay tuned for countless head-to-head walk test comparisons with the Ultra 4 versus the competition; let me know in the comments which smartwatch I should test it against first!</p><h3 class="article-body__section" id="section-buy-no-price-increase"><span>Buy: No price increase</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="qDRmPHVEoKiiwKKRJc9QVB" name="Apple Event — September 9 52-43 screenshot" alt="Apple Watch Ultra 4 pricing" src="https://cdn.mos.cms.futurecdn.net/qDRmPHVEoKiiwKKRJc9QVB-1920-80.png" 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: Apple)</span></figcaption></figure><p>Unlike those nerds over at Google and Samsung, Apple opted to keep its pricing for the 2026 line of smartwatches exactly the same as before, inflation and RAM crisis be damned! </p><p>This is commendable and, frankly, not very Apple-like. But, hey, there’s a new CEO in charge, so maybe the Apple of today and tomorrow will be a little more budget-minded than the Apple of yesterday. </p><h3 class="article-body__section" id="section-skip-same-display"><span>Skip: Same display</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="pZ83Xgm3USZxuey6qEgDuK" name="Apple Event — September 9 54-44 screenshot" alt="Ternus with Apple Watch 12 series" src="https://cdn.mos.cms.futurecdn.net/pZ83Xgm3USZxuey6qEgDuK-1920-80.png" 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: Apple)</span></figcaption></figure><p>The Apple Watch Ultra 4 sports the same exact display as its predecessor. Don’t get me wrong, it’s a fantastic panel that’s easy to read at just about any angle. It also boasts an impressive max brightness of 3,000 nits. </p><p>That said, the Apple Watch Ultra 4’s nearest competitor, the <a href="https://www.tomsguide.com/wellness/smartwatches/galaxy-watch-ultra-2-hands-on-review">Samsung Galaxy Watch Ultra 2</a>, boasts a max screen brightness of 5,000 nits. Ultimately, it would’ve been nice to see some sort of upgrade to the display in the Ultra 4, if only to keep up with its rivals.</p><h3 class="article-body__section" id="section-skip-it-s-still-gigantic"><span>Skip: It’s still gigantic </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="q6RPuprHDQb5uHVE6hD8Cj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/q6RPuprHDQb5uHVE6hD8Cj-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>Every year, come late August, I close my eyes and pray to Steve Jobs, asking him for the <em>one</em> thing that would make the latest Apple Watch Ultra a total slam-dunk: A smaller size option. And every year, I’m disappointed. </p><p>The Apple Watch Ultra 4 is the same dimensions as its predecessor, and even though it isn’t quite as chunky as the Samsung Galaxy Watch Ultra 2, it still wears rather large on my fairly average-sized 6.5-inch wrist. </p><p>Ultimately, in addition to the 49 x 44mm standard Ultra model, I’d loooove to see a second 45 x 40mm offering for those who prefer smaller wrist candy and/or have daintier extremities. </p><p>What are your thoughts on the new Apple Watch Ultra 4? What do you love, and what do you hate? Let me know below. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">I went hands-on with the Apple Watch Series 12: A new heart rate sensor, ceramic colors and a readiness score, at last</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai">We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4">I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch Series 12 hands-on: A new heart rate sensor and a readiness score (at last) ]]></title>
                                                                                                <dc:content><![CDATA[ <p>"Your heart tells a story of your health, and it’s a story worth hearing," said Apple, as it announced the updated Apple Watch Series 12, with the most accurate heart rate sensor yet. It's not often a tech keynote makes me emotional, but as a health writer, this one did. Maybe I'm jet-lagged, or maybe I believe that these huge health updates might make this the best smartwatch on the market. </p><p>I spend my days writing about how the best prediction of longevity is how healthy your heart is. With a new heart rate sensor, the Apple Watch Series 12 gives you a heart rate reading every five seconds, 60 times more frequent than the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch Series 11</a>. This supports HRV readings, a new readiness score that gives you deeper insights into when to push and when to recover, and new longevity features in the updated Health app.</p><p>With a built-in microphone for audio intelligence features and new ceramic colors, there's a lot to like about this new watch. Read my hands-on review of the Apple Watch Series 12 below to find out more. </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/2qNfOa5AuVU" allowfullscreen></iframe></div></div><h3 class="article-body__section" id="section-apple-watch-series-12-quick-facts"><span>Apple Watch Series 12: Quick facts </span></h3><ul><li><strong>Same 24-hour battery life</strong>: Despite the addition of continuous heart rate monitoring, the Apple Watch Series 12 has the same 24-hour battery life as the Series 11</li><li><strong>New S11 chip: </strong>Faster, more efficient processing with support for Siri AI features</li><li><strong>Redesigned holistic sensors:</strong> Apple says this is the most accurate heart rate sensor on a wearable; heart rate and HRV are sampled more frequently than before; HRV insights are now more readily displayed in the Health app</li><li><strong>New health metrics:</strong> Series 12 supports a new Readiness score and Health Age metric</li><li><strong>Siri AI features: </strong>The watch ships with support for Siri AI voice assistance; new "Audio Intelligence" features help you better navigate life's fine details</li></ul><h3 class="article-body__section" id="section-apple-watch-series-12-hands-on-specs"><span>Apple Watch Series 12 hands-on: Specs</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Apple Watch Series 12</p></th><th  ><p>Apple Watch Series 11</p></th><th  ><p>Apple Watch Ultra 4</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$399</p></td><td  ><p>$399</p></td><td  ><p>$799</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>46mm: 46 x 40 x 9.7mm / 42mm: 42 x 37 x 9.7mm</p></td><td  ><p>46mm: 46 x 39 x 9.7mm / 42mm: 42 x 36 x 9.7mm</p></td><td  ><p>49 x 44 x 12 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Case colors</strong></p></td><td  ><p>Aluminum: Dark Bronze, Light Gold, Black, Space Gray / Titanium: Radiant Gold, Natural / Ceramic: Pearl White, Night Blue</p><p></p></td><td  ><p>Aluminum: Rose Gold, Silver, Space Gray, Jet Black / Titanium: Gold, Natural, Slate</p></td><td  ><p>Titanium: Natural, Black</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>46mm:  416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p><p></p></td><td  ><p>46mm: 416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td></tr><tr><td class="firstcol " ><p><strong>Display brightness</strong></p><p></p><p></p><p></p></td><td  ><p>2,000 nits</p></td><td  ><p>2,000 nits</p></td><td  ><p>3,000 nits</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>46mm: ~ 39 g / 44mm: ~32 g</p></td><td  ><p>46mm: 37.8 g / 44mm: 30.3 g</p></td><td  ><p>~63 g</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>S11</p></td><td  ><p>S10</p></td><td  ><p>S11</p></td></tr><tr><td class="firstcol " ><p><strong>Cellular </strong></p></td><td  ><p>5G</p></td><td  ><p>5G</p></td><td  ><p>56</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>50 meters</p></td><td  ><p>50 meters</p></td><td  ><p>100 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life with always-on display (rated)</strong></p></td><td  ><p>24 hours</p></td><td  ><p>24 hours</p></td><td  ><p>50 hours</p></td></tr><tr><td class="firstcol " ><p><strong>Compatibility</strong></p></td><td  ><p>iOS 27 or later</p></td><td  ><p>iOS 26 or later</p></td><td  ><p>iOS 27 or later</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-apple-watch-series-12-hands-on-review-price-and-availability"><span>Apple Watch Series 12 hands-on review: Price and availability </span></h3><p>The Apple Watch Series 12 is available for preorder starting September 9, with units expected to arrive on September 18. The Series 12 has the same starting cost as the Series 11 — $399. </p><p>In addition to the standard aluminum and upgraded titanium case options, the Apple Watch Series 12 is also available in two ceramic finishes: Pearl White and Night Blue. </p><p>See a full breakdown of pricing for all the case options and sizes below</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="xRW6Xa7uF7PNUugA3vFxv4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/xRW6Xa7uF7PNUugA3vFxv4-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><ul><li><strong>Apple Watch Series 12, 42mm, GPS (Aluminum): $399</strong></li><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Aluminum): $499</strong></li><li><strong>Apple Watch Series 12, 46mm, GPS (Aluminum): $449</strong></li><li><strong>Apple Watch Series 12, 46mm, GPS+5G (Aluminum): $549</strong></li></ul><ul><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Titanium): $699</strong></li><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Titanium): $749</strong></li></ul><ul><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Ceramic): $899</strong></li><li><strong>Apple Watch Series 12, 42mm, GPS+5 (Ceramic): $949</strong></li></ul><h3 class="article-body__section" id="section-apple-watch-series-12-hands-on-review-design-and-display"><span>Apple Watch Series 12 hands-on review: Design and display </span></h3><p>Design-wise, the Apple Watch Series 12 looks pretty identical to the Apple Watch Series 11. That said, with Series 12, Apple has released some new colors: there's now a dark bronze in the aluminum case, radiant gold in the titanium case and all-new ceramic cases in pearl white and night blue.</p><p>The ceramic pearl white looks beautiful in person, and the radiant gold is a close runner-up in my eyes. </p><p>The biggest difference design-wise is on the back of the watch: the heart rate sensor has been completely redesigned. More on that below. </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="s5kSpqHJhfuo5782A4unU4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/s5kSpqHJhfuo5782A4unU4-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-apple-watch-series-12-hands-on-review-health-tracking"><span>Apple Watch Series 12 hands-on review: Health tracking</span></h3><p>Both the Apple Watch Series 12 and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a> feature a completely new heart rate monitor, which Apple says offers the most accurate heart rate tracking in a wearable. </p><p>When looking at the two monitors side-by-side, the Series 12 and Ultra 4 have a “32-petal design,” whereas the older watches had a two-petal design. This refers to the spoke-like lines coming out of the electrode. The green LED lights, which measure your heart rate by shining light into the skin, are bigger and more powerful. This supposedly makes the heart rate tracking more accurate. </p><p>Heart rate data lies at the heart of a lot of health features on the Apple Watch, including HRV, workouts, and ovulation prediction. The new sensors all feed into the new daily Readiness score that is based on your recent workouts, sleep quality, and vitals. There's also a new Health Age score that compares your physical fitness to the average for your age range.</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="H4nJDVCkJRhdcJkJh9Hiv4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/H4nJDVCkJRhdcJkJh9Hiv4-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 will, of course, be testing the readiness score, and the heart rate tracking over the next week. You need a week's worth of data, including seven nights of sleep longer than four hours to recieve a readiness score. The readiness score will not roll out to older models, as it relies on the continuous heart rate monitoring offered on the Apple Watch Series 12.</p><p>Later this year, a redesigned Health app is expected to launch with a greater emphasis on long-term trend reporting and actionable Siri AI-powered insights and advice. </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="gBWZFzx3Kqd4Nd7BEsg8D4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/gBWZFzx3Kqd4Nd7BEsg8D4-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-apple-watch-series-12-hands-on-review-ai-features"><span>Apple Watch Series 12 hands-on review: AI features</span></h3><p>The Apple Watch Series 12 ships running <a href="https://www.tomsguide.com/wellness/smartwatches/watchos-27-all-the-new-features-coming-to-apple-watch-later-this-year">watchOS 27</a>, which means that it's one of the very first Apple Watch models to support Apple's Siri AI voice assistant, which is trained to answer queries and provide context-based guidance tailored to the individual user.</p><p>Siri AI also powers a handful of new "Audio Intelligence" features like Live Rewind, which lets you go back and listen to the past 15 seconds of ambient sound at any given time by double-pressing the digital crown.</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="W5QaBdWA6ZqoxGfUz3gDu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/W5QaBdWA6ZqoxGfUz3gDu4-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>Not the best note-taker? Siri Recap can listen into your conversation or meeting and automatically generate a report highlighting key topics, along with an overall summary of what was discussed.</p><p>Finally, Series 12 supports Apple's Sound Recognition technology, which can automatically alert users when common sounds like a doorbell or fire alarm are observed. </p><h3 class="article-body__section" id="section-apple-watch-series-12-hands-on-review-battery-life"><span>Apple Watch Series 12 hands-on review: Battery life</span></h3><p>The Apple Watch Series 12 has the same 24 hours of battery life as the Series 11, but Apple have given us faster charging as well as a bunch of new sensors. You can now get up to 80% charge in about 30 minutes, 15 minutes for up to 12 hours of normal use and 5 minutes for up to 10 hours of sleep tracking.</p><p>I will, of course, be testing the battery life claims. </p><h3 class="article-body__section" id="section-apple-watch-series-12-hands-on-review-should-you-buy"><span>Apple Watch Series 12 hands-on review: Should you buy?</span></h3><p>It's too soon for me to say yes, you should buy this watch over the Apple Watch Series 11, but based on my brief experience with the watch, the ceramic casing is beautiful. </p><p>While the Siri AI elements are cool, what's more impressive, in my opinion, is the heart rate sensor. </p><p>My full review of the Apple Watch Series 12 will be dropping later this month, so stay tuned. </p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice"><strong>iPhone Duo hands-on: Apple nailed it — and just put everyone else on notice</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained"><strong>Apple Watch Ultra 4 is official: All the upgrades explained</strong></a></li><li><a href="https://www.tomsguide.com/news/live/apple-event-live-foldable-iphone-iphone-18-pro-max-apple-watch-12-and-all-the-big-news"><strong>Apple Event live blog — Hands-on with the iPhone Duo and all the big announcements including the iPhone 18 Pro Max, Apple Watch 12</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12</link>
                                                                            <description>
                            <![CDATA[ We've been hands-on with the new Apple Watch Series 12. Here's everything you need to know about Apple's new flagship watch ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">q8wNUgVQxzu6L2AvHzGLxM</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/h9pUCaivgXc2tpjF4BPEu4-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 23:40:13 +0000</pubDate>                                                                                                                                <updated>Thu, 10 Sep 2026 06:15:47 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></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/h9pUCaivgXc2tpjF4BPEu4-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Series 12]]></media:description>                                                            <media:text><![CDATA[Apple Watch Series 12]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Series 12]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/h9pUCaivgXc2tpjF4BPEu4-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>"Your heart tells a story of your health, and it’s a story worth hearing," said Apple, as it announced the updated Apple Watch Series 12, with the most accurate heart rate sensor yet. It's not often a tech keynote makes me emotional, but as a health writer, this one did. Maybe I'm jet-lagged, or maybe I believe that these huge health updates might make this the best smartwatch on the market. </p><p>I spend my days writing about how the best prediction of longevity is how healthy your heart is. With a new heart rate sensor, the Apple Watch Series 12 gives you a heart rate reading every five seconds, 60 times more frequent than the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch Series 11</a>. This supports HRV readings, a new readiness score that gives you deeper insights into when to push and when to recover, and new longevity features in the updated Health app.</p><p>With a built-in microphone for audio intelligence features and new ceramic colors, there's a lot to like about this new watch. Read my hands-on review of the Apple Watch Series 12 below to find out more. </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/2qNfOa5AuVU" allowfullscreen></iframe></div></div><h3 class="article-body__section" id="section-apple-watch-series-12-quick-facts"><span>Apple Watch Series 12: Quick facts </span></h3><ul><li><strong>Same 24-hour battery life</strong>: Despite the addition of continuous heart rate monitoring, the Apple Watch Series 12 has the same 24-hour battery life as the Series 11</li><li><strong>New S11 chip: </strong>Faster, more efficient processing with support for Siri AI features</li><li><strong>Redesigned holistic sensors:</strong> Apple says this is the most accurate heart rate sensor on a wearable; heart rate and HRV are sampled more frequently than before; HRV insights are now more readily displayed in the Health app</li><li><strong>New health metrics:</strong> Series 12 supports a new Readiness score and Health Age metric</li><li><strong>Siri AI features: </strong>The watch ships with support for Siri AI voice assistance; new "Audio Intelligence" features help you better navigate life's fine details</li></ul><h3 class="article-body__section" id="section-apple-watch-series-12-hands-on-specs"><span>Apple Watch Series 12 hands-on: Specs</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Apple Watch Series 12</p></th><th  ><p>Apple Watch Series 11</p></th><th  ><p>Apple Watch Ultra 4</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$399</p></td><td  ><p>$399</p></td><td  ><p>$799</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>46mm: 46 x 40 x 9.7mm / 42mm: 42 x 37 x 9.7mm</p></td><td  ><p>46mm: 46 x 39 x 9.7mm / 42mm: 42 x 36 x 9.7mm</p></td><td  ><p>49 x 44 x 12 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Case colors</strong></p></td><td  ><p>Aluminum: Dark Bronze, Light Gold, Black, Space Gray / Titanium: Radiant Gold, Natural / Ceramic: Pearl White, Night Blue</p><p></p></td><td  ><p>Aluminum: Rose Gold, Silver, Space Gray, Jet Black / Titanium: Gold, Natural, Slate</p></td><td  ><p>Titanium: Natural, Black</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>46mm:  416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p><p></p></td><td  ><p>46mm: 416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td></tr><tr><td class="firstcol " ><p><strong>Display brightness</strong></p><p></p><p></p><p></p></td><td  ><p>2,000 nits</p></td><td  ><p>2,000 nits</p></td><td  ><p>3,000 nits</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>46mm: ~ 39 g / 44mm: ~32 g</p></td><td  ><p>46mm: 37.8 g / 44mm: 30.3 g</p></td><td  ><p>~63 g</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>S11</p></td><td  ><p>S10</p></td><td  ><p>S11</p></td></tr><tr><td class="firstcol " ><p><strong>Cellular </strong></p></td><td  ><p>5G</p></td><td  ><p>5G</p></td><td  ><p>56</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>50 meters</p></td><td  ><p>50 meters</p></td><td  ><p>100 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life with always-on display (rated)</strong></p></td><td  ><p>24 hours</p></td><td  ><p>24 hours</p></td><td  ><p>50 hours</p></td></tr><tr><td class="firstcol " ><p><strong>Compatibility</strong></p></td><td  ><p>iOS 27 or later</p></td><td  ><p>iOS 26 or later</p></td><td  ><p>iOS 27 or later</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-apple-watch-series-12-hands-on-review-price-and-availability"><span>Apple Watch Series 12 hands-on review: Price and availability </span></h3><p>The Apple Watch Series 12 is available for preorder starting September 9, with units expected to arrive on September 18. The Series 12 has the same starting cost as the Series 11 — $399. </p><p>In addition to the standard aluminum and upgraded titanium case options, the Apple Watch Series 12 is also available in two ceramic finishes: Pearl White and Night Blue. </p><p>See a full breakdown of pricing for all the case options and sizes below</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="xRW6Xa7uF7PNUugA3vFxv4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/xRW6Xa7uF7PNUugA3vFxv4-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><ul><li><strong>Apple Watch Series 12, 42mm, GPS (Aluminum): $399</strong></li><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Aluminum): $499</strong></li><li><strong>Apple Watch Series 12, 46mm, GPS (Aluminum): $449</strong></li><li><strong>Apple Watch Series 12, 46mm, GPS+5G (Aluminum): $549</strong></li></ul><ul><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Titanium): $699</strong></li><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Titanium): $749</strong></li></ul><ul><li><strong>Apple Watch Series 12, 42mm, GPS+5G (Ceramic): $899</strong></li><li><strong>Apple Watch Series 12, 42mm, GPS+5 (Ceramic): $949</strong></li></ul><h3 class="article-body__section" id="section-apple-watch-series-12-hands-on-review-design-and-display"><span>Apple Watch Series 12 hands-on review: Design and display </span></h3><p>Design-wise, the Apple Watch Series 12 looks pretty identical to the Apple Watch Series 11. That said, with Series 12, Apple has released some new colors: there's now a dark bronze in the aluminum case, radiant gold in the titanium case and all-new ceramic cases in pearl white and night blue.</p><p>The ceramic pearl white looks beautiful in person, and the radiant gold is a close runner-up in my eyes. </p><p>The biggest difference design-wise is on the back of the watch: the heart rate sensor has been completely redesigned. More on that below. </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="s5kSpqHJhfuo5782A4unU4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/s5kSpqHJhfuo5782A4unU4-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-apple-watch-series-12-hands-on-review-health-tracking"><span>Apple Watch Series 12 hands-on review: Health tracking</span></h3><p>Both the Apple Watch Series 12 and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a> feature a completely new heart rate monitor, which Apple says offers the most accurate heart rate tracking in a wearable. </p><p>When looking at the two monitors side-by-side, the Series 12 and Ultra 4 have a “32-petal design,” whereas the older watches had a two-petal design. This refers to the spoke-like lines coming out of the electrode. The green LED lights, which measure your heart rate by shining light into the skin, are bigger and more powerful. This supposedly makes the heart rate tracking more accurate. </p><p>Heart rate data lies at the heart of a lot of health features on the Apple Watch, including HRV, workouts, and ovulation prediction. The new sensors all feed into the new daily Readiness score that is based on your recent workouts, sleep quality, and vitals. There's also a new Health Age score that compares your physical fitness to the average for your age range.</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="H4nJDVCkJRhdcJkJh9Hiv4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/H4nJDVCkJRhdcJkJh9Hiv4-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 will, of course, be testing the readiness score, and the heart rate tracking over the next week. You need a week's worth of data, including seven nights of sleep longer than four hours to recieve a readiness score. The readiness score will not roll out to older models, as it relies on the continuous heart rate monitoring offered on the Apple Watch Series 12.</p><p>Later this year, a redesigned Health app is expected to launch with a greater emphasis on long-term trend reporting and actionable Siri AI-powered insights and advice. </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="gBWZFzx3Kqd4Nd7BEsg8D4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/gBWZFzx3Kqd4Nd7BEsg8D4-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-apple-watch-series-12-hands-on-review-ai-features"><span>Apple Watch Series 12 hands-on review: AI features</span></h3><p>The Apple Watch Series 12 ships running <a href="https://www.tomsguide.com/wellness/smartwatches/watchos-27-all-the-new-features-coming-to-apple-watch-later-this-year">watchOS 27</a>, which means that it's one of the very first Apple Watch models to support Apple's Siri AI voice assistant, which is trained to answer queries and provide context-based guidance tailored to the individual user.</p><p>Siri AI also powers a handful of new "Audio Intelligence" features like Live Rewind, which lets you go back and listen to the past 15 seconds of ambient sound at any given time by double-pressing the digital crown.</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="W5QaBdWA6ZqoxGfUz3gDu4" name="Apple Watch Series 12" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/W5QaBdWA6ZqoxGfUz3gDu4-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>Not the best note-taker? Siri Recap can listen into your conversation or meeting and automatically generate a report highlighting key topics, along with an overall summary of what was discussed.</p><p>Finally, Series 12 supports Apple's Sound Recognition technology, which can automatically alert users when common sounds like a doorbell or fire alarm are observed. </p><h3 class="article-body__section" id="section-apple-watch-series-12-hands-on-review-battery-life"><span>Apple Watch Series 12 hands-on review: Battery life</span></h3><p>The Apple Watch Series 12 has the same 24 hours of battery life as the Series 11, but Apple have given us faster charging as well as a bunch of new sensors. You can now get up to 80% charge in about 30 minutes, 15 minutes for up to 12 hours of normal use and 5 minutes for up to 10 hours of sleep tracking.</p><p>I will, of course, be testing the battery life claims. </p><h3 class="article-body__section" id="section-apple-watch-series-12-hands-on-review-should-you-buy"><span>Apple Watch Series 12 hands-on review: Should you buy?</span></h3><p>It's too soon for me to say yes, you should buy this watch over the Apple Watch Series 11, but based on my brief experience with the watch, the ceramic casing is beautiful. </p><p>While the Siri AI elements are cool, what's more impressive, in my opinion, is the heart rate sensor. </p><p>My full review of the Apple Watch Series 12 will be dropping later this month, so stay tuned. </p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice"><strong>iPhone Duo hands-on: Apple nailed it — and just put everyone else on notice</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained"><strong>Apple Watch Ultra 4 is official: All the upgrades explained</strong></a></li><li><a href="https://www.tomsguide.com/news/live/apple-event-live-foldable-iphone-iphone-18-pro-max-apple-watch-12-and-all-the-big-news"><strong>Apple Event live blog — Hands-on with the iPhone Duo and all the big announcements including the iPhone 18 Pro Max, Apple Watch 12</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I just went hands on with the Apple Watch Ultra 4: Better battery, improved heart health tracking, and new holistic features galore ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The new <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a> is here, and while it may look identical to its predecessor, I assure you it is not. Under the hood, the Ultra 4 sports a new, speedier processor, a more accurate/robust health sensor array, better battery life, and lots of cool AI tools. </p><p>Here's everything you need to know about the new Apple Watch Ultra 4 smartwatch based on our hands-on experience with the device at the official "Surprise and Shine" launch event in Cupertino, California. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-quick-facts"><span>Apple Watch Ultra 4: Quick facts </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="ksjEAsDzPnVz4PFiyS54Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/ksjEAsDzPnVz4PFiyS54Rj-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><ul><li><strong>Improved battery life:</strong> lasts up to 50 hours per charge compared to 42 hours for the Ultra 3</li><li><strong>New S11 chip: </strong>Faster, more efficient processing with support for Siri AI features</li><li><strong>Redesigned holistic sensors:</strong> Apple says this is the most accurate heart rate sensor on a wearable; heart rate and HRV are sampled more frequently than before; HRV insights are now more readily displayed in the Health app</li><li><strong>New health metrics:</strong> the Ultra 4 supports a new Readiness score and Health Age metric</li><li><strong>Siri AI features: </strong>the Ultra 4 ships with support for Siri AI voice assistance; new  "Audio Intelligence" features help you better navigate life's fine details</li></ul><h3 class="article-body__section" id="section-apple-watch-ultra-4-specs"><span>Apple Watch Ultra 4: Specs</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Apple Watch Ultra 4</p></th><th  ><p>Apple Watch Ultra 3</p></th><th  ><p>Apple Watch Series 12</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$799 / AU$1,349</p></td><td  ><p>$799 / AU$1,399</p></td><td  ><p>$399 / AU$649</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>49 x 44 x 12 mm</p></td><td  ><p>49 x 44 x 12 mm</p></td><td  ><p>46mm: 46 x 40 x 9.7mm / 42mm: 42 x 37 x 9.7mm</p></td></tr><tr><td class="firstcol " ><p><strong>Case colors</strong></p></td><td  ><p>Titanium: Natural, Black</p></td><td  ><p>Titanium: Natural, Black</p></td><td  ><p>Aluminum: Dark Bronze, Light Gold, Black, Space Gray / Titanium: Radiant Gold, Natural / Ceramic: Pearl White, Night Blue</p><p></p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td><td  ><p>46mm:  416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p><p></p></td></tr><tr><td class="firstcol " ><p><strong>Display brightness</strong></p><p></p><p></p><p></p></td><td  ><p>3,000 nits</p></td><td  ><p>3,000 nits</p></td><td  ><p>2,000 nits</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>~63 g</p></td><td  ><p>~61 g</p></td><td  ><p>46mm: ~ 39 g / 44mm: ~32 g</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>S11</p></td><td  ><p>S10</p></td><td  ><p>S11</p></td></tr><tr><td class="firstcol " ><p><strong>Cellular </strong></p></td><td  ><p>56</p></td><td  ><p>5G</p></td><td  ><p>5G</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>100 meters</p></td><td  ><p>100 meters</p></td><td  ><p>50 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life with always-on display (rated)</strong></p></td><td  ><p>50 hours</p></td><td  ><p>42 hours</p></td><td  ><p>24 hours</p></td></tr><tr><td class="firstcol " ><p><strong>Compatibility</strong></p></td><td  ><p>iOS 27 or later</p></td><td  ><p>iOS 26 or later</p></td><td  ><p>iOS 27 or later</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-apple-watch-ultra-4-hands-on-review-price-and-availability"><span>Apple Watch Ultra 4 hands-on review: Price and availability </span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1338px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="93pm4CaurnZ79Nk8fsTgiP" name="AWU4-02" alt="Close-up of the Apple Watch Ultra 4 side profile" src="https://cdn.mos.cms.futurecdn.net/93pm4CaurnZ79Nk8fsTgiP-1920-80.jpg" mos="" align="middle" fullscreen="" width="1338" height="753" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>The Apple Watch Ultra 4 is available for preorder from September 9, 2026. Units should hit store shelves and your hands starting on September 18. </p><p>The Apple Watch Ultra 4 is $799 / AU$1,349, the same price as the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a> and prior models. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-hands-on-review-design-and-display"><span>Apple Watch Ultra 4 hands-on review: Design and display </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="q6RPuprHDQb5uHVE6hD8Cj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/q6RPuprHDQb5uHVE6hD8Cj-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 Apple Watch Ultra 4 looks physically identical to the Ultra 3, boasting the same dimensions, oversized display with 3,000 nits of max brightness, an all-titanium case, and 100 meters of water resistance. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-hands-on-review-health-and-fitness-upgrades"><span>Apple Watch Ultra 4 hands-on review: Health and fitness upgrades</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="wJzr9bqD5grXgaeqP9hXPj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/wJzr9bqD5grXgaeqP9hXPj-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>Apple totally redesigned the health sensor array on the Ultra 4 to make its heart rate data more accurate, efficient, and frequently sampled. The new health sensing system now samples your heart rate every five seconds, 60x more frequently than its predecessor.</p><p>It also reads your heart rate variability every 15 seconds, a 24x increase in frequency over the Ultra 3. Apple also completely reworked the pedometer algorithm for improved step count accuracy and more precise distance data when logging an outdoor workout. </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="xv7TVM8BxL5mYTJonKP7Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/xv7TVM8BxL5mYTJonKP7Rj-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>Apple is also adding several handy new metrics to the Health app, including a daily Readiness score that is based on your recent workouts, sleep quality, and vitals. There's also a new Health Age score that compares your physical fitness to the average for your age range.</p><p>Later this year, a redesigned Health app is expected to launch with a greater emphasis on long-term trend reporting and actionable Siri AI-powered insights and advice. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-hands-on-review-ai-features"><span>Apple Watch Ultra 4 hands-on review: AI features </span></h3><p>The Apple Watch Ultra 4 ships running <a href="https://www.tomsguide.com/wellness/smartwatches/watchos-27-all-the-new-features-coming-to-apple-watch-later-this-year">watchOS 27</a>, which means that it's one of the very first Apple Watch models to support Apple's Siri AI voice assistant, which is trained to answer queries and provide context-based guidance tailored to the individual user.</p><p>Siri AI also powers a handful of new "Audio Intelligence" features like Live Rewind, which lets you go back and relisten to the past 15 seconds of ambient sound at any given time by double-pressing the digital crown.</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="8bcbHKT8rtMP46JqtdXmRN" name="Apple Event — September 9 47-49 screenshot" alt="Live Rewind on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/8bcbHKT8rtMP46JqtdXmRN-1920-80.png" 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: Apple)</span></figcaption></figure><p>Not the best note-taker? Siri Recap can listen into your conversation or meeting and automatically generate a report highlighting key topics, along with an overall summary of what was discussed.</p><p>Finally, the Ultra 4 supports Apple's Sound Recognition technology, which can automatically alert users when common sounds like a doorbell or fire alarm are observed. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-hands-on-review-battery-life"><span>Apple Watch Ultra 4 hands-on review: Battery life</span></h3><div><blockquote><p>The Ultra 4 sees a welcome battery life rating increase from 42 hours per charge to 50 hours per charge.</p></blockquote></div><p>The Apple Watch Ultra series has always been the brand's longest-lasting, and the latest Ultra 4 sees a welcome battery life rating increase from 42 hours per charge to 50 hours per charge. </p><p>When recording outdoor workouts with full heart rate and GPS data, the Ultra 4 is rated for roughly 18 hours per charge. However, a new Max Extended tracking mode increases that rating to an impressive 45 hours of use per charge.</p><h3 class="article-body__section" id="section-apple-watch-ultra-4-hands-on-review-should-you-buy"><span>Apple Watch Ultra 4 hands-on review: Should you buy?</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="D2MaHGKfuSAn5WQsdoHV86" name="Apple Event — September 9 52-32 screenshot" alt="Apple Watch Ultra 4 Fact Sheet" src="https://cdn.mos.cms.futurecdn.net/D2MaHGKfuSAn5WQsdoHV86-1920-80.png" 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: Apple)</span></figcaption></figure><p>Without thoroughly testing the improved battery life, health tracking, and outdoor workout logging claims, it's impossible to say for certain whether the Apple Watch Ultra 4 is a must-buy. The same goes for all the new holistic tools and AI features.</p><p>Furthermore, some of the advertised upgrades won't be available right at launch; the redesigned Health app with improved longevity insights and custom-tailored holistic advice won't be ready until later this year.</p><p>This is to say, it's probably best to hold off on dropping serious dough on the Ultra 4 until our full review is live later this month. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4</link>
                                                                            <description>
                            <![CDATA[ We've been hands-on with the new Apple Watch Ultra 4. Here's everything you need to know about this new rugged, sporty model. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">KMpHXSpZKbyMjW7NvCmzVQ</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 22:09:51 +0000</pubDate>                                                                                                                                <updated>Thu, 10 Sep 2026 08:12:52 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/AYP57Su3Eno7XWdwUbPfJj-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Ultra 4]]></media:description>                                                            <media:text><![CDATA[Apple Watch Ultra 4]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Ultra 4]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/AYP57Su3Eno7XWdwUbPfJj-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The new <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a> is here, and while it may look identical to its predecessor, I assure you it is not. Under the hood, the Ultra 4 sports a new, speedier processor, a more accurate/robust health sensor array, better battery life, and lots of cool AI tools. </p><p>Here's everything you need to know about the new Apple Watch Ultra 4 smartwatch based on our hands-on experience with the device at the official "Surprise and Shine" launch event in Cupertino, California. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-quick-facts"><span>Apple Watch Ultra 4: Quick facts </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="ksjEAsDzPnVz4PFiyS54Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/ksjEAsDzPnVz4PFiyS54Rj-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><ul><li><strong>Improved battery life:</strong> lasts up to 50 hours per charge compared to 42 hours for the Ultra 3</li><li><strong>New S11 chip: </strong>Faster, more efficient processing with support for Siri AI features</li><li><strong>Redesigned holistic sensors:</strong> Apple says this is the most accurate heart rate sensor on a wearable; heart rate and HRV are sampled more frequently than before; HRV insights are now more readily displayed in the Health app</li><li><strong>New health metrics:</strong> the Ultra 4 supports a new Readiness score and Health Age metric</li><li><strong>Siri AI features: </strong>the Ultra 4 ships with support for Siri AI voice assistance; new  "Audio Intelligence" features help you better navigate life's fine details</li></ul><h3 class="article-body__section" id="section-apple-watch-ultra-4-specs"><span>Apple Watch Ultra 4: Specs</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Apple Watch Ultra 4</p></th><th  ><p>Apple Watch Ultra 3</p></th><th  ><p>Apple Watch Series 12</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$799 / AU$1,349</p></td><td  ><p>$799 / AU$1,399</p></td><td  ><p>$399 / AU$649</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>49 x 44 x 12 mm</p></td><td  ><p>49 x 44 x 12 mm</p></td><td  ><p>46mm: 46 x 40 x 9.7mm / 42mm: 42 x 37 x 9.7mm</p></td></tr><tr><td class="firstcol " ><p><strong>Case colors</strong></p></td><td  ><p>Titanium: Natural, Black</p></td><td  ><p>Titanium: Natural, Black</p></td><td  ><p>Aluminum: Dark Bronze, Light Gold, Black, Space Gray / Titanium: Radiant Gold, Natural / Ceramic: Pearl White, Night Blue</p><p></p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td><td  ><p>422 x 514 pixels (Always-On LTPO3 Wide-Angle OLED)</p></td><td  ><p>46mm:  416 x 496 pixels / 44mm: 374 x 446 pixels (Always-On LTPO3 Wide-Angle OLED)</p><p></p></td></tr><tr><td class="firstcol " ><p><strong>Display brightness</strong></p><p></p><p></p><p></p></td><td  ><p>3,000 nits</p></td><td  ><p>3,000 nits</p></td><td  ><p>2,000 nits</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>~63 g</p></td><td  ><p>~61 g</p></td><td  ><p>46mm: ~ 39 g / 44mm: ~32 g</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>S11</p></td><td  ><p>S10</p></td><td  ><p>S11</p></td></tr><tr><td class="firstcol " ><p><strong>Cellular </strong></p></td><td  ><p>56</p></td><td  ><p>5G</p></td><td  ><p>5G</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>100 meters</p></td><td  ><p>100 meters</p></td><td  ><p>50 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life with always-on display (rated)</strong></p></td><td  ><p>50 hours</p></td><td  ><p>42 hours</p></td><td  ><p>24 hours</p></td></tr><tr><td class="firstcol " ><p><strong>Compatibility</strong></p></td><td  ><p>iOS 27 or later</p></td><td  ><p>iOS 26 or later</p></td><td  ><p>iOS 27 or later</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-apple-watch-ultra-4-hands-on-review-price-and-availability"><span>Apple Watch Ultra 4 hands-on review: Price and availability </span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1338px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="93pm4CaurnZ79Nk8fsTgiP" name="AWU4-02" alt="Close-up of the Apple Watch Ultra 4 side profile" src="https://cdn.mos.cms.futurecdn.net/93pm4CaurnZ79Nk8fsTgiP-1920-80.jpg" mos="" align="middle" fullscreen="" width="1338" height="753" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>The Apple Watch Ultra 4 is available for preorder from September 9, 2026. Units should hit store shelves and your hands starting on September 18. </p><p>The Apple Watch Ultra 4 is $799 / AU$1,349, the same price as the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a> and prior models. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-hands-on-review-design-and-display"><span>Apple Watch Ultra 4 hands-on review: Design and display </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="q6RPuprHDQb5uHVE6hD8Cj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/q6RPuprHDQb5uHVE6hD8Cj-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 Apple Watch Ultra 4 looks physically identical to the Ultra 3, boasting the same dimensions, oversized display with 3,000 nits of max brightness, an all-titanium case, and 100 meters of water resistance. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-hands-on-review-health-and-fitness-upgrades"><span>Apple Watch Ultra 4 hands-on review: Health and fitness upgrades</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="wJzr9bqD5grXgaeqP9hXPj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/wJzr9bqD5grXgaeqP9hXPj-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>Apple totally redesigned the health sensor array on the Ultra 4 to make its heart rate data more accurate, efficient, and frequently sampled. The new health sensing system now samples your heart rate every five seconds, 60x more frequently than its predecessor.</p><p>It also reads your heart rate variability every 15 seconds, a 24x increase in frequency over the Ultra 3. Apple also completely reworked the pedometer algorithm for improved step count accuracy and more precise distance data when logging an outdoor workout. </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="xv7TVM8BxL5mYTJonKP7Rj" name="Apple Watch Ultra 4" alt="Apple Watch Ultra 4" src="https://cdn.mos.cms.futurecdn.net/xv7TVM8BxL5mYTJonKP7Rj-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>Apple is also adding several handy new metrics to the Health app, including a daily Readiness score that is based on your recent workouts, sleep quality, and vitals. There's also a new Health Age score that compares your physical fitness to the average for your age range.</p><p>Later this year, a redesigned Health app is expected to launch with a greater emphasis on long-term trend reporting and actionable Siri AI-powered insights and advice. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-hands-on-review-ai-features"><span>Apple Watch Ultra 4 hands-on review: AI features </span></h3><p>The Apple Watch Ultra 4 ships running <a href="https://www.tomsguide.com/wellness/smartwatches/watchos-27-all-the-new-features-coming-to-apple-watch-later-this-year">watchOS 27</a>, which means that it's one of the very first Apple Watch models to support Apple's Siri AI voice assistant, which is trained to answer queries and provide context-based guidance tailored to the individual user.</p><p>Siri AI also powers a handful of new "Audio Intelligence" features like Live Rewind, which lets you go back and relisten to the past 15 seconds of ambient sound at any given time by double-pressing the digital crown.</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="8bcbHKT8rtMP46JqtdXmRN" name="Apple Event — September 9 47-49 screenshot" alt="Live Rewind on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/8bcbHKT8rtMP46JqtdXmRN-1920-80.png" 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: Apple)</span></figcaption></figure><p>Not the best note-taker? Siri Recap can listen into your conversation or meeting and automatically generate a report highlighting key topics, along with an overall summary of what was discussed.</p><p>Finally, the Ultra 4 supports Apple's Sound Recognition technology, which can automatically alert users when common sounds like a doorbell or fire alarm are observed. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-hands-on-review-battery-life"><span>Apple Watch Ultra 4 hands-on review: Battery life</span></h3><div><blockquote><p>The Ultra 4 sees a welcome battery life rating increase from 42 hours per charge to 50 hours per charge.</p></blockquote></div><p>The Apple Watch Ultra series has always been the brand's longest-lasting, and the latest Ultra 4 sees a welcome battery life rating increase from 42 hours per charge to 50 hours per charge. </p><p>When recording outdoor workouts with full heart rate and GPS data, the Ultra 4 is rated for roughly 18 hours per charge. However, a new Max Extended tracking mode increases that rating to an impressive 45 hours of use per charge.</p><h3 class="article-body__section" id="section-apple-watch-ultra-4-hands-on-review-should-you-buy"><span>Apple Watch Ultra 4 hands-on review: Should you buy?</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="D2MaHGKfuSAn5WQsdoHV86" name="Apple Event — September 9 52-32 screenshot" alt="Apple Watch Ultra 4 Fact Sheet" src="https://cdn.mos.cms.futurecdn.net/D2MaHGKfuSAn5WQsdoHV86-1920-80.png" 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: Apple)</span></figcaption></figure><p>Without thoroughly testing the improved battery life, health tracking, and outdoor workout logging claims, it's impossible to say for certain whether the Apple Watch Ultra 4 is a must-buy. The same goes for all the new holistic tools and AI features.</p><p>Furthermore, some of the advertised upgrades won't be available right at launch; the redesigned Health app with improved longevity insights and custom-tailored holistic advice won't be ready until later this year.</p><p>This is to say, it's probably best to hold off on dropping serious dough on the Ultra 4 until our full review is live later this month. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch 12 and Apple Watch Ultra 4 preorders are live — save up to $430 ]]></title>
                                                                                                <dc:content><![CDATA[ <p>It’s official: Apple has unveiled the latest additions to its wearables lineup — <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-announced-everything-you-need-to-know-about-the-new-flagship-apple-watch">Apple Watch Series 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a>. Announced today at Apple’s “Surprise and Shine” event, both devices are set to launch on September 18.</p><p>Introduced alongside the new <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know">iPhone 18 Pro</a>, the Apple Watch 12 is Apple's latest flagship smartwatch, with its price starting at $399 — the same starting price as the Series 11. Apple says the new watch will deliver "the most accurate heart rate sensing in a wearable," alongside a suite of advanced health and fitness features. It's powered by Apple's new S11 chip, which enables new Audio Intelligence features set to arrive later this year.</p><p>Also revealed at today's event, the Apple Watch Ultra 4 will start at $799 (also the same price as its predecessor). The ultimate sports and adventure watch includes all the same advanced features as the Apple Watch 12, except it offers a longer battery life of up to 2 days. </p><p>Ready to upgrade to Apple's latest wearable? Apple Watch 12 and Ultra 4 preorders start today at Apple, Amazon, Best Buy and Walmart. There are also opportunities to trade in an old smartwatch and save up to $430 on your new watch. (For more ways to save, make sure to check out our <a href="https://www.tomsguide.com/coupons/apple.com">Apple Store coupons</a> coverage).  </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong>Apple Watch 12: </strong><a href="https://www.apple.com/shop/buy-watch/apple-watch" target="_blank" rel="nofollow"><strong>from $399 @ Apple</strong></a></li><li><strong>Apple Watch 12: </strong><a href="https://www.bestbuy.com/product/apple-watch-series-12-gps-42mm-black-aluminum-case-with-black-sport-band-s-m-black-2026/JJGCQP9FPT/sku/6572728"><strong>from $399 @ Best Buy</strong></a></li><li><strong>Apple Watch 12: </strong><a href="https://www.amazon.com/dp/B0HJ9ZXCSD/"><strong>from $399 @ Amazon</strong></a><strong> </strong></li><li><strong>Apple Watch 12: </strong><a href="https://www.walmart.com/ip/Apple-Watch-Series-12-GPS-42mm-Black-Aluminum-Case-with-Black-Sport-Band-S-M/20961269689?" target="_blank" rel="nofollow"><strong>from $399 @ Walmart</strong></a></li><li><strong>Apple Watch Ultra 4: </strong><a href="https://www.apple.com/shop/buy-watch/apple-watch-ultra" target="_blank" rel="nofollow"><strong>from $799 @ Apple</strong></a></li><li><strong>Apple Watch Ultra 4: </strong><a href="https://www.bestbuy.com/product/apple-watch-ultra-4-gps-cellular-49mm-black-titanium-case-with-translucent-black-ocean-band-black-2026/JJGCQPR88C/sku/6597854"><strong>from $799 @ Best Buy</strong></a></li><li><strong>Apple Watch Ultra 4: </strong><a href="https://www.amazon.com/dp/B0HJB92SVQ/"><strong>from $799 @ Amazon</strong></a></li></ul><h3 class="article-body__section" id="section-apple-watch-12-preorders"><span>Apple Watch 12 preorders</span></h3><div class="product"><a data-dimension112="fb8a41c4-ac65-11f1-b94c-113dafe0e1a5" data-action="Deal Block" data-label="Apple Watch 12: from $399 @ Apple" data-dimension48="Apple Watch 12: from $399 @ Apple" href="https://www.apple.com/shop/buy-watch/apple-watch" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:64.06%;"><img id="3M6hnNTpsU94f3V64La4d6" name="Apple Watch 12" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3M6hnNTpsU94f3V64La4d6-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1640" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch 12: </strong><a href="https://www.apple.com/shop/buy-watch/apple-watch" target="_blank" rel="nofollow" data-dimension112="fb8a41c4-ac65-11f1-b94c-113dafe0e1a5" data-action="Deal Block" data-label="Apple Watch 12: from $399 @ Apple" data-dimension48="Apple Watch 12: from $399 @ Apple" data-dimension25=""><strong>from $399 @ Apple</strong></a><br>Apple's latest flagship smartwatch, the Apple Watch 12 is available for preorder now and will ship on September 18. It's available in 42mm and 46mm sizes for $399 and $429, respectively. There are also GPS/Cellular models from $499. You can choose from Aluminum, Titanium and Ceramic finishes, but the latter two options will cost more.  You can get up to a $430 credit when you trade-in an eligible device. <a class="view-deal button" href="https://www.apple.com/shop/buy-watch/apple-watch" target="_blank" rel="nofollow" data-dimension112="fb8a41c4-ac65-11f1-b94c-113dafe0e1a5" data-action="Deal Block" data-label="Apple Watch 12: from $399 @ Apple" data-dimension48="Apple Watch 12: from $399 @ Apple" data-dimension25="">View Deal</a></p></div><div class="product"><a data-dimension112="fb8a4264-ac65-11f1-9053-4111151585a4" data-action="Deal Block" data-label="Apple Watch 12 (42 mm): from $399 @ Best Buy" data-dimension48="Apple Watch 12 (42 mm): from $399 @ Best Buy" data-dimension25="$" href="https://www.bestbuy.com/product/apple-watch-series-12-gps-42mm-black-aluminum-case-with-black-sport-band-s-m-black-2026/JJGCQP9FPT/sku/6572728" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:800px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="Aze3cYwcHH9zfekingtW5d" name="best_buy_logo.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Aze3cYwcHH9zfekingtW5d-1920-80.jpg" mos="" align="middle" fullscreen="" width="800" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch 12 (42 mm): </strong><a href="https://www.bestbuy.com/product/apple-watch-series-12-gps-42mm-black-aluminum-case-with-black-sport-band-s-m-black-2026/JJGCQP9FPT/sku/6572728" target="_blank" rel="nofollow" data-dimension112="fb8a4264-ac65-11f1-9053-4111151585a4" data-action="Deal Block" data-label="Apple Watch 12 (42 mm): from $399 @ Best Buy" data-dimension48="Apple Watch 12 (42 mm): from $399 @ Best Buy" data-dimension25="$"><strong>from $399 @ Best Buy</strong></a><br>Best Buy is now offering the Apple Watch 12 preorders in both the 42mm and 46mm sizes. There are also GPS/Cellular models from $499. If you have an older watch to trade-in, you can get a credit to put toward your new watch. <a href="https://www.bestbuy.com/site/apple-watch-device-accessories/apple-smartwatch/pcmcat1724092038795.c?id=pcmcat1724092038795" target="_blank" rel="nofollow">Check your estimated trade value here</a>. <a class="view-deal button" href="https://www.bestbuy.com/product/apple-watch-series-12-gps-42mm-black-aluminum-case-with-black-sport-band-s-m-black-2026/JJGCQP9FPT/sku/6572728" target="_blank" rel="nofollow" data-dimension112="fb8a4264-ac65-11f1-9053-4111151585a4" data-action="Deal Block" data-label="Apple Watch 12 (42 mm): from $399 @ Best Buy" data-dimension48="Apple Watch 12 (42 mm): from $399 @ Best Buy" data-dimension25="$">View Deal</a></p></div><div class="product"><a data-dimension112="fb8a42fa-ac65-11f1-a268-7d2228ebf201" data-action="Deal Block" data-label="Apple Watch 12 (42mm): from $399 @ Amazon" data-dimension48="Apple Watch 12 (42mm): from $399 @ Amazon" data-dimension25="$" href="https://www.amazon.com/dp/B0HJ9ZXCSD/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:952px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="XrQBp78kAFsWqRjpGsZBzF" name="Amazon logo.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XrQBp78kAFsWqRjpGsZBzF-1920-80.jpg" mos="" align="middle" fullscreen="" width="952" height="952" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch 12 (42mm): </strong><a href="https://www.amazon.com/dp/B0HJ9ZXCSD/" target="_blank" rel="nofollow" data-dimension112="fb8a42fa-ac65-11f1-a268-7d2228ebf201" data-action="Deal Block" data-label="Apple Watch 12 (42mm): from $399 @ Amazon" data-dimension48="Apple Watch 12 (42mm): from $399 @ Amazon" data-dimension25="$"><strong>from $399 @ Amazon </strong></a><br>Apple Watch 12 is officially available for preorder at Amazon. Amazon is usually one of the first retailers to offer deals on Apple's new kit. While there aren't any discounts yet, you can likely expect them to come this fall. <a class="view-deal button" href="https://www.amazon.com/dp/B0HJ9ZXCSD/" target="_blank" rel="nofollow" data-dimension112="fb8a42fa-ac65-11f1-a268-7d2228ebf201" data-action="Deal Block" data-label="Apple Watch 12 (42mm): from $399 @ Amazon" data-dimension48="Apple Watch 12 (42mm): from $399 @ Amazon" data-dimension25="$">View Deal</a></p></div><div class="product"><a data-dimension112="fb8a4368-ac65-11f1-a89a-f7e2357873fe" data-action="Deal Block" data-label="Apple Watch 12: from $399 @ Walmart" data-dimension48="Apple Watch 12: from $399 @ Walmart" href="https://www.walmart.com/ip/Apple-Watch-Series-12-GPS-42mm-Black-Aluminum-Case-with-Black-Sport-Band-S-M/20961269689?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:960px;"><p class="vanilla-image-block" style="padding-top:93.65%;"><img id="Bi2iDjTxUHTUQK9FHZ4W8D" name="Walmart logo.jpeg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Bi2iDjTxUHTUQK9FHZ4W8D-1920-80.jpeg" mos="" align="middle" fullscreen="" width="960" height="899" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch 12: </strong><a href="https://www.walmart.com/ip/Apple-Watch-Series-12-GPS-42mm-Black-Aluminum-Case-with-Black-Sport-Band-S-M/20961269689?" target="_blank" rel="nofollow" data-dimension112="fb8a4368-ac65-11f1-a89a-f7e2357873fe" data-action="Deal Block" data-label="Apple Watch 12: from $399 @ Walmart" data-dimension48="Apple Watch 12: from $399 @ Walmart" data-dimension25=""><strong>from $399 @ Walmart</strong></a><br>Walmart is the latest retailer offering the Apple Watch 12 in both 42mm and 46mm sizes. Preorder yours today. <a class="view-deal button" href="https://www.walmart.com/ip/Apple-Watch-Series-12-GPS-42mm-Black-Aluminum-Case-with-Black-Sport-Band-S-M/20961269689?" target="_blank" rel="nofollow" data-dimension112="fb8a4368-ac65-11f1-a89a-f7e2357873fe" data-action="Deal Block" data-label="Apple Watch 12: from $399 @ Walmart" data-dimension48="Apple Watch 12: from $399 @ Walmart" data-dimension25="">View Deal</a></p></div><h3 class="article-body__section" id="section-apple-watch-ultra-4-preorders"><span>Apple Watch Ultra 4 preorders</span></h3><div class="product"><a data-dimension112="fb8a4430-ac65-11f1-aa73-ef2b6202ab15" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Apple" data-dimension48="Apple Watch Ultra 4: from $799 @ Apple" href="https://www.apple.com/shop/buy-watch/apple-watch-ultra" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:64.06%;"><img id="XDLU5seBuVG9nRHzwd5Jmc" name="Apple Watch Ultra 4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XDLU5seBuVG9nRHzwd5Jmc-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1640" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch Ultra 4: </strong><a href="https://www.apple.com/shop/buy-watch/apple-watch-ultra" target="_blank" rel="nofollow" data-dimension112="fb8a4430-ac65-11f1-aa73-ef2b6202ab15" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Apple" data-dimension48="Apple Watch Ultra 4: from $799 @ Apple" data-dimension25=""><strong>from $799 @ Apple</strong></a><br>The Apple Watch Ultra 4 is now available for preorder and will ship on September 19. It comes with precision dual-frequency GPS + Cellular connectivity and new built-in satellite communications. It's available in a 49mm size starting at $799. You can get up to a $430 credit when you trade-in an eligible device. <a class="view-deal button" href="https://www.apple.com/shop/buy-watch/apple-watch-ultra" target="_blank" rel="nofollow" data-dimension112="fb8a4430-ac65-11f1-aa73-ef2b6202ab15" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Apple" data-dimension48="Apple Watch Ultra 4: from $799 @ Apple" data-dimension25="">View Deal</a></p></div><div class="product"><a data-dimension112="fb8a44a8-ac65-11f1-8623-8142fc471ccd" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Best Buy" data-dimension48="Apple Watch Ultra 4: from $799 @ Best Buy" data-dimension25="$" href="https://www.bestbuy.com/product/apple-watch-ultra-4-gps-cellular-49mm-black-titanium-case-with-translucent-black-ocean-band-black-2026/JJGCQPR88C/sku/6597854" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:800px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="Aze3cYwcHH9zfekingtW5d" name="best_buy_logo.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Aze3cYwcHH9zfekingtW5d-1920-80.jpg" mos="" align="middle" fullscreen="" width="800" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch Ultra 4: </strong><a href="https://www.bestbuy.com/product/apple-watch-ultra-4-gps-cellular-49mm-black-titanium-case-with-translucent-black-ocean-band-black-2026/JJGCQPR88C/sku/6597854" target="_blank" rel="nofollow" data-dimension112="fb8a44a8-ac65-11f1-8623-8142fc471ccd" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Best Buy" data-dimension48="Apple Watch Ultra 4: from $799 @ Best Buy" data-dimension25="$"><strong>from $799 @ Best Buy</strong></a><br>Best Buy is now offering the Apple Watch Ultra 4 preorders. If you have an older watch to trade-in, you can get a credit to put toward your new watch. <a href="https://www.bestbuy.com/site/apple-watch-device-accessories/apple-smartwatch/pcmcat1724092038795.c?id=pcmcat1724092038795" target="_blank" rel="nofollow">Check your estimated trade value here</a>. <a class="view-deal button" href="https://www.bestbuy.com/product/apple-watch-ultra-4-gps-cellular-49mm-black-titanium-case-with-translucent-black-ocean-band-black-2026/JJGCQPR88C/sku/6597854" target="_blank" rel="nofollow" data-dimension112="fb8a44a8-ac65-11f1-8623-8142fc471ccd" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Best Buy" data-dimension48="Apple Watch Ultra 4: from $799 @ Best Buy" data-dimension25="$">View Deal</a></p></div><div class="product"><a data-dimension112="fb8a4520-ac65-11f1-b833-d70c23e1bc22" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Amazon" data-dimension48="Apple Watch Ultra 4: from $799 @ Amazon" data-dimension25="$" href="https://www.amazon.com/dp/B0HJB92SVQ/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:952px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="XrQBp78kAFsWqRjpGsZBzF" name="Amazon logo.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XrQBp78kAFsWqRjpGsZBzF-1920-80.jpg" mos="" align="middle" fullscreen="" width="952" height="952" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch Ultra 4: </strong><a href="https://www.amazon.com/dp/B0HJB92SVQ/" target="_blank" rel="nofollow" data-dimension112="fb8a4520-ac65-11f1-b833-d70c23e1bc22" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Amazon" data-dimension48="Apple Watch Ultra 4: from $799 @ Amazon" data-dimension25="$"><strong>from $799 @ Amazon</strong></a><strong> </strong><br>Apple Watch Ultra 4 is officially available for preorder at Amazon. Amazon is usually one of the first retailers to offer deals on Apple's new kit. While there aren't any discounts yet, you can likely expect them to come this fall. <a class="view-deal button" href="https://www.amazon.com/dp/B0HJB92SVQ/" target="_blank" rel="nofollow" data-dimension112="fb8a4520-ac65-11f1-b833-d70c23e1bc22" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Amazon" data-dimension48="Apple Watch Ultra 4: from $799 @ Amazon" data-dimension25="$">View Deal</a></p></div><div class="product"><a data-dimension112="fb8a45b6-ac65-11f1-a5ee-89ecb13b3011" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ VerizonApple Watch Ultra 4 is now available for pre-order at Verizon. You can also trade in an old device and get up to $400 in credit." data-dimension48="Apple Watch Ultra 4: from $799 @ VerizonApple Watch Ultra 4 is now available for pre-order at Verizon. You can also trade in an old device and get up to $400 in credit." href="https://www.verizon.com/connected-smartwatches/apple-watch-ultra-3/?sku=sku6037285" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:512px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="TMYzAmBK5LeeB3KJKcp2NT" name="Untitled design - 2024-07-02T104057.380.png" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/TMYzAmBK5LeeB3KJKcp2NT-1920-80.png" mos="" align="middle" fullscreen="" width="512" height="512" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch Ultra 4: from $799 @ Verizon</strong><br>Apple Watch Ultra 4 is now available for pre-order at Verizon. You can also trade in an old device and get up to $400 in credit. <a class="view-deal button" href="https://www.verizon.com/connected-smartwatches/apple-watch-ultra-3/?sku=sku6037285" target="_blank" rel="nofollow" data-dimension112="fb8a45b6-ac65-11f1-a5ee-89ecb13b3011" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ VerizonApple Watch Ultra 4 is now available for pre-order at Verizon. You can also trade in an old device and get up to $400 in credit." data-dimension48="Apple Watch Ultra 4: from $799 @ VerizonApple Watch Ultra 4 is now available for pre-order at Verizon. You can also trade in an old device and get up to $400 in credit." data-dimension25="">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="?brands=Apple&rows=6&view_mode=savings_squad&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-12-and-apple-watch-ultra-4-preorders-are-live-save-up-to-usd430</link>
                                                                            <description>
                            <![CDATA[ Apple Watch 12 and Apple Watch Ultra 4 preorders just went live. Here's how much you can already save. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">b9wQBSeDPSv22mR7USSAmn</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/F3dPCrwUXNdLtNarvrJ7xf-1920-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 19:09:57 +0000</pubDate>                                                                                                                                <updated>Thu, 10 Sep 2026 13:50:29 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></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/png" url="https://cdn.mos.cms.futurecdn.net/F3dPCrwUXNdLtNarvrJ7xf-1920-80.png">
                                                            <media:credit><![CDATA[Apple]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch 12 designs and faces]]></media:description>                                                            <media:text><![CDATA[Apple Watch 12 designs and faces]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch 12 designs and faces]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/F3dPCrwUXNdLtNarvrJ7xf-1920-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>It’s official: Apple has unveiled the latest additions to its wearables lineup — <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-announced-everything-you-need-to-know-about-the-new-flagship-apple-watch">Apple Watch Series 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a>. Announced today at Apple’s “Surprise and Shine” event, both devices are set to launch on September 18.</p><p>Introduced alongside the new <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know">iPhone 18 Pro</a>, the Apple Watch 12 is Apple's latest flagship smartwatch, with its price starting at $399 — the same starting price as the Series 11. Apple says the new watch will deliver "the most accurate heart rate sensing in a wearable," alongside a suite of advanced health and fitness features. It's powered by Apple's new S11 chip, which enables new Audio Intelligence features set to arrive later this year.</p><p>Also revealed at today's event, the Apple Watch Ultra 4 will start at $799 (also the same price as its predecessor). The ultimate sports and adventure watch includes all the same advanced features as the Apple Watch 12, except it offers a longer battery life of up to 2 days. </p><p>Ready to upgrade to Apple's latest wearable? Apple Watch 12 and Ultra 4 preorders start today at Apple, Amazon, Best Buy and Walmart. There are also opportunities to trade in an old smartwatch and save up to $430 on your new watch. (For more ways to save, make sure to check out our <a href="https://www.tomsguide.com/coupons/apple.com">Apple Store coupons</a> coverage).  </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong>Apple Watch 12: </strong><a href="https://www.apple.com/shop/buy-watch/apple-watch" target="_blank" rel="nofollow"><strong>from $399 @ Apple</strong></a></li><li><strong>Apple Watch 12: </strong><a href="https://www.bestbuy.com/product/apple-watch-series-12-gps-42mm-black-aluminum-case-with-black-sport-band-s-m-black-2026/JJGCQP9FPT/sku/6572728"><strong>from $399 @ Best Buy</strong></a></li><li><strong>Apple Watch 12: </strong><a href="https://www.amazon.com/dp/B0HJ9ZXCSD/"><strong>from $399 @ Amazon</strong></a><strong> </strong></li><li><strong>Apple Watch 12: </strong><a href="https://www.walmart.com/ip/Apple-Watch-Series-12-GPS-42mm-Black-Aluminum-Case-with-Black-Sport-Band-S-M/20961269689?" target="_blank" rel="nofollow"><strong>from $399 @ Walmart</strong></a></li><li><strong>Apple Watch Ultra 4: </strong><a href="https://www.apple.com/shop/buy-watch/apple-watch-ultra" target="_blank" rel="nofollow"><strong>from $799 @ Apple</strong></a></li><li><strong>Apple Watch Ultra 4: </strong><a href="https://www.bestbuy.com/product/apple-watch-ultra-4-gps-cellular-49mm-black-titanium-case-with-translucent-black-ocean-band-black-2026/JJGCQPR88C/sku/6597854"><strong>from $799 @ Best Buy</strong></a></li><li><strong>Apple Watch Ultra 4: </strong><a href="https://www.amazon.com/dp/B0HJB92SVQ/"><strong>from $799 @ Amazon</strong></a></li></ul><h3 class="article-body__section" id="section-apple-watch-12-preorders"><span>Apple Watch 12 preorders</span></h3><div class="product"><a data-dimension112="fb8a41c4-ac65-11f1-b94c-113dafe0e1a5" data-action="Deal Block" data-label="Apple Watch 12: from $399 @ Apple" data-dimension48="Apple Watch 12: from $399 @ Apple" href="https://www.apple.com/shop/buy-watch/apple-watch" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:64.06%;"><img id="3M6hnNTpsU94f3V64La4d6" name="Apple Watch 12" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3M6hnNTpsU94f3V64La4d6-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1640" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch 12: </strong><a href="https://www.apple.com/shop/buy-watch/apple-watch" target="_blank" rel="nofollow" data-dimension112="fb8a41c4-ac65-11f1-b94c-113dafe0e1a5" data-action="Deal Block" data-label="Apple Watch 12: from $399 @ Apple" data-dimension48="Apple Watch 12: from $399 @ Apple" data-dimension25=""><strong>from $399 @ Apple</strong></a><br>Apple's latest flagship smartwatch, the Apple Watch 12 is available for preorder now and will ship on September 18. It's available in 42mm and 46mm sizes for $399 and $429, respectively. There are also GPS/Cellular models from $499. You can choose from Aluminum, Titanium and Ceramic finishes, but the latter two options will cost more.  You can get up to a $430 credit when you trade-in an eligible device. <a class="view-deal button" href="https://www.apple.com/shop/buy-watch/apple-watch" target="_blank" rel="nofollow" data-dimension112="fb8a41c4-ac65-11f1-b94c-113dafe0e1a5" data-action="Deal Block" data-label="Apple Watch 12: from $399 @ Apple" data-dimension48="Apple Watch 12: from $399 @ Apple" data-dimension25="">View Deal</a></p></div><div class="product"><a data-dimension112="fb8a4264-ac65-11f1-9053-4111151585a4" data-action="Deal Block" data-label="Apple Watch 12 (42 mm): from $399 @ Best Buy" data-dimension48="Apple Watch 12 (42 mm): from $399 @ Best Buy" data-dimension25="$" href="https://www.bestbuy.com/product/apple-watch-series-12-gps-42mm-black-aluminum-case-with-black-sport-band-s-m-black-2026/JJGCQP9FPT/sku/6572728" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:800px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="Aze3cYwcHH9zfekingtW5d" name="best_buy_logo.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Aze3cYwcHH9zfekingtW5d-1920-80.jpg" mos="" align="middle" fullscreen="" width="800" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch 12 (42 mm): </strong><a href="https://www.bestbuy.com/product/apple-watch-series-12-gps-42mm-black-aluminum-case-with-black-sport-band-s-m-black-2026/JJGCQP9FPT/sku/6572728" target="_blank" rel="nofollow" data-dimension112="fb8a4264-ac65-11f1-9053-4111151585a4" data-action="Deal Block" data-label="Apple Watch 12 (42 mm): from $399 @ Best Buy" data-dimension48="Apple Watch 12 (42 mm): from $399 @ Best Buy" data-dimension25="$"><strong>from $399 @ Best Buy</strong></a><br>Best Buy is now offering the Apple Watch 12 preorders in both the 42mm and 46mm sizes. There are also GPS/Cellular models from $499. If you have an older watch to trade-in, you can get a credit to put toward your new watch. <a href="https://www.bestbuy.com/site/apple-watch-device-accessories/apple-smartwatch/pcmcat1724092038795.c?id=pcmcat1724092038795" target="_blank" rel="nofollow">Check your estimated trade value here</a>. <a class="view-deal button" href="https://www.bestbuy.com/product/apple-watch-series-12-gps-42mm-black-aluminum-case-with-black-sport-band-s-m-black-2026/JJGCQP9FPT/sku/6572728" target="_blank" rel="nofollow" data-dimension112="fb8a4264-ac65-11f1-9053-4111151585a4" data-action="Deal Block" data-label="Apple Watch 12 (42 mm): from $399 @ Best Buy" data-dimension48="Apple Watch 12 (42 mm): from $399 @ Best Buy" data-dimension25="$">View Deal</a></p></div><div class="product"><a data-dimension112="fb8a42fa-ac65-11f1-a268-7d2228ebf201" data-action="Deal Block" data-label="Apple Watch 12 (42mm): from $399 @ Amazon" data-dimension48="Apple Watch 12 (42mm): from $399 @ Amazon" data-dimension25="$" href="https://www.amazon.com/dp/B0HJ9ZXCSD/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:952px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="XrQBp78kAFsWqRjpGsZBzF" name="Amazon logo.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XrQBp78kAFsWqRjpGsZBzF-1920-80.jpg" mos="" align="middle" fullscreen="" width="952" height="952" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch 12 (42mm): </strong><a href="https://www.amazon.com/dp/B0HJ9ZXCSD/" target="_blank" rel="nofollow" data-dimension112="fb8a42fa-ac65-11f1-a268-7d2228ebf201" data-action="Deal Block" data-label="Apple Watch 12 (42mm): from $399 @ Amazon" data-dimension48="Apple Watch 12 (42mm): from $399 @ Amazon" data-dimension25="$"><strong>from $399 @ Amazon </strong></a><br>Apple Watch 12 is officially available for preorder at Amazon. Amazon is usually one of the first retailers to offer deals on Apple's new kit. While there aren't any discounts yet, you can likely expect them to come this fall. <a class="view-deal button" href="https://www.amazon.com/dp/B0HJ9ZXCSD/" target="_blank" rel="nofollow" data-dimension112="fb8a42fa-ac65-11f1-a268-7d2228ebf201" data-action="Deal Block" data-label="Apple Watch 12 (42mm): from $399 @ Amazon" data-dimension48="Apple Watch 12 (42mm): from $399 @ Amazon" data-dimension25="$">View Deal</a></p></div><div class="product"><a data-dimension112="fb8a4368-ac65-11f1-a89a-f7e2357873fe" data-action="Deal Block" data-label="Apple Watch 12: from $399 @ Walmart" data-dimension48="Apple Watch 12: from $399 @ Walmart" href="https://www.walmart.com/ip/Apple-Watch-Series-12-GPS-42mm-Black-Aluminum-Case-with-Black-Sport-Band-S-M/20961269689?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:960px;"><p class="vanilla-image-block" style="padding-top:93.65%;"><img id="Bi2iDjTxUHTUQK9FHZ4W8D" name="Walmart logo.jpeg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Bi2iDjTxUHTUQK9FHZ4W8D-1920-80.jpeg" mos="" align="middle" fullscreen="" width="960" height="899" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch 12: </strong><a href="https://www.walmart.com/ip/Apple-Watch-Series-12-GPS-42mm-Black-Aluminum-Case-with-Black-Sport-Band-S-M/20961269689?" target="_blank" rel="nofollow" data-dimension112="fb8a4368-ac65-11f1-a89a-f7e2357873fe" data-action="Deal Block" data-label="Apple Watch 12: from $399 @ Walmart" data-dimension48="Apple Watch 12: from $399 @ Walmart" data-dimension25=""><strong>from $399 @ Walmart</strong></a><br>Walmart is the latest retailer offering the Apple Watch 12 in both 42mm and 46mm sizes. Preorder yours today. <a class="view-deal button" href="https://www.walmart.com/ip/Apple-Watch-Series-12-GPS-42mm-Black-Aluminum-Case-with-Black-Sport-Band-S-M/20961269689?" target="_blank" rel="nofollow" data-dimension112="fb8a4368-ac65-11f1-a89a-f7e2357873fe" data-action="Deal Block" data-label="Apple Watch 12: from $399 @ Walmart" data-dimension48="Apple Watch 12: from $399 @ Walmart" data-dimension25="">View Deal</a></p></div><h3 class="article-body__section" id="section-apple-watch-ultra-4-preorders"><span>Apple Watch Ultra 4 preorders</span></h3><div class="product"><a data-dimension112="fb8a4430-ac65-11f1-aa73-ef2b6202ab15" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Apple" data-dimension48="Apple Watch Ultra 4: from $799 @ Apple" href="https://www.apple.com/shop/buy-watch/apple-watch-ultra" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:64.06%;"><img id="XDLU5seBuVG9nRHzwd5Jmc" name="Apple Watch Ultra 4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XDLU5seBuVG9nRHzwd5Jmc-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1640" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch Ultra 4: </strong><a href="https://www.apple.com/shop/buy-watch/apple-watch-ultra" target="_blank" rel="nofollow" data-dimension112="fb8a4430-ac65-11f1-aa73-ef2b6202ab15" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Apple" data-dimension48="Apple Watch Ultra 4: from $799 @ Apple" data-dimension25=""><strong>from $799 @ Apple</strong></a><br>The Apple Watch Ultra 4 is now available for preorder and will ship on September 19. It comes with precision dual-frequency GPS + Cellular connectivity and new built-in satellite communications. It's available in a 49mm size starting at $799. You can get up to a $430 credit when you trade-in an eligible device. <a class="view-deal button" href="https://www.apple.com/shop/buy-watch/apple-watch-ultra" target="_blank" rel="nofollow" data-dimension112="fb8a4430-ac65-11f1-aa73-ef2b6202ab15" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Apple" data-dimension48="Apple Watch Ultra 4: from $799 @ Apple" data-dimension25="">View Deal</a></p></div><div class="product"><a data-dimension112="fb8a44a8-ac65-11f1-8623-8142fc471ccd" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Best Buy" data-dimension48="Apple Watch Ultra 4: from $799 @ Best Buy" data-dimension25="$" href="https://www.bestbuy.com/product/apple-watch-ultra-4-gps-cellular-49mm-black-titanium-case-with-translucent-black-ocean-band-black-2026/JJGCQPR88C/sku/6597854" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:800px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="Aze3cYwcHH9zfekingtW5d" name="best_buy_logo.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Aze3cYwcHH9zfekingtW5d-1920-80.jpg" mos="" align="middle" fullscreen="" width="800" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch Ultra 4: </strong><a href="https://www.bestbuy.com/product/apple-watch-ultra-4-gps-cellular-49mm-black-titanium-case-with-translucent-black-ocean-band-black-2026/JJGCQPR88C/sku/6597854" target="_blank" rel="nofollow" data-dimension112="fb8a44a8-ac65-11f1-8623-8142fc471ccd" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Best Buy" data-dimension48="Apple Watch Ultra 4: from $799 @ Best Buy" data-dimension25="$"><strong>from $799 @ Best Buy</strong></a><br>Best Buy is now offering the Apple Watch Ultra 4 preorders. If you have an older watch to trade-in, you can get a credit to put toward your new watch. <a href="https://www.bestbuy.com/site/apple-watch-device-accessories/apple-smartwatch/pcmcat1724092038795.c?id=pcmcat1724092038795" target="_blank" rel="nofollow">Check your estimated trade value here</a>. <a class="view-deal button" href="https://www.bestbuy.com/product/apple-watch-ultra-4-gps-cellular-49mm-black-titanium-case-with-translucent-black-ocean-band-black-2026/JJGCQPR88C/sku/6597854" target="_blank" rel="nofollow" data-dimension112="fb8a44a8-ac65-11f1-8623-8142fc471ccd" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Best Buy" data-dimension48="Apple Watch Ultra 4: from $799 @ Best Buy" data-dimension25="$">View Deal</a></p></div><div class="product"><a data-dimension112="fb8a4520-ac65-11f1-b833-d70c23e1bc22" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Amazon" data-dimension48="Apple Watch Ultra 4: from $799 @ Amazon" data-dimension25="$" href="https://www.amazon.com/dp/B0HJB92SVQ/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:952px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="XrQBp78kAFsWqRjpGsZBzF" name="Amazon logo.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XrQBp78kAFsWqRjpGsZBzF-1920-80.jpg" mos="" align="middle" fullscreen="" width="952" height="952" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch Ultra 4: </strong><a href="https://www.amazon.com/dp/B0HJB92SVQ/" target="_blank" rel="nofollow" data-dimension112="fb8a4520-ac65-11f1-b833-d70c23e1bc22" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Amazon" data-dimension48="Apple Watch Ultra 4: from $799 @ Amazon" data-dimension25="$"><strong>from $799 @ Amazon</strong></a><strong> </strong><br>Apple Watch Ultra 4 is officially available for preorder at Amazon. Amazon is usually one of the first retailers to offer deals on Apple's new kit. While there aren't any discounts yet, you can likely expect them to come this fall. <a class="view-deal button" href="https://www.amazon.com/dp/B0HJB92SVQ/" target="_blank" rel="nofollow" data-dimension112="fb8a4520-ac65-11f1-b833-d70c23e1bc22" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ Amazon" data-dimension48="Apple Watch Ultra 4: from $799 @ Amazon" data-dimension25="$">View Deal</a></p></div><div class="product"><a data-dimension112="fb8a45b6-ac65-11f1-a5ee-89ecb13b3011" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ VerizonApple Watch Ultra 4 is now available for pre-order at Verizon. You can also trade in an old device and get up to $400 in credit." data-dimension48="Apple Watch Ultra 4: from $799 @ VerizonApple Watch Ultra 4 is now available for pre-order at Verizon. You can also trade in an old device and get up to $400 in credit." href="https://www.verizon.com/connected-smartwatches/apple-watch-ultra-3/?sku=sku6037285" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:512px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="TMYzAmBK5LeeB3KJKcp2NT" name="Untitled design - 2024-07-02T104057.380.png" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/TMYzAmBK5LeeB3KJKcp2NT-1920-80.png" mos="" align="middle" fullscreen="" width="512" height="512" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>Apple Watch Ultra 4: from $799 @ Verizon</strong><br>Apple Watch Ultra 4 is now available for pre-order at Verizon. You can also trade in an old device and get up to $400 in credit. <a class="view-deal button" href="https://www.verizon.com/connected-smartwatches/apple-watch-ultra-3/?sku=sku6037285" target="_blank" rel="nofollow" data-dimension112="fb8a45b6-ac65-11f1-a5ee-89ecb13b3011" data-action="Deal Block" data-label="Apple Watch Ultra 4: from $799 @ VerizonApple Watch Ultra 4 is now available for pre-order at Verizon. You can also trade in an old device and get up to $400 in credit." data-dimension48="Apple Watch Ultra 4: from $799 @ VerizonApple Watch Ultra 4 is now available for pre-order at Verizon. You can also trade in an old device and get up to $400 in credit." data-dimension25="">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="?brands=Apple&rows=6&view_mode=savings_squad&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch Ultra 4 is official: All the upgrades explained ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple just announced the Apple Watch Ultra 4 alongside the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-announced-everything-you-need-to-know-about-the-new-flagship-apple-watch">Apple Watch Series 12</a>, <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-official-price-release-date-specs-and-everything-you-need-to-know">iPhone Duo</a>, and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know">iPhone 18 Pro</a> at the September 9th "<a href="https://www.tomsguide.com/phones/live/apple-surprise-and-shine-live-iphone-ultra-iphone-18-pro-max-apple-watch-series-12-and-all-the-latest-news">Surprise and Shine</a>" event in Cupertino, California. </p><p>Boasting loads of new wellness tools, improved heart rate tracking, better battery life, an upgraded processor, and a handful of cool AI features, here's everything you need to know about the Apple Watch Ultra 4.</p><h3 class="article-body__section" id="section-apple-watch-ultra-4-upgrades-cheat-sheet"><span>Apple Watch Ultra 4: Upgrades cheat sheet</span></h3><ul><li><strong>Price and release: </strong>The Apple Watch Ultra 4 is available for preorder starting today and will be available on September 18; the price is $799, the same as the Ultra 3</li><li><strong>Design:</strong> The Apple Watch Ultra 4 looks similar to its predecessor; available in Black or Natural Titanium</li><li><strong>Health features: </strong>Updated health sensing system; improved heart rate and heart rate variability (HRV) tracking; HRV reflected in Vitals app; new Readiness metric; new Health Age score; redesigned Health app with improved recovery insights and personalized AI health/fitness guidance that updates dynamically; Health app now supports personal health data and lab results</li><li><strong>AI features:</strong> Support for Siri AI voice assistant; Live Rewind lets you ‘go back in time’ up to 15 seconds; Sound Recognition can auto-alert users to common sounds like sirens and alarms; Siri Recap takes high-level notes of conversations and generates summaries</li><li><strong>Under-the-hood: </strong>Upgraded S11 processor</li><li><strong>Battery life:</strong> Improved battery performance lasts up to 50 hours per charge; up to 18 hours when recording a workout with heart rate and GPS tracking</li></ul><p>The Apple Watch Ultra 4 is a substantial upgrade over the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a>, which is currently one of the <a href="https://www.tomsguide.com/best-picks/best-apple-watch#section-the-best-apple-watch-for-battery-life">best smartwatches</a> you can buy. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-price-and-availability"><span>Apple Watch Ultra 4: Price and availability </span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="qDRmPHVEoKiiwKKRJc9QVB" name="Apple Event — September 9 52-43 screenshot" alt="Apple Watch Ultra 4 pricing" src="https://cdn.mos.cms.futurecdn.net/qDRmPHVEoKiiwKKRJc9QVB-1920-80.png" 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: Apple)</span></figcaption></figure><p>The Apple Watch Ultra 4 costs $799 / AU$1,349, the same as all the Apple Watch Ultra models that came before it. Available for preorder on launch day (September 9), the Apple Watch Ultra 4 will be available globally starting on September 18 in your choice of Black or Natural Titanium.</p><h3 class="article-body__section" id="section-apple-watch-ultra-4-health-upgrades"><span>Apple Watch Ultra 4: Health upgrades</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="yRGJNwhontYDFNAfsPJuDo" name="Apple Event — September 9 44-35 screenshot" alt="Longevity in Apple Health lifestyle" src="https://cdn.mos.cms.futurecdn.net/yRGJNwhontYDFNAfsPJuDo-1920-80.png" 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: Apple)</span></figcaption></figure><p><strong>Improved heart rate tracking</strong></p><p>The Apple Watch Ultra 4 and Series 12 boast “the most accurate heart rate tracking in wearables.” That is, of course, according to Apple’s own internal testing. To be fair, Apple completely overhauled the sensor array on the underside of the watch, making a number of significant improvements to its functionality.</p><p>Both the optical and electrical components have been reworked for more precise, efficient performance. More powerful LEDs measure your heart rate every five seconds, a 60-fold increase in sampling frequency over prior models.</p><p>Heart Rate Variability (HRV) is now measured every 15 seconds, a 24-fold increase compared to before. Speaking of HRV, users can now view that dynamic metric from the Heart Rate app. HRV is also logged in your overnight vitals report. </p><p><strong>Dynamic Readiness score</strong></p><p>Apple is finally adding a daily Readiness metric to the Health app, something nearly every other smartwatch brand has long offered. Based on a scale from one to ten, your Readiness Score updates dynamically and is based on recent workouts, sleep quality, training load, and vitals. </p><p>The score is accompanied by a brief, actionable, AI-generated recommendation for how to best tackle the day.</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:1415px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="o9CZhWnouG3yzLdrqQp2vK" name="AW-U4-Series12" alt="Close-up of the new Apple Watch Series 12 and Apple Watch Ultra 4 shown during the September 9 launch" src="https://cdn.mos.cms.futurecdn.net/o9CZhWnouG3yzLdrqQp2vK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1415" height="796" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p><strong>Improved step count tracking</strong></p><p>The Apple Watch Ultra 4 should be Cupertino’s most accurate step counter, thanks to a completely overhauled pedometer that uses machine learning to more accurately log your steps and distance covered. There’s also a new step count complication to more easily stay on top of your efforts. </p><p><strong>Redesigned Health app focused on trends and actionable advice </strong></p><p>A totally overhauled Health app is expected to debut later this year with a greater focus on long-term health trends and personalized wellness and fitness advice, courtesy of Siri AI. The refreshed app is expected to offer new Longevity and Insights tabs. The former features a new Health Age feature that compares your physical fitness to others in your age range.</p><p>The Insights tab, meanwhile, is where you’ll find dynamic Siri AI-generated health briefings, workout suggestions, and more.</p><p>Finally, the updated Health app will better support the integration of a user’s personal health data, including notes from doctor’s visits and lab test results. </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:1533px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="Dhxko3QL4xgb7nDXWwBhSk" name="AWU4-01" alt="Apple Watch Ultra 4 close-up showing the new LED health sensors" src="https://cdn.mos.cms.futurecdn.net/Dhxko3QL4xgb7nDXWwBhSk-1920-80.jpg" mos="" align="middle" fullscreen="" width="1533" height="862" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p><strong>Siri AI with Siri Recap</strong></p><p>The Apple Watch Ultra 4 supports Apple Siri AI voice assistant, but AI integration powers much more than just that. Siri Recap, for example, can be set up to listen in on important conversations and meetings, and then automatically generate a report with an overall summary along with key talking points. User control when this feature is active, either manually, via a schedule, or based on location. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-new-ai-features"><span>Apple Watch Ultra 4: New AI features</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="8bcbHKT8rtMP46JqtdXmRN" name="Apple Event — September 9 47-49 screenshot" alt="Live Rewind on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/8bcbHKT8rtMP46JqtdXmRN-1920-80.png" 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: Apple)</span></figcaption></figure><p><strong>Live Rewind and Sound Recognition</strong></p><p>One of the more exciting new Siri AI features is Live Rewind. Let’s say you just met someone new at a dinner party, but their name “went in one ear and out the other.” With Live Rewind, I can double-tap the digital crown on the Ultra 4 and relisten to the past 15 seconds of ambient audio anytime I like. </p><p>It’s worth noting that Apple doesn’t identify people when using this feature or save any recording. Moreover, any logged audio is end-to-end encrypted. </p><p>Finally, the Ultra 4 supports Apple’s Sound Recognition feature, which can alert those who are hard of hearing when sounds like fire alarms, doorbells, sirens, or crying babies are registered. <strong> </strong></p><h3 class="article-body__section" id="section-apple-watch-ultra-4-battery-life"><span>Apple Watch Ultra 4: Battery life</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:1338px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="93pm4CaurnZ79Nk8fsTgiP" name="AWU4-02" alt="Close-up of the Apple Watch Ultra 4 side profile" src="https://cdn.mos.cms.futurecdn.net/93pm4CaurnZ79Nk8fsTgiP-1920-80.jpg" mos="" align="middle" fullscreen="" width="1338" height="753" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>Battery life on the Apple Watch Ultra 4 has been increased to 450 hours per charge, up from 42 hours per charge for the Ultra 3. When using the Ultra 4 to log an outdoor workout with continuous GPS and heart rate tracking, users can expect about 18 hours of use. </p><p>Extended workout tracking mode bumps that number to 25 hours per charge, while a new Max Extended mode increases battery life to an impressive 45 hours per charge.</p><p>The Ultra 4 charges a little faster than its predecessor. Apple says a 15-minute charge should provide up to 18 hours of use. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-outlook"><span>Apple Watch Ultra 4: Outlook</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="pZ83Xgm3USZxuey6qEgDuK" name="Apple Event — September 9 54-44 screenshot" alt="Ternus with Apple Watch 12 series" src="https://cdn.mos.cms.futurecdn.net/pZ83Xgm3USZxuey6qEgDuK-1920-80.png" 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: Apple)</span></figcaption></figure><p>The Apple Watch Ultra 4 isn’t exactly a massive upgrade over the Ultra 3 —externally, the two are identical — but the combination of better health tracking tech, new AI features, improved battery life, and updated holistic tools galore… all for the same price as before, is pretty darn compelling.</p><p>Stay tuned for my full Apple Watch Ultra 4 review, coming soon. Until then, what new Apple Watch Ultra 4 features are you most excited about? Let me know in the comments.</p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4"><strong>I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/leaked-apple-watch-12-design-change-is-the-opposite-of-an-upgrade-and-that-has-me-worried"><strong>Leaked Apple Watch 12 design change is the opposite of an upgrade — and that has me worried</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained</link>
                                                                            <description>
                            <![CDATA[ Apple just announced the Apple Watch Ultra 4, and it's loaded with new wellness features, improved heart rate tracking, better AI tools, and upgraded battery performance. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">GTiurcrT7gVfR7akVXJNw3</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/D2MaHGKfuSAn5WQsdoHV86-1920-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 18:00:40 +0000</pubDate>                                                                                                                                <updated>Thu, 10 Sep 2026 00:14:49 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/png" url="https://cdn.mos.cms.futurecdn.net/D2MaHGKfuSAn5WQsdoHV86-1920-80.png">
                                                            <media:credit><![CDATA[Apple]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Ultra 4 Fact Sheet]]></media:description>                                                            <media:text><![CDATA[Apple Watch Ultra 4 Fact Sheet]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Ultra 4 Fact Sheet]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/D2MaHGKfuSAn5WQsdoHV86-1920-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple just announced the Apple Watch Ultra 4 alongside the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-announced-everything-you-need-to-know-about-the-new-flagship-apple-watch">Apple Watch Series 12</a>, <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-official-price-release-date-specs-and-everything-you-need-to-know">iPhone Duo</a>, and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know">iPhone 18 Pro</a> at the September 9th "<a href="https://www.tomsguide.com/phones/live/apple-surprise-and-shine-live-iphone-ultra-iphone-18-pro-max-apple-watch-series-12-and-all-the-latest-news">Surprise and Shine</a>" event in Cupertino, California. </p><p>Boasting loads of new wellness tools, improved heart rate tracking, better battery life, an upgraded processor, and a handful of cool AI features, here's everything you need to know about the Apple Watch Ultra 4.</p><h3 class="article-body__section" id="section-apple-watch-ultra-4-upgrades-cheat-sheet"><span>Apple Watch Ultra 4: Upgrades cheat sheet</span></h3><ul><li><strong>Price and release: </strong>The Apple Watch Ultra 4 is available for preorder starting today and will be available on September 18; the price is $799, the same as the Ultra 3</li><li><strong>Design:</strong> The Apple Watch Ultra 4 looks similar to its predecessor; available in Black or Natural Titanium</li><li><strong>Health features: </strong>Updated health sensing system; improved heart rate and heart rate variability (HRV) tracking; HRV reflected in Vitals app; new Readiness metric; new Health Age score; redesigned Health app with improved recovery insights and personalized AI health/fitness guidance that updates dynamically; Health app now supports personal health data and lab results</li><li><strong>AI features:</strong> Support for Siri AI voice assistant; Live Rewind lets you ‘go back in time’ up to 15 seconds; Sound Recognition can auto-alert users to common sounds like sirens and alarms; Siri Recap takes high-level notes of conversations and generates summaries</li><li><strong>Under-the-hood: </strong>Upgraded S11 processor</li><li><strong>Battery life:</strong> Improved battery performance lasts up to 50 hours per charge; up to 18 hours when recording a workout with heart rate and GPS tracking</li></ul><p>The Apple Watch Ultra 4 is a substantial upgrade over the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a>, which is currently one of the <a href="https://www.tomsguide.com/best-picks/best-apple-watch#section-the-best-apple-watch-for-battery-life">best smartwatches</a> you can buy. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-price-and-availability"><span>Apple Watch Ultra 4: Price and availability </span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="qDRmPHVEoKiiwKKRJc9QVB" name="Apple Event — September 9 52-43 screenshot" alt="Apple Watch Ultra 4 pricing" src="https://cdn.mos.cms.futurecdn.net/qDRmPHVEoKiiwKKRJc9QVB-1920-80.png" 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: Apple)</span></figcaption></figure><p>The Apple Watch Ultra 4 costs $799 / AU$1,349, the same as all the Apple Watch Ultra models that came before it. Available for preorder on launch day (September 9), the Apple Watch Ultra 4 will be available globally starting on September 18 in your choice of Black or Natural Titanium.</p><h3 class="article-body__section" id="section-apple-watch-ultra-4-health-upgrades"><span>Apple Watch Ultra 4: Health upgrades</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="yRGJNwhontYDFNAfsPJuDo" name="Apple Event — September 9 44-35 screenshot" alt="Longevity in Apple Health lifestyle" src="https://cdn.mos.cms.futurecdn.net/yRGJNwhontYDFNAfsPJuDo-1920-80.png" 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: Apple)</span></figcaption></figure><p><strong>Improved heart rate tracking</strong></p><p>The Apple Watch Ultra 4 and Series 12 boast “the most accurate heart rate tracking in wearables.” That is, of course, according to Apple’s own internal testing. To be fair, Apple completely overhauled the sensor array on the underside of the watch, making a number of significant improvements to its functionality.</p><p>Both the optical and electrical components have been reworked for more precise, efficient performance. More powerful LEDs measure your heart rate every five seconds, a 60-fold increase in sampling frequency over prior models.</p><p>Heart Rate Variability (HRV) is now measured every 15 seconds, a 24-fold increase compared to before. Speaking of HRV, users can now view that dynamic metric from the Heart Rate app. HRV is also logged in your overnight vitals report. </p><p><strong>Dynamic Readiness score</strong></p><p>Apple is finally adding a daily Readiness metric to the Health app, something nearly every other smartwatch brand has long offered. Based on a scale from one to ten, your Readiness Score updates dynamically and is based on recent workouts, sleep quality, training load, and vitals. </p><p>The score is accompanied by a brief, actionable, AI-generated recommendation for how to best tackle the day.</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:1415px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="o9CZhWnouG3yzLdrqQp2vK" name="AW-U4-Series12" alt="Close-up of the new Apple Watch Series 12 and Apple Watch Ultra 4 shown during the September 9 launch" src="https://cdn.mos.cms.futurecdn.net/o9CZhWnouG3yzLdrqQp2vK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1415" height="796" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p><strong>Improved step count tracking</strong></p><p>The Apple Watch Ultra 4 should be Cupertino’s most accurate step counter, thanks to a completely overhauled pedometer that uses machine learning to more accurately log your steps and distance covered. There’s also a new step count complication to more easily stay on top of your efforts. </p><p><strong>Redesigned Health app focused on trends and actionable advice </strong></p><p>A totally overhauled Health app is expected to debut later this year with a greater focus on long-term health trends and personalized wellness and fitness advice, courtesy of Siri AI. The refreshed app is expected to offer new Longevity and Insights tabs. The former features a new Health Age feature that compares your physical fitness to others in your age range.</p><p>The Insights tab, meanwhile, is where you’ll find dynamic Siri AI-generated health briefings, workout suggestions, and more.</p><p>Finally, the updated Health app will better support the integration of a user’s personal health data, including notes from doctor’s visits and lab test results. </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:1533px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="Dhxko3QL4xgb7nDXWwBhSk" name="AWU4-01" alt="Apple Watch Ultra 4 close-up showing the new LED health sensors" src="https://cdn.mos.cms.futurecdn.net/Dhxko3QL4xgb7nDXWwBhSk-1920-80.jpg" mos="" align="middle" fullscreen="" width="1533" height="862" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p><strong>Siri AI with Siri Recap</strong></p><p>The Apple Watch Ultra 4 supports Apple Siri AI voice assistant, but AI integration powers much more than just that. Siri Recap, for example, can be set up to listen in on important conversations and meetings, and then automatically generate a report with an overall summary along with key talking points. User control when this feature is active, either manually, via a schedule, or based on location. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-new-ai-features"><span>Apple Watch Ultra 4: New AI features</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="8bcbHKT8rtMP46JqtdXmRN" name="Apple Event — September 9 47-49 screenshot" alt="Live Rewind on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/8bcbHKT8rtMP46JqtdXmRN-1920-80.png" 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: Apple)</span></figcaption></figure><p><strong>Live Rewind and Sound Recognition</strong></p><p>One of the more exciting new Siri AI features is Live Rewind. Let’s say you just met someone new at a dinner party, but their name “went in one ear and out the other.” With Live Rewind, I can double-tap the digital crown on the Ultra 4 and relisten to the past 15 seconds of ambient audio anytime I like. </p><p>It’s worth noting that Apple doesn’t identify people when using this feature or save any recording. Moreover, any logged audio is end-to-end encrypted. </p><p>Finally, the Ultra 4 supports Apple’s Sound Recognition feature, which can alert those who are hard of hearing when sounds like fire alarms, doorbells, sirens, or crying babies are registered. <strong> </strong></p><h3 class="article-body__section" id="section-apple-watch-ultra-4-battery-life"><span>Apple Watch Ultra 4: Battery life</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:1338px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="93pm4CaurnZ79Nk8fsTgiP" name="AWU4-02" alt="Close-up of the Apple Watch Ultra 4 side profile" src="https://cdn.mos.cms.futurecdn.net/93pm4CaurnZ79Nk8fsTgiP-1920-80.jpg" mos="" align="middle" fullscreen="" width="1338" height="753" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>Battery life on the Apple Watch Ultra 4 has been increased to 450 hours per charge, up from 42 hours per charge for the Ultra 3. When using the Ultra 4 to log an outdoor workout with continuous GPS and heart rate tracking, users can expect about 18 hours of use. </p><p>Extended workout tracking mode bumps that number to 25 hours per charge, while a new Max Extended mode increases battery life to an impressive 45 hours per charge.</p><p>The Ultra 4 charges a little faster than its predecessor. Apple says a 15-minute charge should provide up to 18 hours of use. </p><h3 class="article-body__section" id="section-apple-watch-ultra-4-outlook"><span>Apple Watch Ultra 4: Outlook</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="pZ83Xgm3USZxuey6qEgDuK" name="Apple Event — September 9 54-44 screenshot" alt="Ternus with Apple Watch 12 series" src="https://cdn.mos.cms.futurecdn.net/pZ83Xgm3USZxuey6qEgDuK-1920-80.png" 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: Apple)</span></figcaption></figure><p>The Apple Watch Ultra 4 isn’t exactly a massive upgrade over the Ultra 3 —externally, the two are identical — but the combination of better health tracking tech, new AI features, improved battery life, and updated holistic tools galore… all for the same price as before, is pretty darn compelling.</p><p>Stay tuned for my full Apple Watch Ultra 4 review, coming soon. Until then, what new Apple Watch Ultra 4 features are you most excited about? Let me know in the comments.</p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4"><strong>I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/leaked-apple-watch-12-design-change-is-the-opposite-of-an-upgrade-and-that-has-me-worried"><strong>Leaked Apple Watch 12 design change is the opposite of an upgrade — and that has me worried</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch Series 12 announced: Everything you need to know about the new flagship Apple Watch ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Move over, Apple Watch Series 11; there's a new flagship Apple Watch in town. Apple just announced the Apple Watch Series 12 alongside the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a> during Cupertino's September 9 "<a href="https://www.tomsguide.com/phones/live/apple-surprise-and-shine-live-iphone-ultra-iphone-18-pro-max-apple-watch-series-12-and-all-the-latest-news">Surprise and Shine</a>" event (we also got the new <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know">iPhone 18 series</a> and the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-official-price-release-date-specs-and-everything-you-need-to-know">iPhone Duo</a>).</p><p>Boasting a completely redesigned health sensor array, upgraded processor, and tons of new wellness tools, here's everything you need to know about the Apple Watch Series 12. </p><h3 class="article-body__section" id="section-apple-watch-series-12-upgrades-cheat-sheet"><span>Apple Watch Series 12: Upgrades cheat sheet</span></h3><ul><li><strong>Price and release: </strong>The Apple Watch Series 12 is available for preorder starting today and will be available on September 18, with a starting price of $399, the same as the Series 11</li><li><strong>Design:</strong> The Series 12 looks similar to the Series 11; available in Space Grey, Black, Light Gold, and Dark Bronze (aluminum case); Pearl White and Night Blue (ceramic case); Polished Gold and Polished Silver (titanium case)</li><li><strong>Health features: </strong>Updated health sensing system; improved heart rate and heart rate variability (HRV) tracking; HRV reflected in Vitals app; new Readiness metric; new Health Age score; redesigned Health app with improved recovery insights and personalized AI health/fitness guidance that updates dynamically; Health app now supports personal health data and lab results</li><li><strong>AI features:</strong> Support for Siri AI voice assistant; Live Rewind lets you ‘go back in time’ up to 15 seconds; Sound Recognition can auto-alert users to common sounds like sirens and alarms; Siri Recap takes high-level notes of conversations and generates summaries</li><li><strong>Under-the-hood: </strong>Upgraded S11 processor</li><li><strong>Battery life:</strong> Up to 24 hours per charge, same as Series 11</li></ul><p>Last year's <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch Series 11</a> currently tops our <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatch</a> list; will the new Apple Watch Series 12 take its place? Maybe! Here's what's new and exciting about the latest model.</p><h3 class="article-body__section" id="section-apple-watch-series-12-price-and-release"><span>Apple Watch Series 12: Price and release</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="pZ83Xgm3USZxuey6qEgDuK" name="Apple Event — September 9 54-44 screenshot" alt="Ternus with Apple Watch 12 series" src="https://cdn.mos.cms.futurecdn.net/pZ83Xgm3USZxuey6qEgDuK-1920-80.png" 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: Apple)</span></figcaption></figure><p>Unlike Google and Samsung, which increased pricing across their respective smartwatch lines this year, Apple kept the pricing of the Series 12 consistent with last year’s model. The Apple Watch Series 12 starts at $399 for the smaller, non-cellular 42mm model.</p><p>You can preorder the Apple Watch Series 12 starting today. The device is expected to be available on September 18th. </p><h3 class="article-body__section" id="section-apple-watch-series-12-design"><span>Apple Watch Series 12: Design</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1400px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="2mFfyfBr4EGmESFEwNQ9Lf" name="AW12-01" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/2mFfyfBr4EGmESFEwNQ9Lf-1920-80.jpg" mos="" align="middle" fullscreen="" width="1400" height="787" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>Like the Apple Watch Series 11, the new Apple Watch Series 12 comes in 42mm or 46mm. While the basic design and display remain unchanged, the Series 12 features Apple's Ceramic Shield 2 screen coating, which is 60% tougher than the Ion-X glass used on the Series 11.</p><p>Apple has also added some exciting new case options, including two ceramic models in your choice of Pearl White or Night Blue.</p><p>The Series 12 is additionally available in Polished Silver titanium and Polished Gold titanium. </p><h3 class="article-body__section" id="section-apple-watch-series-12-health-and-fitness"><span>Apple Watch Series 12: Health and fitness </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="6tHqA28o6QopRXgB7G7QsQ" name="Apple Event — September 9 48-28 screenshot" alt="Siri Recap" src="https://cdn.mos.cms.futurecdn.net/6tHqA28o6QopRXgB7G7QsQ-1920-80.png" 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: Apple)</span></figcaption></figure><p>The most notable upgrades to the Apple Watch Series 12 are related to health and fitness. Cupertino completely redesigned the sensor array on the bottom of the device for improved accuracy and efficiency.</p><p>The electrode surface, used for ECG, has been increased in size for more precise readings. The photodiodes, meanwhile, have been rearranged in a ring, resulting in improved efficiency, and the LEDS, used for monitoring heart rate, are more powerful than before.</p><p>The heart rate sensor on the Series 12 now takes a reading every five seconds, day and night, a 60-fold increase in sample frequency compared to the Series 11. Heart Rate Variability (HRV) is now sampled every five minutes, or 24 times more frequently than before. </p><p>According to Apple’s internal testing, the brand’s latest smartwatches have the “most accurate heart rate tracking in a wearable.”</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="dFphJYbbEZzZLVrnAMD2GW" name="Apple Event — September 9 42-2 screenshot" alt="Updated Heartrate app on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/dFphJYbbEZzZLVrnAMD2GW-1920-80.png" 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: Apple)</span></figcaption></figure><p>Meanwhile, a new Heart Rate Variability meter, which lives in the Vitals app, provides dynamic stress and recovery advice. Apple has also added a dynamic Readiness Score, similar to what the competition offers, based on recent activity, sleep quality, and vitals. </p><p>Later this year, Cupertino will also be rolling out an updated Health app with a much cleaner design. It also adds a new “Insights” tab where users can view AI-generated summaries of their recent health trends. Speaking of AI, the app also generates custom-tailored workout and recovery suggestions. </p><p>There’s also a new “Longevity” tab where users can follow guided assessments to learn how their physical fitness compares to other users in their age range. Apple is additionally adding a new Health Age metric, similar to Garmin’s Fitness Age, which similarly compares your workout habits, VO2 Max, sleep trends, heart health, and more, to the averages for your age group. </p><p>Finally, the updated Health app will support the integration of personal health data, like lab results and medical stats. This feature is, of course, optional. </p><h3 class="article-body__section" id="section-apple-watch-series-12-ai-features"><span>Apple Watch Series 12: AI features</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="qS7FapxDrgefPJED7ezcyX" name="Apple Event — September 9 49-24 screenshot" alt="Audio Intelligence on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/qS7FapxDrgefPJED7ezcyX-1920-80.png" 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: Apple)</span></figcaption></figure><p>The Apple Watch Series 12 supports Apple's Siri AI voice assistant, but that’s not all. There are a handful of new audio-based AI features that sound (pun intended) promising, like Live Rewind, which lets you relisten to the past 15 seconds of ambient sound at any moment with a double-press of the digital crown.</p><p>I’m admittedly bad with names, so I could definitely see this feature being useful at my next social outing. Like the latest iPhones, the Series 12 also supports Sound Recognition, which is designed to alert those who are hard of hearing to common noises like fire alarms, doorbells, and even a crying baby. </p><p>Finally, Siri Recap is designed to listen in on your important conversations and create digestible notes with summaries and key points. Users can set when this feature is active or not, either manually or via a schedule/geolocation. </p><p>It’s worth noting that when using these audio AI features, no actual audio is saved, speakers aren’t identified, and everything gets end-to-end encrypted. Unfortunately, you’ll need to wait a while to test Live Rewind and Siri Recap out; they won’t be released until later this year (in beta).</p><h3 class="article-body__section" id="section-apple-watch-series-12-outlook"><span>Apple Watch Series 12: Outlook</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:1436px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="tNN5ecFPnozog8YAMcHWAN" name="AW12-03" alt="Apple Watch Series 12 launch event screenshot showing key specs of the new Apple Watch" src="https://cdn.mos.cms.futurecdn.net/tNN5ecFPnozog8YAMcHWAN-1920-80.jpg" mos="" align="middle" fullscreen="" width="1436" height="808" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>While improved battery performance or a brighter screen topped my upgrade wish list, the Apple Watch Series 12 still seems to be a noteworthy improvement over its predecessor, thanks to a faster processor, better health tracking tech, new wellness metrics galore, and support for some genuinely useful-sounding AI features. I'm also beyond pleased to see no price increases across the Series 12 line.</p><p>Stay tuned for our full Apple Watch Series 12 review. In the meantime, what are your thoughts on the new model? Are you excited for its debut, or less than impressed? Let me know below.</p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4"><strong>I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/leaked-apple-watch-12-design-change-is-the-opposite-of-an-upgrade-and-that-has-me-worried"><strong>Leaked Apple Watch 12 design change is the opposite of an upgrade — and that has me worried</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-announced-everything-you-need-to-know-about-the-new-flagship-apple-watch</link>
                                                                            <description>
                            <![CDATA[ Apple just announced the latest Apple Watch Series 12 with an upgraded processor, improved heart rate tracking, loads of new wellness tools, and a handful of impressive AI features. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">dX9sE7zN2hx5TE2bNJPD94</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/LYi3STDRm3FG5L74WfG9GN-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 17:57:20 +0000</pubDate>                                                                                                                                <updated>Wed, 09 Sep 2026 21:11:41 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/LYi3STDRm3FG5L74WfG9GN-1920-80.jpg">
                                                            <media:credit><![CDATA[Apple]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Series 12 launch event screenshot showing key specs of the new Apple Watch]]></media:description>                                                            <media:text><![CDATA[Apple Watch Series 12 launch event screenshot showing key specs of the new Apple Watch]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Series 12 launch event screenshot showing key specs of the new Apple Watch]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/LYi3STDRm3FG5L74WfG9GN-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Move over, Apple Watch Series 11; there's a new flagship Apple Watch in town. Apple just announced the Apple Watch Series 12 alongside the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a> during Cupertino's September 9 "<a href="https://www.tomsguide.com/phones/live/apple-surprise-and-shine-live-iphone-ultra-iphone-18-pro-max-apple-watch-series-12-and-all-the-latest-news">Surprise and Shine</a>" event (we also got the new <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know">iPhone 18 series</a> and the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-official-price-release-date-specs-and-everything-you-need-to-know">iPhone Duo</a>).</p><p>Boasting a completely redesigned health sensor array, upgraded processor, and tons of new wellness tools, here's everything you need to know about the Apple Watch Series 12. </p><h3 class="article-body__section" id="section-apple-watch-series-12-upgrades-cheat-sheet"><span>Apple Watch Series 12: Upgrades cheat sheet</span></h3><ul><li><strong>Price and release: </strong>The Apple Watch Series 12 is available for preorder starting today and will be available on September 18, with a starting price of $399, the same as the Series 11</li><li><strong>Design:</strong> The Series 12 looks similar to the Series 11; available in Space Grey, Black, Light Gold, and Dark Bronze (aluminum case); Pearl White and Night Blue (ceramic case); Polished Gold and Polished Silver (titanium case)</li><li><strong>Health features: </strong>Updated health sensing system; improved heart rate and heart rate variability (HRV) tracking; HRV reflected in Vitals app; new Readiness metric; new Health Age score; redesigned Health app with improved recovery insights and personalized AI health/fitness guidance that updates dynamically; Health app now supports personal health data and lab results</li><li><strong>AI features:</strong> Support for Siri AI voice assistant; Live Rewind lets you ‘go back in time’ up to 15 seconds; Sound Recognition can auto-alert users to common sounds like sirens and alarms; Siri Recap takes high-level notes of conversations and generates summaries</li><li><strong>Under-the-hood: </strong>Upgraded S11 processor</li><li><strong>Battery life:</strong> Up to 24 hours per charge, same as Series 11</li></ul><p>Last year's <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch Series 11</a> currently tops our <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatch</a> list; will the new Apple Watch Series 12 take its place? Maybe! Here's what's new and exciting about the latest model.</p><h3 class="article-body__section" id="section-apple-watch-series-12-price-and-release"><span>Apple Watch Series 12: Price and release</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="pZ83Xgm3USZxuey6qEgDuK" name="Apple Event — September 9 54-44 screenshot" alt="Ternus with Apple Watch 12 series" src="https://cdn.mos.cms.futurecdn.net/pZ83Xgm3USZxuey6qEgDuK-1920-80.png" 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: Apple)</span></figcaption></figure><p>Unlike Google and Samsung, which increased pricing across their respective smartwatch lines this year, Apple kept the pricing of the Series 12 consistent with last year’s model. The Apple Watch Series 12 starts at $399 for the smaller, non-cellular 42mm model.</p><p>You can preorder the Apple Watch Series 12 starting today. The device is expected to be available on September 18th. </p><h3 class="article-body__section" id="section-apple-watch-series-12-design"><span>Apple Watch Series 12: Design</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1400px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="2mFfyfBr4EGmESFEwNQ9Lf" name="AW12-01" alt="Apple Watch Series 12" src="https://cdn.mos.cms.futurecdn.net/2mFfyfBr4EGmESFEwNQ9Lf-1920-80.jpg" mos="" align="middle" fullscreen="" width="1400" height="787" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>Like the Apple Watch Series 11, the new Apple Watch Series 12 comes in 42mm or 46mm. While the basic design and display remain unchanged, the Series 12 features Apple's Ceramic Shield 2 screen coating, which is 60% tougher than the Ion-X glass used on the Series 11.</p><p>Apple has also added some exciting new case options, including two ceramic models in your choice of Pearl White or Night Blue.</p><p>The Series 12 is additionally available in Polished Silver titanium and Polished Gold titanium. </p><h3 class="article-body__section" id="section-apple-watch-series-12-health-and-fitness"><span>Apple Watch Series 12: Health and fitness </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="6tHqA28o6QopRXgB7G7QsQ" name="Apple Event — September 9 48-28 screenshot" alt="Siri Recap" src="https://cdn.mos.cms.futurecdn.net/6tHqA28o6QopRXgB7G7QsQ-1920-80.png" 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: Apple)</span></figcaption></figure><p>The most notable upgrades to the Apple Watch Series 12 are related to health and fitness. Cupertino completely redesigned the sensor array on the bottom of the device for improved accuracy and efficiency.</p><p>The electrode surface, used for ECG, has been increased in size for more precise readings. The photodiodes, meanwhile, have been rearranged in a ring, resulting in improved efficiency, and the LEDS, used for monitoring heart rate, are more powerful than before.</p><p>The heart rate sensor on the Series 12 now takes a reading every five seconds, day and night, a 60-fold increase in sample frequency compared to the Series 11. Heart Rate Variability (HRV) is now sampled every five minutes, or 24 times more frequently than before. </p><p>According to Apple’s internal testing, the brand’s latest smartwatches have the “most accurate heart rate tracking in a wearable.”</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="dFphJYbbEZzZLVrnAMD2GW" name="Apple Event — September 9 42-2 screenshot" alt="Updated Heartrate app on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/dFphJYbbEZzZLVrnAMD2GW-1920-80.png" 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: Apple)</span></figcaption></figure><p>Meanwhile, a new Heart Rate Variability meter, which lives in the Vitals app, provides dynamic stress and recovery advice. Apple has also added a dynamic Readiness Score, similar to what the competition offers, based on recent activity, sleep quality, and vitals. </p><p>Later this year, Cupertino will also be rolling out an updated Health app with a much cleaner design. It also adds a new “Insights” tab where users can view AI-generated summaries of their recent health trends. Speaking of AI, the app also generates custom-tailored workout and recovery suggestions. </p><p>There’s also a new “Longevity” tab where users can follow guided assessments to learn how their physical fitness compares to other users in their age range. Apple is additionally adding a new Health Age metric, similar to Garmin’s Fitness Age, which similarly compares your workout habits, VO2 Max, sleep trends, heart health, and more, to the averages for your age group. </p><p>Finally, the updated Health app will support the integration of personal health data, like lab results and medical stats. This feature is, of course, optional. </p><h3 class="article-body__section" id="section-apple-watch-series-12-ai-features"><span>Apple Watch Series 12: AI features</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="qS7FapxDrgefPJED7ezcyX" name="Apple Event — September 9 49-24 screenshot" alt="Audio Intelligence on Apple Watch 12" src="https://cdn.mos.cms.futurecdn.net/qS7FapxDrgefPJED7ezcyX-1920-80.png" 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: Apple)</span></figcaption></figure><p>The Apple Watch Series 12 supports Apple's Siri AI voice assistant, but that’s not all. There are a handful of new audio-based AI features that sound (pun intended) promising, like Live Rewind, which lets you relisten to the past 15 seconds of ambient sound at any moment with a double-press of the digital crown.</p><p>I’m admittedly bad with names, so I could definitely see this feature being useful at my next social outing. Like the latest iPhones, the Series 12 also supports Sound Recognition, which is designed to alert those who are hard of hearing to common noises like fire alarms, doorbells, and even a crying baby. </p><p>Finally, Siri Recap is designed to listen in on your important conversations and create digestible notes with summaries and key points. Users can set when this feature is active or not, either manually or via a schedule/geolocation. </p><p>It’s worth noting that when using these audio AI features, no actual audio is saved, speakers aren’t identified, and everything gets end-to-end encrypted. Unfortunately, you’ll need to wait a while to test Live Rewind and Siri Recap out; they won’t be released until later this year (in beta).</p><h3 class="article-body__section" id="section-apple-watch-series-12-outlook"><span>Apple Watch Series 12: Outlook</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:1436px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="tNN5ecFPnozog8YAMcHWAN" name="AW12-03" alt="Apple Watch Series 12 launch event screenshot showing key specs of the new Apple Watch" src="https://cdn.mos.cms.futurecdn.net/tNN5ecFPnozog8YAMcHWAN-1920-80.jpg" mos="" align="middle" fullscreen="" width="1436" height="808" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>While improved battery performance or a brighter screen topped my upgrade wish list, the Apple Watch Series 12 still seems to be a noteworthy improvement over its predecessor, thanks to a faster processor, better health tracking tech, new wellness metrics galore, and support for some genuinely useful-sounding AI features. I'm also beyond pleased to see no price increases across the Series 12 line.</p><p>Stay tuned for our full Apple Watch Series 12 review. In the meantime, what are your thoughts on the new model? Are you excited for its debut, or less than impressed? Let me know below.</p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4"><strong>I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/leaked-apple-watch-12-design-change-is-the-opposite-of-an-upgrade-and-that-has-me-worried"><strong>Leaked Apple Watch 12 design change is the opposite of an upgrade — and that has me worried</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 7 best Garmin smartwatch deals to track your activity this fall ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The Garmin Fenix 9 is here, but who wants to spend $1,099 on a new model when a bunch of older Garmins are discounted? My favorite Garmin watches still have all the important features you need, and they cost a whole lot less.</p><p>Right now you can get <a href="https://www.amazon.com/stores/page/FF0DE967-3578-4FF5-9BB4-07591E715EEE" target="_blank" rel="nofollow">up to 45% off Garmin at Amazon</a>. From the budget-friendly <a href="https://www.amazon.com/Garmin-v%C3%ADvoactive-Fitness-Smartwatch-Display/dp/B0CG6NBJ61" target="_blank" rel="nofollow">Garmin Vivoactive 5 on sale for $181</a> to the feature-packed <a href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD321" target="_blank" rel="nofollow">Garmin Fenix 8 for $749</a>, there's something for everybody here.</p><p>Keep scrolling to see all my favorite Garmin deals. I also recommend checking out our <a href="https://www.tomsguide.com/coupons/amazon.com">Amazon promo codes</a> coverage.</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/FF0DE967-3578-4FF5-9BB4-07591E715EEE" target="_blank" rel="nofollow"><strong>shop all Garmin deals at Amazon</strong></a></li><li><strong>Garmin Vivoactive 5: </strong><a href="https://www.amazon.com/dp/B0CG6NBJ61" target="_blank" rel="nofollow"><strong>was $299 now $181</strong></a></li><li><strong>Garmin Instinct Crossover Solar: </strong><a href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow"><strong>was $449 now $279</strong></a></li><li><strong>Garmin Venu 3S: </strong><a href="https://www.amazon.com/Garmin-Stainless-1-2-Inch-Touchscreen-Silicone/dp/B0CDC6Y617" target="_blank" rel="nofollow"><strong>was $449 now $288</strong></a></li><li><strong>Garmin Epix Pro: </strong><a href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow"><strong>was $1,099 now $599</strong></a></li><li><strong>Garmin Fenix 8: </strong><a href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R" target="_blank" rel="nofollow"><strong>was $999 now $749</strong></a></li></ul><h3 class="article-body__section" id="section-best-garmin-deals"><span>Best Garmin Deals</span></h3><div class="product"><a data-dimension112="2dc8d3ca-ac53-11f1-9746-898af25439c4" data-action="Deal Block" data-label="Vivoactive 5" data-dimension48="Vivoactive 5" data-dimension25="$181" href="https://www.amazon.com/dp/B0CG6NBJ61" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1004px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="VkZemqZBaA53K6cSfpqqgX" name="51zyaVCe-5L._AC_SL1000_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/VkZemqZBaA53K6cSfpqqgX-1920-80.jpg" mos="" align="middle" fullscreen="" width="1004" height="1004" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Garmin Vivoactive 5 is a comprehensive fitness tracker that comes in at an affordable price. In our <a href="https://www.tomsguide.com/reviews/garmin-vivoactive-5-review-is-it-ready-to-take-on-the-apple-watch" data-dimension112="2dc8d3ca-ac53-11f1-9746-898af25439c4" data-action="Deal Block" data-label="Vivoactive 5" data-dimension48="Vivoactive 5" data-dimension25="$181">Garmin Vivoactive 5 review</a>, we loved this device's gorgeous AMOLED display, access to multitude of sports apps and its advanced health stats like sleep and stress coaching.<a class="view-deal button" href="https://www.amazon.com/dp/B0CG6NBJ61" target="_blank" rel="nofollow" data-dimension112="2dc8d3ca-ac53-11f1-9746-898af25439c4" data-action="Deal Block" data-label="Vivoactive 5" data-dimension48="Vivoactive 5" data-dimension25="$181">View Deal</a></p></div><div class="product"><a data-dimension112="2dc8d42e-ac53-11f1-b1f1-57b4e461f78f" data-action="Deal Block" data-label="Forerunner 165" data-dimension48="Forerunner 165" data-dimension25="$199" href="https://www.amazon.com/dp/B0CT3SGHXL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:900px;"><p class="vanilla-image-block" style="padding-top:128.78%;"><img id="5kFqr4NPwzjapMdRURmKzG" name="Forerunner 165" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/5kFqr4NPwzjapMdRURmKzG-1920-80.png" mos="" align="middle" fullscreen="" width="900" height="1159" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Forerunner 165 is the perfect affordable option for runners and considerably cheaper than the newer Garmin Forerunner 170 thanks to this deal, which is on the standard model of the watch. It's a lightweight, attractive watch with an AMOLED display that offers equally accurate GPS and heart rate tracking. It also has support for NFC payments, but keep note that it lacks the music storage available on the <a href="https://www.amazon.com/Garmin-Forerunner%C2%AE-Smartwatch-Advanced-Training/dp/B0H1F79N52" target="_blank" rel="nofollow" data-dimension112="2dc8d42e-ac53-11f1-b1f1-57b4e461f78f" data-action="Deal Block" data-label="Forerunner 165" data-dimension48="Forerunner 165" data-dimension25="$199">pricier Forerunner 170 Music ($349)</a>.<a class="view-deal button" href="https://www.amazon.com/dp/B0CT3SGHXL" target="_blank" rel="nofollow" data-dimension112="2dc8d42e-ac53-11f1-b1f1-57b4e461f78f" data-action="Deal Block" data-label="Forerunner 165" data-dimension48="Forerunner 165" data-dimension25="$199">View Deal</a></p></div><div class="product"><a data-dimension112="2dc8d492-ac53-11f1-b13f-99811db76716" data-action="Deal Block" data-label="Instinct Crossover Solar" data-dimension48="Instinct Crossover Solar" data-dimension25="$279" href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1226px;"><p class="vanilla-image-block" style="padding-top:122.35%;"><img id="TVqyZieEjXyFkdy9iivkcB" name="Instinct Crossover Solar" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/TVqyZieEjXyFkdy9iivkcB-1920-80.jpg" mos="" align="middle" fullscreen="" width="1226" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow" data-dimension112="2dc8d492-ac53-11f1-b13f-99811db76716" data-action="Deal Block" data-label="Instinct Crossover Solar" data-dimension48="Instinct Crossover Solar" data-dimension25="$279">Instinct Crossover Solar: was $449 now $279</a></strong><br>The Garmin Instinct Crossover is a hybrid between a traditional watch and a smartwatch, with mechanical timekeeping and a digital display. You'll get access to smart features like GPS and NFC for payments, as well as incredible 70 day battery life thanks to the solar panel.<a class="view-deal button" href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow" data-dimension112="2dc8d492-ac53-11f1-b13f-99811db76716" data-action="Deal Block" data-label="Instinct Crossover Solar" data-dimension48="Instinct Crossover Solar" data-dimension25="$279">View Deal</a></p></div><div class="product"><a data-dimension112="2dc8d4f6-ac53-11f1-b657-5b2dd9b9dafd" data-action="Deal Block" data-label="Venu 3S" data-dimension48="Venu 3S" data-dimension25="$288" href="https://www.amazon.com/Garmin-Stainless-1-2-Inch-Touchscreen-Silicone/dp/B0CDC6Y617" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1080px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Un7k8oR8kzi2SZoU3heUR4" name="Garmin Venu 3S" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Un7k8oR8kzi2SZoU3heUR4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1080" height="1080" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Garmin Venu 3S shares many of our favorite features of the <a href="https://www.tomsguide.com/reviews/garmin-venu-3" data-dimension112="2dc8d4f6-ac53-11f1-b657-5b2dd9b9dafd" data-action="Deal Block" data-label="Venu 3S" data-dimension48="Venu 3S" data-dimension25="$288">Garmin Venu 3</a>, just in a smaller package. It has a 41mm OLED touch display, excellent fitness tracking features and its battery life lasts up to 10 days.<a class="view-deal button" href="https://www.amazon.com/Garmin-Stainless-1-2-Inch-Touchscreen-Silicone/dp/B0CDC6Y617" target="_blank" rel="nofollow" data-dimension112="2dc8d4f6-ac53-11f1-b657-5b2dd9b9dafd" data-action="Deal Block" data-label="Venu 3S" data-dimension48="Venu 3S" data-dimension25="$288">View Deal</a></p></div><div class="product"><a data-dimension112="2dc8d55a-ac53-11f1-80dd-47ea2eedf452" data-action="Deal Block" data-label="Epix Pro (Gen 2)" data-dimension48="Epix Pro (Gen 2)" data-dimension25="$599" href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1080px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="qR6ajzg9uXied8yzHk82kM" name="Garmin Epix Pro (Gen 2) GPS Smartwatch" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/qR6ajzg9uXied8yzHk82kM-1920-80.jpg" mos="" align="middle" fullscreen="" width="1080" height="1080" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow" data-dimension112="2dc8d55a-ac53-11f1-80dd-47ea2eedf452" data-action="Deal Block" data-label="Epix Pro (Gen 2)" data-dimension48="Epix Pro (Gen 2)" data-dimension25="$599">Epix Pro (Gen 2): was $1099 now $599</a></strong><br>This deal is on the 51mm Garmin Epix Pro Gen 2, the largest model in the Epix lineup. It also has the longest battery life. It's considerably cheaper than the newer Fenix 8, and having tested both, our Fitness Editor says the Epix Pro has all the same key sports tracking and training analysis features you really need, so this deal is worth considering.<a class="view-deal button" href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow" data-dimension112="2dc8d55a-ac53-11f1-80dd-47ea2eedf452" data-action="Deal Block" data-label="Epix Pro (Gen 2)" data-dimension48="Epix Pro (Gen 2)" data-dimension25="$599">View Deal</a></p></div><div class="product"><a data-dimension112="2dc8d5c8-ac53-11f1-8783-95aa9829c8ef" data-action="Deal Block" data-label="Venu X1" data-dimension48="Venu X1" data-dimension25="$599" href="https://www.amazon.com/Lightweight-Smartwatch-Advanced-Features-ComfortFit/dp/B0FCYHNL3C" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:522px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="2zzw7A2SqZL4Bd6YxTYhgG" name="71xYhGgtVCL._SX522_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/2zzw7A2SqZL4Bd6YxTYhgG-1920-80.jpg" mos="" align="middle" fullscreen="" width="522" height="522" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Looking for something different? The <a href="https://www.tomsguide.com/wellness/smartwatches/my-job-is-testing-garmins-heres-why-the-new-venu-x1-shocked-me" data-dimension112="2dc8d5c8-ac53-11f1-8783-95aa9829c8ef" data-action="Deal Block" data-label="Venu X1" data-dimension48="Venu X1" data-dimension25="$599">Garmin Venu X1</a> is a unique smartwatch with a super-large, bright AMOLED display and a super-slim design. It's a great rival to the Apple Watch Ultra for sports fans, with better tracking metrics and navigation tools.<a class="view-deal button" href="https://www.amazon.com/Lightweight-Smartwatch-Advanced-Features-ComfortFit/dp/B0FCYHNL3C" target="_blank" rel="nofollow" data-dimension112="2dc8d5c8-ac53-11f1-8783-95aa9829c8ef" data-action="Deal Block" data-label="Venu X1" data-dimension48="Venu X1" data-dimension25="$599">View Deal</a></p></div><div class="product"><a data-dimension112="2dc8d62c-ac53-11f1-a85b-5f5da67b9d1a" data-action="Deal Block" data-label="Fenix 8" data-dimension48="Fenix 8" data-dimension25="$749" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:694px;"><p class="vanilla-image-block" style="padding-top:116.86%;"><img id="DUPZqNYp7WjoWX5YqacXLE" name="Garmin Fenix 8" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DUPZqNYp7WjoWX5YqacXLE-1920-80.png" mos="" align="middle" fullscreen="" width="694" height="811" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>All three sizes of the Garmin Fenix 8 are on sale at Amazon right now, and you can get them with either steel or titanium cases. The lowest price available is on the steel 43mm or 47mm watches, while titanium models cost $100 more.<a class="view-deal button" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R" target="_blank" rel="nofollow" data-dimension112="2dc8d62c-ac53-11f1-a85b-5f5da67b9d1a" data-action="Deal Block" data-label="Fenix 8" data-dimension48="Fenix 8" data-dimension25="$749">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&rows=6&view_mode=savings_squad&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/7-best-garmin-smartwatch-deals-to-track-your-activity-this-fall</link>
                                                                            <description>
                            <![CDATA[ No need to overspend — there are a bunch of affordable Garmin deals to upgrade your fitness tracking and up your game this fall. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">5SGr6DYnKDg979qqszRXAA</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/wqbcuaC8fpbJj2ocaAyYJm-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 13:56:05 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></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/wqbcuaC8fpbJj2ocaAyYJm-1920-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Garmin Vivoactive 5 on wrist]]></media:description>                                                            <media:text><![CDATA[Garmin Vivoactive 5 on wrist]]></media:text>
                                <media:title type="plain"><![CDATA[Garmin Vivoactive 5 on wrist]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/wqbcuaC8fpbJj2ocaAyYJm-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The Garmin Fenix 9 is here, but who wants to spend $1,099 on a new model when a bunch of older Garmins are discounted? My favorite Garmin watches still have all the important features you need, and they cost a whole lot less.</p><p>Right now you can get <a href="https://www.amazon.com/stores/page/FF0DE967-3578-4FF5-9BB4-07591E715EEE" target="_blank" rel="nofollow">up to 45% off Garmin at Amazon</a>. From the budget-friendly <a href="https://www.amazon.com/Garmin-v%C3%ADvoactive-Fitness-Smartwatch-Display/dp/B0CG6NBJ61" target="_blank" rel="nofollow">Garmin Vivoactive 5 on sale for $181</a> to the feature-packed <a href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD321" target="_blank" rel="nofollow">Garmin Fenix 8 for $749</a>, there's something for everybody here.</p><p>Keep scrolling to see all my favorite Garmin deals. I also recommend checking out our <a href="https://www.tomsguide.com/coupons/amazon.com">Amazon promo codes</a> coverage.</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/FF0DE967-3578-4FF5-9BB4-07591E715EEE" target="_blank" rel="nofollow"><strong>shop all Garmin deals at Amazon</strong></a></li><li><strong>Garmin Vivoactive 5: </strong><a href="https://www.amazon.com/dp/B0CG6NBJ61" target="_blank" rel="nofollow"><strong>was $299 now $181</strong></a></li><li><strong>Garmin Instinct Crossover Solar: </strong><a href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow"><strong>was $449 now $279</strong></a></li><li><strong>Garmin Venu 3S: </strong><a href="https://www.amazon.com/Garmin-Stainless-1-2-Inch-Touchscreen-Silicone/dp/B0CDC6Y617" target="_blank" rel="nofollow"><strong>was $449 now $288</strong></a></li><li><strong>Garmin Epix Pro: </strong><a href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow"><strong>was $1,099 now $599</strong></a></li><li><strong>Garmin Fenix 8: </strong><a href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R" target="_blank" rel="nofollow"><strong>was $999 now $749</strong></a></li></ul><h3 class="article-body__section" id="section-best-garmin-deals"><span>Best Garmin Deals</span></h3><div class="product"><a data-dimension112="2dc8d3ca-ac53-11f1-9746-898af25439c4" data-action="Deal Block" data-label="Vivoactive 5" data-dimension48="Vivoactive 5" data-dimension25="$181" href="https://www.amazon.com/dp/B0CG6NBJ61" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1004px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="VkZemqZBaA53K6cSfpqqgX" name="51zyaVCe-5L._AC_SL1000_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/VkZemqZBaA53K6cSfpqqgX-1920-80.jpg" mos="" align="middle" fullscreen="" width="1004" height="1004" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Garmin Vivoactive 5 is a comprehensive fitness tracker that comes in at an affordable price. In our <a href="https://www.tomsguide.com/reviews/garmin-vivoactive-5-review-is-it-ready-to-take-on-the-apple-watch" data-dimension112="2dc8d3ca-ac53-11f1-9746-898af25439c4" data-action="Deal Block" data-label="Vivoactive 5" data-dimension48="Vivoactive 5" data-dimension25="$181">Garmin Vivoactive 5 review</a>, we loved this device's gorgeous AMOLED display, access to multitude of sports apps and its advanced health stats like sleep and stress coaching.<a class="view-deal button" href="https://www.amazon.com/dp/B0CG6NBJ61" target="_blank" rel="nofollow" data-dimension112="2dc8d3ca-ac53-11f1-9746-898af25439c4" data-action="Deal Block" data-label="Vivoactive 5" data-dimension48="Vivoactive 5" data-dimension25="$181">View Deal</a></p></div><div class="product"><a data-dimension112="2dc8d42e-ac53-11f1-b1f1-57b4e461f78f" data-action="Deal Block" data-label="Forerunner 165" data-dimension48="Forerunner 165" data-dimension25="$199" href="https://www.amazon.com/dp/B0CT3SGHXL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:900px;"><p class="vanilla-image-block" style="padding-top:128.78%;"><img id="5kFqr4NPwzjapMdRURmKzG" name="Forerunner 165" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/5kFqr4NPwzjapMdRURmKzG-1920-80.png" mos="" align="middle" fullscreen="" width="900" height="1159" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Forerunner 165 is the perfect affordable option for runners and considerably cheaper than the newer Garmin Forerunner 170 thanks to this deal, which is on the standard model of the watch. It's a lightweight, attractive watch with an AMOLED display that offers equally accurate GPS and heart rate tracking. It also has support for NFC payments, but keep note that it lacks the music storage available on the <a href="https://www.amazon.com/Garmin-Forerunner%C2%AE-Smartwatch-Advanced-Training/dp/B0H1F79N52" target="_blank" rel="nofollow" data-dimension112="2dc8d42e-ac53-11f1-b1f1-57b4e461f78f" data-action="Deal Block" data-label="Forerunner 165" data-dimension48="Forerunner 165" data-dimension25="$199">pricier Forerunner 170 Music ($349)</a>.<a class="view-deal button" href="https://www.amazon.com/dp/B0CT3SGHXL" target="_blank" rel="nofollow" data-dimension112="2dc8d42e-ac53-11f1-b1f1-57b4e461f78f" data-action="Deal Block" data-label="Forerunner 165" data-dimension48="Forerunner 165" data-dimension25="$199">View Deal</a></p></div><div class="product"><a data-dimension112="2dc8d492-ac53-11f1-b13f-99811db76716" data-action="Deal Block" data-label="Instinct Crossover Solar" data-dimension48="Instinct Crossover Solar" data-dimension25="$279" href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1226px;"><p class="vanilla-image-block" style="padding-top:122.35%;"><img id="TVqyZieEjXyFkdy9iivkcB" name="Instinct Crossover Solar" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/TVqyZieEjXyFkdy9iivkcB-1920-80.jpg" mos="" align="middle" fullscreen="" width="1226" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow" data-dimension112="2dc8d492-ac53-11f1-b13f-99811db76716" data-action="Deal Block" data-label="Instinct Crossover Solar" data-dimension48="Instinct Crossover Solar" data-dimension25="$279">Instinct Crossover Solar: was $449 now $279</a></strong><br>The Garmin Instinct Crossover is a hybrid between a traditional watch and a smartwatch, with mechanical timekeeping and a digital display. You'll get access to smart features like GPS and NFC for payments, as well as incredible 70 day battery life thanks to the solar panel.<a class="view-deal button" href="https://www.amazon.com/Garmin-Instinct-Crossover-Smartwatch-Capabilities/dp/B0BHTV7MCG" target="_blank" rel="nofollow" data-dimension112="2dc8d492-ac53-11f1-b13f-99811db76716" data-action="Deal Block" data-label="Instinct Crossover Solar" data-dimension48="Instinct Crossover Solar" data-dimension25="$279">View Deal</a></p></div><div class="product"><a data-dimension112="2dc8d4f6-ac53-11f1-b657-5b2dd9b9dafd" data-action="Deal Block" data-label="Venu 3S" data-dimension48="Venu 3S" data-dimension25="$288" href="https://www.amazon.com/Garmin-Stainless-1-2-Inch-Touchscreen-Silicone/dp/B0CDC6Y617" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1080px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Un7k8oR8kzi2SZoU3heUR4" name="Garmin Venu 3S" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Un7k8oR8kzi2SZoU3heUR4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1080" height="1080" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Garmin Venu 3S shares many of our favorite features of the <a href="https://www.tomsguide.com/reviews/garmin-venu-3" data-dimension112="2dc8d4f6-ac53-11f1-b657-5b2dd9b9dafd" data-action="Deal Block" data-label="Venu 3S" data-dimension48="Venu 3S" data-dimension25="$288">Garmin Venu 3</a>, just in a smaller package. It has a 41mm OLED touch display, excellent fitness tracking features and its battery life lasts up to 10 days.<a class="view-deal button" href="https://www.amazon.com/Garmin-Stainless-1-2-Inch-Touchscreen-Silicone/dp/B0CDC6Y617" target="_blank" rel="nofollow" data-dimension112="2dc8d4f6-ac53-11f1-b657-5b2dd9b9dafd" data-action="Deal Block" data-label="Venu 3S" data-dimension48="Venu 3S" data-dimension25="$288">View Deal</a></p></div><div class="product"><a data-dimension112="2dc8d55a-ac53-11f1-80dd-47ea2eedf452" data-action="Deal Block" data-label="Epix Pro (Gen 2)" data-dimension48="Epix Pro (Gen 2)" data-dimension25="$599" href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1080px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="qR6ajzg9uXied8yzHk82kM" name="Garmin Epix Pro (Gen 2) GPS Smartwatch" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/qR6ajzg9uXied8yzHk82kM-1920-80.jpg" mos="" align="middle" fullscreen="" width="1080" height="1080" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow" data-dimension112="2dc8d55a-ac53-11f1-80dd-47ea2eedf452" data-action="Deal Block" data-label="Epix Pro (Gen 2)" data-dimension48="Epix Pro (Gen 2)" data-dimension25="$599">Epix Pro (Gen 2): was $1099 now $599</a></strong><br>This deal is on the 51mm Garmin Epix Pro Gen 2, the largest model in the Epix lineup. It also has the longest battery life. It's considerably cheaper than the newer Fenix 8, and having tested both, our Fitness Editor says the Epix Pro has all the same key sports tracking and training analysis features you really need, so this deal is worth considering.<a class="view-deal button" href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFCZZ9F/" target="_blank" rel="nofollow" data-dimension112="2dc8d55a-ac53-11f1-80dd-47ea2eedf452" data-action="Deal Block" data-label="Epix Pro (Gen 2)" data-dimension48="Epix Pro (Gen 2)" data-dimension25="$599">View Deal</a></p></div><div class="product"><a data-dimension112="2dc8d5c8-ac53-11f1-8783-95aa9829c8ef" data-action="Deal Block" data-label="Venu X1" data-dimension48="Venu X1" data-dimension25="$599" href="https://www.amazon.com/Lightweight-Smartwatch-Advanced-Features-ComfortFit/dp/B0FCYHNL3C" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:522px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="2zzw7A2SqZL4Bd6YxTYhgG" name="71xYhGgtVCL._SX522_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/2zzw7A2SqZL4Bd6YxTYhgG-1920-80.jpg" mos="" align="middle" fullscreen="" width="522" height="522" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Looking for something different? The <a href="https://www.tomsguide.com/wellness/smartwatches/my-job-is-testing-garmins-heres-why-the-new-venu-x1-shocked-me" data-dimension112="2dc8d5c8-ac53-11f1-8783-95aa9829c8ef" data-action="Deal Block" data-label="Venu X1" data-dimension48="Venu X1" data-dimension25="$599">Garmin Venu X1</a> is a unique smartwatch with a super-large, bright AMOLED display and a super-slim design. It's a great rival to the Apple Watch Ultra for sports fans, with better tracking metrics and navigation tools.<a class="view-deal button" href="https://www.amazon.com/Lightweight-Smartwatch-Advanced-Features-ComfortFit/dp/B0FCYHNL3C" target="_blank" rel="nofollow" data-dimension112="2dc8d5c8-ac53-11f1-8783-95aa9829c8ef" data-action="Deal Block" data-label="Venu X1" data-dimension48="Venu X1" data-dimension25="$599">View Deal</a></p></div><div class="product"><a data-dimension112="2dc8d62c-ac53-11f1-a85b-5f5da67b9d1a" data-action="Deal Block" data-label="Fenix 8" data-dimension48="Fenix 8" data-dimension25="$749" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:694px;"><p class="vanilla-image-block" style="padding-top:116.86%;"><img id="DUPZqNYp7WjoWX5YqacXLE" name="Garmin Fenix 8" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DUPZqNYp7WjoWX5YqacXLE-1920-80.png" mos="" align="middle" fullscreen="" width="694" height="811" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>All three sizes of the Garmin Fenix 8 are on sale at Amazon right now, and you can get them with either steel or titanium cases. The lowest price available is on the steel 43mm or 47mm watches, while titanium models cost $100 more.<a class="view-deal button" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R" target="_blank" rel="nofollow" data-dimension112="2dc8d62c-ac53-11f1-a85b-5f5da67b9d1a" data-action="Deal Block" data-label="Fenix 8" data-dimension48="Fenix 8" data-dimension25="$749">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&rows=6&view_mode=savings_squad&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I use readiness on my Garmin watch every day — here’s why I'm excited about it coming to the Apple Watch ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple is expected to launch new models of both the Apple Watch and Apple Watch Ultra at today's <a href="https://www.tomsguide.com/phones/live/apple-surprise-and-shine-live-iphone-ultra-iphone-18-pro-max-apple-watch-series-12-and-all-the-latest-news">“Surprise and Shine” event</a>, and according to<a href="https://x.com/markgurman/status/2097348111211659388" target="_blank"> Bloomberg’s Mark Gurman</a>, a new readiness app is set to be a key new feature on the watches.</p><p>Readiness scores are nothing new for wearables and are a key feature of screenless wearables like 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 </a>and <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a>, along with the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches</a>. Adding the holistic health metric to the Apple Watch is a great move in my opinion — I check the score regularly myself on my <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-garmin-forerunner-970-for-six-months-here-are-my-long-term-pros-and-cons">Garmin Forerunner 970</a> to help get a picture of the state of my body.</p><p>It’s not a perfect metric and as ever with the stats on wearables, a readiness score is just a guideline, not something to stick to rigidly, but if confirmed it would be a useful addition to the Apple Watch.</p><h3 class="article-body__section" id="section-what-is-readiness-and-how-is-it-measured"><span>What is readiness and how is it measured?</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="HknnQkwLaNaperRNdfsSQH" name="Garmin Forerunner 970 Readiness" alt="Garmin Forerunner 970 Readiness" src="https://cdn.mos.cms.futurecdn.net/HknnQkwLaNaperRNdfsSQH-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>Simply put, a readiness score indicates how prepared you are to handle the day ahead of you, based on health metrics measured by your wearable.</p><p>It’s sometimes called a recovery score and with many watches and trackers the focus will lean towards how ready you are to train in particular, so you can understand how hard to push in a workout.</p><p>The key stats generally used by a wearable to determine readiness are how well you’ve slept — both last night and over the past couple of weeks — the intensity of your recent activity and workouts, and heart rate stats like heart rate variability and your resting heart rate.</p><p><a href="https://www.tomsguide.com/wellness/sleep/experts-explain-what-hrv-on-your-sleep-tracker-means-and-how-to-improve-yours">Heart rate variability</a> (HRV) in particular is an important metric, because it’s often used as an indication of the stress on your body. Deviations from your normal ranges can indicate that you’re not well recovered, or are even getting ill.</p><p>Past Apple Watch models have measured all the key stats needed for readiness, but didn’t measure your heart rate continuously outside of workouts to save battery life, which reduces the accuracy of the stats that would underpin a readiness score.</p><p>The Apple Watch Series 12 and Apple Watch Ultra 4 are<a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-5-last-minute-leaks-worth-knowing-about#section-apple-watch-12-health-and-fitness-rumors"> rumored to be getting a continuous heart rate monitor</a>, which would tie in with the launch of a readiness score if true.</p><p>At the moment you can get readiness scores from apps like Bevel and Athlytic on the Apple Watch, but I’ve tested these and the lack of continuous heart rate monitoring does throw up some inconsistent results.</p><h3 class="article-body__section" id="section-what-are-the-benefits-of-a-readiness-score"><span>What are the benefits of a readiness score?</span></h3><p>I use readiness scores as a handy one-stop shop that bundles a lot of data into one easy-to-understand data point I can use to check in on my body.</p><p>When I first started using the readiness score on Oura and Garmin devices, I realised I don’t really care exactly how I slept, or what my individual HRV scores were, I just want to know if I’m in good shape to tackle the day, and that’s how readiness works. </p><p>You can still dive into all the individual data points if you want, but the convenience of one score you can see quickly in an app or on your watch face is great for busy mornings.</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:4327px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="5GxrATJEfJ9CLJQsTq88Y9" name="Garmin Forerunner 170" alt="Garmin Forerunner 170" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:384,l:823,cw:4327,ch:2434,q:80/5GxrATJEfJ9CLJQsTq88Y9.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Trends in your readiness score can be great indications of underlying problems too. If I feel like I'm sleeping well and training normally, low scores can be a sign I’m getting ill. This is especially handy as a parent of two young kids who seem to make it their mission to bring as many germs into the house as possible.</p><p>When I’m deep into marathon training and feel a little tired all the time, a high readiness score gives me confidence that I’m actually adapting well to training, and I find that aiming to get a high score promotes good habits like maintaining a consistent bedtime.</p><p>I don’t completely upend my plans if a low score comes up, but I might take things a little easier on my run if I see my readiness is in the red in the morning.</p><p>While it’s not a perfectly accurate score, which I’ll come to, I have found that trends in my Training Readiness score on my Garmin over many years have been a reliable indicator of where my body is at, and that’s useful info to have on your wrist.</p><h3 class="article-body__section" id="section-what-are-the-drawbacks-of-a-readiness-score"><span>What are the drawbacks of a readiness score?</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:3520px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="YVx5Aog8ZrwK7Ean8QHQPm" name="Oura Ring" alt="Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/YVx5Aog8ZrwK7Ean8QHQPm-1920-80.jpg" mos="" align="middle" fullscreen="" width="3520" height="1980" 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>Readiness scores reduces a lot of data to one single score, and if the data underpinning the stat is flawed, then your readiness score can be too. </p><p>Wearables are not perfect with regards to sleep tracking in particular, and with Garmin I have to bear in mind the watches tend to overestimate time asleep and account for that when looking at my score.</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:3371px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="Si9LiYVWRQx8ktemSe4U4e" name="Garmin Venu 4" alt="the Garmin Venu 4 in lunar gold on the wrist" src="https://cdn.mos.cms.futurecdn.net/Si9LiYVWRQx8ktemSe4U4e-1920-80.jpg" mos="" align="middle" fullscreen="" width="3371" height="1896" 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 Apple Watch is one of the better sleep trackers I’ve tested for accuracy, but does tend to give high sleep scores in my experience, which might in turn inflate your readiness score.</p><p>It’s worth checking in on the stats underpinning any readiness score occasionally to see if anything rings false, and in general I think it’s better to look at trends in your data from a device rather than a score on any given day. One very low readiness score might not mean much, but a few days of your score dropping could well be a sign something is wrong.</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="L9RMjnoVbASLpjLkeeNPLW" name="SleepTrackersWhoopMG4" alt="Our sleep tech tester testing the Whoop MG" src="https://cdn.mos.cms.futurecdn.net/L9RMjnoVbASLpjLkeeNPLW-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>If the Apple Watch is getting a continuous heart rate monitor then this might reduce battery life too. That said, many wearables still manage to offer this feature while having long battery life, so hopefully the new watches will at least maintain the battery life of the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch Series 11</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a>.</p><p>Perhaps a bigger drawback to readiness scores is that they can mess with your head a little. It’s important not to let them dictate your day too much and worry about a low score — you don’t need to be at 100% readiness to smash your workout or a busy day at the office.</p><div><blockquote><p>Perhaps a bigger drawback to readiness scores is that they can mess with your head a little.</p></blockquote></div><p>I’ve run some of my best races on low-readiness days and actually usually don’t wear my watch the night before a marathon now, because I don’t find that data helpful on race morning.</p><p>Like all the data on your wearable, it’s a tool or a guideline that can help at times, but if it’s not proving helpful or actually even adding to your stress, then I think it’s always best to just ignore it.</p><p>As an example of that, Roger Bannister slept poorly and then worked a shift in a hospital the morning of the day he ran the first sub-four-minute mile. He wasn't sure if he'd even run, and if he'd had a watch telling him his readiness was low, maybe he wouldn't have. Data is useful, but don't let it be the boss.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OoNbJW"></div>                            </div>                            <script src="https://kwizly.com/embed/OoNbJW.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-wear-an-apple-watch-every-single-day-and-i-never-knew-you-could-do-this">‘I wear an Apple Watch every single day, and I never knew you could do this.’</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/i-wear-an-apple-watch-every-day-and-this-is-the-free-app-i-use-all-of-the-time">I wear an Apple Watch every day, and this is the free app I use all of the time</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/too-busy-to-work-out-i-added-thousands-of-steps-to-my-day-using-this-simple-trick">Forget running — I added thousands of steps to my day using this simple trick</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/i-use-readiness-on-my-garmin-watch-every-day-heres-why-im-excited-about-it-coming-to-the-apple-watch</link>
                                                                            <description>
                            <![CDATA[ Readiness scores can provide a useful snapshot of the state of your body at any given time, and I find the score especially useful as a keen runner. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">X3EeYZuByWGj4Y4QmSyMAm</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/VzUcM6wtvXKraohPwDUeaH-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 11:07:40 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Nick Harris-Fry ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/J5Jjp49GUVjLZEbjEkTex-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/VzUcM6wtvXKraohPwDUeaH-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Garmin Fenix 9 Pro Readiness]]></media:description>                                                            <media:text><![CDATA[Garmin Fenix 9 Pro Readiness]]></media:text>
                                <media:title type="plain"><![CDATA[Garmin Fenix 9 Pro Readiness]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/VzUcM6wtvXKraohPwDUeaH-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple is expected to launch new models of both the Apple Watch and Apple Watch Ultra at today's <a href="https://www.tomsguide.com/phones/live/apple-surprise-and-shine-live-iphone-ultra-iphone-18-pro-max-apple-watch-series-12-and-all-the-latest-news">“Surprise and Shine” event</a>, and according to<a href="https://x.com/markgurman/status/2097348111211659388" target="_blank"> Bloomberg’s Mark Gurman</a>, a new readiness app is set to be a key new feature on the watches.</p><p>Readiness scores are nothing new for wearables and are a key feature of screenless wearables like 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 </a>and <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a>, along with the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches</a>. Adding the holistic health metric to the Apple Watch is a great move in my opinion — I check the score regularly myself on my <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-garmin-forerunner-970-for-six-months-here-are-my-long-term-pros-and-cons">Garmin Forerunner 970</a> to help get a picture of the state of my body.</p><p>It’s not a perfect metric and as ever with the stats on wearables, a readiness score is just a guideline, not something to stick to rigidly, but if confirmed it would be a useful addition to the Apple Watch.</p><h3 class="article-body__section" id="section-what-is-readiness-and-how-is-it-measured"><span>What is readiness and how is it measured?</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="HknnQkwLaNaperRNdfsSQH" name="Garmin Forerunner 970 Readiness" alt="Garmin Forerunner 970 Readiness" src="https://cdn.mos.cms.futurecdn.net/HknnQkwLaNaperRNdfsSQH-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>Simply put, a readiness score indicates how prepared you are to handle the day ahead of you, based on health metrics measured by your wearable.</p><p>It’s sometimes called a recovery score and with many watches and trackers the focus will lean towards how ready you are to train in particular, so you can understand how hard to push in a workout.</p><p>The key stats generally used by a wearable to determine readiness are how well you’ve slept — both last night and over the past couple of weeks — the intensity of your recent activity and workouts, and heart rate stats like heart rate variability and your resting heart rate.</p><p><a href="https://www.tomsguide.com/wellness/sleep/experts-explain-what-hrv-on-your-sleep-tracker-means-and-how-to-improve-yours">Heart rate variability</a> (HRV) in particular is an important metric, because it’s often used as an indication of the stress on your body. Deviations from your normal ranges can indicate that you’re not well recovered, or are even getting ill.</p><p>Past Apple Watch models have measured all the key stats needed for readiness, but didn’t measure your heart rate continuously outside of workouts to save battery life, which reduces the accuracy of the stats that would underpin a readiness score.</p><p>The Apple Watch Series 12 and Apple Watch Ultra 4 are<a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-5-last-minute-leaks-worth-knowing-about#section-apple-watch-12-health-and-fitness-rumors"> rumored to be getting a continuous heart rate monitor</a>, which would tie in with the launch of a readiness score if true.</p><p>At the moment you can get readiness scores from apps like Bevel and Athlytic on the Apple Watch, but I’ve tested these and the lack of continuous heart rate monitoring does throw up some inconsistent results.</p><h3 class="article-body__section" id="section-what-are-the-benefits-of-a-readiness-score"><span>What are the benefits of a readiness score?</span></h3><p>I use readiness scores as a handy one-stop shop that bundles a lot of data into one easy-to-understand data point I can use to check in on my body.</p><p>When I first started using the readiness score on Oura and Garmin devices, I realised I don’t really care exactly how I slept, or what my individual HRV scores were, I just want to know if I’m in good shape to tackle the day, and that’s how readiness works. </p><p>You can still dive into all the individual data points if you want, but the convenience of one score you can see quickly in an app or on your watch face is great for busy mornings.</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:4327px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="5GxrATJEfJ9CLJQsTq88Y9" name="Garmin Forerunner 170" alt="Garmin Forerunner 170" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:384,l:823,cw:4327,ch:2434,q:80/5GxrATJEfJ9CLJQsTq88Y9.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Trends in your readiness score can be great indications of underlying problems too. If I feel like I'm sleeping well and training normally, low scores can be a sign I’m getting ill. This is especially handy as a parent of two young kids who seem to make it their mission to bring as many germs into the house as possible.</p><p>When I’m deep into marathon training and feel a little tired all the time, a high readiness score gives me confidence that I’m actually adapting well to training, and I find that aiming to get a high score promotes good habits like maintaining a consistent bedtime.</p><p>I don’t completely upend my plans if a low score comes up, but I might take things a little easier on my run if I see my readiness is in the red in the morning.</p><p>While it’s not a perfectly accurate score, which I’ll come to, I have found that trends in my Training Readiness score on my Garmin over many years have been a reliable indicator of where my body is at, and that’s useful info to have on your wrist.</p><h3 class="article-body__section" id="section-what-are-the-drawbacks-of-a-readiness-score"><span>What are the drawbacks of a readiness score?</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:3520px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="YVx5Aog8ZrwK7Ean8QHQPm" name="Oura Ring" alt="Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/YVx5Aog8ZrwK7Ean8QHQPm-1920-80.jpg" mos="" align="middle" fullscreen="" width="3520" height="1980" 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>Readiness scores reduces a lot of data to one single score, and if the data underpinning the stat is flawed, then your readiness score can be too. </p><p>Wearables are not perfect with regards to sleep tracking in particular, and with Garmin I have to bear in mind the watches tend to overestimate time asleep and account for that when looking at my score.</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:3371px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="Si9LiYVWRQx8ktemSe4U4e" name="Garmin Venu 4" alt="the Garmin Venu 4 in lunar gold on the wrist" src="https://cdn.mos.cms.futurecdn.net/Si9LiYVWRQx8ktemSe4U4e-1920-80.jpg" mos="" align="middle" fullscreen="" width="3371" height="1896" 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 Apple Watch is one of the better sleep trackers I’ve tested for accuracy, but does tend to give high sleep scores in my experience, which might in turn inflate your readiness score.</p><p>It’s worth checking in on the stats underpinning any readiness score occasionally to see if anything rings false, and in general I think it’s better to look at trends in your data from a device rather than a score on any given day. One very low readiness score might not mean much, but a few days of your score dropping could well be a sign something is wrong.</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="L9RMjnoVbASLpjLkeeNPLW" name="SleepTrackersWhoopMG4" alt="Our sleep tech tester testing the Whoop MG" src="https://cdn.mos.cms.futurecdn.net/L9RMjnoVbASLpjLkeeNPLW-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>If the Apple Watch is getting a continuous heart rate monitor then this might reduce battery life too. That said, many wearables still manage to offer this feature while having long battery life, so hopefully the new watches will at least maintain the battery life of the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch Series 11</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a>.</p><p>Perhaps a bigger drawback to readiness scores is that they can mess with your head a little. It’s important not to let them dictate your day too much and worry about a low score — you don’t need to be at 100% readiness to smash your workout or a busy day at the office.</p><div><blockquote><p>Perhaps a bigger drawback to readiness scores is that they can mess with your head a little.</p></blockquote></div><p>I’ve run some of my best races on low-readiness days and actually usually don’t wear my watch the night before a marathon now, because I don’t find that data helpful on race morning.</p><p>Like all the data on your wearable, it’s a tool or a guideline that can help at times, but if it’s not proving helpful or actually even adding to your stress, then I think it’s always best to just ignore it.</p><p>As an example of that, Roger Bannister slept poorly and then worked a shift in a hospital the morning of the day he ran the first sub-four-minute mile. He wasn't sure if he'd even run, and if he'd had a watch telling him his readiness was low, maybe he wouldn't have. Data is useful, but don't let it be the boss.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OoNbJW"></div>                            </div>                            <script src="https://kwizly.com/embed/OoNbJW.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-wear-an-apple-watch-every-single-day-and-i-never-knew-you-could-do-this">‘I wear an Apple Watch every single day, and I never knew you could do this.’</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/i-wear-an-apple-watch-every-day-and-this-is-the-free-app-i-use-all-of-the-time">I wear an Apple Watch every day, and this is the free app I use all of the time</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/too-busy-to-work-out-i-added-thousands-of-steps-to-my-day-using-this-simple-trick">Forget running — I added thousands of steps to my day using this simple trick</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ The 5 coolest pieces of wearable tech I demoed at IFA 2026 in Berlin ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I attended my first <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA trade show</a> in Berlin last week, and between countless helpings of currywurst, I found myself genuinely floored by all the cool new wearable tech on display. </p><p>From smarter smart rings with onboard NFC for mobile payments to AI-powered pendants that serve as a "second memory," IFA proved to be a treasure trove for gadget lovers like myself. With that in mind, these are the five most incredible pieces of wearable tech I demoed at IFA 2026.</p><h3 class="article-body__section" id="section-1-luna-band"><span>1. Luna Band</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="EtCmRxAJth6TNRprGsdRHo" name="Luna-Band-01" alt="Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/EtCmRxAJth6TNRprGsdRHo-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>I first saw an early version of the Luna Band at <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-luna-band-fitness-tracker-and-it-beats-the-whoop-5-0-in-3-big-ways">CES 2026</a> in January, long before the arrival of the <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-garmin-cirqa-and-it-strikes-a-near-perfect-balance-between-the-fitbit-air-and-whoop-5-0">Garmin Cirqa</a> and <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">Fitbit Air</a>, two of the most capable (mostly) subscription-free alternatives to the popular screenless <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a> fitness tracker.</p><p>Boasting similar features and specs to the competition, the new <a href="https://www.tomsguide.com/wellness/fitness-trackers/forget-whoop-3-major-differences-between-the-subscription-free-luna-band-and-garmin-cirqa">Luna Band</a> splits the difference, price-wise, between the Cirqa ($199) and Air ($99), with a cost of $149. </p><p>However, one notable advantage the Luna Band has over the competition is a completely subscription-free approach to wellness. While Google (Fitbit) and Garmin make you pony up extra cash for deeper insights and AI-generated personalized recommendations, Luna does not. </p><p>In fact, custom-tailored AI-generated workout and health recommendations are a major selling point of the Luna Band. And rather than being overly focused on a cascade of metrics and charts, the companion Luna app is more geared toward digestible, actionable text-based advice based on your holistic trends and personal goals. </p><p>Stay tuned for a full review of the Luna Band, along with head-to-head comparisons versus the competition.</p><h3 class="article-body__section" id="section-2-circular-ring-3"><span>2. Circular Ring 3</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.29%;"><img id="nTJzQuQRUCp2UEiFXmdct7" name="CircularRing3-06" alt="Close-up of the Circular Ring 3 Pro and Slim at the IFA show in Berlin, Germany" src="https://cdn.mos.cms.futurecdn.net/nTJzQuQRUCp2UEiFXmdct7-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1441" 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 launch of the <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">Circular Ring 3</a> was easily the biggest surprise of IFA, at least when it comes to wearable tech. The Circular Ring 2 was a mighty fine alternative to the latest <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>, aka the <a href="https://www.tomsguide.com/wellness/fitness-trackers/best-smart-rings">best smart ring</a> on the market, but when I reviewed it, a buggy app held back the overall user experience.</p><p>Since then, Circular completely overhauled and relaunched the companion app, and more notably, debuted not one but two new smart rings: the Circular Ring 3 Pro and Circular Ring 3 Slim.</p><p>Unlike Oura, these smart rings are subscription-free. They also support some unique features, most notably onboard NFC, giving you the power to pay for things with the touch of a finger. They also support haptic feedback for alerts and alarms. </p><p>The Ring Pro 3 additionally supports a promising new blood pressure trends feature that I look forward to testing when the wearable ships this winter.</p><h3 class="article-body__section" id="section-3-moto-watch-ultra"><span>3. Moto Watch Ultra</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="TuahqyBcrowTeXY8k4uTxa" name="Moto Watch Ultra-2" alt="Close-up of the new Moto Watch Ultra LTE smartwatch at IFA 2026 in Berin" src="https://cdn.mos.cms.futurecdn.net/TuahqyBcrowTeXY8k4uTxa-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: Anthony Spadafora/Tom's Guide)</span></figcaption></figure><p>The <a href="https://www.tomsguide.com/wellness/smartwatches/i-just-went-hands-on-with-motorolas-first-lte-smartwatch-and-google-and-samsung-should-be-worried">Moto Watch Ultra</a> was another pleasant IFA surprise announcement. Motorola's first-ever LTE-capable smartwatch, the Moto Watch Ultra is a direct competitor to the likes of the <a href="https://www.tomsguide.com/wellness/smartwatches/i-wore-the-samsung-galaxy-watch-9-for-a-month-the-new-health-tools-impress-but-that-doesnt-mean-you-should-upgrade">Samsung Galaxy Watch 9</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review">Google Pixel Watch 5</a>, two of the <a href="https://www.tomsguide.com/best-picks/best-smartwatches-android">best smartwatches for Android</a> in 2026.</p><p>The thing is, the Moto Watch Ultra is priced lower than both of the above, while offering similar features. It runs Google's bug-free and user-friendly Wear OS, and for health and fitness tracking, Motorola partnered with the trusted Finnish smartwatch brand Polar.</p><p>A lovely-looking brushed stainless steel case additionally gives the Moto Watch Ultra a more premium look than the competition. Available starting on September 10, the Moto Watch Ultra starts at $349 via Motorola and Amazon. </p><h3 class="article-body__section" id="section-4-odyss-n1"><span>4. Odyss N1 </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="bNn9ciK87xCezTzjhQforZ" name="Odyss-06" alt="Close-up of the Odyss N1 AI-powered necklace that tracks what you eat" src="https://cdn.mos.cms.futurecdn.net/bNn9ciK87xCezTzjhQforZ-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>No, it's not a shark tooth necklace; the <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-odyss-n1-a-sleek-ai-necklace-that-automatically-logs-everything-you-eat#section-odyss-n1-ai-necklace-outlook">Odyss N1</a> is a small, metal pendant sporting an onboard camera and motion sensor designed to automatically log everything you eat. Still just a concept, the Odyss N1 was unknown to me prior to IFA, but when I spotted the brand's booth in the depths of the Berlin Messe, I was instantly drawn in.</p><p>In 2026, the <a href="https://www.tomsguide.com/us/best-fitness-trackers,review-2066.html">best fitness trackers</a> and smartwatches may be able to automatically log sleep, workouts, and stress, but they drop the ball when it comes to recording food intake without user input. This is where the Odyss N1 comes in. Designed to work alongside other fitness wearables, the N1 takes a few weeks to calibrate and learn your eating habits.</p><p>During that time, users are encouraged to manually edit any inaccuracies to help train the AI-powered detection algorithm.  Afterwards, the Odyss N1 should be able to log everything you munch on and sip with a solid degree of accuracy. Of course, the one downside of the Odyss N1 is you pretty much need to wear it all the time to make the most of it. </p><p>No word on a shipping date. </p><h3 class="article-body__section" id="section-5-ikarios"><span>5. iKarios</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="f8Xewm5XDRRZ5YXM7gSL8H" name="iKairos-03" alt="The iKairos wearable AI pendant at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/f8Xewm5XDRRZ5YXM7gSL8H-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>Last but not least, we have the <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-viral-ikarios-ai-pendant-and-im-still-not-completely-sure-what-its-for">iKairos</a>, a peculiar circular-shaped pendant with an animated set of cartoonish eyes. But what purpose does this admittedly cute little wearable, which doubles as a tabletop companion when placed in its charging dock, serve? </p><p>The folks behind iKairos say that it's designed to be a "second memory," with an onboard microphone for recording notes, reminders, events, and more. It also has a built-in camera that's deployed by sliding the back half of the iKairos downward. </p><p>When active, the camera is meant to capture your most important memories; however, the output isn't a lovely photo slideshow or video reel. Instead, the iKairos translates your precious moments into weird, AI-generated images. </p><p>Still just a concept, there's a good chance that the iKairos will ultimately evolve into something more than a goofy-faced eavesdropper. And similar to the Odyss N1, we don't have any indication of when or even if the iKairos will be available to the public. </p><p>Of these five new tech wearables, which one are you most excited about? Let me know in the poll below. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-X75bdW"></div>                            </div>                            <script src="https://kwizly.com/embed/X75bdW.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-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/fitness-trackers/i-just-reviewed-the-garmin-cirqa-5-things-you-need-to-know-about-garmins-subscription-free-whoop-and-fitbit-air-alternative"><strong>I just reviewed the Garmin Cirqa — 5 things you need to know about Garmin’s subscription-free Whoop and Fitbit Air alternative</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/exclusive-garmin-cirqa-pm-says-it-just-felt-like-we-had-all-of-the-pieces-in-place-to-launch-a-screen-free-fitness-tracker"><strong>Exclusive: Garmin Cirqa PM says ‘it just felt like we had all of the pieces in place’ to launch a screen-free fitness tracker</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness-trackers/the-5-coolest-pieces-of-wearable-tech-i-demoed-at-ifa-2026-in-berlin</link>
                                                                            <description>
                            <![CDATA[ From smarter smart rings to AI pendants that serve as a 'second memory,' here are the coolest gadgets I got my hands on during IFA 2026 in Berlin. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">52oBzWQ9bdgM8wZ539RbAE</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/kmdbCu6najejUjwohqY9zh-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 09:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Smartwatches]]></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/kmdbCu6najejUjwohqY9zh-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Circular Ring 3 Pro, Odyss N1, and iKairos at IFA 2026 in Berlin]]></media:description>                                                            <media:text><![CDATA[Close-up of the Circular Ring 3 Pro, Odyss N1, and iKairos at IFA 2026 in Berlin]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Circular Ring 3 Pro, Odyss N1, and iKairos at IFA 2026 in Berlin]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/kmdbCu6najejUjwohqY9zh-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I attended my first <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA trade show</a> in Berlin last week, and between countless helpings of currywurst, I found myself genuinely floored by all the cool new wearable tech on display. </p><p>From smarter smart rings with onboard NFC for mobile payments to AI-powered pendants that serve as a "second memory," IFA proved to be a treasure trove for gadget lovers like myself. With that in mind, these are the five most incredible pieces of wearable tech I demoed at IFA 2026.</p><h3 class="article-body__section" id="section-1-luna-band"><span>1. Luna Band</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="EtCmRxAJth6TNRprGsdRHo" name="Luna-Band-01" alt="Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/EtCmRxAJth6TNRprGsdRHo-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>I first saw an early version of the Luna Band at <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-luna-band-fitness-tracker-and-it-beats-the-whoop-5-0-in-3-big-ways">CES 2026</a> in January, long before the arrival of the <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-garmin-cirqa-and-it-strikes-a-near-perfect-balance-between-the-fitbit-air-and-whoop-5-0">Garmin Cirqa</a> and <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">Fitbit Air</a>, two of the most capable (mostly) subscription-free alternatives to the popular screenless <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a> fitness tracker.</p><p>Boasting similar features and specs to the competition, the new <a href="https://www.tomsguide.com/wellness/fitness-trackers/forget-whoop-3-major-differences-between-the-subscription-free-luna-band-and-garmin-cirqa">Luna Band</a> splits the difference, price-wise, between the Cirqa ($199) and Air ($99), with a cost of $149. </p><p>However, one notable advantage the Luna Band has over the competition is a completely subscription-free approach to wellness. While Google (Fitbit) and Garmin make you pony up extra cash for deeper insights and AI-generated personalized recommendations, Luna does not. </p><p>In fact, custom-tailored AI-generated workout and health recommendations are a major selling point of the Luna Band. And rather than being overly focused on a cascade of metrics and charts, the companion Luna app is more geared toward digestible, actionable text-based advice based on your holistic trends and personal goals. </p><p>Stay tuned for a full review of the Luna Band, along with head-to-head comparisons versus the competition.</p><h3 class="article-body__section" id="section-2-circular-ring-3"><span>2. Circular Ring 3</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.29%;"><img id="nTJzQuQRUCp2UEiFXmdct7" name="CircularRing3-06" alt="Close-up of the Circular Ring 3 Pro and Slim at the IFA show in Berlin, Germany" src="https://cdn.mos.cms.futurecdn.net/nTJzQuQRUCp2UEiFXmdct7-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1441" 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 launch of the <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">Circular Ring 3</a> was easily the biggest surprise of IFA, at least when it comes to wearable tech. The Circular Ring 2 was a mighty fine alternative to the latest <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>, aka the <a href="https://www.tomsguide.com/wellness/fitness-trackers/best-smart-rings">best smart ring</a> on the market, but when I reviewed it, a buggy app held back the overall user experience.</p><p>Since then, Circular completely overhauled and relaunched the companion app, and more notably, debuted not one but two new smart rings: the Circular Ring 3 Pro and Circular Ring 3 Slim.</p><p>Unlike Oura, these smart rings are subscription-free. They also support some unique features, most notably onboard NFC, giving you the power to pay for things with the touch of a finger. They also support haptic feedback for alerts and alarms. </p><p>The Ring Pro 3 additionally supports a promising new blood pressure trends feature that I look forward to testing when the wearable ships this winter.</p><h3 class="article-body__section" id="section-3-moto-watch-ultra"><span>3. Moto Watch Ultra</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="TuahqyBcrowTeXY8k4uTxa" name="Moto Watch Ultra-2" alt="Close-up of the new Moto Watch Ultra LTE smartwatch at IFA 2026 in Berin" src="https://cdn.mos.cms.futurecdn.net/TuahqyBcrowTeXY8k4uTxa-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: Anthony Spadafora/Tom's Guide)</span></figcaption></figure><p>The <a href="https://www.tomsguide.com/wellness/smartwatches/i-just-went-hands-on-with-motorolas-first-lte-smartwatch-and-google-and-samsung-should-be-worried">Moto Watch Ultra</a> was another pleasant IFA surprise announcement. Motorola's first-ever LTE-capable smartwatch, the Moto Watch Ultra is a direct competitor to the likes of the <a href="https://www.tomsguide.com/wellness/smartwatches/i-wore-the-samsung-galaxy-watch-9-for-a-month-the-new-health-tools-impress-but-that-doesnt-mean-you-should-upgrade">Samsung Galaxy Watch 9</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review">Google Pixel Watch 5</a>, two of the <a href="https://www.tomsguide.com/best-picks/best-smartwatches-android">best smartwatches for Android</a> in 2026.</p><p>The thing is, the Moto Watch Ultra is priced lower than both of the above, while offering similar features. It runs Google's bug-free and user-friendly Wear OS, and for health and fitness tracking, Motorola partnered with the trusted Finnish smartwatch brand Polar.</p><p>A lovely-looking brushed stainless steel case additionally gives the Moto Watch Ultra a more premium look than the competition. Available starting on September 10, the Moto Watch Ultra starts at $349 via Motorola and Amazon. </p><h3 class="article-body__section" id="section-4-odyss-n1"><span>4. Odyss N1 </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="bNn9ciK87xCezTzjhQforZ" name="Odyss-06" alt="Close-up of the Odyss N1 AI-powered necklace that tracks what you eat" src="https://cdn.mos.cms.futurecdn.net/bNn9ciK87xCezTzjhQforZ-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>No, it's not a shark tooth necklace; the <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-odyss-n1-a-sleek-ai-necklace-that-automatically-logs-everything-you-eat#section-odyss-n1-ai-necklace-outlook">Odyss N1</a> is a small, metal pendant sporting an onboard camera and motion sensor designed to automatically log everything you eat. Still just a concept, the Odyss N1 was unknown to me prior to IFA, but when I spotted the brand's booth in the depths of the Berlin Messe, I was instantly drawn in.</p><p>In 2026, the <a href="https://www.tomsguide.com/us/best-fitness-trackers,review-2066.html">best fitness trackers</a> and smartwatches may be able to automatically log sleep, workouts, and stress, but they drop the ball when it comes to recording food intake without user input. This is where the Odyss N1 comes in. Designed to work alongside other fitness wearables, the N1 takes a few weeks to calibrate and learn your eating habits.</p><p>During that time, users are encouraged to manually edit any inaccuracies to help train the AI-powered detection algorithm.  Afterwards, the Odyss N1 should be able to log everything you munch on and sip with a solid degree of accuracy. Of course, the one downside of the Odyss N1 is you pretty much need to wear it all the time to make the most of it. </p><p>No word on a shipping date. </p><h3 class="article-body__section" id="section-5-ikarios"><span>5. iKarios</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="f8Xewm5XDRRZ5YXM7gSL8H" name="iKairos-03" alt="The iKairos wearable AI pendant at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/f8Xewm5XDRRZ5YXM7gSL8H-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>Last but not least, we have the <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-viral-ikarios-ai-pendant-and-im-still-not-completely-sure-what-its-for">iKairos</a>, a peculiar circular-shaped pendant with an animated set of cartoonish eyes. But what purpose does this admittedly cute little wearable, which doubles as a tabletop companion when placed in its charging dock, serve? </p><p>The folks behind iKairos say that it's designed to be a "second memory," with an onboard microphone for recording notes, reminders, events, and more. It also has a built-in camera that's deployed by sliding the back half of the iKairos downward. </p><p>When active, the camera is meant to capture your most important memories; however, the output isn't a lovely photo slideshow or video reel. Instead, the iKairos translates your precious moments into weird, AI-generated images. </p><p>Still just a concept, there's a good chance that the iKairos will ultimately evolve into something more than a goofy-faced eavesdropper. And similar to the Odyss N1, we don't have any indication of when or even if the iKairos will be available to the public. </p><p>Of these five new tech wearables, which one are you most excited about? Let me know in the poll below. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-X75bdW"></div>                            </div>                            <script src="https://kwizly.com/embed/X75bdW.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-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/fitness-trackers/i-just-reviewed-the-garmin-cirqa-5-things-you-need-to-know-about-garmins-subscription-free-whoop-and-fitbit-air-alternative"><strong>I just reviewed the Garmin Cirqa — 5 things you need to know about Garmin’s subscription-free Whoop and Fitbit Air alternative</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/exclusive-garmin-cirqa-pm-says-it-just-felt-like-we-had-all-of-the-pieces-in-place-to-launch-a-screen-free-fitness-tracker"><strong>Exclusive: Garmin Cirqa PM says ‘it just felt like we had all of the pieces in place’ to launch a screen-free fitness tracker</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I just went hands-on with the viral iKarios AI pendant — and I'm still not completely sure what it's for ]]></title>
                                                                                                <dc:content><![CDATA[ <p>One of the strangest pieces of wearable tech I demoed at the <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA 2026</a> show is the iKairos. Pitched as a “second memory” that captures the most important moments of your life, this AI-powered device doubles as a wearable pendant and a stationary desktop companion. </p><p>All that said, I still don’t fully understand the purpose of the iKairos, and frankly, the folks showing it at IFA didn't seem to really know either. To be fair, the iKairos is still very much a concept. Here's what I do know.</p><h2 id="a-happy-little-wearable">A happy, little wearable</h2><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="9pEtcgkoUPkEr6qE8y5sFH" name="iKairos-04" alt="The iKairos wearable AI pendant at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/9pEtcgkoUPkEr6qE8y5sFH-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>I was admittedly drawn to the iKairos because of the cute, animated face that beams from a circular display on the front. But what purpose does this sort-of interactive digital face serve? </p><p>Personal note-taking is one of the main advertised features of the iKairos; users can whisper all their deepest, darkest secrets to the happy little guy for safekeeping and transcription.</p><p>I suppose, to make these interactions a little less impersonal-feeling, the folks at iKairos gave the wearable a goofy cartoon face capable of blinking and making a handful of vague expressions.</p><h2 id="a-built-in-camera-captures-your-life-sort-of">A built-in camera captures your life… sort of</h2><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="bEwrvTWhgbx6CoGJpMn56H" name="iKairos-01" alt="The iKairos wearable AI pendant at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/bEwrvTWhgbx6CoGJpMn56H-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 iKairos also sports an onboard camera that can be deployed by sliding the bottom of the device downward. Don’t like the idea of a camera logging and interpreting your every moment? Slide that sucker back up. </p><p>The weird thing about the onboard camera is that the “meaningful memories” it captures aren’t traditional stills or video but weird, AI-generated interpretations of your daily routines and adventures. This, I am not a fan of. </p><h2 id="a-desktop-companion-too">A desktop companion, too</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="hfYZKs5ektUcTFWKzRDmCH" name="iKairos-02" alt="The iKairos wearable AI pendant at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/hfYZKs5ektUcTFWKzRDmCH-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>When you’re not wearing the iKairos around your neck, it’s meant to live on a small docking station that sits on your desk or bedside. </p><p>Regardless of its position, users can converse with the device and use it for more than just note-taking. Other functions include the ability to set reminders, add events to a calendar, and review summaries of past events. </p><h2 id="the-design-isn-39-t-final">The design isn't final</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2286px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="sxhCCMMMmNVuxSmWzXVonA" name="iKairos-05" alt="The iKairos wearable AI pendant at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/sxhCCMMMmNVuxSmWzXVonA-1920-80.jpg" mos="" align="middle" fullscreen="" width="2286" height="1286" 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>It’s worth noting that the iKairos is still a long way off from being an actual product you can purchase online. That said, the company behind it recently secured a hefty amount of investor funding, so hopefully, we’ll eventually see some form of the iKairos come to fruition; it just may look a whole lot different than the product I just demoed.</p><p>What are your thoughts on the iKairos? Is this a product you’d seriously consider buying? What existing features do you like or dislike, and what do you feel is missing? Let me know below. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-odyss-n1-a-sleek-ai-necklace-that-automatically-logs-everything-you-eat">I just went hands-on with the Odyss N1 — a sleek AI necklace that automatically tracks everything you eat</a></li><li><a href="https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-new-circular-ring-3-and-it-beats-the-oura-ring-5-in-3-big-ways">I just went hands-on with the new Circular Ring 3 — and it beats the Oura Ring 5 in 3 big ways</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/i-just-went-hands-on-with-motorolas-first-lte-smartwatch-and-google-and-samsung-should-be-worried">I just went hands-on with Motorola's first LTE smartwatch — and Google and Samsung should be worried</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-viral-ikarios-ai-pendant-and-im-still-not-completely-sure-what-its-for</link>
                                                                            <description>
                            <![CDATA[ The iKairos is meant to be an always-with-you "second memory" device. What does that mean? I'll try my best to explain. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">R9kt6VUmzGWW88R9dr4zE4</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/f8Xewm5XDRRZ5YXM7gSL8H-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 08 Sep 2026 20:44:55 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Smartwatches]]></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/f8Xewm5XDRRZ5YXM7gSL8H-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[The iKairos wearable AI pendant at IFA 2026 in Berlin]]></media:description>                                                            <media:text><![CDATA[The iKairos wearable AI pendant at IFA 2026 in Berlin]]></media:text>
                                <media:title type="plain"><![CDATA[The iKairos wearable AI pendant at IFA 2026 in Berlin]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/f8Xewm5XDRRZ5YXM7gSL8H-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>One of the strangest pieces of wearable tech I demoed at the <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA 2026</a> show is the iKairos. Pitched as a “second memory” that captures the most important moments of your life, this AI-powered device doubles as a wearable pendant and a stationary desktop companion. </p><p>All that said, I still don’t fully understand the purpose of the iKairos, and frankly, the folks showing it at IFA didn't seem to really know either. To be fair, the iKairos is still very much a concept. Here's what I do know.</p><h2 id="a-happy-little-wearable">A happy, little wearable</h2><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="9pEtcgkoUPkEr6qE8y5sFH" name="iKairos-04" alt="The iKairos wearable AI pendant at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/9pEtcgkoUPkEr6qE8y5sFH-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>I was admittedly drawn to the iKairos because of the cute, animated face that beams from a circular display on the front. But what purpose does this sort-of interactive digital face serve? </p><p>Personal note-taking is one of the main advertised features of the iKairos; users can whisper all their deepest, darkest secrets to the happy little guy for safekeeping and transcription.</p><p>I suppose, to make these interactions a little less impersonal-feeling, the folks at iKairos gave the wearable a goofy cartoon face capable of blinking and making a handful of vague expressions.</p><h2 id="a-built-in-camera-captures-your-life-sort-of">A built-in camera captures your life… sort of</h2><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="bEwrvTWhgbx6CoGJpMn56H" name="iKairos-01" alt="The iKairos wearable AI pendant at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/bEwrvTWhgbx6CoGJpMn56H-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 iKairos also sports an onboard camera that can be deployed by sliding the bottom of the device downward. Don’t like the idea of a camera logging and interpreting your every moment? Slide that sucker back up. </p><p>The weird thing about the onboard camera is that the “meaningful memories” it captures aren’t traditional stills or video but weird, AI-generated interpretations of your daily routines and adventures. This, I am not a fan of. </p><h2 id="a-desktop-companion-too">A desktop companion, too</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="hfYZKs5ektUcTFWKzRDmCH" name="iKairos-02" alt="The iKairos wearable AI pendant at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/hfYZKs5ektUcTFWKzRDmCH-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>When you’re not wearing the iKairos around your neck, it’s meant to live on a small docking station that sits on your desk or bedside. </p><p>Regardless of its position, users can converse with the device and use it for more than just note-taking. Other functions include the ability to set reminders, add events to a calendar, and review summaries of past events. </p><h2 id="the-design-isn-39-t-final">The design isn't final</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2286px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="sxhCCMMMmNVuxSmWzXVonA" name="iKairos-05" alt="The iKairos wearable AI pendant at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/sxhCCMMMmNVuxSmWzXVonA-1920-80.jpg" mos="" align="middle" fullscreen="" width="2286" height="1286" 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>It’s worth noting that the iKairos is still a long way off from being an actual product you can purchase online. That said, the company behind it recently secured a hefty amount of investor funding, so hopefully, we’ll eventually see some form of the iKairos come to fruition; it just may look a whole lot different than the product I just demoed.</p><p>What are your thoughts on the iKairos? Is this a product you’d seriously consider buying? What existing features do you like or dislike, and what do you feel is missing? Let me know below. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-odyss-n1-a-sleek-ai-necklace-that-automatically-logs-everything-you-eat">I just went hands-on with the Odyss N1 — a sleek AI necklace that automatically tracks everything you eat</a></li><li><a href="https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-new-circular-ring-3-and-it-beats-the-oura-ring-5-in-3-big-ways">I just went hands-on with the new Circular Ring 3 — and it beats the Oura Ring 5 in 3 big ways</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/i-just-went-hands-on-with-motorolas-first-lte-smartwatch-and-google-and-samsung-should-be-worried">I just went hands-on with Motorola's first LTE smartwatch — and Google and Samsung should be worried</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch Ultra 4 needs these 3 features to compete with the likes of the Garmin Fenix 9 ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Since its launch in September 2022, the Apple Watch Ultra has been positioned as Apple’s most durable adventure watch. The addition of the Action Button was a game changer for runners and cyclists looking to pause their activity without navigating a touch screen with sweaty fingers, and it is, without a doubt, the <a href="https://www.tomsguide.com/best-picks/best-apple-watch">best Apple Watch</a> for fitness fanatics. </p><p>That said, with the smartwatch market getting smarter than ever, Apple needs to make some big upgrades to compete with the likes of the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor">Garmin Fenix 9,</a> which launched last month. I’ll be on the ground in Cupertino bringing you the news from <a href="https://www.tomsguide.com/phones/live/apple-surprise-and-shine-live-iphone-ultra-iphone-18-pro-max-apple-watch-series-12-and-all-the-latest-news">Apple's “Surprise and Shine” event</a> as it happens, but here’s what I’m hoping Apple will bring to the rumored <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-these-are-the-upgrades-apple-needs-to-make-to-remain-the-smartwatch-king">Apple Watch Ultra 4</a> this week. </p><h3 class="article-body__section" id="section-continuous-heart-rate-monitoring"><span>Continuous heart rate monitoring </span></h3><p>According to <a href="https://www.macrumors.com/" target="_blank" rel="nofollow">MacRumors</a>, Apple has been testing a continuous heart rate sensor that would allow the Apple Watch to track your health and recovery 24/7 via your heart rate, similar to the way the <a href="https://www.tomsguide.com/wellness/smart-rings/ive-worn-the-oura-ring-5-for-six-weeks-here-are-3-things-i-love-and-2-things-i-wish-i-could-change">Oura Ring 5</a> or <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a> works. It's also been predicted from discovered code that Apple will launch a new Readiness app with watchOS 27. </p><p>The code suggests this new Readiness app will be separate from the current Vitals app and will give users deeper recovery and training load metrics.</p><p>This is a welcome change, and something that has always been missing from the Apple Watch experience. Until now, Apple hasn't been able to tell you how well your body has recovered from that half marathon you ran yesterday, or how ready you are for a workout based on your sleep and recovery data. </p><p><em>If </em>we do see continuous heart rate monitoring on the Apple Watch Ultra 4, this could allow wearers to see at a glance how ready they are with a daily score, similar to Garmin’s Training Readiness or <a href="https://www.tomsguide.com/news/how-to-use-the-garmin-body-battery-function">Body Battery </a>scores. </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:3332px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="JrqsNFHZVqLYKBKh7GNvaa" name="IMG_6248" alt="a photo of the Apple Watch Ultra 3" src="https://cdn.mos.cms.futurecdn.net/JrqsNFHZVqLYKBKh7GNvaa-1920-80.jpg" mos="" align="middle" fullscreen="" width="3332" height="1874" 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-a-massive-battery-life-boost"><span>A massive battery-life boost </span></h3><p>The 47mm Garmin Fenix 9 has up to 16 days of battery life in smartwatch mode, and up to 30 hours in workout mode. The Apple Watch Ultra 3, on the other hand, has 36 hours of battery life,  extended to 72 hours in low power mode. </p><p>In order to compete with other high-spec sports watches, this needs to improve, especially if Apple does add continuous heart rate monitoring, which typically reduces battery life. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3086px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bRghiFkByGRUquDJ57AHc9" name="AWU3-v-series11-05" alt="Close-up of the Apple Watch Ultra 3 in silver" src="https://cdn.mos.cms.futurecdn.net/bRghiFkByGRUquDJ57AHc9-1920-80.jpg" mos="" align="middle" fullscreen="" width="3086" height="1736" 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><h3 class="article-body__section" id="section-touch-free-interface"><span>Touch-free interface </span></h3><div><blockquote><p>I’ve never met a touchscreen that hasn’t made me want to scream when I’m trying to use it with sweaty fingers</p></blockquote></div><p>Like my wish for a smaller version of the Apple Watch Ultra, this is another dream that almost definitely won’t come true with the Apple Watch Ultra 4, but as a marathon runner, I long for more physical buttons on my Apple Watch. </p><p>I’ve never met a touchscreen that hasn’t made me want to scream when I’m trying to use it with sweaty fingers, or when wearing gloves. An easy workaround for this is physical buttons, and if the Apple Watch Ultra 4 had a button-driven navigation option for workout modes, it would be a game-changer. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OoNbJW"></div>                            </div>                            <script src="https://kwizly.com/embed/OoNbJW.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-wear-an-apple-watch-every-single-day-and-i-never-knew-you-could-do-this">‘I wear an Apple Watch every single day, and I never knew you could do this.’</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/i-wear-an-apple-watch-every-day-and-this-is-the-free-app-i-use-all-of-the-time">I wear an Apple Watch every day, and this is the free app I use all of the time</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/too-busy-to-work-out-i-added-thousands-of-steps-to-my-day-using-this-simple-trick">Forget running — I added thousands of steps to my day using this simple trick</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-needs-these-3-features-to-compete-with-the-likes-of-the-garmin-fenix-9</link>
                                                                            <description>
                            <![CDATA[ We might be getting a new Apple Watch Ultra this week, but here's what it needs to keep up with the Garmin Fenix 9 ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">ArMHxRjeb4W2Lr9wmrwN3E</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/BQuzNQdagdAVD5LbFUpjYo-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 08 Sep 2026 09:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></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/BQuzNQdagdAVD5LbFUpjYo-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Ultra 3 and Garmin Fenix 9 Pro]]></media:description>                                                            <media:text><![CDATA[Apple Watch Ultra 3 and Garmin Fenix 9 Pro]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Ultra 3 and Garmin Fenix 9 Pro]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/BQuzNQdagdAVD5LbFUpjYo-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Since its launch in September 2022, the Apple Watch Ultra has been positioned as Apple’s most durable adventure watch. The addition of the Action Button was a game changer for runners and cyclists looking to pause their activity without navigating a touch screen with sweaty fingers, and it is, without a doubt, the <a href="https://www.tomsguide.com/best-picks/best-apple-watch">best Apple Watch</a> for fitness fanatics. </p><p>That said, with the smartwatch market getting smarter than ever, Apple needs to make some big upgrades to compete with the likes of the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor">Garmin Fenix 9,</a> which launched last month. I’ll be on the ground in Cupertino bringing you the news from <a href="https://www.tomsguide.com/phones/live/apple-surprise-and-shine-live-iphone-ultra-iphone-18-pro-max-apple-watch-series-12-and-all-the-latest-news">Apple's “Surprise and Shine” event</a> as it happens, but here’s what I’m hoping Apple will bring to the rumored <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-these-are-the-upgrades-apple-needs-to-make-to-remain-the-smartwatch-king">Apple Watch Ultra 4</a> this week. </p><h3 class="article-body__section" id="section-continuous-heart-rate-monitoring"><span>Continuous heart rate monitoring </span></h3><p>According to <a href="https://www.macrumors.com/" target="_blank" rel="nofollow">MacRumors</a>, Apple has been testing a continuous heart rate sensor that would allow the Apple Watch to track your health and recovery 24/7 via your heart rate, similar to the way the <a href="https://www.tomsguide.com/wellness/smart-rings/ive-worn-the-oura-ring-5-for-six-weeks-here-are-3-things-i-love-and-2-things-i-wish-i-could-change">Oura Ring 5</a> or <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a> works. It's also been predicted from discovered code that Apple will launch a new Readiness app with watchOS 27. </p><p>The code suggests this new Readiness app will be separate from the current Vitals app and will give users deeper recovery and training load metrics.</p><p>This is a welcome change, and something that has always been missing from the Apple Watch experience. Until now, Apple hasn't been able to tell you how well your body has recovered from that half marathon you ran yesterday, or how ready you are for a workout based on your sleep and recovery data. </p><p><em>If </em>we do see continuous heart rate monitoring on the Apple Watch Ultra 4, this could allow wearers to see at a glance how ready they are with a daily score, similar to Garmin’s Training Readiness or <a href="https://www.tomsguide.com/news/how-to-use-the-garmin-body-battery-function">Body Battery </a>scores. </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:3332px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="JrqsNFHZVqLYKBKh7GNvaa" name="IMG_6248" alt="a photo of the Apple Watch Ultra 3" src="https://cdn.mos.cms.futurecdn.net/JrqsNFHZVqLYKBKh7GNvaa-1920-80.jpg" mos="" align="middle" fullscreen="" width="3332" height="1874" 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-a-massive-battery-life-boost"><span>A massive battery-life boost </span></h3><p>The 47mm Garmin Fenix 9 has up to 16 days of battery life in smartwatch mode, and up to 30 hours in workout mode. The Apple Watch Ultra 3, on the other hand, has 36 hours of battery life,  extended to 72 hours in low power mode. </p><p>In order to compete with other high-spec sports watches, this needs to improve, especially if Apple does add continuous heart rate monitoring, which typically reduces battery life. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3086px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bRghiFkByGRUquDJ57AHc9" name="AWU3-v-series11-05" alt="Close-up of the Apple Watch Ultra 3 in silver" src="https://cdn.mos.cms.futurecdn.net/bRghiFkByGRUquDJ57AHc9-1920-80.jpg" mos="" align="middle" fullscreen="" width="3086" height="1736" 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><h3 class="article-body__section" id="section-touch-free-interface"><span>Touch-free interface </span></h3><div><blockquote><p>I’ve never met a touchscreen that hasn’t made me want to scream when I’m trying to use it with sweaty fingers</p></blockquote></div><p>Like my wish for a smaller version of the Apple Watch Ultra, this is another dream that almost definitely won’t come true with the Apple Watch Ultra 4, but as a marathon runner, I long for more physical buttons on my Apple Watch. </p><p>I’ve never met a touchscreen that hasn’t made me want to scream when I’m trying to use it with sweaty fingers, or when wearing gloves. An easy workaround for this is physical buttons, and if the Apple Watch Ultra 4 had a button-driven navigation option for workout modes, it would be a game-changer. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OoNbJW"></div>                            </div>                            <script src="https://kwizly.com/embed/OoNbJW.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-wear-an-apple-watch-every-single-day-and-i-never-knew-you-could-do-this">‘I wear an Apple Watch every single day, and I never knew you could do this.’</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/i-wear-an-apple-watch-every-day-and-this-is-the-free-app-i-use-all-of-the-time">I wear an Apple Watch every day, and this is the free app I use all of the time</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/too-busy-to-work-out-i-added-thousands-of-steps-to-my-day-using-this-simple-trick">Forget running — I added thousands of steps to my day using this simple trick</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I tested the Suunto Run 2 for two weeks and it’s an accurate and attractive sports watch with maps ]]></title>
                                                                                                <dc:content><![CDATA[ <p>While the <a href="https://www.tomsguide.com/best-picks/best-running-watches">best running watches</a> are, on the whole, getting more and more expensive, the competition has never been fiercer at the affordable end of the market and the <a href="https://www.tomsguide.com/wellness/smartwatches/suunto-run-review-a-great-value-amoled-sports-watch-for-runners">Suunto Run</a> is one of the best value options on the market at $199 or less in sales.</p><p>The Suunto Run 2 builds on the platform set by its predecessor by improving the heart rate tracking and AMOLED display, and adding maps, but these upgrades do come at a cost, with the price rising sharply to $349.</p><p>I’ve been using the Suunto Run 2 for two weeks, tracking my daily runs along with other workouts, and it’s impressed me with its accuracy, battery life, and attractive design.</p><p>There are flaws here too, though — the software can be confusing and a few bugs have appeared during my testing, and Suunto’s smart features are well behind those of Garmin. </p><p>The Suunto Run 2 is a good option for new and seasoned runners and triathletes alike, but a big part of the appeal of the original Run was its value, and now there are cheaper options I’d opt for ahead of the Run 2.</p><h2 class="article-body__section" id="section-suunto-run-2-review-price-and-availability"><span>Suunto Run 2 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:2038px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="ZGhMYNLLCt63zvNMcQMoYE" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:143,l:205,cw:2038,ch:1146,q:80/ZGhMYNLLCt63zvNMcQMoYE.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 Suunto Run 2 launched on 8 September 2026 and comes in two models, one with 4GB of storage that costs $349/£265 and one with 64GB that costs $399/£299. That’s a big jump in price from the original Suunto Run, which cost $249/£199 at launch and is now $199/£199 or less on sale.</p><div class="product"><a data-dimension112="fa984ab4-aa93-11f1-babc-e7a0c1b4588c" data-action="Deal Block" data-label="Run" data-dimension48="Run" data-dimension25="$179" href="https://www.amazon.com/SUUNTO-Touchscreen-Dualband-Heart-Rate-Lightweight/dp/B0F1MWJLDF" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1277px;"><p class="vanilla-image-block" style="padding-top:117.46%;"><img id="mij3e5KuqwaKRjEMHd84KS" name="Suunto Run" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mij3e5KuqwaKRjEMHd84KS-1920-80.png" mos="" align="middle" fullscreen="" width="1277" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Suunto Run is a lightweight running watch that offers outstanding value, especially with its price dropping to just $179 in the sales right now.<a class="view-deal button" href="https://www.amazon.com/SUUNTO-Touchscreen-Dualband-Heart-Rate-Lightweight/dp/B0F1MWJLDF" target="_blank" rel="nofollow" data-dimension112="fa984ab4-aa93-11f1-babc-e7a0c1b4588c" data-action="Deal Block" data-label="Run" data-dimension48="Run" data-dimension25="$179">View Deal</a></p></div><p>It sits below the<a href="https://www.tomsguide.com/wellness/smartwatches/suunto-race-2-review"> Suunto Race 2</a> ($499/£429) in the brand’s current line-up, with older models like the <a href="https://www.tomsguide.com/wellness/smartwatches/suunto-race-s-review-a-good-amoled-sports-watch-at-a-great-price">Suunto Race S</a> being another option to consider in sales, since it’s cheaper than the Suunto Run 2 when discounted.</p><p>The Suunto Run 2 is undercut by the impressive <a href="https://www.tomsguide.com/wellness/smartwatches/coros-pace-4-review">Coros Pace 4</a> (from $249/£229), which recently added maps, and the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-forerunner-170-review-an-affordable-and-accurate-running-watch">Garmin Forerunner 170</a> (from $299/£259), which doesn’t offer maps but has better smart features.</p><h3 class="article-body__section" id="section-suunto-run-2-review-specs-compared"><span>Suunto Run 2 review: specs compared</span></h3><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Suunto Run</strong></p></td><td  ><p><strong>Garmin Forerunner 170</strong></p></td><td  ><p><strong>Coros Pace 4</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p>$349/£265 (4GB);<br>$399/£299 (64GB)</p></td><td  ><p>$299.99/£259.99; $349.99/£299.99 (Music)</p></td><td  ><p>$249.99/£229.99; $279.99/£249.99 (Music)</p></td></tr><tr><td class="firstcol " ><p><strong>Size</strong></p></td><td  ><p>46 x 11.7mm</p></td><td  ><p>42.6 x 11.9mm</p></td><td  ><p>43.4 x 11.8mm</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>1.32in AMOLED</p></td><td  ><p>1.2in 390 x 390 AMOLED</p></td><td  ><p>1.2in 390 x 390 AMOLED</p></td></tr><tr><td class="firstcol " ><p><strong>Bezel</strong></p></td><td  ><p>Steel</p></td><td  ><p>Plastic</p></td><td  ><p>Plastic or aluminium</p></td></tr><tr><td class="firstcol " ><p><strong>Screen</strong></p></td><td  ><p>Glass</p></td><td  ><p>Glass</p></td><td  ><p>Glass</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>35g (watch only)</p></td><td  ><p>41g (with strap)</p></td><td  ><p>40-41g (with strap)</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance</strong></p></td><td  ><p>5ATM</p></td><td  ><p>5ATM</p></td><td  ><p>5ATM</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life (watch mode)</strong></p></td><td  ><p>Up to 10 days</p></td><td  ><p>Up to 10 days</p></td><td  ><p>Up to 19 days</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life (GPS)</strong></p></td><td  ><p>24 hours (multi-band GPS, always-on)</p></td><td  ><p>20 hours (all-systems GPS, always-on)</p></td><td  ><p>24 hours (multi-band GPS, always-on)</p></td></tr><tr><td class="firstcol " ><p><strong>Storage</strong></p></td><td  ><p>4GB or 64GB</p></td><td  ><p>4GB</p></td><td  ><p>4GB</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-suunto-run-2-review-design-and-display"><span>Suunto Run 2 review: design and display</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:2275px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="ZBqxfScoU7WWoXxYdgRbEE" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:90,l:139,cw:2275,ch:1280,q:80/ZBqxfScoU7WWoXxYdgRbEE.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 Suunto Run 2 is a small, lightweight watch with a 1.32in, 2,000-nit AMOLED display. It’s a great-looking little watch and has a premium, sturdy feel for an entry-level watch. It comes in Aloe Green, All Black, and Feather Gold colors.</p><p>For me, the design is a key strength of the watch compared to competitors from other brands. The Coros Pace 4 and Garmin Forerunner 170 are good-looking watches and have proved robust in my testing, but feel more plasticky than the Suunto Run 2.</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:2312px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="3PCye4QuPQMa2ZmKRD46YE" name="Suunto Run 2" alt="Suunto Run 2 and Suunto Run" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:0,l:66,cw:2312,ch:1301,q:80/3PCye4QuPQMa2ZmKRD46YE.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 screen is much brighter than on the original Run and easy to read in all conditions, though I did experience a bug during testing where the always-on screen sometimes didn’t work outside of training, even when I had that setting turned on.</p><p>It has three buttons, one of which is a digital dial, and the touchscreen is responsive and didn’t exhibit any lag during my time with the watch, something that has been a concern with past Suunto models.</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:2025px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="sNconK3gEtkrA5gWLhwJiD" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:242,l:287,cw:2025,ch:1139,q:80/sNconK3gEtkrA5gWLhwJiD.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 Suunto Run 2 has a new optical heart rate sensor on the back and offers multi-band GPS tracking. It also has an altimeter, barometer and compass, as well as a blood oxygen sensor. You can also pair external sensors and headphones via Bluetooth.</p><p>You can choose between 4GB and 64GB of storage on the watch, with the bigger option being ideal for those who want to store a lot of music on the Suunto Run 2 and download a world’s worth of maps — if you just need your local area and don’t use music, 4GB will suffice.</p><h2 class="article-body__section" id="section-suunto-run-2-review-sports-tracking-and-training-analysis"><span>Suunto Run 2 review: sports tracking and training analysis</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:2349px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="bDAUuwu7mfq2wSeQWBihUD" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:29,l:156,cw:2349,ch:1321,q:80/bDAUuwu7mfq2wSeQWBihUD.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 Suunto Run 2 is packed with sports modes, including a dedicated triathlon mode, along with open water swimming and track run options. Most sports are available, and there are also catch-all indoor and outdoor workout options you can use if not.</p><p>You can customize these sports modes to show the data you want (unlike on some Suunto watches where you have to create new modes), but there are some odd limits, like the overall duration of a workout having to be on all data pages.</p><p>Your workouts feed into a comprehensive set of training analysis tools powered by Training Peaks. This training analysis is a little impenetrable to the untrained eye, with lots of acronyms that could be better explained, in my opinion.</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:2099px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="2xeokD3rkR8ZbMgSomoHQD" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:127,l:279,cw:2099,ch:1181,q:80/2xeokD3rkR8ZbMgSomoHQD.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 VO2 max estimate and race predictions on the watch are also quite a long way off my actual times, more so than on other sports watches, but this is something that’s likely to become more accurate with extended use.</p><p>All the data is there, and even experienced athletes will find all they need, but Garmin in particular does a better job of making its analysis clearer and more useful, and has extra stats like Training Readiness.</p><h2 class="article-body__section" id="section-suunto-run-2-review-gps-and-heart-rate-accuracy"><span>Suunto Run 2 review: GPS and heart rate accuracy</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:1592px;"><p class="vanilla-image-block" style="padding-top:58.98%;"><img id="TVzVM29WSRhsW6mkFAB44F" name="Suunto Run 2" alt="Suunto Run 2 and Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/TVzVM29WSRhsW6mkFAB44F-1920-80.jpg" mos="" align="middle" fullscreen="" width="1592" height="939" 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>Suunto’s multi-band GPS has generally been very good across all the watches I’ve tested it on, and that has been the case with the Suunto Run 2. I’ve compared its distance and pace stats to other watches during my runs and looked at the GPS tracks afterwards and it’s been right in line with reliable devices like the Garmin Fenix 9 Pro and Coros Pace 4.</p><p>To check the watch’s heart rate accuracy, I compared it with the readings from a chest strap, which are generally more reliable than the optical sensors on watches.</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:2271px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="bVjzXNn7jTBnCWyFDThqbE" name="Suunto Run 2" alt="Suunto Run 2, Garmin Fenix 9 Pro and Coros Pace 4" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:106,l:193,cw:2271,ch:1278,q:80/bVjzXNn7jTBnCWyFDThqbE.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>Despite Suunto saying the Run 2 had a new and improved optical heart rate sensor, I didn’t have high hopes — this has been claimed with several Suunto watches I’ve tested that had below-par accuracy.</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:784px;"><p class="vanilla-image-block" style="padding-top:40.69%;"><img id="EEtJQmwMTP7hN7XMVsYZ99" name="Suunto Run 2 HR" alt="Suunto Run 2 HR graph" src="https://cdn.mos.cms.futurecdn.net/EEtJQmwMTP7hN7XMVsYZ99-1920-80.jpg" mos="" align="middle" fullscreen="" width="784" height="319" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: DC Rainmaker Analyzer)</span></figcaption></figure><p>However, the Suunto Run 2’s heart rate tracking has been impeccable in my testing, closely matching a chest strap’s readings during all my runs and other workouts, including interval sessions with sharp rises and drops in heart rate.</p><p>I might still defer to a chest strap for key workouts just for peace of mind, but the Suunto Run 2’s optical sensor impressed me greatly in testing.</p><h2 class="article-body__section" id="section-suunto-run-2-review-battery-life"><span>Suunto Run 2 review: battery life</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:2431px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="PKJ7MAEfT6hmLFyk4bjQ9E" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:0,l:45,cw:2431,ch:1367,q:80/PKJ7MAEfT6hmLFyk4bjQ9E.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 Suunto Run 2 is listed as lasting 10 days on a charge and offers up to 24 hours of multi-band GPS tracking, which are impressive numbers for a small watch with a bright AMOLED display.</p><p>During testing, I experienced a bug where I couldn’t charge the watch to 100%; it would cap out somewhere in the 90s no matter how long I charged it, but I still found that the watch lasted me five or six days on a charge with the screen always-on, running every day. Hopefully this will be fixed for the watch’s full launch if it’s a common fault.</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:1698px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="R5hHxAX4kfZUFXG2NHQqkD" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:207,l:430,cw:1698,ch:955,q:80/R5hHxAX4kfZUFXG2NHQqkD.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>Like most sports watches with a high waterproof rating, the Suunto Run 2 uses a proprietary charger. Other brands do at least use the same charger across their watches, whereas the Suunto Run 2’s charger is specific to the watch.</p><p>Compared to the Coros Pace 4 and Garmin Forerunner 70/170 watches, the Suunto Run 2 is the longest-lasting based on my testing, and even if you train outside every day, or multiple times a day, you’ll get the better part of a week of use.</p><h2 class="article-body__section" id="section-suunto-run-2-review-activity-and-sleep-tracking"><span>Suunto Run 2 review: activity and sleep tracking</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:1556px;"><p class="vanilla-image-block" style="padding-top:59.06%;"><img id="SvexYDJ37pY9dLmRSJ4ioE" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/SvexYDJ37pY9dLmRSJ4ioE-1920-80.jpg" mos="" align="middle" fullscreen="" width="1556" height="919" 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 all about step counts, the Suunto Run 2 is not the watch for you. Like other Suunto devices, it significantly underestimated my step counts throughout testing, especially during runs.</p><p>While step tracking might not be a key feature for many people who opt for a sports watch like this over a smartwatch or fitness tracker, it’s odd that this problem has been allowed to persist for so long with Suunto watches.</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:2038px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="y6uWn9i2j3LadepSPs6awD" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:143,l:291,cw:2038,ch:1146,q:80/y6uWn9i2j3LadepSPs6awD.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 also found the sleep tracking to be quite inaccurate, with my total time asleep being shortened on many nights where it suggested I fell asleep after midnight when I’d gone to sleep at around 10 pm.</p><h2 class="article-body__section" id="section-suunto-run-2-review-smart-features-and-maps"><span>Suunto Run 2 review: smart features and maps</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:1253px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="sxfgjZCTBDi2EGnUzuWVgE" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:105,l:70,cw:1253,ch:705,q:80/sxfgjZCTBDi2EGnUzuWVgE.jpg" mos="" align="middle" fullscreen="" width="1366" height="875" 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 Suunto Run 2 allows for a lot of customization of your watch face and widgets, and has some handy smarts like music controls for your phone, weather forecasts, and storage space for music.</p><p>It doesn’t link up with streaming services, though, so the offline music playback feature will only be useful for those with MP3 files to drag and drop onto the watch. There are also no NFC payments on the watch, a feature that you can get on Garmin watches and smartwatches.</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:2193px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="PjkvrtqH5VoBcd4G6hw9NE" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:25,l:205,cw:2193,ch:1234,q:80/PjkvrtqH5VoBcd4G6hw9NE.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 big new addition to the Suunto Run 2 is maps. These are free, and you can download the areas you want to the watch through the partner Suunto app, where you can also plan out routes to send to the watch to follow on your wrist with turn-by-turn directions.</p><p>It’s great to see maps on a more affordable watch like this, and with Coros also adding them to the Pace 4 via a software update, it hopefully means that the feature will become common on cheaper devices in general.</p><p>The maps on the Suunto Run 2 are bright and clear and load quickly when panning and zooming, and it’s easy to follow routes on the watch too.</p><h2 class="article-body__section" id="section-should-you-buy-the-suunto-run-2"><span>Should you buy the Suunto Run 2?</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:2198px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="cN4NbbukJ2fwnCdffvotwD" name="Suunto Run 2" alt="Coros Pace 4, Suunto Run 2 and Garmin Forerunner 170" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:66,l:188,cw:2198,ch:1236,q:80/cN4NbbukJ2fwnCdffvotwD.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 Suunto Run 2 has weaknesses, but its strengths are in the most important areas areas like design, battery life and accuracy, and I’d be happy to wear the watch as my daily driver for marathon training.</p><p>However, the big price jump in the U.S. does weaken its appeal. It’s better value in the U.K., where it’s competitive with the Coros Pace 4 and Garmin Forerunner 170, but the Coros in particular still offers more value. The Garmin has better smart features and training analysis, and a more polished experience all round, especially for new runners, but it lacks maps.</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:1409px;"><p class="vanilla-image-block" style="padding-top:58.41%;"><img id="NQzmLPMA3zkeHsUe92Qj2F" name="Suunto Run 2" alt="Suunto Run 2 and Suunto Race S" src="https://cdn.mos.cms.futurecdn.net/NQzmLPMA3zkeHsUe92Qj2F-1920-80.jpg" mos="" align="middle" fullscreen="" width="1409" height="823" 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 Suunto Run 2’s strengths compared to these rivals are in its attractive design and longer battery life. These strengths are also available on the older Suunto Race S, though, which is cheaper in sales than the new watch and has a similar feature set.</p><p>At its launch price, the Suunto Run 2 ends up in an awkward spot where I think there’s always a better option to buy instead, despite the fact it’s a good watch that impressed me in testing with its performance. </p><p>At $249 or $299, it’s a more interesting option, and I expect that price to come around in sales, but for now the Suunto Run 2 wouldn’t top my shopping list if you’re in the market for a new watch.</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/i-tested-the-suunto-run-2-for-two-weeks-and-its-an-accurate-and-attractive-sports-watch-with-maps</link>
                                                                            <description>
                            <![CDATA[ The Suunto Run 2 is an upgrade on its predecessor both in terms of features and accuracy, but the sharp jump in price is a shame. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">ZwTRJ96CbuKaTCZHxQrDfM</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/4bJbVvMmhfbbqC6fEjoP3F-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 08 Sep 2026 08:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Nick Harris-Fry ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/J5Jjp49GUVjLZEbjEkTex-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/4bJbVvMmhfbbqC6fEjoP3F-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Suunto Run 2]]></media:description>                                                            <media:text><![CDATA[Suunto Run 2]]></media:text>
                                <media:title type="plain"><![CDATA[Suunto Run 2]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/4bJbVvMmhfbbqC6fEjoP3F-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>While the <a href="https://www.tomsguide.com/best-picks/best-running-watches">best running watches</a> are, on the whole, getting more and more expensive, the competition has never been fiercer at the affordable end of the market and the <a href="https://www.tomsguide.com/wellness/smartwatches/suunto-run-review-a-great-value-amoled-sports-watch-for-runners">Suunto Run</a> is one of the best value options on the market at $199 or less in sales.</p><p>The Suunto Run 2 builds on the platform set by its predecessor by improving the heart rate tracking and AMOLED display, and adding maps, but these upgrades do come at a cost, with the price rising sharply to $349.</p><p>I’ve been using the Suunto Run 2 for two weeks, tracking my daily runs along with other workouts, and it’s impressed me with its accuracy, battery life, and attractive design.</p><p>There are flaws here too, though — the software can be confusing and a few bugs have appeared during my testing, and Suunto’s smart features are well behind those of Garmin. </p><p>The Suunto Run 2 is a good option for new and seasoned runners and triathletes alike, but a big part of the appeal of the original Run was its value, and now there are cheaper options I’d opt for ahead of the Run 2.</p><h2 class="article-body__section" id="section-suunto-run-2-review-price-and-availability"><span>Suunto Run 2 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:2038px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="ZGhMYNLLCt63zvNMcQMoYE" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:143,l:205,cw:2038,ch:1146,q:80/ZGhMYNLLCt63zvNMcQMoYE.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 Suunto Run 2 launched on 8 September 2026 and comes in two models, one with 4GB of storage that costs $349/£265 and one with 64GB that costs $399/£299. That’s a big jump in price from the original Suunto Run, which cost $249/£199 at launch and is now $199/£199 or less on sale.</p><div class="product"><a data-dimension112="fa984ab4-aa93-11f1-babc-e7a0c1b4588c" data-action="Deal Block" data-label="Run" data-dimension48="Run" data-dimension25="$179" href="https://www.amazon.com/SUUNTO-Touchscreen-Dualband-Heart-Rate-Lightweight/dp/B0F1MWJLDF" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1277px;"><p class="vanilla-image-block" style="padding-top:117.46%;"><img id="mij3e5KuqwaKRjEMHd84KS" name="Suunto Run" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mij3e5KuqwaKRjEMHd84KS-1920-80.png" mos="" align="middle" fullscreen="" width="1277" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Suunto Run is a lightweight running watch that offers outstanding value, especially with its price dropping to just $179 in the sales right now.<a class="view-deal button" href="https://www.amazon.com/SUUNTO-Touchscreen-Dualband-Heart-Rate-Lightweight/dp/B0F1MWJLDF" target="_blank" rel="nofollow" data-dimension112="fa984ab4-aa93-11f1-babc-e7a0c1b4588c" data-action="Deal Block" data-label="Run" data-dimension48="Run" data-dimension25="$179">View Deal</a></p></div><p>It sits below the<a href="https://www.tomsguide.com/wellness/smartwatches/suunto-race-2-review"> Suunto Race 2</a> ($499/£429) in the brand’s current line-up, with older models like the <a href="https://www.tomsguide.com/wellness/smartwatches/suunto-race-s-review-a-good-amoled-sports-watch-at-a-great-price">Suunto Race S</a> being another option to consider in sales, since it’s cheaper than the Suunto Run 2 when discounted.</p><p>The Suunto Run 2 is undercut by the impressive <a href="https://www.tomsguide.com/wellness/smartwatches/coros-pace-4-review">Coros Pace 4</a> (from $249/£229), which recently added maps, and the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-forerunner-170-review-an-affordable-and-accurate-running-watch">Garmin Forerunner 170</a> (from $299/£259), which doesn’t offer maps but has better smart features.</p><h3 class="article-body__section" id="section-suunto-run-2-review-specs-compared"><span>Suunto Run 2 review: specs compared</span></h3><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Suunto Run</strong></p></td><td  ><p><strong>Garmin Forerunner 170</strong></p></td><td  ><p><strong>Coros Pace 4</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p>$349/£265 (4GB);<br>$399/£299 (64GB)</p></td><td  ><p>$299.99/£259.99; $349.99/£299.99 (Music)</p></td><td  ><p>$249.99/£229.99; $279.99/£249.99 (Music)</p></td></tr><tr><td class="firstcol " ><p><strong>Size</strong></p></td><td  ><p>46 x 11.7mm</p></td><td  ><p>42.6 x 11.9mm</p></td><td  ><p>43.4 x 11.8mm</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>1.32in AMOLED</p></td><td  ><p>1.2in 390 x 390 AMOLED</p></td><td  ><p>1.2in 390 x 390 AMOLED</p></td></tr><tr><td class="firstcol " ><p><strong>Bezel</strong></p></td><td  ><p>Steel</p></td><td  ><p>Plastic</p></td><td  ><p>Plastic or aluminium</p></td></tr><tr><td class="firstcol " ><p><strong>Screen</strong></p></td><td  ><p>Glass</p></td><td  ><p>Glass</p></td><td  ><p>Glass</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>35g (watch only)</p></td><td  ><p>41g (with strap)</p></td><td  ><p>40-41g (with strap)</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance</strong></p></td><td  ><p>5ATM</p></td><td  ><p>5ATM</p></td><td  ><p>5ATM</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life (watch mode)</strong></p></td><td  ><p>Up to 10 days</p></td><td  ><p>Up to 10 days</p></td><td  ><p>Up to 19 days</p></td></tr><tr><td class="firstcol " ><p><strong>Battery life (GPS)</strong></p></td><td  ><p>24 hours (multi-band GPS, always-on)</p></td><td  ><p>20 hours (all-systems GPS, always-on)</p></td><td  ><p>24 hours (multi-band GPS, always-on)</p></td></tr><tr><td class="firstcol " ><p><strong>Storage</strong></p></td><td  ><p>4GB or 64GB</p></td><td  ><p>4GB</p></td><td  ><p>4GB</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-suunto-run-2-review-design-and-display"><span>Suunto Run 2 review: design and display</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:2275px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="ZBqxfScoU7WWoXxYdgRbEE" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:90,l:139,cw:2275,ch:1280,q:80/ZBqxfScoU7WWoXxYdgRbEE.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 Suunto Run 2 is a small, lightweight watch with a 1.32in, 2,000-nit AMOLED display. It’s a great-looking little watch and has a premium, sturdy feel for an entry-level watch. It comes in Aloe Green, All Black, and Feather Gold colors.</p><p>For me, the design is a key strength of the watch compared to competitors from other brands. The Coros Pace 4 and Garmin Forerunner 170 are good-looking watches and have proved robust in my testing, but feel more plasticky than the Suunto Run 2.</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:2312px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="3PCye4QuPQMa2ZmKRD46YE" name="Suunto Run 2" alt="Suunto Run 2 and Suunto Run" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:0,l:66,cw:2312,ch:1301,q:80/3PCye4QuPQMa2ZmKRD46YE.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 screen is much brighter than on the original Run and easy to read in all conditions, though I did experience a bug during testing where the always-on screen sometimes didn’t work outside of training, even when I had that setting turned on.</p><p>It has three buttons, one of which is a digital dial, and the touchscreen is responsive and didn’t exhibit any lag during my time with the watch, something that has been a concern with past Suunto models.</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:2025px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="sNconK3gEtkrA5gWLhwJiD" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:242,l:287,cw:2025,ch:1139,q:80/sNconK3gEtkrA5gWLhwJiD.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 Suunto Run 2 has a new optical heart rate sensor on the back and offers multi-band GPS tracking. It also has an altimeter, barometer and compass, as well as a blood oxygen sensor. You can also pair external sensors and headphones via Bluetooth.</p><p>You can choose between 4GB and 64GB of storage on the watch, with the bigger option being ideal for those who want to store a lot of music on the Suunto Run 2 and download a world’s worth of maps — if you just need your local area and don’t use music, 4GB will suffice.</p><h2 class="article-body__section" id="section-suunto-run-2-review-sports-tracking-and-training-analysis"><span>Suunto Run 2 review: sports tracking and training analysis</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:2349px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="bDAUuwu7mfq2wSeQWBihUD" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:29,l:156,cw:2349,ch:1321,q:80/bDAUuwu7mfq2wSeQWBihUD.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 Suunto Run 2 is packed with sports modes, including a dedicated triathlon mode, along with open water swimming and track run options. Most sports are available, and there are also catch-all indoor and outdoor workout options you can use if not.</p><p>You can customize these sports modes to show the data you want (unlike on some Suunto watches where you have to create new modes), but there are some odd limits, like the overall duration of a workout having to be on all data pages.</p><p>Your workouts feed into a comprehensive set of training analysis tools powered by Training Peaks. This training analysis is a little impenetrable to the untrained eye, with lots of acronyms that could be better explained, in my opinion.</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:2099px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="2xeokD3rkR8ZbMgSomoHQD" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:127,l:279,cw:2099,ch:1181,q:80/2xeokD3rkR8ZbMgSomoHQD.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 VO2 max estimate and race predictions on the watch are also quite a long way off my actual times, more so than on other sports watches, but this is something that’s likely to become more accurate with extended use.</p><p>All the data is there, and even experienced athletes will find all they need, but Garmin in particular does a better job of making its analysis clearer and more useful, and has extra stats like Training Readiness.</p><h2 class="article-body__section" id="section-suunto-run-2-review-gps-and-heart-rate-accuracy"><span>Suunto Run 2 review: GPS and heart rate accuracy</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:1592px;"><p class="vanilla-image-block" style="padding-top:58.98%;"><img id="TVzVM29WSRhsW6mkFAB44F" name="Suunto Run 2" alt="Suunto Run 2 and Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/TVzVM29WSRhsW6mkFAB44F-1920-80.jpg" mos="" align="middle" fullscreen="" width="1592" height="939" 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>Suunto’s multi-band GPS has generally been very good across all the watches I’ve tested it on, and that has been the case with the Suunto Run 2. I’ve compared its distance and pace stats to other watches during my runs and looked at the GPS tracks afterwards and it’s been right in line with reliable devices like the Garmin Fenix 9 Pro and Coros Pace 4.</p><p>To check the watch’s heart rate accuracy, I compared it with the readings from a chest strap, which are generally more reliable than the optical sensors on watches.</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:2271px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="bVjzXNn7jTBnCWyFDThqbE" name="Suunto Run 2" alt="Suunto Run 2, Garmin Fenix 9 Pro and Coros Pace 4" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:106,l:193,cw:2271,ch:1278,q:80/bVjzXNn7jTBnCWyFDThqbE.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>Despite Suunto saying the Run 2 had a new and improved optical heart rate sensor, I didn’t have high hopes — this has been claimed with several Suunto watches I’ve tested that had below-par accuracy.</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:784px;"><p class="vanilla-image-block" style="padding-top:40.69%;"><img id="EEtJQmwMTP7hN7XMVsYZ99" name="Suunto Run 2 HR" alt="Suunto Run 2 HR graph" src="https://cdn.mos.cms.futurecdn.net/EEtJQmwMTP7hN7XMVsYZ99-1920-80.jpg" mos="" align="middle" fullscreen="" width="784" height="319" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: DC Rainmaker Analyzer)</span></figcaption></figure><p>However, the Suunto Run 2’s heart rate tracking has been impeccable in my testing, closely matching a chest strap’s readings during all my runs and other workouts, including interval sessions with sharp rises and drops in heart rate.</p><p>I might still defer to a chest strap for key workouts just for peace of mind, but the Suunto Run 2’s optical sensor impressed me greatly in testing.</p><h2 class="article-body__section" id="section-suunto-run-2-review-battery-life"><span>Suunto Run 2 review: battery life</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:2431px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="PKJ7MAEfT6hmLFyk4bjQ9E" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:0,l:45,cw:2431,ch:1367,q:80/PKJ7MAEfT6hmLFyk4bjQ9E.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 Suunto Run 2 is listed as lasting 10 days on a charge and offers up to 24 hours of multi-band GPS tracking, which are impressive numbers for a small watch with a bright AMOLED display.</p><p>During testing, I experienced a bug where I couldn’t charge the watch to 100%; it would cap out somewhere in the 90s no matter how long I charged it, but I still found that the watch lasted me five or six days on a charge with the screen always-on, running every day. Hopefully this will be fixed for the watch’s full launch if it’s a common fault.</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:1698px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="R5hHxAX4kfZUFXG2NHQqkD" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:207,l:430,cw:1698,ch:955,q:80/R5hHxAX4kfZUFXG2NHQqkD.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>Like most sports watches with a high waterproof rating, the Suunto Run 2 uses a proprietary charger. Other brands do at least use the same charger across their watches, whereas the Suunto Run 2’s charger is specific to the watch.</p><p>Compared to the Coros Pace 4 and Garmin Forerunner 70/170 watches, the Suunto Run 2 is the longest-lasting based on my testing, and even if you train outside every day, or multiple times a day, you’ll get the better part of a week of use.</p><h2 class="article-body__section" id="section-suunto-run-2-review-activity-and-sleep-tracking"><span>Suunto Run 2 review: activity and sleep tracking</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:1556px;"><p class="vanilla-image-block" style="padding-top:59.06%;"><img id="SvexYDJ37pY9dLmRSJ4ioE" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/SvexYDJ37pY9dLmRSJ4ioE-1920-80.jpg" mos="" align="middle" fullscreen="" width="1556" height="919" 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 all about step counts, the Suunto Run 2 is not the watch for you. Like other Suunto devices, it significantly underestimated my step counts throughout testing, especially during runs.</p><p>While step tracking might not be a key feature for many people who opt for a sports watch like this over a smartwatch or fitness tracker, it’s odd that this problem has been allowed to persist for so long with Suunto watches.</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:2038px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="y6uWn9i2j3LadepSPs6awD" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:143,l:291,cw:2038,ch:1146,q:80/y6uWn9i2j3LadepSPs6awD.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 also found the sleep tracking to be quite inaccurate, with my total time asleep being shortened on many nights where it suggested I fell asleep after midnight when I’d gone to sleep at around 10 pm.</p><h2 class="article-body__section" id="section-suunto-run-2-review-smart-features-and-maps"><span>Suunto Run 2 review: smart features and maps</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:1253px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="sxfgjZCTBDi2EGnUzuWVgE" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:105,l:70,cw:1253,ch:705,q:80/sxfgjZCTBDi2EGnUzuWVgE.jpg" mos="" align="middle" fullscreen="" width="1366" height="875" 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 Suunto Run 2 allows for a lot of customization of your watch face and widgets, and has some handy smarts like music controls for your phone, weather forecasts, and storage space for music.</p><p>It doesn’t link up with streaming services, though, so the offline music playback feature will only be useful for those with MP3 files to drag and drop onto the watch. There are also no NFC payments on the watch, a feature that you can get on Garmin watches and smartwatches.</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:2193px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="PjkvrtqH5VoBcd4G6hw9NE" name="Suunto Run 2" alt="Suunto Run 2" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:25,l:205,cw:2193,ch:1234,q:80/PjkvrtqH5VoBcd4G6hw9NE.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 big new addition to the Suunto Run 2 is maps. These are free, and you can download the areas you want to the watch through the partner Suunto app, where you can also plan out routes to send to the watch to follow on your wrist with turn-by-turn directions.</p><p>It’s great to see maps on a more affordable watch like this, and with Coros also adding them to the Pace 4 via a software update, it hopefully means that the feature will become common on cheaper devices in general.</p><p>The maps on the Suunto Run 2 are bright and clear and load quickly when panning and zooming, and it’s easy to follow routes on the watch too.</p><h2 class="article-body__section" id="section-should-you-buy-the-suunto-run-2"><span>Should you buy the Suunto Run 2?</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:2198px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="cN4NbbukJ2fwnCdffvotwD" name="Suunto Run 2" alt="Coros Pace 4, Suunto Run 2 and Garmin Forerunner 170" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:66,l:188,cw:2198,ch:1236,q:80/cN4NbbukJ2fwnCdffvotwD.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 Suunto Run 2 has weaknesses, but its strengths are in the most important areas areas like design, battery life and accuracy, and I’d be happy to wear the watch as my daily driver for marathon training.</p><p>However, the big price jump in the U.S. does weaken its appeal. It’s better value in the U.K., where it’s competitive with the Coros Pace 4 and Garmin Forerunner 170, but the Coros in particular still offers more value. The Garmin has better smart features and training analysis, and a more polished experience all round, especially for new runners, but it lacks maps.</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:1409px;"><p class="vanilla-image-block" style="padding-top:58.41%;"><img id="NQzmLPMA3zkeHsUe92Qj2F" name="Suunto Run 2" alt="Suunto Run 2 and Suunto Race S" src="https://cdn.mos.cms.futurecdn.net/NQzmLPMA3zkeHsUe92Qj2F-1920-80.jpg" mos="" align="middle" fullscreen="" width="1409" height="823" 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 Suunto Run 2’s strengths compared to these rivals are in its attractive design and longer battery life. These strengths are also available on the older Suunto Race S, though, which is cheaper in sales than the new watch and has a similar feature set.</p><p>At its launch price, the Suunto Run 2 ends up in an awkward spot where I think there’s always a better option to buy instead, despite the fact it’s a good watch that impressed me in testing with its performance. </p><p>At $249 or $299, it’s a more interesting option, and I expect that price to come around in sales, but for now the Suunto Run 2 wouldn’t top my shopping list if you’re in the market for a new watch.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’ve written about Apple Watch for a decade: Here’s the rumored upgrade to the Apple Watch 12 I’m most excited about ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Happy Apple week to all who celebrate. We’re just 48 hours away from Apple’s <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">“Surprise and Shine” event</a>, where the brand will release all its new products. I’ve been writing about Apple Watch for the past decade, and will be on the ground in Cupertino bringing you all the updates as they drop, but it’s safe to say we can expect a new <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-all-the-design-health-and-battery-life-rumors-so-far">Apple Watch 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-these-are-the-upgrades-apple-needs-to-make-to-remain-the-smartwatch-king">Apple Watch Ultra 4</a>. </p><p>Design-wise, it’s thought that Apple will keep things pretty similar to the Apple Watch 11 and Apple Watch Ultra 3, but one big change that could affect the health and fitness tracking on the watch is a new continuous heart rate sensor. </p><p>According to <a href="https://www.macrumors.com/" target="_blank">MacRumors</a>, Apple has been testing a continuous heart rate sensor that would allow the Apple Watch to track your health and recovery 24/7 via your heart rate, similar to the way the <a href="https://www.tomsguide.com/wellness/smart-rings/ive-worn-the-oura-ring-5-for-six-weeks-here-are-3-things-i-love-and-2-things-i-wish-i-could-change">Oura Ring 5 </a>or <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a> works. </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:3694px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="utjaKsfFTCYuECT64i4fz9" name="IMG_4742" alt="a photo of heart rate range on Apple Watch Ultra 3" src="https://cdn.mos.cms.futurecdn.net/utjaKsfFTCYuECT64i4fz9-1920-80.jpg" mos="" align="middle" fullscreen="" width="3694" height="2078" 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>On current models, the Apple Watch measures your heart rate every few minutes throughout the day, and to save battery life, it only moves to continuous tracking when you manually log a workout. By switching to continuous tracking all day, Apple will be able to give more accurate data, or even build a readiness or wellness score. </p><p>A wellness score has always been missing from the Apple Watch, and is one thing that sets other wearables, like Garmin and Fitbit, apart. Sure, all the data is in the Health app, but Apple Watch wearers still can’t see at a glance how well they’ve recovered from a particular workout, or their baseline readiness each morning. </p><p>What’s more, continuous Heart Rate Variability (HRV) readings are one of the easiest ways to spot you’re getting sick or run down. Apple’s “Vitals” app, introduced in watchOS 11, was a first step in this direction, but continuous tracking would give Apple higher quality data to match competitors like Oura. </p><p>Obviously, the Apple Watch-shaped elephant in the room here is how this continuous heart rate tracking might affect battery life. Apple Watch has notoriously fallen short when it comes to battery life, with the Apple Watch 11 giving 18 hours of battery life, compared to the Oura Ring or Whoop, which last 4- 7 days between charges. How Apple will manage this if they do add continuous heart rate tracking to the Apple Watch remains to be seen. The good news is, we don’t have long to wait to find out. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OoNbJW"></div>                            </div>                            <script src="https://kwizly.com/embed/OoNbJW.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-wear-an-apple-watch-every-single-day-and-i-never-knew-you-could-do-this">‘I wear an Apple Watch every single day, and I never knew you could do this.’</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/i-wear-an-apple-watch-every-day-and-this-is-the-free-app-i-use-all-of-the-time">I wear an Apple Watch every day, and this is the free app I use all of the time</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/too-busy-to-work-out-i-added-thousands-of-steps-to-my-day-using-this-simple-trick">Forget running — I added thousands of steps to my day using this simple trick</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/ive-written-about-apple-watch-for-a-decade-heres-the-rumored-upgrade-to-the-apple-watch-12-im-most-excited-about</link>
                                                                            <description>
                            <![CDATA[ Apple could be switching to continuous heart rate monitoring, taking on the likes of Oura and Whoop ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">hNQ3Thk4b5TQF24t8rbc4B</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/ExQoDTSvoG8aybCuKn67DM-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 08 Sep 2026 06:30:00 +0000</pubDate>                                                                                                                                <updated>Tue, 08 Sep 2026 08:17:58 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></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/ExQoDTSvoG8aybCuKn67DM-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[The Apple Watch Series 10 on display at the device&#039;s launch in September 2024]]></media:description>                                                            <media:text><![CDATA[The Apple Watch Series 10 on display at the device&#039;s launch in September 2024]]></media:text>
                                <media:title type="plain"><![CDATA[The Apple Watch Series 10 on display at the device&#039;s launch in September 2024]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/ExQoDTSvoG8aybCuKn67DM-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Happy Apple week to all who celebrate. We’re just 48 hours away from Apple’s <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">“Surprise and Shine” event</a>, where the brand will release all its new products. I’ve been writing about Apple Watch for the past decade, and will be on the ground in Cupertino bringing you all the updates as they drop, but it’s safe to say we can expect a new <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-all-the-design-health-and-battery-life-rumors-so-far">Apple Watch 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-these-are-the-upgrades-apple-needs-to-make-to-remain-the-smartwatch-king">Apple Watch Ultra 4</a>. </p><p>Design-wise, it’s thought that Apple will keep things pretty similar to the Apple Watch 11 and Apple Watch Ultra 3, but one big change that could affect the health and fitness tracking on the watch is a new continuous heart rate sensor. </p><p>According to <a href="https://www.macrumors.com/" target="_blank">MacRumors</a>, Apple has been testing a continuous heart rate sensor that would allow the Apple Watch to track your health and recovery 24/7 via your heart rate, similar to the way the <a href="https://www.tomsguide.com/wellness/smart-rings/ive-worn-the-oura-ring-5-for-six-weeks-here-are-3-things-i-love-and-2-things-i-wish-i-could-change">Oura Ring 5 </a>or <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a> works. </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:3694px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="utjaKsfFTCYuECT64i4fz9" name="IMG_4742" alt="a photo of heart rate range on Apple Watch Ultra 3" src="https://cdn.mos.cms.futurecdn.net/utjaKsfFTCYuECT64i4fz9-1920-80.jpg" mos="" align="middle" fullscreen="" width="3694" height="2078" 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>On current models, the Apple Watch measures your heart rate every few minutes throughout the day, and to save battery life, it only moves to continuous tracking when you manually log a workout. By switching to continuous tracking all day, Apple will be able to give more accurate data, or even build a readiness or wellness score. </p><p>A wellness score has always been missing from the Apple Watch, and is one thing that sets other wearables, like Garmin and Fitbit, apart. Sure, all the data is in the Health app, but Apple Watch wearers still can’t see at a glance how well they’ve recovered from a particular workout, or their baseline readiness each morning. </p><p>What’s more, continuous Heart Rate Variability (HRV) readings are one of the easiest ways to spot you’re getting sick or run down. Apple’s “Vitals” app, introduced in watchOS 11, was a first step in this direction, but continuous tracking would give Apple higher quality data to match competitors like Oura. </p><p>Obviously, the Apple Watch-shaped elephant in the room here is how this continuous heart rate tracking might affect battery life. Apple Watch has notoriously fallen short when it comes to battery life, with the Apple Watch 11 giving 18 hours of battery life, compared to the Oura Ring or Whoop, which last 4- 7 days between charges. How Apple will manage this if they do add continuous heart rate tracking to the Apple Watch remains to be seen. The good news is, we don’t have long to wait to find out. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OoNbJW"></div>                            </div>                            <script src="https://kwizly.com/embed/OoNbJW.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-wear-an-apple-watch-every-single-day-and-i-never-knew-you-could-do-this">‘I wear an Apple Watch every single day, and I never knew you could do this.’</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/i-wear-an-apple-watch-every-day-and-this-is-the-free-app-i-use-all-of-the-time">I wear an Apple Watch every day, and this is the free app I use all of the time</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/too-busy-to-work-out-i-added-thousands-of-steps-to-my-day-using-this-simple-trick">Forget running — I added thousands of steps to my day using this simple trick</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I just went hands-on with the Odyss N1 — a sleek AI necklace that automatically tracks everything you eat ]]></title>
                                                                                                <dc:content><![CDATA[ <p>We've got fitness trackers, smartwatches, and smart rings that can precisely log our sleep, workouts, stress, and more with minimal user legwork, but one holistic tracking pain point that persists is food logging. </p><p>Sure, lots of companion apps, including Garmin Connect and the Oura app, let you manually log your calorie and nutritional intake, but what if there was an easier way? </p><p>The Odyss N1 AI necklace is aiming to be the missing link. Still a concept, I had the chance to demo the Odyss N1 at <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA 2026</a> in Berlin, and even though I'm slightly skeptical of its capabilities, I'm seriously intrigued by what it potentially offers. </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="adp7NC6isGrgiKKNNbM8mZ" name="Odyss-02" alt="Close-up of the Odyss N1 AI-powered necklace that tracks what you eat" src="https://cdn.mos.cms.futurecdn.net/adp7NC6isGrgiKKNNbM8mZ-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><h3 class="article-body__section" id="section-odyss-n1-ai-necklace-design"><span>Odyss N1 AI necklace: design</span></h3><p>The Odyss N1 consists of a small, triangular metal pendant with a built-in camera and accelerometer used to track what you eat, when you eat, and how much you eat.</p><p>The necklace itself is actually a cable that connects the pendant to a battery module that sits at the back of your neck. This power module also boasts haptic feedback for notifications. </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="bNn9ciK87xCezTzjhQforZ" name="Odyss-06" alt="Close-up of the Odyss N1 AI-powered necklace that tracks what you eat" src="https://cdn.mos.cms.futurecdn.net/bNn9ciK87xCezTzjhQforZ-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 pendant is constructed of metal and available in three colors: black, silver, and gold. It's also remarkably high-quality and jewelry-like.</p><p>A single physical button adorns the top of the pendant. Pressing it turns off all the food logging features. Another privacy feature: the Odyss N1 doesn't save any raw imaging data, ever. </p><h3 class="article-body__section" id="section-odyss-n1-ai-necklace-how-it-works"><span>Odyss N1 AI necklace: how it works</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="VB82hXzQ6XdSmfRdEMHXaZ" name="Odyss-04" alt="Close-up of the Odyss N1 AI-powered necklace that tracks what you eat" src="https://cdn.mos.cms.futurecdn.net/VB82hXzQ6XdSmfRdEMHXaZ-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 Odyss N1 feeds visual and motion data into an AI-powered algorithm, which also takes into account prior contextual data to try to accurately predict what exactly you're eating, including details on how it was cooked. Users can, of course, edit the details logged at any time. Better yet, the Odyss N1 learns from your edits.</p><p>The more you wear the Odyss N1 and/or update the logged info, the smarter it gets. I'm told that users will need to wear it for at least two weeks to fully calibrate the device for accuracy, but after that, it should be good to go.</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="QLvr7cszW5TMueLFy8FrWZ" name="Odyss-01" alt="Close-up of the Odyss N1 AI-powered necklace that tracks what you eat" src="https://cdn.mos.cms.futurecdn.net/QLvr7cszW5TMueLFy8FrWZ-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>What happens to all that logged food data? The companion app uses it to track your overall nutritional trends and even make recommendations to help you improve your diet.</p><p>In addition to nutrition, the app generates diet analysis reports focused on three key metrics: quality, energy, and rhythm. </p><p>While the Odyss N1 is still just a concept, the plan is to make its food logging data accessible to other popular holistic tracking apps. Likewise, the Odyss app is designed to import and analyze health data from other wearable tech and factor it into your nutritional recommendations and insights.</p><h3 class="article-body__section" id="section-odyss-n1-ai-necklace-outlook"><span>Odyss N1 AI necklace: Outlook </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="ngLXg7SjXH7ooPVdgWmhvZ" name="Odyss-03" alt="Close-up of the Odyss N1 AI-powered necklace that tracks what you eat" src="https://cdn.mos.cms.futurecdn.net/ngLXg7SjXH7ooPVdgWmhvZ-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 Odyss N1 is more than a cool idea. It's a potentially groundbreaking piece of wearable tech that truly attempts to solve a problem. Assuming it plays nicely with other popular health apps, isn't too pricey, and actually works as intended, I could definitely see the Odyss N1 catching on.</p><p>On the other hand,  one downside of the design is that you pretty much need to wear it all the time for the food tracking feature to work effectively. Moreover, battery life appears to be limited to a day or two at best, requiring users to frequently take it off for a recharge.</p><p>What are your thoughts on the Odyss N1 AI smart necklace? Is it something you'd consider wearing? Also, how much do you think it should sell for? Let me know in the comments below. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/forget-whoop-3-major-differences-between-the-subscription-free-luna-band-and-garmin-cirqa">Forget Whoop — 3 major differences between the subscription-free Luna Band and Garmin Cirqa</a></li><li><a href="https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-new-circular-ring-3-and-it-beats-the-oura-ring-5-in-3-big-ways">I just went hands-on with the new Circular Ring 3 — and it beats the Oura Ring 5 in 3 big ways</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/garmin-launches-nutrition-tracking-but-youll-have-to-subscribe-to-connect-to-get-it">Garmin launches nutrition tracking — but you’ll have to subscribe to Connect+ to get it</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-odyss-n1-a-sleek-ai-necklace-that-automatically-logs-everything-you-eat</link>
                                                                            <description>
                            <![CDATA[ The Odyss N1 is a sleek AI necklace aimed at revolutionizing how you log meals by taking all of the legwork out of the task. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">k7YTbW3baH6jvNjJ2DQPJN</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/MkDAozpLwhETPYrqvqRseZ-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 05 Sep 2026 16:07:23 +0000</pubDate>                                                                                                                                <updated>Sat, 05 Sep 2026 16:09:22 +0000</updated>
                                                                                                                                            <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Smartwatches]]></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/MkDAozpLwhETPYrqvqRseZ-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Odyss N1 AI-powered necklace that tracks what you eat]]></media:description>                                                            <media:text><![CDATA[Close-up of the Odyss N1 AI-powered necklace that tracks what you eat]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Odyss N1 AI-powered necklace that tracks what you eat]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/MkDAozpLwhETPYrqvqRseZ-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>We've got fitness trackers, smartwatches, and smart rings that can precisely log our sleep, workouts, stress, and more with minimal user legwork, but one holistic tracking pain point that persists is food logging. </p><p>Sure, lots of companion apps, including Garmin Connect and the Oura app, let you manually log your calorie and nutritional intake, but what if there was an easier way? </p><p>The Odyss N1 AI necklace is aiming to be the missing link. Still a concept, I had the chance to demo the Odyss N1 at <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA 2026</a> in Berlin, and even though I'm slightly skeptical of its capabilities, I'm seriously intrigued by what it potentially offers. </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="adp7NC6isGrgiKKNNbM8mZ" name="Odyss-02" alt="Close-up of the Odyss N1 AI-powered necklace that tracks what you eat" src="https://cdn.mos.cms.futurecdn.net/adp7NC6isGrgiKKNNbM8mZ-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><h3 class="article-body__section" id="section-odyss-n1-ai-necklace-design"><span>Odyss N1 AI necklace: design</span></h3><p>The Odyss N1 consists of a small, triangular metal pendant with a built-in camera and accelerometer used to track what you eat, when you eat, and how much you eat.</p><p>The necklace itself is actually a cable that connects the pendant to a battery module that sits at the back of your neck. This power module also boasts haptic feedback for notifications. </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="bNn9ciK87xCezTzjhQforZ" name="Odyss-06" alt="Close-up of the Odyss N1 AI-powered necklace that tracks what you eat" src="https://cdn.mos.cms.futurecdn.net/bNn9ciK87xCezTzjhQforZ-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 pendant is constructed of metal and available in three colors: black, silver, and gold. It's also remarkably high-quality and jewelry-like.</p><p>A single physical button adorns the top of the pendant. Pressing it turns off all the food logging features. Another privacy feature: the Odyss N1 doesn't save any raw imaging data, ever. </p><h3 class="article-body__section" id="section-odyss-n1-ai-necklace-how-it-works"><span>Odyss N1 AI necklace: how it works</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="VB82hXzQ6XdSmfRdEMHXaZ" name="Odyss-04" alt="Close-up of the Odyss N1 AI-powered necklace that tracks what you eat" src="https://cdn.mos.cms.futurecdn.net/VB82hXzQ6XdSmfRdEMHXaZ-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 Odyss N1 feeds visual and motion data into an AI-powered algorithm, which also takes into account prior contextual data to try to accurately predict what exactly you're eating, including details on how it was cooked. Users can, of course, edit the details logged at any time. Better yet, the Odyss N1 learns from your edits.</p><p>The more you wear the Odyss N1 and/or update the logged info, the smarter it gets. I'm told that users will need to wear it for at least two weeks to fully calibrate the device for accuracy, but after that, it should be good to go.</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="QLvr7cszW5TMueLFy8FrWZ" name="Odyss-01" alt="Close-up of the Odyss N1 AI-powered necklace that tracks what you eat" src="https://cdn.mos.cms.futurecdn.net/QLvr7cszW5TMueLFy8FrWZ-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>What happens to all that logged food data? The companion app uses it to track your overall nutritional trends and even make recommendations to help you improve your diet.</p><p>In addition to nutrition, the app generates diet analysis reports focused on three key metrics: quality, energy, and rhythm. </p><p>While the Odyss N1 is still just a concept, the plan is to make its food logging data accessible to other popular holistic tracking apps. Likewise, the Odyss app is designed to import and analyze health data from other wearable tech and factor it into your nutritional recommendations and insights.</p><h3 class="article-body__section" id="section-odyss-n1-ai-necklace-outlook"><span>Odyss N1 AI necklace: Outlook </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="ngLXg7SjXH7ooPVdgWmhvZ" name="Odyss-03" alt="Close-up of the Odyss N1 AI-powered necklace that tracks what you eat" src="https://cdn.mos.cms.futurecdn.net/ngLXg7SjXH7ooPVdgWmhvZ-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 Odyss N1 is more than a cool idea. It's a potentially groundbreaking piece of wearable tech that truly attempts to solve a problem. Assuming it plays nicely with other popular health apps, isn't too pricey, and actually works as intended, I could definitely see the Odyss N1 catching on.</p><p>On the other hand,  one downside of the design is that you pretty much need to wear it all the time for the food tracking feature to work effectively. Moreover, battery life appears to be limited to a day or two at best, requiring users to frequently take it off for a recharge.</p><p>What are your thoughts on the Odyss N1 AI smart necklace? Is it something you'd consider wearing? Also, how much do you think it should sell for? Let me know in the comments below. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/forget-whoop-3-major-differences-between-the-subscription-free-luna-band-and-garmin-cirqa">Forget Whoop — 3 major differences between the subscription-free Luna Band and Garmin Cirqa</a></li><li><a href="https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-new-circular-ring-3-and-it-beats-the-oura-ring-5-in-3-big-ways">I just went hands-on with the new Circular Ring 3 — and it beats the Oura Ring 5 in 3 big ways</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/garmin-launches-nutrition-tracking-but-youll-have-to-subscribe-to-connect-to-get-it">Garmin launches nutrition tracking — but you’ll have to subscribe to Connect+ to get it</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I just went hands-on with Motorola's first LTE smartwatch — and Google and Samsung should be worried ]]></title>
                                                                                                <dc:content><![CDATA[ <p>One of the biggest surprises out of <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA 2026 </a>in Berlin, from a wearable tech perspective, is the debut of Motorola’s first LTE smartwatch. The new Moto Watch Ultra boasts some darn impressive features and specs, like support for Gemini AI, detailed sleep insights, and a brushed stainless steel case, but can it really compete with the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> out there?</p><p>I got my first look at the new Motorola Moto Watch Ultra at IFA 2026 and was pleasantly surprised by all that it offers. So, should Google and Samsung be worried? Maybe! Here’s everything you need to know about the Moto Watch Ultra. </p><h3 class="article-body__section" id="section-moto-watch-ultra-price-and-availability"><span>Moto Watch Ultra: price and availability </span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="YBhMT6yBBXxyW3JTQe3GCb" name="Moto Watch Ultra-4" alt="Close-up of the new Moto Watch Ultra LTE smartwatch at IFA 2026 in Berin" src="https://cdn.mos.cms.futurecdn.net/YBhMT6yBBXxyW3JTQe3GCb-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: Anthony Spadafora/Tom's Guide)</span></figcaption></figure><p>The Moto Watch Ultra will initially debut in European markets for around 429 euros. According to Motorola, it should hit store shelves within the next few weeks. </p><p>In Uncle Sam's house, the Moto Watch Ultra will be available starting on September 10th for $349 via Motorola and Amazon. That makes it a better value than other flagship smartwatches, like the <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review">Google Pixel Watch 5</a> (from $399),  <a href="https://www.tomsguide.com/wellness/smartwatches/i-wore-the-samsung-galaxy-watch-9-for-a-month-the-new-health-tools-impress-but-that-doesnt-mean-you-should-upgrade">Samsung Galaxy Watch 9</a> (from $379), and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch Series 11</a> (from $399).</p><h3 class="article-body__section" id="section-moto-watch-ultra-design"><span>Moto Watch Ultra: design</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="TuahqyBcrowTeXY8k4uTxa" name="Moto Watch Ultra-2" alt="Close-up of the new Moto Watch Ultra LTE smartwatch at IFA 2026 in Berin" src="https://cdn.mos.cms.futurecdn.net/TuahqyBcrowTeXY8k4uTxa-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: Anthony Spadafora/Tom's Guide)</span></figcaption></figure><p>Despite its slightly more affordable price, the Moto Watch Ultra features a surprisingly premium design. The case is made entirely from brushed stainless steel and is paired with a 1.5-inch OLED touchscreen. Max screen brightness is 2,700 nits, a little behind the Pixel Watch 5 and Galaxy Watch 9 (3,000 nits) but ahead of the Apple Watch 11 (2,000 nits). </p><p>Two physical controls adorn one side of the case, including a standard button and a digital crown that doubles as a button. </p><p>The 46mm case is on the chunkier side and is noticeably thicker (12.1mm) than many of the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> I've tested. Weighing in at 51 g, it's also heavier than most full-featured flagships but lighter than rugged models like the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/galaxy-watch-ultra-2-hands-on-review">Galaxy Watch Ultra 2</a>. </p><h3 class="article-body__section" id="section-moto-watch-ultra-os-and-connectivity"><span>Moto Watch Ultra: OS and connectivity </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:1859px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="G94dvF85yNwk8fgSre4J8Z" name="MotoWatchUltra-08" alt="Close-up of the new Moto Watch Ultra" src="https://cdn.mos.cms.futurecdn.net/G94dvF85yNwk8fgSre4J8Z-1920-80.jpg" mos="" align="middle" fullscreen="" width="1859" height="1046" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Motorola )</span></figcaption></figure><p>The Moto Watch Ultra runs on Google’s excellent/refined Wear OS platform, which also means support for useful apps like Google Wallet and Google Translate, as well as Gemini AI features. The smartwatch ships running Wear OS 6, and Motorola promises support for up to two future OS updates.  </p><p>An LTE antenna unlocks on-the-go connectivity without a paired smartphone, though you’ll need a data plan to make use of it. The Moto Watch Ultra also boasts an onboard microphone and speaker for taking on-wrist calls. </p><h3 class="article-body__section" id="section-moto-watch-ultra-health-and-fitness-tracking"><span>Moto Watch Ultra: Health and fitness tracking </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="i9rKNNtdsd7f5nw6DTTqCb" name="Moto Watch Ultra-3" alt="Close-up of the new Moto Watch Ultra LTE smartwatch at IFA 2026 in Berin" src="https://cdn.mos.cms.futurecdn.net/i9rKNNtdsd7f5nw6DTTqCb-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: Anthony Spadafora/Tom's Guide)</span></figcaption></figure><p>For health and fitness tracking, Motorola has partnered with the Finnish smartwatch maker <a href="https://www.tomsguide.com/wellness/smartwatches/watch-out-garmin-this-new-polar-watch-has-a-built-in-flashlight-and-a-tiny-price-tag">Polar</a>. Like most modern smartwatches, the Moto Watch Ultra logs your sleep quality, including sleep stages, workouts, productivity, and energy levels. </p><p>Dual-band GPS ensures accurate tracking when logging outdoor activities, without the need to carry a paired smartphone. It also features a personalized running coach to help you train for events like marathons. </p><h3 class="article-body__section" id="section-moto-watch-ultra-battery-life"><span>Moto Watch Ultra: Battery life</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:2236px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="fZYwpEgc32pwvcEhUCevEA" name="MotoWatchUltra-05" alt="Close-up of the Moto Watch Ultra smartwatch" src="https://cdn.mos.cms.futurecdn.net/fZYwpEgc32pwvcEhUCevEA-1920-80.jpg" mos="" align="middle" fullscreen="" width="2236" height="1258" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Motorola )</span></figcaption></figure><p>Motorola is a bit vague about battery life, saying only that the Moto Watch Ultra should last up to two days when not using the always-on display mode. The brand also mentioned that a 15-minute charge should provide enough power for 24 hours of use. This seemingly suggests a full recharge takes only 30 minutes (but I will confirm).</p><p>48 hours of battery life without the always-on display puts the Moto Watch Ultra a little ahead of the Apple Watch 11, which lasts roughly 38 hours per charge sans always-on. The Pixel Watch 5, meanwhile, lasts for 72 hours or more without the always-on screen function.</p><h3 class="article-body__section" id="section-moto-watch-ultra-outlook"><span>Moto Watch Ultra: Outlook </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:2009px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="6j6YSt4EGLtmEzvHZwNGMA" name="MotoWatchUltra-06" alt="Close-up of the Moto Watch Ultra smartwatch" src="https://cdn.mos.cms.futurecdn.net/6j6YSt4EGLtmEzvHZwNGMA-1920-80.jpg" mos="" align="middle" fullscreen="" width="2009" height="1130" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Motorola )</span></figcaption></figure><p>I’m always excited to see a new full-featured smartwatch come to market that doesn’t have Apple, Pixel, or Galaxy in its name. </p><p>The Moto Watch Ultra is cheaper than its closest competitors, namely the Pixel Watch 5 and Galaxy Watch 9, while boasting an arguably more premium design.</p><p>Motorola was wise to again partner with Polar for all things fitness and holistic; the brand is a trusted player in the space. Similarly, Google’s Wear OS platform ensures a smooth, bug-free user experience. </p><p>Ultimately, if the Moto Watch Ultra proves as capable as the <a href="https://www.tomsguide.com/best-picks/best-smartwatches-android">best smartwatches for Android</a>, it could be the perfect antidote to a market currently dominated by Google and Samsung.</p><p>What are your thoughts on the new Moto Watch Ultra LTE smartwatch? Would you consider swapping out your Pixel Watch or Galaxy Watch for it? Are there any important features it’s missing? Let me know in the comments below. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/forget-whoop-3-major-differences-between-the-subscription-free-luna-band-and-garmin-cirqa">Forget Whoop — 3 major differences between the subscription-free Luna Band and Garmin Cirqa</a></li><li><a href="https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-new-circular-ring-3-and-it-beats-the-oura-ring-5-in-3-big-ways">I just went hands-on with the new Circular Ring 3 — and it beats the Oura Ring 5 in 3 big ways</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/i-hiked-7-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-9-and-the-winner-is-clear-as-day">I hiked 7 miles with the Garmin Instinct 3 vs Samsung Galaxy Watch 9 — and the winner is clear as day</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/i-just-went-hands-on-with-motorolas-first-lte-smartwatch-and-google-and-samsung-should-be-worried</link>
                                                                            <description>
                            <![CDATA[ The Moto Watch Ultra is Motorola’s first smartwatch with LTE. It also runs on Google’s Wear OS and even supports Gemini AI features. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">F7s8pDzALBoQp6LJpfoekS</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/9ymhi2rEvxfYgVxuunX2Lb-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 05 Sep 2026 14:38:28 +0000</pubDate>                                                                                                                                <updated>Sat, 05 Sep 2026 15:17:57 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/9ymhi2rEvxfYgVxuunX2Lb-1920-80.jpg">
                                                            <media:credit><![CDATA[Anthony Spadafora/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the new Moto Watch Ultra LTE smartwatch at IFA 2026 in Berin]]></media:description>                                                            <media:text><![CDATA[Close-up of the new Moto Watch Ultra LTE smartwatch at IFA 2026 in Berin]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the new Moto Watch Ultra LTE smartwatch at IFA 2026 in Berin]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/9ymhi2rEvxfYgVxuunX2Lb-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>One of the biggest surprises out of <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA 2026 </a>in Berlin, from a wearable tech perspective, is the debut of Motorola’s first LTE smartwatch. The new Moto Watch Ultra boasts some darn impressive features and specs, like support for Gemini AI, detailed sleep insights, and a brushed stainless steel case, but can it really compete with the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> out there?</p><p>I got my first look at the new Motorola Moto Watch Ultra at IFA 2026 and was pleasantly surprised by all that it offers. So, should Google and Samsung be worried? Maybe! Here’s everything you need to know about the Moto Watch Ultra. </p><h3 class="article-body__section" id="section-moto-watch-ultra-price-and-availability"><span>Moto Watch Ultra: price and availability </span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="YBhMT6yBBXxyW3JTQe3GCb" name="Moto Watch Ultra-4" alt="Close-up of the new Moto Watch Ultra LTE smartwatch at IFA 2026 in Berin" src="https://cdn.mos.cms.futurecdn.net/YBhMT6yBBXxyW3JTQe3GCb-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: Anthony Spadafora/Tom's Guide)</span></figcaption></figure><p>The Moto Watch Ultra will initially debut in European markets for around 429 euros. According to Motorola, it should hit store shelves within the next few weeks. </p><p>In Uncle Sam's house, the Moto Watch Ultra will be available starting on September 10th for $349 via Motorola and Amazon. That makes it a better value than other flagship smartwatches, like the <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review">Google Pixel Watch 5</a> (from $399),  <a href="https://www.tomsguide.com/wellness/smartwatches/i-wore-the-samsung-galaxy-watch-9-for-a-month-the-new-health-tools-impress-but-that-doesnt-mean-you-should-upgrade">Samsung Galaxy Watch 9</a> (from $379), and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch Series 11</a> (from $399).</p><h3 class="article-body__section" id="section-moto-watch-ultra-design"><span>Moto Watch Ultra: design</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="TuahqyBcrowTeXY8k4uTxa" name="Moto Watch Ultra-2" alt="Close-up of the new Moto Watch Ultra LTE smartwatch at IFA 2026 in Berin" src="https://cdn.mos.cms.futurecdn.net/TuahqyBcrowTeXY8k4uTxa-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: Anthony Spadafora/Tom's Guide)</span></figcaption></figure><p>Despite its slightly more affordable price, the Moto Watch Ultra features a surprisingly premium design. The case is made entirely from brushed stainless steel and is paired with a 1.5-inch OLED touchscreen. Max screen brightness is 2,700 nits, a little behind the Pixel Watch 5 and Galaxy Watch 9 (3,000 nits) but ahead of the Apple Watch 11 (2,000 nits). </p><p>Two physical controls adorn one side of the case, including a standard button and a digital crown that doubles as a button. </p><p>The 46mm case is on the chunkier side and is noticeably thicker (12.1mm) than many of the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> I've tested. Weighing in at 51 g, it's also heavier than most full-featured flagships but lighter than rugged models like the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/galaxy-watch-ultra-2-hands-on-review">Galaxy Watch Ultra 2</a>. </p><h3 class="article-body__section" id="section-moto-watch-ultra-os-and-connectivity"><span>Moto Watch Ultra: OS and connectivity </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:1859px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="G94dvF85yNwk8fgSre4J8Z" name="MotoWatchUltra-08" alt="Close-up of the new Moto Watch Ultra" src="https://cdn.mos.cms.futurecdn.net/G94dvF85yNwk8fgSre4J8Z-1920-80.jpg" mos="" align="middle" fullscreen="" width="1859" height="1046" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Motorola )</span></figcaption></figure><p>The Moto Watch Ultra runs on Google’s excellent/refined Wear OS platform, which also means support for useful apps like Google Wallet and Google Translate, as well as Gemini AI features. The smartwatch ships running Wear OS 6, and Motorola promises support for up to two future OS updates.  </p><p>An LTE antenna unlocks on-the-go connectivity without a paired smartphone, though you’ll need a data plan to make use of it. The Moto Watch Ultra also boasts an onboard microphone and speaker for taking on-wrist calls. </p><h3 class="article-body__section" id="section-moto-watch-ultra-health-and-fitness-tracking"><span>Moto Watch Ultra: Health and fitness tracking </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="i9rKNNtdsd7f5nw6DTTqCb" name="Moto Watch Ultra-3" alt="Close-up of the new Moto Watch Ultra LTE smartwatch at IFA 2026 in Berin" src="https://cdn.mos.cms.futurecdn.net/i9rKNNtdsd7f5nw6DTTqCb-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: Anthony Spadafora/Tom's Guide)</span></figcaption></figure><p>For health and fitness tracking, Motorola has partnered with the Finnish smartwatch maker <a href="https://www.tomsguide.com/wellness/smartwatches/watch-out-garmin-this-new-polar-watch-has-a-built-in-flashlight-and-a-tiny-price-tag">Polar</a>. Like most modern smartwatches, the Moto Watch Ultra logs your sleep quality, including sleep stages, workouts, productivity, and energy levels. </p><p>Dual-band GPS ensures accurate tracking when logging outdoor activities, without the need to carry a paired smartphone. It also features a personalized running coach to help you train for events like marathons. </p><h3 class="article-body__section" id="section-moto-watch-ultra-battery-life"><span>Moto Watch Ultra: Battery life</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:2236px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="fZYwpEgc32pwvcEhUCevEA" name="MotoWatchUltra-05" alt="Close-up of the Moto Watch Ultra smartwatch" src="https://cdn.mos.cms.futurecdn.net/fZYwpEgc32pwvcEhUCevEA-1920-80.jpg" mos="" align="middle" fullscreen="" width="2236" height="1258" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Motorola )</span></figcaption></figure><p>Motorola is a bit vague about battery life, saying only that the Moto Watch Ultra should last up to two days when not using the always-on display mode. The brand also mentioned that a 15-minute charge should provide enough power for 24 hours of use. This seemingly suggests a full recharge takes only 30 minutes (but I will confirm).</p><p>48 hours of battery life without the always-on display puts the Moto Watch Ultra a little ahead of the Apple Watch 11, which lasts roughly 38 hours per charge sans always-on. The Pixel Watch 5, meanwhile, lasts for 72 hours or more without the always-on screen function.</p><h3 class="article-body__section" id="section-moto-watch-ultra-outlook"><span>Moto Watch Ultra: Outlook </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:2009px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="6j6YSt4EGLtmEzvHZwNGMA" name="MotoWatchUltra-06" alt="Close-up of the Moto Watch Ultra smartwatch" src="https://cdn.mos.cms.futurecdn.net/6j6YSt4EGLtmEzvHZwNGMA-1920-80.jpg" mos="" align="middle" fullscreen="" width="2009" height="1130" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Motorola )</span></figcaption></figure><p>I’m always excited to see a new full-featured smartwatch come to market that doesn’t have Apple, Pixel, or Galaxy in its name. </p><p>The Moto Watch Ultra is cheaper than its closest competitors, namely the Pixel Watch 5 and Galaxy Watch 9, while boasting an arguably more premium design.</p><p>Motorola was wise to again partner with Polar for all things fitness and holistic; the brand is a trusted player in the space. Similarly, Google’s Wear OS platform ensures a smooth, bug-free user experience. </p><p>Ultimately, if the Moto Watch Ultra proves as capable as the <a href="https://www.tomsguide.com/best-picks/best-smartwatches-android">best smartwatches for Android</a>, it could be the perfect antidote to a market currently dominated by Google and Samsung.</p><p>What are your thoughts on the new Moto Watch Ultra LTE smartwatch? Would you consider swapping out your Pixel Watch or Galaxy Watch for it? Are there any important features it’s missing? Let me know in the comments below. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/forget-whoop-3-major-differences-between-the-subscription-free-luna-band-and-garmin-cirqa">Forget Whoop — 3 major differences between the subscription-free Luna Band and Garmin Cirqa</a></li><li><a href="https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-new-circular-ring-3-and-it-beats-the-oura-ring-5-in-3-big-ways">I just went hands-on with the new Circular Ring 3 — and it beats the Oura Ring 5 in 3 big ways</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/i-hiked-7-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-9-and-the-winner-is-clear-as-day">I hiked 7 miles with the Garmin Instinct 3 vs Samsung Galaxy Watch 9 — and the winner is clear as day</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch Ultra 4 needs to steal these two features from the Garmin Fenix 9 right away ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-rumors-everything-we-know-about-apples-next-ultra-rugged-smartwatch">Apple Watch Ultra 4</a> is set to be one of the new products launched at Apple’s upcoming <a href="https://www.tomsguide.com/phones/iphones/apple-sept-9-event-all-9-new-products-were-expecting-to-see">Surprise and Shine event</a> on 9 September, and it will follow hot on the heels of Garmin’s new flagship sports watches, the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor">Fenix 9 and Fenix 9 Pro</a>.</p><p>These were announced on 25 August, and I’ve been testing out the Garmin Fenix 9 Pro 51mm watch for the past week. I’ve tested every Fenix model since the Garmin Fenix 5 Plus, and I’ve also tested every Apple Watch Ultra launched to date, and both are consistently among the <a href="https://www.tomsguide.com/us/best-gps-watches,review-2638.html">best sports watches </a>available.</p><p>Apple has also made great strides in closing the sports tracking gap between its devices and the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches</a>, with accuracy, battery life and training analysis features all improving with each generation of the Ultra.</p><p>However, there are certainly still areas where the Garmin Fenix 9 Pro outperforms the Apple Watch Ultra, and even after just a week of using the new Fenix, there are two features I’d love to see on the Apple Watch Ultra 4.</p><h3 class="article-body__section" id="section-maps-within-activity-screens"><span>Maps within activity screens</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="eZHBCPefduMUnbd4Z2jNq5" name="Garmin Fenix 9 Pro maps" alt="Garmin Fenix 9 Pro maps" src="https://cdn.mos.cms.futurecdn.net/eZHBCPefduMUnbd4Z2jNq5-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 feel like this should be a pretty simple update to effect, and it’s something that’s standard across any sports watch with offline maps.</p><p>The Apple Watch Ultra 3 does offer maps and navigation tools, but you can’t have the map as one of your data screens in an activity, so if you want to check your route during a run, for example, you have to exit the Workout app to see it, then switch back to the Workout app afterward.</p><p>With the Garmin Fenix 9, you just scroll down to your map screen, which can even show activity stats overlaid on the top, so you can follow a route while also checking the activity duration or pace.</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:53.50%;"><img id="y7oD8GTuAku8kPEhozW2eU" name="WorkOutDoors App Apple Watch-5.jpg" alt="WorkOutDoors app on Apple Watch Ultra 2" src="https://cdn.mos.cms.futurecdn.net/y7oD8GTuAku8kPEhozW2eU-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1070" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>You can actually do this already with third-party sports tracking apps on the Apple Watch, like <a href="https://www.tomsguide.com/wellness/smartwatches/i-run-marathons-and-this-apple-watch-running-app-is-the-best-usd8-ive-ever-spent">WorkOutDoors</a>, so hopefully it’s something that shows up as a software update during Apple’s September event and then rolls back to older Apple Watch models.</p><h3 class="article-body__section" id="section-a-built-in-flashlight"><span>A built-in flashlight</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="HsEvn6zkCC3qyFB7uE4uB7" name="Garmin Fenix 9 Pro flashlight" alt="Garmin Fenix 9 Pro flashlight" src="https://cdn.mos.cms.futurecdn.net/HsEvn6zkCC3qyFB7uE4uB7-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>This is an ambitious hope, but most of Garmin’s top watches now feature a built-in flashlight, and it’s just so useful that I have to hope it’s something that eventually pops up on the Apple Watch Ultra.</p><p>When Garmin first launched a watch with a built-in flashlight, I didn’t think it was all that big a deal, but I constantly use the flashlight on my watch, either to navigate around the house at night, find children’s toys that have rolled under sofas, or as an extra light when running after sunset.</p><p>The Garmin Fenix 9 Pro has an upgraded flashlight compared to past watches, with a new green option alongside the red light and several levels of white. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="fGrGUfaLTVf2k5dJJNWLTo" name="Garmin Fenix 9 Pro flashlight" alt="Garmin Fenix 9 Pro flashlight" src="https://cdn.mos.cms.futurecdn.net/fGrGUfaLTVf2k5dJJNWLTo-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 don’t think the Apple Watch Ultra 4 has to go green, though it’s apparently useful for certain sports and for reading maps at night, but any kind of built-in flashlight would be a great addition to the watch.</p><p>At the moment, you can use the screen on the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3 </a>as a torch, but it’s not as bright as a built-in LED light, nor as easy to direct light, and you can’t use the flashlight at the same time as using the screen.</p><p>This major design change is the kind of thing that would probably have shown up in leaks if it were going to arrive on the Apple Watch Ultra 4, but I live in hope it makes an unexpected appearance, especially as it would fit perfectly with the "surprise and shine" theme of the September event.</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><ul><li><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></li></ul><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/smartwatches/from-fall-detection-to-hypertension-10-apple-watch-innovations-that-changed-the-game"><strong>10 Apple Watch innovations that changed the game — from Fall Detection to Hypertension Alerts</strong></a><strong></strong></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/im-a-smartwatch-reviewer-and-heres-my-apple-watch-series-12-wish-list-three-upgrades-i-want-and-one-i-dont"><strong>I'm a smartwatch reviewer, and here's my Apple Watch Series 12 wish list — three upgrades I want, and one I don't</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/3-apple-watch-settings-i-always-turn-off-to-maximize-battery-life"><strong>3 Apple Watch settings I always turn off to maximize battery life</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-needs-to-steal-these-2-features-from-the-garmin-fenix-9-right-away</link>
                                                                            <description>
                            <![CDATA[ The Apple Watch Ultra 4 is likely to launch at Apple’s September event, and I’d love to see it feature these two features common on top sports watches like the Garmin Fenix 9. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">QVui4tuGkoKTVuvRzvYUPX</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/BQuzNQdagdAVD5LbFUpjYo-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 05 Sep 2026 07:00:00 +0000</pubDate>                                                                                                                                <updated>Sat, 05 Sep 2026 12:27:40 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Nick Harris-Fry ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/J5Jjp49GUVjLZEbjEkTex-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/BQuzNQdagdAVD5LbFUpjYo-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Watch Ultra 3 and Garmin Fenix 9 Pro]]></media:description>                                                            <media:text><![CDATA[Apple Watch Ultra 3 and Garmin Fenix 9 Pro]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Watch Ultra 3 and Garmin Fenix 9 Pro]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/BQuzNQdagdAVD5LbFUpjYo-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-rumors-everything-we-know-about-apples-next-ultra-rugged-smartwatch">Apple Watch Ultra 4</a> is set to be one of the new products launched at Apple’s upcoming <a href="https://www.tomsguide.com/phones/iphones/apple-sept-9-event-all-9-new-products-were-expecting-to-see">Surprise and Shine event</a> on 9 September, and it will follow hot on the heels of Garmin’s new flagship sports watches, the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor">Fenix 9 and Fenix 9 Pro</a>.</p><p>These were announced on 25 August, and I’ve been testing out the Garmin Fenix 9 Pro 51mm watch for the past week. I’ve tested every Fenix model since the Garmin Fenix 5 Plus, and I’ve also tested every Apple Watch Ultra launched to date, and both are consistently among the <a href="https://www.tomsguide.com/us/best-gps-watches,review-2638.html">best sports watches </a>available.</p><p>Apple has also made great strides in closing the sports tracking gap between its devices and the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches</a>, with accuracy, battery life and training analysis features all improving with each generation of the Ultra.</p><p>However, there are certainly still areas where the Garmin Fenix 9 Pro outperforms the Apple Watch Ultra, and even after just a week of using the new Fenix, there are two features I’d love to see on the Apple Watch Ultra 4.</p><h3 class="article-body__section" id="section-maps-within-activity-screens"><span>Maps within activity screens</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="eZHBCPefduMUnbd4Z2jNq5" name="Garmin Fenix 9 Pro maps" alt="Garmin Fenix 9 Pro maps" src="https://cdn.mos.cms.futurecdn.net/eZHBCPefduMUnbd4Z2jNq5-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 feel like this should be a pretty simple update to effect, and it’s something that’s standard across any sports watch with offline maps.</p><p>The Apple Watch Ultra 3 does offer maps and navigation tools, but you can’t have the map as one of your data screens in an activity, so if you want to check your route during a run, for example, you have to exit the Workout app to see it, then switch back to the Workout app afterward.</p><p>With the Garmin Fenix 9, you just scroll down to your map screen, which can even show activity stats overlaid on the top, so you can follow a route while also checking the activity duration or pace.</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:53.50%;"><img id="y7oD8GTuAku8kPEhozW2eU" name="WorkOutDoors App Apple Watch-5.jpg" alt="WorkOutDoors app on Apple Watch Ultra 2" src="https://cdn.mos.cms.futurecdn.net/y7oD8GTuAku8kPEhozW2eU-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1070" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>You can actually do this already with third-party sports tracking apps on the Apple Watch, like <a href="https://www.tomsguide.com/wellness/smartwatches/i-run-marathons-and-this-apple-watch-running-app-is-the-best-usd8-ive-ever-spent">WorkOutDoors</a>, so hopefully it’s something that shows up as a software update during Apple’s September event and then rolls back to older Apple Watch models.</p><h3 class="article-body__section" id="section-a-built-in-flashlight"><span>A built-in flashlight</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="HsEvn6zkCC3qyFB7uE4uB7" name="Garmin Fenix 9 Pro flashlight" alt="Garmin Fenix 9 Pro flashlight" src="https://cdn.mos.cms.futurecdn.net/HsEvn6zkCC3qyFB7uE4uB7-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>This is an ambitious hope, but most of Garmin’s top watches now feature a built-in flashlight, and it’s just so useful that I have to hope it’s something that eventually pops up on the Apple Watch Ultra.</p><p>When Garmin first launched a watch with a built-in flashlight, I didn’t think it was all that big a deal, but I constantly use the flashlight on my watch, either to navigate around the house at night, find children’s toys that have rolled under sofas, or as an extra light when running after sunset.</p><p>The Garmin Fenix 9 Pro has an upgraded flashlight compared to past watches, with a new green option alongside the red light and several levels of white. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="fGrGUfaLTVf2k5dJJNWLTo" name="Garmin Fenix 9 Pro flashlight" alt="Garmin Fenix 9 Pro flashlight" src="https://cdn.mos.cms.futurecdn.net/fGrGUfaLTVf2k5dJJNWLTo-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 don’t think the Apple Watch Ultra 4 has to go green, though it’s apparently useful for certain sports and for reading maps at night, but any kind of built-in flashlight would be a great addition to the watch.</p><p>At the moment, you can use the screen on the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3 </a>as a torch, but it’s not as bright as a built-in LED light, nor as easy to direct light, and you can’t use the flashlight at the same time as using the screen.</p><p>This major design change is the kind of thing that would probably have shown up in leaks if it were going to arrive on the Apple Watch Ultra 4, but I live in hope it makes an unexpected appearance, especially as it would fit perfectly with the "surprise and shine" theme of the September event.</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><ul><li><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></li></ul><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/smartwatches/from-fall-detection-to-hypertension-10-apple-watch-innovations-that-changed-the-game"><strong>10 Apple Watch innovations that changed the game — from Fall Detection to Hypertension Alerts</strong></a><strong></strong></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/im-a-smartwatch-reviewer-and-heres-my-apple-watch-series-12-wish-list-three-upgrades-i-want-and-one-i-dont"><strong>I'm a smartwatch reviewer, and here's my Apple Watch Series 12 wish list — three upgrades I want, and one I don't</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/3-apple-watch-settings-i-always-turn-off-to-maximize-battery-life"><strong>3 Apple Watch settings I always turn off to maximize battery life</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Forget Whoop — 3 major differences between the subscription-free Luna Band and Garmin Cirqa ]]></title>
                                                                                                <dc:content><![CDATA[ <p>2026 has been a massive year for screen-free fitness wearables, with models like the <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">Fitbit Air</a> and <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-garmin-cirqa-and-it-strikes-a-near-perfect-balance-between-the-fitbit-air-and-whoop-5-0">Garmin Cirqa</a> debuting alongside more established players, like the latest <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a>. </p><p>Now, the competition is about to get a little tougher: The $149 Luna Band just officially began shipping worldwide. Not only that, it seems poised to give Garmin,  Google, and Whoop a serious run for the money, especially when it comes to free, personalized AI insights.</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="y3UCCPrwa3fasP6JkXMYHo" name="Luna-Cirqa-04" alt="Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/y3UCCPrwa3fasP6JkXMYHo-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>I initially checked out an early version of the <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-luna-band-fitness-tracker-and-it-beats-the-whoop-5-0-in-3-big-ways">Luna Band</a> back at CES in January 2026. Now, nine months later, the final product is ready for prime time. </p><p>Not only that, I just demoed the final Luna Band at <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA 2026 in Berlin</a>, and I have to say, I am impressed. I also had the chance to compare it head-to-head against the Garmin Cirqa (which I was wearing at the time), and even though the two have a lot in common, small but meaningful things set them apart.</p><p>With that in mind, here are the three biggest differences between the new Luna Band and the Garmin Cirqa, its closest competition. </p><h2 id="1-the-luna-band-costs-less-than-the-garmin-cirqa">1. The Luna Band costs less than the Garmin Cirqa</h2><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="TrVGT7FHzWykpwioYKi8yn" name="Luna-Cirqa-01" alt="Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/TrVGT7FHzWykpwioYKi8yn-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>Unlike the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> out there, the newest screen-free fitness trackers shouldn't shatter your piggy bank. The Garmin Cirqa, for example, is $199, while the Luna Band is priced $50 cheaper at $149. That said, the Fitbit Air beats them both with a starting price of just $99.</p><p>However, both Garmin and Google (Fitbit) place some of their headier training insights and personalized AI-backed features behind a monthly paywall. Luna does not...</p><h2 id="2-none-of-luna-s-features-are-paywalled">2. None of Luna’s features are paywalled </h2><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="EtCmRxAJth6TNRprGsdRHo" name="Luna-Band-01" alt="Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/EtCmRxAJth6TNRprGsdRHo-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 Luna Band records all the basic holistic data points you expect, like continuous heart rate, sleep quality, workouts, and daily movement, but unlike the Fitbit Air and Garmin Cirqa, the Luna Band companion app is less focused on metrics and charts and more focused on generating actionable insights and reports based on both your current holistic trends and your overall goals. These are, of course, accomplished with the help of AI.</p><p>More simply put: Luna's personalized AI recommendations are part of what you're paying for when you spend $149 on the device... no need to cough up extra dough down the line. Meanwhile, similar custom, AI-driven advice from Garmin and Fitbit requires an additional monthly fee even after purchasing either tracker.</p><h2 id="3-only-the-garmin-cirqa-has-a-physical-button">3. Only the Garmin Cirqa has a physical button</h2><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="fjAqcyfidP8xCqcaK64D9o" name="Luna-Cirqa-02" alt="Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/fjAqcyfidP8xCqcaK64D9o-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, while the Luna Band is more compact and affordable than the Garmin Cirqa — with no subscription costs, optional or otherwise — one feature it's missing is a physical button. On the Garmin Cirqa, users can program the wearable's sole control point to start and stop any workout type of their choosing. It can also be used to broadcast heart rate data to another compatible Garmin device. </p><p>Personally, I feel that a similarly customizable physical button would feel right at home on the Luna Band (the Fitbit Air, too). </p><p>Stay tuned for my full Luna Band review, coming soon. In the meantime, what are your thoughts on the new Luna Band? Would you consider picking it up over the Garmin Cirqa and/or Fitbit Air? Let me know in the poll below. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eygYAO"></div>                            </div>                            <script src="https://kwizly.com/embed/eygYAO.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><a href="https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-new-circular-ring-3-and-it-beats-the-oura-ring-5-in-3-big-ways">I just went hands-on with the new Circular Ring 3 — and it beats the Oura Ring 5 in 3 big ways</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-reviewed-the-garmin-cirqa-5-things-you-need-to-know-about-garmins-subscription-free-whoop-and-fitbit-air-alternative">I just reviewed the Garmin Cirqa — 5 things you need to know about Garmin’s subscription-free Whoop and Fitbit Air alternative</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/exclusive-garmin-cirqa-pm-says-it-just-felt-like-we-had-all-of-the-pieces-in-place-to-launch-a-screen-free-fitness-tracker">Exclusive: Garmin Cirqa PM says ‘it just felt like we had all of the pieces in place’ to launch a screen-free fitness tracker</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness-trackers/forget-whoop-3-major-differences-between-the-subscription-free-luna-band-and-garmin-cirqa</link>
                                                                            <description>
                            <![CDATA[ Watch out, Whoop, Garmin, and Fitbit, there's a new screen-free fitness tracker available, and it could be the best one yet. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">7AHr6g9yb2dKLGYwuJBR4X</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/qV7YvVUjSxb25swRkqkw4o-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 04 Sep 2026 19:20:56 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Smartwatches]]></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/qV7YvVUjSxb25swRkqkw4o-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin]]></media:description>                                                            <media:text><![CDATA[Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/qV7YvVUjSxb25swRkqkw4o-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>2026 has been a massive year for screen-free fitness wearables, with models like the <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">Fitbit Air</a> and <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-garmin-cirqa-and-it-strikes-a-near-perfect-balance-between-the-fitbit-air-and-whoop-5-0">Garmin Cirqa</a> debuting alongside more established players, like the latest <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a>. </p><p>Now, the competition is about to get a little tougher: The $149 Luna Band just officially began shipping worldwide. Not only that, it seems poised to give Garmin,  Google, and Whoop a serious run for the money, especially when it comes to free, personalized AI insights.</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="y3UCCPrwa3fasP6JkXMYHo" name="Luna-Cirqa-04" alt="Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/y3UCCPrwa3fasP6JkXMYHo-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>I initially checked out an early version of the <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-luna-band-fitness-tracker-and-it-beats-the-whoop-5-0-in-3-big-ways">Luna Band</a> back at CES in January 2026. Now, nine months later, the final product is ready for prime time. </p><p>Not only that, I just demoed the final Luna Band at <a href="https://www.tomsguide.com/tech-events/best-of-ifa-2026-we-found-the-26-top-new-gadgets">IFA 2026 in Berlin</a>, and I have to say, I am impressed. I also had the chance to compare it head-to-head against the Garmin Cirqa (which I was wearing at the time), and even though the two have a lot in common, small but meaningful things set them apart.</p><p>With that in mind, here are the three biggest differences between the new Luna Band and the Garmin Cirqa, its closest competition. </p><h2 id="1-the-luna-band-costs-less-than-the-garmin-cirqa">1. The Luna Band costs less than the Garmin Cirqa</h2><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="TrVGT7FHzWykpwioYKi8yn" name="Luna-Cirqa-01" alt="Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/TrVGT7FHzWykpwioYKi8yn-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>Unlike the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> out there, the newest screen-free fitness trackers shouldn't shatter your piggy bank. The Garmin Cirqa, for example, is $199, while the Luna Band is priced $50 cheaper at $149. That said, the Fitbit Air beats them both with a starting price of just $99.</p><p>However, both Garmin and Google (Fitbit) place some of their headier training insights and personalized AI-backed features behind a monthly paywall. Luna does not...</p><h2 id="2-none-of-luna-s-features-are-paywalled">2. None of Luna’s features are paywalled </h2><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="EtCmRxAJth6TNRprGsdRHo" name="Luna-Band-01" alt="Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/EtCmRxAJth6TNRprGsdRHo-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 Luna Band records all the basic holistic data points you expect, like continuous heart rate, sleep quality, workouts, and daily movement, but unlike the Fitbit Air and Garmin Cirqa, the Luna Band companion app is less focused on metrics and charts and more focused on generating actionable insights and reports based on both your current holistic trends and your overall goals. These are, of course, accomplished with the help of AI.</p><p>More simply put: Luna's personalized AI recommendations are part of what you're paying for when you spend $149 on the device... no need to cough up extra dough down the line. Meanwhile, similar custom, AI-driven advice from Garmin and Fitbit requires an additional monthly fee even after purchasing either tracker.</p><h2 id="3-only-the-garmin-cirqa-has-a-physical-button">3. Only the Garmin Cirqa has a physical button</h2><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="fjAqcyfidP8xCqcaK64D9o" name="Luna-Cirqa-02" alt="Close-up of the Garmin Cirqa screen-free tracker next to the Luna Band at IFA 2026 in Berlin" src="https://cdn.mos.cms.futurecdn.net/fjAqcyfidP8xCqcaK64D9o-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, while the Luna Band is more compact and affordable than the Garmin Cirqa — with no subscription costs, optional or otherwise — one feature it's missing is a physical button. On the Garmin Cirqa, users can program the wearable's sole control point to start and stop any workout type of their choosing. It can also be used to broadcast heart rate data to another compatible Garmin device. </p><p>Personally, I feel that a similarly customizable physical button would feel right at home on the Luna Band (the Fitbit Air, too). </p><p>Stay tuned for my full Luna Band review, coming soon. In the meantime, what are your thoughts on the new Luna Band? Would you consider picking it up over the Garmin Cirqa and/or Fitbit Air? Let me know in the poll below. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eygYAO"></div>                            </div>                            <script src="https://kwizly.com/embed/eygYAO.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><a href="https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-new-circular-ring-3-and-it-beats-the-oura-ring-5-in-3-big-ways">I just went hands-on with the new Circular Ring 3 — and it beats the Oura Ring 5 in 3 big ways</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-reviewed-the-garmin-cirqa-5-things-you-need-to-know-about-garmins-subscription-free-whoop-and-fitbit-air-alternative">I just reviewed the Garmin Cirqa — 5 things you need to know about Garmin’s subscription-free Whoop and Fitbit Air alternative</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/exclusive-garmin-cirqa-pm-says-it-just-felt-like-we-had-all-of-the-pieces-in-place-to-launch-a-screen-free-fitness-tracker">Exclusive: Garmin Cirqa PM says ‘it just felt like we had all of the pieces in place’ to launch a screen-free fitness tracker</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Coros just added offline maps to its most affordable sports watch — but there's a catch ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The <a href="https://www.tomsguide.com/wellness/smartwatches/coros-pace-4-review">Coros Pace 4 </a>impressed from the moment I first strapped it to my wrist, and after using it for <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-coros-pace-4-for-six-months-here-are-my-long-term-pros-and-cons">several months of marathon training</a> I liked it even more. </p><p>One of the very few complaints I had about the watch was that it didn’t offer offline maps. Guess what just got added to the Coros Pace 4 via a free software update?</p><p>You can now download maps to the Coros Pace 4 and use it to follow routes with turn-by-turn directions, making it one of the most affordable<a href="https://www.tomsguide.com/us/best-gps-watches,review-2638.html"> sports watches</a> to offer this feature.</p><div class="product"><a data-dimension112="167a70b0-a795-11f1-891f-3b6a4e0e8cd1" data-action="Deal Block" data-label="Pace 4" data-dimension48="Pace 4" data-dimension25="$249" href="https://www.amazon.com/COROS-Ultralight-Touchscreen-Features-Advanced/dp/B0FYGTCX83/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:831px;"><p class="vanilla-image-block" style="padding-top:131.53%;"><img id="myvKDNp3qYeHPKM4wyEs8n" name="Coros Pace 4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/myvKDNp3qYeHPKM4wyEs8n-1920-80.png" mos="" align="middle" fullscreen="" width="831" height="1093" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Coros Pace 4 is an outstanding sports watch for runner and triathletes and already offered great value even before it added maps to its extensive list of features,<a class="view-deal button" href="https://www.amazon.com/COROS-Ultralight-Touchscreen-Features-Advanced/dp/B0FYGTCX83/" target="_blank" rel="nofollow" data-dimension112="167a70b0-a795-11f1-891f-3b6a4e0e8cd1" data-action="Deal Block" data-label="Pace 4" data-dimension48="Pace 4" data-dimension25="$249">View Deal</a></p></div><p>Coros has always done a great job of adding value to its watches with software updates long after they launch, but this is a particularly big upgrade and one I wasn’t expecting. There is, however, a minor catch with the new feature…</p><h2 id="you-only-have-4gb-of-space-to-play-with">You only have 4GB of space to play with</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3368px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="fBS6oZKQJdHkNkzQ6hfuRn" name="Coros Pace 4" alt="Coros Pace 4 and Coros Pace 4 aluminium" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:466,l:1389,cw:3368,ch:1894,q:80/fBS6oZKQJdHkNkzQ6hfuRn.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The 4GB of storage on the Pace 4 is a lot less than the minimum of 16GB you usually get on watches with maps, and it limits how much you can download to the watch, especially if you also store your music on the Pace 4.</p><p>It’s also important to note that a lot of that 4GB is already taken up with system data, so you can’t manage it — I only have 1.6GB left on my Coros Pace 4 without any music on the watch.</p><p>I consider this a fairly small drawback though, because there is still comfortably enough space to download your local area and you can add and remove maps easily through the app, so you can download places you plan to travel to. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oQcF3BGSPAo3L9eKCGrHTR" name="Coros app maps" alt="Coros app maps" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:209,l:0,cw:2560,ch:1440,q:80/oQcF3BGSPAo3L9eKCGrHTR.jpg" mos="" align="middle" fullscreen="" width="2560" height="1920" 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>For example, the size of two areas around me that cover London and the south east of the U.K. is 151.2MB, and two large areas that cover New York and Philadelphia is 122.4MB, so you should have room to download your local area and anywhere you visit regularly.</p><p>You can’t download the whole world and if you do use the music feature you might have to delete some tracks to make space for maps, but I consider that a minor inconvenience to add such a useful feature to the watch.</p><h2 id="how-to-get-maps-on-the-coros-pace-4">How to get maps on the Coros Pace 4</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1845px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="kSPp84rKr8YsbaWXAn34VE" name="Coros Pace 4 maps" alt="Coros Pace 4 maps" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:156,l:365,cw:1845,ch:1038,q:80/kSPp84rKr8YsbaWXAn34VE.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>To start using the new feature on the Pace 4 you first have to join the get the <a href="https://support.coros.com/hc/en-us/articles/26051859672724-COROS-Beta-Testing-Guide">Public Beta version of the Coros app</a>. Then youcan <strong>update your watch in the partner Coros app</strong> — this should come up as an option when you log in and sync your watch, or you can find the option to update in the watch section of the app.</p><p>Once the update is done you then have to <strong>choose and add the areas you want maps</strong> for on your watch, which are shown with their file sizes so you can plan how to use your storage accordingly. </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="w3URf4oLawYFnWYMEngtSR" name="Coros app maps" alt="Coros app maps" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:225,l:0,cw:2560,ch:1440,q:80/w3URf4oLawYFnWYMEngtSR.jpg" mos="" align="middle" fullscreen="" width="2560" height="1920" 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>Rather than breaking the world down into areas that fit directly with countries or major cities, in the Coros app you <strong>select preset squares that each cover an area</strong> of the world. Once you’ve picked your squares, hit download and your watch will connect to Wi-Fi and download the maps.</p><p>It’s a pretty fast process in my experience, and once on your watch you can see your maps during outdoor activities by using the action button on the Pace 4 to toggle between your stats and your map. </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:2034px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="4Hbyhuqs8wvVvh9tDVc9JE" name="Coros Pace 4 maps" alt="Coros Pace 4 maps" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:152,l:311,cw:2034,ch:1144,q:80/4Hbyhuqs8wvVvh9tDVc9JE.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>To use routes with the maps you can create them directly in the Coros app in the Explore tab and sync them to your watch.</p><p>The Coros Pace 4 doesn’t have the largest display, but the bright AMOLED screen means it’s still easy to see your maps and routes during activities. </p><p>This is a big update for an affordable sports watch, and it will be interesting to see if Garmin in particular responds, because downloadable maps have always been a feature restricted to Garmin’s most expensive watches.</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><ul><li><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></li></ul><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/smartwatches/from-fall-detection-to-hypertension-10-apple-watch-innovations-that-changed-the-game"><strong>10 Apple Watch innovations that changed the game — from Fall Detection to Hypertension Alerts</strong></a><strong></strong></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/im-a-smartwatch-reviewer-and-heres-my-apple-watch-series-12-wish-list-three-upgrades-i-want-and-one-i-dont"><strong>I'm a smartwatch reviewer, and here's my Apple Watch Series 12 wish list — three upgrades I want, and one I don't</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/3-apple-watch-settings-i-always-turn-off-to-maximize-battery-life"><strong>3 Apple Watch settings I always turn off to maximize battery life</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/coros-just-added-offline-maps-to-its-most-affordable-sports-watch-but-theres-a-catch</link>
                                                                            <description>
                            <![CDATA[ The Coros Pace 4 now offers offline maps, which is a fantastic addition that makes the watch even better value, but its limited storage space means you can’t download the whole world. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">GgJYYSHhXrNvRiDuQjG5Rc</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/YCUaQGixZh8wpBVWPw6XWR-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 04 Sep 2026 13:00:00 +0000</pubDate>                                                                                                                                <updated>Mon, 07 Sep 2026 14:58:50 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Nick Harris-Fry ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/J5Jjp49GUVjLZEbjEkTex-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/YCUaQGixZh8wpBVWPw6XWR-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Coros Pace 4 maps ]]></media:description>                                                            <media:text><![CDATA[Coros Pace 4 maps ]]></media:text>
                                <media:title type="plain"><![CDATA[Coros Pace 4 maps ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/YCUaQGixZh8wpBVWPw6XWR-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The <a href="https://www.tomsguide.com/wellness/smartwatches/coros-pace-4-review">Coros Pace 4 </a>impressed from the moment I first strapped it to my wrist, and after using it for <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-coros-pace-4-for-six-months-here-are-my-long-term-pros-and-cons">several months of marathon training</a> I liked it even more. </p><p>One of the very few complaints I had about the watch was that it didn’t offer offline maps. Guess what just got added to the Coros Pace 4 via a free software update?</p><p>You can now download maps to the Coros Pace 4 and use it to follow routes with turn-by-turn directions, making it one of the most affordable<a href="https://www.tomsguide.com/us/best-gps-watches,review-2638.html"> sports watches</a> to offer this feature.</p><div class="product"><a data-dimension112="167a70b0-a795-11f1-891f-3b6a4e0e8cd1" data-action="Deal Block" data-label="Pace 4" data-dimension48="Pace 4" data-dimension25="$249" href="https://www.amazon.com/COROS-Ultralight-Touchscreen-Features-Advanced/dp/B0FYGTCX83/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:831px;"><p class="vanilla-image-block" style="padding-top:131.53%;"><img id="myvKDNp3qYeHPKM4wyEs8n" name="Coros Pace 4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/myvKDNp3qYeHPKM4wyEs8n-1920-80.png" mos="" align="middle" fullscreen="" width="831" height="1093" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Coros Pace 4 is an outstanding sports watch for runner and triathletes and already offered great value even before it added maps to its extensive list of features,<a class="view-deal button" href="https://www.amazon.com/COROS-Ultralight-Touchscreen-Features-Advanced/dp/B0FYGTCX83/" target="_blank" rel="nofollow" data-dimension112="167a70b0-a795-11f1-891f-3b6a4e0e8cd1" data-action="Deal Block" data-label="Pace 4" data-dimension48="Pace 4" data-dimension25="$249">View Deal</a></p></div><p>Coros has always done a great job of adding value to its watches with software updates long after they launch, but this is a particularly big upgrade and one I wasn’t expecting. There is, however, a minor catch with the new feature…</p><h2 id="you-only-have-4gb-of-space-to-play-with">You only have 4GB of space to play with</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3368px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="fBS6oZKQJdHkNkzQ6hfuRn" name="Coros Pace 4" alt="Coros Pace 4 and Coros Pace 4 aluminium" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:466,l:1389,cw:3368,ch:1894,q:80/fBS6oZKQJdHkNkzQ6hfuRn.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The 4GB of storage on the Pace 4 is a lot less than the minimum of 16GB you usually get on watches with maps, and it limits how much you can download to the watch, especially if you also store your music on the Pace 4.</p><p>It’s also important to note that a lot of that 4GB is already taken up with system data, so you can’t manage it — I only have 1.6GB left on my Coros Pace 4 without any music on the watch.</p><p>I consider this a fairly small drawback though, because there is still comfortably enough space to download your local area and you can add and remove maps easily through the app, so you can download places you plan to travel to. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oQcF3BGSPAo3L9eKCGrHTR" name="Coros app maps" alt="Coros app maps" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:209,l:0,cw:2560,ch:1440,q:80/oQcF3BGSPAo3L9eKCGrHTR.jpg" mos="" align="middle" fullscreen="" width="2560" height="1920" 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>For example, the size of two areas around me that cover London and the south east of the U.K. is 151.2MB, and two large areas that cover New York and Philadelphia is 122.4MB, so you should have room to download your local area and anywhere you visit regularly.</p><p>You can’t download the whole world and if you do use the music feature you might have to delete some tracks to make space for maps, but I consider that a minor inconvenience to add such a useful feature to the watch.</p><h2 id="how-to-get-maps-on-the-coros-pace-4">How to get maps on the Coros Pace 4</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1845px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="kSPp84rKr8YsbaWXAn34VE" name="Coros Pace 4 maps" alt="Coros Pace 4 maps" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:156,l:365,cw:1845,ch:1038,q:80/kSPp84rKr8YsbaWXAn34VE.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>To start using the new feature on the Pace 4 you first have to join the get the <a href="https://support.coros.com/hc/en-us/articles/26051859672724-COROS-Beta-Testing-Guide">Public Beta version of the Coros app</a>. Then youcan <strong>update your watch in the partner Coros app</strong> — this should come up as an option when you log in and sync your watch, or you can find the option to update in the watch section of the app.</p><p>Once the update is done you then have to <strong>choose and add the areas you want maps</strong> for on your watch, which are shown with their file sizes so you can plan how to use your storage accordingly. </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="w3URf4oLawYFnWYMEngtSR" name="Coros app maps" alt="Coros app maps" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:225,l:0,cw:2560,ch:1440,q:80/w3URf4oLawYFnWYMEngtSR.jpg" mos="" align="middle" fullscreen="" width="2560" height="1920" 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>Rather than breaking the world down into areas that fit directly with countries or major cities, in the Coros app you <strong>select preset squares that each cover an area</strong> of the world. Once you’ve picked your squares, hit download and your watch will connect to Wi-Fi and download the maps.</p><p>It’s a pretty fast process in my experience, and once on your watch you can see your maps during outdoor activities by using the action button on the Pace 4 to toggle between your stats and your map. </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:2034px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="4Hbyhuqs8wvVvh9tDVc9JE" name="Coros Pace 4 maps" alt="Coros Pace 4 maps" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:152,l:311,cw:2034,ch:1144,q:80/4Hbyhuqs8wvVvh9tDVc9JE.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>To use routes with the maps you can create them directly in the Coros app in the Explore tab and sync them to your watch.</p><p>The Coros Pace 4 doesn’t have the largest display, but the bright AMOLED screen means it’s still easy to see your maps and routes during activities. </p><p>This is a big update for an affordable sports watch, and it will be interesting to see if Garmin in particular responds, because downloadable maps have always been a feature restricted to Garmin’s most expensive watches.</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><ul><li><em><strong>Follow </strong></em><a href="https://www.instagram.com/tomsguidefitness/" target="_blank"><em><strong>Tom's Guide fitness</strong></em></a><em><strong> on Instagram for more workouts, routines, tips, and tricks.</strong></em></li></ul><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/smartwatches/from-fall-detection-to-hypertension-10-apple-watch-innovations-that-changed-the-game"><strong>10 Apple Watch innovations that changed the game — from Fall Detection to Hypertension Alerts</strong></a><strong></strong></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/im-a-smartwatch-reviewer-and-heres-my-apple-watch-series-12-wish-list-three-upgrades-i-want-and-one-i-dont"><strong>I'm a smartwatch reviewer, and here's my Apple Watch Series 12 wish list — three upgrades I want, and one I don't</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/3-apple-watch-settings-i-always-turn-off-to-maximize-battery-life"><strong>3 Apple Watch settings I always turn off to maximize battery life</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch 12 and Ultra 4 rumors: Your next Apple Watch could have a ceramic case ]]></title>
                                                                                                <dc:content><![CDATA[ <p>There hasn’t been a ceramic Apple Watch since 2019’s Apple Watch Series 5, but that could be about to change. With the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-all-the-design-health-and-battery-life-rumors-so-far">Apple Watch Series 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-rumors-everything-we-know-about-apples-next-ultra-rugged-smartwatch">Ultra 4</a> tipped to arrive next week, one notable Apple insider suggests that an optional, elevated ceramic shell could be on the table this year.</p><p>In fact, we may get new Apple Watches offered in not one, but two ceramic case choices. Here’s everything you need to know about Apple Watch 12 and Apple Watch Ultra 4 ceramic case and general design rumors. </p><h2 id="no-massive-apple-watch-design-changes-for-2026">No massive Apple Watch design changes for 2026</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3066px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="wFrwtxB59iwVBRXoDsAHSA" name="fav-AW-apps" alt="Close up of the Apple Watch 11 on a user's wrist with the app icon screen displayed" src="https://cdn.mos.cms.futurecdn.net/wFrwtxB59iwVBRXoDsAHSA-1920-80.jpg" mos="" align="middle" fullscreen="" width="3066" height="1725" 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>We’re a little more than a week out from Apple’s big September "<a href="https://www.tomsguide.com/phones/iphones/apple-event-is-official-for-september-9-iphone-ultra-iphone-18-pro-max-watch-12-and-more">Surprise and shine</a>" smartwatch and smartphone launch, and prolific Apple insider <a href="https://www.bloomberg.com/news/newsletters/2026-08-30/john-ternus-management-team-apple-watch-series-12-foldable-iphone-apple-pencil-mtfvmdyu">Mark Gurman</a> just dropped some juicy details about what we <em>might</em> expect from the Apple Watch 12 and Apple Watch Ultra 4.</p><p>For starters, it doesn’t sound like either model will look all that different from last year’s <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch 11</a> or <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a>. Instead, Gurman predicts a major redesign for both lines will probably arrive in 2027. </p><p>Under the hood, however, there will likely be small improvements, like a faster processor and potentially improved heart rate tracking. However, a much-rumored onboard fingerprint scanner to unlock the Apple Watch doesn't seem to be in the cards, says Gurman.</p><h2 id="apple-39-s-first-ceramic-model-in-seven-years">Apple's first ceramic model in seven years?</h2><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="6xWxFmJRkMDPWa7YQ7zZ33" name="IMG_5005" alt="A photo of the Apple Watch Ultra 3" src="https://cdn.mos.cms.futurecdn.net/6xWxFmJRkMDPWa7YQ7zZ33-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>Despite Gurman putting the kibosh on some of the more exciting Apple Watch Series 12 and Apple Watch Ultra 4 design rumors, he’s fairly certain of one: the return of an optional ceramic case. </p><p>Why is a ceramic smartwatch case such a big deal? In addition to being more impact-resistant than stainless steel and aluminum, zirconia ceramic is also more scratch-resistant than the former (though not the latter).</p><p>That said, for most folks, the real appeal of a ceramic Apple Watch 12 or Ultra 4 case will come down to aesthetics. For example, the <a href="https://www.tomsguide.com/reviews/apple-watch-5">Series 5</a> in white ceramic (shown at the top of the page) was widely admired for its unique, elevated, pearly appearance. </p><p>According to Gurman, new ceramic color options for the latest Apple Watch models might include a similar pearly white and dark grey. </p><h2 id="apple-watch-12-ceramic-price-prediction">Apple Watch 12 ceramic: price prediction</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2659px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="FJQDmsv347vjHMZCoFxV4T" name="AppleWatchUltra3-v-Series11" alt="Apple Watch Ultra 3 and Apple Watch Series 11" src="https://cdn.mos.cms.futurecdn.net/FJQDmsv347vjHMZCoFxV4T-1920-80.jpg" mos="" align="middle" fullscreen="" width="2659" height="1496" 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>Here’s the bad news: When the Apple Watch Series 5 launched in 2019, the standard model started at $399 while the ceramic Series 5 started at a whopping $1,299. </p><p>I’m not even going to wager how much a ceramic Apple Watch Ultra 4 might go for, as I’m also not convinced Cupertino will offer such a model. The Series 12 ceramic, however, seems much more possible.</p><p>I'm already anticipating a potential price increase for the standard flagship Apple Watch 12 (though nothing is confirmed). Let’s assume, for a moment, the new model starts at $449 instead of $399. In that scenario, I could see a ceramic Series 12 starting as high as $1,499. Woof.</p><p>What are your thoughts on the possibility of a ceramic Apple Watch Series 12 or ceramic Apple Watch Ultra 4? Let me know in the comments below. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4"><strong>I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/leaked-apple-watch-12-design-change-is-the-opposite-of-an-upgrade-and-that-has-me-worried"><strong>Leaked Apple Watch 12 design change is the opposite of an upgrade — and that has me worried</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-12-and-ultra-4-rumors-your-next-apple-watch-could-have-a-ceramic-case</link>
                                                                            <description>
                            <![CDATA[ Here are the latest design rumors for the Apple Watch Series 12 and Apple Watch Ultra 4, including hints of a ceramic case for one or both models. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">9a5frmNdyr9XTDXuZhiLgQ</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/ppvYQkWYjYNxjTTKzABg6U-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 31 Aug 2026 22:24:26 +0000</pubDate>                                                                                                                                <updated>Tue, 01 Sep 2026 01:44:13 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/ppvYQkWYjYNxjTTKzABg6U-1920-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Apple Watch Series 5 in white ceramic on a user&#039;s wrist]]></media:description>                                                            <media:text><![CDATA[Close-up of the Apple Watch Series 5 in white ceramic on a user&#039;s wrist]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Apple Watch Series 5 in white ceramic on a user&#039;s wrist]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/ppvYQkWYjYNxjTTKzABg6U-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>There hasn’t been a ceramic Apple Watch since 2019’s Apple Watch Series 5, but that could be about to change. With the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-all-the-design-health-and-battery-life-rumors-so-far">Apple Watch Series 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-rumors-everything-we-know-about-apples-next-ultra-rugged-smartwatch">Ultra 4</a> tipped to arrive next week, one notable Apple insider suggests that an optional, elevated ceramic shell could be on the table this year.</p><p>In fact, we may get new Apple Watches offered in not one, but two ceramic case choices. Here’s everything you need to know about Apple Watch 12 and Apple Watch Ultra 4 ceramic case and general design rumors. </p><h2 id="no-massive-apple-watch-design-changes-for-2026">No massive Apple Watch design changes for 2026</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3066px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="wFrwtxB59iwVBRXoDsAHSA" name="fav-AW-apps" alt="Close up of the Apple Watch 11 on a user's wrist with the app icon screen displayed" src="https://cdn.mos.cms.futurecdn.net/wFrwtxB59iwVBRXoDsAHSA-1920-80.jpg" mos="" align="middle" fullscreen="" width="3066" height="1725" 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>We’re a little more than a week out from Apple’s big September "<a href="https://www.tomsguide.com/phones/iphones/apple-event-is-official-for-september-9-iphone-ultra-iphone-18-pro-max-watch-12-and-more">Surprise and shine</a>" smartwatch and smartphone launch, and prolific Apple insider <a href="https://www.bloomberg.com/news/newsletters/2026-08-30/john-ternus-management-team-apple-watch-series-12-foldable-iphone-apple-pencil-mtfvmdyu">Mark Gurman</a> just dropped some juicy details about what we <em>might</em> expect from the Apple Watch 12 and Apple Watch Ultra 4.</p><p>For starters, it doesn’t sound like either model will look all that different from last year’s <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch 11</a> or <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a>. Instead, Gurman predicts a major redesign for both lines will probably arrive in 2027. </p><p>Under the hood, however, there will likely be small improvements, like a faster processor and potentially improved heart rate tracking. However, a much-rumored onboard fingerprint scanner to unlock the Apple Watch doesn't seem to be in the cards, says Gurman.</p><h2 id="apple-39-s-first-ceramic-model-in-seven-years">Apple's first ceramic model in seven years?</h2><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="6xWxFmJRkMDPWa7YQ7zZ33" name="IMG_5005" alt="A photo of the Apple Watch Ultra 3" src="https://cdn.mos.cms.futurecdn.net/6xWxFmJRkMDPWa7YQ7zZ33-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>Despite Gurman putting the kibosh on some of the more exciting Apple Watch Series 12 and Apple Watch Ultra 4 design rumors, he’s fairly certain of one: the return of an optional ceramic case. </p><p>Why is a ceramic smartwatch case such a big deal? In addition to being more impact-resistant than stainless steel and aluminum, zirconia ceramic is also more scratch-resistant than the former (though not the latter).</p><p>That said, for most folks, the real appeal of a ceramic Apple Watch 12 or Ultra 4 case will come down to aesthetics. For example, the <a href="https://www.tomsguide.com/reviews/apple-watch-5">Series 5</a> in white ceramic (shown at the top of the page) was widely admired for its unique, elevated, pearly appearance. </p><p>According to Gurman, new ceramic color options for the latest Apple Watch models might include a similar pearly white and dark grey. </p><h2 id="apple-watch-12-ceramic-price-prediction">Apple Watch 12 ceramic: price prediction</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2659px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="FJQDmsv347vjHMZCoFxV4T" name="AppleWatchUltra3-v-Series11" alt="Apple Watch Ultra 3 and Apple Watch Series 11" src="https://cdn.mos.cms.futurecdn.net/FJQDmsv347vjHMZCoFxV4T-1920-80.jpg" mos="" align="middle" fullscreen="" width="2659" height="1496" 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>Here’s the bad news: When the Apple Watch Series 5 launched in 2019, the standard model started at $399 while the ceramic Series 5 started at a whopping $1,299. </p><p>I’m not even going to wager how much a ceramic Apple Watch Ultra 4 might go for, as I’m also not convinced Cupertino will offer such a model. The Series 12 ceramic, however, seems much more possible.</p><p>I'm already anticipating a potential price increase for the standard flagship Apple Watch 12 (though nothing is confirmed). Let’s assume, for a moment, the new model starts at $449 instead of $399. In that scenario, I could see a ceramic Series 12 starting as high as $1,499. Woof.</p><p>What are your thoughts on the possibility of a ceramic Apple Watch Series 12 or ceramic Apple Watch Ultra 4? Let me know in the comments below. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/we-asked-368-people-what-they-want-from-the-apple-watch-ultra-4-heres-the-resounding-answer-and-its-not-ai"><strong>We asked 368 people what they want from the Apple Watch Ultra 4. Here’s the resounding answer (and it’s not AI)</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4"><strong>I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/leaked-apple-watch-12-design-change-is-the-opposite-of-an-upgrade-and-that-has-me-worried"><strong>Leaked Apple Watch 12 design change is the opposite of an upgrade — and that has me worried</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ We asked 300 people which screenless fitness tracker they’d buy, and the results are pretty close ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I’ve said it before, and I’ll say it again — 2026 is the year of the screenless tracker. It seems that we’re moving away from screens and notifications into a calmer, quieter world of 24/7 health tracking. </p><p>This year has seen the launch of the <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-new-fitbit-air-for-5-days-and-this-is-the-one-thing-that-has-really-impressed-me-so-far">Fitbit Air</a>, Google’s $99 screenless tracker, and more recently the <a href="https://www.tomsguide.com/wellness/fitness-trackers/ive-been-wearing-the-garmin-cirqa-for-3-weeks-here-are-3-things-i-like-and-3-things-id-change">Garmin Cirqa</a>, Garmin’s $199 equivalent. Neither requires a subscription, but I’d argue some of the best features on the Fitbit Air are behind the paywall. Oura also launched its <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> this year — the smallest and lightest smart ring on the market. </p><p>You can read my <a href="https://www.tomsguide.com/wellness/fitness-trackers/garmin-cirqa-vs-fitbit-air-vs-whoop-5-0-vs-oura-ring-5-which-fitness-tracker-should-you-buy">Fitbit Air vs Garmin Cirqa vs Whoop 5.0 vs Oura Ring 5 face-off </a>here, but to find out what <em>you’re </em>buying, we asked over 300 of you which tracker you’d buy. Read on to find out which came out on top. </p><h2 id="which-screenless-tracker-are-you-buying">Which screenless tracker are you buying? </h2><p>313 Tom’s Guide users answered our poll, and the results are pretty clear: it’s between the Fitbit Air and the Garmin Cirqa. Here’s what you said: </p><div ><table><caption>Which screenless tracker would you buy? The results: </caption><tbody><tr><td class="firstcol " ><p>Fitbit Air</p></td><td  ><p>41%</p></td></tr><tr><td class="firstcol " ><p>Garmin Cirqa</p></td><td  ><p>31%</p></td></tr><tr><td class="firstcol " ><p>Whoop</p></td><td  ><p>13%</p></td></tr><tr><td class="firstcol " ><p>Oura Ring</p></td><td  ><p>12%</p></td></tr><tr><td class="firstcol " ><p>Other</p></td><td  ><p>1%</p></td></tr></tbody></table></div><p>Even though the <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-garmin-cirqa-and-it-strikes-a-near-perfect-balance-between-the-fitbit-air-and-whoop-5-0">Garmin Cirqa</a> is twice the cost of the <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">Fitbit Air</a> — $199 vs $99 — these two trackers have a lot in common. Screen-free, your primary method for interacting with either is through the companion app. That said, the Cirqa also has one physical button to start and stop 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:5020px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="zCBBhA82yv8MGUKAmpHWt5" name="Fitbit-Air-lead" alt="Close-up of the sensors on the Fitbit Air" src="https://cdn.mos.cms.futurecdn.net/zCBBhA82yv8MGUKAmpHWt5-1920-80.jpg" mos="" align="middle" fullscreen="" width="5020" height="2824" 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>When it comes to the apps, both are excellent. With the Fitbit Air, you’ll be using the new Google Health App, which (if you pay for the subscription) comes with the Gemini-powered AI health coach that really is the best I’ve tested. </p><p>Garmin fans, on the other hand, will be pleased to hear that the Garmin Cirqa can be synced with the Garmin Connect app, allowing you to seamlessly move between your watch and the screenless tracker. </p><p>Which you choose really comes down to your budget and your preference. I personally find the Fitbit Air more comfortable on the wrist, but I do think you’ll need to pay the monthly subscription to get the most out of the device. </p><p>The Garmin Cirqa gives you all your data subscription-free (with a Garmin Connect+ subscription, you’ll get additional nutrition and coaching plans), and the side button makes your workout data more accurate. That said, it’s double the price. </p><p>We’ll keep putting these two trackers head-to-head over the next few months, so stay tuned. Which are you thinking of buying? Have your say below. </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><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-OKB5GW"></div>                            </div>                            <script src="https://kwizly.com/embed/OKB5GW.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/apple-watch-series-12-everything-we-know-so-far">Apple Watch Series 12 rumors — everything we know so far</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/from-fall-detection-to-hypertension-10-apple-watch-innovations-that-changed-the-game">10 Apple Watch innovations that changed the game — from Fall Detection to Hypertension Alerts</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/garmins-rumored-screen-less-wearable-just-might-be-the-subscription-free-whoop-rival-ive-been-waiting-for">Garmin’s rumored screen-less wearable just might be the subscription-free Whoop rival I’ve been waiting for</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness-trackers/we-asked-300-people-which-screenless-tracker-theyd-buy-and-the-results-are-pretty-close</link>
                                                                            <description>
                            <![CDATA[ We polled Tom's Guide readers which screenless fitness tracker they preferred - the Whoop, Fitbit Air, or Garmin Cirqa - and the results were pretty close. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">MPUMKJdgdDS4BSmCsxHhoC</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Ff9hx8JnRhaSc9bAGZ5AMn-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 31 Aug 2026 04:30:00 +0000</pubDate>                                                                                                                                <updated>Mon, 31 Aug 2026 11:30:15 +0000</updated>
                                                                                                                                            <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Smartwatches]]></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/Ff9hx8JnRhaSc9bAGZ5AMn-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Fitbit Air, Whoop MG and Garmin Cirqa]]></media:description>                                                            <media:text><![CDATA[Fitbit Air, Whoop MG and Garmin Cirqa]]></media:text>
                                <media:title type="plain"><![CDATA[Fitbit Air, Whoop MG and Garmin Cirqa]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Ff9hx8JnRhaSc9bAGZ5AMn-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I’ve said it before, and I’ll say it again — 2026 is the year of the screenless tracker. It seems that we’re moving away from screens and notifications into a calmer, quieter world of 24/7 health tracking. </p><p>This year has seen the launch of the <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-new-fitbit-air-for-5-days-and-this-is-the-one-thing-that-has-really-impressed-me-so-far">Fitbit Air</a>, Google’s $99 screenless tracker, and more recently the <a href="https://www.tomsguide.com/wellness/fitness-trackers/ive-been-wearing-the-garmin-cirqa-for-3-weeks-here-are-3-things-i-like-and-3-things-id-change">Garmin Cirqa</a>, Garmin’s $199 equivalent. Neither requires a subscription, but I’d argue some of the best features on the Fitbit Air are behind the paywall. Oura also launched its <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> this year — the smallest and lightest smart ring on the market. </p><p>You can read my <a href="https://www.tomsguide.com/wellness/fitness-trackers/garmin-cirqa-vs-fitbit-air-vs-whoop-5-0-vs-oura-ring-5-which-fitness-tracker-should-you-buy">Fitbit Air vs Garmin Cirqa vs Whoop 5.0 vs Oura Ring 5 face-off </a>here, but to find out what <em>you’re </em>buying, we asked over 300 of you which tracker you’d buy. Read on to find out which came out on top. </p><h2 id="which-screenless-tracker-are-you-buying">Which screenless tracker are you buying? </h2><p>313 Tom’s Guide users answered our poll, and the results are pretty clear: it’s between the Fitbit Air and the Garmin Cirqa. Here’s what you said: </p><div ><table><caption>Which screenless tracker would you buy? The results: </caption><tbody><tr><td class="firstcol " ><p>Fitbit Air</p></td><td  ><p>41%</p></td></tr><tr><td class="firstcol " ><p>Garmin Cirqa</p></td><td  ><p>31%</p></td></tr><tr><td class="firstcol " ><p>Whoop</p></td><td  ><p>13%</p></td></tr><tr><td class="firstcol " ><p>Oura Ring</p></td><td  ><p>12%</p></td></tr><tr><td class="firstcol " ><p>Other</p></td><td  ><p>1%</p></td></tr></tbody></table></div><p>Even though the <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-just-went-hands-on-with-the-garmin-cirqa-and-it-strikes-a-near-perfect-balance-between-the-fitbit-air-and-whoop-5-0">Garmin Cirqa</a> is twice the cost of the <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">Fitbit Air</a> — $199 vs $99 — these two trackers have a lot in common. Screen-free, your primary method for interacting with either is through the companion app. That said, the Cirqa also has one physical button to start and stop 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:5020px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="zCBBhA82yv8MGUKAmpHWt5" name="Fitbit-Air-lead" alt="Close-up of the sensors on the Fitbit Air" src="https://cdn.mos.cms.futurecdn.net/zCBBhA82yv8MGUKAmpHWt5-1920-80.jpg" mos="" align="middle" fullscreen="" width="5020" height="2824" 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>When it comes to the apps, both are excellent. With the Fitbit Air, you’ll be using the new Google Health App, which (if you pay for the subscription) comes with the Gemini-powered AI health coach that really is the best I’ve tested. </p><p>Garmin fans, on the other hand, will be pleased to hear that the Garmin Cirqa can be synced with the Garmin Connect app, allowing you to seamlessly move between your watch and the screenless tracker. </p><p>Which you choose really comes down to your budget and your preference. I personally find the Fitbit Air more comfortable on the wrist, but I do think you’ll need to pay the monthly subscription to get the most out of the device. </p><p>The Garmin Cirqa gives you all your data subscription-free (with a Garmin Connect+ subscription, you’ll get additional nutrition and coaching plans), and the side button makes your workout data more accurate. That said, it’s double the price. </p><p>We’ll keep putting these two trackers head-to-head over the next few months, so stay tuned. Which are you thinking of buying? Have your say below. </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><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-OKB5GW"></div>                            </div>                            <script src="https://kwizly.com/embed/OKB5GW.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/apple-watch-series-12-everything-we-know-so-far">Apple Watch Series 12 rumors — everything we know so far</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/from-fall-detection-to-hypertension-10-apple-watch-innovations-that-changed-the-game">10 Apple Watch innovations that changed the game — from Fall Detection to Hypertension Alerts</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/garmins-rumored-screen-less-wearable-just-might-be-the-subscription-free-whoop-rival-ive-been-waiting-for">Garmin’s rumored screen-less wearable just might be the subscription-free Whoop rival I’ve been waiting for</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ We asked Tom’s Guide readers which 2026 Android smartwatch they prefer — and the winner is clear ]]></title>
                                                                                                <dc:content><![CDATA[ <p>We asked Tom’s Guide readers which 2026 full-featured Android smartwatch they prefer, and the winner is crystal clear.</p><p>With 830 total votes, one device proved way more popular than the others, but was it the <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review">Google Pixel Watch 5</a>, the <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-to-know-about-the-new-samsung-galaxy-watch-9">Samsung Galaxy Watch 9</a>, or the <a href="https://www.tomsguide.com/wellness/smartwatches/galaxy-watch-ultra-2-hands-on-review">Samsung Galaxy Watch Ultra 2</a>? Check out the results for yourself below. </p><h2 id="which-full-featured-2026-android-smartwatch-would-you-rather-own">Which full-featured 2026 Android smartwatch would you rather own?</h2><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-XjarYO"></div>                            </div>                            <script src="https://kwizly.com/embed/XjarYO.js" async></script><ul><li><strong>1st place</strong>: 50%, Google Pixel Watch 5</li><li><strong>2nd place</strong>: 24%, Samsung Galaxy Watch Ultra 2</li><li><strong>3rd place</strong>: 16%, Samsung Galaxy Watch 9</li></ul><p>With a total of 418 votes, 50% of respondents said that the Pixel Watch 5 is their preferred current-model Android smartwatch. The Samsung Galaxy Watch Ultra 2 came in second place with 203 votes, or 24%. </p><p>The Samsung Galaxy Watch 9, meanwhile, was the least popular of the three, with just 135 folks preferring it to the other options, or 16% of respondents. And then we have those who prefer something other than the models listed; 74 of y’all selected that option, which begs the question: what would you buy instead?</p><h3 class="article-body__section" id="section-the-pixel-watch-5-is-the-clear-winner-but-why"><span>The Pixel Watch 5 is the clear winner, but why?</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:3982px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UedGRJgfxxBpcTJLDkJwmi" name="Google Pixel Watch 5-LIST2" alt="Close-up of the Pixel Watch 5 in 45mm on a user's wrist" src="https://cdn.mos.cms.futurecdn.net/UedGRJgfxxBpcTJLDkJwmi-1920-80.jpg" mos="" align="middle" fullscreen="" width="3982" height="2240" 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>So, why did the Pixel Watch 5 decimate the competition in this popularity poll over its peers? I think it simply comes down to the fact that it’s the more exciting model of the three. The Galaxy Watch 9 is a seriously minor update to the <a href="https://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-8-review">Galaxy Watch 8</a>. Likewise, the Galaxy Watch Ultra 2 adds some cool new features for <a href="https://www.tomsguide.com/wellness/smartwatches/samsung-turned-the-galaxy-watch-ultra-2-into-a-fully-fledged-dive-computer-but-theres-a-catch">scuba divers</a>, but little else.</p><p>The Pixel Watch 5, meanwhile, is also pretty much a carbon copy of its predecessor, but it does boast some unique and possibly groundbreaking new preventive health and safety tools, including <a href="https://www.tomsguide.com/wellness/smartwatches/exclusive-google-pm-says-the-pixel-watch-5-is-like-an-airbag-on-your-wrist-thanks-to-features-like-breathing-emergency-detection">Breathing Emergency Detection</a>, Insulin Resistance Trends, and Blood Pressure Trends. </p><h2 id="bottom-line">Bottom line</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4182px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="Su4KjbbvHMUJPbJL3EjFJV" name="Galaxy9-Pixel5-01" alt="Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5" src="https://cdn.mos.cms.futurecdn.net/Su4KjbbvHMUJPbJL3EjFJV-1920-80.jpg" mos="" align="middle" fullscreen="" width="4182" height="2353" 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 Samsung Galaxy Watch 9 may be the most affordable of its 2026 Android smartwatch class, but the Google Pixel Watch 5 wins prom king by a 2:1 margin versus the Galaxy Watch Ultra 2 and a 3:1 margin against the Samsung Galaxy Watch 9. </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/we-asked-toms-guide-readers-which-fitness-tracking-metrics-do-you-trust-the-least-heres-the-surprising-answer"><strong>We asked Tom's Guide readers, 'Which fitness tracking metrics do you trust the least?' Here's the surprising answer</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/can-the-usd99-fitbit-air-beat-the-usd799-apple-watch-ultra-3-at-fitness-tracking-i-manually-counted-4-500-steps-to-find-out"><strong>Can the $99 Fitbit Air beat the $799 Apple Watch Ultra 3 at fitness tracking? I manually counted 4,500 steps to find out</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/ive-tested-over-100-fitness-trackers-head-to-head-3-workout-stats-i-trust-the-least"><strong>I’ve tested over 100 fitness trackers head-to-head — 3 workout stats I trust the least</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/we-asked-toms-guide-readers-which-2026-android-smartwatch-they-prefer-and-the-winner-is-clear</link>
                                                                            <description>
                            <![CDATA[ We asked Tom's Guide readers which new Android smartwatch they'd rather own, and the response was overwhelming. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">fFFMGJQq4TBi5sGY5MSoaL</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Y7eJTDxMxazNSn9JssC77Z-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 30 Aug 2026 09:30:00 +0000</pubDate>                                                                                                                                <updated>Sun, 30 Aug 2026 12:30:41 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/Y7eJTDxMxazNSn9JssC77Z-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5 next to the Samsung Galaxy Watch Ultra 2]]></media:description>                                                            <media:text><![CDATA[Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5 next to the Samsung Galaxy Watch Ultra 2]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5 next to the Samsung Galaxy Watch Ultra 2]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Y7eJTDxMxazNSn9JssC77Z-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>We asked Tom’s Guide readers which 2026 full-featured Android smartwatch they prefer, and the winner is crystal clear.</p><p>With 830 total votes, one device proved way more popular than the others, but was it the <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review">Google Pixel Watch 5</a>, the <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-to-know-about-the-new-samsung-galaxy-watch-9">Samsung Galaxy Watch 9</a>, or the <a href="https://www.tomsguide.com/wellness/smartwatches/galaxy-watch-ultra-2-hands-on-review">Samsung Galaxy Watch Ultra 2</a>? Check out the results for yourself below. </p><h2 id="which-full-featured-2026-android-smartwatch-would-you-rather-own">Which full-featured 2026 Android smartwatch would you rather own?</h2><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-XjarYO"></div>                            </div>                            <script src="https://kwizly.com/embed/XjarYO.js" async></script><ul><li><strong>1st place</strong>: 50%, Google Pixel Watch 5</li><li><strong>2nd place</strong>: 24%, Samsung Galaxy Watch Ultra 2</li><li><strong>3rd place</strong>: 16%, Samsung Galaxy Watch 9</li></ul><p>With a total of 418 votes, 50% of respondents said that the Pixel Watch 5 is their preferred current-model Android smartwatch. The Samsung Galaxy Watch Ultra 2 came in second place with 203 votes, or 24%. </p><p>The Samsung Galaxy Watch 9, meanwhile, was the least popular of the three, with just 135 folks preferring it to the other options, or 16% of respondents. And then we have those who prefer something other than the models listed; 74 of y’all selected that option, which begs the question: what would you buy instead?</p><h3 class="article-body__section" id="section-the-pixel-watch-5-is-the-clear-winner-but-why"><span>The Pixel Watch 5 is the clear winner, but why?</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:3982px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UedGRJgfxxBpcTJLDkJwmi" name="Google Pixel Watch 5-LIST2" alt="Close-up of the Pixel Watch 5 in 45mm on a user's wrist" src="https://cdn.mos.cms.futurecdn.net/UedGRJgfxxBpcTJLDkJwmi-1920-80.jpg" mos="" align="middle" fullscreen="" width="3982" height="2240" 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>So, why did the Pixel Watch 5 decimate the competition in this popularity poll over its peers? I think it simply comes down to the fact that it’s the more exciting model of the three. The Galaxy Watch 9 is a seriously minor update to the <a href="https://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-8-review">Galaxy Watch 8</a>. Likewise, the Galaxy Watch Ultra 2 adds some cool new features for <a href="https://www.tomsguide.com/wellness/smartwatches/samsung-turned-the-galaxy-watch-ultra-2-into-a-fully-fledged-dive-computer-but-theres-a-catch">scuba divers</a>, but little else.</p><p>The Pixel Watch 5, meanwhile, is also pretty much a carbon copy of its predecessor, but it does boast some unique and possibly groundbreaking new preventive health and safety tools, including <a href="https://www.tomsguide.com/wellness/smartwatches/exclusive-google-pm-says-the-pixel-watch-5-is-like-an-airbag-on-your-wrist-thanks-to-features-like-breathing-emergency-detection">Breathing Emergency Detection</a>, Insulin Resistance Trends, and Blood Pressure Trends. </p><h2 id="bottom-line">Bottom line</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4182px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="Su4KjbbvHMUJPbJL3EjFJV" name="Galaxy9-Pixel5-01" alt="Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5" src="https://cdn.mos.cms.futurecdn.net/Su4KjbbvHMUJPbJL3EjFJV-1920-80.jpg" mos="" align="middle" fullscreen="" width="4182" height="2353" 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 Samsung Galaxy Watch 9 may be the most affordable of its 2026 Android smartwatch class, but the Google Pixel Watch 5 wins prom king by a 2:1 margin versus the Galaxy Watch Ultra 2 and a 3:1 margin against the Samsung Galaxy Watch 9. </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/we-asked-toms-guide-readers-which-fitness-tracking-metrics-do-you-trust-the-least-heres-the-surprising-answer"><strong>We asked Tom's Guide readers, 'Which fitness tracking metrics do you trust the least?' Here's the surprising answer</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/can-the-usd99-fitbit-air-beat-the-usd799-apple-watch-ultra-3-at-fitness-tracking-i-manually-counted-4-500-steps-to-find-out"><strong>Can the $99 Fitbit Air beat the $799 Apple Watch Ultra 3 at fitness tracking? I manually counted 4,500 steps to find out</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/ive-tested-over-100-fitness-trackers-head-to-head-3-workout-stats-i-trust-the-least"><strong>I’ve tested over 100 fitness trackers head-to-head — 3 workout stats I trust the least</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I wore the Samsung Galaxy Watch 9 for a month — the new health tools impress, but that doesn’t mean you should upgrade ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I've been wearing the latest Samsung Galaxy Watch 9 for over a month — collectively, the TG fitness team has been <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-training-with-the-galaxy-watch-9-for-a-month-3-things-i-like-and-3-i-dont">wearing it even longer</a> than that — and it's ultimately a very minor upgrade over 2025's <a href="https://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-8-reviewhttps://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-8-review">Galaxy Watch 8.</a></p><p>The design, display, and battery life all remain unchanged, but the Galaxy Watch 9 supports a handful of useful new features, a slightly faster processor, and a comfier strap. It also costs more than its predecessor.</p><p>Here's everything you need to know about the Samsung Galaxy Watch 9.</p><h3 class="article-body__section" id="section-galaxy-watch-9-cheat-sheet"><span>Galaxy Watch 9 cheat sheet</span></h3><ul><li><strong>Price: </strong><a href="https://www.samsung.com/us/watches/galaxy-watch9/buy/galaxy-watch9-40mm-graphite-bluetooth-sku-sm-l340nzkaxaa/" target="_blank" rel="nofollow">$379 for 40mm</a> (no LTE) or <a href="https://www.samsung.com/us/watches/galaxy-watch9/buy/galaxy-watch9-44mm-graphite-bluetooth-sku-sm-l350nzkaxaa/" target="_blank" rel="nofollow">$409 for 44mm</a> (no LTE); add $50 to either for cellular</li><li><strong>Design: </strong>Same design and size options as Galaxy Watch 8; 40mm is available in Cream or Graphite; 44mm comes in Graphite or Silver</li><li><strong>'Classic' model</strong>: Samsung did not announce a Galaxy Watch 9 Classic with a clicky bezel</li><li><strong>Screen: </strong>Same max brightness, 3,000 nits, as Galaxy Watch 8</li><li><strong>Health features:</strong> New 'Vitals' dashboard with key metrics including heart rate, HRV, Sp02, body temp, and breath rate in one place; new 'Heart Health' score</li><li><strong>Fitness features:</strong> New 'Cardio Load' insights, new 'Fitness Index' score out of 100 and based on factors like daily step count average, V02 Max, average heart rate, BIA (Bioelectrical Impedance Analysis), and average workout recovery time</li><li><strong>Battery life: </strong>Slight increase in battery capacity, but battery life remains unchanged from the Galaxy Watch 8: 30 hours for the 40mm model and 40 hours for the 44mm</li></ul><h3 class="article-body__section" id="section-galaxy-watch-9-versus-the-competition"><span>Galaxy Watch 9: Versus the competition</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:4182px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="Su4KjbbvHMUJPbJL3EjFJV" name="Galaxy9-Pixel5-01" alt="Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5" src="https://cdn.mos.cms.futurecdn.net/Su4KjbbvHMUJPbJL3EjFJV-1920-80.jpg" mos="" align="middle" fullscreen="" width="4182" height="2353" 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><div ><table><caption>Samsung Galaxy Watch 9 specs</caption><thead><tr><th class="firstcol empty" ></th><th  ><p>Samsung Galaxy Watch 9</p></th><th  ><p>Samsung Galaxy Watch 8</p></th><th  ><p>Samsung Galaxy Watch Ultra 2</p></th><th  ><p>Pixel Watch 5</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$379</p></td><td  ><p>$349</p></td><td  ><p>$699</p></td><td  ><p>$399</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>42.7 x 40.4 x 8.6mm /<br>46.0 x 43.7 x 8.6 mm</p></td><td  ><p>42.7 x 40.4 x 8.6mm /<br>46.0 x 43.7 x 8.6 mm</p></td><td  ><p>47 x 47 x 10 mm </p></td><td  ><p>41 x 41 x 12.3 mm /<br>45 x 45 x 12.3 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>31.5 g / 34 g</p></td><td  ><p>30 g / 34 g</p></td><td  ><p>61.5 g</p></td><td  ><p>31 g / 36.7 g</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>1.34-inch / 1.47-inch; 3,000 nits max brightness</p></td><td  ><p>1.34-inch / 1.47-inch; 3,000 nits max brightness</p></td><td  ><p>1.52-inch AMOLED, 5,000 nits max brightness </p></td><td  ><p>1.2-inch, 1.4-inch AMOLED; 3,000 nits max brightness</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>50 meters</p></td><td  ><p>50 meters</p></td><td  ><p>100 meters</p></td><td  ><p>50 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery capacity</strong></p></td><td  ><p>40mm: 390mAh / 44mm: 445mAh</p></td><td  ><p>40mm: 325mAh / 44mm: 435mAh</p></td><td  ><p>800 mAh</p></td><td  ><p>41mm: 332mAh / <br>45mm: 465 mAh</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-value-3-5-5"><span>Samsung Galaxy Watch 9 value: 3.5/5</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:5322px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="ryz4WsgNuzbFG2wC9R8VKk" name="GalaxyWatch9-03" alt="Close-up of the Samsung Galaxy Watch 9 in white" src="https://cdn.mos.cms.futurecdn.net/ryz4WsgNuzbFG2wC9R8VKk-1920-80.jpg" mos="" align="middle" fullscreen="" width="5322" height="2994" 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 Samsung Galaxy Watch 9 was announced on July 22, 2026. It is available worldwide now.</p><p>When Samsung announced the Galaxy Watch 8 this time last year, I wasn't surprised to see a $50 price increase across the board compared to the <a href="https://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-7-review">Galaxy Watch 7</a>. However, I was surprised to see Samsung raise the price of the Watch 9 this time around.</p><p>The 40mm Galaxy Watch 9, for example, <a href="https://www.samsung.com/us/watches/galaxy-watch9/buy/galaxy-watch9-40mm-graphite-bluetooth-sku-sm-l340nzkaxaa/" target="_blank" rel="nofollow">starts at $379</a> without LTE, compared to $349 for the Galaxy Watch 8 equivalent. The 44mm Galaxy Watch 9, meanwhile, is $409 versus $379 for last year's equivalent. </p><p>Fortunately for Samsung (and Samsung alone), Google also raised prices across the <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review" target="_blank">Google Pixel Watch 5</a> lineup, which means the Galaxy Watch 9 is technically the most wallet-friendly 2026 full-featured smartwatch for Android (by $20). </p><ul><li><strong>Galaxy Watch 9 (Bluetooth, 40mm): $379</strong></li><li><strong>Galaxy Watch 9 (LTE, 40mm): $429</strong></li><li><strong>Galaxy Watch 9 (Bluetooth, 44mm): $409</strong></li><li><strong>Galaxy Watch 9 (LTE, 44mm): $459</strong></li></ul><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-design-and-display-3-5-5"><span>Samsung Galaxy Watch 9 design and display: 3.5/5 </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:5294px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="u4bJvYVtRRHJ63QdqboeXM" name="GalaxyWatch9-design" alt="Close-up of the Samsung Galaxy Watch 9 on a user's wrist" src="https://cdn.mos.cms.futurecdn.net/u4bJvYVtRRHJ63QdqboeXM-1920-80.jpg" mos="" align="middle" fullscreen="" width="5294" height="2977" 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>While Samsung made all sorts of under-the-hood upgrades to the Galaxy Watch 9, including a new processor and increased battery capacity, the outward appearance remains unchanged from its predecessor.</p><p>The physical dimensions and the weight are also essentially the same, as is the 50-meter water resistance rating. Finally, the Galaxy Watch 9 also boasts the same 3,000-nit max brightness display and twin-button design as the Galaxy Watch 8.</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="JN2bbBaBoTPrpbhNd9WPLj" name="GalaxyWatch8-rev-19" alt="Close-up of the Samsung Galaxy Watch Classic on a user's wrist with the Gemini AI app open" src="https://cdn.mos.cms.futurecdn.net/JN2bbBaBoTPrpbhNd9WPLj-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: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>I was a big fan of the Samsung Galaxy Watch 8 Classic (see image above), which sports a bidirectional clicky bezel for navigation and an additional customizable button compared to the standard Galaxy Watch 8 models.</p><p>Unfortunately, there is no Samsung Galaxy Watch 9 Classic. That said, Samsung has confirmed that the Galaxy Watch 8 Classic will remain in the brand's lineup for the time being. </p><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-wellness-tools-4-5-5"><span>Samsung Galaxy Watch 9 wellness tools: 4.5/5</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:4889px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9VYZkwkFKGrzUBK9zzEc3k" name="GalaxyWatch9-02" alt="Close-up of the Samsung Galaxy Watch 9 in white" src="https://cdn.mos.cms.futurecdn.net/9VYZkwkFKGrzUBK9zzEc3k-1920-80.jpg" mos="" align="middle" fullscreen="" width="4889" height="2750" 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>Samsung already offers an impressive suite of completely free wellness tracking insights, and they only get better with the Galaxy Watch 9. Better yet, important health info is now more visible in the companion app thanks to a new "Vitals" tab. There's additionally a greater focus on long-term trend reports and preventive health.</p><p>The newly introduced Vitals dashboard in the Health app brings your most important wellness metrics into one easy-to-view panel. It displays your current heart rate, heart rate variability (HRV), blood oxygen saturation percentage (Sp02), body temperature, and breath rate.</p><p>To keep you looped into your cardiovascular well-being, the Galaxy Watch 9 boasts a new Heart Health score based on a scale from one to 100. You'll need to wear the device for at least four consecutive nights to generate your initial score. Ultimately, what makes this tool valuable is its long-term insights, which can clue you in to how your day-to-day choices may be impacting your heart health for better or worse. </p><p>Note: As of writing, Samsung's Heart Health score is exclusive to the latest 2026 models.</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:4996px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="qkNNwr3UPRR6b8yK94DdDk" name="GalaxyWatch9-01" alt="Close-up of the Samsung Galaxy Watch 9 on a user's wrist against a blue background" src="https://cdn.mos.cms.futurecdn.net/qkNNwr3UPRR6b8yK94DdDk-1920-80.jpg" mos="" align="middle" fullscreen="" width="4996" height="2810" 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>When it comes to sleep tracking, not much has changed from the Galaxy Watch 8. Users are still presented with a daily sleep score and energy score, both out of 100, along with a breakdown of time spent in each of the various sleep cycles, total time spent asleep, sleep disturbances, the consistency of your bedtime, and more.</p><p>I wore both the Samsung <a href="https://www.tomsguide.com/wellness/smartwatches/pixel-watch-5-vs-samsung-galaxy-watch-9-5-key-differences-you-need-to-know">Galaxy Watch 9 and Google Pixel Watch 5</a> to bed for a week and discovered that both of these flagship Android smartwatches calculated surprisingly similar sleep data. </p><p>Finally, one major advantage the Samsung Galaxy Watch 9 has over the Google Pixel Watch 5 is an FDA-cleared sleep apnea detection feature. On the flip side, the newest Galaxy Watch lacks some of the heady health safety tools found on the latest Pixel Watch, like <a href="https://www.tomsguide.com/wellness/smartwatches/exclusive-google-pm-says-the-pixel-watch-5-is-like-an-airbag-on-your-wrist-thanks-to-features-like-breathing-emergency-detection">Breathing Emergency Detection</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/google-exclusive-how-the-pixel-watch-3-got-a-life-saving-feature-the-apple-watch-cant-match">Loss of Pulse Detection</a>.</p><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-fitness-tracking-4-5"><span>Samsung Galaxy Watch 9 fitness tracking: 4/5 </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:4834px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kuTYfGbyRcRugdWr8FJdqf" name="Galaxy9-v-Instinct3-02" alt="Close-up of the Garmin Instinct 3 next to the Samsung Galaxy Watch 9 with evergreens in the background" src="https://cdn.mos.cms.futurecdn.net/kuTYfGbyRcRugdWr8FJdqf-1920-80.jpg" mos="" align="middle" fullscreen="" width="4834" height="2719" 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 Samsung Galaxy Watch 9 is a fairly reliable fitness tracker for both indoor and outdoor workouts. When I tested it <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-walked-4-000-steps-with-the-pixel-watch-5-vs-samsung-galaxy-watch-9-and-we-have-a-new-android-champ">against the Pixel Watch 5</a>, the Google smartwatch proved slightly more precise, but the Galaxy Watch 9's performance wasn't far behind. </p><p>I also pitted the Galaxy Watch 9 <a href="https://www.tomsguide.com/wellness/smartwatches/i-hiked-7-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-9-and-the-winner-is-clear-as-day">against the Garmin Instinct 3</a>, my go-to smartwatch for logging outdoor adventures, and a model that costs roughly the same. During my seven-mile hike, the Samsung watch again performed pretty well, but ultimately struggled to accurately log my climb.</p><p>The Galaxy Watch 9 also lacks some of the more common workout tracking modes offered by the competition, like e-biking and skateboarding (two of my faves). That said, the auto workout tracking feature works quite well, a finding my colleague <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-training-with-the-galaxy-watch-9-for-a-month-3-things-i-like-and-3-i-dont">Sam also found impressive</a>.</p><p>The new Galaxy Watch also boasts several new fitness-focused metrics, including Cardio Load and a Fitness Index score. While Cardio Load will be supported by older Galaxy Watch models, the Fitness Index Score is, for now, exclusive to the Galaxy Watch 9 and <a href="https://www.tomsguide.com/wellness/smartwatches/galaxy-watch-ultra-2-hands-on-review">Galaxy Watch Ultra 2</a>.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5408px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="r8eU5UpsMnb4H9VFcKFJiV" name="Galaxy9-Pixel5-04" alt="Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5" src="https://cdn.mos.cms.futurecdn.net/r8eU5UpsMnb4H9VFcKFJiV-1920-80.jpg" mos="" align="middle" fullscreen="" width="5408" height="3042" 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>Based on factors like daily step count average, V02 Max, average heart rate, BIA (Bioelectrical Impedance Analysis), and average workout recovery time, the Fitness Index score is on a scale from zero to 100. </p><p>As of writing, mine is an 82, or "average." The Health app further breaks that score down into five individual categories, each with its own score: Body Composition, Cardio, Endurance, Strength, and Flexibility. These scores, along with the overall Fitness Index score, are calculated by comparing your fitness levels to other users in your age range.</p><p>For example, from my score breakdown, I can glean that my endurance is solid (rated 93/100) while my overall strength could use attention (rated 63/100).</p><p>For high-cardio athletes, the new Cardio Load metric is designed to help you train more effectively. It takes seven days to fully calibrate, i.e., establish a baseline for your maximum training capacity. Once complete, users get a daily cardio intensity rating ranging from "under target" to "over." This rating is calculated by analyzing how much time you spent doing activities that pushed your heart rate into Zone 3 or higher. </p><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-ai-features-3-5"><span>Samsung Galaxy Watch 9 AI features: 3/5</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:4384px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bAoGSNWdD3TukFKtx2DHpA" name="GalaxyWatch9-raise" alt="Close-up of the Samsung Galaxy Watch 9 on a user's wrist showing the gesture control options" src="https://cdn.mos.cms.futurecdn.net/bAoGSNWdD3TukFKtx2DHpA-1920-80.jpg" mos="" align="middle" fullscreen="" width="4384" height="2466" 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 Samsung Galaxy Watch 9 ships with Google's Gemini AI voice assistant built in, and it's easily the best smartwatch personal assistant I've tested. Even better, the Galaxy Watch 9 now supports a wrist raise gesture control to unlock Gemini, something first introduced in last year's <a href="https://www.tomsguide.com/wellness/smartwatches/i-just-went-hands-on-with-google-pixel-watch-4-and-it-could-be-my-new-favorite-smartwatch-for-android">Pixel Watch 4</a>.</p><p>As of writing, the Galaxy Watch 9 and Galaxy Watch Ultra 2 are the only two Samsung models that support using Raise to talk to unlock Gemini. </p><p>In terms of usefulness, Samsung's Google AI assistant does a reasonably good job answering random, hyper-specific questions like, "How many adult penguins can I fit in a 1995 Ford Taurus?"</p><p>It's also good at context-specific tasks. For example, Gemini was helpful when I was searching for new restaurants within walking distance of my house to order for dinner. The Gemini AI assistant additionally correctly named the opening acts and start time for an upcoming concert I was seeing (The Strokes). </p><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-battery-life-3-5"><span>Samsung Galaxy Watch 9 battery life: 3/5</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:4874px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="XLQGGRLwUHbnZNMdPut7Aj" name="GalaxyWatch9-05" alt="Close-up of the Samsung Galaxy Watch 9 in white" src="https://cdn.mos.cms.futurecdn.net/XLQGGRLwUHbnZNMdPut7Aj-1920-80.jpg" mos="" align="middle" fullscreen="" width="4874" height="2742" 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>Both the 40mm and 44mm Samsung Galaxy Watch 9 models see tiny battery capacity increases. The smaller model jumps from 325 mAh for the Galaxy Watch 8 to 390 mAh for the Galaxy Watch 9. The bigger model has increased from 435 mAh on the Galaxy Watch 8 to 445 mAh for the Galaxy Watch 9.</p><p>Unfortunately, these bigger batteries don't result in any tangible longevity improvements. The 40mm is still rated at 30 hours per charge, and the 44mm is still rated at 40 hours per charge, just like last year's model.</p><p>In real-world use,  the 40mm Galaxy Watch 9 averaged about 32 hours of use per charge. That's behind the Pixel Watch 5, which averages closer to 48 hours of use per charge in my testing. </p><p>The Galaxy Watch 9 also recharges a little slower than its Google rival. Again, testing the smaller model, a full recharge took about 90 minutes for the Galaxy Watch 9, compared to closer to 60 minutes for the Pixel Watch 5.</p><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-verdict"><span>Samsung Galaxy Watch 9: Verdict</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5053px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="hM7Qvm7gLY6iCvAnLrV5tU" name="Galaxy9-Pixel5-03" alt="Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5" src="https://cdn.mos.cms.futurecdn.net/hM7Qvm7gLY6iCvAnLrV5tU-1920-80.jpg" mos="" align="middle" fullscreen="" width="5053" height="2842" 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 Samsung Galaxy Watch 9 is easily one of the <a href="https://www.tomsguide.com/best-picks/best-smartwatches-android">best smartwatches</a> for Android, but that doesn't mean you should buy one, especially if you already own the Galaxy Watch 8. Aside from a faster processor, a softer strap, and a couple of exclusive health metrics, the Galaxy Watch 9 is pretty much the same as the Galaxy Watch 8, just pricier.</p><p>It does support a handy new (for Samsung) raise-wrist gesture for unlocking the excellent onboard Gemini AI assistant. However, battery life remains unchanged compared to its predecessor. More notably, the Galaxy Watch 9 doesn't last as long per charge as its biggest rival, the Google Pixel Watch 5. It also lacks the Pixel Watch's impressive suite of safety tools.</p><p>That said, Samsung, unlike Google and Garmin, provides all of its wellness and fitness insights without forcing you to pony up for a monthly/annual subscription. That I like.</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/smartwatches/im-a-smartwatch-reviewer-and-heres-my-apple-watch-series-12-wish-list-three-upgrades-i-want-and-one-i-dont"><strong>I'm a smartwatch reviewer, and here's my Apple Watch Series 12 wish list — three upgrades I want, and one I don't</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/leaked-apple-watch-12-design-change-is-the-opposite-of-an-upgrade-and-that-has-me-worried"><strong>Leaked Apple Watch 12 design change is the opposite of an upgrade — and that has me worried</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-ultra-2-needs-these-3-upgrades-to-convince-me-to-switch-from-my-apple-watch-ultra-3"><strong>Samsung Galaxy Watch Ultra 2 needs these 3 upgrades to convince me to switch from my Apple Watch Ultra 3</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/i-wore-the-samsung-galaxy-watch-9-for-a-month-the-new-health-tools-impress-but-that-doesnt-mean-you-should-upgrade</link>
                                                                            <description>
                            <![CDATA[ The Galaxy Watch 9 looks exactly like the Galaxy Watch 8, but don't let that fool you. Samsung went ahead and added some useful new health, fitness, and AI features. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">CdpNZobMQf2DrJxJePdUYJ</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/ZfFbLbSaYpGwerPZTYP73j-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 30 Aug 2026 05:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/ZfFbLbSaYpGwerPZTYP73j-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Samsung Galaxy Watch 9 in white]]></media:description>                                                            <media:text><![CDATA[Close-up of the Samsung Galaxy Watch 9 in white]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Samsung Galaxy Watch 9 in white]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/ZfFbLbSaYpGwerPZTYP73j-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I've been wearing the latest Samsung Galaxy Watch 9 for over a month — collectively, the TG fitness team has been <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-training-with-the-galaxy-watch-9-for-a-month-3-things-i-like-and-3-i-dont">wearing it even longer</a> than that — and it's ultimately a very minor upgrade over 2025's <a href="https://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-8-reviewhttps://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-8-review">Galaxy Watch 8.</a></p><p>The design, display, and battery life all remain unchanged, but the Galaxy Watch 9 supports a handful of useful new features, a slightly faster processor, and a comfier strap. It also costs more than its predecessor.</p><p>Here's everything you need to know about the Samsung Galaxy Watch 9.</p><h3 class="article-body__section" id="section-galaxy-watch-9-cheat-sheet"><span>Galaxy Watch 9 cheat sheet</span></h3><ul><li><strong>Price: </strong><a href="https://www.samsung.com/us/watches/galaxy-watch9/buy/galaxy-watch9-40mm-graphite-bluetooth-sku-sm-l340nzkaxaa/" target="_blank" rel="nofollow">$379 for 40mm</a> (no LTE) or <a href="https://www.samsung.com/us/watches/galaxy-watch9/buy/galaxy-watch9-44mm-graphite-bluetooth-sku-sm-l350nzkaxaa/" target="_blank" rel="nofollow">$409 for 44mm</a> (no LTE); add $50 to either for cellular</li><li><strong>Design: </strong>Same design and size options as Galaxy Watch 8; 40mm is available in Cream or Graphite; 44mm comes in Graphite or Silver</li><li><strong>'Classic' model</strong>: Samsung did not announce a Galaxy Watch 9 Classic with a clicky bezel</li><li><strong>Screen: </strong>Same max brightness, 3,000 nits, as Galaxy Watch 8</li><li><strong>Health features:</strong> New 'Vitals' dashboard with key metrics including heart rate, HRV, Sp02, body temp, and breath rate in one place; new 'Heart Health' score</li><li><strong>Fitness features:</strong> New 'Cardio Load' insights, new 'Fitness Index' score out of 100 and based on factors like daily step count average, V02 Max, average heart rate, BIA (Bioelectrical Impedance Analysis), and average workout recovery time</li><li><strong>Battery life: </strong>Slight increase in battery capacity, but battery life remains unchanged from the Galaxy Watch 8: 30 hours for the 40mm model and 40 hours for the 44mm</li></ul><h3 class="article-body__section" id="section-galaxy-watch-9-versus-the-competition"><span>Galaxy Watch 9: Versus the competition</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:4182px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="Su4KjbbvHMUJPbJL3EjFJV" name="Galaxy9-Pixel5-01" alt="Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5" src="https://cdn.mos.cms.futurecdn.net/Su4KjbbvHMUJPbJL3EjFJV-1920-80.jpg" mos="" align="middle" fullscreen="" width="4182" height="2353" 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><div ><table><caption>Samsung Galaxy Watch 9 specs</caption><thead><tr><th class="firstcol empty" ></th><th  ><p>Samsung Galaxy Watch 9</p></th><th  ><p>Samsung Galaxy Watch 8</p></th><th  ><p>Samsung Galaxy Watch Ultra 2</p></th><th  ><p>Pixel Watch 5</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$379</p></td><td  ><p>$349</p></td><td  ><p>$699</p></td><td  ><p>$399</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions </strong></p></td><td  ><p>42.7 x 40.4 x 8.6mm /<br>46.0 x 43.7 x 8.6 mm</p></td><td  ><p>42.7 x 40.4 x 8.6mm /<br>46.0 x 43.7 x 8.6 mm</p></td><td  ><p>47 x 47 x 10 mm </p></td><td  ><p>41 x 41 x 12.3 mm /<br>45 x 45 x 12.3 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>31.5 g / 34 g</p></td><td  ><p>30 g / 34 g</p></td><td  ><p>61.5 g</p></td><td  ><p>31 g / 36.7 g</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>1.34-inch / 1.47-inch; 3,000 nits max brightness</p></td><td  ><p>1.34-inch / 1.47-inch; 3,000 nits max brightness</p></td><td  ><p>1.52-inch AMOLED, 5,000 nits max brightness </p></td><td  ><p>1.2-inch, 1.4-inch AMOLED; 3,000 nits max brightness</p></td></tr><tr><td class="firstcol " ><p><strong>Water resistance </strong></p></td><td  ><p>50 meters</p></td><td  ><p>50 meters</p></td><td  ><p>100 meters</p></td><td  ><p>50 meters</p></td></tr><tr><td class="firstcol " ><p><strong>Battery capacity</strong></p></td><td  ><p>40mm: 390mAh / 44mm: 445mAh</p></td><td  ><p>40mm: 325mAh / 44mm: 435mAh</p></td><td  ><p>800 mAh</p></td><td  ><p>41mm: 332mAh / <br>45mm: 465 mAh</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-value-3-5-5"><span>Samsung Galaxy Watch 9 value: 3.5/5</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:5322px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="ryz4WsgNuzbFG2wC9R8VKk" name="GalaxyWatch9-03" alt="Close-up of the Samsung Galaxy Watch 9 in white" src="https://cdn.mos.cms.futurecdn.net/ryz4WsgNuzbFG2wC9R8VKk-1920-80.jpg" mos="" align="middle" fullscreen="" width="5322" height="2994" 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 Samsung Galaxy Watch 9 was announced on July 22, 2026. It is available worldwide now.</p><p>When Samsung announced the Galaxy Watch 8 this time last year, I wasn't surprised to see a $50 price increase across the board compared to the <a href="https://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-7-review">Galaxy Watch 7</a>. However, I was surprised to see Samsung raise the price of the Watch 9 this time around.</p><p>The 40mm Galaxy Watch 9, for example, <a href="https://www.samsung.com/us/watches/galaxy-watch9/buy/galaxy-watch9-40mm-graphite-bluetooth-sku-sm-l340nzkaxaa/" target="_blank" rel="nofollow">starts at $379</a> without LTE, compared to $349 for the Galaxy Watch 8 equivalent. The 44mm Galaxy Watch 9, meanwhile, is $409 versus $379 for last year's equivalent. </p><p>Fortunately for Samsung (and Samsung alone), Google also raised prices across the <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review" target="_blank">Google Pixel Watch 5</a> lineup, which means the Galaxy Watch 9 is technically the most wallet-friendly 2026 full-featured smartwatch for Android (by $20). </p><ul><li><strong>Galaxy Watch 9 (Bluetooth, 40mm): $379</strong></li><li><strong>Galaxy Watch 9 (LTE, 40mm): $429</strong></li><li><strong>Galaxy Watch 9 (Bluetooth, 44mm): $409</strong></li><li><strong>Galaxy Watch 9 (LTE, 44mm): $459</strong></li></ul><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-design-and-display-3-5-5"><span>Samsung Galaxy Watch 9 design and display: 3.5/5 </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:5294px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="u4bJvYVtRRHJ63QdqboeXM" name="GalaxyWatch9-design" alt="Close-up of the Samsung Galaxy Watch 9 on a user's wrist" src="https://cdn.mos.cms.futurecdn.net/u4bJvYVtRRHJ63QdqboeXM-1920-80.jpg" mos="" align="middle" fullscreen="" width="5294" height="2977" 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>While Samsung made all sorts of under-the-hood upgrades to the Galaxy Watch 9, including a new processor and increased battery capacity, the outward appearance remains unchanged from its predecessor.</p><p>The physical dimensions and the weight are also essentially the same, as is the 50-meter water resistance rating. Finally, the Galaxy Watch 9 also boasts the same 3,000-nit max brightness display and twin-button design as the Galaxy Watch 8.</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="JN2bbBaBoTPrpbhNd9WPLj" name="GalaxyWatch8-rev-19" alt="Close-up of the Samsung Galaxy Watch Classic on a user's wrist with the Gemini AI app open" src="https://cdn.mos.cms.futurecdn.net/JN2bbBaBoTPrpbhNd9WPLj-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: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>I was a big fan of the Samsung Galaxy Watch 8 Classic (see image above), which sports a bidirectional clicky bezel for navigation and an additional customizable button compared to the standard Galaxy Watch 8 models.</p><p>Unfortunately, there is no Samsung Galaxy Watch 9 Classic. That said, Samsung has confirmed that the Galaxy Watch 8 Classic will remain in the brand's lineup for the time being. </p><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-wellness-tools-4-5-5"><span>Samsung Galaxy Watch 9 wellness tools: 4.5/5</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:4889px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9VYZkwkFKGrzUBK9zzEc3k" name="GalaxyWatch9-02" alt="Close-up of the Samsung Galaxy Watch 9 in white" src="https://cdn.mos.cms.futurecdn.net/9VYZkwkFKGrzUBK9zzEc3k-1920-80.jpg" mos="" align="middle" fullscreen="" width="4889" height="2750" 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>Samsung already offers an impressive suite of completely free wellness tracking insights, and they only get better with the Galaxy Watch 9. Better yet, important health info is now more visible in the companion app thanks to a new "Vitals" tab. There's additionally a greater focus on long-term trend reports and preventive health.</p><p>The newly introduced Vitals dashboard in the Health app brings your most important wellness metrics into one easy-to-view panel. It displays your current heart rate, heart rate variability (HRV), blood oxygen saturation percentage (Sp02), body temperature, and breath rate.</p><p>To keep you looped into your cardiovascular well-being, the Galaxy Watch 9 boasts a new Heart Health score based on a scale from one to 100. You'll need to wear the device for at least four consecutive nights to generate your initial score. Ultimately, what makes this tool valuable is its long-term insights, which can clue you in to how your day-to-day choices may be impacting your heart health for better or worse. </p><p>Note: As of writing, Samsung's Heart Health score is exclusive to the latest 2026 models.</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:4996px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="qkNNwr3UPRR6b8yK94DdDk" name="GalaxyWatch9-01" alt="Close-up of the Samsung Galaxy Watch 9 on a user's wrist against a blue background" src="https://cdn.mos.cms.futurecdn.net/qkNNwr3UPRR6b8yK94DdDk-1920-80.jpg" mos="" align="middle" fullscreen="" width="4996" height="2810" 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>When it comes to sleep tracking, not much has changed from the Galaxy Watch 8. Users are still presented with a daily sleep score and energy score, both out of 100, along with a breakdown of time spent in each of the various sleep cycles, total time spent asleep, sleep disturbances, the consistency of your bedtime, and more.</p><p>I wore both the Samsung <a href="https://www.tomsguide.com/wellness/smartwatches/pixel-watch-5-vs-samsung-galaxy-watch-9-5-key-differences-you-need-to-know">Galaxy Watch 9 and Google Pixel Watch 5</a> to bed for a week and discovered that both of these flagship Android smartwatches calculated surprisingly similar sleep data. </p><p>Finally, one major advantage the Samsung Galaxy Watch 9 has over the Google Pixel Watch 5 is an FDA-cleared sleep apnea detection feature. On the flip side, the newest Galaxy Watch lacks some of the heady health safety tools found on the latest Pixel Watch, like <a href="https://www.tomsguide.com/wellness/smartwatches/exclusive-google-pm-says-the-pixel-watch-5-is-like-an-airbag-on-your-wrist-thanks-to-features-like-breathing-emergency-detection">Breathing Emergency Detection</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/google-exclusive-how-the-pixel-watch-3-got-a-life-saving-feature-the-apple-watch-cant-match">Loss of Pulse Detection</a>.</p><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-fitness-tracking-4-5"><span>Samsung Galaxy Watch 9 fitness tracking: 4/5 </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:4834px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kuTYfGbyRcRugdWr8FJdqf" name="Galaxy9-v-Instinct3-02" alt="Close-up of the Garmin Instinct 3 next to the Samsung Galaxy Watch 9 with evergreens in the background" src="https://cdn.mos.cms.futurecdn.net/kuTYfGbyRcRugdWr8FJdqf-1920-80.jpg" mos="" align="middle" fullscreen="" width="4834" height="2719" 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 Samsung Galaxy Watch 9 is a fairly reliable fitness tracker for both indoor and outdoor workouts. When I tested it <a href="https://www.tomsguide.com/wellness/fitness-trackers/i-walked-4-000-steps-with-the-pixel-watch-5-vs-samsung-galaxy-watch-9-and-we-have-a-new-android-champ">against the Pixel Watch 5</a>, the Google smartwatch proved slightly more precise, but the Galaxy Watch 9's performance wasn't far behind. </p><p>I also pitted the Galaxy Watch 9 <a href="https://www.tomsguide.com/wellness/smartwatches/i-hiked-7-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-9-and-the-winner-is-clear-as-day">against the Garmin Instinct 3</a>, my go-to smartwatch for logging outdoor adventures, and a model that costs roughly the same. During my seven-mile hike, the Samsung watch again performed pretty well, but ultimately struggled to accurately log my climb.</p><p>The Galaxy Watch 9 also lacks some of the more common workout tracking modes offered by the competition, like e-biking and skateboarding (two of my faves). That said, the auto workout tracking feature works quite well, a finding my colleague <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-training-with-the-galaxy-watch-9-for-a-month-3-things-i-like-and-3-i-dont">Sam also found impressive</a>.</p><p>The new Galaxy Watch also boasts several new fitness-focused metrics, including Cardio Load and a Fitness Index score. While Cardio Load will be supported by older Galaxy Watch models, the Fitness Index Score is, for now, exclusive to the Galaxy Watch 9 and <a href="https://www.tomsguide.com/wellness/smartwatches/galaxy-watch-ultra-2-hands-on-review">Galaxy Watch Ultra 2</a>.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5408px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="r8eU5UpsMnb4H9VFcKFJiV" name="Galaxy9-Pixel5-04" alt="Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5" src="https://cdn.mos.cms.futurecdn.net/r8eU5UpsMnb4H9VFcKFJiV-1920-80.jpg" mos="" align="middle" fullscreen="" width="5408" height="3042" 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>Based on factors like daily step count average, V02 Max, average heart rate, BIA (Bioelectrical Impedance Analysis), and average workout recovery time, the Fitness Index score is on a scale from zero to 100. </p><p>As of writing, mine is an 82, or "average." The Health app further breaks that score down into five individual categories, each with its own score: Body Composition, Cardio, Endurance, Strength, and Flexibility. These scores, along with the overall Fitness Index score, are calculated by comparing your fitness levels to other users in your age range.</p><p>For example, from my score breakdown, I can glean that my endurance is solid (rated 93/100) while my overall strength could use attention (rated 63/100).</p><p>For high-cardio athletes, the new Cardio Load metric is designed to help you train more effectively. It takes seven days to fully calibrate, i.e., establish a baseline for your maximum training capacity. Once complete, users get a daily cardio intensity rating ranging from "under target" to "over." This rating is calculated by analyzing how much time you spent doing activities that pushed your heart rate into Zone 3 or higher. </p><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-ai-features-3-5"><span>Samsung Galaxy Watch 9 AI features: 3/5</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:4384px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bAoGSNWdD3TukFKtx2DHpA" name="GalaxyWatch9-raise" alt="Close-up of the Samsung Galaxy Watch 9 on a user's wrist showing the gesture control options" src="https://cdn.mos.cms.futurecdn.net/bAoGSNWdD3TukFKtx2DHpA-1920-80.jpg" mos="" align="middle" fullscreen="" width="4384" height="2466" 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 Samsung Galaxy Watch 9 ships with Google's Gemini AI voice assistant built in, and it's easily the best smartwatch personal assistant I've tested. Even better, the Galaxy Watch 9 now supports a wrist raise gesture control to unlock Gemini, something first introduced in last year's <a href="https://www.tomsguide.com/wellness/smartwatches/i-just-went-hands-on-with-google-pixel-watch-4-and-it-could-be-my-new-favorite-smartwatch-for-android">Pixel Watch 4</a>.</p><p>As of writing, the Galaxy Watch 9 and Galaxy Watch Ultra 2 are the only two Samsung models that support using Raise to talk to unlock Gemini. </p><p>In terms of usefulness, Samsung's Google AI assistant does a reasonably good job answering random, hyper-specific questions like, "How many adult penguins can I fit in a 1995 Ford Taurus?"</p><p>It's also good at context-specific tasks. For example, Gemini was helpful when I was searching for new restaurants within walking distance of my house to order for dinner. The Gemini AI assistant additionally correctly named the opening acts and start time for an upcoming concert I was seeing (The Strokes). </p><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-battery-life-3-5"><span>Samsung Galaxy Watch 9 battery life: 3/5</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:4874px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="XLQGGRLwUHbnZNMdPut7Aj" name="GalaxyWatch9-05" alt="Close-up of the Samsung Galaxy Watch 9 in white" src="https://cdn.mos.cms.futurecdn.net/XLQGGRLwUHbnZNMdPut7Aj-1920-80.jpg" mos="" align="middle" fullscreen="" width="4874" height="2742" 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>Both the 40mm and 44mm Samsung Galaxy Watch 9 models see tiny battery capacity increases. The smaller model jumps from 325 mAh for the Galaxy Watch 8 to 390 mAh for the Galaxy Watch 9. The bigger model has increased from 435 mAh on the Galaxy Watch 8 to 445 mAh for the Galaxy Watch 9.</p><p>Unfortunately, these bigger batteries don't result in any tangible longevity improvements. The 40mm is still rated at 30 hours per charge, and the 44mm is still rated at 40 hours per charge, just like last year's model.</p><p>In real-world use,  the 40mm Galaxy Watch 9 averaged about 32 hours of use per charge. That's behind the Pixel Watch 5, which averages closer to 48 hours of use per charge in my testing. </p><p>The Galaxy Watch 9 also recharges a little slower than its Google rival. Again, testing the smaller model, a full recharge took about 90 minutes for the Galaxy Watch 9, compared to closer to 60 minutes for the Pixel Watch 5.</p><h3 class="article-body__section" id="section-samsung-galaxy-watch-9-verdict"><span>Samsung Galaxy Watch 9: Verdict</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5053px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="hM7Qvm7gLY6iCvAnLrV5tU" name="Galaxy9-Pixel5-03" alt="Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5" src="https://cdn.mos.cms.futurecdn.net/hM7Qvm7gLY6iCvAnLrV5tU-1920-80.jpg" mos="" align="middle" fullscreen="" width="5053" height="2842" 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 Samsung Galaxy Watch 9 is easily one of the <a href="https://www.tomsguide.com/best-picks/best-smartwatches-android">best smartwatches</a> for Android, but that doesn't mean you should buy one, especially if you already own the Galaxy Watch 8. Aside from a faster processor, a softer strap, and a couple of exclusive health metrics, the Galaxy Watch 9 is pretty much the same as the Galaxy Watch 8, just pricier.</p><p>It does support a handy new (for Samsung) raise-wrist gesture for unlocking the excellent onboard Gemini AI assistant. However, battery life remains unchanged compared to its predecessor. More notably, the Galaxy Watch 9 doesn't last as long per charge as its biggest rival, the Google Pixel Watch 5. It also lacks the Pixel Watch's impressive suite of safety tools.</p><p>That said, Samsung, unlike Google and Garmin, provides all of its wellness and fitness insights without forcing you to pony up for a monthly/annual subscription. That I like.</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/smartwatches/im-a-smartwatch-reviewer-and-heres-my-apple-watch-series-12-wish-list-three-upgrades-i-want-and-one-i-dont"><strong>I'm a smartwatch reviewer, and here's my Apple Watch Series 12 wish list — three upgrades I want, and one I don't</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/leaked-apple-watch-12-design-change-is-the-opposite-of-an-upgrade-and-that-has-me-worried"><strong>Leaked Apple Watch 12 design change is the opposite of an upgrade — and that has me worried</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smartwatches/samsung-galaxy-watch-ultra-2-needs-these-3-upgrades-to-convince-me-to-switch-from-my-apple-watch-ultra-3"><strong>Samsung Galaxy Watch Ultra 2 needs these 3 upgrades to convince me to switch from my Apple Watch Ultra 3</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Your fitness tracker has a lot of numbers — these are the ones that are worth watching ]]></title>
                                                                                                <dc:content><![CDATA[ <p>As <a href="https://www.tomsguide.com/us/best-fitness-trackers,review-2066.html">fitness trackers</a> like the <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">Fitbit Air</a> become better and better, they are now remarkably good at finding new things to measure. </p><p>Open the companion app after a workout or a night’s sleep and you'll be greeted by a dizzying array of stats: steps, heart rate, HRV, sleep stages, VO2 max, calories burned, and many more besides. </p><p>Some of that information is genuinely useful, but a lot of it is better treated as (interesting) background noise.</p><p>The trick is knowing which numbers can tell you something meaningful about your activity or recovery — and, just as importantly, which ones you can actually do something with. </p><p>For most of us, though, that leaves a much shorter list than the dashboard might suggest.</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:2826px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="gzvMQLs88dSzLa7Pe9Y2KE" name="Oura Ring 5" alt="photos of the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/gzvMQLs88dSzLa7Pe9Y2KE-1920-80.jpg" mos="" align="middle" fullscreen="" width="2826" height="1590" 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><h2 id="steps-still-matter">Steps still matter</h2><p>With all the newer metrics available, step count can feel almost quaint, but it remains one of the most useful numbers going, simply because it offers a clear picture of how much you’re moving during the day.</p><p>There’s no need to treat 10,000 steps as a magic target, either. <a href="https://www.sciencedirect.com/science/article/pii/S0091743524002020" target="_blank" rel="nofollow">Research suggests</a> health benefits begin well below that figure, with more movement generally bringing greater benefits.</p><p>Your own baseline is the best place to start. If you typically manage, say, 4,000 steps per day, regularly getting closer to 6,000 is meaningful progress.</p><p>Step counting is also one of the things fitness trackers do reasonably well. It won’t tell you how hard you exercised, which we’ll come to next, but it’s an easy way to spot whether a desk-heavy week has turned into a sedentary one.</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:5020px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="zCBBhA82yv8MGUKAmpHWt5" name="Fitbit-Air-lead" alt="Close-up of the sensors on the Fitbit Air" src="https://cdn.mos.cms.futurecdn.net/zCBBhA82yv8MGUKAmpHWt5-1920-80.jpg" mos="" align="middle" fullscreen="" width="5020" height="2824" 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><h2 id="track-how-hard-you-re-moving">Track how hard you’re moving</h2><p>Step count tells you how much you’ve moved, but it says little about intensity. A brisk walk can add the same number of steps as a much slower one while placing very different demands on your body.</p><p>Active minutes help fill in that gap. Most trackers estimate how much time you spend at moderate or vigorous intensity, giving you a clearer sense of whether your week includes enough purposeful exercise alongside general movement.</p><p>For reference, the World Health Organization <a href="https://www.who.int/publications/i/item/9789240015128" target="_blank" rel="nofollow">recommends</a> at least 150 minutes of moderate-intensity aerobic activity each week — or 75 minutes at vigorous intensity — with more activity bringing additional benefits.</p><p>Heart rate zones can also be useful during individual workouts, giving you a quick way to check whether an easy session stayed easy. </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:4626px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Ff9hx8JnRhaSc9bAGZ5AMn" name="IMG_0934-2" alt="Fitbit Air, Whoop MG and Garmin Cirqa" src="https://cdn.mos.cms.futurecdn.net/Ff9hx8JnRhaSc9bAGZ5AMn-1920-80.jpg" mos="" align="middle" fullscreen="" width="4626" height="2602" 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><h2 id="watch-your-resting-heart-rate-and-hrv">Watch your resting heart rate and HRV</h2><p>Resting heart rate is one of the simpler recovery metrics to understand, showing how many times your heart beats per minute when you’re at rest. Regular aerobic training can gradually bring that number down over time.</p><p>Where fitness trackers excel is showing you the <em>trend</em>. A sudden rise above your usual range can sometimes line up with poor recovery or an illness, while a gradual decline can be a sign that your cardiovascular fitness is improving.</p><p>Heart rate variability, or HRV, adds more context by measuring the variation in time between heartbeats and can be useful for spotting changes in recovery. It's worth noting that HRV is highly individual, so try not to compare scores. </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="rZtWweMfmTbWFc3A7cEKNN" name="Sleep Trackers Oura Ring 4" alt="Our sleep tech tester testing the silver Oura Ring 4 in bed with white bedsheets and a rattan headboard" src="https://cdn.mos.cms.futurecdn.net/rZtWweMfmTbWFc3A7cEKNN-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><h2 id="focus-on-better-sleep-not-a-better-sleep-score">Focus on better sleep, not a better sleep score</h2><p>Sleep tracking is most useful when you keep it simple: start with how long you’re actually sleeping and whether your bedtime and wake-up time are reasonably consistent from one day to the next.</p><p>Those numbers are easier to interpret than the detailed breakdowns many trackers now provide. Consumer wearables estimate sleep stages from signals such as movement and heart rate, so it’s worth being cautious about treating every minute of deep or REM sleep as exact.</p><p>The same goes for proprietary sleep scores; they can be handy as a quick summary, but the underlying habits are usually more useful to watch over time.</p><p>I've sometimes found that a low sleep score can trick my brain into thinking I had a bad sleep, which then makes me feel worse, whereas a similar sleep without a tracker leaves me feeling well-rested. Too much information can, in some cases, be a bad thing. </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="sppVH3W74zvzBJtaGywaRZ" name="Xiaomi Smart Band 10" alt="Xiaomi Smart Band 10 in Ceramic Pearl White" src="https://cdn.mos.cms.futurecdn.net/sppVH3W74zvzBJtaGywaRZ-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><h2 id="use-vo2-max-to-track-the-bigger-picture">Use VO2 max to track the bigger picture</h2><p>VO2 max gives you an estimate of how effectively your body can use oxygen during exercise, which makes it a useful shorthand for aerobic fitness.</p><p>Most watches calculate it from workout data rather than measuring it directly, so the figure on your wrist won’t be as precise as a laboratory test.</p><p>That doesn’t make it useless. If you keep using the same device, the direction of travel can still tell you plenty. For example, a VO2 max score rising over several months indicates improving aerobic fitness. </p><p>It’s another metric where the trend is more valuable than the exact number. Whether your watch says 45 or 47 matters less than where that figure is heading over time. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:9254px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="JpSXwAkfnPAtMwt3ZYMFrR" name="Fitbit-Air-07" alt="Close-up of the Fitbit Air fitness tracker" src="https://cdn.mos.cms.futurecdn.net/JpSXwAkfnPAtMwt3ZYMFrR-1920-80.jpg" mos="" align="middle" fullscreen="" width="9254" height="5205" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Google)</span></figcaption></figure><h2 id="the-numbers-you-can-mostly-ignore">The numbers you can mostly ignore</h2><p>Plenty of other fitness tracker stats can still be interesting, but they don’t all deserve the same attention. </p><p>Calories burned are a good example: estimates can vary considerably between devices, making them a shaky basis for deciding how much to eat or whether you’ve “earned” an extra snack.</p><p>Readiness, recovery, and sleep scores can be useful shortcuts, although they’re usually built from the underlying measurements we’ve already covered, so treat them as context rather than definitive judgements. </p><p>A good <a href="https://www.tomsguide.com/sales-events/best-fitness-tracker-deals">fitness tracker</a> can measure an enormous amount. The trick is learning which numbers actually help you make better decisions – and letting the rest fade into the background.</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/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">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</a></li><li><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">I tested shoes from 5 up-and-coming running brands — here are the ones worth your money</a></li><li><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">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</a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness-trackers/your-fitness-tracker-has-a-lot-of-numbers-these-are-the-ones-that-are-worth-watching</link>
                                                                            <description>
                            <![CDATA[ Here's what you should be tracking on your wearable ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">fv2Pn2j3jLgyYvSpZ32ED3</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/S7rj9Ysn9dyL4QqAhNFCrQ-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 29 Aug 2026 09:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Smartwatches]]></category>
                                                                                                                    <dc:creator><![CDATA[ Max Slater-Robins ]]></dc:creator>                                                                                                        <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/S7rj9Ysn9dyL4QqAhNFCrQ-1920-80.jpg">
                                                            <media:credit><![CDATA[Google]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Fitbit Air fitness tracker]]></media:description>                                                            <media:text><![CDATA[Close-up of the Fitbit Air fitness tracker]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Fitbit Air fitness tracker]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/S7rj9Ysn9dyL4QqAhNFCrQ-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>As <a href="https://www.tomsguide.com/us/best-fitness-trackers,review-2066.html">fitness trackers</a> like the <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">Fitbit Air</a> become better and better, they are now remarkably good at finding new things to measure. </p><p>Open the companion app after a workout or a night’s sleep and you'll be greeted by a dizzying array of stats: steps, heart rate, HRV, sleep stages, VO2 max, calories burned, and many more besides. </p><p>Some of that information is genuinely useful, but a lot of it is better treated as (interesting) background noise.</p><p>The trick is knowing which numbers can tell you something meaningful about your activity or recovery — and, just as importantly, which ones you can actually do something with. </p><p>For most of us, though, that leaves a much shorter list than the dashboard might suggest.</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:2826px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="gzvMQLs88dSzLa7Pe9Y2KE" name="Oura Ring 5" alt="photos of the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/gzvMQLs88dSzLa7Pe9Y2KE-1920-80.jpg" mos="" align="middle" fullscreen="" width="2826" height="1590" 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><h2 id="steps-still-matter">Steps still matter</h2><p>With all the newer metrics available, step count can feel almost quaint, but it remains one of the most useful numbers going, simply because it offers a clear picture of how much you’re moving during the day.</p><p>There’s no need to treat 10,000 steps as a magic target, either. <a href="https://www.sciencedirect.com/science/article/pii/S0091743524002020" target="_blank" rel="nofollow">Research suggests</a> health benefits begin well below that figure, with more movement generally bringing greater benefits.</p><p>Your own baseline is the best place to start. If you typically manage, say, 4,000 steps per day, regularly getting closer to 6,000 is meaningful progress.</p><p>Step counting is also one of the things fitness trackers do reasonably well. It won’t tell you how hard you exercised, which we’ll come to next, but it’s an easy way to spot whether a desk-heavy week has turned into a sedentary one.</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:5020px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="zCBBhA82yv8MGUKAmpHWt5" name="Fitbit-Air-lead" alt="Close-up of the sensors on the Fitbit Air" src="https://cdn.mos.cms.futurecdn.net/zCBBhA82yv8MGUKAmpHWt5-1920-80.jpg" mos="" align="middle" fullscreen="" width="5020" height="2824" 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><h2 id="track-how-hard-you-re-moving">Track how hard you’re moving</h2><p>Step count tells you how much you’ve moved, but it says little about intensity. A brisk walk can add the same number of steps as a much slower one while placing very different demands on your body.</p><p>Active minutes help fill in that gap. Most trackers estimate how much time you spend at moderate or vigorous intensity, giving you a clearer sense of whether your week includes enough purposeful exercise alongside general movement.</p><p>For reference, the World Health Organization <a href="https://www.who.int/publications/i/item/9789240015128" target="_blank" rel="nofollow">recommends</a> at least 150 minutes of moderate-intensity aerobic activity each week — or 75 minutes at vigorous intensity — with more activity bringing additional benefits.</p><p>Heart rate zones can also be useful during individual workouts, giving you a quick way to check whether an easy session stayed easy. </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:4626px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Ff9hx8JnRhaSc9bAGZ5AMn" name="IMG_0934-2" alt="Fitbit Air, Whoop MG and Garmin Cirqa" src="https://cdn.mos.cms.futurecdn.net/Ff9hx8JnRhaSc9bAGZ5AMn-1920-80.jpg" mos="" align="middle" fullscreen="" width="4626" height="2602" 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><h2 id="watch-your-resting-heart-rate-and-hrv">Watch your resting heart rate and HRV</h2><p>Resting heart rate is one of the simpler recovery metrics to understand, showing how many times your heart beats per minute when you’re at rest. Regular aerobic training can gradually bring that number down over time.</p><p>Where fitness trackers excel is showing you the <em>trend</em>. A sudden rise above your usual range can sometimes line up with poor recovery or an illness, while a gradual decline can be a sign that your cardiovascular fitness is improving.</p><p>Heart rate variability, or HRV, adds more context by measuring the variation in time between heartbeats and can be useful for spotting changes in recovery. It's worth noting that HRV is highly individual, so try not to compare scores. </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="rZtWweMfmTbWFc3A7cEKNN" name="Sleep Trackers Oura Ring 4" alt="Our sleep tech tester testing the silver Oura Ring 4 in bed with white bedsheets and a rattan headboard" src="https://cdn.mos.cms.futurecdn.net/rZtWweMfmTbWFc3A7cEKNN-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><h2 id="focus-on-better-sleep-not-a-better-sleep-score">Focus on better sleep, not a better sleep score</h2><p>Sleep tracking is most useful when you keep it simple: start with how long you’re actually sleeping and whether your bedtime and wake-up time are reasonably consistent from one day to the next.</p><p>Those numbers are easier to interpret than the detailed breakdowns many trackers now provide. Consumer wearables estimate sleep stages from signals such as movement and heart rate, so it’s worth being cautious about treating every minute of deep or REM sleep as exact.</p><p>The same goes for proprietary sleep scores; they can be handy as a quick summary, but the underlying habits are usually more useful to watch over time.</p><p>I've sometimes found that a low sleep score can trick my brain into thinking I had a bad sleep, which then makes me feel worse, whereas a similar sleep without a tracker leaves me feeling well-rested. Too much information can, in some cases, be a bad thing. </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="sppVH3W74zvzBJtaGywaRZ" name="Xiaomi Smart Band 10" alt="Xiaomi Smart Band 10 in Ceramic Pearl White" src="https://cdn.mos.cms.futurecdn.net/sppVH3W74zvzBJtaGywaRZ-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><h2 id="use-vo2-max-to-track-the-bigger-picture">Use VO2 max to track the bigger picture</h2><p>VO2 max gives you an estimate of how effectively your body can use oxygen during exercise, which makes it a useful shorthand for aerobic fitness.</p><p>Most watches calculate it from workout data rather than measuring it directly, so the figure on your wrist won’t be as precise as a laboratory test.</p><p>That doesn’t make it useless. If you keep using the same device, the direction of travel can still tell you plenty. For example, a VO2 max score rising over several months indicates improving aerobic fitness. </p><p>It’s another metric where the trend is more valuable than the exact number. Whether your watch says 45 or 47 matters less than where that figure is heading over time. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:9254px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="JpSXwAkfnPAtMwt3ZYMFrR" name="Fitbit-Air-07" alt="Close-up of the Fitbit Air fitness tracker" src="https://cdn.mos.cms.futurecdn.net/JpSXwAkfnPAtMwt3ZYMFrR-1920-80.jpg" mos="" align="middle" fullscreen="" width="9254" height="5205" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Google)</span></figcaption></figure><h2 id="the-numbers-you-can-mostly-ignore">The numbers you can mostly ignore</h2><p>Plenty of other fitness tracker stats can still be interesting, but they don’t all deserve the same attention. </p><p>Calories burned are a good example: estimates can vary considerably between devices, making them a shaky basis for deciding how much to eat or whether you’ve “earned” an extra snack.</p><p>Readiness, recovery, and sleep scores can be useful shortcuts, although they’re usually built from the underlying measurements we’ve already covered, so treat them as context rather than definitive judgements. </p><p>A good <a href="https://www.tomsguide.com/sales-events/best-fitness-tracker-deals">fitness tracker</a> can measure an enormous amount. The trick is learning which numbers actually help you make better decisions – and letting the rest fade into the background.</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/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">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</a></li><li><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">I tested shoes from 5 up-and-coming running brands — here are the ones worth your money</a></li><li><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">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</a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I hiked 7 miles with the Garmin Instinct 3 vs Samsung Galaxy Watch 9 — and the winner is clear as day ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Which is the better smartwatch for hikers, the <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-to-know-about-the-new-samsung-galaxy-watch-9">Samsung Galaxy Watch 9</a> or the <a href="https://www.tomsguide.com/Garmin-Instinct-3-review">Garmin Instinct 3</a>? The latter may be built for logging outdoor adventures, but both watches use similar tracking tech, offer a dedicated hiking mode, and also cost about the same.</p><p>To find out, I wore the Garmin Instinct 3 on my right wrist and the Samsung Galaxy Watch 9 on my left wrist, fired up a hiking workout on both, and started the ~1,700-foot climb to Snow Lake, a scenic high-altitude alpine lake located in the Cascade Mountains, an hour east of Seattle. I also logged the trek using the Strava app on my iPhone 16 as a control.</p><h3 class="article-body__section" id="section-i-hiked-7-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-9"><span>I hiked 7 miles with the Garmin Instinct 3 vs Samsung Galaxy Watch 9 </span></h3><p>So, which smartwatch, the Samsung Galaxy Watch 9 or the Garmin Instinct 3, proved to be the more reliable hiking companion? Find the results for each watch, along with Strava, below. </p><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Galaxy Watch 9</p></th><th  ><p>Garmin Instinct 3</p></th><th  ><p>Strava</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Distance</strong></p></td><td  ><p>6.49 miles</p></td><td  ><p>6.55 miles</p></td><td  ><p>6.70 miles</p></td></tr><tr><td class="firstcol " ><p><strong>Climb</strong></p></td><td  ><p>1,866 feet</p></td><td  ><p>1,693 feet</p></td><td  ><p>1,674 feet</p></td></tr><tr><td class="firstcol " ><p><strong>Steps</strong></p></td><td  ><p>Not provided</p></td><td  ><p>16,096 steps</p></td><td  ><p>15,048 steps</p></td></tr><tr><td class="firstcol " ><p><strong>Average pace </strong></p></td><td  ><p>34 mins 20 secs per mile</p></td><td  ><p>24 mins 15 secs per mile</p></td><td  ><p>25 mins 23 secs per mile</p></td></tr><tr><td class="firstcol " ><p><strong>Average heart rate</strong></p></td><td  ><p>133 bpm</p></td><td  ><p>130 bpm</p></td><td  ><p>n/a</p></td></tr><tr><td class="firstcol " ><p><strong>Max heart rate</strong></p></td><td  ><p>174 bpm</p></td><td  ><p>173 bpm</p></td><td  ><p>n/a</p></td></tr><tr><td class="firstcol " ><p><strong>Calories burned (total)</strong></p></td><td  ><p>1,442 calories</p></td><td  ><p>1,332 calories</p></td><td  ><p>n/a</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-1-samsung-overcounted-my-climb-and-undercounted-my-distance"><span>1. Samsung overcounted my climb and undercounted my distance</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:3701px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="yaL9XTKoBPfLqrd6sDVKdB" name="Garmin-Torch-03" alt="Close-up of the Garmin Instinct 3 showing the 'Torch' LED flashlight illuminated from the top of the watch case" src="https://cdn.mos.cms.futurecdn.net/yaL9XTKoBPfLqrd6sDVKdB-1920-80.jpg" mos="" align="middle" fullscreen="" width="3701" height="2082" 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><div><blockquote><p>The Galaxy Watch 9 overcounted my uphill efforts by a whopping 180 feet</p></blockquote></div><p>According to <a href="https://www.tomsguide.com/wellness/fitness/i-tried-alltrails-new-custom-routes-tool-and-its-a-game-changer-for-hikers-bikers-and-runners">AllTrails</a>, the <a href="https://www.alltrails.com/trail/us/washington/snow-lake-trail" target="_blank">Snow Lake Trail</a> is 6.7 miles, which is exactly what Strava logged. The Instinct 3 came pretty close, depriving me of 0.15 miles of effort, while the Galaxy Watch 9 undercounted by 0.21 miles.</p><p>AllTrails additionally lists 1,686 feet of elevation gain for the hike, a tally that both Strava and Garmin came incredibly close to nailing; the former undercounted by just 12 feet and the latter overcounted by a mere 7 feet. </p><p>The Galaxy Watch 9, meanwhile, overcounted my uphill efforts by a whopping 180 feet. </p><h3 class="article-body__section" id="section-2-the-galaxy-watch-9-didn-t-count-my-steps"><span>2. The Galaxy Watch 9 didn't count my steps</span></h3><p>While distance and elevation are the two metrics I care about most when tracking a hike, along with moving pace (more on that below), it's always nice to get a sense of my step count. Unfortunately, the Galaxy Watch 9 neglected to count my steps, which is odd, given it has no trouble doing so when you track a normal walking workout.</p><h3 class="article-body__section" id="section-3-samsung-doesn-t-record-a-moving-pace"><span>3. Samsung doesn't record a 'moving pace'</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:4889px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9VYZkwkFKGrzUBK9zzEc3k" name="GalaxyWatch9-02" alt="Close-up of the Samsung Galaxy Watch 9 in white" src="https://cdn.mos.cms.futurecdn.net/9VYZkwkFKGrzUBK9zzEc3k-1920-80.jpg" mos="" align="middle" fullscreen="" width="4889" height="2750" 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><div><blockquote><p>Most smartwatches in 2026 are smart enough to notice that you've stopped moving and automatically pause your workout</p></blockquote></div><p>My brother, who was visiting from the U.S. East Coast, joined me on this hike. Our plan was to make it to the lake, cool off, enjoy the tranquility (along with a cheeky beverage), and then head back down. </p><p>During our mid-hike break, I left all three workout sessions running. Most smartwatches in 2026 are smart enough to notice that you've stopped moving and automatically pause your workout until you're in motion again.</p><p>Post-outdoor workout, the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> provide two pace metrics, one reflecting your average moving pace and the other showing your average elapsed pace with pauses included in the calculation. As you might guess, the former is more useful and reflective of your <em>actual</em> efforts.</p><p>Unfortunately, the Samsung Galaxy Watch 9 only provided one average pace metric without specifying which, but the answer seems obvious. For what it's worth, Garmin and Strava both noted a similar average elapsed pace to Samsung's: 34 mins 10 secs per mile for Garmin and 33 mins 06 secs per mile from Strava.</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:1741px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="NquCSuaEaN7a23EHqscKSN" name="GarminInstinct3-snow-02" alt="Garmin Instinct 3 on a user's wrist shown up-close in between a ski glove and jacket" src="https://cdn.mos.cms.futurecdn.net/NquCSuaEaN7a23EHqscKSN-1920-80.jpg" mos="" align="middle" fullscreen="" width="1741" height="979" 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><h3 class="article-body__section" id="section-4-heart-rate-and-calorie-data-matches-up-nicely"><span>4. Heart rate and calorie data matches up nicely</span></h3><p>Now for the good news. The Galaxy Watch 9's heart rate data is a near match with Garmin's, a result I love to see. Both smartwatches also calculated a similar number of calories burned during my 3.5-hour excursion. </p><h3 class="article-body__section" id="section-winner-garmin-instinct-3"><span>Winner: Garmin Instinct 3</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:4834px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kuTYfGbyRcRugdWr8FJdqf" name="Galaxy9-v-Instinct3-02" alt="Close-up of the Garmin Instinct 3 next to the Samsung Galaxy Watch 9 with evergreens in the background" src="https://cdn.mos.cms.futurecdn.net/kuTYfGbyRcRugdWr8FJdqf-1920-80.jpg" mos="" align="middle" fullscreen="" width="4834" height="2719" 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 Garmin Instinct 3 long ago established itself as my go-to smartwatch for logging outdoor adventures thanks to its reliability, ridiculously good battery performance, bright screen, and rugged design. And it once again excelled on all fronts in this hiking comparison versus the Samsung Galaxy Watch 9.</p><p>Not only did Garmin calculate more precise distance, climb, and pace data than Samsung, it also logged my steps, something the Galaxy Watch 9 failed to do, all while using way less battery. In other words, the Garmin Instinct 3 wins this comparison.</p><p>Which smartwatches or fitness trackers should I test head-to-head next? Let me know in the comments below. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eJ9PvX"></div>                            </div>                            <script src="https://kwizly.com/embed/eJ9PvX.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/smartwatches/i-biked-11-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-ultra-2-and-the-winner-is-clear"><strong>I biked 11 miles with the Garmin Instinct 3 vs Samsung Galaxy Watch Ultra 2 — and the winner is clear</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-walked-4-000-steps-with-the-pixel-watch-5-vs-samsung-galaxy-watch-9-and-we-have-a-new-android-champ"><strong>I walked 4,000 steps with the Pixel Watch 5 vs Samsung Galaxy Watch 9 — and we have a new Android champ</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-walked-7-miles-with-the-apple-watch-ultra-3-vs-pixel-watch-5-and-the-winner-is-nearly-too-close-to-call"><strong>I walked 7 miles with the Apple Watch Ultra 3 vs Pixel Watch 5 — here's the winner</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/i-hiked-7-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-9-and-the-winner-is-clear-as-day</link>
                                                                            <description>
                            <![CDATA[ I tested the tracking accuracy of the Garmin Instinct 3 vs Samsung Galaxy Watch 9 during an epic seven-mile hike to an alpine lake. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">FDgPHG2C8SFZvms4WGridf</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/wspKcYvnj3bAwYgpJzAq5g-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 28 Aug 2026 08:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/wspKcYvnj3bAwYgpJzAq5g-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Garmin Instinct 3 next to the Samsung Galaxy Watch 9 with evergreens in the background]]></media:description>                                                            <media:text><![CDATA[Close-up of the Garmin Instinct 3 next to the Samsung Galaxy Watch 9 with evergreens in the background]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Garmin Instinct 3 next to the Samsung Galaxy Watch 9 with evergreens in the background]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/wspKcYvnj3bAwYgpJzAq5g-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Which is the better smartwatch for hikers, the <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-to-know-about-the-new-samsung-galaxy-watch-9">Samsung Galaxy Watch 9</a> or the <a href="https://www.tomsguide.com/Garmin-Instinct-3-review">Garmin Instinct 3</a>? The latter may be built for logging outdoor adventures, but both watches use similar tracking tech, offer a dedicated hiking mode, and also cost about the same.</p><p>To find out, I wore the Garmin Instinct 3 on my right wrist and the Samsung Galaxy Watch 9 on my left wrist, fired up a hiking workout on both, and started the ~1,700-foot climb to Snow Lake, a scenic high-altitude alpine lake located in the Cascade Mountains, an hour east of Seattle. I also logged the trek using the Strava app on my iPhone 16 as a control.</p><h3 class="article-body__section" id="section-i-hiked-7-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-9"><span>I hiked 7 miles with the Garmin Instinct 3 vs Samsung Galaxy Watch 9 </span></h3><p>So, which smartwatch, the Samsung Galaxy Watch 9 or the Garmin Instinct 3, proved to be the more reliable hiking companion? Find the results for each watch, along with Strava, below. </p><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Galaxy Watch 9</p></th><th  ><p>Garmin Instinct 3</p></th><th  ><p>Strava</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Distance</strong></p></td><td  ><p>6.49 miles</p></td><td  ><p>6.55 miles</p></td><td  ><p>6.70 miles</p></td></tr><tr><td class="firstcol " ><p><strong>Climb</strong></p></td><td  ><p>1,866 feet</p></td><td  ><p>1,693 feet</p></td><td  ><p>1,674 feet</p></td></tr><tr><td class="firstcol " ><p><strong>Steps</strong></p></td><td  ><p>Not provided</p></td><td  ><p>16,096 steps</p></td><td  ><p>15,048 steps</p></td></tr><tr><td class="firstcol " ><p><strong>Average pace </strong></p></td><td  ><p>34 mins 20 secs per mile</p></td><td  ><p>24 mins 15 secs per mile</p></td><td  ><p>25 mins 23 secs per mile</p></td></tr><tr><td class="firstcol " ><p><strong>Average heart rate</strong></p></td><td  ><p>133 bpm</p></td><td  ><p>130 bpm</p></td><td  ><p>n/a</p></td></tr><tr><td class="firstcol " ><p><strong>Max heart rate</strong></p></td><td  ><p>174 bpm</p></td><td  ><p>173 bpm</p></td><td  ><p>n/a</p></td></tr><tr><td class="firstcol " ><p><strong>Calories burned (total)</strong></p></td><td  ><p>1,442 calories</p></td><td  ><p>1,332 calories</p></td><td  ><p>n/a</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-1-samsung-overcounted-my-climb-and-undercounted-my-distance"><span>1. Samsung overcounted my climb and undercounted my distance</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:3701px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="yaL9XTKoBPfLqrd6sDVKdB" name="Garmin-Torch-03" alt="Close-up of the Garmin Instinct 3 showing the 'Torch' LED flashlight illuminated from the top of the watch case" src="https://cdn.mos.cms.futurecdn.net/yaL9XTKoBPfLqrd6sDVKdB-1920-80.jpg" mos="" align="middle" fullscreen="" width="3701" height="2082" 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><div><blockquote><p>The Galaxy Watch 9 overcounted my uphill efforts by a whopping 180 feet</p></blockquote></div><p>According to <a href="https://www.tomsguide.com/wellness/fitness/i-tried-alltrails-new-custom-routes-tool-and-its-a-game-changer-for-hikers-bikers-and-runners">AllTrails</a>, the <a href="https://www.alltrails.com/trail/us/washington/snow-lake-trail" target="_blank">Snow Lake Trail</a> is 6.7 miles, which is exactly what Strava logged. The Instinct 3 came pretty close, depriving me of 0.15 miles of effort, while the Galaxy Watch 9 undercounted by 0.21 miles.</p><p>AllTrails additionally lists 1,686 feet of elevation gain for the hike, a tally that both Strava and Garmin came incredibly close to nailing; the former undercounted by just 12 feet and the latter overcounted by a mere 7 feet. </p><p>The Galaxy Watch 9, meanwhile, overcounted my uphill efforts by a whopping 180 feet. </p><h3 class="article-body__section" id="section-2-the-galaxy-watch-9-didn-t-count-my-steps"><span>2. The Galaxy Watch 9 didn't count my steps</span></h3><p>While distance and elevation are the two metrics I care about most when tracking a hike, along with moving pace (more on that below), it's always nice to get a sense of my step count. Unfortunately, the Galaxy Watch 9 neglected to count my steps, which is odd, given it has no trouble doing so when you track a normal walking workout.</p><h3 class="article-body__section" id="section-3-samsung-doesn-t-record-a-moving-pace"><span>3. Samsung doesn't record a 'moving pace'</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:4889px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9VYZkwkFKGrzUBK9zzEc3k" name="GalaxyWatch9-02" alt="Close-up of the Samsung Galaxy Watch 9 in white" src="https://cdn.mos.cms.futurecdn.net/9VYZkwkFKGrzUBK9zzEc3k-1920-80.jpg" mos="" align="middle" fullscreen="" width="4889" height="2750" 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><div><blockquote><p>Most smartwatches in 2026 are smart enough to notice that you've stopped moving and automatically pause your workout</p></blockquote></div><p>My brother, who was visiting from the U.S. East Coast, joined me on this hike. Our plan was to make it to the lake, cool off, enjoy the tranquility (along with a cheeky beverage), and then head back down. </p><p>During our mid-hike break, I left all three workout sessions running. Most smartwatches in 2026 are smart enough to notice that you've stopped moving and automatically pause your workout until you're in motion again.</p><p>Post-outdoor workout, the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> provide two pace metrics, one reflecting your average moving pace and the other showing your average elapsed pace with pauses included in the calculation. As you might guess, the former is more useful and reflective of your <em>actual</em> efforts.</p><p>Unfortunately, the Samsung Galaxy Watch 9 only provided one average pace metric without specifying which, but the answer seems obvious. For what it's worth, Garmin and Strava both noted a similar average elapsed pace to Samsung's: 34 mins 10 secs per mile for Garmin and 33 mins 06 secs per mile from Strava.</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:1741px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="NquCSuaEaN7a23EHqscKSN" name="GarminInstinct3-snow-02" alt="Garmin Instinct 3 on a user's wrist shown up-close in between a ski glove and jacket" src="https://cdn.mos.cms.futurecdn.net/NquCSuaEaN7a23EHqscKSN-1920-80.jpg" mos="" align="middle" fullscreen="" width="1741" height="979" 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><h3 class="article-body__section" id="section-4-heart-rate-and-calorie-data-matches-up-nicely"><span>4. Heart rate and calorie data matches up nicely</span></h3><p>Now for the good news. The Galaxy Watch 9's heart rate data is a near match with Garmin's, a result I love to see. Both smartwatches also calculated a similar number of calories burned during my 3.5-hour excursion. </p><h3 class="article-body__section" id="section-winner-garmin-instinct-3"><span>Winner: Garmin Instinct 3</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:4834px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kuTYfGbyRcRugdWr8FJdqf" name="Galaxy9-v-Instinct3-02" alt="Close-up of the Garmin Instinct 3 next to the Samsung Galaxy Watch 9 with evergreens in the background" src="https://cdn.mos.cms.futurecdn.net/kuTYfGbyRcRugdWr8FJdqf-1920-80.jpg" mos="" align="middle" fullscreen="" width="4834" height="2719" 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 Garmin Instinct 3 long ago established itself as my go-to smartwatch for logging outdoor adventures thanks to its reliability, ridiculously good battery performance, bright screen, and rugged design. And it once again excelled on all fronts in this hiking comparison versus the Samsung Galaxy Watch 9.</p><p>Not only did Garmin calculate more precise distance, climb, and pace data than Samsung, it also logged my steps, something the Galaxy Watch 9 failed to do, all while using way less battery. In other words, the Garmin Instinct 3 wins this comparison.</p><p>Which smartwatches or fitness trackers should I test head-to-head next? Let me know in the comments below. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eJ9PvX"></div>                            </div>                            <script src="https://kwizly.com/embed/eJ9PvX.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/smartwatches/i-biked-11-miles-with-the-garmin-instinct-3-vs-samsung-galaxy-watch-ultra-2-and-the-winner-is-clear"><strong>I biked 11 miles with the Garmin Instinct 3 vs Samsung Galaxy Watch Ultra 2 — and the winner is clear</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-walked-4-000-steps-with-the-pixel-watch-5-vs-samsung-galaxy-watch-9-and-we-have-a-new-android-champ"><strong>I walked 4,000 steps with the Pixel Watch 5 vs Samsung Galaxy Watch 9 — and we have a new Android champ</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/i-walked-7-miles-with-the-apple-watch-ultra-3-vs-pixel-watch-5-and-the-winner-is-nearly-too-close-to-call"><strong>I walked 7 miles with the Apple Watch Ultra 3 vs Pixel Watch 5 — here's the winner</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’ve been writing about the Apple Watch for the past decade: Here’s the rumored update I’m most excited about for the Apple Watch Ultra 4 ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple's <a href="https://www.tomsguide.com/phones/iphones/apple-event-is-official-for-september-9-iphone-ultra-iphone-18-pro-max-watch-12-and-more">"Surprise and Shine" event</a> is confirmed for Wednesday, September 9 at 10:00 a.m. PT / 1:00 p.m. ET. And according to rumors, we can expect a new <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-all-the-design-health-and-battery-life-rumors-so-far">Apple Watch Series 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-all-the-design-health-and-battery-life-rumors-so-far">Apple Watch Ultra 4</a> to be unveiled. </p><p>Whether these watches appear and what they look like remains to be seen (I’ll be in Cupertino keeping you updated), but for now, this is the Apple Watch Ultra 4 rumor I’m most excited about. </p><h2 id="this-is-the-apple-watch-ultra-4-rumor-i-m-most-excited-about">This is the Apple Watch Ultra 4 rumor I’m most excited about</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3267px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="Z3xWgF9LvrsH7Q2vjwtrQE" name="IMG_4292" alt="a photo of the Apple Watch Ultra 3" src="https://cdn.mos.cms.futurecdn.net/Z3xWgF9LvrsH7Q2vjwtrQE-1920-80.jpg" mos="" align="middle" fullscreen="" width="3267" height="1838" 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’ve been writing about the Apple Watch for the past decade, and without a doubt, the Apple Watch Ultra 3 is the best Apple Watch for runners, cyclists, and fitness fanatics. I wore the <a href="https://www.tomsguide.com/wellness/smartwatches/i-wore-an-apple-watch-and-a-garmin-for-the-london-marathon-heres-which-came-out-on-top"><u>Apple Watch Ultra 3 alongside this Garmin for the London Marathon in April</u></a>, and was impressed with the GPS accuracy, even through the mile 20 Canary Wharf skyscraper dead zone. Yet I have one pretty big issue with the Ultra, and every model that has been released so far: it’s huge on my wrist, and pretty uncomfortable, especially at night. </p><p>According to Bloomberg’s Mark Gurman, this year the big news regarding Apple Watches will be what’s inside. In his <a href="https://www.bloomberg.com/news/newsletters/2026-07-26/apple-glasses-may-debut-at-wwdc-2027-privacy-camera-features-versus-meta-ms1v7lta" target="_blank" rel="nofollow"><em>Power On</em> newsletter</a>, Gurman wrote, “None of this year’s watches is expected to get a major design overhaul, I’m told. Apple is more focused on what’s inside: There will be health and fitness-tracking improvements, along with a long-awaited bump in chips and speed.”</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:3086px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bRghiFkByGRUquDJ57AHc9" name="AWU3-v-series11-05" alt="Close-up of the Apple Watch Ultra 3 in silver" src="https://cdn.mos.cms.futurecdn.net/bRghiFkByGRUquDJ57AHc9-1920-80.jpg" mos="" align="middle" fullscreen="" width="3086" height="1736" 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>It’s thought that these health and fitness improvements will include a new high blood pressure notification, but other than that, it’s unclear. I predict vast updates to Workout Buddy, or Apple introducing an AI health coach, similar to the Gemini coach used in the Google Health App. </p><p>Yet elsewhere, reports have hinted at a slightly thinner and smaller design for the Apple Watch Ultra 4, a rumor I’m really hoping is true. One day, I’d love to see two different size options for the Ultra 4 to suit different wrist sizes, but this is probably a long way off. Time will tell, but one thing is for sure — we don’t have long to wait. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ORVGJO"></div>                            </div>                            <script src="https://kwizly.com/embed/ORVGJO.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/apple-watch-series-12-everything-we-know-so-far">Apple Watch Series 12 rumors — everything we know so far</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/from-fall-detection-to-hypertension-10-apple-watch-innovations-that-changed-the-game">10 Apple Watch innovations that changed the game — from Fall Detection to Hypertension Alerts</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/garmins-rumored-screen-less-wearable-just-might-be-the-subscription-free-whoop-rival-ive-been-waiting-for">Garmin’s rumored screen-less wearable just might be the subscription-free Whoop rival I’ve been waiting for</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/ive-been-writing-about-the-apple-watch-for-the-past-decade-heres-the-rumored-update-im-most-excited-about-for-the-apple-watch-ultra-4</link>
                                                                            <description>
                            <![CDATA[ New Apple Watches should be arriving on September 9; here's the Apple Watch Ultra 4 rumor I'm most excited about. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">n2i4cgHn2KmDW3F2XXQmWG</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/6xWxFmJRkMDPWa7YQ7zZ33-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 26 Aug 2026 16:50:02 +0000</pubDate>                                                                                                                                <updated>Wed, 26 Aug 2026 23:41:09 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></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/6xWxFmJRkMDPWa7YQ7zZ33-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A photo of the Apple Watch Ultra 3]]></media:description>                                                            <media:text><![CDATA[A photo of the Apple Watch Ultra 3]]></media:text>
                                <media:title type="plain"><![CDATA[A photo of the Apple Watch Ultra 3]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/6xWxFmJRkMDPWa7YQ7zZ33-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple's <a href="https://www.tomsguide.com/phones/iphones/apple-event-is-official-for-september-9-iphone-ultra-iphone-18-pro-max-watch-12-and-more">"Surprise and Shine" event</a> is confirmed for Wednesday, September 9 at 10:00 a.m. PT / 1:00 p.m. ET. And according to rumors, we can expect a new <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-all-the-design-health-and-battery-life-rumors-so-far">Apple Watch Series 12</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-all-the-design-health-and-battery-life-rumors-so-far">Apple Watch Ultra 4</a> to be unveiled. </p><p>Whether these watches appear and what they look like remains to be seen (I’ll be in Cupertino keeping you updated), but for now, this is the Apple Watch Ultra 4 rumor I’m most excited about. </p><h2 id="this-is-the-apple-watch-ultra-4-rumor-i-m-most-excited-about">This is the Apple Watch Ultra 4 rumor I’m most excited about</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3267px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="Z3xWgF9LvrsH7Q2vjwtrQE" name="IMG_4292" alt="a photo of the Apple Watch Ultra 3" src="https://cdn.mos.cms.futurecdn.net/Z3xWgF9LvrsH7Q2vjwtrQE-1920-80.jpg" mos="" align="middle" fullscreen="" width="3267" height="1838" 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’ve been writing about the Apple Watch for the past decade, and without a doubt, the Apple Watch Ultra 3 is the best Apple Watch for runners, cyclists, and fitness fanatics. I wore the <a href="https://www.tomsguide.com/wellness/smartwatches/i-wore-an-apple-watch-and-a-garmin-for-the-london-marathon-heres-which-came-out-on-top"><u>Apple Watch Ultra 3 alongside this Garmin for the London Marathon in April</u></a>, and was impressed with the GPS accuracy, even through the mile 20 Canary Wharf skyscraper dead zone. Yet I have one pretty big issue with the Ultra, and every model that has been released so far: it’s huge on my wrist, and pretty uncomfortable, especially at night. </p><p>According to Bloomberg’s Mark Gurman, this year the big news regarding Apple Watches will be what’s inside. In his <a href="https://www.bloomberg.com/news/newsletters/2026-07-26/apple-glasses-may-debut-at-wwdc-2027-privacy-camera-features-versus-meta-ms1v7lta" target="_blank" rel="nofollow"><em>Power On</em> newsletter</a>, Gurman wrote, “None of this year’s watches is expected to get a major design overhaul, I’m told. Apple is more focused on what’s inside: There will be health and fitness-tracking improvements, along with a long-awaited bump in chips and speed.”</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:3086px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bRghiFkByGRUquDJ57AHc9" name="AWU3-v-series11-05" alt="Close-up of the Apple Watch Ultra 3 in silver" src="https://cdn.mos.cms.futurecdn.net/bRghiFkByGRUquDJ57AHc9-1920-80.jpg" mos="" align="middle" fullscreen="" width="3086" height="1736" 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>It’s thought that these health and fitness improvements will include a new high blood pressure notification, but other than that, it’s unclear. I predict vast updates to Workout Buddy, or Apple introducing an AI health coach, similar to the Gemini coach used in the Google Health App. </p><p>Yet elsewhere, reports have hinted at a slightly thinner and smaller design for the Apple Watch Ultra 4, a rumor I’m really hoping is true. One day, I’d love to see two different size options for the Ultra 4 to suit different wrist sizes, but this is probably a long way off. Time will tell, but one thing is for sure — we don’t have long to wait. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ORVGJO"></div>                            </div>                            <script src="https://kwizly.com/embed/ORVGJO.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/apple-watch-series-12-everything-we-know-so-far">Apple Watch Series 12 rumors — everything we know so far</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/from-fall-detection-to-hypertension-10-apple-watch-innovations-that-changed-the-game">10 Apple Watch innovations that changed the game — from Fall Detection to Hypertension Alerts</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/garmins-rumored-screen-less-wearable-just-might-be-the-subscription-free-whoop-rival-ive-been-waiting-for">Garmin’s rumored screen-less wearable just might be the subscription-free Whoop rival I’ve been waiting for</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple Watch Series 12 vs 11: Biggest rumored upgrades ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Grab a grain of salt and join me; it's time to chew on the biggest Apple Watch rumors of 2026 (so far). With not one but two new models possible on September 9th — the Apple Watch Series 12 and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-all-the-design-health-and-battery-life-rumors-so-far">Apple Watch Ultra 4</a> — there's a lot to cover. So, let's focus on the flagship.</p><p>As is often the case this time of year, leaks and "insider" reports are plentiful, ranging from believable to, well, not. With that in mind, here's everything we think we know about Apple's next flagship wearable, the Apple Watch Series 12, including whether or not it has a chance of making our <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">Best Smartwatch</a> list.</p><h3 class="article-body__section" id="section-apple-watch-12-rumors-in-brief"><span>Apple Watch 12: Rumors in brief</span></h3><ul><li><strong>Price and launch:</strong> Expected to be revealed on September 9's "Surprise and shine" event; preorders will likely open on Saturday, with units shipping the following week; a price increase is possible following</li><li><strong>Health and fitness:</strong> Support for wrist-based blood pressure readings is rumored but remains unlikely; an updated Health app focused on long-term trends is possible; Apple may also (finally) bring users' health, fitness, and medical data under the roof of a singular app</li><li><strong>Design and display:</strong> A more efficient LTPO display is possible; a fingerprint scanner for Touch ID is rumored but less likely; an upgraded ceramic case option is possible</li><li><strong>AI features: </strong> The Series 12 is expected to support Apple's new Siri AI voice assistant; a personalized wellness concierge is also rumored</li><li><strong>Battery life:</strong> A larger capacity battery is possible; the S12 processor could bring efficiency improvements, too</li></ul><h3 class="article-body__section" id="section-apple-watch-12-price-and-launch-predictions"><span>Apple Watch 12: Price and launch predictions</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:2906px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="Yp3ND3TWUcSEqk9mC727n9" name="AppleWatchUltra3-01" alt="Apple Watch Ultra 3, Apple Watch Series 11, Apple Watch SE 3" src="https://cdn.mos.cms.futurecdn.net/Yp3ND3TWUcSEqk9mC727n9-1920-80.jpg" mos="" align="middle" fullscreen="" width="2906" height="1634" 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>Apple tends to hold an annual launch event in the second week of September, and this year is no exception. </p><p>Apple has confirmed a "Surprise and Shine" launch event for Wednesday, September 9th, where we'll likely get our first look at the Apple Watch Series 12, <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-rumors-everything-we-know-about-apples-next-ultra-rugged-smartwatch">Apple Watch Ultra 4</a>, and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-set-to-arrive-this-year-and-here-are-3-upgrades-im-most-excited-for">iPhone 18</a>. That said, with the U.S. Labor Day holiday falling the Monday before, Apple may push the event to Wednesday, September 9th or the following Tuesday, September 15th. </p><p>How much will the Apple Watch 12 cost? With both Samsung and Google increasing pricing across their respective smartwatch lineups — the <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review">Pixel Watch 5</a> now starts at $399, and the <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-to-know-about-the-new-samsung-galaxy-watch-9">Galaxy Watch 9</a> starts at $379 — a price bump for the Apple Watch 12 is possible. Put another way: a $399 starting price for the flagship smartwatch is far from guaranteed. </p><p>There are also rumors of a <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-12-and-ultra-4-rumors-your-next-apple-watch-could-have-a-ceramic-case">ceramic Apple Watch Series 12</a>. The last time Apple offered such an upgrade was in the 2019 Apple Watch Series 5. That model started at $399 for the standard version, but jumped to $1,299 for the ceramic model. So, yeah, if a ceramic Series 12 does exist, it will surely cost a pretty penny. </p><p>In terms of availability, Apple usually opens preorders on the Friday after a Tuesday product announcement, with units hitting store shelves in the weeks that follow; I suspect this will be the case for the Series 12, too. </p><h3 class="article-body__section" id="section-apple-watch-12-health-and-fitness-rumors"><span>Apple Watch 12: Health and fitness rumors </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:3118px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Eqd2jLmCaGjvJLxrQEmFMm" name="Apple-sleep-score-08" alt="Close-up of the Apple Watch Series 11 showing a user's sleep score" src="https://cdn.mos.cms.futurecdn.net/Eqd2jLmCaGjvJLxrQEmFMm-1920-80.jpg" mos="" align="middle" fullscreen="" width="3118" height="1754" 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 Apple Watch Series 12 could arrive with an <a href="https://www.tomsguide.com/wellness/smartwatches/skip-the-apple-watch-11-next-years-apple-watch-12-tipped-for-huge-sensor-upgrade">updated health sensor array</a>. According to a report in <a href="https://www.digitimes.com/news/a20250814PD217/apple-watch-wearable-smart-healthcare-high-end-demand-2026.html" target="_blank">DigiTimes</a> (via <a href="https://wccftech.com/apple-watch-series-12-redesign-2026/" target="_blank">Wccftech</a>), such an upgrade might unlock new holistic metrics or trend reports.  </p><p>We could also see an expansion of Apple’s groundbreaking <a href="https://www.tomsguide.com/wellness/smartwatches/hypertension-tracking-is-now-live-on-the-apple-watch-heres-what-to-do-if-you-get-an-alert">Hypertension Alerts</a> feature. According to <a href="https://www.bloomberg.com/news/newsletters/2025-03-23/apple-aapl-explores-turning-watches-into-wearable-ai-devices-with-cameras-m8ll6mvy" target="_blank">Bloomberg’s Mark Gurman</a>, one of the more trusted Apple insiders, Cupertino is hard at work on a wrist-based blood pressure monitor that provides readings similar to a traditional cuff. The question is, when will it be ready? I'm not convinced 2026 is the year.</p><p>On-wrist blood glucose monitoring is another focus for the Apple Watch team, but <a href="https://www.bloomberg.com/news/newsletters/2025-03-30/apple-readies-biggest-push-into-health-yet-with-revamped-app-ai-doctor-service-m8vl97k2" target="_blank">according to Gurman</a>, that tech is even further out than blood pressure monitoring.  </p><p>You can also expect an overhaul of the onboard Health app, with key metrics better organized in one location and a greater emphasis on long-term wellness trend reporting. </p><p>In fact, according to <a href="https://www.bloomberg.com/news/newsletters/2025-03-23/apple-aapl-explores-turning-watches-into-wearable-ai-devices-with-cameras-m8ll6mvy" target="_blank">Bloomberg's Gurman</a>, there's a possibility that Apple will finally bring all of a user’s health, fitness, and medical data under the roof of a singular app. </p><h3 class="article-body__section" id="section-apple-watch-12-design-and-display-rumors"><span>Apple Watch 12: Design and display rumors</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:2213px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="9BSyzrq4QFNifQ8BoZnMyj" name="dji_mimo_20250909_145252_20250909145253_1757471917429_photo" alt="Apple Watch Series 11" src="https://cdn.mos.cms.futurecdn.net/9BSyzrq4QFNifQ8BoZnMyj-1920-80.jpg" mos="" align="middle" fullscreen="" width="2213" height="1245" 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 Apple Watch Series 12 is rumored to sport an updated processor (likely dubbed S12), which could make it both faster and less power-hungry than the S10 chip in the Series 11. Less likely but still possible: the Series 12 arrives with an LTPO display, which would be more power-efficient than the OLED panel in the Series 11.</p><p>I’d also like to see Apple increase the screen brightness on the Series 12 to 3,000 nits or more (from 2,000 nits) to keep up with the latest Google Pixel Watch 5 and Samsung Galaxy Watch 9. </p><p>Changes to the case dimensions and button layout seem unlikely. The <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-10-review">Series 10</a> ushered in an updated case in 2024, and Apple only tends to switch up the design every four-ish launch cycles. Moreover, <a href="https://www.bloomberg.com/sessions/2026-03-26/live-q-amp-a-ask-mark-gurman-anything-about-apple" target="_blank">Bloomberg’s Mark Gurman</a> also thinks a major design shift is unlikely.</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:970px;"><p class="vanilla-image-block" style="padding-top:56.29%;"><img id="5UZmFrXnmYtGfpn3thBJUh" name="Apple Watch with bands" alt="Apple Watch with bands" src="https://cdn.mos.cms.futurecdn.net/5UZmFrXnmYtGfpn3thBJUh-1920-80.png" mos="" align="middle" fullscreen="" width="970" height="546" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>One design-related rumor I'm hoping doesn't come true is the introduction of a <a href="https://www.tomsguide.com/wellness/smartwatches/leaked-apple-watch-12-design-change-is-the-opposite-of-an-upgrade-and-that-has-me-worried">new strap attachment system</a>. Such a change would render all previously acquired Apple Watch straps useless, a move that would no doubt annoy longtime customers far and wide. </p><p>Some insiders think the Series 12 will sport a <a href="https://www.tomsguide.com/news/future-apple-watch-could-have-a-built-in-camera">front-facing camera</a> hidden beneath the display, not for taking pictures, but for unlocking the screen with Face ID or for AI-backed visual scene and object recognition. The <a href="https://www.tomsguide.com/us/best-apple-iphone,review-6348.html">best iPhone</a> models already have a similar Visual Search tool that uses the camera. Perhaps Cupertino is bringing the tech to the Apple Watch next. Either way, this rumor doesn't seem all that likely. </p><p>On the other hand, the addition of a long-retired iPhone feature, Touch ID, seems a tad more plausible. According to a report from <a href="https://www.macworld.com/article/2881882/apple-code-suggests-touch-id-could-be-coming-to-apple-watch.html" target="_blank">Macworld</a>, Apple has at the very least explored adding this much-asked-for feature, which would eliminate the need to punch in a passcode every time you want to unlock the watch.</p><h3 class="article-body__section" id="section-apple-watch-12-ai-features"><span>Apple Watch 12: AI features</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:2008px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="ZxC3rWauVZymkkhUsAUCNm" name="watchOS27-Siri" alt="Close-up of an iPhone and Apple Watch showing a continuous Siri AI conversation" src="https://cdn.mos.cms.futurecdn.net/ZxC3rWauVZymkkhUsAUCNm-1920-80.jpg" mos="" align="middle" fullscreen="" width="2008" height="1130" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>Apple has already confirmed that the next-gen <a href="https://www.tomsguide.com/wellness/smartwatches/watchos-27-all-the-new-features-coming-to-apple-watch-later-this-year#section-watchos-27-new-health-and-fitness-features">watchOS 27</a> operating system will support the company's AI-powered Siri voice assistant. While some older models will also get this feature via a free firmware upgrade, the Apple Watch 12 will likely ship with watchOS 27 pre-installed.</p><p>The real question is, will the new <a href="https://www.tomsguide.com/phones/i-asked-siri-ai-and-gemini-a-series-of-increasingly-bizarre-questions-to-see-how-they-responded-heres-what-happened">Siri AI</a> be ready to roll right from the start when the Series 12 arrives? I'm optimistic it will. Other new AI tools could come in the form of a more personalized wellness concierge that helps you set and maintain goals, sort of like an expansion of <a href="https://www.tomsguide.com/wellness/fitness/i-ran-15-miles-with-the-apple-watchs-new-workout-buddy-heres-my-verdict">Workout Buddy</a> for your overall health.</p><h3 class="article-body__section" id="section-apple-watch-12-battery-life-predictions"><span>Apple Watch 12: Battery life predictions </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:3475px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="PWuMXBhopftXqEiSjvepWY" name="AW11-battery" alt="Apple Watch Series 11 close-up showing the remaining battery life after 24 hours" src="https://cdn.mos.cms.futurecdn.net/PWuMXBhopftXqEiSjvepWY-1920-80.jpg" mos="" align="middle" fullscreen="" width="3475" height="1955" 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 Apple Watch Series 11 received a nice <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review#section-apple-watch-series-11-review-battery-life">battery life increase</a> over the models before it, from 18 hours per charge to 24 hours. Might the Apple Watch 12 last even longer? It's certainly possible! But the stars will have to align.</p><p>While a more efficient processor and display technology could meaningfully reduce power consumption, a larger-capacity battery — which a handful of insiders have suggested — could mean that the Series 12 lasts substantially longer than the Series 11. But don't get too excited; most of the bigger-battery reports have come from less-than-reliable leakers, so this upgrade is far from guaranteed.  </p><h3 class="article-body__section" id="section-apple-watch-12-outlook"><span>Apple Watch 12: Outlook</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="g6cEh4MumgB8V7qrZwi5Nc" name="Apple Watch Series 11-1" alt="Apple Watch Series 11 on a person's wrist" src="https://cdn.mos.cms.futurecdn.net/g6cEh4MumgB8V7qrZwi5Nc-1920-80.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Last year’s <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch Series 11</a> represented a fairly <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-11-vs-apple-watch-10">minor upgrade over the Series 10</a>, with the primary benefit being better battery performance. This makes me hopeful that the Series 12 will be an even bigger jump in performance and features.</p><p>For example, a next-gen sensor array that unlocks new wellness trend data would be a welcome advancement, while support for on-wrist blood pressure readings would be the ultimate holistic upgrade (and a major flex on the competition), even if it's less likely. </p><p>Toss in a fingerprint scanner for unlocking the Series 12, a more power-efficient display, and a larger-capacity battery (why not?), and Apple's new flagship smartwatch starts to look like a legit upgrade over last year's model, rather than an iterative one. </p><p>What do you think? Is the Apple Watch Series 12 something you're excited for, and if so, what features are you hoping for the most? Let me know below. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xpox4O"></div>                            </div>                            <script src="https://kwizly.com/embed/Xpox4O.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/smartwatches/from-fall-detection-to-hypertension-10-apple-watch-innovations-that-changed-the-game"><strong>10 Apple Watch innovations that changed the game — from Fall Detection to Hypertension Alerts</strong></a><strong></strong></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/im-a-smartwatch-reviewer-and-heres-my-apple-watch-series-12-wish-list-three-upgrades-i-want-and-one-i-dont"><strong>I'm a smartwatch reviewer, and here's my Apple Watch Series 12 wish list — three upgrades I want, and one I don't</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/3-apple-watch-settings-i-always-turn-off-to-maximize-battery-life"><strong>3 Apple Watch settings I always turn off to maximize battery life</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-all-the-design-health-and-battery-life-rumors-so-far</link>
                                                                            <description>
                            <![CDATA[ Apple Watch 12 rumor report: New display tech, health tools, and AI features could all be in the cards. Here's everything you need to know about the next flagship Apple Watch. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">v7L8tYjybiGxNj6QZEspM3</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/r2c2FfYmhRm6nb3DhTmXf6-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 26 Aug 2026 12:00:00 +0000</pubDate>                                                                                                                                <updated>Tue, 08 Sep 2026 13:18:39 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></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/r2c2FfYmhRm6nb3DhTmXf6-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Apple Watch 11 on a user&#039;s wrist against a blue background with the app icon grid displayed on the screen]]></media:description>                                                            <media:text><![CDATA[Close-up of the Apple Watch 11 on a user&#039;s wrist against a blue background with the app icon grid displayed on the screen]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Apple Watch 11 on a user&#039;s wrist against a blue background with the app icon grid displayed on the screen]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/r2c2FfYmhRm6nb3DhTmXf6-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Grab a grain of salt and join me; it's time to chew on the biggest Apple Watch rumors of 2026 (so far). With not one but two new models possible on September 9th — the Apple Watch Series 12 and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-all-the-design-health-and-battery-life-rumors-so-far">Apple Watch Ultra 4</a> — there's a lot to cover. So, let's focus on the flagship.</p><p>As is often the case this time of year, leaks and "insider" reports are plentiful, ranging from believable to, well, not. With that in mind, here's everything we think we know about Apple's next flagship wearable, the Apple Watch Series 12, including whether or not it has a chance of making our <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">Best Smartwatch</a> list.</p><h3 class="article-body__section" id="section-apple-watch-12-rumors-in-brief"><span>Apple Watch 12: Rumors in brief</span></h3><ul><li><strong>Price and launch:</strong> Expected to be revealed on September 9's "Surprise and shine" event; preorders will likely open on Saturday, with units shipping the following week; a price increase is possible following</li><li><strong>Health and fitness:</strong> Support for wrist-based blood pressure readings is rumored but remains unlikely; an updated Health app focused on long-term trends is possible; Apple may also (finally) bring users' health, fitness, and medical data under the roof of a singular app</li><li><strong>Design and display:</strong> A more efficient LTPO display is possible; a fingerprint scanner for Touch ID is rumored but less likely; an upgraded ceramic case option is possible</li><li><strong>AI features: </strong> The Series 12 is expected to support Apple's new Siri AI voice assistant; a personalized wellness concierge is also rumored</li><li><strong>Battery life:</strong> A larger capacity battery is possible; the S12 processor could bring efficiency improvements, too</li></ul><h3 class="article-body__section" id="section-apple-watch-12-price-and-launch-predictions"><span>Apple Watch 12: Price and launch predictions</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:2906px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="Yp3ND3TWUcSEqk9mC727n9" name="AppleWatchUltra3-01" alt="Apple Watch Ultra 3, Apple Watch Series 11, Apple Watch SE 3" src="https://cdn.mos.cms.futurecdn.net/Yp3ND3TWUcSEqk9mC727n9-1920-80.jpg" mos="" align="middle" fullscreen="" width="2906" height="1634" 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>Apple tends to hold an annual launch event in the second week of September, and this year is no exception. </p><p>Apple has confirmed a "Surprise and Shine" launch event for Wednesday, September 9th, where we'll likely get our first look at the Apple Watch Series 12, <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-rumors-everything-we-know-about-apples-next-ultra-rugged-smartwatch">Apple Watch Ultra 4</a>, and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-set-to-arrive-this-year-and-here-are-3-upgrades-im-most-excited-for">iPhone 18</a>. That said, with the U.S. Labor Day holiday falling the Monday before, Apple may push the event to Wednesday, September 9th or the following Tuesday, September 15th. </p><p>How much will the Apple Watch 12 cost? With both Samsung and Google increasing pricing across their respective smartwatch lineups — the <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review">Pixel Watch 5</a> now starts at $399, and the <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-to-know-about-the-new-samsung-galaxy-watch-9">Galaxy Watch 9</a> starts at $379 — a price bump for the Apple Watch 12 is possible. Put another way: a $399 starting price for the flagship smartwatch is far from guaranteed. </p><p>There are also rumors of a <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-12-and-ultra-4-rumors-your-next-apple-watch-could-have-a-ceramic-case">ceramic Apple Watch Series 12</a>. The last time Apple offered such an upgrade was in the 2019 Apple Watch Series 5. That model started at $399 for the standard version, but jumped to $1,299 for the ceramic model. So, yeah, if a ceramic Series 12 does exist, it will surely cost a pretty penny. </p><p>In terms of availability, Apple usually opens preorders on the Friday after a Tuesday product announcement, with units hitting store shelves in the weeks that follow; I suspect this will be the case for the Series 12, too. </p><h3 class="article-body__section" id="section-apple-watch-12-health-and-fitness-rumors"><span>Apple Watch 12: Health and fitness rumors </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:3118px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Eqd2jLmCaGjvJLxrQEmFMm" name="Apple-sleep-score-08" alt="Close-up of the Apple Watch Series 11 showing a user's sleep score" src="https://cdn.mos.cms.futurecdn.net/Eqd2jLmCaGjvJLxrQEmFMm-1920-80.jpg" mos="" align="middle" fullscreen="" width="3118" height="1754" 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 Apple Watch Series 12 could arrive with an <a href="https://www.tomsguide.com/wellness/smartwatches/skip-the-apple-watch-11-next-years-apple-watch-12-tipped-for-huge-sensor-upgrade">updated health sensor array</a>. According to a report in <a href="https://www.digitimes.com/news/a20250814PD217/apple-watch-wearable-smart-healthcare-high-end-demand-2026.html" target="_blank">DigiTimes</a> (via <a href="https://wccftech.com/apple-watch-series-12-redesign-2026/" target="_blank">Wccftech</a>), such an upgrade might unlock new holistic metrics or trend reports.  </p><p>We could also see an expansion of Apple’s groundbreaking <a href="https://www.tomsguide.com/wellness/smartwatches/hypertension-tracking-is-now-live-on-the-apple-watch-heres-what-to-do-if-you-get-an-alert">Hypertension Alerts</a> feature. According to <a href="https://www.bloomberg.com/news/newsletters/2025-03-23/apple-aapl-explores-turning-watches-into-wearable-ai-devices-with-cameras-m8ll6mvy" target="_blank">Bloomberg’s Mark Gurman</a>, one of the more trusted Apple insiders, Cupertino is hard at work on a wrist-based blood pressure monitor that provides readings similar to a traditional cuff. The question is, when will it be ready? I'm not convinced 2026 is the year.</p><p>On-wrist blood glucose monitoring is another focus for the Apple Watch team, but <a href="https://www.bloomberg.com/news/newsletters/2025-03-30/apple-readies-biggest-push-into-health-yet-with-revamped-app-ai-doctor-service-m8vl97k2" target="_blank">according to Gurman</a>, that tech is even further out than blood pressure monitoring.  </p><p>You can also expect an overhaul of the onboard Health app, with key metrics better organized in one location and a greater emphasis on long-term wellness trend reporting. </p><p>In fact, according to <a href="https://www.bloomberg.com/news/newsletters/2025-03-23/apple-aapl-explores-turning-watches-into-wearable-ai-devices-with-cameras-m8ll6mvy" target="_blank">Bloomberg's Gurman</a>, there's a possibility that Apple will finally bring all of a user’s health, fitness, and medical data under the roof of a singular app. </p><h3 class="article-body__section" id="section-apple-watch-12-design-and-display-rumors"><span>Apple Watch 12: Design and display rumors</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:2213px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="9BSyzrq4QFNifQ8BoZnMyj" name="dji_mimo_20250909_145252_20250909145253_1757471917429_photo" alt="Apple Watch Series 11" src="https://cdn.mos.cms.futurecdn.net/9BSyzrq4QFNifQ8BoZnMyj-1920-80.jpg" mos="" align="middle" fullscreen="" width="2213" height="1245" 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 Apple Watch Series 12 is rumored to sport an updated processor (likely dubbed S12), which could make it both faster and less power-hungry than the S10 chip in the Series 11. Less likely but still possible: the Series 12 arrives with an LTPO display, which would be more power-efficient than the OLED panel in the Series 11.</p><p>I’d also like to see Apple increase the screen brightness on the Series 12 to 3,000 nits or more (from 2,000 nits) to keep up with the latest Google Pixel Watch 5 and Samsung Galaxy Watch 9. </p><p>Changes to the case dimensions and button layout seem unlikely. The <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-10-review">Series 10</a> ushered in an updated case in 2024, and Apple only tends to switch up the design every four-ish launch cycles. Moreover, <a href="https://www.bloomberg.com/sessions/2026-03-26/live-q-amp-a-ask-mark-gurman-anything-about-apple" target="_blank">Bloomberg’s Mark Gurman</a> also thinks a major design shift is unlikely.</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:970px;"><p class="vanilla-image-block" style="padding-top:56.29%;"><img id="5UZmFrXnmYtGfpn3thBJUh" name="Apple Watch with bands" alt="Apple Watch with bands" src="https://cdn.mos.cms.futurecdn.net/5UZmFrXnmYtGfpn3thBJUh-1920-80.png" mos="" align="middle" fullscreen="" width="970" height="546" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>One design-related rumor I'm hoping doesn't come true is the introduction of a <a href="https://www.tomsguide.com/wellness/smartwatches/leaked-apple-watch-12-design-change-is-the-opposite-of-an-upgrade-and-that-has-me-worried">new strap attachment system</a>. Such a change would render all previously acquired Apple Watch straps useless, a move that would no doubt annoy longtime customers far and wide. </p><p>Some insiders think the Series 12 will sport a <a href="https://www.tomsguide.com/news/future-apple-watch-could-have-a-built-in-camera">front-facing camera</a> hidden beneath the display, not for taking pictures, but for unlocking the screen with Face ID or for AI-backed visual scene and object recognition. The <a href="https://www.tomsguide.com/us/best-apple-iphone,review-6348.html">best iPhone</a> models already have a similar Visual Search tool that uses the camera. Perhaps Cupertino is bringing the tech to the Apple Watch next. Either way, this rumor doesn't seem all that likely. </p><p>On the other hand, the addition of a long-retired iPhone feature, Touch ID, seems a tad more plausible. According to a report from <a href="https://www.macworld.com/article/2881882/apple-code-suggests-touch-id-could-be-coming-to-apple-watch.html" target="_blank">Macworld</a>, Apple has at the very least explored adding this much-asked-for feature, which would eliminate the need to punch in a passcode every time you want to unlock the watch.</p><h3 class="article-body__section" id="section-apple-watch-12-ai-features"><span>Apple Watch 12: AI features</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:2008px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="ZxC3rWauVZymkkhUsAUCNm" name="watchOS27-Siri" alt="Close-up of an iPhone and Apple Watch showing a continuous Siri AI conversation" src="https://cdn.mos.cms.futurecdn.net/ZxC3rWauVZymkkhUsAUCNm-1920-80.jpg" mos="" align="middle" fullscreen="" width="2008" height="1130" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>Apple has already confirmed that the next-gen <a href="https://www.tomsguide.com/wellness/smartwatches/watchos-27-all-the-new-features-coming-to-apple-watch-later-this-year#section-watchos-27-new-health-and-fitness-features">watchOS 27</a> operating system will support the company's AI-powered Siri voice assistant. While some older models will also get this feature via a free firmware upgrade, the Apple Watch 12 will likely ship with watchOS 27 pre-installed.</p><p>The real question is, will the new <a href="https://www.tomsguide.com/phones/i-asked-siri-ai-and-gemini-a-series-of-increasingly-bizarre-questions-to-see-how-they-responded-heres-what-happened">Siri AI</a> be ready to roll right from the start when the Series 12 arrives? I'm optimistic it will. Other new AI tools could come in the form of a more personalized wellness concierge that helps you set and maintain goals, sort of like an expansion of <a href="https://www.tomsguide.com/wellness/fitness/i-ran-15-miles-with-the-apple-watchs-new-workout-buddy-heres-my-verdict">Workout Buddy</a> for your overall health.</p><h3 class="article-body__section" id="section-apple-watch-12-battery-life-predictions"><span>Apple Watch 12: Battery life predictions </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:3475px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="PWuMXBhopftXqEiSjvepWY" name="AW11-battery" alt="Apple Watch Series 11 close-up showing the remaining battery life after 24 hours" src="https://cdn.mos.cms.futurecdn.net/PWuMXBhopftXqEiSjvepWY-1920-80.jpg" mos="" align="middle" fullscreen="" width="3475" height="1955" 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 Apple Watch Series 11 received a nice <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review#section-apple-watch-series-11-review-battery-life">battery life increase</a> over the models before it, from 18 hours per charge to 24 hours. Might the Apple Watch 12 last even longer? It's certainly possible! But the stars will have to align.</p><p>While a more efficient processor and display technology could meaningfully reduce power consumption, a larger-capacity battery — which a handful of insiders have suggested — could mean that the Series 12 lasts substantially longer than the Series 11. But don't get too excited; most of the bigger-battery reports have come from less-than-reliable leakers, so this upgrade is far from guaranteed.  </p><h3 class="article-body__section" id="section-apple-watch-12-outlook"><span>Apple Watch 12: Outlook</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="g6cEh4MumgB8V7qrZwi5Nc" name="Apple Watch Series 11-1" alt="Apple Watch Series 11 on a person's wrist" src="https://cdn.mos.cms.futurecdn.net/g6cEh4MumgB8V7qrZwi5Nc-1920-80.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Last year’s <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-11-review">Apple Watch Series 11</a> represented a fairly <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-11-vs-apple-watch-10">minor upgrade over the Series 10</a>, with the primary benefit being better battery performance. This makes me hopeful that the Series 12 will be an even bigger jump in performance and features.</p><p>For example, a next-gen sensor array that unlocks new wellness trend data would be a welcome advancement, while support for on-wrist blood pressure readings would be the ultimate holistic upgrade (and a major flex on the competition), even if it's less likely. </p><p>Toss in a fingerprint scanner for unlocking the Series 12, a more power-efficient display, and a larger-capacity battery (why not?), and Apple's new flagship smartwatch starts to look like a legit upgrade over last year's model, rather than an iterative one. </p><p>What do you think? Is the Apple Watch Series 12 something you're excited for, and if so, what features are you hoping for the most? Let me know below. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xpox4O"></div>                            </div>                            <script src="https://kwizly.com/embed/Xpox4O.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/smartwatches/from-fall-detection-to-hypertension-10-apple-watch-innovations-that-changed-the-game"><strong>10 Apple Watch innovations that changed the game — from Fall Detection to Hypertension Alerts</strong></a><strong></strong></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/im-a-smartwatch-reviewer-and-heres-my-apple-watch-series-12-wish-list-three-upgrades-i-want-and-one-i-dont"><strong>I'm a smartwatch reviewer, and here's my Apple Watch Series 12 wish list — three upgrades I want, and one I don't</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/3-apple-watch-settings-i-always-turn-off-to-maximize-battery-life"><strong>3 Apple Watch settings I always turn off to maximize battery life</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Garmin Fenix 9 has launched, so I went hunting for deals on the Fenix 8 and other older models — here’s what I found ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Garmin has launched the latest models of its flagship Fenix adventure watch, with the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor">Fenix 9 and Fenix 9 Pro</a> set to go on sale on Friday, August 28.</p><p>Both look fantastic, with upgrades to the design and software that include the largest screen ever on a Fenix with the 51mm models, full titanium cases on the Pro models, and a faster mapping experience.</p><p>While the Fenix 9 and Fenix 9 Pro might be the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches</a> available, you may get better value by opting for an older model, with the Garmin Fenix 8 and Garmin Fenix 8 Pro both reduced right now. The <a href="https://www.amazon.com/Garmin-Connected-Multisport-Smartwatch-Technology/dp/B0FPMGFV9G" target="_blank" rel="nofollow">Fenix 8 Pro is down to $949 at Amazon,</a> while the Fenix 8 is down to $849 at Amazon.</p><div class="product"><a data-dimension112="2f80cb3e-a134-11f1-a6ae-f1240804f88b" data-action="Deal Block" data-label="Fenix 8" data-dimension48="Fenix 8" data-dimension25="$749" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:694px;"><p class="vanilla-image-block" style="padding-top:116.86%;"><img id="DUPZqNYp7WjoWX5YqacXLE" name="Garmin Fenix 8" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DUPZqNYp7WjoWX5YqacXLE-1920-80.png" mos="" align="middle" fullscreen="" width="694" height="811" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>All three sizes of the Garmin Fenix 8 are reduced in the Amazon sale, and you can get them with either steel or titanium cases. The lowest price available is on the steel 43mm or 47mm watches, while titanium models cost $100 more.<a class="view-deal button" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R/" target="_blank" rel="nofollow" data-dimension112="2f80cb3e-a134-11f1-a6ae-f1240804f88b" data-action="Deal Block" data-label="Fenix 8" data-dimension48="Fenix 8" data-dimension25="$749">View Deal</a></p></div><div class="product"><a data-dimension112="2f80cbb6-a134-11f1-94c1-5f4ea2f45cb1" data-action="Deal Block" data-label="Fenix 8 Pro" data-dimension48="Fenix 8 Pro" data-dimension25="$949" href="https://www.amazon.com/Garmin-Connected-Multisport-Smartwatch-Technology/dp/B0FPMGFV9G" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1077px;"><p class="vanilla-image-block" style="padding-top:117.46%;"><img id="hvGcvSCXeNBAAhk6HMZLN8" name="Fenix 8 Pro" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hvGcvSCXeNBAAhk6HMZLN8-1920-80.png" mos="" align="middle" fullscreen="" width="1077" height="1265" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Garmin Fenix 8 Pro has satellite and LTE connectivity on top of all the excellent sports tracking and navigation tools it offers, so this $250 saving is worth looking at if you regularly spend your free time off the grid. <a class="view-deal button" href="https://www.amazon.com/Garmin-Connected-Multisport-Smartwatch-Technology/dp/B0FPMGFV9G" target="_blank" rel="nofollow" data-dimension112="2f80cbb6-a134-11f1-94c1-5f4ea2f45cb1" data-action="Deal Block" data-label="Fenix 8 Pro" data-dimension48="Fenix 8 Pro" data-dimension25="$949">View Deal</a></p></div><h2 id="new-features-are-rolling-back-to-the-fenix-8-and-fenix-8-pro">New features are rolling back to the Fenix 8 and Fenix 8 Pro</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="WTCmBvypKiCgqhr6NRVdNa" name="Garmin Fenix 8 Pro" alt="Garmin Fenix 8 Pro" src="https://cdn.mos.cms.futurecdn.net/WTCmBvypKiCgqhr6NRVdNa-1920-80.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>These deals are especially interesting because <a href="https://www.dcrainmaker.com/2026/08/garmin-fenix9-software-feature-overview.html" target="_blank">according to DC Rainmaker</a>, Garmin is going to bring almost all of the new features from the Fenix 9 line-up to the Fenix 8 and <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-8-pro-review-the-greatest-fenix-yet">Fenix 8 Pro</a>.</p><p>Last year Garmin updated its software platform to make it the same across a wide range of models, and that means it’s easier for new features to be rolled back to older watches.</p><p>Some of the flagship features launched on the Fenix 9, like the Epic tool for grouping activities and upgraded Stamina feature for judging your effort during long activities, will be available on the Fenix 8 and Fenix 8 Pro (along with the <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-garmin-forerunner-970-for-six-months-here-are-my-long-term-pros-and-cons">Garmin Forerunner 970</a>).</p><p>Older watches also get the updated rucking and rowing features, including VO2 max based on rowing activities, and the improved grade adjusted pace stats during runs.</p><h2 id="the-fenix-9-still-has-some-exclusive-upgrades">The Fenix 9 still has some exclusive upgrades</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1485px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="kXiKhRWe86qomugNvt8ky9" name="vJ8mM3GdPthVTRngYK3FaP" alt="Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/kXiKhRWe86qomugNvt8ky9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1485" height="836" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>Naturally there are still some reasons to opt for the new watch, such as the design upgrades — the all-titanium case on the Fenix 9 Pro is attractive and the 1.5in screen on the 51mm models will be exciting for those with big wrists.</p><p>The Fenix 9 line-up also gets mapping upgrades that will make it faster and smoother to pan and zoom on the maps, and archery features that will be nigh-on essential if that’s your main sport.</p><p>As always, you can expect future software updates to come to the Fenix 9 and Fenix 9 Pro for longer than they will on the older watches too, and the new Pro models also have a green light mode on the built-in flashlight that’s exclusive to them.</p><p>However, if you don’t need to have the latest and greatest device on your wrist, I think there’s certainly better value to be had by opting for a Fenix 8 right now, especially the Fenix 8 Pro which has Garmin’s LTE and satellite connectivity.</p><p>To get those features, you pay a minimum of $1,199 for the Fenix 9 Pro InReach model, and the standard Fenix 9 starts at $999 compared to $749 for the Fenix 8 in the sales.</p><p>For those who don’t mind going for an even older device and just want a rugged Garmin adventure watch with maps and an AMOLED display, the <a href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFDZ6KB" target="_blank" rel="nofollow">Garmin Epix Pro is $519 on Amazon</a> right now, down from $999.</p><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Everything&rows=6&view_mode=savings_squad&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-has-launched-so-i-went-hunting-for-deals-on-the-fenix-8-and-other-older-models-heres-what-i-found</link>
                                                                            <description>
                            <![CDATA[ The Garmin Fenix 9 and Fenix 9 Pro have launched, but before you jump on the new watch, it’s worth looking at deals on the Fenix 8 and Fenix 8 Pro. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">Z2rnrrLHXAfwSDbmobrkVQ</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/xuWjffnhUTEUCYYnhvySjd-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 26 Aug 2026 10:54:26 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Nick Harris-Fry ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/J5Jjp49GUVjLZEbjEkTex-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/xuWjffnhUTEUCYYnhvySjd-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Garmin Fenix 8 and Fenix 8 Pro Savings Squad]]></media:description>                                                            <media:text><![CDATA[Garmin Fenix 8 and Fenix 8 Pro Savings Squad]]></media:text>
                                <media:title type="plain"><![CDATA[Garmin Fenix 8 and Fenix 8 Pro Savings Squad]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/xuWjffnhUTEUCYYnhvySjd-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Garmin has launched the latest models of its flagship Fenix adventure watch, with the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor">Fenix 9 and Fenix 9 Pro</a> set to go on sale on Friday, August 28.</p><p>Both look fantastic, with upgrades to the design and software that include the largest screen ever on a Fenix with the 51mm models, full titanium cases on the Pro models, and a faster mapping experience.</p><p>While the Fenix 9 and Fenix 9 Pro might be the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches</a> available, you may get better value by opting for an older model, with the Garmin Fenix 8 and Garmin Fenix 8 Pro both reduced right now. The <a href="https://www.amazon.com/Garmin-Connected-Multisport-Smartwatch-Technology/dp/B0FPMGFV9G" target="_blank" rel="nofollow">Fenix 8 Pro is down to $949 at Amazon,</a> while the Fenix 8 is down to $849 at Amazon.</p><div class="product"><a data-dimension112="2f80cb3e-a134-11f1-a6ae-f1240804f88b" data-action="Deal Block" data-label="Fenix 8" data-dimension48="Fenix 8" data-dimension25="$749" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:694px;"><p class="vanilla-image-block" style="padding-top:116.86%;"><img id="DUPZqNYp7WjoWX5YqacXLE" name="Garmin Fenix 8" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DUPZqNYp7WjoWX5YqacXLE-1920-80.png" mos="" align="middle" fullscreen="" width="694" height="811" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>All three sizes of the Garmin Fenix 8 are reduced in the Amazon sale, and you can get them with either steel or titanium cases. The lowest price available is on the steel 43mm or 47mm watches, while titanium models cost $100 more.<a class="view-deal button" href="https://www.amazon.com/Garmin-f%C4%93nix%C2%AE-Multisport-Long-Lasting-Built/dp/B0DC6ZD31R/" target="_blank" rel="nofollow" data-dimension112="2f80cb3e-a134-11f1-a6ae-f1240804f88b" data-action="Deal Block" data-label="Fenix 8" data-dimension48="Fenix 8" data-dimension25="$749">View Deal</a></p></div><div class="product"><a data-dimension112="2f80cbb6-a134-11f1-94c1-5f4ea2f45cb1" data-action="Deal Block" data-label="Fenix 8 Pro" data-dimension48="Fenix 8 Pro" data-dimension25="$949" href="https://www.amazon.com/Garmin-Connected-Multisport-Smartwatch-Technology/dp/B0FPMGFV9G" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1077px;"><p class="vanilla-image-block" style="padding-top:117.46%;"><img id="hvGcvSCXeNBAAhk6HMZLN8" name="Fenix 8 Pro" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hvGcvSCXeNBAAhk6HMZLN8-1920-80.png" mos="" align="middle" fullscreen="" width="1077" height="1265" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Garmin Fenix 8 Pro has satellite and LTE connectivity on top of all the excellent sports tracking and navigation tools it offers, so this $250 saving is worth looking at if you regularly spend your free time off the grid. <a class="view-deal button" href="https://www.amazon.com/Garmin-Connected-Multisport-Smartwatch-Technology/dp/B0FPMGFV9G" target="_blank" rel="nofollow" data-dimension112="2f80cbb6-a134-11f1-94c1-5f4ea2f45cb1" data-action="Deal Block" data-label="Fenix 8 Pro" data-dimension48="Fenix 8 Pro" data-dimension25="$949">View Deal</a></p></div><h2 id="new-features-are-rolling-back-to-the-fenix-8-and-fenix-8-pro">New features are rolling back to the Fenix 8 and Fenix 8 Pro</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="WTCmBvypKiCgqhr6NRVdNa" name="Garmin Fenix 8 Pro" alt="Garmin Fenix 8 Pro" src="https://cdn.mos.cms.futurecdn.net/WTCmBvypKiCgqhr6NRVdNa-1920-80.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>These deals are especially interesting because <a href="https://www.dcrainmaker.com/2026/08/garmin-fenix9-software-feature-overview.html" target="_blank">according to DC Rainmaker</a>, Garmin is going to bring almost all of the new features from the Fenix 9 line-up to the Fenix 8 and <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-8-pro-review-the-greatest-fenix-yet">Fenix 8 Pro</a>.</p><p>Last year Garmin updated its software platform to make it the same across a wide range of models, and that means it’s easier for new features to be rolled back to older watches.</p><p>Some of the flagship features launched on the Fenix 9, like the Epic tool for grouping activities and upgraded Stamina feature for judging your effort during long activities, will be available on the Fenix 8 and Fenix 8 Pro (along with the <a href="https://www.tomsguide.com/wellness/smartwatches/ive-been-wearing-the-garmin-forerunner-970-for-six-months-here-are-my-long-term-pros-and-cons">Garmin Forerunner 970</a>).</p><p>Older watches also get the updated rucking and rowing features, including VO2 max based on rowing activities, and the improved grade adjusted pace stats during runs.</p><h2 id="the-fenix-9-still-has-some-exclusive-upgrades">The Fenix 9 still has some exclusive upgrades</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1485px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="kXiKhRWe86qomugNvt8ky9" name="vJ8mM3GdPthVTRngYK3FaP" alt="Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/kXiKhRWe86qomugNvt8ky9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1485" height="836" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>Naturally there are still some reasons to opt for the new watch, such as the design upgrades — the all-titanium case on the Fenix 9 Pro is attractive and the 1.5in screen on the 51mm models will be exciting for those with big wrists.</p><p>The Fenix 9 line-up also gets mapping upgrades that will make it faster and smoother to pan and zoom on the maps, and archery features that will be nigh-on essential if that’s your main sport.</p><p>As always, you can expect future software updates to come to the Fenix 9 and Fenix 9 Pro for longer than they will on the older watches too, and the new Pro models also have a green light mode on the built-in flashlight that’s exclusive to them.</p><p>However, if you don’t need to have the latest and greatest device on your wrist, I think there’s certainly better value to be had by opting for a Fenix 8 right now, especially the Fenix 8 Pro which has Garmin’s LTE and satellite connectivity.</p><p>To get those features, you pay a minimum of $1,199 for the Fenix 9 Pro InReach model, and the standard Fenix 9 starts at $999 compared to $749 for the Fenix 8 in the sales.</p><p>For those who don’t mind going for an even older device and just want a rugged Garmin adventure watch with maps and an AMOLED display, the <a href="https://www.amazon.com/Garmin-Performance-Smartwatch-Technology-Flashlight/dp/B0BYFDZ6KB" target="_blank" rel="nofollow">Garmin Epix Pro is $519 on Amazon</a> right now, down from $999.</p><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Everything&rows=6&view_mode=savings_squad&widget_title=Top+Deals+Handpicked+by+Our+Editors&widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Garmin Fenix 9 is here, and it’s brighter and thinner than its predecessor ]]></title>
                                                                                                <dc:content><![CDATA[ <p>If you weren’t following along with our <a href="https://www.tomsguide.com/news/live/garmin-fenix-9-event">Garmin ‘Play Harder’ live blog</a> (where were you?), you might have missed Garmin’s latest announcement: the Garmin Fenix 9 and Fenix 9 Pro just dropped. </p><p>Below, we’ve rounded up all the information about Garmin’s latest high-end outdoor watches. </p><h3 class="article-body__section" id="section-garmin-fenix-9-specs"><span>Garmin Fenix 9: Specs </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:2446px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="HzyJBZg5Fz4ncDaUfJ3oY" name="Fenix 9" alt="Garmin Fenix 9" src="https://cdn.mos.cms.futurecdn.net/HzyJBZg5Fz4ncDaUfJ3oY-1920-80.jpg" mos="" align="middle" fullscreen="" width="2446" height="1376" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>The Garmin Fenix 9 will be available to pre-order on August 28, starting at $999. It’s available in three different sizes: 43mm, 47mm, and 51mm. Here are the key stats:</p><ul><li>Up to 29 days of battery life in smartwatch mode on the 51mm version of the watch; this drops to up to 16 days on the 47mm version and 10 days on the 43mm version.</li><li>The Fenix 9 has an AMOLED display that is double the brightness of the Fenix 8.</li><li>It has a scratch-resistant sapphire lens and is dive-rated up to 40m.</li><li>The watch now has 64GB of memory built-in, which equates to around 7,000 songs. It also means you can download twice as many maps as you could on the Fenix 8.</li><li>Both the Garmin Fenix 9 and Fenix 9 Pro have new CustomFit accessory bands available: this is a fabric band designed for a comfortable fit.</li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:6663px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="mWPWaKCVm36VcYs6WBEkVG" name="20260428_SOCIAL_RECOD_4282_cmyk" alt="Garmin Fenix 9" src="https://cdn.mos.cms.futurecdn.net/mWPWaKCVm36VcYs6WBEkVG-1920-80.jpg" mos="" align="middle" fullscreen="" width="6663" height="3748" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><h3 class="article-body__section" id="section-garmin-fenix-9-pro-specs"><span>Garmin Fenix 9 Pro: Specs</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:2566px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="adZYMZc7vxvcSLAq6VNnSa" name="Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/adZYMZc7vxvcSLAq6VNnSa-1920-80.jpg" mos="" align="middle" fullscreen="" width="2566" height="1444" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>The Garmin Fenix 9 Pro is also available to pre-order later this week, on August 28, and starts at $1099. Here’s what you need to know: </p><ul><li>The Fenix 9 Pro is available in three different sizes: 43mm, 47mm, and 51mm.</li><li>When it comes to battery life, you can get up to 31 days of battery life in smartwatch mode with the 51mm AMOLED display. Solar charging models can get up to 57 days of battery life.</li><li>The Pro models are available with or without inReach connectivity. For the first time, it is available on all Fenix 9 Pro size options.</li><li>The 9 Pro is the first Fenix to feature a titanium watch case, which is thinner than its predecessor.</li><li>The Fenix 9 Pro AMOLED display has 3,000 nits of brightness.</li><li>The 51mm Pro includes Garmin’s first 1.5-inch AMOLED display, which is 15% larger than the Fenix 8.</li><li>The integrated LED flashlight now has a green mode.</li></ul><h3 class="article-body__section" id="section-what-else-was-announced-today"><span>What else was announced today? </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:7075px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="JyKN7NYgr5uWBf2MLPmm75" name="20260428_SOCIAL_RECOD_1525" alt="a photo of the Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/JyKN7NYgr5uWBf2MLPmm75-1920-80.jpg" mos="" align="middle" fullscreen="" width="7075" height="3980" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>Two new features were also announced along with the Fenix 9 range. First up, a free Garmin Epic feature, which allows you to turn multiple activities into a cohesive story in the Garmin Connect app. You can group activities recorded over several days, weeks, or months to see your health and performance data during that time. You can also add notes and photos to create an ‘Epic’ that you can share with friends and family. </p><p>There were also some new stamina tracking features announced today — stamina zones and stamina curve. The stamina zones will now be available in the post-activity summary.</p><p>There's also a new stamina curve feature, which is an easy-to-understand visual representation of your fitness and how aerobic and anaerobic workouts alike contribute to your improving stamina.</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/smartwatches/garmin-fenix-9-is-here-and-its-brighter-and-thinner-than-its-predecessor</link>
                                                                            <description>
                            <![CDATA[ Here's everything you need to know about Garmin's new watches ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">e3dBcVCMpx8vXzSMJT8AyA</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/kXiKhRWe86qomugNvt8ky9-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 25 Aug 2026 12:26:48 +0000</pubDate>                                                                                                                                <updated>Tue, 25 Aug 2026 13:28:30 +0000</updated>
                                                                                                                                            <category><![CDATA[Smartwatches]]></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/kXiKhRWe86qomugNvt8ky9-1920-80.jpg">
                                                            <media:credit><![CDATA[Garmin]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Fenix 9 Pro]]></media:description>                                                            <media:text><![CDATA[Fenix 9 Pro]]></media:text>
                                <media:title type="plain"><![CDATA[Fenix 9 Pro]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/kXiKhRWe86qomugNvt8ky9-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>If you weren’t following along with our <a href="https://www.tomsguide.com/news/live/garmin-fenix-9-event">Garmin ‘Play Harder’ live blog</a> (where were you?), you might have missed Garmin’s latest announcement: the Garmin Fenix 9 and Fenix 9 Pro just dropped. </p><p>Below, we’ve rounded up all the information about Garmin’s latest high-end outdoor watches. </p><h3 class="article-body__section" id="section-garmin-fenix-9-specs"><span>Garmin Fenix 9: Specs </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:2446px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="HzyJBZg5Fz4ncDaUfJ3oY" name="Fenix 9" alt="Garmin Fenix 9" src="https://cdn.mos.cms.futurecdn.net/HzyJBZg5Fz4ncDaUfJ3oY-1920-80.jpg" mos="" align="middle" fullscreen="" width="2446" height="1376" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>The Garmin Fenix 9 will be available to pre-order on August 28, starting at $999. It’s available in three different sizes: 43mm, 47mm, and 51mm. Here are the key stats:</p><ul><li>Up to 29 days of battery life in smartwatch mode on the 51mm version of the watch; this drops to up to 16 days on the 47mm version and 10 days on the 43mm version.</li><li>The Fenix 9 has an AMOLED display that is double the brightness of the Fenix 8.</li><li>It has a scratch-resistant sapphire lens and is dive-rated up to 40m.</li><li>The watch now has 64GB of memory built-in, which equates to around 7,000 songs. It also means you can download twice as many maps as you could on the Fenix 8.</li><li>Both the Garmin Fenix 9 and Fenix 9 Pro have new CustomFit accessory bands available: this is a fabric band designed for a comfortable fit.</li></ul><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:6663px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="mWPWaKCVm36VcYs6WBEkVG" name="20260428_SOCIAL_RECOD_4282_cmyk" alt="Garmin Fenix 9" src="https://cdn.mos.cms.futurecdn.net/mWPWaKCVm36VcYs6WBEkVG-1920-80.jpg" mos="" align="middle" fullscreen="" width="6663" height="3748" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><h3 class="article-body__section" id="section-garmin-fenix-9-pro-specs"><span>Garmin Fenix 9 Pro: Specs</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:2566px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="adZYMZc7vxvcSLAq6VNnSa" name="Fenix 9 Pro" alt="Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/adZYMZc7vxvcSLAq6VNnSa-1920-80.jpg" mos="" align="middle" fullscreen="" width="2566" height="1444" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>The Garmin Fenix 9 Pro is also available to pre-order later this week, on August 28, and starts at $1099. Here’s what you need to know: </p><ul><li>The Fenix 9 Pro is available in three different sizes: 43mm, 47mm, and 51mm.</li><li>When it comes to battery life, you can get up to 31 days of battery life in smartwatch mode with the 51mm AMOLED display. Solar charging models can get up to 57 days of battery life.</li><li>The Pro models are available with or without inReach connectivity. For the first time, it is available on all Fenix 9 Pro size options.</li><li>The 9 Pro is the first Fenix to feature a titanium watch case, which is thinner than its predecessor.</li><li>The Fenix 9 Pro AMOLED display has 3,000 nits of brightness.</li><li>The 51mm Pro includes Garmin’s first 1.5-inch AMOLED display, which is 15% larger than the Fenix 8.</li><li>The integrated LED flashlight now has a green mode.</li></ul><h3 class="article-body__section" id="section-what-else-was-announced-today"><span>What else was announced today? </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:7075px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="JyKN7NYgr5uWBf2MLPmm75" name="20260428_SOCIAL_RECOD_1525" alt="a photo of the Garmin Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/JyKN7NYgr5uWBf2MLPmm75-1920-80.jpg" mos="" align="middle" fullscreen="" width="7075" height="3980" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>Two new features were also announced along with the Fenix 9 range. First up, a free Garmin Epic feature, which allows you to turn multiple activities into a cohesive story in the Garmin Connect app. You can group activities recorded over several days, weeks, or months to see your health and performance data during that time. You can also add notes and photos to create an ‘Epic’ that you can share with friends and family. </p><p>There were also some new stamina tracking features announced today — stamina zones and stamina curve. The stamina zones will now be available in the post-activity summary.</p><p>There's also a new stamina curve feature, which is an easy-to-understand visual representation of your fitness and how aerobic and anaerobic workouts alike contribute to your improving stamina.</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[ Garmin ‘Play Harder’ LIVE: Fenix 9 and 9 Pro announced ]]></title>
                                                                                                <dc:content><![CDATA[ <div class="live-content"><p>It’s (another) Garmin launch day, and according to rumors, the Garmin Fenix 9 is hours away from dropping. </p><p>Garmin has quietly announced a ‘Play Harder’ launch, which will happen on YouTube at 4am PT and 7am ET in the US, 12pm BST in the UK. </p><p>If you've been following the <a href="https://www.notebookcheck.com/Garmin-Fenix-9-Pro-leakt-auf-Bildern-samt-AMOLED-und-Solar-MiP-Version.1377290.0.html" target="_blank">rumors and leaks</a>, it's looking like we're getting a revised titanium design that stays true to the Fenix look. On top of that, you'll be able to pick from an AMOLED display or MiP screen with solar cells for charging on-the-go.</p><p>Stay tuned for all the updates as they happen here on Tom’s Guide. </p><h2 class="article-body__section" id="section-garmin-event-live-updates"><span>Garmin event: LIVE updates</span></h2></div><div class="live-content"><time datetime="2026-08-25T08:53:20+00:00">August 25, 2026 – 4:53 AM</time><h2 id="what-are-we-predicting">What are we predicting? </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CvzABggpzc4uM96BMLUgsK" name="Garmin Fenix 8 Pro" alt="Garmin Fenix 8 Pro" src="https://cdn.mos.cms.futurecdn.net/CvzABggpzc4uM96BMLUgsK-1920-80.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>What are we predicting? According to our resident Garmin expert, Nick Harris-Fry, the Garmin Fenix 9 and Enduro 4. </p><p>Why? Firstly, the timing of the event. It's been a couple of years (almost to the day) since Garmin put on a similar event to launch the<a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-8-vs-garmin-fenix-8-pro-should-you-upgrade"> <u>Garmin Fenix 8</u></a> and<a href="https://www.tomsguide.com/wellness/smartwatches/garmin-enduro-3-review"> <u>Garmin Enduro 3</u></a> and it ties in with UTMB in Chamonix, France, which is one of the biggest weeks on the ultramarathon running calendar.</p></div><div class="live-content"><time datetime="2026-08-25T09:10:38+00:00">August 25, 2026 – 5:10 AM</time><h2 id="what-have-garmin-said-so-far">What have Garmin said so far?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2550px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="u9hVyDJcNttY6FBXkqqUaK" name="Garmin - Media Launch Invite" alt="a screenshot from the Garmin Play Harder event" src="https://cdn.mos.cms.futurecdn.net/u9hVyDJcNttY6FBXkqqUaK-1920-80.jpg" mos="" align="middle" fullscreen="" width="2550" height="1435" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>Garmin typically keeps pretty tight-lipped about leaks and launches, yet there's another reason to think this isn't the rumored <a href="https://www.tomsguide.com/wellness/smart-rings/garmin-looks-to-be-developing-a-smart-ring-heres-what-we-know-so-far">Cirqa smart ring </a>dropping.  Garmin's CEO Cliff Pemble said earlier this year that there would be a “<a href="https://www.tomsguide.com/wellness/smartwatches/garmin-plans-a-significant-number-of-new-product-introductions-in-its-outdoor-segment-in-2026-could-this-mean-the-fenix-9"><u>significant number of new product introductions”</u></a> in the outdoor category in the second half of 2026. </p></div><div class="live-content"><time datetime="2026-08-25T09:45:07+00:00">August 25, 2026 – 5:45 AM</time><h2 id="here-39-s-what-i-39-m-hoping-for-from-the-fenix-9">Here's what I'm hoping for from the Fenix 9</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1833px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Y2s69jNNkPbEZeF9TBAEkW" name="Garmin Fenix 8 3.jpg" alt="Garmin Fenix 8 watch" src="https://cdn.mos.cms.futurecdn.net/Y2s69jNNkPbEZeF9TBAEkW-1920-80.jpg" mos="" align="middle" fullscreen="" width="1833" height="1031" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>I realise I never introduced myself: I'm Jane McGuire, the Fitness Editor here at Tom's Guide, and I've been writing about Garmin for the past decade.</p><p>As a female marathon runner, I've said it time and time again — don't put all the best recovery and safety features on watches that are huge on our wrists! I'm hoping for a return of the 43mm Fenix 9 Pro, which wasn't available for the Fenix 8 Pro.</p><p>Hopefully, I'm in luck. A leak spotted by <a href="https://www.fitness-tracker-test.info/en/garmin-fenix-9-livestream-event-and-first-product-listings/" target="_blank">Fitness Tracker Test</a> suggested that three sizes would be available for both watches — 43mm, 47mm, and 51mm — with AMOLED and MIP versions of the Pro watch.</p></div><div class="live-content"><time datetime="2026-08-25T10:01:05+00:00">August 25, 2026 – 6:01 AM</time><h2 id="what-about-the-enduro-4">What about the Enduro 4? </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:664px;"><p class="vanilla-image-block" style="padding-top:56.33%;"><img id="CUejPqjarLjrQFDHfkpP35" name="Garmin Enduro 3" alt="Garmin Enduro 3" src="https://cdn.mos.cms.futurecdn.net/CUejPqjarLjrQFDHfkpP35-1920-80.jpg" mos="" align="middle" fullscreen="" width="664" height="374" 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>What about the Enduro 4? While the screens on the new Fenix 9 models are likely to get brighter, the Enduro range has traditionally been a MIP watch with the best battery life in the Garmin line-up, and we’d expect that to be the case with the Enduro 4. </p><p>The fact that the YouTube invite features a photo of a man surfing, we can expect this launch to focus on rugged, outdoor watches, and the Enduro fits this brief. </p></div><div class="live-content"><time datetime="2026-08-25T10:16:45+00:00">August 25, 2026 – 6:16 AM</time><h2 id="how-to-watch">How to watch! </h2><div class="youtube-video" data-nosnippet ><div class="video-aspect-box"><iframe data-lazy-priority="low" data-lazy-src="https://www.youtube-nocookie.com/embed/WFW9SdPrjAo" allowfullscreen></iframe></div></div><p>There's less than an hour to go, so a reminder of how to watch the Garmin Play Harder event. The event will stream live on YouTube, so you can follow along live, or just keep an eye on our Live Blog if you don't want your boss to see you watching at your desk. Your secret is safe with us. </p></div><div class="live-content"><time datetime="2026-08-25T10:38:24+00:00">August 25, 2026 – 6:38 AM</time><h2 id="the-garmin-leaks-are-leaking">The Garmin leaks are leaking </h2><p>It seems like the rumors are correct: get ready for the Fenix 9. <a href="https://gadgetsandwearables.com/2026/08/25/garmin-fenix-9-pro-specs-features-leak/" target="_blank">Gadgets & Wearables</a> spotted an official listing of the Garmin Fenix 9 Pro via the company's Taiwan website before it was quickly taken down.</p><p>The Fenix 9 Pro 47mm listing, according to Gadgets & Wearables, gets a fully titanium case rather than the Fenix 8 Pro's titanium bezel and backplate, with a plastic middle. Not long to go! </p></div><div class="live-content"><time datetime="2026-08-25T10:59:13+00:00">August 25, 2026 – 6:59 AM</time><h2 id="here-we-go">HERE WE GO! </h2><p>If you're just joining us, the Garmin Play Harder event is about to begin, scroll down for the YouTube link if you want to watch with us live. </p></div><div class="live-content"><time datetime="2026-08-25T11:04:21+00:00">August 25, 2026 – 7:04 AM</time><h2 id="it-39-s-official-the-fenix-9-is-here">It's official: the Fenix 9 is here </h2><p>We just got our first look at the Fenix 9, and we're only 3 minutes into the launch. </p><p>The Fenix 9 and Fenix 9 pro have just been announced. </p></div><div class="live-content"><time datetime="2026-08-25T11:09:22+00:00">August 25, 2026 – 7:09 AM</time><h2 id="fenix-9-pro-the-details">Fenix 9 Pro: The details </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:989px;"><p class="vanilla-image-block" style="padding-top:56.22%;"><img id="Xedkqb55iVvNCZUSjFPsV3" name="Screenshot 2026-08-25 at 12.04.10" alt="Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/Xedkqb55iVvNCZUSjFPsV3-1920-80.png" mos="" align="middle" fullscreen="" width="989" height="556" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>Here's what Garmin just announced about the Fenix 9 Pro: </p><ul><li>Thinner than the Fenix 8 Pro at 47mm</li><li>The watch features a titanium case and a sapphire lens</li><li>New build increases strength and durability without adding weight</li><li>The watch has a green flashlight for the first time</li><li>Available in three different sizes: 43mm, 47mm, 51mm</li><li>The 51mm Fenix 9 Pro has the largest display Garmin has ever released at 1.5 inches. It also has a brightness of 3,000 nits</li></ul></div><div class="live-content"><time datetime="2026-08-25T11:13:01+00:00">August 25, 2026 – 7:13 AM</time><h2 id="garmin-announces-a-new-feature-garmin-epic">Garmin announces a new feature: Garmin Epic</h2><p>With the Fenix 9 and the 9 Pro, Garmin has announced a new feature: Garmin Epic. This allows you to group multiple activities for a longer adventure, such as a weekend skiing trip. You'll be able to see different activities, recoveries, notes, and photos. </p><p>Andrew Perkins, Garmin's Product Manager, confirmed users will be able to go back through activites in Garmin Connect to try this. </p></div><div class="live-content"><time datetime="2026-08-25T11:23:22+00:00">August 25, 2026 – 7:23 AM</time><h2 id="fenix-9-the-details">Fenix 9: The details </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1485px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="kXiKhRWe86qomugNvt8ky9" name="vJ8mM3GdPthVTRngYK3FaP" alt="Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/kXiKhRWe86qomugNvt8ky9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1485" height="836" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>Here's what just got announced about the Fenix 9: </p><ul><li>New mapping engine is 30% faster than the Fenix 8</li><li>64GB memory</li><li>AMOLED display is twice as bright as the Fenix 8</li><li>Dive-rated up to 40m</li><li>Available in three sizes: 43mm, 47mm, 51mm</li></ul></div><div class="live-content"><time datetime="2026-08-25T11:25:02+00:00">August 25, 2026 – 7:25 AM</time><h2 id="garmin-announces-new-mapping-features-on-the-fenix-9-and-9-pro">Garmin announces new mapping features on the Fenix 9 and 9 Pro</h2><p>Garmin says they have redesigned the mapping engines for the Fenix 9 and 9 Pro, making zooming in on the app smoother and more user friendly. The mapping on the watches is also more responsive, allowing for faster panning. They'll also be a new perspective view on the watch. </p></div><div class="live-content"><time datetime="2026-08-25T11:37:36+00:00">August 25, 2026 – 7:37 AM</time><h2 id="how-much-do-the-new-watches-cost">How much do the new watches cost? </h2><p>The Fenix 9 and Fenix 9 Pro just hit the Garmin website, here's how much you can expect to pay: </p><div ><table><caption>Fenix 9 line-up cost</caption><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>43mm</strong></p></td><td  ><p><strong>47mm</strong></p></td><td  ><p><strong>51mm</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Fenix 9</strong></p></td><td  ><p>$999</p></td><td  ><p>$999</p></td><td  ><p>$1099</p></td></tr><tr><td class="firstcol " ><p><strong>Fenix 9 Pro</strong></p></td><td  ><p>$1099 without InReach Connectivity/$1199 with InReach</p></td><td  ><p>$1099 without InReach Connectivity/$1199 with InReach</p></td><td  ><p>$1199 without InReach Connectivity/$1299 with InReach</p></td></tr><tr><td class="firstcol " ><p><strong>Fenix 9 Pro Solar</strong></p></td><td  ><p>$1099 without InReach Connectivity/$1199 with InReach</p></td><td  ><p>$1099 without InReach Connectivity/$1299 with InReach</p></td><td  ><p>$1199 without InReach Connectivity/$1299 with InReach</p></td></tr></tbody></table></div><p>All watches will be available to pre-order on August 28.</p></div><div class="live-content"><time datetime="2026-08-25T11:43:10+00:00">August 25, 2026 – 7:43 AM</time><h2 id="there-were-two-new-stamina-features-mentioned-in-the-launch">There were two new Stamina features mentioned in the launch</h2><p>As well as the two new watches, Garmin announces two new Stamina features. Firstly, personalised stamina zones will now be available in the post-activity summary. </p><p>There's also a new stamina curve feature, which is an easy-to-understand visual representation of your fitness and how aerobic and anaerobic workouts alike contribute to improving your stamina.</p></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/news/live/garmin-fenix-9-event</link>
                                                                            <description>
                            <![CDATA[ Garmin looks set to drop new running watches today, and we'll be covering the event live ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">QMMym4BLNnLZGGLUGAPQKi</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/u9hVyDJcNttY6FBXkqqUaK-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 25 Aug 2026 08:49:29 +0000</pubDate>                                                                                                                                <updated>Tue, 25 Aug 2026 14:08:36 +0000</updated>
                                                                                                                                            <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Smartwatches]]></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/u9hVyDJcNttY6FBXkqqUaK-1920-80.jpg">
                                                            <media:credit><![CDATA[Garmin]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a screenshot from the Garmin Play Harder event]]></media:description>                                                            <media:text><![CDATA[a screenshot from the Garmin Play Harder event]]></media:text>
                                <media:title type="plain"><![CDATA[a screenshot from the Garmin Play Harder event]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/u9hVyDJcNttY6FBXkqqUaK-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <div class="live-content"><p>It’s (another) Garmin launch day, and according to rumors, the Garmin Fenix 9 is hours away from dropping. </p><p>Garmin has quietly announced a ‘Play Harder’ launch, which will happen on YouTube at 4am PT and 7am ET in the US, 12pm BST in the UK. </p><p>If you've been following the <a href="https://www.notebookcheck.com/Garmin-Fenix-9-Pro-leakt-auf-Bildern-samt-AMOLED-und-Solar-MiP-Version.1377290.0.html" target="_blank">rumors and leaks</a>, it's looking like we're getting a revised titanium design that stays true to the Fenix look. On top of that, you'll be able to pick from an AMOLED display or MiP screen with solar cells for charging on-the-go.</p><p>Stay tuned for all the updates as they happen here on Tom’s Guide. </p><h2 class="article-body__section" id="section-garmin-event-live-updates"><span>Garmin event: LIVE updates</span></h2></div><div class="live-content"><time datetime="2026-08-25T08:53:20+00:00">August 25, 2026 – 4:53 AM</time><h2 id="what-are-we-predicting">What are we predicting? </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5712px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CvzABggpzc4uM96BMLUgsK" name="Garmin Fenix 8 Pro" alt="Garmin Fenix 8 Pro" src="https://cdn.mos.cms.futurecdn.net/CvzABggpzc4uM96BMLUgsK-1920-80.jpg" mos="" align="middle" fullscreen="" width="5712" height="3213" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>What are we predicting? According to our resident Garmin expert, Nick Harris-Fry, the Garmin Fenix 9 and Enduro 4. </p><p>Why? Firstly, the timing of the event. It's been a couple of years (almost to the day) since Garmin put on a similar event to launch the<a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-8-vs-garmin-fenix-8-pro-should-you-upgrade"> <u>Garmin Fenix 8</u></a> and<a href="https://www.tomsguide.com/wellness/smartwatches/garmin-enduro-3-review"> <u>Garmin Enduro 3</u></a> and it ties in with UTMB in Chamonix, France, which is one of the biggest weeks on the ultramarathon running calendar.</p></div><div class="live-content"><time datetime="2026-08-25T09:10:38+00:00">August 25, 2026 – 5:10 AM</time><h2 id="what-have-garmin-said-so-far">What have Garmin said so far?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2550px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="u9hVyDJcNttY6FBXkqqUaK" name="Garmin - Media Launch Invite" alt="a screenshot from the Garmin Play Harder event" src="https://cdn.mos.cms.futurecdn.net/u9hVyDJcNttY6FBXkqqUaK-1920-80.jpg" mos="" align="middle" fullscreen="" width="2550" height="1435" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>Garmin typically keeps pretty tight-lipped about leaks and launches, yet there's another reason to think this isn't the rumored <a href="https://www.tomsguide.com/wellness/smart-rings/garmin-looks-to-be-developing-a-smart-ring-heres-what-we-know-so-far">Cirqa smart ring </a>dropping.  Garmin's CEO Cliff Pemble said earlier this year that there would be a “<a href="https://www.tomsguide.com/wellness/smartwatches/garmin-plans-a-significant-number-of-new-product-introductions-in-its-outdoor-segment-in-2026-could-this-mean-the-fenix-9"><u>significant number of new product introductions”</u></a> in the outdoor category in the second half of 2026. </p></div><div class="live-content"><time datetime="2026-08-25T09:45:07+00:00">August 25, 2026 – 5:45 AM</time><h2 id="here-39-s-what-i-39-m-hoping-for-from-the-fenix-9">Here's what I'm hoping for from the Fenix 9</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1833px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Y2s69jNNkPbEZeF9TBAEkW" name="Garmin Fenix 8 3.jpg" alt="Garmin Fenix 8 watch" src="https://cdn.mos.cms.futurecdn.net/Y2s69jNNkPbEZeF9TBAEkW-1920-80.jpg" mos="" align="middle" fullscreen="" width="1833" height="1031" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>I realise I never introduced myself: I'm Jane McGuire, the Fitness Editor here at Tom's Guide, and I've been writing about Garmin for the past decade.</p><p>As a female marathon runner, I've said it time and time again — don't put all the best recovery and safety features on watches that are huge on our wrists! I'm hoping for a return of the 43mm Fenix 9 Pro, which wasn't available for the Fenix 8 Pro.</p><p>Hopefully, I'm in luck. A leak spotted by <a href="https://www.fitness-tracker-test.info/en/garmin-fenix-9-livestream-event-and-first-product-listings/" target="_blank">Fitness Tracker Test</a> suggested that three sizes would be available for both watches — 43mm, 47mm, and 51mm — with AMOLED and MIP versions of the Pro watch.</p></div><div class="live-content"><time datetime="2026-08-25T10:01:05+00:00">August 25, 2026 – 6:01 AM</time><h2 id="what-about-the-enduro-4">What about the Enduro 4? </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:664px;"><p class="vanilla-image-block" style="padding-top:56.33%;"><img id="CUejPqjarLjrQFDHfkpP35" name="Garmin Enduro 3" alt="Garmin Enduro 3" src="https://cdn.mos.cms.futurecdn.net/CUejPqjarLjrQFDHfkpP35-1920-80.jpg" mos="" align="middle" fullscreen="" width="664" height="374" 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>What about the Enduro 4? While the screens on the new Fenix 9 models are likely to get brighter, the Enduro range has traditionally been a MIP watch with the best battery life in the Garmin line-up, and we’d expect that to be the case with the Enduro 4. </p><p>The fact that the YouTube invite features a photo of a man surfing, we can expect this launch to focus on rugged, outdoor watches, and the Enduro fits this brief. </p></div><div class="live-content"><time datetime="2026-08-25T10:16:45+00:00">August 25, 2026 – 6:16 AM</time><h2 id="how-to-watch">How to watch! </h2><div class="youtube-video" data-nosnippet ><div class="video-aspect-box"><iframe data-lazy-priority="low" data-lazy-src="https://www.youtube-nocookie.com/embed/WFW9SdPrjAo" allowfullscreen></iframe></div></div><p>There's less than an hour to go, so a reminder of how to watch the Garmin Play Harder event. The event will stream live on YouTube, so you can follow along live, or just keep an eye on our Live Blog if you don't want your boss to see you watching at your desk. Your secret is safe with us. </p></div><div class="live-content"><time datetime="2026-08-25T10:38:24+00:00">August 25, 2026 – 6:38 AM</time><h2 id="the-garmin-leaks-are-leaking">The Garmin leaks are leaking </h2><p>It seems like the rumors are correct: get ready for the Fenix 9. <a href="https://gadgetsandwearables.com/2026/08/25/garmin-fenix-9-pro-specs-features-leak/" target="_blank">Gadgets & Wearables</a> spotted an official listing of the Garmin Fenix 9 Pro via the company's Taiwan website before it was quickly taken down.</p><p>The Fenix 9 Pro 47mm listing, according to Gadgets & Wearables, gets a fully titanium case rather than the Fenix 8 Pro's titanium bezel and backplate, with a plastic middle. Not long to go! </p></div><div class="live-content"><time datetime="2026-08-25T10:59:13+00:00">August 25, 2026 – 6:59 AM</time><h2 id="here-we-go">HERE WE GO! </h2><p>If you're just joining us, the Garmin Play Harder event is about to begin, scroll down for the YouTube link if you want to watch with us live. </p></div><div class="live-content"><time datetime="2026-08-25T11:04:21+00:00">August 25, 2026 – 7:04 AM</time><h2 id="it-39-s-official-the-fenix-9-is-here">It's official: the Fenix 9 is here </h2><p>We just got our first look at the Fenix 9, and we're only 3 minutes into the launch. </p><p>The Fenix 9 and Fenix 9 pro have just been announced. </p></div><div class="live-content"><time datetime="2026-08-25T11:09:22+00:00">August 25, 2026 – 7:09 AM</time><h2 id="fenix-9-pro-the-details">Fenix 9 Pro: The details </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:989px;"><p class="vanilla-image-block" style="padding-top:56.22%;"><img id="Xedkqb55iVvNCZUSjFPsV3" name="Screenshot 2026-08-25 at 12.04.10" alt="Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/Xedkqb55iVvNCZUSjFPsV3-1920-80.png" mos="" align="middle" fullscreen="" width="989" height="556" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>Here's what Garmin just announced about the Fenix 9 Pro: </p><ul><li>Thinner than the Fenix 8 Pro at 47mm</li><li>The watch features a titanium case and a sapphire lens</li><li>New build increases strength and durability without adding weight</li><li>The watch has a green flashlight for the first time</li><li>Available in three different sizes: 43mm, 47mm, 51mm</li><li>The 51mm Fenix 9 Pro has the largest display Garmin has ever released at 1.5 inches. It also has a brightness of 3,000 nits</li></ul></div><div class="live-content"><time datetime="2026-08-25T11:13:01+00:00">August 25, 2026 – 7:13 AM</time><h2 id="garmin-announces-a-new-feature-garmin-epic">Garmin announces a new feature: Garmin Epic</h2><p>With the Fenix 9 and the 9 Pro, Garmin has announced a new feature: Garmin Epic. This allows you to group multiple activities for a longer adventure, such as a weekend skiing trip. You'll be able to see different activities, recoveries, notes, and photos. </p><p>Andrew Perkins, Garmin's Product Manager, confirmed users will be able to go back through activites in Garmin Connect to try this. </p></div><div class="live-content"><time datetime="2026-08-25T11:23:22+00:00">August 25, 2026 – 7:23 AM</time><h2 id="fenix-9-the-details">Fenix 9: The details </h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1485px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="kXiKhRWe86qomugNvt8ky9" name="vJ8mM3GdPthVTRngYK3FaP" alt="Fenix 9 Pro" src="https://cdn.mos.cms.futurecdn.net/kXiKhRWe86qomugNvt8ky9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1485" height="836" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Garmin)</span></figcaption></figure><p>Here's what just got announced about the Fenix 9: </p><ul><li>New mapping engine is 30% faster than the Fenix 8</li><li>64GB memory</li><li>AMOLED display is twice as bright as the Fenix 8</li><li>Dive-rated up to 40m</li><li>Available in three sizes: 43mm, 47mm, 51mm</li></ul></div><div class="live-content"><time datetime="2026-08-25T11:25:02+00:00">August 25, 2026 – 7:25 AM</time><h2 id="garmin-announces-new-mapping-features-on-the-fenix-9-and-9-pro">Garmin announces new mapping features on the Fenix 9 and 9 Pro</h2><p>Garmin says they have redesigned the mapping engines for the Fenix 9 and 9 Pro, making zooming in on the app smoother and more user friendly. The mapping on the watches is also more responsive, allowing for faster panning. They'll also be a new perspective view on the watch. </p></div><div class="live-content"><time datetime="2026-08-25T11:37:36+00:00">August 25, 2026 – 7:37 AM</time><h2 id="how-much-do-the-new-watches-cost">How much do the new watches cost? </h2><p>The Fenix 9 and Fenix 9 Pro just hit the Garmin website, here's how much you can expect to pay: </p><div ><table><caption>Fenix 9 line-up cost</caption><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>43mm</strong></p></td><td  ><p><strong>47mm</strong></p></td><td  ><p><strong>51mm</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Fenix 9</strong></p></td><td  ><p>$999</p></td><td  ><p>$999</p></td><td  ><p>$1099</p></td></tr><tr><td class="firstcol " ><p><strong>Fenix 9 Pro</strong></p></td><td  ><p>$1099 without InReach Connectivity/$1199 with InReach</p></td><td  ><p>$1099 without InReach Connectivity/$1199 with InReach</p></td><td  ><p>$1199 without InReach Connectivity/$1299 with InReach</p></td></tr><tr><td class="firstcol " ><p><strong>Fenix 9 Pro Solar</strong></p></td><td  ><p>$1099 without InReach Connectivity/$1199 with InReach</p></td><td  ><p>$1099 without InReach Connectivity/$1299 with InReach</p></td><td  ><p>$1199 without InReach Connectivity/$1299 with InReach</p></td></tr></tbody></table></div><p>All watches will be available to pre-order on August 28.</p></div><div class="live-content"><time datetime="2026-08-25T11:43:10+00:00">August 25, 2026 – 7:43 AM</time><h2 id="there-were-two-new-stamina-features-mentioned-in-the-launch">There were two new Stamina features mentioned in the launch</h2><p>As well as the two new watches, Garmin announces two new Stamina features. Firstly, personalised stamina zones will now be available in the post-activity summary. </p><p>There's also a new stamina curve feature, which is an easy-to-understand visual representation of your fitness and how aerobic and anaerobic workouts alike contribute to improving your stamina.</p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Garmin Fenix 9 expected to launch at ‘Play Harder’ event — here’s when it is and how to watch ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Garmin has lined up a live event on its YouTube channel called "Play Harder," and while nothing has been confirmed yet, all signs suggest this could well be the launch of the <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-i-hope-to-see-on-the-garmin-fenix-9-including-the-return-of-a-smaller-size">Garmin Fenix 9</a>, perhaps alongside the Garmin Enduro 4.</p><p>The <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-8-pro-review-the-greatest-fenix-yet">Garmin Fenix 8 Pro</a> and Enduro 3 remain two of the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches </a>available, so it will be exciting to see what updates are coming to the Fenix 9 and Enduro 4, if they are indeed launched at the Play Harder event.</p><h3 class="article-body__section" id="section-how-to-watch-the-garmin-play-harder-event"><span>How to watch the Garmin ‘Play Harder’ event</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:1688px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="jKjbCogSfLppppXWnywP43" name="Garmin Fenix 8 Pro MicroLED-7" alt="Garmin Fenix 8 Pro MicroLED" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:83,l:154,cw:1688,ch:950,q:80/jKjbCogSfLppppXWnywP43.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Garmin Play Harder event is scheduled to go live on YouTube at 12:00pm BST on Tuesday, 25 August. That’s 7:00am Eastern Time, 4:00am Pacific Time and 1:00pm CET.</p><p>Whether the event will be a presentation or just trailers for new watches is yet to be seen, but you can sign up to be notified when the event happens on YouTube.</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/WFW9SdPrjAo" allowfullscreen></iframe></div></div><h3 class="article-body__section" id="section-what-watches-are-likely-to-launch"><span>What watches are likely to launch?</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="uJozQYJcmb5HmCL5Sre2Wa" name="Garmin Fenix 8 Pro" alt="Garmin Fenix 8 Pro" src="https://cdn.mos.cms.futurecdn.net/uJozQYJcmb5HmCL5Sre2Wa-1920-80.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Garmin plays its hand very close to its chest when it comes to new launches, so leaks and rumors always have to be taken with a pinch of salt, but there are several reasons to believe the Play Harder event will launch the Fenix 9 and Enduro 4.</p><p>Firstly, the timing of the event. It's been a couple of years (almost to the day) since Garmin put on a similar event to launch the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-8-vs-garmin-fenix-8-pro-should-you-upgrade">Garmin Fenix 8</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-enduro-3-review">Garmin Enduro 3</a> and it ties in with UTMB in Chamonix, France, which is one of the biggest weeks on the ultramarathon running calendar.</p><p>Garmin CEO Cliff Pemble said earlier this year that there would be a “<a href="https://www.tomsguide.com/wellness/smartwatches/garmin-plans-a-significant-number-of-new-product-introductions-in-its-outdoor-segment-in-2026-could-this-mean-the-fenix-9">significant number of new product introductions”</a> in the outdoor category in the second half of 2026. </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:664px;"><p class="vanilla-image-block" style="padding-top:56.33%;"><img id="CUejPqjarLjrQFDHfkpP35" name="Garmin Enduro 3" alt="Garmin Enduro 3" src="https://cdn.mos.cms.futurecdn.net/CUejPqjarLjrQFDHfkpP35-1920-80.jpg" mos="" align="middle" fullscreen="" width="664" height="374" 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 Fenix 9 was always likely to be one of these since the flagship watch has been on a yearly release cycle since 2022, while the timing of this event also works for the Enduro’s biennial launch cycle.</p><p>With the event titled "Play Harder" and showing a surfer, it also suggests that rugged, outdoorsy devices are more likely to be on the billing than smartwatches.</p><h3 class="article-body__section" id="section-what-to-expect-from-the-garmin-fenix-9-and-enduro-4"><span>What to expect from the Garmin Fenix 9 and Enduro 4?</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="B63V5jMEy5D6AVZEE4UASa" name="Garmin Fenix 8 Pro" alt="Garmin Fenix 8 Pro" src="https://cdn.mos.cms.futurecdn.net/B63V5jMEy5D6AVZEE4UASa-1920-80.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Fenix line-up is always extensive with regard to the size, material and display options available, and rumors suggest that both a Fenix 9 and Fenix 9 Pro are likely to launch, with the Pro model having options with and without Garmin’s InReach connectivity.</p><p>A leak spotted by <a href="https://www.fitness-tracker-test.info/en/garmin-fenix-9-livestream-event-and-first-product-listings/" target="_blank">Fitness Tracker Test</a> suggested that three sizes would be available for both watches — 43mm, 47mm, and 51mm — with AMOLED and MIP versions of the Pro watch.</p><p>The return of the smallest 43mm size is welcome after it wasn’t available for the Fenix 8 Pro. Interestingly, the rumors suggest there won’t be a MicroLED model, despite Garmin using the tech on the <a href="https://www.tomsguide.com/wellness/smartwatches/i-tried-garmins-usd2k-microled-smartwatch-and-the-display-was-even-better-than-i-expected">Fenix 8 Pro MicroLED</a> last year.</p><p>We’ll have to wait and see what new features arrive with the Fenix 9 line-up, but a brighter screen is a likely upgrade.</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="GeWQDYtuVywmuyTKhEMJ69" name="TG_Garmin-Enduro-3-3.jpg" alt="Garmin Enduro 3 watch" src="https://cdn.mos.cms.futurecdn.net/GeWQDYtuVywmuyTKhEMJ69-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: Nick Harris-Fry/Future)</span></figcaption></figure><p>This might hit battery life, but that’s where the rumored Enduro 4 will come in. The Enduro has traditionally been a MIP watch with the best battery life in the Garmin line-up, and we’d expect that to be the case with the Enduro 4. </p><p>We’ll try to get our hands on any new devices launched as soon as possible to see how they stack up against the best sports watches available.</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><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/smartwatches/garmin-fenix-9-expected-to-launch-at-play-harder-event-heres-when-it-is-and-how-to-watch</link>
                                                                            <description>
                            <![CDATA[ Garmin has quietly scheduled an event on its YouTube channel that seems likely to launch the Fenix 9 and Enduro 4 adventure watches. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">tBE28fKujj6rudbCUZ7Y4C</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/EuN4aB2dskcAEQ9EerEJ23-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 25 Aug 2026 08:40:38 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></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/EuN4aB2dskcAEQ9EerEJ23-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Garmin Fenix 8 Pro MicroLED]]></media:description>                                                            <media:text><![CDATA[Garmin Fenix 8 Pro MicroLED]]></media:text>
                                <media:title type="plain"><![CDATA[Garmin Fenix 8 Pro MicroLED]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/EuN4aB2dskcAEQ9EerEJ23-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Garmin has lined up a live event on its YouTube channel called "Play Harder," and while nothing has been confirmed yet, all signs suggest this could well be the launch of the <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-i-hope-to-see-on-the-garmin-fenix-9-including-the-return-of-a-smaller-size">Garmin Fenix 9</a>, perhaps alongside the Garmin Enduro 4.</p><p>The <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-8-pro-review-the-greatest-fenix-yet">Garmin Fenix 8 Pro</a> and Enduro 3 remain two of the <a href="https://www.tomsguide.com/best-picks/best-garmin-watch">best Garmin watches </a>available, so it will be exciting to see what updates are coming to the Fenix 9 and Enduro 4, if they are indeed launched at the Play Harder event.</p><h3 class="article-body__section" id="section-how-to-watch-the-garmin-play-harder-event"><span>How to watch the Garmin ‘Play Harder’ event</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:1688px;"><p class="vanilla-image-block" style="padding-top:56.28%;"><img id="jKjbCogSfLppppXWnywP43" name="Garmin Fenix 8 Pro MicroLED-7" alt="Garmin Fenix 8 Pro MicroLED" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:83,l:154,cw:1688,ch:950,q:80/jKjbCogSfLppppXWnywP43.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Garmin Play Harder event is scheduled to go live on YouTube at 12:00pm BST on Tuesday, 25 August. That’s 7:00am Eastern Time, 4:00am Pacific Time and 1:00pm CET.</p><p>Whether the event will be a presentation or just trailers for new watches is yet to be seen, but you can sign up to be notified when the event happens on YouTube.</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/WFW9SdPrjAo" allowfullscreen></iframe></div></div><h3 class="article-body__section" id="section-what-watches-are-likely-to-launch"><span>What watches are likely to launch?</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="uJozQYJcmb5HmCL5Sre2Wa" name="Garmin Fenix 8 Pro" alt="Garmin Fenix 8 Pro" src="https://cdn.mos.cms.futurecdn.net/uJozQYJcmb5HmCL5Sre2Wa-1920-80.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Garmin plays its hand very close to its chest when it comes to new launches, so leaks and rumors always have to be taken with a pinch of salt, but there are several reasons to believe the Play Harder event will launch the Fenix 9 and Enduro 4.</p><p>Firstly, the timing of the event. It's been a couple of years (almost to the day) since Garmin put on a similar event to launch the <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-fenix-8-vs-garmin-fenix-8-pro-should-you-upgrade">Garmin Fenix 8</a> and <a href="https://www.tomsguide.com/wellness/smartwatches/garmin-enduro-3-review">Garmin Enduro 3</a> and it ties in with UTMB in Chamonix, France, which is one of the biggest weeks on the ultramarathon running calendar.</p><p>Garmin CEO Cliff Pemble said earlier this year that there would be a “<a href="https://www.tomsguide.com/wellness/smartwatches/garmin-plans-a-significant-number-of-new-product-introductions-in-its-outdoor-segment-in-2026-could-this-mean-the-fenix-9">significant number of new product introductions”</a> in the outdoor category in the second half of 2026. </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:664px;"><p class="vanilla-image-block" style="padding-top:56.33%;"><img id="CUejPqjarLjrQFDHfkpP35" name="Garmin Enduro 3" alt="Garmin Enduro 3" src="https://cdn.mos.cms.futurecdn.net/CUejPqjarLjrQFDHfkpP35-1920-80.jpg" mos="" align="middle" fullscreen="" width="664" height="374" 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 Fenix 9 was always likely to be one of these since the flagship watch has been on a yearly release cycle since 2022, while the timing of this event also works for the Enduro’s biennial launch cycle.</p><p>With the event titled "Play Harder" and showing a surfer, it also suggests that rugged, outdoorsy devices are more likely to be on the billing than smartwatches.</p><h3 class="article-body__section" id="section-what-to-expect-from-the-garmin-fenix-9-and-enduro-4"><span>What to expect from the Garmin Fenix 9 and Enduro 4?</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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="B63V5jMEy5D6AVZEE4UASa" name="Garmin Fenix 8 Pro" alt="Garmin Fenix 8 Pro" src="https://cdn.mos.cms.futurecdn.net/B63V5jMEy5D6AVZEE4UASa-1920-80.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Fenix line-up is always extensive with regard to the size, material and display options available, and rumors suggest that both a Fenix 9 and Fenix 9 Pro are likely to launch, with the Pro model having options with and without Garmin’s InReach connectivity.</p><p>A leak spotted by <a href="https://www.fitness-tracker-test.info/en/garmin-fenix-9-livestream-event-and-first-product-listings/" target="_blank">Fitness Tracker Test</a> suggested that three sizes would be available for both watches — 43mm, 47mm, and 51mm — with AMOLED and MIP versions of the Pro watch.</p><p>The return of the smallest 43mm size is welcome after it wasn’t available for the Fenix 8 Pro. Interestingly, the rumors suggest there won’t be a MicroLED model, despite Garmin using the tech on the <a href="https://www.tomsguide.com/wellness/smartwatches/i-tried-garmins-usd2k-microled-smartwatch-and-the-display-was-even-better-than-i-expected">Fenix 8 Pro MicroLED</a> last year.</p><p>We’ll have to wait and see what new features arrive with the Fenix 9 line-up, but a brighter screen is a likely upgrade.</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="GeWQDYtuVywmuyTKhEMJ69" name="TG_Garmin-Enduro-3-3.jpg" alt="Garmin Enduro 3 watch" src="https://cdn.mos.cms.futurecdn.net/GeWQDYtuVywmuyTKhEMJ69-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: Nick Harris-Fry/Future)</span></figcaption></figure><p>This might hit battery life, but that’s where the rumored Enduro 4 will come in. The Enduro has traditionally been a MIP watch with the best battery life in the Garmin line-up, and we’d expect that to be the case with the Enduro 4. </p><p>We’ll try to get our hands on any new devices launched as soon as possible to see how they stack up against the best sports watches available.</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><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 walked 12,000 steps with the $799 Apple Watch Ultra 3 and the $199 Garmin Cirqa: Here’s which came out on top ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I’ve been writing about fitness trackers for the better part of a decade, and one thing I always do when unboxing a new device is look at how well it does the basics. One of these easy-to-measure basics is how many steps I’ve taken; hence, these Tom’s Guide walking tests were born. </p><p>A few weeks ago, I unboxed the <a href="https://www.tomsguide.com/wellness/fitness-trackers/ive-been-wearing-the-garmin-cirqa-for-3-weeks-here-are-3-things-i-like-and-3-things-id-change">Garmin Cirqa</a> — Garmin’s first screenless tracker, which is set to take on the likes of the <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">Fitbit Air </a>and the <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a>. My first walking test compared the Garmin Cirqa to the Fitbit Air, and it was pretty disastrous. Since then, I’ve customized the button on my Cirqa and worn it continuously for the past few weeks. </p><p>To see if things had improved, I strapped it on and walked 12,000 steps with the $799 <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a>. Of course, I don’t think most people would be trying to choose between these two devices — they are extremely different. But I wanted to see how the $199 Cirqa kept up with Apple’s most expensive and smartest smartwatch. Read on to find out which came out on top. </p>        <div class="featured_product_block featured_block_versus" data-id="c9e82358-9bbb-11f1-9e38-7b201bf4628f">            <a href="https://www.amazon.com/Apple-Multisport-Smartwatch-Satellite-Communications/dp/B0FQFHVZYL/" data-model-name="Watch Ultra 3" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:111.44%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/UEFg3q3tMPbexcJCuF8bEZ.png" alt="Apple, Watch Ultra 3"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                            <div class='featured__brand'>Apple </div>                    <div class="featured__title">Watch Ultra 3</div>                                    </div>                <div class="subtitle__description">                                                            <p><p>The Apple Watch Ultra 3 is Apple's smartest smartwatch, with the longest battery life of any Apple Watch, as well as tons of health and fitness tracking features. </p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_versus" data-id="c9e823d0-9bbb-11f1-97d7-db84831046fe">            <a href="https://www.amazon.com/Garmin-CIRQATM-Smart-Subscription-Mauve/dp/B0H94S154D/" data-model-name="Cirqa" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:102.04%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/4evX7WqPWr9jhKZeqqaxnb.png" alt="Garmin, Cirqa"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                            <div class='featured__brand'>Garmin</div>                    <div class="featured__title">Cirqa</div>                                    </div>                <div class="subtitle__description">                                                            <p><p>The Garmin Cirqa is Garmin's newly released screenless tracker with 10 days of battery life and the ability to keep track of all your stats without distractions. </p></p>                </div>                            </div>        </div><h2 id="i-walked-12-000-steps-with-the-799-apple-watch-ultra-3-and-the-199-garmin-cirqa">I walked 12,000 steps with the $799 Apple Watch Ultra 3 and the $199 Garmin Cirqa</h2><p>If you’ve read one of these articles from the Tom’s Guide fitness desk, you’ll know that manually counting 12,000 steps is out of my remit, so I rely on a trusty $5 clicker tool from <a href="https://www.tomsguide.com/uk/tag/amazon">Amazon</a>.</p><p>I manually click every time I take a step. For this test, I wore the Apple Watch Ultra 3 on my left wrist and the Garmin Cirqa on my right. Both trackers count your steps using an internal accelerometer, which measures the swing of your arms.</p><p>Each swing counts for two steps, and it doesn’t matter whether you wear your watch on your dominant or non-dominant hand. It doesn’t matter if you walk with your hands in your pockets or holding a cup of coffee; the accelerometer should still measure your body’s movement. It does, however, make a difference if you’re pushing a stroller — no, Apple, I promise I haven’t done a 45-minute elliptical workout while trying to get my toddler to sleep.</p><p>As with all of the <a href="https://www.tomsguide.com/best-picks/best-apple-watch">best Apple Watche</a>s, the Apple Watch Ultra 3 doesn’t tell you the number of steps you’ve taken during a specific workout; instead, you see an overall number of steps throughout the day. Probably because <a href="https://www.tomsguide.com/wellness/fitness/forget-10000-steps-researchers-say-this-is-way-more-important">steps aren’t actually that useful a metric</a> beyond a certain point, but annoying for me when writing these articles. For this comparison, I downloaded a third-party Pedometer+ app onto my Apple Watch.</p><p>I split this test into three walks, and when I got home, I downloaded all the data and compared the results:</p><div ><table><caption>Walk one </caption><tbody><tr><td class="firstcol " ><p>Manual:</p></td><td  ><p>4,790 steps</p></td></tr><tr><td class="firstcol " ><p>Apple Watch Ultra 3:</p></td><td  ><p>4,706 steps</p></td></tr><tr><td class="firstcol " ><p>Garmin Cirqa:</p></td><td  ><p>4,826 steps</p></td></tr></tbody></table></div><div ><table><caption>Walk two </caption><tbody><tr><td class="firstcol " ><p>Manual:</p></td><td  ><p>3,412 steps</p></td></tr><tr><td class="firstcol " ><p>Apple Watch Ultra 3:</p></td><td  ><p>3,362 steps</p></td></tr><tr><td class="firstcol " ><p>Garmin Cirqa:</p></td><td  ><p>3,420 steps</p></td></tr></tbody></table></div><div ><table><caption>Walk three </caption><tbody><tr><td class="firstcol " ><p>Manual:</p></td><td  ><p>4,373 steps</p></td></tr><tr><td class="firstcol " ><p>Apple Watch Ultra 3:</p></td><td  ><p>4,265 steps </p></td></tr><tr><td class="firstcol " ><p>Garmin Cirqa:</p></td><td  ><p>4,432 steps </p></td></tr></tbody></table></div><div ><table><caption>Results</caption><tbody><tr><td class="firstcol " ><p>Manual:</p></td><td  ><p>12,575 steps </p></td></tr><tr><td class="firstcol " ><p>Apple Watch Ultra 3:</p></td><td  ><p>12,333 steps</p></td></tr><tr><td class="firstcol " ><p>Garmin Cirqa:</p></td><td  ><p>12,678 steps </p></td></tr></tbody></table></div><p>As you can see, this one is incredibly close. The Garmin Cirqa came out on top, but by 100 steps, as it counted 103 steps more than I did manually, whereas the Apple Watch Ultra 3 missed 242 steps.</p><p>It goes without saying that when we’re talking about a hundred steps, this isn’t much at all over the course of 12,000. The average person takes 2,000 steps a mile, so missing or overcounting 100 in the grand scheme of things won’t really make a difference to your tracking. </p><p>It’s also important to point out, again, that I don’t think many people would be choosing between these two devices, as they are designed for very different consumers. Instead, the test was to see how Garmin’s $199 screenless tracker could keep up with a watch four times its price, and I’m impressed. </p><p>One thing I did (which I’m sure made my Garmin Cirqa’s data more accurate) was to customize the activity on the side button. When you unbox the device, it’s automatically set to Timed Activity, and in my experience, these activities don’t give you an accurate step count goal. </p><p>Instead, I changed the button to automatically start a walk. To do this,<strong> head to your Garmin Connect app</strong> and <strong>click the Cirqa icon.</strong> From there, go to <strong>Activity Options </strong>and then<strong> Edit</strong> to change the <strong>On Device </strong>option. </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-OoD6zX"></div>                            </div>                            <script src="https://kwizly.com/embed/OoD6zX.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/fitness-trackers/can-the-usd99-fitbit-air-beat-the-usd799-apple-watch-ultra-3-at-fitness-tracking-i-manually-counted-4-500-steps-to-find-out">Can the $99 Fitbit Air beat the $799 Apple Watch Ultra 3 at fitness tracking? I manually counted 4,500 steps to find out</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/i-manually-counted-4-000-steps-to-test-the-apple-watch-ultra-3-vs-samsung-galaxy-watch-ultra-2-and-samsung-wins-the-accuracy-battle-with-better-elevation-data-too">I walked 4,000 steps with the Apple Watch Ultra 3 vs Samsung Galaxy Watch Ultra 2 — and the winning margin was razor-thin</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/oura-whoop-or-fitbit-air-5-questions-to-ask-yourself-before-buying-a-screen-free-fitness-tracker">Oura vs Whoop vs Fitbit Air — 5 questions to ask yourself before buying a screen-free fitness tracker</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness-trackers/i-walked-12-000-steps-with-the-usd799-apple-watch-ultra-3-and-the-usd199-garmin-cirqa-heres-which-came-out-on-top</link>
                                                                            <description>
                            <![CDATA[ Can the Garmin Cirqa beat a smartwatch four times its price? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">pRWF4MSYPKAd4Ho6fXmhvd</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/BcpMpprJrMnsMUNjMaE4g4-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 23 Aug 2026 05:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Smartwatches]]></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/BcpMpprJrMnsMUNjMaE4g4-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[the Apple Watch Ultra 3 and Garmin Cirqa on wrist ]]></media:description>                                                            <media:text><![CDATA[the Apple Watch Ultra 3 and Garmin Cirqa on wrist ]]></media:text>
                                <media:title type="plain"><![CDATA[the Apple Watch Ultra 3 and Garmin Cirqa on wrist ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/BcpMpprJrMnsMUNjMaE4g4-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I’ve been writing about fitness trackers for the better part of a decade, and one thing I always do when unboxing a new device is look at how well it does the basics. One of these easy-to-measure basics is how many steps I’ve taken; hence, these Tom’s Guide walking tests were born. </p><p>A few weeks ago, I unboxed the <a href="https://www.tomsguide.com/wellness/fitness-trackers/ive-been-wearing-the-garmin-cirqa-for-3-weeks-here-are-3-things-i-like-and-3-things-id-change">Garmin Cirqa</a> — Garmin’s first screenless tracker, which is set to take on the likes of the <a href="https://www.tomsguide.com/wellness/fitness-trackers/fitbit-air-review">Fitbit Air </a>and the <a href="https://www.tomsguide.com/wellness/fitness-trackers/whoop-5-0-review-should-you-give-a-whoop-about-this-new-tracker">Whoop 5.0</a>. My first walking test compared the Garmin Cirqa to the Fitbit Air, and it was pretty disastrous. Since then, I’ve customized the button on my Cirqa and worn it continuously for the past few weeks. </p><p>To see if things had improved, I strapped it on and walked 12,000 steps with the $799 <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-3-review">Apple Watch Ultra 3</a>. Of course, I don’t think most people would be trying to choose between these two devices — they are extremely different. But I wanted to see how the $199 Cirqa kept up with Apple’s most expensive and smartest smartwatch. Read on to find out which came out on top. </p>        <div class="featured_product_block featured_block_versus" data-id="c9e82358-9bbb-11f1-9e38-7b201bf4628f">            <a href="https://www.amazon.com/Apple-Multisport-Smartwatch-Satellite-Communications/dp/B0FQFHVZYL/" data-model-name="Watch Ultra 3" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:111.44%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/UEFg3q3tMPbexcJCuF8bEZ.png" alt="Apple, Watch Ultra 3"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                            <div class='featured__brand'>Apple </div>                    <div class="featured__title">Watch Ultra 3</div>                                    </div>                <div class="subtitle__description">                                                            <p><p>The Apple Watch Ultra 3 is Apple's smartest smartwatch, with the longest battery life of any Apple Watch, as well as tons of health and fitness tracking features. </p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_versus" data-id="c9e823d0-9bbb-11f1-97d7-db84831046fe">            <a href="https://www.amazon.com/Garmin-CIRQATM-Smart-Subscription-Mauve/dp/B0H94S154D/" data-model-name="Cirqa" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:102.04%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/4evX7WqPWr9jhKZeqqaxnb.png" alt="Garmin, Cirqa"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                            <div class='featured__brand'>Garmin</div>                    <div class="featured__title">Cirqa</div>                                    </div>                <div class="subtitle__description">                                                            <p><p>The Garmin Cirqa is Garmin's newly released screenless tracker with 10 days of battery life and the ability to keep track of all your stats without distractions. </p></p>                </div>                            </div>        </div><h2 id="i-walked-12-000-steps-with-the-799-apple-watch-ultra-3-and-the-199-garmin-cirqa">I walked 12,000 steps with the $799 Apple Watch Ultra 3 and the $199 Garmin Cirqa</h2><p>If you’ve read one of these articles from the Tom’s Guide fitness desk, you’ll know that manually counting 12,000 steps is out of my remit, so I rely on a trusty $5 clicker tool from <a href="https://www.tomsguide.com/uk/tag/amazon">Amazon</a>.</p><p>I manually click every time I take a step. For this test, I wore the Apple Watch Ultra 3 on my left wrist and the Garmin Cirqa on my right. Both trackers count your steps using an internal accelerometer, which measures the swing of your arms.</p><p>Each swing counts for two steps, and it doesn’t matter whether you wear your watch on your dominant or non-dominant hand. It doesn’t matter if you walk with your hands in your pockets or holding a cup of coffee; the accelerometer should still measure your body’s movement. It does, however, make a difference if you’re pushing a stroller — no, Apple, I promise I haven’t done a 45-minute elliptical workout while trying to get my toddler to sleep.</p><p>As with all of the <a href="https://www.tomsguide.com/best-picks/best-apple-watch">best Apple Watche</a>s, the Apple Watch Ultra 3 doesn’t tell you the number of steps you’ve taken during a specific workout; instead, you see an overall number of steps throughout the day. Probably because <a href="https://www.tomsguide.com/wellness/fitness/forget-10000-steps-researchers-say-this-is-way-more-important">steps aren’t actually that useful a metric</a> beyond a certain point, but annoying for me when writing these articles. For this comparison, I downloaded a third-party Pedometer+ app onto my Apple Watch.</p><p>I split this test into three walks, and when I got home, I downloaded all the data and compared the results:</p><div ><table><caption>Walk one </caption><tbody><tr><td class="firstcol " ><p>Manual:</p></td><td  ><p>4,790 steps</p></td></tr><tr><td class="firstcol " ><p>Apple Watch Ultra 3:</p></td><td  ><p>4,706 steps</p></td></tr><tr><td class="firstcol " ><p>Garmin Cirqa:</p></td><td  ><p>4,826 steps</p></td></tr></tbody></table></div><div ><table><caption>Walk two </caption><tbody><tr><td class="firstcol " ><p>Manual:</p></td><td  ><p>3,412 steps</p></td></tr><tr><td class="firstcol " ><p>Apple Watch Ultra 3:</p></td><td  ><p>3,362 steps</p></td></tr><tr><td class="firstcol " ><p>Garmin Cirqa:</p></td><td  ><p>3,420 steps</p></td></tr></tbody></table></div><div ><table><caption>Walk three </caption><tbody><tr><td class="firstcol " ><p>Manual:</p></td><td  ><p>4,373 steps</p></td></tr><tr><td class="firstcol " ><p>Apple Watch Ultra 3:</p></td><td  ><p>4,265 steps </p></td></tr><tr><td class="firstcol " ><p>Garmin Cirqa:</p></td><td  ><p>4,432 steps </p></td></tr></tbody></table></div><div ><table><caption>Results</caption><tbody><tr><td class="firstcol " ><p>Manual:</p></td><td  ><p>12,575 steps </p></td></tr><tr><td class="firstcol " ><p>Apple Watch Ultra 3:</p></td><td  ><p>12,333 steps</p></td></tr><tr><td class="firstcol " ><p>Garmin Cirqa:</p></td><td  ><p>12,678 steps </p></td></tr></tbody></table></div><p>As you can see, this one is incredibly close. The Garmin Cirqa came out on top, but by 100 steps, as it counted 103 steps more than I did manually, whereas the Apple Watch Ultra 3 missed 242 steps.</p><p>It goes without saying that when we’re talking about a hundred steps, this isn’t much at all over the course of 12,000. The average person takes 2,000 steps a mile, so missing or overcounting 100 in the grand scheme of things won’t really make a difference to your tracking. </p><p>It’s also important to point out, again, that I don’t think many people would be choosing between these two devices, as they are designed for very different consumers. Instead, the test was to see how Garmin’s $199 screenless tracker could keep up with a watch four times its price, and I’m impressed. </p><p>One thing I did (which I’m sure made my Garmin Cirqa’s data more accurate) was to customize the activity on the side button. When you unbox the device, it’s automatically set to Timed Activity, and in my experience, these activities don’t give you an accurate step count goal. </p><p>Instead, I changed the button to automatically start a walk. To do this,<strong> head to your Garmin Connect app</strong> and <strong>click the Cirqa icon.</strong> From there, go to <strong>Activity Options </strong>and then<strong> Edit</strong> to change the <strong>On Device </strong>option. </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-OoD6zX"></div>                            </div>                            <script src="https://kwizly.com/embed/OoD6zX.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/fitness-trackers/can-the-usd99-fitbit-air-beat-the-usd799-apple-watch-ultra-3-at-fitness-tracking-i-manually-counted-4-500-steps-to-find-out">Can the $99 Fitbit Air beat the $799 Apple Watch Ultra 3 at fitness tracking? I manually counted 4,500 steps to find out</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/i-manually-counted-4-000-steps-to-test-the-apple-watch-ultra-3-vs-samsung-galaxy-watch-ultra-2-and-samsung-wins-the-accuracy-battle-with-better-elevation-data-too">I walked 4,000 steps with the Apple Watch Ultra 3 vs Samsung Galaxy Watch Ultra 2 — and the winning margin was razor-thin</a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/oura-whoop-or-fitbit-air-5-questions-to-ask-yourself-before-buying-a-screen-free-fitness-tracker">Oura vs Whoop vs Fitbit Air — 5 questions to ask yourself before buying a screen-free fitness tracker</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I walked 4,000 steps with the Pixel Watch 5 vs Samsung Galaxy Watch 9 — and we have a new Android champ ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Which 2026 smartwatch is the more accurate fitness tracker, the <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review">Google Pixel Watch 5 </a>or the <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-to-know-about-the-new-samsung-galaxy-watch-9">Samsung Galaxy Watch 9</a>? I just had to know.</p><p>So, I did what any tech geek with access to both devices and two wrists would do: I strapped one to each arm, logged a ~35-minute walk, and then compared the data. As a primary control for accuracy, I manually counted all 4,000 steps.</p><p>I also tracked the walk using the Strava app on my iPhone 16 Plus. Find the results of this comparison between the <a href="https://www.tomsguide.com/wellness/smartwatches/pixel-watch-5-vs-samsung-galaxy-watch-9-5-key-differences-you-need-to-know">Pixel Watch 5 and Galaxy Watch 9</a>, and key takeaways, below.  </p><h3 class="article-body__section" id="section-i-walked-4-000-steps-with-the-samsung-galaxy-watch-9-vs-google-pixel-watch-5"><span>I walked 4,000 steps with the Samsung Galaxy Watch 9 vs Google Pixel Watch 5</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:5408px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="r8eU5UpsMnb4H9VFcKFJiV" name="Galaxy9-Pixel5-04" alt="Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5" src="https://cdn.mos.cms.futurecdn.net/r8eU5UpsMnb4H9VFcKFJiV-1920-80.jpg" mos="" align="middle" fullscreen="" width="5408" height="3042" 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>So, which of these flagship Android wearables —  two of the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> around —  is the more competent fitness tracker: the Galaxy Watch 9 or Pixel Watch 5? Have a look for yourself. </p><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Pixel Watch 5</p></th><th  ><p>Galaxy Watch 9</p></th><th  ><p>Control</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Steps</strong></p></td><td  ><p>4,010 steps</p></td><td  ><p>4,017 steps</p></td><td  ><p> 4,000 steps (manual count)</p></td></tr><tr><td class="firstcol " ><p><strong>Distance</strong></p></td><td  ><p>2.07 miles</p></td><td  ><p>2.06 miles</p></td><td  ><p>2.11 miles</p></td></tr><tr><td class="firstcol " ><p><strong>Climb</strong></p></td><td  ><p>229 feet</p></td><td  ><p>254 feet</p></td><td  ><p>233 feet</p></td></tr><tr><td class="firstcol " ><p><strong>Average pace</strong></p></td><td  ><p>19 mins 23 secs per mile</p></td><td  ><p>18 mins 24 secs per mile</p></td><td  ><p>17 mins 54 secs per mile</p></td></tr><tr><td class="firstcol " ><p><strong>Average heart rate</strong></p></td><td  ><p>139 bpm</p></td><td  ><p>102 bpm</p></td><td  ><p>n/a</p></td></tr><tr><td class="firstcol " ><p><strong>Max heart rate</strong></p></td><td  ><p>160 bpm</p></td><td  ><p>128 bpm</p></td><td  ><p>n/a</p></td></tr><tr><td class="firstcol " ><p><strong>Calories burned</strong></p></td><td  ><p>410 total calories</p></td><td  ><p>219 total calories</p></td><td  ><p>n/a</p></td></tr><tr><td class="firstcol " ><p><strong>Battery usage</strong></p></td><td  ><p>4%</p></td><td  ><p>7%</p></td><td  ><p>n/a</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-google-s-step-count-was-closer"><span>Google's step count was closer</span></h3><p>As you can see, both the Samsung Galaxy Watch 9 and Google Pixel Watch 5 logged step count totals within 20 steps of my actual count, which is a seriously impressive and commendable result. However, in the interest of friendly competition and this article, the Pixel Watch officially wins in this category. </p><h3 class="article-body__section" id="section-the-pixel-watch-also-logged-more-accurate-climb-and-distance-data"><span>The Pixel Watch also logged more accurate climb and distance data</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:4182px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="Su4KjbbvHMUJPbJL3EjFJV" name="Galaxy9-Pixel5-01" alt="Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5" src="https://cdn.mos.cms.futurecdn.net/Su4KjbbvHMUJPbJL3EjFJV-1920-80.jpg" mos="" align="middle" fullscreen="" width="4182" height="2353" 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>Again, both the Google Pixel Watch 5 and the Samsung Galaxy Watch 9 performed extremely well when it came to accurately logging distance and climb. That said, the Pixel Watch's data was again closer to the control on both counts.</p><h3 class="article-body__section" id="section-google-s-pace-data-is-slower-than-expected"><span>Google's pace data is slower than expected</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:5322px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="ryz4WsgNuzbFG2wC9R8VKk" name="GalaxyWatch9-03" alt="Close-up of the Samsung Galaxy Watch 9 in white" src="https://cdn.mos.cms.futurecdn.net/ryz4WsgNuzbFG2wC9R8VKk-1920-80.jpg" mos="" align="middle" fullscreen="" width="5322" height="2994" 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 logging more precise distance, climb, and steps, the Pixel Watch 5 reported an oddly slow average pace for my walk. Not only is it more than a minute slower than Strava's pace, but it's also lower than pretty much every pace metric I've recorded during one of these walk test comparisons (and I've done <em>many</em>). </p><h3 class="article-body__section" id="section-samsung-s-heart-rate-data-is-lower-than-expected"><span>Samsung's heart rate data is lower than expected</span></h3><p>Speaking of strange results, Samsung's heart rate data for this comparison is way lower than expected. Again, I've done lots of these comparisons, and from the cumulative results, I generally expect an average heart rate of around 125 bpm and a max of around 160 bpm. </p><p>That may seem high, but keep in mind I am a brisk walker and purposely take steep, hilly routes to thoroughly assess elevation-tracking accuracy.  That said, Google's average heart rate is also strangely high, even if its max heart rate metric appears to be on the money.</p><h3 class="article-body__section" id="section-the-google-pixel-watch-5-wins"><span>The Google Pixel Watch 5 wins</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:3982px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UedGRJgfxxBpcTJLDkJwmi" name="Google Pixel Watch 5-LIST2" alt="Close-up of the Pixel Watch 5 in 45mm on a user's wrist" src="https://cdn.mos.cms.futurecdn.net/UedGRJgfxxBpcTJLDkJwmi-1920-80.jpg" mos="" align="middle" fullscreen="" width="3982" height="2240" 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>Ultimately, in this fitness tracking accuracy comparison between the Google Pixel Watch 5 and the Samsung Galaxy Watch 9, the Pixel Watch takes home the trophy, with more accurate step count, distance, and climb data. </p><p>The Samsung Galaxy Watch 9 also performed well at tracking most of my key metrics, with the exception of its questionably low heart rate recording, which I plan to investigate further as I work toward publishing a full review. Stay tuned for that!</p><p>In the meantime, what smartwatches, fitness trackers, or other wearables should I test head-to-head next? Let me know in the comments below. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-XjarYO"></div>                            </div>                            <script src="https://kwizly.com/embed/XjarYO.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/fitness-trackers/i-walked-5-000-steps-with-the-fitbit-air-vs-garmin-cirqa-round-2-we-have-a-new-champ"><strong>I walked 5,000 steps with the Fitbit Air vs Garmin Cirqa — Round 2: We have a new champ</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/galaxy-watch-ultra-2-hands-on-review"><strong>I’ve been wearing the Samsung Galaxy Watch Ultra 2 for nearly a week — 5 things I like and 1 thing I don’t</strong></a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/ive-tested-over-100-fitness-trackers-head-to-head-3-workout-stats-i-trust-the-least"><strong>I’ve tested over 100 fitness trackers head-to-head — 3 workout stats I trust the least</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness-trackers/i-walked-4-000-steps-with-the-pixel-watch-5-vs-samsung-galaxy-watch-9-and-we-have-a-new-android-champ</link>
                                                                            <description>
                            <![CDATA[ Samsung Galaxy Watch 9 or Google Pixel Watch 5: which is the more accurate fitness tracker? I decided to find out by logging a workout with one on either wrist and comparing the data. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">xbpmp6ap4AYkcVfRpfV4w8</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/cHa3NJgTZQ6WEMqK2PhBiU-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 22 Aug 2026 05:30:00 +0000</pubDate>                                                                                                                                <updated>Sat, 22 Aug 2026 12:20:38 +0000</updated>
                                                                                                                                            <category><![CDATA[Fitness Trackers]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Smartwatches]]></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/cHa3NJgTZQ6WEMqK2PhBiU-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5]]></media:description>                                                            <media:text><![CDATA[Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/cHa3NJgTZQ6WEMqK2PhBiU-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Which 2026 smartwatch is the more accurate fitness tracker, the <a href="https://www.tomsguide.com/wellness/smartwatches/google-pixel-watch5-review">Google Pixel Watch 5 </a>or the <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-to-know-about-the-new-samsung-galaxy-watch-9">Samsung Galaxy Watch 9</a>? I just had to know.</p><p>So, I did what any tech geek with access to both devices and two wrists would do: I strapped one to each arm, logged a ~35-minute walk, and then compared the data. As a primary control for accuracy, I manually counted all 4,000 steps.</p><p>I also tracked the walk using the Strava app on my iPhone 16 Plus. Find the results of this comparison between the <a href="https://www.tomsguide.com/wellness/smartwatches/pixel-watch-5-vs-samsung-galaxy-watch-9-5-key-differences-you-need-to-know">Pixel Watch 5 and Galaxy Watch 9</a>, and key takeaways, below.  </p><h3 class="article-body__section" id="section-i-walked-4-000-steps-with-the-samsung-galaxy-watch-9-vs-google-pixel-watch-5"><span>I walked 4,000 steps with the Samsung Galaxy Watch 9 vs Google Pixel Watch 5</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:5408px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="r8eU5UpsMnb4H9VFcKFJiV" name="Galaxy9-Pixel5-04" alt="Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5" src="https://cdn.mos.cms.futurecdn.net/r8eU5UpsMnb4H9VFcKFJiV-1920-80.jpg" mos="" align="middle" fullscreen="" width="5408" height="3042" 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>So, which of these flagship Android wearables —  two of the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> around —  is the more competent fitness tracker: the Galaxy Watch 9 or Pixel Watch 5? Have a look for yourself. </p><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p>Pixel Watch 5</p></th><th  ><p>Galaxy Watch 9</p></th><th  ><p>Control</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Steps</strong></p></td><td  ><p>4,010 steps</p></td><td  ><p>4,017 steps</p></td><td  ><p> 4,000 steps (manual count)</p></td></tr><tr><td class="firstcol " ><p><strong>Distance</strong></p></td><td  ><p>2.07 miles</p></td><td  ><p>2.06 miles</p></td><td  ><p>2.11 miles</p></td></tr><tr><td class="firstcol " ><p><strong>Climb</strong></p></td><td  ><p>229 feet</p></td><td  ><p>254 feet</p></td><td  ><p>233 feet</p></td></tr><tr><td class="firstcol " ><p><strong>Average pace</strong></p></td><td  ><p>19 mins 23 secs per mile</p></td><td  ><p>18 mins 24 secs per mile</p></td><td  ><p>17 mins 54 secs per mile</p></td></tr><tr><td class="firstcol " ><p><strong>Average heart rate</strong></p></td><td  ><p>139 bpm</p></td><td  ><p>102 bpm</p></td><td  ><p>n/a</p></td></tr><tr><td class="firstcol " ><p><strong>Max heart rate</strong></p></td><td  ><p>160 bpm</p></td><td  ><p>128 bpm</p></td><td  ><p>n/a</p></td></tr><tr><td class="firstcol " ><p><strong>Calories burned</strong></p></td><td  ><p>410 total calories</p></td><td  ><p>219 total calories</p></td><td  ><p>n/a</p></td></tr><tr><td class="firstcol " ><p><strong>Battery usage</strong></p></td><td  ><p>4%</p></td><td  ><p>7%</p></td><td  ><p>n/a</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-google-s-step-count-was-closer"><span>Google's step count was closer</span></h3><p>As you can see, both the Samsung Galaxy Watch 9 and Google Pixel Watch 5 logged step count totals within 20 steps of my actual count, which is a seriously impressive and commendable result. However, in the interest of friendly competition and this article, the Pixel Watch officially wins in this category. </p><h3 class="article-body__section" id="section-the-pixel-watch-also-logged-more-accurate-climb-and-distance-data"><span>The Pixel Watch also logged more accurate climb and distance data</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:4182px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="Su4KjbbvHMUJPbJL3EjFJV" name="Galaxy9-Pixel5-01" alt="Close-up of the Samsung Galaxy Watch 9 next to the Google Pixel Watch 5" src="https://cdn.mos.cms.futurecdn.net/Su4KjbbvHMUJPbJL3EjFJV-1920-80.jpg" mos="" align="middle" fullscreen="" width="4182" height="2353" 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>Again, both the Google Pixel Watch 5 and the Samsung Galaxy Watch 9 performed extremely well when it came to accurately logging distance and climb. That said, the Pixel Watch's data was again closer to the control on both counts.</p><h3 class="article-body__section" id="section-google-s-pace-data-is-slower-than-expected"><span>Google's pace data is slower than expected</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:5322px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="ryz4WsgNuzbFG2wC9R8VKk" name="GalaxyWatch9-03" alt="Close-up of the Samsung Galaxy Watch 9 in white" src="https://cdn.mos.cms.futurecdn.net/ryz4WsgNuzbFG2wC9R8VKk-1920-80.jpg" mos="" align="middle" fullscreen="" width="5322" height="2994" 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 logging more precise distance, climb, and steps, the Pixel Watch 5 reported an oddly slow average pace for my walk. Not only is it more than a minute slower than Strava's pace, but it's also lower than pretty much every pace metric I've recorded during one of these walk test comparisons (and I've done <em>many</em>). </p><h3 class="article-body__section" id="section-samsung-s-heart-rate-data-is-lower-than-expected"><span>Samsung's heart rate data is lower than expected</span></h3><p>Speaking of strange results, Samsung's heart rate data for this comparison is way lower than expected. Again, I've done lots of these comparisons, and from the cumulative results, I generally expect an average heart rate of around 125 bpm and a max of around 160 bpm. </p><p>That may seem high, but keep in mind I am a brisk walker and purposely take steep, hilly routes to thoroughly assess elevation-tracking accuracy.  That said, Google's average heart rate is also strangely high, even if its max heart rate metric appears to be on the money.</p><h3 class="article-body__section" id="section-the-google-pixel-watch-5-wins"><span>The Google Pixel Watch 5 wins</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:3982px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UedGRJgfxxBpcTJLDkJwmi" name="Google Pixel Watch 5-LIST2" alt="Close-up of the Pixel Watch 5 in 45mm on a user's wrist" src="https://cdn.mos.cms.futurecdn.net/UedGRJgfxxBpcTJLDkJwmi-1920-80.jpg" mos="" align="middle" fullscreen="" width="3982" height="2240" 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>Ultimately, in this fitness tracking accuracy comparison between the Google Pixel Watch 5 and the Samsung Galaxy Watch 9, the Pixel Watch takes home the trophy, with more accurate step count, distance, and climb data. </p><p>The Samsung Galaxy Watch 9 also performed well at tracking most of my key metrics, with the exception of its questionably low heart rate recording, which I plan to investigate further as I work toward publishing a full review. Stay tuned for that!</p><p>In the meantime, what smartwatches, fitness trackers, or other wearables should I test head-to-head next? Let me know in the comments below. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-XjarYO"></div>                            </div>                            <script src="https://kwizly.com/embed/XjarYO.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/fitness-trackers/i-walked-5-000-steps-with-the-fitbit-air-vs-garmin-cirqa-round-2-we-have-a-new-champ"><strong>I walked 5,000 steps with the Fitbit Air vs Garmin Cirqa — Round 2: We have a new champ</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/galaxy-watch-ultra-2-hands-on-review"><strong>I’ve been wearing the Samsung Galaxy Watch Ultra 2 for nearly a week — 5 things I like and 1 thing I don’t</strong></a></li><li><a href="https://www.tomsguide.com/wellness/fitness-trackers/ive-tested-over-100-fitness-trackers-head-to-head-3-workout-stats-i-trust-the-least"><strong>I’ve tested over 100 fitness trackers head-to-head — 3 workout stats I trust the least</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I've been training with the Galaxy Watch 9 for a month — 3 things I like (and 3 I don't) ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The Samsung Galaxy Watch 9 was unveiled at the <a href="https://www.tomsguide.com/news/live/samsung-galaxy-unpacked-2026-live">Galaxy Unpacked</a> event alongside the <a href="https://www.tomsguide.com/wellness/smartwatches/galaxy-watch-ultra-2-hands-on-review">Galaxy Watch Ultra 2</a>.</p><p>To read the full lowdown on what you can do with the latest Galaxy Watch model, my wearables expert colleague <a href="https://www.tomsguide.com/author/dan-bracaglia">Dan Bracaglia</a> discusses the <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-to-know-about-the-new-samsung-galaxy-watch-9">5 things you need to know about the Galaxy Watch 9</a> in more detail. However, as a trainer and fitness editor, I'm more concerned about whether it's the type of watch I want strapped to my wrist during workouts. </p><p>Recently, I attended BXR to get first-hand experience with the watch on behalf of Samsung; we hit the treadmills, did some strength training and even stretched it out in a 20-minute yoga class. But for me, that wasn't enough. Thankfully, I got to spend more time with the model, training at home, in the gym and in my yoga classes, to really see what it's about. </p><p>Here are three things I like so far, and three that I'm really not a fan of if you're looking to purchase one of the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> in 2026.</p><div class="product"><a data-dimension112="ade90f98-9cd1-11f1-a314-f7a6b93fb3ee" data-action="Deal Block" data-label="Galaxy Watch 9" data-dimension48="Galaxy Watch 9" data-dimension25="£379.99" href="https://www.samsung.com/us/watches/galaxy-watch9/buy/galaxy-watch9-40mm-graphite-bluetooth-sku-sm-l340nzkaxaa/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1148px;"><p class="vanilla-image-block" style="padding-top:116.72%;"><img id="tEF32W52wJvZ9enzPgBxfB" name="Galaxy Watch 9 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/tEF32W52wJvZ9enzPgBxfB-1920-80.jpg" mos="" align="middle" fullscreen="" width="1148" height="1340" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Galaxy Watch 9 offers better battery life and a wealth of health and fitness tracking capabilities that aren't all locked behind a paywall. <a class="view-deal button" href="https://www.samsung.com/us/watches/galaxy-watch9/buy/galaxy-watch9-40mm-graphite-bluetooth-sku-sm-l340nzkaxaa/" target="_blank" rel="nofollow" data-dimension112="ade90f98-9cd1-11f1-a314-f7a6b93fb3ee" data-action="Deal Block" data-label="Galaxy Watch 9" data-dimension48="Galaxy Watch 9" data-dimension25="£379.99">View Deal</a></p></div><h3 class="article-body__section" id="section-like-1-aesthetics"><span>Like 1: Aesthetics</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:5322px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="ryz4WsgNuzbFG2wC9R8VKk" name="GalaxyWatch9-03" alt="Close-up of the Samsung Galaxy Watch 9 in white" src="https://cdn.mos.cms.futurecdn.net/ryz4WsgNuzbFG2wC9R8VKk-1920-80.jpg" mos="" align="middle" fullscreen="" width="5322" height="2994" 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>Retailing at $379 for 40mm (no LTE, which is $50 extra) or $409 for 44mm (no LTE) compared to $349 for the Galaxy Watch 8, the 9 is no doubt a good-looking smartwatch-fitness tracker with a premium price tag. </p><p>I like how easy it is to set up and pair with the <a href="https://www.tomsguide.com/phones/samsung-phones/ive-spent-more-than-three-weeks-using-the-galaxy-z-flip-8-and-its-a-tipping-point-for-samsung">Samsung Galaxy Z Flip 8</a>, and the sleek sports strap and screen design are right up my alley; I don't like having garish fitness trackers or fussy smartwatches on my wrist, especially when lifting weights. 40mm is available in Cream or Graphite; 44mm comes in Graphite or Silver.</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/DbK_qq0gAGV/" target="_blank">A post shared by Tom's Guide Fitness (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><p>We'll get on to size (one of my dislikes) below, but in terms of design, you get pretty much the same aesthetics, screen brightness and size options as the 8. However, the 9 boasts a faster processor and up to 20% better battery life. You can also customize your sports bands with various color options, too.</p><p>I highly recommend leaving the always-on option enabled so you can glance during workouts. I didn't do this at first and it caused me some very high cortisol levels and extra faff.</p><p>But let's focus on the real MVP: new health and fitness tracking tools. </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/DcN39S0IeBU/" target="_blank">A post shared by Tom's Guide Fitness (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><h3 class="article-body__section" id="section-like-2-swipeable-health-features-upgraded"><span>Like 2: Swipeable health features upgraded</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:4996px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="qkNNwr3UPRR6b8yK94DdDk" name="GalaxyWatch9-01" alt="Close-up of the Samsung Galaxy Watch 9 on a user's wrist against a blue background" src="https://cdn.mos.cms.futurecdn.net/qkNNwr3UPRR6b8yK94DdDk-1920-80.jpg" mos="" align="middle" fullscreen="" width="4996" height="2810" 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>Samsung Health offers a wealth of fitness and health tracking and insights, without locking it all behind a paywall. There are plenty of sports and activities to choose from, and an array of sensors means you can pick up pretty detailed data.</p><p>Some of the latest upgrades include a <strong>Vitals dashboard </strong>with metrics for heart rate, HRV, sp02, body temperature, breathing, and <strong>Heart Health Score.</strong> Alongside this, you get fitness features such as <strong>Cardio Load</strong> and <strong>Fitness Index</strong> (a score out of 100 based on activity levels, VO2 max, recovery time and more).</p><p>The idea is to be preventative, which means more of a holistic focus on wellbeing and useful insights. The Vitals dashboard features one easy-to-view panel with information on heart rate, blood pressure and ECG. It's handy to swipe left and right to catch a quick glance while on the go. You can also swipe to use quick features such as <strong>Running Coach, Body Composition and Sleep. </strong></p><p>By swiping twice to my left, I could quickly access the <strong>Fitness</strong> section, where I could select from a list of activities or add my own via my Samsung Galaxy phone or on the watch itself. You can set up your watch to suit your preferences, but note that you'll need to sleep with it on to access some of the longer-term trends and vitals, particularly sleep, of course.</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="o3hRCLxa7rk5VKMhfRf2Wa" name="samsung galaxy watch vs coros 2" alt="Samsung Galaxy Watch 9 on user wrist during treadmill workout" src="https://cdn.mos.cms.futurecdn.net/o3hRCLxa7rk5VKMhfRf2Wa-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>I’ve worn the<a href="https://www.tomsguide.com/wellness/smartwatches/coros-pace-4-review"> Coros Pace 4 </a>alongside the Samsung Galaxy Watch 9 on several occasions. Not because it's a totally fair comparison, but if I'm exploring what I like and don't like about a watch during exercise, I'm doing it with my favorite one on my wrist, too. </p><p>The Coros Pace 4 has proved reliable for workouts for me and my colleague <a href="https://www.tomsguide.com/author/nick-harris-fry">Nick Harris-Fry</a>, who runs regularly wearing it alongside other wearables because of dual-band GPS tracking and top sports features.</p><p>Throughout testing, the Galaxy Watch 9 has been fairly consistent with my trusty Coros Pace 4, though the Watch 9 tends to track more time spent in heart rate zones 1, 2, and 3 during my running efforts than the Pace 4. The Watch 9 also tends to overestimate calorie burn, but I don't pay too much attention to <a href="https://www.tomsguide.com/wellness/workouts/we-asked-toms-guide-readers-which-fitness-tracking-metrics-do-you-trust-the-least-heres-the-surprising-answer">calorie burn on fitness trackers</a> anyway, as so many variables impact how many active calories you can burn.</p><p>That aside, distances and paces have been around the same, and the Galaxy Watch 9 is intuitive at picking up workouts through auto-detection. And it's useful to remember that the Pace 4 is a sports watch, after all, not a smart one, so those who are most likely to purchase this smartwatch-come-fitness tracker will be looking at a lot more than just workouts.</p><h3 class="article-body__section" id="section-like-3-auto-activity-detection"><span>Like 3: Auto activity detection</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="Um6SwSAjctWztR46p2WpVa" name="samsung galaxy v coros" alt="Samsung Galaxy Watch 9 on user wrist during treadmill workout" src="https://cdn.mos.cms.futurecdn.net/Um6SwSAjctWztR46p2WpVa-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: Future)</span></figcaption></figure><p>The Samsung Galaxy Watch 9 can automatically track exercises, including walking, running, cycling, swimming, rowing, and elliptical, using its BioActive Sensor and accelerometer. That means you don't need to rely on manually starting some activities, which I found really handy.</p><p>The watch automatically picked up when I walked and paused when it detected I was stationary. I found this to be pretty accurate for time and distance, and it's good to know that this data feeds into my overall activity levels, trends and insights. I'd like this feature to roll out across more activities, but it's great that the basics are there.</p><p>I could view duration, pace, distance and time of day at a glance, and I found the watch particularly good for tracking running data. That said, if you take your running seriously, you'd be looking more at the <a href="https://www.tomsguide.com/wellness/smartwatches/i-tested-19-running-watches-in-2025-these-are-the-2-that-id-actually-buy">best running watch</a> anyway. </p><h3 class="article-body__section" id="section-dislike-1-hard-to-use-on-the-go"><span>Dislike 1: Hard to use on the go</span></h3><p>I recently became emotionally dependent on my Coros Pace 4 sports watch, which is easy to wear, tight-fitting, rugged, very easy to use on the go and tracks everything I need during exercise. It also has excellent battery life without overwhelming me. </p><p>While this is not a head-to-head comparison, using both watches has given me a strong sense of what works and doesn't work for me personally during exercise.</p><p>I've worn both watches for yoga, Pilates, strength training and running, and I find the Galaxy Watch 9 "faffy" to use. The screen is extremely sensitive (but yes, it is fast), and I find it hard to navigate the tiles and swipe left-to-right quickly while running and walking.</p><p>I'm a button girlie, and while the swipeable screen is handy, I will always prefer navigating settings primarily with buttons. There are two on the watch on the right side, but I couldn't use them as much as I wanted to.</p><p>I'm also not a fan of overcomplicated screens and having to swipe this way and that to see a handful of the metrics I find most important. I recommend spending some time setting up your Galaxy Watch 9 by configuring the layout and features you need most, plus choosing a clean watch face via the Galaxy Wearable app, if you're a bit like me with tech overwhelm.</p><p>You'll also need to go into the Samsung Health app to enable various health and fitness tracking features, which aren't automatically set up; be warned, there are many, and it takes a little time. </p><h3 class="article-body__section" id="section-dislike-2-sizing"><span>Dislike 2: Sizing</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="eFPf6iF8xmwkUeBk8Z7uTa" name="samsung galaxy watch vs coros 3" alt="Samsung Galaxy Watch 9 on user wrist during treadmill workout" src="https://cdn.mos.cms.futurecdn.net/eFPf6iF8xmwkUeBk8Z7uTa-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>As a female with small wrists, I have this issue with sports and smartwatches all the time. It's one of the areas where my colleague Jane McGuire says<a href="https://www.tomsguide.com/wellness/fitness-trackers/ive-been-writing-about-fitness-trackers-for-a-decade-10-years-later-they-are-still-falling-short-for-women"> fitness trackers still fall short for women.  </a></p><p>I don't need bulk on my wrists when I lift weights or run; it is distracting and creates more weight and fuss when I'm trying to position weights along my forearms for exercises like front rack squats or cleans.  </p><p>For me, the Galaxy Watch 9 feels heavy, even with the aluminum casing, which is supposed to help make the watch lightweight. I was given a M/L wrist strap, so I highly recommend picking a S/M strap if you have small wrists like mine, as the watch slid around even on the tightest strap setting.</p><p>For those who get sweaty during workouts, I'd also consider the fabric band instead of the sports band that came with my watch.</p><p>While I do like how the watch looks and I enjoy the understated design, I'm not a fan of the sizing overall, even for the smaller 40mm model. I still think brands need to think more about their female customers when designing smartwatches and sports watches in general.</p><p>For that reason, I wouldn't want to wear this watch to bed. But that said, I generally don't like having anything on my wrist at night and rely on my <a href="https://www.tomsguide.com/wellness/smart-rings/ive-worn-the-oura-ring-5-for-six-weeks-here-are-3-things-i-love-and-2-things-i-wish-i-could-change">Oura Ring 5</a> to track sleep instead. If this is a problem for you, note that some features rely on you sleeping in your watch.</p><h3 class="article-body__section" id="section-dislike-3-battery-life"><span>Dislike 3: Battery life</span></h3><p>Both the 40mm and 44mm Samsung Galaxy Watch 9 models feature modest battery capacity increases. For the smaller model, that's a jump from 325 mAh for the Galaxy Watch 8 to 390 mAh for the Galaxy Watch 9. For the bigger model, the capacity has increased from 435 mAh on the Galaxy Watch 8 to 445 mAh for the Galaxy Watch 9.</p><p>This, coupled with up to 15% more efficient processing,<em> should </em>mean that the Galaxy Watch 9 lasts longer than the average of roughly 30 hours per charge (for the 8) with the always-on enabled.</p><p>I'd say I'm very active, and mine has lasted roughly 24 hours on a charge. Compare that with watches like the <a href="https://www.tomsguide.com/wellness/smartwatches/i-just-tried-the-new-google-pixel-watch-5-and-its-new-health-and-safety-features-blow-the-apple-watch-out-of-the-water">Pixel Watch 5,</a> which should last around two days, and the <a href="https://www.tomsguide.com/wellness/smartwatches/coros-pace-4-review">Coros Pace 4</a>, which I usually wear and can last me about a week, and the battery life could be better. </p><p>I'm a little disappointed, as battery life is one of the features most celebrated with the Galaxy Watch 9. if I were taking it away on a trip, I'd need to charge it every day, though it does charge quickly when you do juice it up.</p><h2 id="verdict">Verdict</h2><p>For me, the Samsung Galaxy Watch 9 looks great, is fast, offers a wealth of health and fitness features and pretty accurate tracking across the activities I tested, but would I switch out other trusty watches in favor of it for exercise alone? No, I wouldn't. </p><p>That said, I will be spending some more time wearing it, and I plan to update you here with more long-term feedback. </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/smartwatches/google-exclusive-how-the-pixel-watch-3-got-a-life-saving-feature-the-apple-watch-cant-match"><strong>Exclusive: Garmin Cirqa PM says ‘it just felt like we had all of the pieces in place’ to launch a screen-free fitness tracker</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness/an-iphone-moment-for-your-eyes-why-xpanceo-is-betting-big-on-smart-contact-lenses-as-the-future-of-ar"><strong>An ‘iPhone moment’ for your eyes — why Xpanceo is betting big on smart contact lenses as the future of AR</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/exclusive-google-design-director-says-fitbit-air-reception-proves-they-made-the-right-decision-going-screen-free"><strong>Exclusive: Google design director says Fitbit Air reception proves they 'made the right decision' going screen-free</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smartwatches/ive-been-training-with-the-galaxy-watch-9-for-a-month-3-things-i-like-and-3-i-dont</link>
                                                                            <description>
                            <![CDATA[ We've been training with the Galaxy Watch 9, and there are some features we like and dislike so far. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">NT6f8Q8DoFuk7EciGQX2r4</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/9VYZkwkFKGrzUBK9zzEc3k-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 21 Aug 2026 08:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smartwatches]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                <author><![CDATA[ sam.hopes@futurenet.com (Sam Hopes) ]]></author>                    <dc:creator><![CDATA[ Sam Hopes ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/jZ88qJqvjWaCXXv3qvUQPA-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/9VYZkwkFKGrzUBK9zzEc3k-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the Samsung Galaxy Watch 9 in white]]></media:description>                                                            <media:text><![CDATA[Close-up of the Samsung Galaxy Watch 9 in white]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the Samsung Galaxy Watch 9 in white]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/9VYZkwkFKGrzUBK9zzEc3k-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The Samsung Galaxy Watch 9 was unveiled at the <a href="https://www.tomsguide.com/news/live/samsung-galaxy-unpacked-2026-live">Galaxy Unpacked</a> event alongside the <a href="https://www.tomsguide.com/wellness/smartwatches/galaxy-watch-ultra-2-hands-on-review">Galaxy Watch Ultra 2</a>.</p><p>To read the full lowdown on what you can do with the latest Galaxy Watch model, my wearables expert colleague <a href="https://www.tomsguide.com/author/dan-bracaglia">Dan Bracaglia</a> discusses the <a href="https://www.tomsguide.com/wellness/smartwatches/5-things-to-know-about-the-new-samsung-galaxy-watch-9">5 things you need to know about the Galaxy Watch 9</a> in more detail. However, as a trainer and fitness editor, I'm more concerned about whether it's the type of watch I want strapped to my wrist during workouts. </p><p>Recently, I attended BXR to get first-hand experience with the watch on behalf of Samsung; we hit the treadmills, did some strength training and even stretched it out in a 20-minute yoga class. But for me, that wasn't enough. Thankfully, I got to spend more time with the model, training at home, in the gym and in my yoga classes, to really see what it's about. </p><p>Here are three things I like so far, and three that I'm really not a fan of if you're looking to purchase one of the <a href="https://www.tomsguide.com/wellness/smartwatches/best-smartwatch">best smartwatches</a> in 2026.</p><div class="product"><a data-dimension112="ade90f98-9cd1-11f1-a314-f7a6b93fb3ee" data-action="Deal Block" data-label="Galaxy Watch 9" data-dimension48="Galaxy Watch 9" data-dimension25="£379.99" href="https://www.samsung.com/us/watches/galaxy-watch9/buy/galaxy-watch9-40mm-graphite-bluetooth-sku-sm-l340nzkaxaa/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1148px;"><p class="vanilla-image-block" style="padding-top:116.72%;"><img id="tEF32W52wJvZ9enzPgBxfB" name="Galaxy Watch 9 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/tEF32W52wJvZ9enzPgBxfB-1920-80.jpg" mos="" align="middle" fullscreen="" width="1148" height="1340" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The Galaxy Watch 9 offers better battery life and a wealth of health and fitness tracking capabilities that aren't all locked behind a paywall. <a class="view-deal button" href="https://www.samsung.com/us/watches/galaxy-watch9/buy/galaxy-watch9-40mm-graphite-bluetooth-sku-sm-l340nzkaxaa/" target="_blank" rel="nofollow" data-dimension112="ade90f98-9cd1-11f1-a314-f7a6b93fb3ee" data-action="Deal Block" data-label="Galaxy Watch 9" data-dimension48="Galaxy Watch 9" data-dimension25="£379.99">View Deal</a></p></div><h3 class="article-body__section" id="section-like-1-aesthetics"><span>Like 1: Aesthetics</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:5322px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="ryz4WsgNuzbFG2wC9R8VKk" name="GalaxyWatch9-03" alt="Close-up of the Samsung Galaxy Watch 9 in white" src="https://cdn.mos.cms.futurecdn.net/ryz4WsgNuzbFG2wC9R8VKk-1920-80.jpg" mos="" align="middle" fullscreen="" width="5322" height="2994" 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>Retailing at $379 for 40mm (no LTE, which is $50 extra) or $409 for 44mm (no LTE) compared to $349 for the Galaxy Watch 8, the 9 is no doubt a good-looking smartwatch-fitness tracker with a premium price tag. </p><p>I like how easy it is to set up and pair with the <a href="https://www.tomsguide.com/phones/samsung-phones/ive-spent-more-than-three-weeks-using-the-galaxy-z-flip-8-and-its-a-tipping-point-for-samsung">Samsung Galaxy Z Flip 8</a>, and the sleek sports strap and screen design are right up my alley; I don't like having garish fitness trackers or fussy smartwatches on my wrist, especially when lifting weights. 40mm is available in Cream or Graphite; 44mm comes in Graphite or Silver.</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/DbK_qq0gAGV/" target="_blank">A post shared by Tom's Guide Fitness (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><p>We'll get on to size (one of my dislikes) below, but in terms of design, you get pretty much the same aesthetics, screen brightness and size options as the 8. However, the 9 boasts a faster processor and up to 20% better battery life. You can also customize your sports bands with various color options, too.</p><p>I highly recommend leaving the always-on option enabled so you can glance during workouts. I didn't do this at first and it caused me some very high cortisol levels and extra faff.</p><p>But let's focus on the real MVP: new health and fitness tracking tools. </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/DcN39S0IeBU/" target="_blank">A post shared by Tom's Guide Fitness (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><h3 class="article-body__section" id="section-like-2-swipeable-health-features-upgraded"><span>Like 2: Swipeable health features upgraded</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:4996px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="qkNNwr3UPRR6b8yK94DdDk" name="GalaxyWatch9-01" alt="Close-up of the Samsung Galaxy Watch 9 on a user's wrist against a blue background" src="https://cdn.mos.cms.futurecdn.net/qkNNwr3UPRR6b8yK94DdDk-1920-80.jpg" mos="" align="middle" fullscreen="" width="4996" height="2810" 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>Samsung Health offers a wealth of fitness and health tracking and insights, without locking it all behind a paywall. There are plenty of sports and activities to choose from, and an array of sensors means you can pick up pretty detailed data.</p><p>Some of the latest upgrades include a <strong>Vitals dashboard </strong>with metrics for heart rate, HRV, sp02, body temperature, breathing, and <strong>Heart Health Score.</strong> Alongside this, you get fitness features such as <strong>Cardio Load</strong> and <strong>Fitness Index</strong> (a score out of 100 based on activity levels, VO2 max, recovery time and more).</p><p>The idea is to be preventative, which means more of a holistic focus on wellbeing and useful insights. The Vitals dashboard features one easy-to-view panel with information on heart rate, blood pressure and ECG. It's handy to swipe left and right to catch a quick glance while on the go. You can also swipe to use quick features such as <strong>Running Coach, Body Composition and Sleep. </strong></p><p>By swiping twice to my left, I could quickly access the <strong>Fitness</strong> section, where I could select from a list of activities or add my own via my Samsung Galaxy phone or on the watch itself. You can set up your watch to suit your preferences, but note that you'll need to sleep with it on to access some of the longer-term trends and vitals, particularly sleep, of course.</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="o3hRCLxa7rk5VKMhfRf2Wa" name="samsung galaxy watch vs coros 2" alt="Samsung Galaxy Watch 9 on user wrist during treadmill workout" src="https://cdn.mos.cms.futurecdn.net/o3hRCLxa7rk5VKMhfRf2Wa-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>I’ve worn the<a href="https://www.tomsguide.com/wellness/smartwatches/coros-pace-4-review"> Coros Pace 4 </a>alongside the Samsung Galaxy Watch 9 on several occasions. Not because it's a totally fair comparison, but if I'm exploring what I like and don't like about a watch during exercise, I'm doing it with my favorite one on my wrist, too. </p><p>The Coros Pace 4 has proved reliable for workouts for me and my colleague <a href="https://www.tomsguide.com/author/nick-harris-fry">Nick Harris-Fry</a>, who runs regularly wearing it alongside other wearables because of dual-band GPS tracking and top sports features.</p><p>Throughout testing, the Galaxy Watch 9 has been fairly consistent with my trusty Coros Pace 4, though the Watch 9 tends to track more time spent in heart rate zones 1, 2, and 3 during my running efforts than the Pace 4. The Watch 9 also tends to overestimate calorie burn, but I don't pay too much attention to <a href="https://www.tomsguide.com/wellness/workouts/we-asked-toms-guide-readers-which-fitness-tracking-metrics-do-you-trust-the-least-heres-the-surprising-answer">calorie burn on fitness trackers</a> anyway, as so many variables impact how many active calories you can burn.</p><p>That aside, distances and paces have been around the same, and the Galaxy Watch 9 is intuitive at picking up workouts through auto-detection. And it's useful to remember that the Pace 4 is a sports watch, after all, not a smart one, so those who are most likely to purchase this smartwatch-come-fitness tracker will be looking at a lot more than just workouts.</p><h3 class="article-body__section" id="section-like-3-auto-activity-detection"><span>Like 3: Auto activity detection</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="Um6SwSAjctWztR46p2WpVa" name="samsung galaxy v coros" alt="Samsung Galaxy Watch 9 on user wrist during treadmill workout" src="https://cdn.mos.cms.futurecdn.net/Um6SwSAjctWztR46p2WpVa-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: Future)</span></figcaption></figure><p>The Samsung Galaxy Watch 9 can automatically track exercises, including walking, running, cycling, swimming, rowing, and elliptical, using its BioActive Sensor and accelerometer. That means you don't need to rely on manually starting some activities, which I found really handy.</p><p>The watch automatically picked up when I walked and paused when it detected I was stationary. I found this to be pretty accurate for time and distance, and it's good to know that this data feeds into my overall activity levels, trends and insights. I'd like this feature to roll out across more activities, but it's great that the basics are there.</p><p>I could view duration, pace, distance and time of day at a glance, and I found the watch particularly good for tracking running data. That said, if you take your running seriously, you'd be looking more at the <a href="https://www.tomsguide.com/wellness/smartwatches/i-tested-19-running-watches-in-2025-these-are-the-2-that-id-actually-buy">best running watch</a> anyway. </p><h3 class="article-body__section" id="section-dislike-1-hard-to-use-on-the-go"><span>Dislike 1: Hard to use on the go</span></h3><p>I recently became emotionally dependent on my Coros Pace 4 sports watch, which is easy to wear, tight-fitting, rugged, very easy to use on the go and tracks everything I need during exercise. It also has excellent battery life without overwhelming me. </p><p>While this is not a head-to-head comparison, using both watches has given me a strong sense of what works and doesn't work for me personally during exercise.</p><p>I've worn both watches for yoga, Pilates, strength training and running, and I find the Galaxy Watch 9 "faffy" to use. The screen is extremely sensitive (but yes, it is fast), and I find it hard to navigate the tiles and swipe left-to-right quickly while running and walking.</p><p>I'm a button girlie, and while the swipeable screen is handy, I will always prefer navigating settings primarily with buttons. There are two on the watch on the right side, but I couldn't use them as much as I wanted to.</p><p>I'm also not a fan of overcomplicated screens and having to swipe this way and that to see a handful of the metrics I find most important. I recommend spending some time setting up your Galaxy Watch 9 by configuring the layout and features you need most, plus choosing a clean watch face via the Galaxy Wearable app, if you're a bit like me with tech overwhelm.</p><p>You'll also need to go into the Samsung Health app to enable various health and fitness tracking features, which aren't automatically set up; be warned, there are many, and it takes a little time. </p><h3 class="article-body__section" id="section-dislike-2-sizing"><span>Dislike 2: Sizing</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="eFPf6iF8xmwkUeBk8Z7uTa" name="samsung galaxy watch vs coros 3" alt="Samsung Galaxy Watch 9 on user wrist during treadmill workout" src="https://cdn.mos.cms.futurecdn.net/eFPf6iF8xmwkUeBk8Z7uTa-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>As a female with small wrists, I have this issue with sports and smartwatches all the time. It's one of the areas where my colleague Jane McGuire says<a href="https://www.tomsguide.com/wellness/fitness-trackers/ive-been-writing-about-fitness-trackers-for-a-decade-10-years-later-they-are-still-falling-short-for-women"> fitness trackers still fall short for women.  </a></p><p>I don't need bulk on my wrists when I lift weights or run; it is distracting and creates more weight and fuss when I'm trying to position weights along my forearms for exercises like front rack squats or cleans.  </p><p>For me, the Galaxy Watch 9 feels heavy, even with the aluminum casing, which is supposed to help make the watch lightweight. I was given a M/L wrist strap, so I highly recommend picking a S/M strap if you have small wrists like mine, as the watch slid around even on the tightest strap setting.</p><p>For those who get sweaty during workouts, I'd also consider the fabric band instead of the sports band that came with my watch.</p><p>While I do like how the watch looks and I enjoy the understated design, I'm not a fan of the sizing overall, even for the smaller 40mm model. I still think brands need to think more about their female customers when designing smartwatches and sports watches in general.</p><p>For that reason, I wouldn't want to wear this watch to bed. But that said, I generally don't like having anything on my wrist at night and rely on my <a href="https://www.tomsguide.com/wellness/smart-rings/ive-worn-the-oura-ring-5-for-six-weeks-here-are-3-things-i-love-and-2-things-i-wish-i-could-change">Oura Ring 5</a> to track sleep instead. If this is a problem for you, note that some features rely on you sleeping in your watch.</p><h3 class="article-body__section" id="section-dislike-3-battery-life"><span>Dislike 3: Battery life</span></h3><p>Both the 40mm and 44mm Samsung Galaxy Watch 9 models feature modest battery capacity increases. For the smaller model, that's a jump from 325 mAh for the Galaxy Watch 8 to 390 mAh for the Galaxy Watch 9. For the bigger model, the capacity has increased from 435 mAh on the Galaxy Watch 8 to 445 mAh for the Galaxy Watch 9.</p><p>This, coupled with up to 15% more efficient processing,<em> should </em>mean that the Galaxy Watch 9 lasts longer than the average of roughly 30 hours per charge (for the 8) with the always-on enabled.</p><p>I'd say I'm very active, and mine has lasted roughly 24 hours on a charge. Compare that with watches like the <a href="https://www.tomsguide.com/wellness/smartwatches/i-just-tried-the-new-google-pixel-watch-5-and-its-new-health-and-safety-features-blow-the-apple-watch-out-of-the-water">Pixel Watch 5,</a> which should last around two days, and the <a href="https://www.tomsguide.com/wellness/smartwatches/coros-pace-4-review">Coros Pace 4</a>, which I usually wear and can last me about a week, and the battery life could be better. </p><p>I'm a little disappointed, as battery life is one of the features most celebrated with the Galaxy Watch 9. if I were taking it away on a trip, I'd need to charge it every day, though it does charge quickly when you do juice it up.</p><h2 id="verdict">Verdict</h2><p>For me, the Samsung Galaxy Watch 9 looks great, is fast, offers a wealth of health and fitness features and pretty accurate tracking across the activities I tested, but would I switch out other trusty watches in favor of it for exercise alone? No, I wouldn't. </p><p>That said, I will be spending some more time wearing it, and I plan to update you here with more long-term feedback. </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/smartwatches/google-exclusive-how-the-pixel-watch-3-got-a-life-saving-feature-the-apple-watch-cant-match"><strong>Exclusive: Garmin Cirqa PM says ‘it just felt like we had all of the pieces in place’ to launch a screen-free fitness tracker</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness/an-iphone-moment-for-your-eyes-why-xpanceo-is-betting-big-on-smart-contact-lenses-as-the-future-of-ar"><strong>An ‘iPhone moment’ for your eyes — why Xpanceo is betting big on smart contact lenses as the future of AR</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness-trackers/exclusive-google-design-director-says-fitbit-air-reception-proves-they-made-the-right-decision-going-screen-free"><strong>Exclusive: Google design director says Fitbit Air reception proves they 'made the right decision' going screen-free</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
            </channel>
</rss>