<?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/apple" rel="self" type="application/rss+xml" />
                            <title><![CDATA[ Latest from Tom's Guide in Apple ]]></title>
                <link>https://www.tomsguide.com/tag/apple</link>
        <description><![CDATA[ All the latest apple content from the Tom's Guide team ]]></description>
                                    <lastBuildDate>Fri, 11 Sep 2026 15:05:49 +0000</lastBuildDate>
                            <language>en</language>
                                <item>
                                                            <title><![CDATA[ People are freaking out about the new 'always-listening' Apple Watches — here's what Apple CEO John Ternus told us ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Among the <a href="https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained">big new features Apple</a> revealed with 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> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a> were a few that pricked the ears of those with privacy concerns. Apple's Audio Intelligence is a suite of AI-powered features that use the Apple Watch to listen in on what's happening around you, so that Siri can provide more proactive advice, as well as help you remember what it was you just heard. </p><p>The most controversial of these features were <strong>Siri Recap,</strong> which allows your watch to listen in on conversations you have throughout the day, and uses AI to take notes and generate summaries, and <strong>Live Rewind</strong>, which lets you go back 15 seconds and view a transcript of what was just said. </p><p>The idea behind this is that Apple can "jog your memory" on events from your day, and make sure you can stay present in the moment. Naturally there are a lot of people who aren't happy about the idea that someone's Apple Watch could be listening in on conversations without warning. </p><div class="youtube-video" data-nosnippet ><div class="video-aspect-box"><iframe data-lazy-priority="high" data-lazy-src="https://www.youtube-nocookie.com/embed/HWg75OAmJLc?start=187" allowfullscreen></iframe></div></div><p>Apple has anticipated this, and when <a href="https://www.tomsguide.com/phones/iphones/interview-apple-ceo-john-ternus-on-his-defining-moment-for-the-iphone-duo">we spoke to John Ternus</a>, the new Apple CEO, and Greg Joswiak, Apple's senior vice president of worldwide marketing, they revealed their approach to Recap's privacy at length.</p><p>"Whenever we do anything, we always do it with an eye towards privacy and security," Ternus said. "It's something we take very seriously and approach very thoughtfully. </p><p>On the subject of Siri Recap, Ternus pointed out that it's been possible to record audio and create transcripts of what people have said for a while — both on smartwatches and phones. </p><p>Ternus makes it clear that recap does not produce a recording or a transcript, with Jozwiak adding that Apple can't access what doesn't exist. "If we don't have a recording, it means no one else has the recording. It can't get hacked. It can't get delivered to somebody."</p><p>It sounds unrealistic, but Jozwiak does confirm that Apple had to develop a whole new chip to make Recap possible in this manner. In the process, he sees it as a feature that allows people to concentrate on what they're doing, while being able to generate "higher level notes" that aren't indiscriminately documenting whatever sensitive information is being said.</p><p>"We wanted to do this in a way that people feel comfortable using it, said Ternus. "And people around the user feel comfortable about its existence."</p><h2 id="siri-recap-39-s-privacy-features">Siri Recap's privacy features</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width: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.jpg" mos="" align="middle" fullscreen="" width="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 also <a href="https://support.apple.com/en-us/148354" target="_blank" rel="nofollow">posted a sizable explainer</a> discussing all the different privacy features Recap incorporates.</p><p>The big privacy feature here is that any audio that the Watch hears is sent to Apple's Secure Enclave on the watch itself or your paired iPhone. Apple claims that it can't be accessed by the user, Apple, apps or even the operating system itself. </p><p>The audio also isn't recorded or stored, though the processed data is summarized and formatted by <a href="https://www.tomsguide.com/ai/apple-intelligence/apple-will-pay-up-to-usd1-million-to-anyone-who-finds-a-privacy-flaw-inside-apple-intelligence">Apple's Private Cloud Compute</a>. Apparently this involves condensed versions of the original conversation that are less than half their length, reducing the contents to the core, rather than a full-length transcript.</p><p>While the Private Cloud Compute data is not accessible by Apple or anyone else, it does still mean your data is being processed on the cloud rather than just on your device. Which may be too risky for some of you to agree with.</p><div><blockquote><p>While the Private Cloud Compute data is not accessible by Apple or anyone else, it does still mean your data is being processed on the cloud rather than just on your device.</p></blockquote></div><p>Other features include a lack of speaker attribution, which means nobody will be directly quoted or attributed to. Siri is also going to censor what it hears, and will automatically omit anything it deems harmful or sensitive. Apple says this includes language promoting self-harm, hate speech, financial data, authentication and personally identifying data and "government-assigned identifiers." So it won't be making a record of your social security number.</p><p>Summaries are automatically deleted after seven days unless you save them to the Siri app. Like all Siri data, those saved summaries can then be deleted from all synced devices at any time — though you can also export them to other apps, including Apple Notes. Syncing is also encrypted and done via iCloud, meaning only your own trusted devices can access those summaries.</p><p>Recaps aren't running all the time, and you do need to opt in to actually set them up. How they record depends on you, with Apple promising you can set up a schedule or manually toggle it on and off in the Control Center. </p><p>Because it's an AI feature, Apple has the usual caveat explaining that the summaries aren't going to be 100% accurate all the time. That doesn't fill me with a whole lot of confidence, especially after the <a href="https://www.tomsguide.com/ai/apple-intelligence/apple-scraps-apple-intelligence-news-feature-after-misinformation-complaints-what-you-need-to-know">fiasco with Apple News summaries</a> that had to be recalled from iOS.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-X75rDW"></div>                            </div>                            <script src="https://kwizly.com/embed/X75rDW.js" async></script><h2 id="live-rewind">Live Rewind</h2><p>If you've ever been pulled in two directions at once, you've inevitably had to ask "what did you just say?" to someone. Live Rewind is meant to help jog your short-short-term memory, by displaying a text snippet of the last 15 seconds of conversation when you double-press the Digital Crown on your Apple Watch.</p><p>To address privacy concerns around this feature, Apple says that these text snippets "disappear permanently from your Apple Watch approximately 30 seconds after the Apple Watch display dims," unless you purposely save them. </p><h2 id="this-doesn-39-t-fix-everything">This doesn't fix everything</h2><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.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 suggests that people "be mindful" of everyone around them, especially if there are sensitive conversations happening. Though that may be giving people too much credit. </p><p>There are plenty of people out there that are considerate of other people's thoughts and opinions, but there are also plenty who aren't. They either forget recap is running, or straight up do not care that other people may not like it.</p><p>Admittedly, both Ternus and Jozwiak have a point: there are features that offer this sort of thing without <em>any</em> emphasis on privacy. Then again, it is more likely that people take issue with the implied always-listening approach Recap takes. I personally feel it would make a lot more sense to restrict it to manual control.</p><p>Whichever way you look at it, though, I guess it's still a better option than seeing people pull out their phones to video every little unusual thing they come across.</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/best-picks/best-apple-watch">We've tested every Apple Watch and these are the 3 models I recommend right now</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-vs-apple-watch-ultra-4-which-new-apple-watch-should-you-buy">Apple Watch Series 12 vs Apple Watch Ultra 4: Which new Apple Watch should you buy?</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained">All the new audio features on Apple Watch explained</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>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</link>
                                                                            <description>
                            <![CDATA[ Some people aren't happy that Siri Recap could be listening in without you realizing, but Apple still has privacy on its mind. I'm not convinced it'll solve the issues people have, though. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">EPvzymhxEDF2bMCmUPBeUi</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/h9pUCaivgXc2tpjF4BPEu4-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 11 Sep 2026 15:05:49 +0000</pubDate>                                                                                                                                <updated>Fri, 11 Sep 2026 15:36:33 +0000</updated>
                                                                                                                                            <category><![CDATA[Apple Intelligence]]></category>
                                                    <category><![CDATA[AI]]></category>
                                                                                                <author><![CDATA[ tom.pritchard@futurenet.com (Tom Pritchard) ]]></author>                    <dc:creator><![CDATA[ Tom Pritchard ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/biCewUkKfSA6QnT2HxVc3f.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/h9pUCaivgXc2tpjF4BPEu4-1280-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-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Among the <a href="https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained">big new features Apple</a> revealed with 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> and <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a> were a few that pricked the ears of those with privacy concerns. Apple's Audio Intelligence is a suite of AI-powered features that use the Apple Watch to listen in on what's happening around you, so that Siri can provide more proactive advice, as well as help you remember what it was you just heard. </p><p>The most controversial of these features were <strong>Siri Recap,</strong> which allows your watch to listen in on conversations you have throughout the day, and uses AI to take notes and generate summaries, and <strong>Live Rewind</strong>, which lets you go back 15 seconds and view a transcript of what was just said. </p><p>The idea behind this is that Apple can "jog your memory" on events from your day, and make sure you can stay present in the moment. Naturally there are a lot of people who aren't happy about the idea that someone's Apple Watch could be listening in on conversations without warning. </p><div class="youtube-video" data-nosnippet ><div class="video-aspect-box"><iframe data-lazy-priority="high" data-lazy-src="https://www.youtube-nocookie.com/embed/HWg75OAmJLc?start=187" allowfullscreen></iframe></div></div><p>Apple has anticipated this, and when <a href="https://www.tomsguide.com/phones/iphones/interview-apple-ceo-john-ternus-on-his-defining-moment-for-the-iphone-duo">we spoke to John Ternus</a>, the new Apple CEO, and Greg Joswiak, Apple's senior vice president of worldwide marketing, they revealed their approach to Recap's privacy at length.</p><p>"Whenever we do anything, we always do it with an eye towards privacy and security," Ternus said. "It's something we take very seriously and approach very thoughtfully. </p><p>On the subject of Siri Recap, Ternus pointed out that it's been possible to record audio and create transcripts of what people have said for a while — both on smartwatches and phones. </p><p>Ternus makes it clear that recap does not produce a recording or a transcript, with Jozwiak adding that Apple can't access what doesn't exist. "If we don't have a recording, it means no one else has the recording. It can't get hacked. It can't get delivered to somebody."</p><p>It sounds unrealistic, but Jozwiak does confirm that Apple had to develop a whole new chip to make Recap possible in this manner. In the process, he sees it as a feature that allows people to concentrate on what they're doing, while being able to generate "higher level notes" that aren't indiscriminately documenting whatever sensitive information is being said.</p><p>"We wanted to do this in a way that people feel comfortable using it, said Ternus. "And people around the user feel comfortable about its existence."</p><h2 id="siri-recap-39-s-privacy-features">Siri Recap's privacy features</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width: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.jpg" mos="" align="middle" fullscreen="" width="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 also <a href="https://support.apple.com/en-us/148354" target="_blank" rel="nofollow">posted a sizable explainer</a> discussing all the different privacy features Recap incorporates.</p><p>The big privacy feature here is that any audio that the Watch hears is sent to Apple's Secure Enclave on the watch itself or your paired iPhone. Apple claims that it can't be accessed by the user, Apple, apps or even the operating system itself. </p><p>The audio also isn't recorded or stored, though the processed data is summarized and formatted by <a href="https://www.tomsguide.com/ai/apple-intelligence/apple-will-pay-up-to-usd1-million-to-anyone-who-finds-a-privacy-flaw-inside-apple-intelligence">Apple's Private Cloud Compute</a>. Apparently this involves condensed versions of the original conversation that are less than half their length, reducing the contents to the core, rather than a full-length transcript.</p><p>While the Private Cloud Compute data is not accessible by Apple or anyone else, it does still mean your data is being processed on the cloud rather than just on your device. Which may be too risky for some of you to agree with.</p><div><blockquote><p>While the Private Cloud Compute data is not accessible by Apple or anyone else, it does still mean your data is being processed on the cloud rather than just on your device.</p></blockquote></div><p>Other features include a lack of speaker attribution, which means nobody will be directly quoted or attributed to. Siri is also going to censor what it hears, and will automatically omit anything it deems harmful or sensitive. Apple says this includes language promoting self-harm, hate speech, financial data, authentication and personally identifying data and "government-assigned identifiers." So it won't be making a record of your social security number.</p><p>Summaries are automatically deleted after seven days unless you save them to the Siri app. Like all Siri data, those saved summaries can then be deleted from all synced devices at any time — though you can also export them to other apps, including Apple Notes. Syncing is also encrypted and done via iCloud, meaning only your own trusted devices can access those summaries.</p><p>Recaps aren't running all the time, and you do need to opt in to actually set them up. How they record depends on you, with Apple promising you can set up a schedule or manually toggle it on and off in the Control Center. </p><p>Because it's an AI feature, Apple has the usual caveat explaining that the summaries aren't going to be 100% accurate all the time. That doesn't fill me with a whole lot of confidence, especially after the <a href="https://www.tomsguide.com/ai/apple-intelligence/apple-scraps-apple-intelligence-news-feature-after-misinformation-complaints-what-you-need-to-know">fiasco with Apple News summaries</a> that had to be recalled from iOS.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-X75rDW"></div>                            </div>                            <script src="https://kwizly.com/embed/X75rDW.js" async></script><h2 id="live-rewind">Live Rewind</h2><p>If you've ever been pulled in two directions at once, you've inevitably had to ask "what did you just say?" to someone. Live Rewind is meant to help jog your short-short-term memory, by displaying a text snippet of the last 15 seconds of conversation when you double-press the Digital Crown on your Apple Watch.</p><p>To address privacy concerns around this feature, Apple says that these text snippets "disappear permanently from your Apple Watch approximately 30 seconds after the Apple Watch display dims," unless you purposely save them. </p><h2 id="this-doesn-39-t-fix-everything">This doesn't fix everything</h2><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.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 suggests that people "be mindful" of everyone around them, especially if there are sensitive conversations happening. Though that may be giving people too much credit. </p><p>There are plenty of people out there that are considerate of other people's thoughts and opinions, but there are also plenty who aren't. They either forget recap is running, or straight up do not care that other people may not like it.</p><p>Admittedly, both Ternus and Jozwiak have a point: there are features that offer this sort of thing without <em>any</em> emphasis on privacy. Then again, it is more likely that people take issue with the implied always-listening approach Recap takes. I personally feel it would make a lot more sense to restrict it to manual control.</p><p>Whichever way you look at it, though, I guess it's still a better option than seeing people pull out their phones to video every little unusual thing they come across.</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/best-picks/best-apple-watch">We've tested every Apple Watch and these are the 3 models I recommend right now</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-vs-apple-watch-ultra-4-which-new-apple-watch-should-you-buy">Apple Watch Series 12 vs Apple Watch Ultra 4: Which new Apple Watch should you buy?</a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/all-the-new-audio-features-on-apple-watch-explained">All the new audio features on Apple Watch explained</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Don't have iPhone Duo money? These are the best Apple deals to upgrade your tech on a budget ]]></title>
                                                                                                <dc:content><![CDATA[ <p>We've just seen a host of <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">new Apple products announced</a>, from the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo</a> to the <a href="https://www.tomsguide.com/audio/airpods/apple-airpods-5-officially-announced-here-are-the-upgrades">AirPods 5</a>. But new Apple tech can get seriously expensive, so I'm mostly interested in scooping up savings on previous models — where you can score some huge discounts.</p><p>Right now, you can <a href="https://www.amazon.com/stores/Apple/page/77D9E1F7-0337-4282-9DB6-B6B8FB2DC98D?" target="_blank" rel="nofollow">shop deals on AirPods, iPads, MacBooks, accessories and more</a>. One of the most useful deals for Apple fans is definitely the <a href="https://www.amazon.com/Apple-AirTag-2nd-Generation-Precision/dp/B0GJTXVN9Z" target="_blank" rel="nofollow">AirTag 2nd Gen (4-Pack) on sale for $79</a>. This is the lowest price ever for this bundle, and these keyfinders are extremely handy for keeping tabs on your important items using the Find My app on your iPhone.</p><p>Meanwhile, if you do want the newest iPhones, you can get the <a href="https://tmobilepostpaid.pxf.io/c/1943169/3726747/38171?subId1=hawk-custom-tracking" target="_blank" rel="nofollow">iPhone 18 for free when you trade-in and opt for an unlimited plan at T-Mobile</a>.</p><p>There are lots more deals up for grabs, so keep scrolling to see my favorites.</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/Apple/page/77D9E1F7-0337-4282-9DB6-B6B8FB2DC98D?" target="_blank" rel="nofollow"><strong>shop all Apple deals on Amazon</strong></a><strong>   </strong></li><li><strong>Apple EarPods (Lightning): </strong><a href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow"><strong>was $19 now $14</strong></a></li><li><strong>Apple AirTag: </strong><a href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow"><strong>was $29 now $24</strong></a></li><li><strong>AirPods Max 2: </strong><a href="https://www.amazon.com/dp/B0GSS72GZJ" target="_blank" rel="nofollow"><strong>was $549 now $449</strong></a></li><li><strong>MacBook Neo: </strong><a href="https://www.amazon.com/dp/B0GR6BVYS5" target="_blank" rel="nofollow"><strong>was $699 now $679</strong></a></li><li><strong>15" MacBook Air (M5): </strong><a href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" target="_blank" rel="nofollow"><strong>was $1,499 now $1,399</strong></a></li><li><strong>iPhone 18 Pro: </strong><a href="https://tmobilepostpaid.pxf.io/c/1943169/3726747/38171?subId1=hawk-custom-tracking" target="_blank" rel="nofollow"><strong>free w/ trade-in + unlimited</strong></a></li></ul><h3 class="article-body__section" id="section-iphone"><span>iPhone</span></h3><div class="product"><a data-dimension112="2c072aee-add6-11f1-938f-d1b911d32d33" data-action="Deal Block" data-label="iPhone 18 Pro: free w/ trade-in + unlimited @ T-Mobile" data-dimension48="iPhone 18 Pro: free w/ trade-in + unlimited @ T-Mobile" href="https://tmobilepostpaid.pxf.io/c/1943169/3726747/38171?subId1=hawk-custom-tracking" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:600px;"><p class="vanilla-image-block" style="padding-top:50.00%;"><img id="Y26QJd7Ff7aeQmTHuW8nCP" name="NEW T-Mobile Logo" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Y26QJd7Ff7aeQmTHuW8nCP.png" mos="" align="middle" fullscreen="" width="600" height="300" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>iPhone 18 Pro: </strong><a href="https://tmobilepostpaid.pxf.io/c/1943169/3726747/38171?subId1=hawk-custom-tracking" target="_blank" rel="nofollow" data-dimension112="2c072aee-add6-11f1-938f-d1b911d32d33" data-action="Deal Block" data-label="iPhone 18 Pro: free w/ trade-in + unlimited @ T-Mobile" data-dimension48="iPhone 18 Pro: free w/ trade-in + unlimited @ T-Mobile" data-dimension25=""><strong>free w/ trade-in + unlimited @ T-Mobile</strong></a><br>T-Mobile is offering the iPhone 18 Pro for free when you switch and bring your number or when you trade-in an eligible phone and sign up for T-Mobile's Experience Beyond plan. The iPhone 18 Pro features a 6.3-inch OLED 120Hz display (2622 x 1206), A20 Pro chipset, and 256GB of storage. You also get a 48MP main, 48MP ultrawide, and 48MP telephoto lens w/ 4x zoom. The front camera is 18MP. <a class="view-deal button" href="https://tmobilepostpaid.pxf.io/c/1943169/3726747/38171?subId1=hawk-custom-tracking" target="_blank" rel="nofollow" data-dimension112="2c072aee-add6-11f1-938f-d1b911d32d33" data-action="Deal Block" data-label="iPhone 18 Pro: free w/ trade-in + unlimited @ T-Mobile" data-dimension48="iPhone 18 Pro: free w/ trade-in + unlimited @ T-Mobile" data-dimension25="">View Deal</a></p></div><div class="product"><a data-dimension112="2c072b52-add6-11f1-8d0d-937dcaffa153" data-action="Deal Block" data-label="iPhone 18 Pro Max: free w/ trade-in + unlimited @ Xfinity Mobile" data-dimension48="iPhone 18 Pro Max: free w/ trade-in + unlimited @ Xfinity Mobile" href="https://www.xfinity.com/learn/mobile" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1413px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="MEg942YDCTSzn9H3vsaqPj" name="xfinity-mobile.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/MEg942YDCTSzn9H3vsaqPj.jpg" mos="" align="middle" fullscreen="" width="1413" height="1413" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>iPhone 18 Pro Max: </strong><a href="https://www.xfinity.com/learn/mobile" target="_blank" rel="nofollow" data-dimension112="2c072b52-add6-11f1-8d0d-937dcaffa153" data-action="Deal Block" data-label="iPhone 18 Pro Max: free w/ trade-in + unlimited @ Xfinity Mobile" data-dimension48="iPhone 18 Pro Max: free w/ trade-in + unlimited @ Xfinity Mobile" data-dimension25=""><strong>free w/ trade-in + unlimited @ Xfinity Mobile</strong></a><br>New and existing Xfinity Mobile customers can get the iPhone 18 Pro Max for free with a Mobile Plus plan and trade-in. New customers must activate a new Xfinity Mobile line within 30 days of purchase, whereas existing customers can upgrade one of their existing lines to receive the deal. <a class="view-deal button" href="https://www.xfinity.com/learn/mobile" target="_blank" rel="nofollow" data-dimension112="2c072b52-add6-11f1-8d0d-937dcaffa153" data-action="Deal Block" data-label="iPhone 18 Pro Max: free w/ trade-in + unlimited @ Xfinity Mobile" data-dimension48="iPhone 18 Pro Max: free w/ trade-in + unlimited @ Xfinity Mobile" data-dimension25="">View Deal</a></p></div><h3 class="article-body__section" id="section-accessories"><span>Accessories</span></h3><div class="product"><a data-dimension112="2c072c10-add6-11f1-8192-615a79dc6810" data-action="Deal Block" data-label="EarPods (Lightning)" data-dimension48="EarPods (Lightning)" data-dimension25="$14" href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1040px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Ys3T2v7S48cnc2sK2hLS9U" name="apple earpods with lightning connector.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Ys3T2v7S48cnc2sK2hLS9U.jpg" mos="" align="middle" fullscreen="" width="1040" height="1040" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow" data-dimension112="2c072c10-add6-11f1-8192-615a79dc6810" data-action="Deal Block" data-label="EarPods (Lightning)" data-dimension48="EarPods (Lightning)" data-dimension25="$14">EarPods (Lightning): was $19 now $14</a></strong><br>If you like listening to your music the old-fashioned way, this pair of wired EarPods has a Lightning connector, allowing them to be used with older Apple devices. For this price, you might as well grab a pair!<a class="view-deal button" href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow" data-dimension112="2c072c10-add6-11f1-8192-615a79dc6810" data-action="Deal Block" data-label="EarPods (Lightning)" data-dimension48="EarPods (Lightning)" data-dimension25="$14">View Deal</a></p></div><div class="product"><a data-dimension112="2c072c6a-add6-11f1-b75e-5141d26254c9" data-action="Deal Block" data-label="20W USB-C Compact Power Adapter" data-dimension48="20W USB-C Compact Power Adapter" data-dimension25="$14" href="https://www.amazon.com/Apple-20W-USB-C-Power-Adapter/dp/B0DJFW7PNM" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:649px;"><p class="vanilla-image-block" style="padding-top:149.61%;"><img id="mhEQ7c2rj34AhoPSdBToNX" name="20W USB-C Compact Power Adapter" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mhEQ7c2rj34AhoPSdBToNX.jpg" mos="" align="middle" fullscreen="" width="649" height="971" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-20W-USB-C-Power-Adapter/dp/B0DJFW7PNM" target="_blank" rel="nofollow" data-dimension112="2c072c6a-add6-11f1-b75e-5141d26254c9" data-action="Deal Block" data-label="20W USB-C Compact Power Adapter" data-dimension48="20W USB-C Compact Power Adapter" data-dimension25="$14">20W USB-C Compact Power Adapter: was $19 now $14</a></strong><br>This is one of those essentials everyone needs, so you might as well buy one while it's on sale. It offers 20W fast charging for iPhone 8 and up.<a class="view-deal button" href="https://www.amazon.com/Apple-20W-USB-C-Power-Adapter/dp/B0DJFW7PNM" target="_blank" rel="nofollow" data-dimension112="2c072c6a-add6-11f1-b75e-5141d26254c9" data-action="Deal Block" data-label="20W USB-C Compact Power Adapter" data-dimension48="20W USB-C Compact Power Adapter" data-dimension25="$14">View Deal</a></p></div><div class="product"><a data-dimension112="2c072d14-add6-11f1-86d1-4149fd7a0d83" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$24" href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:600px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="EzmCNB37HYZTKq3XSMqvTY" name="Apple AirTag 2 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/EzmCNB37HYZTKq3XSMqvTY.jpg" mos="" align="middle" fullscreen="" width="600" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow" data-dimension112="2c072d14-add6-11f1-86d1-4149fd7a0d83" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$24">AirTag (2nd Gen): was $29 now $24</a></strong><br>Apple's second generation AirTag offers better range, precision finding, a louder speaking and a bunch of extra improvements to help you track your lost keys and bags.<a class="view-deal button" href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow" data-dimension112="2c072d14-add6-11f1-86d1-4149fd7a0d83" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$24">View Deal</a></p></div><div class="product"><a data-dimension112="2c072d78-add6-11f1-8979-95e17ba4f48e" data-action="Deal Block" data-label="240W USB-C to USB-C Woven Charge Cable (2 m)" data-dimension48="240W USB-C to USB-C Woven Charge Cable (2 m)" data-dimension25="$24" href="https://www.amazon.com/Apple-USB-C-Woven-Charge-Cable/dp/B0DCH5B2HF" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:71.07%;"><img id="H37kKia68mrqHSBwHDsVRJ" name="240W USB-C to USB-C Woven Charge Cable (2 m)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/H37kKia68mrqHSBwHDsVRJ.jpg" mos="" align="middle" fullscreen="" width="1500" height="1066" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-USB-C-Woven-Charge-Cable/dp/B0DCH5B2HF" target="_blank" rel="nofollow" data-dimension112="2c072d78-add6-11f1-8979-95e17ba4f48e" data-action="Deal Block" data-label="240W USB-C to USB-C Woven Charge Cable (2 m)" data-dimension48="240W USB-C to USB-C Woven Charge Cable (2 m)" data-dimension25="$24">240W USB-C to USB-C Woven Charge Cable (2 m): was $29 now $24</a></strong><br>Another essential you don't want to go without. I have mostly USB-A to USB-C cables, so I definitely need to grab one of these for when a USB-A charging port isn't available — plus it's $5 off.<a class="view-deal button" href="https://www.amazon.com/Apple-USB-C-Woven-Charge-Cable/dp/B0DCH5B2HF" target="_blank" rel="nofollow" data-dimension112="2c072d78-add6-11f1-8979-95e17ba4f48e" data-action="Deal Block" data-label="240W USB-C to USB-C Woven Charge Cable (2 m)" data-dimension48="240W USB-C to USB-C Woven Charge Cable (2 m)" data-dimension25="$24">View Deal</a></p></div><div class="product"><a data-dimension112="2c072dd2-add6-11f1-a03b-2ffcd05ce3db" data-action="Deal Block" data-label="Pencil (USB-C)" data-dimension48="Pencil (USB-C)" data-dimension25="$69" href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="LCuHYQPiVnordwa3UuoKE6" name="1721134277.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LCuHYQPiVnordwa3UuoKE6.jpg" mos="" align="middle" fullscreen="" width="500" height="500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow" data-dimension112="2c072dd2-add6-11f1-a03b-2ffcd05ce3db" data-action="Deal Block" data-label="Pencil (USB-C)" data-dimension48="Pencil (USB-C)" data-dimension25="$69">Pencil (USB-C): was $79 now $69</a></strong><br>If you want a cheaper stylus that covers the basics, than the Apple Pencil USB-C is the one for you. With pixel-perfect precision, low-latency and magnets to attach to your tablet, this is the no-frills approach to writing ad drawing on your tablet.<a class="view-deal button" href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow" data-dimension112="2c072dd2-add6-11f1-a03b-2ffcd05ce3db" data-action="Deal Block" data-label="Pencil (USB-C)" data-dimension48="Pencil (USB-C)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="2c072e2c-add6-11f1-aba7-83eea5ba66eb" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$79" href="https://www.amazon.com/Apple-AirTag-2nd-Generation-Precision/dp/B0GJTXVN9Z" 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:133.33%;"><img id="HCUqWkUuUEZJCvXyEu4wwk" name="Apple - AirTag 4 pack (2nd generation) - 2026 - White" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/HCUqWkUuUEZJCvXyEu4wwk.jpg" mos="" align="middle" fullscreen="" width="900" height="1200" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Score a four-pack of Apple AirTag (2nd Gen) keyfinders with a discount. If you have a lot of stuff you need to keep track of, this deal is one of the best ways to do it! Apple's second generation AirTag offers better range, precision finding, a louder speaking and a bunch of extra improvements to help you track your lost keys and bags.<a class="view-deal button" href="https://www.amazon.com/Apple-AirTag-2nd-Generation-Precision/dp/B0GJTXVN9Z" target="_blank" rel="nofollow" data-dimension112="2c072e2c-add6-11f1-aba7-83eea5ba66eb" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$79">View Deal</a></p></div><h3 class="article-body__section" id="section-airpods"><span>AirPods</span></h3><div class="product"><a data-dimension112="2c072eea-add6-11f1-955d-099a1e1fde3f" data-action="Deal Block" data-label="AirPods 4 w/ ANC" data-dimension48="AirPods 4 w/ ANC" data-dimension25="$148" href="https://www.amazon.com/Apple-Headphones-Cancellation-Transparency-Personalized/dp/B0DGJ7HYG1" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:93.08%;"><img id="iW6XqU9SoqpTBgf9epawof" name="Apple AirPods 4 deal block.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iW6XqU9SoqpTBgf9epawof.jpg" mos="" align="middle" fullscreen="" width="679" height="632" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-Headphones-Cancellation-Transparency-Personalized/dp/B0DGJ7HYG1" target="_blank" rel="nofollow" data-dimension112="2c072eea-add6-11f1-955d-099a1e1fde3f" data-action="Deal Block" data-label="AirPods 4 w/ ANC" data-dimension48="AirPods 4 w/ ANC" data-dimension25="$148">AirPods 4 w/ ANC: was $179 now $148</a></strong><br>These AirPods 4 have all the same great features as the base AirPods 4, except they also include Active Noise Cancellation. They also feature Adaptive Audio, Transparency mode, and Voice Isolation. It's a modest, but welcome price cut.<a class="view-deal button" href="https://www.amazon.com/Apple-Headphones-Cancellation-Transparency-Personalized/dp/B0DGJ7HYG1" target="_blank" rel="nofollow" data-dimension112="2c072eea-add6-11f1-955d-099a1e1fde3f" data-action="Deal Block" data-label="AirPods 4 w/ ANC" data-dimension48="AirPods 4 w/ ANC" data-dimension25="$148">View Deal</a></p></div><div class="product"><a data-dimension112="2c072f44-add6-11f1-84a6-37d10cfe2338" data-action="Deal Block" data-label="AirPods Pro 3" data-dimension48="AirPods Pro 3" data-dimension25="$199" href="https://www.amazon.com/Apple-Cancellation-Translation-Headphones-High-Fidelity/dp/B0FQFB8FMG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:842px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="FYzcjQSdtuwidVacXmMNL5" name="AirPods Pro 3.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FYzcjQSdtuwidVacXmMNL5.jpg" mos="" align="middle" fullscreen="" width="842" height="842" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The AirPods Pro 3 bring the heat with 10 hours of battery life, improved sound, and superior active noise canceling. In our <a href="https://www.tomsguide.com/audio/airpods/apple-airpods-pro-3-review" data-dimension112="2c072f44-add6-11f1-84a6-37d10cfe2338" data-action="Deal Block" data-label="AirPods Pro 3" data-dimension48="AirPods Pro 3" data-dimension25="$199">AirPods Pro 3 review</a> we said the Editor's Choice buds deliver the upgrade iPhone users have been waiting for with improved battery life, stronger noise cancellation, and smart new features like Live Translation, which delivers real-time translations to your ears. <a class="view-deal button" href="https://www.amazon.com/Apple-Cancellation-Translation-Headphones-High-Fidelity/dp/B0FQFB8FMG" target="_blank" rel="nofollow" data-dimension112="2c072f44-add6-11f1-84a6-37d10cfe2338" data-action="Deal Block" data-label="AirPods Pro 3" data-dimension48="AirPods Pro 3" data-dimension25="$199">View Deal</a></p></div><div class="product"><a data-dimension112="2c072f9e-add6-11f1-92e3-1f6c568cc27d" data-action="Deal Block" data-label="AirPods Max 2" data-dimension48="AirPods Max 2" data-dimension25="$449" href="https://www.amazon.com/dp/B0GSS72GZJ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="TSi2XMUrFhYn5nqrGBsd59" name="airpods max 2 deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/TSi2XMUrFhYn5nqrGBsd59.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>These are some of the best headphones we've ever used. With seamless Apple ecosystem integration, well-balanced sound, and excellent comfort, the AirPods Max 2 will make you want to listen to music. You have to try them to believe them and at this price, it's almost a steal.<a class="view-deal button" href="https://www.amazon.com/dp/B0GSS72GZJ" target="_blank" rel="nofollow" data-dimension112="2c072f9e-add6-11f1-92e3-1f6c568cc27d" data-action="Deal Block" data-label="AirPods Max 2" data-dimension48="AirPods Max 2" data-dimension25="$449">View Deal</a></p></div><h3 class="article-body__section" id="section-apple-watch"><span>Apple Watch</span></h3><div class="product"><a data-dimension112="2c073066-add6-11f1-bade-a1125d0c5086" data-action="Deal Block" data-label="Watch 11 (GPS/46mm)" data-dimension48="Watch 11 (GPS/46mm)" data-dimension25="$329" href="https://www.amazon.com/Apple-Watch-Smartwatch-Aluminum-Always/dp/B0FQFHVKZ4" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1270px;"><p class="vanilla-image-block" style="padding-top:118.11%;"><img id="GuyP4rEgTW2kHmRSjGeHCG" name="Apple Watch 11 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GuyP4rEgTW2kHmRSjGeHCG.jpg" mos="" align="middle" fullscreen="" width="1270" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-Watch-Smartwatch-Aluminum-Always/dp/B0FQFHVKZ4" target="_blank" rel="nofollow" data-dimension112="2c073066-add6-11f1-bade-a1125d0c5086" data-action="Deal Block" data-label="Watch 11 (GPS/46mm)" data-dimension48="Watch 11 (GPS/46mm)" data-dimension25="$329">Watch 11 (GPS/46mm): was $429 now $329</a></strong><br>Need a bigger screen? The larger 46mm model of the Apple Watch 11 is on sale for $329 — that's $100 off. Otherwise, it has all of the same great features as the smaller 42mm model, including amazing battery life that lasts up to 24 hours (up to 38 hours in low power mode.) And it's $120 cheaper than the new 46mm Apple Watch 12.<a class="view-deal button" href="https://www.amazon.com/Apple-Watch-Smartwatch-Aluminum-Always/dp/B0FQFHVKZ4" target="_blank" rel="nofollow" data-dimension112="2c073066-add6-11f1-bade-a1125d0c5086" data-action="Deal Block" data-label="Watch 11 (GPS/46mm)" data-dimension48="Watch 11 (GPS/46mm)" data-dimension25="$329">View Deal</a></p></div><h3 class="article-body__section" id="section-ipads"><span>iPads</span></h3><div class="product"><a data-dimension112="2c07311a-add6-11f1-8240-15d9275a7b0e" data-action="Deal Block" data-label="iPad mini 7" data-dimension48="iPad mini 7" data-dimension25="$569" href="https://www.amazon.com/dp/B0DK3W4YHS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1203px;"><p class="vanilla-image-block" style="padding-top:124.69%;"><img id="G2PjHEjHsRfuddfWSzPBjd" name="iPad mini 2024 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/G2PjHEjHsRfuddfWSzPBjd.jpg" mos="" align="middle" fullscreen="" width="1203" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The iPad mini is getting a discount, and any price cut to this small tablet is welcome. We're big fans of its incredibly portable design and long battery life (it lasted 10 hours in our battery life tests.) It comes with speedy performance thanks to Apple's A17 Pro chip, and has a gorgeous 8.3-inch (2,266 x 1,488) Liquid Retina display. You also get 12MP cameras on the front and back and Wi-Fi 6e support. In our <a href="https://www.tomsguide.com/tablets/ipads/ipad-mini-7-review" data-dimension112="2c07311a-add6-11f1-8240-15d9275a7b0e" data-action="Deal Block" data-label="iPad mini 7" data-dimension48="iPad mini 7" data-dimension25="$569">iPad mini 7 review</a>, we said it delivers the full iPad experience in a tiny size. <a class="view-deal button" href="https://www.amazon.com/dp/B0DK3W4YHS" target="_blank" rel="nofollow" data-dimension112="2c07311a-add6-11f1-8240-15d9275a7b0e" data-action="Deal Block" data-label="iPad mini 7" data-dimension48="iPad mini 7" data-dimension25="$569">View Deal</a></p></div><div class="product"><a data-dimension112="2c073174-add6-11f1-829f-5f28787d7d43" data-action="Deal Block" data-label="11" iPad Air (WiFi/128GB)" data-dimension48="11" iPad Air (WiFi/128GB)" data-dimension25="$712" href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQVBJT4J" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1325px;"><p class="vanilla-image-block" style="padding-top:113.21%;"><img id="NVZkwX7FuVd3CYdiYHdsgm" name="iPad Air 11 2024 deal block.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/NVZkwX7FuVd3CYdiYHdsgm.jpg" mos="" align="middle" fullscreen="" width="1325" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQVBJT4J" target="_blank" rel="nofollow" data-dimension112="2c073174-add6-11f1-829f-5f28787d7d43" data-action="Deal Block" data-label='11" iPad Air (WiFi/128GB)' data-dimension48='11" iPad Air (WiFi/128GB)' data-dimension25="$712">11" iPad Air (WiFi/128GB): was $749 now $712</a></strong><br>The 2026 iPad Air packs Apple's M4 processor, which Apple states is up to 30 percent faster than iPad Air with M3. It also has an 11-inch LED (2360 x 1640) display, 128GB of storage, 12MP rear camera, and 12MP front camera. The tablet now supports Wi-Fi 7 a well as Bluetooth 6 and Thread. In our <a href="https://www.tomsguide.com/computing/ipads/apple-ipad-air-m4-review-small-tweaks-to-the-gold-standard">iPad Air M4 review</a>, we said the upgrades are modest, but the iPad Air remains the best tablet out there. <a class="view-deal button" href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQVBJT4J" target="_blank" rel="nofollow" data-dimension112="2c073174-add6-11f1-829f-5f28787d7d43" data-action="Deal Block" data-label="11" iPad Air (WiFi/128GB)" data-dimension48="11" iPad Air (WiFi/128GB)" data-dimension25="$712">View Deal</a></p></div><h3 class="article-body__section" id="section-macbooks"><span>MacBooks</span></h3><div class="product"><a data-dimension112="2c073232-add6-11f1-964c-51f770bc2e45" data-action="Deal Block" data-label="MacBook Neo" data-dimension48="MacBook Neo" data-dimension25="$679" href="https://www.amazon.com/dp/B0GR6BVYS5" 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:61.07%;"><img id="Lg4Dvg68j9SbB5CPNrTEpH" name="MacBook Neo deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg" mos="" align="middle" fullscreen="" width="1500" height="916" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The MacBook Neo sports a 13-inch Liquid Retina (2408 x 1506) display, A18 Pro chipset, 8GB of RAM, 256GB SSD, and 1080p FaceTime HD camera. The 2.7-lb. laptop is available in Indigo, Blush, Citrus, and Silver. In our <a href="https://www.tomsguide.com/computing/macbooks/apple-macbook-neo-review" data-dimension112="2c073232-add6-11f1-964c-51f770bc2e45" data-action="Deal Block" data-label="MacBook Neo" data-dimension48="MacBook Neo" data-dimension25="$679">MacBook Neo review</a>, we said no other laptop comes close to the Neo in terms of bang for your buck — even with its new/higher $699 price tag. <a class="view-deal button" href="https://www.amazon.com/dp/B0GR6BVYS5" target="_blank" rel="nofollow" data-dimension112="2c073232-add6-11f1-964c-51f770bc2e45" data-action="Deal Block" data-label="MacBook Neo" data-dimension48="MacBook Neo" data-dimension25="$679">View Deal</a></p></div><div class="product"><a data-dimension112="2c07328c-add6-11f1-9027-ef0e3b0387c2" data-action="Deal Block" data-label="15" MacBook Air (M5)" data-dimension48="15" MacBook Air (M5)" data-dimension25="$1399" href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" 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:60.73%;"><img id="R5hxVnj9RteJKiej8tQbLH" name="MacBook Air M5 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/R5hxVnj9RteJKiej8tQbLH.jpg" mos="" align="middle" fullscreen="" width="1500" height="911" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" target="_blank" rel="nofollow" data-dimension112="2c07328c-add6-11f1-9027-ef0e3b0387c2" data-action="Deal Block" data-label='15" MacBook Air (M5)' data-dimension48='15" MacBook Air (M5)' data-dimension25="$1399">15" MacBook Air (M5): was $1499 now $1399</a></strong><br>Right now you can get the 15-inch MacBook Air M5 for $100 off. This laptop features a 15.3-inch (2880 x 1864) display, Apple M5 chipset, 16GB of RAM, 512GB SSD, and support for WiFi 7 and Bluetooth 6. <br><strong>Price check: </strong><a href="https://www.bestbuy.com/product/apple-macbook-air-15-inch-laptop-m5-chip-with-10-core-cpu-and-10-core-gpu-16gb-memory-512gb-ssd-midnight/JJGCQLKQL9/sku/6571043" target="_blank" rel="nofollow"><strong>$1,399 @ Best Buy</strong></a><strong></strong><a class="view-deal button" href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" target="_blank" rel="nofollow" data-dimension112="2c07328c-add6-11f1-9027-ef0e3b0387c2" data-action="Deal Block" data-label="15" MacBook Air (M5)" data-dimension48="15" MacBook Air (M5)" data-dimension25="$1399">View Deal</a></p></div><div class="product"><a data-dimension112="2c0732e6-add6-11f1-b7b8-8372e9e09d42" data-action="Deal Block" data-label="MacBook Pro 14" (M5/1TB)" data-dimension48="MacBook Pro 14" (M5/1TB)" data-dimension25="$1849" href="https://www.amazon.com/dp/B0FWD8WBSW" 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:60.53%;"><img id="GnpQTG2JTWSenJyfrWydnm" name="MacBook Pro M5 deals" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GnpQTG2JTWSenJyfrWydnm.jpg" mos="" align="middle" fullscreen="" width="1500" height="908" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0FWD8WBSW" target="_blank" rel="nofollow" data-dimension112="2c0732e6-add6-11f1-b7b8-8372e9e09d42" data-action="Deal Block" data-label='MacBook Pro 14" (M5/1TB)' data-dimension48='MacBook Pro 14" (M5/1TB)' data-dimension25="$1849">MacBook Pro 14" (M5/1TB): was $1999 now $1849</a></strong><br>This MacBook Pro features Apple's M5 chipset, with a 10-core CPU and 10-core GPU. It's designed to deliver a huge boost in AI and graphics performance for everyone from students to creatives. In our <a href="https://www.tomsguide.com/computing/macbooks/macbook-pro-m5-review">MacBook Pro M5 review</a> we said the Editor's Choice machine is a fantastic option for power users who demand a powerful and portable notebook with epic (18 hour) battery life. The base model features a 14.2-inch 3024 x 1964 Retina display, Apple M5 CPU, 16GB of RAM and a 512GB SSD.<a class="view-deal button" href="https://www.amazon.com/dp/B0FWD8WBSW" target="_blank" rel="nofollow" data-dimension112="2c0732e6-add6-11f1-b7b8-8372e9e09d42" data-action="Deal Block" data-label="MacBook Pro 14" (M5/1TB)" data-dimension48="MacBook Pro 14" (M5/1TB)" data-dimension25="$1849">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=school&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/sales-events/dont-have-iphone-duo-money-these-are-the-best-apple-deals-to-upgrade-your-tech-on-a-budget</link>
                                                                            <description>
                            <![CDATA[ A bunch of new Apple tech has just been announced — but you can save a ton by going for the older models. Check out the best deals on Apple tech to upgrade your setup for less. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">usL3g4FNLY6rxB34diPcq9</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/6PKQ4RNqoFP6HzG2g4RGAc-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 11 Sep 2026 12:12:28 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Sales Events]]></category>
                                                                                                <author><![CDATA[ millie.daviswilliams@futurenet.com (Millie Davis-Williams) ]]></author>                    <dc:creator><![CDATA[ Millie Davis-Williams ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/WU6pa7hKuxs5ScCoqcXYWA.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Millie is a Deals Editor at Tom&#039;s Guide specializing in tech deals content. Based in London, Millie has spent a lifetime stubbornly refusing to pay full price on any possible purchase. She has years of searching for the best discounts on the latest and greatest phones, TVs and gadgets under her belt, and knows how to sort the best deals from the rest. Helping readers save on the products they want is her mission, whether it’s an Apple Watch or a new tablet.&lt;/p&gt;&lt;p&gt;Since working at Tom’s Guide, Millie has covered retail events like Prime Day, Black Friday and Cyber Monday extensively, meaning she knows the products readers are looking for and the best times of year to hit “purchase.”&lt;/p&gt;&lt;p&gt;When she’s not looking for discounts, Millie covers news and writes how-to articles about everything from phones, streaming devices, and headphones to apps and video games.&lt;/p&gt;&lt;p&gt;In her spare time, Millie enjoys reading, gaming on her Nintendo Switch and creating digital art. She’s also a fan of watching Disney movies and collecting plush (the latter having totally taken over her bedroom.)&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/6PKQ4RNqoFP6HzG2g4RGAc-1280-80.jpg">
                                                            <media:credit><![CDATA[Amazon / edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple deals]]></media:description>                                                            <media:text><![CDATA[Apple deals]]></media:text>
                                <media:title type="plain"><![CDATA[Apple deals]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/6PKQ4RNqoFP6HzG2g4RGAc-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>We've just seen a host of <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">new Apple products announced</a>, from the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo</a> to the <a href="https://www.tomsguide.com/audio/airpods/apple-airpods-5-officially-announced-here-are-the-upgrades">AirPods 5</a>. But new Apple tech can get seriously expensive, so I'm mostly interested in scooping up savings on previous models — where you can score some huge discounts.</p><p>Right now, you can <a href="https://www.amazon.com/stores/Apple/page/77D9E1F7-0337-4282-9DB6-B6B8FB2DC98D?" target="_blank" rel="nofollow">shop deals on AirPods, iPads, MacBooks, accessories and more</a>. One of the most useful deals for Apple fans is definitely the <a href="https://www.amazon.com/Apple-AirTag-2nd-Generation-Precision/dp/B0GJTXVN9Z" target="_blank" rel="nofollow">AirTag 2nd Gen (4-Pack) on sale for $79</a>. This is the lowest price ever for this bundle, and these keyfinders are extremely handy for keeping tabs on your important items using the Find My app on your iPhone.</p><p>Meanwhile, if you do want the newest iPhones, you can get the <a href="https://tmobilepostpaid.pxf.io/c/1943169/3726747/38171?subId1=hawk-custom-tracking" target="_blank" rel="nofollow">iPhone 18 for free when you trade-in and opt for an unlimited plan at T-Mobile</a>.</p><p>There are lots more deals up for grabs, so keep scrolling to see my favorites.</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/Apple/page/77D9E1F7-0337-4282-9DB6-B6B8FB2DC98D?" target="_blank" rel="nofollow"><strong>shop all Apple deals on Amazon</strong></a><strong>   </strong></li><li><strong>Apple EarPods (Lightning): </strong><a href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow"><strong>was $19 now $14</strong></a></li><li><strong>Apple AirTag: </strong><a href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow"><strong>was $29 now $24</strong></a></li><li><strong>AirPods Max 2: </strong><a href="https://www.amazon.com/dp/B0GSS72GZJ" target="_blank" rel="nofollow"><strong>was $549 now $449</strong></a></li><li><strong>MacBook Neo: </strong><a href="https://www.amazon.com/dp/B0GR6BVYS5" target="_blank" rel="nofollow"><strong>was $699 now $679</strong></a></li><li><strong>15" MacBook Air (M5): </strong><a href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" target="_blank" rel="nofollow"><strong>was $1,499 now $1,399</strong></a></li><li><strong>iPhone 18 Pro: </strong><a href="https://tmobilepostpaid.pxf.io/c/1943169/3726747/38171?subId1=hawk-custom-tracking" target="_blank" rel="nofollow"><strong>free w/ trade-in + unlimited</strong></a></li></ul><h3 class="article-body__section" id="section-iphone"><span>iPhone</span></h3><div class="product"><a data-dimension112="2c072aee-add6-11f1-938f-d1b911d32d33" data-action="Deal Block" data-label="iPhone 18 Pro: free w/ trade-in + unlimited @ T-Mobile" data-dimension48="iPhone 18 Pro: free w/ trade-in + unlimited @ T-Mobile" href="https://tmobilepostpaid.pxf.io/c/1943169/3726747/38171?subId1=hawk-custom-tracking" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:600px;"><p class="vanilla-image-block" style="padding-top:50.00%;"><img id="Y26QJd7Ff7aeQmTHuW8nCP" name="NEW T-Mobile Logo" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Y26QJd7Ff7aeQmTHuW8nCP.png" mos="" align="middle" fullscreen="" width="600" height="300" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>iPhone 18 Pro: </strong><a href="https://tmobilepostpaid.pxf.io/c/1943169/3726747/38171?subId1=hawk-custom-tracking" target="_blank" rel="nofollow" data-dimension112="2c072aee-add6-11f1-938f-d1b911d32d33" data-action="Deal Block" data-label="iPhone 18 Pro: free w/ trade-in + unlimited @ T-Mobile" data-dimension48="iPhone 18 Pro: free w/ trade-in + unlimited @ T-Mobile" data-dimension25=""><strong>free w/ trade-in + unlimited @ T-Mobile</strong></a><br>T-Mobile is offering the iPhone 18 Pro for free when you switch and bring your number or when you trade-in an eligible phone and sign up for T-Mobile's Experience Beyond plan. The iPhone 18 Pro features a 6.3-inch OLED 120Hz display (2622 x 1206), A20 Pro chipset, and 256GB of storage. You also get a 48MP main, 48MP ultrawide, and 48MP telephoto lens w/ 4x zoom. The front camera is 18MP. <a class="view-deal button" href="https://tmobilepostpaid.pxf.io/c/1943169/3726747/38171?subId1=hawk-custom-tracking" target="_blank" rel="nofollow" data-dimension112="2c072aee-add6-11f1-938f-d1b911d32d33" data-action="Deal Block" data-label="iPhone 18 Pro: free w/ trade-in + unlimited @ T-Mobile" data-dimension48="iPhone 18 Pro: free w/ trade-in + unlimited @ T-Mobile" data-dimension25="">View Deal</a></p></div><div class="product"><a data-dimension112="2c072b52-add6-11f1-8d0d-937dcaffa153" data-action="Deal Block" data-label="iPhone 18 Pro Max: free w/ trade-in + unlimited @ Xfinity Mobile" data-dimension48="iPhone 18 Pro Max: free w/ trade-in + unlimited @ Xfinity Mobile" href="https://www.xfinity.com/learn/mobile" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1413px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="MEg942YDCTSzn9H3vsaqPj" name="xfinity-mobile.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/MEg942YDCTSzn9H3vsaqPj.jpg" mos="" align="middle" fullscreen="" width="1413" height="1413" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong>iPhone 18 Pro Max: </strong><a href="https://www.xfinity.com/learn/mobile" target="_blank" rel="nofollow" data-dimension112="2c072b52-add6-11f1-8d0d-937dcaffa153" data-action="Deal Block" data-label="iPhone 18 Pro Max: free w/ trade-in + unlimited @ Xfinity Mobile" data-dimension48="iPhone 18 Pro Max: free w/ trade-in + unlimited @ Xfinity Mobile" data-dimension25=""><strong>free w/ trade-in + unlimited @ Xfinity Mobile</strong></a><br>New and existing Xfinity Mobile customers can get the iPhone 18 Pro Max for free with a Mobile Plus plan and trade-in. New customers must activate a new Xfinity Mobile line within 30 days of purchase, whereas existing customers can upgrade one of their existing lines to receive the deal. <a class="view-deal button" href="https://www.xfinity.com/learn/mobile" target="_blank" rel="nofollow" data-dimension112="2c072b52-add6-11f1-8d0d-937dcaffa153" data-action="Deal Block" data-label="iPhone 18 Pro Max: free w/ trade-in + unlimited @ Xfinity Mobile" data-dimension48="iPhone 18 Pro Max: free w/ trade-in + unlimited @ Xfinity Mobile" data-dimension25="">View Deal</a></p></div><h3 class="article-body__section" id="section-accessories"><span>Accessories</span></h3><div class="product"><a data-dimension112="2c072c10-add6-11f1-8192-615a79dc6810" data-action="Deal Block" data-label="EarPods (Lightning)" data-dimension48="EarPods (Lightning)" data-dimension25="$14" href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1040px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Ys3T2v7S48cnc2sK2hLS9U" name="apple earpods with lightning connector.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Ys3T2v7S48cnc2sK2hLS9U.jpg" mos="" align="middle" fullscreen="" width="1040" height="1040" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow" data-dimension112="2c072c10-add6-11f1-8192-615a79dc6810" data-action="Deal Block" data-label="EarPods (Lightning)" data-dimension48="EarPods (Lightning)" data-dimension25="$14">EarPods (Lightning): was $19 now $14</a></strong><br>If you like listening to your music the old-fashioned way, this pair of wired EarPods has a Lightning connector, allowing them to be used with older Apple devices. For this price, you might as well grab a pair!<a class="view-deal button" href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow" data-dimension112="2c072c10-add6-11f1-8192-615a79dc6810" data-action="Deal Block" data-label="EarPods (Lightning)" data-dimension48="EarPods (Lightning)" data-dimension25="$14">View Deal</a></p></div><div class="product"><a data-dimension112="2c072c6a-add6-11f1-b75e-5141d26254c9" data-action="Deal Block" data-label="20W USB-C Compact Power Adapter" data-dimension48="20W USB-C Compact Power Adapter" data-dimension25="$14" href="https://www.amazon.com/Apple-20W-USB-C-Power-Adapter/dp/B0DJFW7PNM" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:649px;"><p class="vanilla-image-block" style="padding-top:149.61%;"><img id="mhEQ7c2rj34AhoPSdBToNX" name="20W USB-C Compact Power Adapter" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mhEQ7c2rj34AhoPSdBToNX.jpg" mos="" align="middle" fullscreen="" width="649" height="971" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-20W-USB-C-Power-Adapter/dp/B0DJFW7PNM" target="_blank" rel="nofollow" data-dimension112="2c072c6a-add6-11f1-b75e-5141d26254c9" data-action="Deal Block" data-label="20W USB-C Compact Power Adapter" data-dimension48="20W USB-C Compact Power Adapter" data-dimension25="$14">20W USB-C Compact Power Adapter: was $19 now $14</a></strong><br>This is one of those essentials everyone needs, so you might as well buy one while it's on sale. It offers 20W fast charging for iPhone 8 and up.<a class="view-deal button" href="https://www.amazon.com/Apple-20W-USB-C-Power-Adapter/dp/B0DJFW7PNM" target="_blank" rel="nofollow" data-dimension112="2c072c6a-add6-11f1-b75e-5141d26254c9" data-action="Deal Block" data-label="20W USB-C Compact Power Adapter" data-dimension48="20W USB-C Compact Power Adapter" data-dimension25="$14">View Deal</a></p></div><div class="product"><a data-dimension112="2c072d14-add6-11f1-86d1-4149fd7a0d83" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$24" href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:600px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="EzmCNB37HYZTKq3XSMqvTY" name="Apple AirTag 2 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/EzmCNB37HYZTKq3XSMqvTY.jpg" mos="" align="middle" fullscreen="" width="600" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow" data-dimension112="2c072d14-add6-11f1-86d1-4149fd7a0d83" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$24">AirTag (2nd Gen): was $29 now $24</a></strong><br>Apple's second generation AirTag offers better range, precision finding, a louder speaking and a bunch of extra improvements to help you track your lost keys and bags.<a class="view-deal button" href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow" data-dimension112="2c072d14-add6-11f1-86d1-4149fd7a0d83" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$24">View Deal</a></p></div><div class="product"><a data-dimension112="2c072d78-add6-11f1-8979-95e17ba4f48e" data-action="Deal Block" data-label="240W USB-C to USB-C Woven Charge Cable (2 m)" data-dimension48="240W USB-C to USB-C Woven Charge Cable (2 m)" data-dimension25="$24" href="https://www.amazon.com/Apple-USB-C-Woven-Charge-Cable/dp/B0DCH5B2HF" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1500px;"><p class="vanilla-image-block" style="padding-top:71.07%;"><img id="H37kKia68mrqHSBwHDsVRJ" name="240W USB-C to USB-C Woven Charge Cable (2 m)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/H37kKia68mrqHSBwHDsVRJ.jpg" mos="" align="middle" fullscreen="" width="1500" height="1066" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-USB-C-Woven-Charge-Cable/dp/B0DCH5B2HF" target="_blank" rel="nofollow" data-dimension112="2c072d78-add6-11f1-8979-95e17ba4f48e" data-action="Deal Block" data-label="240W USB-C to USB-C Woven Charge Cable (2 m)" data-dimension48="240W USB-C to USB-C Woven Charge Cable (2 m)" data-dimension25="$24">240W USB-C to USB-C Woven Charge Cable (2 m): was $29 now $24</a></strong><br>Another essential you don't want to go without. I have mostly USB-A to USB-C cables, so I definitely need to grab one of these for when a USB-A charging port isn't available — plus it's $5 off.<a class="view-deal button" href="https://www.amazon.com/Apple-USB-C-Woven-Charge-Cable/dp/B0DCH5B2HF" target="_blank" rel="nofollow" data-dimension112="2c072d78-add6-11f1-8979-95e17ba4f48e" data-action="Deal Block" data-label="240W USB-C to USB-C Woven Charge Cable (2 m)" data-dimension48="240W USB-C to USB-C Woven Charge Cable (2 m)" data-dimension25="$24">View Deal</a></p></div><div class="product"><a data-dimension112="2c072dd2-add6-11f1-a03b-2ffcd05ce3db" data-action="Deal Block" data-label="Pencil (USB-C)" data-dimension48="Pencil (USB-C)" data-dimension25="$69" href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="LCuHYQPiVnordwa3UuoKE6" name="1721134277.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LCuHYQPiVnordwa3UuoKE6.jpg" mos="" align="middle" fullscreen="" width="500" height="500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow" data-dimension112="2c072dd2-add6-11f1-a03b-2ffcd05ce3db" data-action="Deal Block" data-label="Pencil (USB-C)" data-dimension48="Pencil (USB-C)" data-dimension25="$69">Pencil (USB-C): was $79 now $69</a></strong><br>If you want a cheaper stylus that covers the basics, than the Apple Pencil USB-C is the one for you. With pixel-perfect precision, low-latency and magnets to attach to your tablet, this is the no-frills approach to writing ad drawing on your tablet.<a class="view-deal button" href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow" data-dimension112="2c072dd2-add6-11f1-a03b-2ffcd05ce3db" data-action="Deal Block" data-label="Pencil (USB-C)" data-dimension48="Pencil (USB-C)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="2c072e2c-add6-11f1-aba7-83eea5ba66eb" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$79" href="https://www.amazon.com/Apple-AirTag-2nd-Generation-Precision/dp/B0GJTXVN9Z" 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:133.33%;"><img id="HCUqWkUuUEZJCvXyEu4wwk" name="Apple - AirTag 4 pack (2nd generation) - 2026 - White" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/HCUqWkUuUEZJCvXyEu4wwk.jpg" mos="" align="middle" fullscreen="" width="900" height="1200" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Score a four-pack of Apple AirTag (2nd Gen) keyfinders with a discount. If you have a lot of stuff you need to keep track of, this deal is one of the best ways to do it! Apple's second generation AirTag offers better range, precision finding, a louder speaking and a bunch of extra improvements to help you track your lost keys and bags.<a class="view-deal button" href="https://www.amazon.com/Apple-AirTag-2nd-Generation-Precision/dp/B0GJTXVN9Z" target="_blank" rel="nofollow" data-dimension112="2c072e2c-add6-11f1-aba7-83eea5ba66eb" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$79">View Deal</a></p></div><h3 class="article-body__section" id="section-airpods"><span>AirPods</span></h3><div class="product"><a data-dimension112="2c072eea-add6-11f1-955d-099a1e1fde3f" data-action="Deal Block" data-label="AirPods 4 w/ ANC" data-dimension48="AirPods 4 w/ ANC" data-dimension25="$148" href="https://www.amazon.com/Apple-Headphones-Cancellation-Transparency-Personalized/dp/B0DGJ7HYG1" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:93.08%;"><img id="iW6XqU9SoqpTBgf9epawof" name="Apple AirPods 4 deal block.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iW6XqU9SoqpTBgf9epawof.jpg" mos="" align="middle" fullscreen="" width="679" height="632" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-Headphones-Cancellation-Transparency-Personalized/dp/B0DGJ7HYG1" target="_blank" rel="nofollow" data-dimension112="2c072eea-add6-11f1-955d-099a1e1fde3f" data-action="Deal Block" data-label="AirPods 4 w/ ANC" data-dimension48="AirPods 4 w/ ANC" data-dimension25="$148">AirPods 4 w/ ANC: was $179 now $148</a></strong><br>These AirPods 4 have all the same great features as the base AirPods 4, except they also include Active Noise Cancellation. They also feature Adaptive Audio, Transparency mode, and Voice Isolation. It's a modest, but welcome price cut.<a class="view-deal button" href="https://www.amazon.com/Apple-Headphones-Cancellation-Transparency-Personalized/dp/B0DGJ7HYG1" target="_blank" rel="nofollow" data-dimension112="2c072eea-add6-11f1-955d-099a1e1fde3f" data-action="Deal Block" data-label="AirPods 4 w/ ANC" data-dimension48="AirPods 4 w/ ANC" data-dimension25="$148">View Deal</a></p></div><div class="product"><a data-dimension112="2c072f44-add6-11f1-84a6-37d10cfe2338" data-action="Deal Block" data-label="AirPods Pro 3" data-dimension48="AirPods Pro 3" data-dimension25="$199" href="https://www.amazon.com/Apple-Cancellation-Translation-Headphones-High-Fidelity/dp/B0FQFB8FMG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:842px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="FYzcjQSdtuwidVacXmMNL5" name="AirPods Pro 3.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FYzcjQSdtuwidVacXmMNL5.jpg" mos="" align="middle" fullscreen="" width="842" height="842" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The AirPods Pro 3 bring the heat with 10 hours of battery life, improved sound, and superior active noise canceling. In our <a href="https://www.tomsguide.com/audio/airpods/apple-airpods-pro-3-review" data-dimension112="2c072f44-add6-11f1-84a6-37d10cfe2338" data-action="Deal Block" data-label="AirPods Pro 3" data-dimension48="AirPods Pro 3" data-dimension25="$199">AirPods Pro 3 review</a> we said the Editor's Choice buds deliver the upgrade iPhone users have been waiting for with improved battery life, stronger noise cancellation, and smart new features like Live Translation, which delivers real-time translations to your ears. <a class="view-deal button" href="https://www.amazon.com/Apple-Cancellation-Translation-Headphones-High-Fidelity/dp/B0FQFB8FMG" target="_blank" rel="nofollow" data-dimension112="2c072f44-add6-11f1-84a6-37d10cfe2338" data-action="Deal Block" data-label="AirPods Pro 3" data-dimension48="AirPods Pro 3" data-dimension25="$199">View Deal</a></p></div><div class="product"><a data-dimension112="2c072f9e-add6-11f1-92e3-1f6c568cc27d" data-action="Deal Block" data-label="AirPods Max 2" data-dimension48="AirPods Max 2" data-dimension25="$449" href="https://www.amazon.com/dp/B0GSS72GZJ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="TSi2XMUrFhYn5nqrGBsd59" name="airpods max 2 deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/TSi2XMUrFhYn5nqrGBsd59.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>These are some of the best headphones we've ever used. With seamless Apple ecosystem integration, well-balanced sound, and excellent comfort, the AirPods Max 2 will make you want to listen to music. You have to try them to believe them and at this price, it's almost a steal.<a class="view-deal button" href="https://www.amazon.com/dp/B0GSS72GZJ" target="_blank" rel="nofollow" data-dimension112="2c072f9e-add6-11f1-92e3-1f6c568cc27d" data-action="Deal Block" data-label="AirPods Max 2" data-dimension48="AirPods Max 2" data-dimension25="$449">View Deal</a></p></div><h3 class="article-body__section" id="section-apple-watch"><span>Apple Watch</span></h3><div class="product"><a data-dimension112="2c073066-add6-11f1-bade-a1125d0c5086" data-action="Deal Block" data-label="Watch 11 (GPS/46mm)" data-dimension48="Watch 11 (GPS/46mm)" data-dimension25="$329" href="https://www.amazon.com/Apple-Watch-Smartwatch-Aluminum-Always/dp/B0FQFHVKZ4" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1270px;"><p class="vanilla-image-block" style="padding-top:118.11%;"><img id="GuyP4rEgTW2kHmRSjGeHCG" name="Apple Watch 11 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GuyP4rEgTW2kHmRSjGeHCG.jpg" mos="" align="middle" fullscreen="" width="1270" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-Watch-Smartwatch-Aluminum-Always/dp/B0FQFHVKZ4" target="_blank" rel="nofollow" data-dimension112="2c073066-add6-11f1-bade-a1125d0c5086" data-action="Deal Block" data-label="Watch 11 (GPS/46mm)" data-dimension48="Watch 11 (GPS/46mm)" data-dimension25="$329">Watch 11 (GPS/46mm): was $429 now $329</a></strong><br>Need a bigger screen? The larger 46mm model of the Apple Watch 11 is on sale for $329 — that's $100 off. Otherwise, it has all of the same great features as the smaller 42mm model, including amazing battery life that lasts up to 24 hours (up to 38 hours in low power mode.) And it's $120 cheaper than the new 46mm Apple Watch 12.<a class="view-deal button" href="https://www.amazon.com/Apple-Watch-Smartwatch-Aluminum-Always/dp/B0FQFHVKZ4" target="_blank" rel="nofollow" data-dimension112="2c073066-add6-11f1-bade-a1125d0c5086" data-action="Deal Block" data-label="Watch 11 (GPS/46mm)" data-dimension48="Watch 11 (GPS/46mm)" data-dimension25="$329">View Deal</a></p></div><h3 class="article-body__section" id="section-ipads"><span>iPads</span></h3><div class="product"><a data-dimension112="2c07311a-add6-11f1-8240-15d9275a7b0e" data-action="Deal Block" data-label="iPad mini 7" data-dimension48="iPad mini 7" data-dimension25="$569" href="https://www.amazon.com/dp/B0DK3W4YHS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1203px;"><p class="vanilla-image-block" style="padding-top:124.69%;"><img id="G2PjHEjHsRfuddfWSzPBjd" name="iPad mini 2024 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/G2PjHEjHsRfuddfWSzPBjd.jpg" mos="" align="middle" fullscreen="" width="1203" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The iPad mini is getting a discount, and any price cut to this small tablet is welcome. We're big fans of its incredibly portable design and long battery life (it lasted 10 hours in our battery life tests.) It comes with speedy performance thanks to Apple's A17 Pro chip, and has a gorgeous 8.3-inch (2,266 x 1,488) Liquid Retina display. You also get 12MP cameras on the front and back and Wi-Fi 6e support. In our <a href="https://www.tomsguide.com/tablets/ipads/ipad-mini-7-review" data-dimension112="2c07311a-add6-11f1-8240-15d9275a7b0e" data-action="Deal Block" data-label="iPad mini 7" data-dimension48="iPad mini 7" data-dimension25="$569">iPad mini 7 review</a>, we said it delivers the full iPad experience in a tiny size. <a class="view-deal button" href="https://www.amazon.com/dp/B0DK3W4YHS" target="_blank" rel="nofollow" data-dimension112="2c07311a-add6-11f1-8240-15d9275a7b0e" data-action="Deal Block" data-label="iPad mini 7" data-dimension48="iPad mini 7" data-dimension25="$569">View Deal</a></p></div><div class="product"><a data-dimension112="2c073174-add6-11f1-829f-5f28787d7d43" data-action="Deal Block" data-label="11" iPad Air (WiFi/128GB)" data-dimension48="11" iPad Air (WiFi/128GB)" data-dimension25="$712" href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQVBJT4J" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1325px;"><p class="vanilla-image-block" style="padding-top:113.21%;"><img id="NVZkwX7FuVd3CYdiYHdsgm" name="iPad Air 11 2024 deal block.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/NVZkwX7FuVd3CYdiYHdsgm.jpg" mos="" align="middle" fullscreen="" width="1325" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQVBJT4J" target="_blank" rel="nofollow" data-dimension112="2c073174-add6-11f1-829f-5f28787d7d43" data-action="Deal Block" data-label='11" iPad Air (WiFi/128GB)' data-dimension48='11" iPad Air (WiFi/128GB)' data-dimension25="$712">11" iPad Air (WiFi/128GB): was $749 now $712</a></strong><br>The 2026 iPad Air packs Apple's M4 processor, which Apple states is up to 30 percent faster than iPad Air with M3. It also has an 11-inch LED (2360 x 1640) display, 128GB of storage, 12MP rear camera, and 12MP front camera. The tablet now supports Wi-Fi 7 a well as Bluetooth 6 and Thread. In our <a href="https://www.tomsguide.com/computing/ipads/apple-ipad-air-m4-review-small-tweaks-to-the-gold-standard">iPad Air M4 review</a>, we said the upgrades are modest, but the iPad Air remains the best tablet out there. <a class="view-deal button" href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQVBJT4J" target="_blank" rel="nofollow" data-dimension112="2c073174-add6-11f1-829f-5f28787d7d43" data-action="Deal Block" data-label="11" iPad Air (WiFi/128GB)" data-dimension48="11" iPad Air (WiFi/128GB)" data-dimension25="$712">View Deal</a></p></div><h3 class="article-body__section" id="section-macbooks"><span>MacBooks</span></h3><div class="product"><a data-dimension112="2c073232-add6-11f1-964c-51f770bc2e45" data-action="Deal Block" data-label="MacBook Neo" data-dimension48="MacBook Neo" data-dimension25="$679" href="https://www.amazon.com/dp/B0GR6BVYS5" 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:61.07%;"><img id="Lg4Dvg68j9SbB5CPNrTEpH" name="MacBook Neo deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg" mos="" align="middle" fullscreen="" width="1500" height="916" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The MacBook Neo sports a 13-inch Liquid Retina (2408 x 1506) display, A18 Pro chipset, 8GB of RAM, 256GB SSD, and 1080p FaceTime HD camera. The 2.7-lb. laptop is available in Indigo, Blush, Citrus, and Silver. In our <a href="https://www.tomsguide.com/computing/macbooks/apple-macbook-neo-review" data-dimension112="2c073232-add6-11f1-964c-51f770bc2e45" data-action="Deal Block" data-label="MacBook Neo" data-dimension48="MacBook Neo" data-dimension25="$679">MacBook Neo review</a>, we said no other laptop comes close to the Neo in terms of bang for your buck — even with its new/higher $699 price tag. <a class="view-deal button" href="https://www.amazon.com/dp/B0GR6BVYS5" target="_blank" rel="nofollow" data-dimension112="2c073232-add6-11f1-964c-51f770bc2e45" data-action="Deal Block" data-label="MacBook Neo" data-dimension48="MacBook Neo" data-dimension25="$679">View Deal</a></p></div><div class="product"><a data-dimension112="2c07328c-add6-11f1-9027-ef0e3b0387c2" data-action="Deal Block" data-label="15" MacBook Air (M5)" data-dimension48="15" MacBook Air (M5)" data-dimension25="$1399" href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" 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:60.73%;"><img id="R5hxVnj9RteJKiej8tQbLH" name="MacBook Air M5 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/R5hxVnj9RteJKiej8tQbLH.jpg" mos="" align="middle" fullscreen="" width="1500" height="911" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" target="_blank" rel="nofollow" data-dimension112="2c07328c-add6-11f1-9027-ef0e3b0387c2" data-action="Deal Block" data-label='15" MacBook Air (M5)' data-dimension48='15" MacBook Air (M5)' data-dimension25="$1399">15" MacBook Air (M5): was $1499 now $1399</a></strong><br>Right now you can get the 15-inch MacBook Air M5 for $100 off. This laptop features a 15.3-inch (2880 x 1864) display, Apple M5 chipset, 16GB of RAM, 512GB SSD, and support for WiFi 7 and Bluetooth 6. <br><strong>Price check: </strong><a href="https://www.bestbuy.com/product/apple-macbook-air-15-inch-laptop-m5-chip-with-10-core-cpu-and-10-core-gpu-16gb-memory-512gb-ssd-midnight/JJGCQLKQL9/sku/6571043" target="_blank" rel="nofollow"><strong>$1,399 @ Best Buy</strong></a><strong></strong><a class="view-deal button" href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" target="_blank" rel="nofollow" data-dimension112="2c07328c-add6-11f1-9027-ef0e3b0387c2" data-action="Deal Block" data-label="15" MacBook Air (M5)" data-dimension48="15" MacBook Air (M5)" data-dimension25="$1399">View Deal</a></p></div><div class="product"><a data-dimension112="2c0732e6-add6-11f1-b7b8-8372e9e09d42" data-action="Deal Block" data-label="MacBook Pro 14" (M5/1TB)" data-dimension48="MacBook Pro 14" (M5/1TB)" data-dimension25="$1849" href="https://www.amazon.com/dp/B0FWD8WBSW" 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:60.53%;"><img id="GnpQTG2JTWSenJyfrWydnm" name="MacBook Pro M5 deals" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GnpQTG2JTWSenJyfrWydnm.jpg" mos="" align="middle" fullscreen="" width="1500" height="908" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0FWD8WBSW" target="_blank" rel="nofollow" data-dimension112="2c0732e6-add6-11f1-b7b8-8372e9e09d42" data-action="Deal Block" data-label='MacBook Pro 14" (M5/1TB)' data-dimension48='MacBook Pro 14" (M5/1TB)' data-dimension25="$1849">MacBook Pro 14" (M5/1TB): was $1999 now $1849</a></strong><br>This MacBook Pro features Apple's M5 chipset, with a 10-core CPU and 10-core GPU. It's designed to deliver a huge boost in AI and graphics performance for everyone from students to creatives. In our <a href="https://www.tomsguide.com/computing/macbooks/macbook-pro-m5-review">MacBook Pro M5 review</a> we said the Editor's Choice machine is a fantastic option for power users who demand a powerful and portable notebook with epic (18 hour) battery life. The base model features a 14.2-inch 3024 x 1964 Retina display, Apple M5 CPU, 16GB of RAM and a 512GB SSD.<a class="view-deal button" href="https://www.amazon.com/dp/B0FWD8WBSW" target="_blank" rel="nofollow" data-dimension112="2c0732e6-add6-11f1-b7b8-8372e9e09d42" data-action="Deal Block" data-label="MacBook Pro 14" (M5/1TB)" data-dimension48="MacBook Pro 14" (M5/1TB)" data-dimension25="$1849">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=school&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[ iPhone 18 Pro and Pro Max battery capacity confirmed in Europe — here's how they compare to iPhone 17 Pro ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple made a bunch of grandiose claims about the battery upgrades in the <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 and iPhone 18 Pro Max,</a> but stopped short of revealing how large the new batteries actually are. That's pretty typical for Apple, though new European Union (EU) regulations may have just helped reveal the answer.</p><p>All phones that go on sale with the EU need to have publicly accessible Energy Labels. These labels list key details about the phone including IP ratings, drop test performance, repairability, energy performance and battery specs. That information also includes battery capacity.</p><p>According to the listings <strong>iPhone 18 Pro will have </strong><a href="https://regulatoryinfo.apple.com/cwt/api/ext/file?fileId=energyLabels/A3714_V1/A3714/A3714_PIS_LotX_EU_English.pdf" target="_blank"><strong>a 4,056 mAh battery</strong></a>, while the <strong>iPhone 18 Pro Max will offer</strong><a href="https://regulatoryinfo.apple.com/cwt/api/ext/file?fileId=energyLabels/A3717_V1/A3717/A3717_PIS_LotX_EU_English.pdf" target="_blank"><strong> 5,391 mAh capacity</strong></a> in the EU and other related regions. These devices likely all come with physical SIM card slots, since European iPhone owners aren't yet forced to use eSIMs the way they are in places like the U.S.  </p><p>This is important because it means the North American models may actually offer slightly larger batteries. That trend started with the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a> and<a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review"> Pro Max,</a> and considering the design hasn't changed that much, we're expecting it to happen again this year. But for now, let's examine the changes in battery size as if everyone is getting the same thing — SIM slot or not.</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Capacity (mAh)</strong></p></td><td  ><p><strong>Difference (%)</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro (nano SIM)</strong></p></td><td  ><p>4,056</p></td><td  ><p>N/A</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro Max (nano SIM)</strong></p></td><td  ><p>5,391</p></td><td  ><p>N/A</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro (eSIM)</strong></p></td><td  ><p>4,252</p></td><td  ><p>-4.71%</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max (eSIM)</strong></p></td><td  ><p>5,088</p></td><td  ><p>5.78%</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro (nano SIM)</strong></p></td><td  ><p>3,998</p></td><td  ><p>1.44%</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max (nano SIM)</strong></p></td><td  ><p>4,823</p></td><td  ><p>11.12%</p></td></tr></tbody></table></div><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eGbxVX"></div>                            </div>                            <script src="https://kwizly.com/embed/eGbxVX.js" async></script><p>The EU iPhone 18 Pro actually has a smaller battery than the eSIM-only iPhone 17 Pro, with a difference of almost 5%. However it is slightly higher than the nano-SIM 17 Pro variant, with 1.44% more battery capacity. If we extrapolate that change, we estimate that the eSIM-only 18 Pro could have <strong>roughly 4,313 mAh of capacity.</strong></p><p>The nano SIM iPhone 18 Pro Max's battery is 5.78% larger than that of the eSIM iPhone 17 Pro Max, and a whopping 11.12% larger than the battery on the nano SIM iPhone 17 Pro Max. Again if there's a similar size difference between the two eSIM variants, the iPhone 18 Pro Max could have as much as <strong>5,653 mAh of battery capacity</strong> — which is absurd when you consider Apple typically offers much smaller batteries than its rivals.</p><p>Of course we don't know for sure whether the new batteries will be that size, on account of the U.S. not having the same regulatory requirements as the EU. So unless Apple makes the uncharacteristic decision to reveal all the nitty-gritty specs of the new iPhones, we're going to have to wait for teardowns following the September 18 release date.</p><p>As for the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo</a>, we're just going to have to wait a little longer. Since it won't be released until October 23, we're going to have to wait a few months before these sort of regulatory filings are made available to the public. </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-vs-samsung-galaxy-z-fold-8-7-ways-apples-foldable-beats-its-rival-from-ip68-to-faster-charging-and-more">iPhone Duo vs Galaxy Z Fold 8 — 7 ways Apple beats Samsung's foldable</a></li><li><a href="https://www.tomsguide.com/phones/iphones/interview-apple-ceo-john-ternus-on-his-defining-moment-for-the-iphone-duo">Exclusive: Apple CEO John Ternus and Joz on making iPhone Duo, fixing the crease and 'uninspiring' Android foldables</a></li><li><a href="https://www.tomsguide.com/phones/iphones/apples-usd1-999-gamble-analysts-react-to-the-new-iphone-duo-foldable">Apple's $1,999 gamble — analysts react to the new iPhone Duo foldable</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-pro-max-battery-capacity-confirmed-in-europe-heres-how-they-compare-to-iphone-17-pro</link>
                                                                            <description>
                            <![CDATA[ EU regulatory filings just revealed how big the batteries are in the two newest iPhones. Here's how they compare to last year's models. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">VP4L9Hxg5sdCVRnysUfMJg</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/6N7PRoZ922V5VYKySqDu7o-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 11 Sep 2026 10:58:19 +0000</pubDate>                                                                                                                                <updated>Fri, 11 Sep 2026 11:58:24 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ tom.pritchard@futurenet.com (Tom Pritchard) ]]></author>                    <dc:creator><![CDATA[ Tom Pritchard ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/biCewUkKfSA6QnT2HxVc3f.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/6N7PRoZ922V5VYKySqDu7o-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone 18 Pro Max]]></media:description>                                                            <media:text><![CDATA[iPhone 18 Pro Max]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone 18 Pro Max]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/6N7PRoZ922V5VYKySqDu7o-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple made a bunch of grandiose claims about the battery upgrades in the <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 and iPhone 18 Pro Max,</a> but stopped short of revealing how large the new batteries actually are. That's pretty typical for Apple, though new European Union (EU) regulations may have just helped reveal the answer.</p><p>All phones that go on sale with the EU need to have publicly accessible Energy Labels. These labels list key details about the phone including IP ratings, drop test performance, repairability, energy performance and battery specs. That information also includes battery capacity.</p><p>According to the listings <strong>iPhone 18 Pro will have </strong><a href="https://regulatoryinfo.apple.com/cwt/api/ext/file?fileId=energyLabels/A3714_V1/A3714/A3714_PIS_LotX_EU_English.pdf" target="_blank"><strong>a 4,056 mAh battery</strong></a>, while the <strong>iPhone 18 Pro Max will offer</strong><a href="https://regulatoryinfo.apple.com/cwt/api/ext/file?fileId=energyLabels/A3717_V1/A3717/A3717_PIS_LotX_EU_English.pdf" target="_blank"><strong> 5,391 mAh capacity</strong></a> in the EU and other related regions. These devices likely all come with physical SIM card slots, since European iPhone owners aren't yet forced to use eSIMs the way they are in places like the U.S.  </p><p>This is important because it means the North American models may actually offer slightly larger batteries. That trend started with the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a> and<a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review"> Pro Max,</a> and considering the design hasn't changed that much, we're expecting it to happen again this year. But for now, let's examine the changes in battery size as if everyone is getting the same thing — SIM slot or not.</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Capacity (mAh)</strong></p></td><td  ><p><strong>Difference (%)</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro (nano SIM)</strong></p></td><td  ><p>4,056</p></td><td  ><p>N/A</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro Max (nano SIM)</strong></p></td><td  ><p>5,391</p></td><td  ><p>N/A</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro (eSIM)</strong></p></td><td  ><p>4,252</p></td><td  ><p>-4.71%</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max (eSIM)</strong></p></td><td  ><p>5,088</p></td><td  ><p>5.78%</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro (nano SIM)</strong></p></td><td  ><p>3,998</p></td><td  ><p>1.44%</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max (nano SIM)</strong></p></td><td  ><p>4,823</p></td><td  ><p>11.12%</p></td></tr></tbody></table></div><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eGbxVX"></div>                            </div>                            <script src="https://kwizly.com/embed/eGbxVX.js" async></script><p>The EU iPhone 18 Pro actually has a smaller battery than the eSIM-only iPhone 17 Pro, with a difference of almost 5%. However it is slightly higher than the nano-SIM 17 Pro variant, with 1.44% more battery capacity. If we extrapolate that change, we estimate that the eSIM-only 18 Pro could have <strong>roughly 4,313 mAh of capacity.</strong></p><p>The nano SIM iPhone 18 Pro Max's battery is 5.78% larger than that of the eSIM iPhone 17 Pro Max, and a whopping 11.12% larger than the battery on the nano SIM iPhone 17 Pro Max. Again if there's a similar size difference between the two eSIM variants, the iPhone 18 Pro Max could have as much as <strong>5,653 mAh of battery capacity</strong> — which is absurd when you consider Apple typically offers much smaller batteries than its rivals.</p><p>Of course we don't know for sure whether the new batteries will be that size, on account of the U.S. not having the same regulatory requirements as the EU. So unless Apple makes the uncharacteristic decision to reveal all the nitty-gritty specs of the new iPhones, we're going to have to wait for teardowns following the September 18 release date.</p><p>As for the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo</a>, we're just going to have to wait a little longer. Since it won't be released until October 23, we're going to have to wait a few months before these sort of regulatory filings are made available to the public. </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-vs-samsung-galaxy-z-fold-8-7-ways-apples-foldable-beats-its-rival-from-ip68-to-faster-charging-and-more">iPhone Duo vs Galaxy Z Fold 8 — 7 ways Apple beats Samsung's foldable</a></li><li><a href="https://www.tomsguide.com/phones/iphones/interview-apple-ceo-john-ternus-on-his-defining-moment-for-the-iphone-duo">Exclusive: Apple CEO John Ternus and Joz on making iPhone Duo, fixing the crease and 'uninspiring' Android foldables</a></li><li><a href="https://www.tomsguide.com/phones/iphones/apples-usd1-999-gamble-analysts-react-to-the-new-iphone-duo-foldable">Apple's $1,999 gamble — analysts react to the new iPhone Duo foldable</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ The hidden iOS 27 iPhone setting every parent needs to turn on right now ]]></title>
                                                                                                <dc:content><![CDATA[ <p>With iOS 27, you can hand an iPhone to a child with far greater confidence. Apple has overhauled its parental controls with a new guided setup assistant, making it simpler than ever to apply smart restrictions and tailor the device to a younger user.</p><p>There are several powerful features worth exploring. Beyond capping app availability and blocking in-app purchases, you can restrict adult websites, set strict time limits on games or social media, and automatically blur images containing graphic violence and gore alongside nudity.</p><p>If your child uses an iPhone, taking a few minutes to walk through these settings is essential. Tech-savvy kids might eventually look for a workaround (don’t they always?), but setting these guardrails now offers invaluable peace of mind.</p><h3 class="article-body__section" id="section-how-to-set-up-a-child-s-account"><span>How to set up a child’s account</span></h3><p>First of all, you will need to create a child's account.</p><section class="howto-block">                    <h3>1. Add a child</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/ADnFMt3kUVsagjdwasn6w3.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/ADnFMt3kUVsagjdwasn6w3.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>If you haven’t set up a child’s account before, don’t worry. It’s relatively straightforward.</p><p>First of all, you’re going to need to set up the account in Family Sharing so <strong>open the Settings app</strong> and <strong>select Family</strong>. So long as you’re the family organiser or a parent/guardian, you’ll be able to <strong>select the Add Member icon</strong> in the top-right corner of the screen.</p></p>                </section><section class="howto-block">                    <h3>2. Create the child account</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/AK2pzfeHkEcd5fiEW7S6rH.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/AK2pzfeHkEcd5fiEW7S6rH.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>Next,<strong> enter the child’s name and date of birth </strong>and <strong>tap Create Child Account</strong>. Once done, you’ll be asked to <strong>agree with Apple’s family privacy disclosure for children</strong>.</p><p>An email address will then be created for the child. <strong>Tap Continue</strong> if you’re happy with it or <strong>tap the email address to edit it</strong>. You will be asked to <strong>create a password</strong> too.</p></p>                </section><h3 class="article-body__section" id="section-how-to-manage-the-parental-controls"><span>How to manage the parental controls</span></h3><p>Once you have created a child's account, you can begin to manage access.</p><section class="howto-block">                    <h3>1. Access the controls</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/5acxaGmiKcF3Y2JJBcqeJL.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/5acxaGmiKcF3Y2JJBcqeJL.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>Once you have created a child account, you can begin to control how it’s use. <strong>Open the Settings app</strong> and <strong>select Family</strong>. Next,<strong>select a child account</strong> you wish to control.</p></p>                </section><section class="howto-block">                    <h3>2. Set an app age range</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/gxookVxmXBnQVtUchiYZqM.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/gxookVxmXBnQVtUchiYZqM.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>Some apps alter how they are experienced depending on the age of the child. </p><p>In order to do this, the apps need to be told the age range of the child (not, it must be noted, their actual date-of-birth). You can determine how and when this information is shared..</p><p><strong>Select Set Up</strong> next to Age Range for Apps and<strong> tap Confirm Age</strong>. Then, either <strong>choose Always</strong> to ensure the age range is always shared, <strong>select Ask First</strong> if you would rather children choose when their age range is shared, or <strong>tap Never</strong> to prevent the age range from ever being shared.</p></p>                </section><section class="howto-block">                    <h3>3. Limit a child’s usage</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/xkge2kn8Pgz2cGnE6y7UHQ.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/xkge2kn8Pgz2cGnE6y7UHQ.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>If you would like to place restrictions on how a child uses the iPhone,<strong> tap ScreenTime</strong> and look under the section Limit Usage.</p><p>Here, you can <strong>select Downtime</strong>, a feature that blocks access to most apps and notifications during specified hours. You can <strong>set the time period</strong> during which Downtime is active and <strong>choose how frequently it is enabled</strong> — either every day or on specific days. For the latter, <strong>tap Customize Days</strong>.</p><p>You can also <strong>use the toggle to turn on Block at Downtime</strong>. This will block the iPhone during the specified time period.</p></p>                </section><section class="howto-block">                    <h3>4. Set app time limits</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/BTjnZrk7EjLTyvzGdCn9aS.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/BTjnZrk7EjLTyvzGdCn9aS.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>You can also restrict the amount of time a child spends on an app. You may, for example, only want your child to play games for an hour max each day.</p><p>To do this, <strong>tap App Limits</strong>, <strong>select Add Limit</strong>, <strong>choose an app category</strong> and <strong>tap Next</strong>.</p><p>You can then<strong> set the required time period</strong> and indicate whether this should be in place on specific days or every day. You can also <strong>determine whether the app is blocked at the end of the time limit, </strong>or whether the child is simply alerted to the fact their time is up.</p></p>                </section><section class="howto-block">                    <h3>5. Make exemptions</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/caqaXfFXjKNz3MzNtmfuvU.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/caqaXfFXjKNz3MzNtmfuvU.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>If you <strong>select All Apps & Categories</strong> when setting app time limits, there may be some apps that you would like your child to have access to at all times. </p><p>For example, it may make sense to allow the child to use the Phone app at any time. <strong>Tap Always Allowed</strong> to choose which apps your child can access without time restrictions.</p><p>For added safety, if you’re allowing a child to use communication apps, you can limit who they are able to communicate with. <strong>Select Contacts Only</strong> and you can<strong> select Specific Contacts</strong> before determining which ones are permissible.</p></p>                </section><section class="howto-block">                    <h3>6. Set communication limits</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/QcW6rNp68tKEgYDjce4hYW.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/QcW6rNp68tKEgYDjce4hYW.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>For even more control over communication,<strong> select Communication Limits</strong> on the main Screen Time settings screen. </p><p>This will allow you to determine which contacts are allowed during Screen Time and Downtime and determine who is in the contacts list.</p></p>                </section><section class="howto-block">                    <h3>7. Ban sensitive content</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/XZoNiVTSuBPpuSr7cQcXJY.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/XZoNiVTSuBPpuSr7cQcXJY.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>To shield younger users from exposure to explicit, violent, or inappropriate media, <strong>turning on Communication Safety</strong> adds a critical layer of automatic protection.</p><p><strong>Simply toggle this feature on in your Screen Time setting</strong>s, and if iOS detects sensitive images, it will blur them and provide age-appropriate guidance to help your child make a safe choice.</p></p>                </section><section class="howto-block">                    <h3>8. Use content and privacy restrictions</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/5P9Bfn44QTqZJKqyRo9b4a.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/5P9Bfn44QTqZJKqyRo9b4a.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>You can also prevent children from accessing adult videos, music, apps, and podcasts. Tap <strong>Content & Privacy Restrictions</strong>, then explore the sub-menus for <strong>App Store, Media, Web & Games</strong>, <strong>Allowed Apps & Features</strong>, and <strong>iTunes & App Store Purchases</strong>. </p><p>From here, you can set age limits, turn off specific app access, block new installs, and prevent in-app purchases.</p><p>Finally, decide whether to allow your child to change their passcode, alter Face ID settings, or switch accounts. <strong>Under Allow Changes</strong>, review each setting and toggle off any permissions you want to lock down.</p><p>It’s also worth tapping <strong>App Store, Media, Web & Games</strong> to customize internet access. <strong>Select Web Content</strong> to restrict adult sites or limit browsing exclusively to an approved list. </p><p>Apple provides a preset selection of kid-friendly sites, but you can<strong> scroll to the bottom and tap Add Website</strong> to include your own trusted URLs.</p></p>                </section><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Oajr1X"></div>                            </div>                            <script src="https://kwizly.com/embed/Oajr1X.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-parental-control-apps,review-2258.html">The best parental control apps in 2026</a></li><li><a href="https://www.tomsguide.com/phones/back-to-school-phone-setup-essential-parental-controls-every-parent-needs">How to set up your child's first smartphone (and keep them safe online)</a></li><li><a href="https://www.tomsguide.com/phones/iphones/the-new-siri-app-in-ios-27-is-keeping-receipts-on-everything-you-ask-heres-how-to-auto-delete-your-chats">The new Siri app in iOS 27 is keeping receipts on everything you ask — here’s how to auto-delete your chats</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/the-hidden-ios-27-iphone-setting-every-parent-needs-to-turn-on-right-now</link>
                                                                            <description>
                            <![CDATA[ In iOS 27, expanded parental control features make using an iPhone much safer for children. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">8XWwCnXpf4r8aMbyQ89Kqk</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/d5iDY77o2nwEi7UEEz3TzB-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 11 Sep 2026 09:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                                    <dc:creator><![CDATA[ David Crookes ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/yQWsHDmJr9eBZrL4xqd3bE.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;David Crookes has been writing professionally for close to 30 years and, as well as a great fondness for gaming, space, film, music, history, health and politics, he&#039;s largely specialized in technology for much of his career. He particularly focuses on Apple devices, having admired the company&#039;s tech since using iMac G3 in 1998. He also developed a fondness for the older Macintosh LC III that he later used in his first job as a newspaper reporter.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Since becoming a freelance writer, he has written for a wide number of publications including the Apple-focussed magazines iCreate and Macworld as well as Micro Mart, Web User, T3, Retro Gamer, MagPi, Computer Shopper, Gadget and 3D Artist. His love of gaming has seen him write for Retro Gamer, GamesTM and Wireframe among others and, despite his love of Apple, he still uses a PC – working for PC Pro and once writing for Total PC Gaming.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;One of his joys is helping others to use technology which has led him to writing many “how to” tutorials explaining many ways of getting the most out of various devices. He&#039;s become an expert user of the iPhone, iPad, Mac, Apple Watch and Apple TV. He also likes to kick back with a gaming session on an PlayStation 5 or Xbox Series X | S while getting his retro fix on an Evercade handheld.&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/d5iDY77o2nwEi7UEEz3TzB-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Hand holding an iPhone displaying the Apple Screen Time app icon]]></media:description>                                                            <media:text><![CDATA[Hand holding an iPhone displaying the Apple Screen Time app icon]]></media:text>
                                <media:title type="plain"><![CDATA[Hand holding an iPhone displaying the Apple Screen Time app icon]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/d5iDY77o2nwEi7UEEz3TzB-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>With iOS 27, you can hand an iPhone to a child with far greater confidence. Apple has overhauled its parental controls with a new guided setup assistant, making it simpler than ever to apply smart restrictions and tailor the device to a younger user.</p><p>There are several powerful features worth exploring. Beyond capping app availability and blocking in-app purchases, you can restrict adult websites, set strict time limits on games or social media, and automatically blur images containing graphic violence and gore alongside nudity.</p><p>If your child uses an iPhone, taking a few minutes to walk through these settings is essential. Tech-savvy kids might eventually look for a workaround (don’t they always?), but setting these guardrails now offers invaluable peace of mind.</p><h3 class="article-body__section" id="section-how-to-set-up-a-child-s-account"><span>How to set up a child’s account</span></h3><p>First of all, you will need to create a child's account.</p><section class="howto-block">                    <h3>1. Add a child</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/ADnFMt3kUVsagjdwasn6w3.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/ADnFMt3kUVsagjdwasn6w3.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>If you haven’t set up a child’s account before, don’t worry. It’s relatively straightforward.</p><p>First of all, you’re going to need to set up the account in Family Sharing so <strong>open the Settings app</strong> and <strong>select Family</strong>. So long as you’re the family organiser or a parent/guardian, you’ll be able to <strong>select the Add Member icon</strong> in the top-right corner of the screen.</p></p>                </section><section class="howto-block">                    <h3>2. Create the child account</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/AK2pzfeHkEcd5fiEW7S6rH.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/AK2pzfeHkEcd5fiEW7S6rH.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>Next,<strong> enter the child’s name and date of birth </strong>and <strong>tap Create Child Account</strong>. Once done, you’ll be asked to <strong>agree with Apple’s family privacy disclosure for children</strong>.</p><p>An email address will then be created for the child. <strong>Tap Continue</strong> if you’re happy with it or <strong>tap the email address to edit it</strong>. You will be asked to <strong>create a password</strong> too.</p></p>                </section><h3 class="article-body__section" id="section-how-to-manage-the-parental-controls"><span>How to manage the parental controls</span></h3><p>Once you have created a child's account, you can begin to manage access.</p><section class="howto-block">                    <h3>1. Access the controls</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/5acxaGmiKcF3Y2JJBcqeJL.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/5acxaGmiKcF3Y2JJBcqeJL.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>Once you have created a child account, you can begin to control how it’s use. <strong>Open the Settings app</strong> and <strong>select Family</strong>. Next,<strong>select a child account</strong> you wish to control.</p></p>                </section><section class="howto-block">                    <h3>2. Set an app age range</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/gxookVxmXBnQVtUchiYZqM.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/gxookVxmXBnQVtUchiYZqM.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>Some apps alter how they are experienced depending on the age of the child. </p><p>In order to do this, the apps need to be told the age range of the child (not, it must be noted, their actual date-of-birth). You can determine how and when this information is shared..</p><p><strong>Select Set Up</strong> next to Age Range for Apps and<strong> tap Confirm Age</strong>. Then, either <strong>choose Always</strong> to ensure the age range is always shared, <strong>select Ask First</strong> if you would rather children choose when their age range is shared, or <strong>tap Never</strong> to prevent the age range from ever being shared.</p></p>                </section><section class="howto-block">                    <h3>3. Limit a child’s usage</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/xkge2kn8Pgz2cGnE6y7UHQ.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/xkge2kn8Pgz2cGnE6y7UHQ.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>If you would like to place restrictions on how a child uses the iPhone,<strong> tap ScreenTime</strong> and look under the section Limit Usage.</p><p>Here, you can <strong>select Downtime</strong>, a feature that blocks access to most apps and notifications during specified hours. You can <strong>set the time period</strong> during which Downtime is active and <strong>choose how frequently it is enabled</strong> — either every day or on specific days. For the latter, <strong>tap Customize Days</strong>.</p><p>You can also <strong>use the toggle to turn on Block at Downtime</strong>. This will block the iPhone during the specified time period.</p></p>                </section><section class="howto-block">                    <h3>4. Set app time limits</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/BTjnZrk7EjLTyvzGdCn9aS.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/BTjnZrk7EjLTyvzGdCn9aS.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>You can also restrict the amount of time a child spends on an app. You may, for example, only want your child to play games for an hour max each day.</p><p>To do this, <strong>tap App Limits</strong>, <strong>select Add Limit</strong>, <strong>choose an app category</strong> and <strong>tap Next</strong>.</p><p>You can then<strong> set the required time period</strong> and indicate whether this should be in place on specific days or every day. You can also <strong>determine whether the app is blocked at the end of the time limit, </strong>or whether the child is simply alerted to the fact their time is up.</p></p>                </section><section class="howto-block">                    <h3>5. Make exemptions</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/caqaXfFXjKNz3MzNtmfuvU.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/caqaXfFXjKNz3MzNtmfuvU.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>If you <strong>select All Apps & Categories</strong> when setting app time limits, there may be some apps that you would like your child to have access to at all times. </p><p>For example, it may make sense to allow the child to use the Phone app at any time. <strong>Tap Always Allowed</strong> to choose which apps your child can access without time restrictions.</p><p>For added safety, if you’re allowing a child to use communication apps, you can limit who they are able to communicate with. <strong>Select Contacts Only</strong> and you can<strong> select Specific Contacts</strong> before determining which ones are permissible.</p></p>                </section><section class="howto-block">                    <h3>6. Set communication limits</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/QcW6rNp68tKEgYDjce4hYW.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/QcW6rNp68tKEgYDjce4hYW.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>For even more control over communication,<strong> select Communication Limits</strong> on the main Screen Time settings screen. </p><p>This will allow you to determine which contacts are allowed during Screen Time and Downtime and determine who is in the contacts list.</p></p>                </section><section class="howto-block">                    <h3>7. Ban sensitive content</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/XZoNiVTSuBPpuSr7cQcXJY.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/XZoNiVTSuBPpuSr7cQcXJY.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>To shield younger users from exposure to explicit, violent, or inappropriate media, <strong>turning on Communication Safety</strong> adds a critical layer of automatic protection.</p><p><strong>Simply toggle this feature on in your Screen Time setting</strong>s, and if iOS detects sensitive images, it will blur them and provide age-appropriate guidance to help your child make a safe choice.</p></p>                </section><section class="howto-block">                    <h3>8. Use content and privacy restrictions</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/5P9Bfn44QTqZJKqyRo9b4a.png"                                        alt="How to set up parental controls on an iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/5P9Bfn44QTqZJKqyRo9b4a.png"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>You can also prevent children from accessing adult videos, music, apps, and podcasts. Tap <strong>Content & Privacy Restrictions</strong>, then explore the sub-menus for <strong>App Store, Media, Web & Games</strong>, <strong>Allowed Apps & Features</strong>, and <strong>iTunes & App Store Purchases</strong>. </p><p>From here, you can set age limits, turn off specific app access, block new installs, and prevent in-app purchases.</p><p>Finally, decide whether to allow your child to change their passcode, alter Face ID settings, or switch accounts. <strong>Under Allow Changes</strong>, review each setting and toggle off any permissions you want to lock down.</p><p>It’s also worth tapping <strong>App Store, Media, Web & Games</strong> to customize internet access. <strong>Select Web Content</strong> to restrict adult sites or limit browsing exclusively to an approved list. </p><p>Apple provides a preset selection of kid-friendly sites, but you can<strong> scroll to the bottom and tap Add Website</strong> to include your own trusted URLs.</p></p>                </section><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Oajr1X"></div>                            </div>                            <script src="https://kwizly.com/embed/Oajr1X.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-parental-control-apps,review-2258.html">The best parental control apps in 2026</a></li><li><a href="https://www.tomsguide.com/phones/back-to-school-phone-setup-essential-parental-controls-every-parent-needs">How to set up your child's first smartphone (and keep them safe online)</a></li><li><a href="https://www.tomsguide.com/phones/iphones/the-new-siri-app-in-ios-27-is-keeping-receipts-on-everything-you-ask-heres-how-to-auto-delete-your-chats">The new Siri app in iOS 27 is keeping receipts on everything you ask — here’s how to auto-delete your chats</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone Duo vs Galaxy Z Fold 8 — 7 ways Apple beats Samsung's foldable ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The launch of <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo</a> is a big deal. This is the first ever foldable developed by Apple, and for that reason alone it has the chance to dethrone Samsung as the king of the foldable phone space. But it also helps that Apple has produced a phone with a lot of great qualities, and will naturally lead to comparisons with the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Samsung Galaxy Z Fold 8</a>.</p><p>The two phones are similar in a bunch of ways, including their wider, passport-inspired design. However, there are a number of key ways Apple has improved on the foldable design, and beaten Samsung at its own game. Considering this is Apple's first foldable, that might just make the extended development time worth it. Here are seven ways iPhone Duo actually beats the Galaxy Z Fold 8.</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-ip68-rating"><span>IP68 rating</span></h3><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="i4QF9zqZdmy4sZPuE8hXFa" name="iphone duo edit 4" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/i4QF9zqZdmy4sZPuE8hXFa.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>Google proved that a foldable could get an IP68 water and dust resistance rating with last year's <a href="https://www.tomsguide.com/phones/google-pixel-phones/pixel-10-pro-fold-review">Pixel 10 Pro Fold</a>. This means that, despite all the moving parts around the hinge, Google was able to seal the phone up and ensure dust and other foreign particles can't get inside. Apple continued that trend by also sealing the iPhone Duo up to the same IP68 standard.</p><p>Meanwhile the Galaxy Z Fold 8 is only rated to IP48. The 8 means that it's water-tight, capable of being submerged in up to a meter of water for up to 30 minutes — just like Google and Apple. However, the 4 means that the Z Fold 8 offers no protection against dust, or any other particles larger than one millimeter (0.04 inches).</p><p>In other words, there's a whole bunch of nasty stuff that could get inside the Z Fold 8 and cause problems — and you might not even realize it. In other words, you should be able to take the iPhone Duo to the beach.</p><h3 class="article-body__section" id="section-apple-pencil-support"><span>Apple Pencil support</span></h3><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="utmMc9q6LHmFEEaQK8rvhB" name="iPhone Duo apple pencil" alt="iPhone Duo with Apple Pencil" src="https://cdn.mos.cms.futurecdn.net/utmMc9q6LHmFEEaQK8rvhB.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: Apple)</span></figcaption></figure><p>Samsung used to sell foldables that supported the S Pen stylus, but the last one to be released was 2024's<a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-6-review-test-results"> Galaxy Z Fold 6.</a> From the <a href="https://www.tomsguide.com/phones/samsung-galaxy-z-fold-7-review">Z Fold 7 </a>onwards, Samsung stripped out the S Pen functionality, removing a critical part of the display makeup in order to reduce the phone's thickness. This means that the Z Fold 8 does not support any kind of active stylus. </p><p>Meanwhile, the <a href="https://www.tomsguide.com/phones/iphones/steve-jobs-said-there-would-never-be-an-iphone-stylus-but-iphone-duo-just-proved-him-wrong-and-itll-be-a-better-device-for-it">iPhone Duo not only offers stylus support</a>, it's compatible with the <a href="https://www.tomsguide.com/hands-on/apple-pencil-usb-c-hands-on-is-this-pen-mightier">Apple Pencil USB-C</a> — which works with the majority of iPads still on sale. Samsung needed a special kind of S Pen for the foldable screen, but the iPhone Duo uses a stylus that you may already have.</p><p>It's the most basic Apple stylus on sale, and it lacks key features you'll find on the <a href="https://www.tomsguide.com/tablets/ipads/apple-announces-apple-pencil-pro-with-barrel-roll-and-squeeze-capabilities">Apple Pencil Pro</a>, but it's better than nothing.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-exgNKX"></div>                            </div>                            <script src="https://kwizly.com/embed/exgNKX.js" async></script><h3 class="article-body__section" id="section-magsafe"><span>MagSafe</span></h3><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="UDr8c5DLF9rP5aXyr9NwQ5" name="iphone duo software" alt="iphone duo two apps" src="https://cdn.mos.cms.futurecdn.net/UDr8c5DLF9rP5aXyr9NwQ5.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>Magnetic wireless charging is a rarity, in part because Apple had a stranglehold on it for so long. While <a href="https://www.tomsguide.com/phones/what-is-qi2-wireless-charging">Qi2 wireless charging</a> does allow phones to add a MagSafe-style magnetic ring, <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s25-has-supports-qi2-charging-but-theres-a-big-catch">Samsung has avoided doing this </a>— preferring to utilize special magnetic cases instead. The Galaxy Z Fold 8 is no exception to this trend, despite offering all the other benefits of Qi2 charging.</p><p>Apple had no such issue adding <a href="https://www.tomsguide.com/phones/iphones/what-is-apple-magsafe-and-which-iphones-support-it">MagSafe</a> to the iPhone Duo, as it's done with virtually every iPhone released since the <a href="https://www.tomsguide.com/reviews/iphone-12">iPhone 12.</a> Plus, despite the phone's unique shape and size, Apple confirmed that it is compatible with MagSafe accessories and chargers  — meaning all your old MagSafe products should still fit.</p><h3 class="article-body__section" id="section-faster-60w-charging"><span>Faster 60W charging</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2144px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4oMko37sfDNte8KzjvzD2M" name="Apple iPhone Duo hands on-3" alt="Apple iPhone Duo shown in hand" src="https://cdn.mos.cms.futurecdn.net/4oMko37sfDNte8KzjvzD2M.jpg" mos="" align="middle" fullscreen="" width="2144" height="1206" 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>MagSafe isn't the only way iPhone Duo beats Z Fold 8 in the charging department. Apple's foldable also offers faster charging speeds, regardless of whether you use MagSafe or a plug-in charging cable.</p><p>Wired charging supports up to 60W speeds, which regains 50% charge in just 15 minutes. Meanwhile, wireless charging is capped at 25W. In comparison, the Galaxy Z Fold 8 offers 45W wired charging, and can regain 43% in 15 minutes. Wireless charging is also slightly slower at 20W, which puts it at a slight disadvantage to the iPhone.</p><h3 class="article-body__section" id="section-better-front-facing-camera-hardware"><span>Better front-facing camera hardware</span></h3><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="SoAi2j7o9Dqs6v288A4cEa" name="iPhone Duo edit 3" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/SoAi2j7o9Dqs6v288A4cEa.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>Like the S Pen, Samsung used to offer an <a href="https://www.tomsguide.com/news/samsung-galaxy-z-fold-3-under-display-camera-tested-its-amazing-and-flawed">under-display camera</a> on Galaxy Z Fold phones — and it hasn't been seen since the Galaxy Z Fold 6. The quality was not great, and it was no surprise that later Z folds switched back to the hole-punch camera design. Apple is giving under-display camera tech another chance at the limelight.</p><p>Apple hasn't specified the quality of this camera, noting that it's designed for use with FaceTime and other video calling software rather than selfies. That suggests the quality isn't great. But at least Apple is willing to try new things with the Duo, rather than reusing the same lackluster selfie camera hardware for multiple years in a row.</p><p>Plus, the iPhone Duo's actual selfie camera, which is in the cover display, offers higher resolution than Samsung. We're talking 12MP compared to 10MP, and while resolution doesn't automatically mean quality, it's likely that this is a similar selfie camera to the one in iPhone 17 Pro Max — <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">which I found to take better photos than the Galaxy Z Fold 8 Ultra.</a></p><h3 class="article-body__section" id="section-iphone-duo-software-reacts-based-on-folded-hinge-state"><span>iPhone Duo software reacts based on folded hinge state</span></h3><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="N49opwHV76RM3BfKvL8REa" name="iPhone duo edit 2" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/N49opwHV76RM3BfKvL8REa.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>A lot of Samsung phones offer what the company calls "Flex Mode," which allows the phone to react and adapt depending on the angle of the central hinge. Samsung Galaxy Z Fold 8 is the first Galaxy foldable to ditch this feature, despite the fact it's available on the Ultra model. This reduces the functionality of the phone somewhat, especially compared to iPhone Duo.</p><p>Apple doesn't have a special name for this feature, but the Duo does react depending on the angle of the hinge and the state of the fold itself. So if you have Netflix running, folding the screen to a 90-degree angle will shift the video to one side of the screen, and media controls to the other. </p><h3 class="article-body__section" id="section-vapor-chamber-cooling"><span>Vapor chamber cooling</span></h3><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="CN7RzmKPJyev7oUAf2fdFa" name="iPhone duo gaming" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/CN7RzmKPJyev7oUAf2fdFa.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 iPhone Duo offers an A20 Pro chipset with vapor chamber cooling, which helps dissipate heat. This means that the iPhone should offer better sustained performance, especially when doing resource-heavy tasks like gaming, multitasking and AI processing. </p><p>We haven't done any performance or thermal testing on the iPhone Duo just yet, so we don't know how effective the vapor chamber will be. That said, the Fold 8 doesn't offer a vapor chamber at all. </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/phones/iphones/apple-quietly-jacks-the-prices-of-the-iphone-16-iphone-17-and-iphone-air-heres-how-much-youll-pay-now"><strong>Apple quietly jacks the prices of the iPhone 16, iPhone 17, and iPhone Air — here's how much you'll pay now</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/phones/iphones/apples-just-extended-free-access-to-emergency-satellite-communication-for-another-year-its-the-third-time-this-has-happened"><strong>Apple's just extended free access to emergency satellite communication for another year — it's the third time this has happened</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/phones/iphones/steve-jobs-said-there-would-never-be-an-iphone-stylus-but-iphone-duo-just-proved-him-wrong-and-itll-be-a-better-device-for-it"><strong>Steve Jobs said there would never be an iPhone stylus but iPhone Duo just proved him wrong — and it'll be a better device for it</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-duo-vs-samsung-galaxy-z-fold-8-7-ways-apples-foldable-beats-its-rival-from-ip68-to-faster-charging-and-more</link>
                                                                            <description>
                            <![CDATA[ iPhone Duo may be the first Apple foldable, but it's already beating Samsung at its own game. Here are seven ways it beats the Galaxy Z Fold 8. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">YMufsSbjwum9vd5JjKhXUQ</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/NE3m4C3QUpw7U8uQfUAmea-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 11 Sep 2026 07:30:00 +0000</pubDate>                                                                                                                                <updated>Fri, 11 Sep 2026 14:22:10 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Samsung Phones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                    <category><![CDATA[Android Phones]]></category>
                                                                                                <author><![CDATA[ tom.pritchard@futurenet.com (Tom Pritchard) ]]></author>                    <dc:creator><![CDATA[ Tom Pritchard ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/biCewUkKfSA6QnT2HxVc3f.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/NE3m4C3QUpw7U8uQfUAmea-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[IPhone duo vs galaxy Z Fold 8]]></media:description>                                                            <media:text><![CDATA[IPhone duo vs galaxy Z Fold 8]]></media:text>
                                <media:title type="plain"><![CDATA[IPhone duo vs galaxy Z Fold 8]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/NE3m4C3QUpw7U8uQfUAmea-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The launch of <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo</a> is a big deal. This is the first ever foldable developed by Apple, and for that reason alone it has the chance to dethrone Samsung as the king of the foldable phone space. But it also helps that Apple has produced a phone with a lot of great qualities, and will naturally lead to comparisons with the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Samsung Galaxy Z Fold 8</a>.</p><p>The two phones are similar in a bunch of ways, including their wider, passport-inspired design. However, there are a number of key ways Apple has improved on the foldable design, and beaten Samsung at its own game. Considering this is Apple's first foldable, that might just make the extended development time worth it. Here are seven ways iPhone Duo actually beats the Galaxy Z Fold 8.</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-ip68-rating"><span>IP68 rating</span></h3><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="i4QF9zqZdmy4sZPuE8hXFa" name="iphone duo edit 4" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/i4QF9zqZdmy4sZPuE8hXFa.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>Google proved that a foldable could get an IP68 water and dust resistance rating with last year's <a href="https://www.tomsguide.com/phones/google-pixel-phones/pixel-10-pro-fold-review">Pixel 10 Pro Fold</a>. This means that, despite all the moving parts around the hinge, Google was able to seal the phone up and ensure dust and other foreign particles can't get inside. Apple continued that trend by also sealing the iPhone Duo up to the same IP68 standard.</p><p>Meanwhile the Galaxy Z Fold 8 is only rated to IP48. The 8 means that it's water-tight, capable of being submerged in up to a meter of water for up to 30 minutes — just like Google and Apple. However, the 4 means that the Z Fold 8 offers no protection against dust, or any other particles larger than one millimeter (0.04 inches).</p><p>In other words, there's a whole bunch of nasty stuff that could get inside the Z Fold 8 and cause problems — and you might not even realize it. In other words, you should be able to take the iPhone Duo to the beach.</p><h3 class="article-body__section" id="section-apple-pencil-support"><span>Apple Pencil support</span></h3><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="utmMc9q6LHmFEEaQK8rvhB" name="iPhone Duo apple pencil" alt="iPhone Duo with Apple Pencil" src="https://cdn.mos.cms.futurecdn.net/utmMc9q6LHmFEEaQK8rvhB.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: Apple)</span></figcaption></figure><p>Samsung used to sell foldables that supported the S Pen stylus, but the last one to be released was 2024's<a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-6-review-test-results"> Galaxy Z Fold 6.</a> From the <a href="https://www.tomsguide.com/phones/samsung-galaxy-z-fold-7-review">Z Fold 7 </a>onwards, Samsung stripped out the S Pen functionality, removing a critical part of the display makeup in order to reduce the phone's thickness. This means that the Z Fold 8 does not support any kind of active stylus. </p><p>Meanwhile, the <a href="https://www.tomsguide.com/phones/iphones/steve-jobs-said-there-would-never-be-an-iphone-stylus-but-iphone-duo-just-proved-him-wrong-and-itll-be-a-better-device-for-it">iPhone Duo not only offers stylus support</a>, it's compatible with the <a href="https://www.tomsguide.com/hands-on/apple-pencil-usb-c-hands-on-is-this-pen-mightier">Apple Pencil USB-C</a> — which works with the majority of iPads still on sale. Samsung needed a special kind of S Pen for the foldable screen, but the iPhone Duo uses a stylus that you may already have.</p><p>It's the most basic Apple stylus on sale, and it lacks key features you'll find on the <a href="https://www.tomsguide.com/tablets/ipads/apple-announces-apple-pencil-pro-with-barrel-roll-and-squeeze-capabilities">Apple Pencil Pro</a>, but it's better than nothing.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-exgNKX"></div>                            </div>                            <script src="https://kwizly.com/embed/exgNKX.js" async></script><h3 class="article-body__section" id="section-magsafe"><span>MagSafe</span></h3><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="UDr8c5DLF9rP5aXyr9NwQ5" name="iphone duo software" alt="iphone duo two apps" src="https://cdn.mos.cms.futurecdn.net/UDr8c5DLF9rP5aXyr9NwQ5.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>Magnetic wireless charging is a rarity, in part because Apple had a stranglehold on it for so long. While <a href="https://www.tomsguide.com/phones/what-is-qi2-wireless-charging">Qi2 wireless charging</a> does allow phones to add a MagSafe-style magnetic ring, <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s25-has-supports-qi2-charging-but-theres-a-big-catch">Samsung has avoided doing this </a>— preferring to utilize special magnetic cases instead. The Galaxy Z Fold 8 is no exception to this trend, despite offering all the other benefits of Qi2 charging.</p><p>Apple had no such issue adding <a href="https://www.tomsguide.com/phones/iphones/what-is-apple-magsafe-and-which-iphones-support-it">MagSafe</a> to the iPhone Duo, as it's done with virtually every iPhone released since the <a href="https://www.tomsguide.com/reviews/iphone-12">iPhone 12.</a> Plus, despite the phone's unique shape and size, Apple confirmed that it is compatible with MagSafe accessories and chargers  — meaning all your old MagSafe products should still fit.</p><h3 class="article-body__section" id="section-faster-60w-charging"><span>Faster 60W charging</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2144px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4oMko37sfDNte8KzjvzD2M" name="Apple iPhone Duo hands on-3" alt="Apple iPhone Duo shown in hand" src="https://cdn.mos.cms.futurecdn.net/4oMko37sfDNte8KzjvzD2M.jpg" mos="" align="middle" fullscreen="" width="2144" height="1206" 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>MagSafe isn't the only way iPhone Duo beats Z Fold 8 in the charging department. Apple's foldable also offers faster charging speeds, regardless of whether you use MagSafe or a plug-in charging cable.</p><p>Wired charging supports up to 60W speeds, which regains 50% charge in just 15 minutes. Meanwhile, wireless charging is capped at 25W. In comparison, the Galaxy Z Fold 8 offers 45W wired charging, and can regain 43% in 15 minutes. Wireless charging is also slightly slower at 20W, which puts it at a slight disadvantage to the iPhone.</p><h3 class="article-body__section" id="section-better-front-facing-camera-hardware"><span>Better front-facing camera hardware</span></h3><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="SoAi2j7o9Dqs6v288A4cEa" name="iPhone Duo edit 3" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/SoAi2j7o9Dqs6v288A4cEa.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>Like the S Pen, Samsung used to offer an <a href="https://www.tomsguide.com/news/samsung-galaxy-z-fold-3-under-display-camera-tested-its-amazing-and-flawed">under-display camera</a> on Galaxy Z Fold phones — and it hasn't been seen since the Galaxy Z Fold 6. The quality was not great, and it was no surprise that later Z folds switched back to the hole-punch camera design. Apple is giving under-display camera tech another chance at the limelight.</p><p>Apple hasn't specified the quality of this camera, noting that it's designed for use with FaceTime and other video calling software rather than selfies. That suggests the quality isn't great. But at least Apple is willing to try new things with the Duo, rather than reusing the same lackluster selfie camera hardware for multiple years in a row.</p><p>Plus, the iPhone Duo's actual selfie camera, which is in the cover display, offers higher resolution than Samsung. We're talking 12MP compared to 10MP, and while resolution doesn't automatically mean quality, it's likely that this is a similar selfie camera to the one in iPhone 17 Pro Max — <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">which I found to take better photos than the Galaxy Z Fold 8 Ultra.</a></p><h3 class="article-body__section" id="section-iphone-duo-software-reacts-based-on-folded-hinge-state"><span>iPhone Duo software reacts based on folded hinge state</span></h3><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="N49opwHV76RM3BfKvL8REa" name="iPhone duo edit 2" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/N49opwHV76RM3BfKvL8REa.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>A lot of Samsung phones offer what the company calls "Flex Mode," which allows the phone to react and adapt depending on the angle of the central hinge. Samsung Galaxy Z Fold 8 is the first Galaxy foldable to ditch this feature, despite the fact it's available on the Ultra model. This reduces the functionality of the phone somewhat, especially compared to iPhone Duo.</p><p>Apple doesn't have a special name for this feature, but the Duo does react depending on the angle of the hinge and the state of the fold itself. So if you have Netflix running, folding the screen to a 90-degree angle will shift the video to one side of the screen, and media controls to the other. </p><h3 class="article-body__section" id="section-vapor-chamber-cooling"><span>Vapor chamber cooling</span></h3><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="CN7RzmKPJyev7oUAf2fdFa" name="iPhone duo gaming" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/CN7RzmKPJyev7oUAf2fdFa.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 iPhone Duo offers an A20 Pro chipset with vapor chamber cooling, which helps dissipate heat. This means that the iPhone should offer better sustained performance, especially when doing resource-heavy tasks like gaming, multitasking and AI processing. </p><p>We haven't done any performance or thermal testing on the iPhone Duo just yet, so we don't know how effective the vapor chamber will be. That said, the Fold 8 doesn't offer a vapor chamber at all. </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/phones/iphones/apple-quietly-jacks-the-prices-of-the-iphone-16-iphone-17-and-iphone-air-heres-how-much-youll-pay-now"><strong>Apple quietly jacks the prices of the iPhone 16, iPhone 17, and iPhone Air — here's how much you'll pay now</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/phones/iphones/apples-just-extended-free-access-to-emergency-satellite-communication-for-another-year-its-the-third-time-this-has-happened"><strong>Apple's just extended free access to emergency satellite communication for another year — it's the third time this has happened</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/phones/iphones/steve-jobs-said-there-would-never-be-an-iphone-stylus-but-iphone-duo-just-proved-him-wrong-and-itll-be-a-better-device-for-it"><strong>Steve Jobs said there would never be an iPhone stylus but iPhone Duo just proved him wrong — and it'll be a better device for it</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple's $1,999 gamble — analysts react to the new iPhone Duo foldable ]]></title>
                                                                                                <dc:content><![CDATA[ <p>There’s no doubt about who the star of <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’s September 9 launch event</a> turned out to be. With new <a href="https://www.tomsguide.com/computing/macbooks/i-interviewed-john-ternus-right-before-he-was-named-apple-ceo-heres-the-5-quotes-that-stand-out-to-me">CEO John Ternus</a> reviving the company’s trademark “One More Thing…” announcement to show off the new <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>, analysts are agreed that Apple’s first attempt at a foldable phone is definitely one to watch.</p><p>Ben Wood, chief analyst at CCS Insight, said the Duo brings “a distinctive new design to the iPhone lineup.” In a research note released after the Apple event, IDC senior research director Nabila Popal said she was “almost certain [the Duo] will convert even the biggest critics of foldables.” And Michael Gartenberg, an analyst and former Apple marketing director, noted the foldable phone’s October release will open up a new opportunity for the company.</p><p>Arriving in stores October 23, the iPhone Duo is a passport-sized device that unfolds to reveal a 7.6-inch main display. Unlike some of the <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phones</a> already on the market, the Duo offers a wider layout and Apple Pencil support to go with the kind of features — a powerful A20 Pro system-on-chip and <a href="https://www.tomsguide.com/phones/iphones/ios-27-public-beta-hands-on-preview-the-new-siri-and-apple-intelligence-features-completely-changed-how-i-use-my-iphone">iOS 27</a> software support — that you’d expect from one of Apple’s phones. It also happens to be most significant addition to the iPhone lineup since the <a href="https://www.tomsguide.com/us/iphone-x,review-4800.html">iPhone X</a> introduced a new look to Apple’s offerings back in 2017.</p><div><blockquote><p>Despite being late to market compared to Samsung and Google, Apple has delivered a solid first generation of foldables.</p><p>Michael Gartenberg</p></blockquote></div><p>“While the new [iPhone 18] Pro devices are mostly incremental, the iPhone Duo takes Apple into new territory,” Gartenberg said. “Despite being late to market compared to Samsung and Google, Apple has delivered a solid first generation of foldables.”</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><h2 id="iphone-duo-what-impressed-analysts">iPhone Duo: What impressed analysts</h2><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="K4dYCSX4YtJxxvZCenRip9" name="iphone duo display" alt="iPhone Duo hands on display" src="https://cdn.mos.cms.futurecdn.net/K4dYCSX4YtJxxvZCenRip9.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>While the iPhone Duo has only appeared in an Apple keynote and, briefly, in a hands-on area following its debut, the phone has made a strong first impression with people who’ve seen it. And there are several aspects surrounding the Duo that are winning early raves.</p><p>Start with the screen, which Tom’s Guide Global Editor in Chief Mark Spoonauer described as “breathtaking” in his <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo hands-on</a>. Netflix — which has been optimized for the Duo’s design — takes up the whole screen when you’re streaming movies. And Apple has managed to minimize the crease that can appear on folding displays to the point where you don’t even notice it.</p><p>“The iPhone Duo has clearly benefited from major advances in the quality and reliability of flexible displays,” said Wood, who notes that Apple, like Samsung with its <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a> foldable, use a titanium plate beneath the display. But Wood notes there’s a key difference in the case of the Duo.</p><p>“A differentiator is the nano-texture finish on the display, previously featured on the MacBook Pro and Studio Display,” he added. “This will improve readability, particularly in bright light, and give the touch screen a smooth finish for finger gestures.”</p><p>Durability is always a concern among shoppers when it comes to foldable phones, even more so than it is with more conventional handsets. With foldables, you have two screens to worry about, not just one, and there’s also the hinge that handles opening and closing the device to keep in mind.</p><p>To that end, Apple is using grade 5 titanium for the iPhone Duo’s frame while Ceramic Shield 2 protects the front of the phone. (The back of the Duo uses an earlier version of Ceramic Shield.) IDC’s Popal calls the Duo “a solid device that looks and feels premium,” while noting that Apple’s foldable offers an IP68 rating for water and dust resistance. In contrast, the Galaxy Z Fold 8 can withstand a plunge into water, but it isn’t dust resistant like Apple’s foldable.</p><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="UDr8c5DLF9rP5aXyr9NwQ5" name="iphone duo software" alt="iphone duo two apps" src="https://cdn.mos.cms.futurecdn.net/UDr8c5DLF9rP5aXyr9NwQ5.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>Software also looks to be a big selling point for the iPhone Duo, highlighted by Apple redesigning its apps to take advantage of the foldable design. App controls and the dock on the home screen now live on the side of the display for easier access. In addition to Netflix, Zoom and Slack have been optimized for the Duo, with Wood expecting other app makers to follow suit after the phone launches in October.</p><p>“Unsurprisingly, the software on the iPhone Duo looks familiar and intuitive, with gesture-based navigation that makes it easy to do things like placing apps side by side,” Wood said. “Subtle features such as a screen transition as you flip the device open look very Apple-esque.”</p><h2 id="iphone-duo-price-is-a-concern">iPhone Duo: Price is a concern</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2144px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4QQN7JtKkmsE7V6tNMwe2M" name="Apple iPhone Duo hands on-2" alt="Apple iPhone Duo shown in hand" src="https://cdn.mos.cms.futurecdn.net/4QQN7JtKkmsE7V6tNMwe2M.jpg" mos="" align="middle" fullscreen="" width="2144" height="1206" 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>Still, a few things stand between the iPhone Duo and world domination, and the biggest one happens to be the cost of the phone. With a starting price of $1,999, this is the most expensive iPhone Apple sells — that’s even $300 more than what you’d pay for a <a href="https://www.tomsguide.com/computing/ipads/ipad-pro-m5-review">13-inch iPad Pro</a> with cellular connectivity.</p><p>“The price point will obviously keep things out of reach for some, but that's what financing and carrier incentives are for,” said Avi Greengart, president of Techsponential.</p><div><blockquote><p>The price point will obviously keep things out of reach for some, but that's what financing and carrier incentives are for</p><p>Avi Greengart</p></blockquote></div><p>Michael Gartenberg agreed: “Pricing is expensive, but very much in line with other vendors. A good deal will depend on carriers offering significant subsidies or how many users will pay $2,000-plus on a device over time with Apple's new installment plan.”</p><p>Ahead of iPhone Duo preorders starting on October 16, Apple lets you pay off the phone in 24 monthly installments of $83.29. Leasing the Duo through the Apple Upgrade program lowers the monthly payment to $57.99 (though you wouldn’t own the phone at the end of your lease agreement unless you paid the remaining balance). Those prices are before device trade-ins which figure to lower the size of the monthly payment even further.</p><h2 id="iphone-duo-taking-on-the-galaxy-z-fold-8">iPhone Duo: Taking on the Galaxy Z Fold 8</h2><p>Any iPhone Duo analysis is going to invite comparisons to the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a> — and to a lesser extent the more expensive <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> — that Samsung released earlier this year. “Samsung has a price advantage, but not enough of one that it's likely to be a major factor,” Greengart said.</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Apple iPhone Duo</strong></p></td><td  ><p><strong>Samsung Galaxy Z Fold 8</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$1,999</p></td><td  ><p>$1,899</p></td></tr><tr><td class="firstcol " ><p><strong>Main Display</strong></p></td><td  ><p>7.6 inches</p></td><td  ><p>7.6 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Outer display</strong></p></td><td  ><p>5.4 inches</p></td><td  ><p>5.5 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>A20 Pro</p></td><td  ><p>Snapdragon 8 Elite Gen 5 for Galaxy</p></td></tr><tr><td class="firstcol " ><p><strong>Memory</strong></p></td><td  ><p>12GB</p></td><td  ><p>12GB, 16GB</p></td></tr><tr><td class="firstcol " ><p><strong>Storage</strong></p></td><td  ><p>256GB, 512GB, 1TB, 2TB</p></td><td  ><p>256GB, 512GB, 1TB</p></td></tr><tr><td class="firstcol " ><p><strong>Rear Cameras</strong></p></td><td  ><p>48MP wide 48MP ultrawide</p></td><td  ><p>50MP wide, 50MP ultrawide</p></td></tr><tr><td class="firstcol " ><p><strong>Selfie Cameras</strong></p></td><td  ><p>24MP (main), 24MP (cover)</p></td><td  ><p>10MP (main), 10MP (cover)</p></td></tr><tr><td class="firstcol " ><p><strong>Size (opened)</strong></p></td><td  ><p>164.6 x 117.8 x 5.2mm (6.5 x 4.6 x 0.21 inches)</p></td><td  ><p>161.4 x 123.9 x 4.5 mm (6.4 x 4.9 x 0.18 inches)</p></td></tr><tr><td class="firstcol " ><p><strong>Size (closed)</strong></p></td><td  ><p>84.1 x 117.8 x 11.3mm (3.3 x 4.7 x 0.44 inches)</p></td><td  ><p>123.9 x 81.9 x 9.7 mm (4.88 × 3.22 × 0.38 inches)</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>254 grams (8.95 ounces)</p></td><td  ><p>201 grams (7.09 ounces)</p></td></tr><tr><td class="firstcol " ><p><strong>Software</strong></p></td><td  ><p>iOS 27</p></td><td  ><p>Android 17 (One UI 9)</p></td></tr><tr><td class="firstcol " ><p><strong>Colors</strong></p></td><td  ><p>Night Sky, Star White</p></td><td  ><p>Lavender, Graphite, Cream, Pistachio (online)</p></td></tr></tbody></table></div><p>Samsung has been at this a while, having released the first Fold back in 2019. That’s given Samsung a head start in not only building a market for foldable devices, but also fine-tuning its own product. The new Fold 8, for example, offers a more pocketable design than past offerings with improved battery life and a less noticeable crease than before.</p><p>In fact, at 9.7mm when closed and 205 grams, the Galaxy Z Fold 8 is thinner and lighter than the iPhone Duo, which measures at 11.3mm and weighs 254 grams. Samsung’s phone also offers a RAM upgrade, face unlocking and a <a href="https://www.tomsguide.com/phones/samsung-phones/i-just-tried-the-new-samsung-dex-on-the-galaxy-z-fold-8-and-it-has-one-huge-upgrade">desktop mode that lets you plug the Fold into a monitor and use it as a PC</a>. And as Greengart notes, the Galaxy Z Fold has an  $1,899 starting price compared to the iPhone Duo’s $1,999 cost.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-W2EK0e"></div>                            </div>                            <script src="https://kwizly.com/embed/W2EK0e.js" async></script><p>But Apple’s phone has a few advantages of its own, like the IP rating and Apple Pencil support. Other metric comparisons, like performance and battery life will have to wait until we get a chance to test Apple’s phone.</p><p>“Watching the keynote, it was easy to forget that surrounding these new products is the introduction of iOS 27,” Wood of CCS Insight said. “It's an important update, delivering major performance improvements and introducing the latest version of Apple Intelligence and Siri AI. These seem like a big step up from Apple’s earlier AI efforts, and based on my experience with the beta release, they're performing well.”</p><h2 id="iphone-duo-outlook">iPhone Duo outlook</h2><p>Foldable phones remains a small segment of the overall mobile market, though it’s growing — CCS Insight says that 25 million foldables sold in 2025, up 18% from the previous year. Wood anticipates growth this year and next, despite rising prices for memory and phone components. And the iPhone Duo’s arrival figures to be a big reason why.</p><p>“iPhone Duo is for anyone who has wanted a foldable but has not been willing to leave the iOS ecosystem, plus anyone who just wants a modern smartphone that opens up into a widescreen for watching content or multitasking,” Greengart said.</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/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><strong></strong></li><li><strong></strong><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 recap — Hands-on with the iPhone Duo and all the big announcements</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/phones/iphones/apples-just-extended-free-access-to-emergency-satellite-communication-for-another-year-its-the-third-time-this-has-happened"><strong>Apple's just extended free access to emergency satellite communication for another year — it's the third time this has happened</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/apples-usd1-999-gamble-analysts-react-to-the-new-iphone-duo-foldable</link>
                                                                            <description>
                            <![CDATA[ Analysts broadly praise the iPhone Duo for its refined hardware, crease-free display, and deep software integration, but there's also concern. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">nXhksdQEmQkjPqMV3ckaFf</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Mdj8kozN6J8WNXPhazFQFa-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 11 Sep 2026 04:30:00 +0000</pubDate>                                                                                                                                <updated>Fri, 11 Sep 2026 13:03:11 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                                    <dc:creator><![CDATA[ Philip Michaels ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/LBUqkHQCeeRgqR9Mz69X75.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/Mdj8kozN6J8WNXPhazFQFa-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Duo]]></media:description>                                                            <media:text><![CDATA[iPhone Duo]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Duo]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Mdj8kozN6J8WNXPhazFQFa-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>There’s no doubt about who the star of <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’s September 9 launch event</a> turned out to be. With new <a href="https://www.tomsguide.com/computing/macbooks/i-interviewed-john-ternus-right-before-he-was-named-apple-ceo-heres-the-5-quotes-that-stand-out-to-me">CEO John Ternus</a> reviving the company’s trademark “One More Thing…” announcement to show off the new <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>, analysts are agreed that Apple’s first attempt at a foldable phone is definitely one to watch.</p><p>Ben Wood, chief analyst at CCS Insight, said the Duo brings “a distinctive new design to the iPhone lineup.” In a research note released after the Apple event, IDC senior research director Nabila Popal said she was “almost certain [the Duo] will convert even the biggest critics of foldables.” And Michael Gartenberg, an analyst and former Apple marketing director, noted the foldable phone’s October release will open up a new opportunity for the company.</p><p>Arriving in stores October 23, the iPhone Duo is a passport-sized device that unfolds to reveal a 7.6-inch main display. Unlike some of the <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phones</a> already on the market, the Duo offers a wider layout and Apple Pencil support to go with the kind of features — a powerful A20 Pro system-on-chip and <a href="https://www.tomsguide.com/phones/iphones/ios-27-public-beta-hands-on-preview-the-new-siri-and-apple-intelligence-features-completely-changed-how-i-use-my-iphone">iOS 27</a> software support — that you’d expect from one of Apple’s phones. It also happens to be most significant addition to the iPhone lineup since the <a href="https://www.tomsguide.com/us/iphone-x,review-4800.html">iPhone X</a> introduced a new look to Apple’s offerings back in 2017.</p><div><blockquote><p>Despite being late to market compared to Samsung and Google, Apple has delivered a solid first generation of foldables.</p><p>Michael Gartenberg</p></blockquote></div><p>“While the new [iPhone 18] Pro devices are mostly incremental, the iPhone Duo takes Apple into new territory,” Gartenberg said. “Despite being late to market compared to Samsung and Google, Apple has delivered a solid first generation of foldables.”</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><h2 id="iphone-duo-what-impressed-analysts">iPhone Duo: What impressed analysts</h2><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="K4dYCSX4YtJxxvZCenRip9" name="iphone duo display" alt="iPhone Duo hands on display" src="https://cdn.mos.cms.futurecdn.net/K4dYCSX4YtJxxvZCenRip9.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>While the iPhone Duo has only appeared in an Apple keynote and, briefly, in a hands-on area following its debut, the phone has made a strong first impression with people who’ve seen it. And there are several aspects surrounding the Duo that are winning early raves.</p><p>Start with the screen, which Tom’s Guide Global Editor in Chief Mark Spoonauer described as “breathtaking” in his <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo hands-on</a>. Netflix — which has been optimized for the Duo’s design — takes up the whole screen when you’re streaming movies. And Apple has managed to minimize the crease that can appear on folding displays to the point where you don’t even notice it.</p><p>“The iPhone Duo has clearly benefited from major advances in the quality and reliability of flexible displays,” said Wood, who notes that Apple, like Samsung with its <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a> foldable, use a titanium plate beneath the display. But Wood notes there’s a key difference in the case of the Duo.</p><p>“A differentiator is the nano-texture finish on the display, previously featured on the MacBook Pro and Studio Display,” he added. “This will improve readability, particularly in bright light, and give the touch screen a smooth finish for finger gestures.”</p><p>Durability is always a concern among shoppers when it comes to foldable phones, even more so than it is with more conventional handsets. With foldables, you have two screens to worry about, not just one, and there’s also the hinge that handles opening and closing the device to keep in mind.</p><p>To that end, Apple is using grade 5 titanium for the iPhone Duo’s frame while Ceramic Shield 2 protects the front of the phone. (The back of the Duo uses an earlier version of Ceramic Shield.) IDC’s Popal calls the Duo “a solid device that looks and feels premium,” while noting that Apple’s foldable offers an IP68 rating for water and dust resistance. In contrast, the Galaxy Z Fold 8 can withstand a plunge into water, but it isn’t dust resistant like Apple’s foldable.</p><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="UDr8c5DLF9rP5aXyr9NwQ5" name="iphone duo software" alt="iphone duo two apps" src="https://cdn.mos.cms.futurecdn.net/UDr8c5DLF9rP5aXyr9NwQ5.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>Software also looks to be a big selling point for the iPhone Duo, highlighted by Apple redesigning its apps to take advantage of the foldable design. App controls and the dock on the home screen now live on the side of the display for easier access. In addition to Netflix, Zoom and Slack have been optimized for the Duo, with Wood expecting other app makers to follow suit after the phone launches in October.</p><p>“Unsurprisingly, the software on the iPhone Duo looks familiar and intuitive, with gesture-based navigation that makes it easy to do things like placing apps side by side,” Wood said. “Subtle features such as a screen transition as you flip the device open look very Apple-esque.”</p><h2 id="iphone-duo-price-is-a-concern">iPhone Duo: Price is a concern</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2144px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4QQN7JtKkmsE7V6tNMwe2M" name="Apple iPhone Duo hands on-2" alt="Apple iPhone Duo shown in hand" src="https://cdn.mos.cms.futurecdn.net/4QQN7JtKkmsE7V6tNMwe2M.jpg" mos="" align="middle" fullscreen="" width="2144" height="1206" 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>Still, a few things stand between the iPhone Duo and world domination, and the biggest one happens to be the cost of the phone. With a starting price of $1,999, this is the most expensive iPhone Apple sells — that’s even $300 more than what you’d pay for a <a href="https://www.tomsguide.com/computing/ipads/ipad-pro-m5-review">13-inch iPad Pro</a> with cellular connectivity.</p><p>“The price point will obviously keep things out of reach for some, but that's what financing and carrier incentives are for,” said Avi Greengart, president of Techsponential.</p><div><blockquote><p>The price point will obviously keep things out of reach for some, but that's what financing and carrier incentives are for</p><p>Avi Greengart</p></blockquote></div><p>Michael Gartenberg agreed: “Pricing is expensive, but very much in line with other vendors. A good deal will depend on carriers offering significant subsidies or how many users will pay $2,000-plus on a device over time with Apple's new installment plan.”</p><p>Ahead of iPhone Duo preorders starting on October 16, Apple lets you pay off the phone in 24 monthly installments of $83.29. Leasing the Duo through the Apple Upgrade program lowers the monthly payment to $57.99 (though you wouldn’t own the phone at the end of your lease agreement unless you paid the remaining balance). Those prices are before device trade-ins which figure to lower the size of the monthly payment even further.</p><h2 id="iphone-duo-taking-on-the-galaxy-z-fold-8">iPhone Duo: Taking on the Galaxy Z Fold 8</h2><p>Any iPhone Duo analysis is going to invite comparisons to the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a> — and to a lesser extent the more expensive <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> — that Samsung released earlier this year. “Samsung has a price advantage, but not enough of one that it's likely to be a major factor,” Greengart said.</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Apple iPhone Duo</strong></p></td><td  ><p><strong>Samsung Galaxy Z Fold 8</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$1,999</p></td><td  ><p>$1,899</p></td></tr><tr><td class="firstcol " ><p><strong>Main Display</strong></p></td><td  ><p>7.6 inches</p></td><td  ><p>7.6 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Outer display</strong></p></td><td  ><p>5.4 inches</p></td><td  ><p>5.5 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>A20 Pro</p></td><td  ><p>Snapdragon 8 Elite Gen 5 for Galaxy</p></td></tr><tr><td class="firstcol " ><p><strong>Memory</strong></p></td><td  ><p>12GB</p></td><td  ><p>12GB, 16GB</p></td></tr><tr><td class="firstcol " ><p><strong>Storage</strong></p></td><td  ><p>256GB, 512GB, 1TB, 2TB</p></td><td  ><p>256GB, 512GB, 1TB</p></td></tr><tr><td class="firstcol " ><p><strong>Rear Cameras</strong></p></td><td  ><p>48MP wide 48MP ultrawide</p></td><td  ><p>50MP wide, 50MP ultrawide</p></td></tr><tr><td class="firstcol " ><p><strong>Selfie Cameras</strong></p></td><td  ><p>24MP (main), 24MP (cover)</p></td><td  ><p>10MP (main), 10MP (cover)</p></td></tr><tr><td class="firstcol " ><p><strong>Size (opened)</strong></p></td><td  ><p>164.6 x 117.8 x 5.2mm (6.5 x 4.6 x 0.21 inches)</p></td><td  ><p>161.4 x 123.9 x 4.5 mm (6.4 x 4.9 x 0.18 inches)</p></td></tr><tr><td class="firstcol " ><p><strong>Size (closed)</strong></p></td><td  ><p>84.1 x 117.8 x 11.3mm (3.3 x 4.7 x 0.44 inches)</p></td><td  ><p>123.9 x 81.9 x 9.7 mm (4.88 × 3.22 × 0.38 inches)</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>254 grams (8.95 ounces)</p></td><td  ><p>201 grams (7.09 ounces)</p></td></tr><tr><td class="firstcol " ><p><strong>Software</strong></p></td><td  ><p>iOS 27</p></td><td  ><p>Android 17 (One UI 9)</p></td></tr><tr><td class="firstcol " ><p><strong>Colors</strong></p></td><td  ><p>Night Sky, Star White</p></td><td  ><p>Lavender, Graphite, Cream, Pistachio (online)</p></td></tr></tbody></table></div><p>Samsung has been at this a while, having released the first Fold back in 2019. That’s given Samsung a head start in not only building a market for foldable devices, but also fine-tuning its own product. The new Fold 8, for example, offers a more pocketable design than past offerings with improved battery life and a less noticeable crease than before.</p><p>In fact, at 9.7mm when closed and 205 grams, the Galaxy Z Fold 8 is thinner and lighter than the iPhone Duo, which measures at 11.3mm and weighs 254 grams. Samsung’s phone also offers a RAM upgrade, face unlocking and a <a href="https://www.tomsguide.com/phones/samsung-phones/i-just-tried-the-new-samsung-dex-on-the-galaxy-z-fold-8-and-it-has-one-huge-upgrade">desktop mode that lets you plug the Fold into a monitor and use it as a PC</a>. And as Greengart notes, the Galaxy Z Fold has an  $1,899 starting price compared to the iPhone Duo’s $1,999 cost.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-W2EK0e"></div>                            </div>                            <script src="https://kwizly.com/embed/W2EK0e.js" async></script><p>But Apple’s phone has a few advantages of its own, like the IP rating and Apple Pencil support. Other metric comparisons, like performance and battery life will have to wait until we get a chance to test Apple’s phone.</p><p>“Watching the keynote, it was easy to forget that surrounding these new products is the introduction of iOS 27,” Wood of CCS Insight said. “It's an important update, delivering major performance improvements and introducing the latest version of Apple Intelligence and Siri AI. These seem like a big step up from Apple’s earlier AI efforts, and based on my experience with the beta release, they're performing well.”</p><h2 id="iphone-duo-outlook">iPhone Duo outlook</h2><p>Foldable phones remains a small segment of the overall mobile market, though it’s growing — CCS Insight says that 25 million foldables sold in 2025, up 18% from the previous year. Wood anticipates growth this year and next, despite rising prices for memory and phone components. And the iPhone Duo’s arrival figures to be a big reason why.</p><p>“iPhone Duo is for anyone who has wanted a foldable but has not been willing to leave the iOS ecosystem, plus anyone who just wants a modern smartphone that opens up into a widescreen for watching content or multitasking,” Greengart said.</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/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><strong></strong></li><li><strong></strong><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 recap — Hands-on with the iPhone Duo and all the big announcements</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/phones/iphones/apples-just-extended-free-access-to-emergency-satellite-communication-for-another-year-its-the-third-time-this-has-happened"><strong>Apple's just extended free access to emergency satellite communication for another year — it's the third time this has happened</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I interviewed Apple CEO John Ternus on the making of the iPhone Duo — here's what made him say 'yes, that's it' ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple’s first <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">foldable phone</a> is finally coming in the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo</a>, and like most other Apple products, the company is famously late entering a new category. Yup, Samsung, Google, Huawei and others have been making foldables for several years, but Apple is adamant that it’s not chasing the Android competition.</p><p>While the iPhone Duo has a passport-style design like the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a>, in a lot of ways the phones couldn’t be more different. The Duo completely reimagines <a href="https://www.tomsguide.com/phones/iphones/ios-27-public-beta-hands-on-preview-the-new-siri-and-apple-intelligence-features-completely-changed-how-i-use-my-iphone">iOS 27</a> for the foldable form factor; it has Apple Pencil support and IP68 durability; and Apple is making a huge push to have lots of apps optimized for the Duo’s big 7.6-inch screen before the phone goes on sale in October.</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/uJKt432tWM4" allowfullscreen></iframe></div></div><p>Along with TechRadar’s Lance Ulanoff, I sat down with Apple CEO John Ternus and senior vice president of worldwide marketing Greg ‘Joz’ Joswiak, and they stressed that Apple is making something truly unique.</p><p>“I think for us, it's always about when do we feel like we have a product idea that meets our bar for quality and durability but also design?” Ternus said. “What I think is particularly amazing about the Duo is that it's such a good example of hardware and software coming together to make something really special.”</p><p>That’s exactly what I wanted to dig into with Ternus and Joz: What really makes the iPhone Duo special in a sea of foldables? </p><h2 id="iphone-duo-the-a-ha-moment-for-apple-s-ceo">iPhone Duo: The ‘a-ha’ moment for Apple’s CEO</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1802px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="ENFN2u4hpSYiQYfbA6WbcL" name="Apple iPhone Duo hands on-4" alt="Apple iPhone Duo shown in hand" src="https://cdn.mos.cms.futurecdn.net/ENFN2u4hpSYiQYfbA6WbcL.jpg" mos="" align="middle" fullscreen="" width="1802" height="1014" 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>One of the things that struck me most during my <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice"><u>hands-on time with the iPhone Duo</u></a> is that you can barely see the crease. And that’s thanks in large part to Apple’s nano-texture display. </p><p>The technology first appeared on the Mac Studio Display but has since migrated to the <a href="https://www.tomsguide.com/computing/ipads/ipad-pro-m5-review">iPad Pro</a> and <a href="https://www.tomsguide.com/computing/macbooks/the-new-macbook-pro-m4-is-a-game-changer-for-how-i-work-and-it-has-nothing-to-do-with-apple-intelligence">MacBook Pro</a>.</p><p>This nano-texture finish is designed to reduce glare and reflections, and the matte surface minimizes crease visibility. I also couldn’t feel the crease when using the Duo.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:33.28%;"><img id="5aML3J8mGVPRkeFAPUmS85" name="Apple-feature-PQ_Ternus2" alt="Apple CEO John Ternus" src="https://cdn.mos.cms.futurecdn.net/5aML3J8mGVPRkeFAPUmS85.png" mos="" align="middle" fullscreen="" width="2560" height="852" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide/Getty)</span></figcaption></figure><p>When Ternus saw this technology in action for the first time on Apple’s foldable prototype, he was convinced it was the right direction.</p><p>“It was like, ‘yes, that's it.’ ‘This is what I want. And then once we have that, then it's like okay, how do we go make it happen and make it real?’</p><p>Ternus shared that Apple came up with a new way of making the nano-texture display so that it’s optimized for a polymer surface instead of glass. </p><p>“I think what you've seen out there are all these just kind of cheap feeling plastic surfaces that don't feel good to the touch,” Ternus said. They're kind of wavy wrinkly, and the nano texture just wipes that all out. It's beautifully flat. It feels amazing to touch, and it's incredibly durable.”</p><h2 id="iphone-duo-vs-android-foldables">iPhone Duo vs Android foldables</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="fd7Kxymcum9UffZNVnDaJg" name="Apple iPhone Duo hands on-5" alt="Apple's John Ternus and Greg Joswiak sit down with Tom's Guide to discuss the new Apple iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/fd7Kxymcum9UffZNVnDaJg.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Apple's John Ternus and Greg Joswiak sit down with Tom's Guide to discuss the new iPhone Duo foldable </span><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>As impressive as Android foldable phones have become over the past few years, especially in terms of sheer thinness and lightness, the Android ecosystem is still pretty fragmented when it comes to apps.</p><p>For example, Slack just looks like a blown-up phone app on Android foldables, and pulling up comments on Instagram just covers the content. I don’t get the sense that this is going to be the case with the iPhone Duo.</p><p>Apple has been working behind the scenes with developers to optimize their apps for the iPhone Duo’s cover and main displays. This includes Netflix, Slack and Zoom.</p><p>“What we saw others doing wasn't particularly inspiring,” said Joz. “Our history has never been to rush into something with something half baked.”</p><p>So what does a fully baked iPhone Duo look like? </p><p>This includes a redesigned software experience that moves the main controls to the right edge of the screen so that they’re easier to reach. And this is for both displays.</p><p>“It turns out to be an incredibly intuitive control system, because it's there under your right thumb when it's closed,” said Ternus. “You open it up, it's there under your right thumb again. So I think that's one of the biggest things with iOS is you're going to have two screens. How do you make sure that it feels continuous?”</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:33.28%;"><img id="iXqvqh7cBFZZUNNvPKcLRT" name="Apple-feature-PQ_Joz1" alt="Quote from Apple VP Greg Joswiak" src="https://cdn.mos.cms.futurecdn.net/iXqvqh7cBFZZUNNvPKcLRT.png" mos="" align="middle" fullscreen="" width="2560" height="852" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide/Getty)</span></figcaption></figure><p>I asked explicitly about whether the October 23 release date for the iPhone Duo will help ensure Apple has enough optimized apps for launch. And Joz likened the launch to the original iPad.</p><p>“That’s why we went so out of our way with iPad development, both internally and with our third parties,” Joz said. “We didn't want the iPad to feel like a big phone and that's again exactly what Android tablets felt like. And the same thing applies here.”</p><h2 id="iphone-stylus-breaking-apple-s-rules">iPhone + stylus = breaking Apple’s rules?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2297px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="g8hRHytY7NFuF8mBGUagyL" name="Apple iPhone Duo hands on" alt="Apple iPhone Duo shown in hand" src="https://cdn.mos.cms.futurecdn.net/g8hRHytY7NFuF8mBGUagyL.jpg" mos="" align="middle" fullscreen="" width="2297" height="1292" 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>Steve Jobs famously said that “if you see a stylus, they blew it’ in reference to smartphones. But that was 2007. </p><p>So is Apple breaking its own rules by offering Apple Pencil support in the iPhone Duo? Not really. Because it’s an iPhone and iPad in one device.</p><p>“I’ve never really thought of it as a rule,” Ternus said. “We started with iPad. There was no Apple Pencil, right? But then there's things you can do with a pencil on that larger screen that are really powerful and capable. And I think we saw that opportunity here. </p><p>“You don't need a pencil, but I think some people are going to like it, and it's going to be fun.”</p><h2 id="the-2-000-question">The $2,000 question</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2144px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4QQN7JtKkmsE7V6tNMwe2M" name="Apple iPhone Duo hands on-2" alt="Apple iPhone Duo shown in hand" src="https://cdn.mos.cms.futurecdn.net/4QQN7JtKkmsE7V6tNMwe2M.jpg" mos="" align="middle" fullscreen="" width="2144" height="1206" 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 a starting price of $1,999, the iPhone Duo is by far the most expensive iPhone ever, so I wanted to know how Apple is going to justify the premium.</p><p>“We're always focused on building cool things that people love, but also are a really good value,” Ternus said. “And (the iPhone Duo) is an incredibly complex and well-engineered device. Yes, it's more expensive than the other phones, but we think it's a great value.”</p><p>At the same time, the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-hands-on-sneaky-awesome-upgrades-but-worth-the-price-hike">iPhone 18 Pro and iPhone 18 Pro Max</a> have also gone up in price by $100 each. But Apple insists that the new Pro phones deliver. This includes a new variable aperture camera, faster <a href="https://www.tomsguide.com/phones/iphones/apple-a20-pro-chip-why-its-such-a-big-deal-for-the-iphone-ultra-and-iphone-18-pro-max">A20 Pro chip</a> (that’s also in the iPhone Duo), bigger vapor chamber and even longer battery life.</p><p>“I look at those products as, ‘Man, how do you really feed an iPhone 17 Pro steroids and take not just an incremental improvement in each of these areas but massive year-on-year improvements,” Jozwiak asks.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:33.28%;"><img id="uLUGrvsxWyUBSMPaVJVpQT" name="Apple-feature-PQ_Ternus1" alt="Quote from Apple CEO John Ternus" src="https://cdn.mos.cms.futurecdn.net/uLUGrvsxWyUBSMPaVJVpQT.png" mos="" align="middle" fullscreen="" width="2560" height="852" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide/Getty)</span></figcaption></figure><p>Ultimately, though, all eyes will be on the Duo because it’s the shiny new thing. And it’s the experiences that it enables that Apple is hoping will get foldable phone doubters off the fence. For example, the Smart Take camera mode lets you prop up the Duo and is intelligent enough to snap photos when everyone is in position in a group shot — no timer required.</p><p>“The beauty of Apple is its hardware, software, and services,” Ternus said. “What I love is when all of these things come together and interact and create an experience that is just bigger than the sum of its parts.”</p><p><strong>NEXT: Watch part 2 of our interview with Turnus and Joz on TechRadar.</strong></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/HWg75OAmJLc" allowfullscreen></iframe></div></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/interview-apple-ceo-john-ternus-on-his-defining-moment-for-the-iphone-duo</link>
                                                                            <description>
                            <![CDATA[ I spoke with Apple CEO John Ternus and SVP of worldwide marketing Greg ‘Joz’ Joswiak about the iPhone Duo and what Apple is doing to stand out in a sea of established Android foldables. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">Bdp4Yc4gTZq4KFyiETLJN5</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/QnvxRM3sKN53UTet25jkZS-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 10 Sep 2026 21:40:52 +0000</pubDate>                                                                                                                                <updated>Fri, 11 Sep 2026 12:01:27 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                                    <dc:creator><![CDATA[ Mark Spoonauer ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/wtAspSzVfcKLB4JEd39AMo.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Mark Spoonauer is the global editor in chief of Tom&#039;s Guide and has covered technology for over 20 years. He oversees the direction of Tom&#039;s Guide and leads a team of over 25 journalists to bring you our expert buying guides, reviews, news, how-to articles, deals and other coverage.&lt;/p&gt;&lt;p&gt;Mark has a passion for covering all things mobile, having reviewed dozens of smartphones and other gadgets. He enjoys testing the top mobile devices and putting them up against each other in our in-depth face-offs. He also works hand in hand with our editors and testing team to continually improve how we evaluate products. &lt;/p&gt;&lt;p&gt;Having led Tom&#039;s Guide since 2013, Mark has focused on growing the core tech coverage of the site while also expanding into new areas, such as entertainment, fitness and home, recruiting talented writers and editors to help our readers figure out what to buy and how to get the most out of the products and services they use every day. &lt;/p&gt;&lt;p&gt;Mark has spoken at key industry events and appears regularly on TV to discuss the latest trends, including &lt;a href=&quot;https://cheddar.com/media/pixel-watch-gets-a-release-date-at-google-i-o-2022&quot;&gt;Cheddar&lt;/a&gt;, Fox 5, &lt;a href=&quot;https://www.foxbusiness.com/technology/apple-march-event-5g-iphone&quot;&gt;Fox Business&lt;/a&gt; and other outlets. Mark was previously editor in chief of Laptop Mag, and his work has appeared in Wired, Popular Science and Inc. Follow him on Twitter at @mspoonauer.&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/QnvxRM3sKN53UTet25jkZS-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple executives John Ternus and Greg Joswiak]]></media:description>                                                            <media:text><![CDATA[Apple executives John Ternus and Greg Joswiak]]></media:text>
                                <media:title type="plain"><![CDATA[Apple executives John Ternus and Greg Joswiak]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/QnvxRM3sKN53UTet25jkZS-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple’s first <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">foldable phone</a> is finally coming in the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo</a>, and like most other Apple products, the company is famously late entering a new category. Yup, Samsung, Google, Huawei and others have been making foldables for several years, but Apple is adamant that it’s not chasing the Android competition.</p><p>While the iPhone Duo has a passport-style design like the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a>, in a lot of ways the phones couldn’t be more different. The Duo completely reimagines <a href="https://www.tomsguide.com/phones/iphones/ios-27-public-beta-hands-on-preview-the-new-siri-and-apple-intelligence-features-completely-changed-how-i-use-my-iphone">iOS 27</a> for the foldable form factor; it has Apple Pencil support and IP68 durability; and Apple is making a huge push to have lots of apps optimized for the Duo’s big 7.6-inch screen before the phone goes on sale in October.</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/uJKt432tWM4" allowfullscreen></iframe></div></div><p>Along with TechRadar’s Lance Ulanoff, I sat down with Apple CEO John Ternus and senior vice president of worldwide marketing Greg ‘Joz’ Joswiak, and they stressed that Apple is making something truly unique.</p><p>“I think for us, it's always about when do we feel like we have a product idea that meets our bar for quality and durability but also design?” Ternus said. “What I think is particularly amazing about the Duo is that it's such a good example of hardware and software coming together to make something really special.”</p><p>That’s exactly what I wanted to dig into with Ternus and Joz: What really makes the iPhone Duo special in a sea of foldables? </p><h2 id="iphone-duo-the-a-ha-moment-for-apple-s-ceo">iPhone Duo: The ‘a-ha’ moment for Apple’s CEO</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1802px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="ENFN2u4hpSYiQYfbA6WbcL" name="Apple iPhone Duo hands on-4" alt="Apple iPhone Duo shown in hand" src="https://cdn.mos.cms.futurecdn.net/ENFN2u4hpSYiQYfbA6WbcL.jpg" mos="" align="middle" fullscreen="" width="1802" height="1014" 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>One of the things that struck me most during my <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice"><u>hands-on time with the iPhone Duo</u></a> is that you can barely see the crease. And that’s thanks in large part to Apple’s nano-texture display. </p><p>The technology first appeared on the Mac Studio Display but has since migrated to the <a href="https://www.tomsguide.com/computing/ipads/ipad-pro-m5-review">iPad Pro</a> and <a href="https://www.tomsguide.com/computing/macbooks/the-new-macbook-pro-m4-is-a-game-changer-for-how-i-work-and-it-has-nothing-to-do-with-apple-intelligence">MacBook Pro</a>.</p><p>This nano-texture finish is designed to reduce glare and reflections, and the matte surface minimizes crease visibility. I also couldn’t feel the crease when using the Duo.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:33.28%;"><img id="5aML3J8mGVPRkeFAPUmS85" name="Apple-feature-PQ_Ternus2" alt="Apple CEO John Ternus" src="https://cdn.mos.cms.futurecdn.net/5aML3J8mGVPRkeFAPUmS85.png" mos="" align="middle" fullscreen="" width="2560" height="852" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide/Getty)</span></figcaption></figure><p>When Ternus saw this technology in action for the first time on Apple’s foldable prototype, he was convinced it was the right direction.</p><p>“It was like, ‘yes, that's it.’ ‘This is what I want. And then once we have that, then it's like okay, how do we go make it happen and make it real?’</p><p>Ternus shared that Apple came up with a new way of making the nano-texture display so that it’s optimized for a polymer surface instead of glass. </p><p>“I think what you've seen out there are all these just kind of cheap feeling plastic surfaces that don't feel good to the touch,” Ternus said. They're kind of wavy wrinkly, and the nano texture just wipes that all out. It's beautifully flat. It feels amazing to touch, and it's incredibly durable.”</p><h2 id="iphone-duo-vs-android-foldables">iPhone Duo vs Android foldables</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="fd7Kxymcum9UffZNVnDaJg" name="Apple iPhone Duo hands on-5" alt="Apple's John Ternus and Greg Joswiak sit down with Tom's Guide to discuss the new Apple iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/fd7Kxymcum9UffZNVnDaJg.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">Apple's John Ternus and Greg Joswiak sit down with Tom's Guide to discuss the new iPhone Duo foldable </span><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>As impressive as Android foldable phones have become over the past few years, especially in terms of sheer thinness and lightness, the Android ecosystem is still pretty fragmented when it comes to apps.</p><p>For example, Slack just looks like a blown-up phone app on Android foldables, and pulling up comments on Instagram just covers the content. I don’t get the sense that this is going to be the case with the iPhone Duo.</p><p>Apple has been working behind the scenes with developers to optimize their apps for the iPhone Duo’s cover and main displays. This includes Netflix, Slack and Zoom.</p><p>“What we saw others doing wasn't particularly inspiring,” said Joz. “Our history has never been to rush into something with something half baked.”</p><p>So what does a fully baked iPhone Duo look like? </p><p>This includes a redesigned software experience that moves the main controls to the right edge of the screen so that they’re easier to reach. And this is for both displays.</p><p>“It turns out to be an incredibly intuitive control system, because it's there under your right thumb when it's closed,” said Ternus. “You open it up, it's there under your right thumb again. So I think that's one of the biggest things with iOS is you're going to have two screens. How do you make sure that it feels continuous?”</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:33.28%;"><img id="iXqvqh7cBFZZUNNvPKcLRT" name="Apple-feature-PQ_Joz1" alt="Quote from Apple VP Greg Joswiak" src="https://cdn.mos.cms.futurecdn.net/iXqvqh7cBFZZUNNvPKcLRT.png" mos="" align="middle" fullscreen="" width="2560" height="852" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide/Getty)</span></figcaption></figure><p>I asked explicitly about whether the October 23 release date for the iPhone Duo will help ensure Apple has enough optimized apps for launch. And Joz likened the launch to the original iPad.</p><p>“That’s why we went so out of our way with iPad development, both internally and with our third parties,” Joz said. “We didn't want the iPad to feel like a big phone and that's again exactly what Android tablets felt like. And the same thing applies here.”</p><h2 id="iphone-stylus-breaking-apple-s-rules">iPhone + stylus = breaking Apple’s rules?</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2297px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="g8hRHytY7NFuF8mBGUagyL" name="Apple iPhone Duo hands on" alt="Apple iPhone Duo shown in hand" src="https://cdn.mos.cms.futurecdn.net/g8hRHytY7NFuF8mBGUagyL.jpg" mos="" align="middle" fullscreen="" width="2297" height="1292" 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>Steve Jobs famously said that “if you see a stylus, they blew it’ in reference to smartphones. But that was 2007. </p><p>So is Apple breaking its own rules by offering Apple Pencil support in the iPhone Duo? Not really. Because it’s an iPhone and iPad in one device.</p><p>“I’ve never really thought of it as a rule,” Ternus said. “We started with iPad. There was no Apple Pencil, right? But then there's things you can do with a pencil on that larger screen that are really powerful and capable. And I think we saw that opportunity here. </p><p>“You don't need a pencil, but I think some people are going to like it, and it's going to be fun.”</p><h2 id="the-2-000-question">The $2,000 question</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2144px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4QQN7JtKkmsE7V6tNMwe2M" name="Apple iPhone Duo hands on-2" alt="Apple iPhone Duo shown in hand" src="https://cdn.mos.cms.futurecdn.net/4QQN7JtKkmsE7V6tNMwe2M.jpg" mos="" align="middle" fullscreen="" width="2144" height="1206" 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 a starting price of $1,999, the iPhone Duo is by far the most expensive iPhone ever, so I wanted to know how Apple is going to justify the premium.</p><p>“We're always focused on building cool things that people love, but also are a really good value,” Ternus said. “And (the iPhone Duo) is an incredibly complex and well-engineered device. Yes, it's more expensive than the other phones, but we think it's a great value.”</p><p>At the same time, the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-hands-on-sneaky-awesome-upgrades-but-worth-the-price-hike">iPhone 18 Pro and iPhone 18 Pro Max</a> have also gone up in price by $100 each. But Apple insists that the new Pro phones deliver. This includes a new variable aperture camera, faster <a href="https://www.tomsguide.com/phones/iphones/apple-a20-pro-chip-why-its-such-a-big-deal-for-the-iphone-ultra-and-iphone-18-pro-max">A20 Pro chip</a> (that’s also in the iPhone Duo), bigger vapor chamber and even longer battery life.</p><p>“I look at those products as, ‘Man, how do you really feed an iPhone 17 Pro steroids and take not just an incremental improvement in each of these areas but massive year-on-year improvements,” Jozwiak asks.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:33.28%;"><img id="uLUGrvsxWyUBSMPaVJVpQT" name="Apple-feature-PQ_Ternus1" alt="Quote from Apple CEO John Ternus" src="https://cdn.mos.cms.futurecdn.net/uLUGrvsxWyUBSMPaVJVpQT.png" mos="" align="middle" fullscreen="" width="2560" height="852" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide/Getty)</span></figcaption></figure><p>Ultimately, though, all eyes will be on the Duo because it’s the shiny new thing. And it’s the experiences that it enables that Apple is hoping will get foldable phone doubters off the fence. For example, the Smart Take camera mode lets you prop up the Duo and is intelligent enough to snap photos when everyone is in position in a group shot — no timer required.</p><p>“The beauty of Apple is its hardware, software, and services,” Ternus said. “What I love is when all of these things come together and interact and create an experience that is just bigger than the sum of its parts.”</p><p><strong>NEXT: Watch part 2 of our interview with Turnus and Joz on TechRadar.</strong></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/HWg75OAmJLc" allowfullscreen></iframe></div></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ The iPhone 18 Pro may be faster but it also comes with a potential battery downgrade ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-hands-on-sneaky-awesome-upgrades-but-worth-the-price-hike">iPhone 18 Pro and iPhone 18 Pro Max </a>are finally here. Surprisingly, there is still information we don't know yet, including battery size (something Apple doesn't share) and how much better the A20 Pro chipset is compared to the A19 series.</p><p>Two different leaks may have given us some of that information. The first is a new <a href="https://browser.geekbench.com/v6/cpu/19143100" target="_blank">Geekbench listing</a> that appears to show how the A20 Pro works in the iPhone 18 Pro spotted by <a href="https://x.com/never_released/status/2097928549072052373" target="_blank">X user never_released</a>.</p><div class="youtube-video" data-nosnippet ><div class="video-aspect-box"><iframe data-lazy-priority="low" data-lazy-src="https://www.youtube-nocookie.com/embed/BZi0R_thP9M" allowfullscreen></iframe></div></div><p>If the results from this listing are typical, the single core of 4,719 and a multi-core 12,677 show that the A20 is about 25% faster than the A19 silicon. In its <a href="https://www.apple.com/newsroom/2026/09/apple-debuts-iphone-18-pro-and-iphone-18-pro-max/" target="_blank">press release</a>, Apple claims the A20 Pro has 50% more memory bandwidth and 40% faster than the A19 Pro. </p><div ><table><caption>A20 vs A19</caption><thead><tr><th class="firstcol " ><p>Phone</p></th><th  ><p>Processor</p></th><th  ><p>Geekbench results</p></th></tr></thead><tbody><tr><td class="firstcol " ><p>iPhone 17 Pro</p></td><td  ><p>A19 Pro</p></td><td  ><p>3834 / 9988</p></td></tr><tr><td class="firstcol " ><p>iPhone 17 Pro Max</p></td><td  ><p>A19 Pro</p></td><td  ><p>3871 / 9968</p></td></tr><tr><td class="firstcol " ><p>iPhone 18 Pro (leak)</p></td><td  ><p>A20 Pro</p></td><td  ><p>4719/12677</p></td></tr><tr><td class="firstcol " ><p>M5 MacBook Pro 14-inch</p></td><td  ><p>M5</p></td><td  ><p>4288/17926</p></td></tr></tbody></table></div><p>It's not quite 40% better, but the A20 Pro is still a significantly more powerful chip. In fact, I looked at <a href="https://www.tomsguide.com/computing/macbooks/macbook-pro-m5-benchmarks-are-in-heres-how-it-compares-to-m4-windows-laptops-and-more#section-performance-tests">our testing for the M5 chip</a>, and it compares very favorably to Apple's M5 chipset.</p><p>We've <a href="https://www.tomsguide.com/computing/laptops/apples-low-cost-macbook-could-prove-phone-chips-are-the-key-to-cheap-laptops-but-qualcomm-says-its-in-a-very-good-position-to-fight">argued before</a> and the A20 Pro seems to prove it, there is no reason Apple couldn't run its laptops on its own phone chips. The proof is in the <a href="https://www.tomsguide.com/computing/macbooks/i-tested-the-macbook-neo-for-4k-video-editing-and-it-surprisingly-didnt-suck-until-it-did">MacBook Neo</a>, but things could get even more powerful.</p><p>Now, this is all said with the caveat that Geekbench listings can be faked, and we have the iPhone 18 Pro in hand right now. We're sending the new iPhones to our testing lab where we'll put the phones through our own series of tests. </p><h2 id="a-battery-downgrade">A battery downgrade?</h2><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="euGqodDZHMhayDEp6Hikzh" name="how-check-iphone-battery-health-image.jpg" alt="how to check iphone battery health" src="https://cdn.mos.cms.futurecdn.net/euGqodDZHMhayDEp6Hikzh.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>Some of the imagery and press releases from Apple claimed that the battery in the iPhone 18 Pro and Pro Max is larger than the one in the iPhone 17 Pro models. It's hard to prove because Apple doesn't list battery size in its technical specifications, at least in the US. </p><p>In the EU, the company does list the capacity. <a href="https://www.macrumors.com/2026/09/09/iphone-18-pro-max-battery-capacities/" target="_blank">MacRumors</a> spotted the capacities for the SIM tray versions of the iPhone 18 Pro.</p><ul><li><strong>iPhone 18 Pro: </strong>4,056 mAh</li><li><strong>iPhone 17 Pro: </strong>4,252 mAh</li><li><strong>iPhone 18 Pro Max: </strong>5,391 mAh</li><li><strong>iPhone 17 Pro Max: </strong>5,088 mAh<strong> </strong></li></ul><p>Based on those numbers, that's a 1.7% increase for the Pro and almost a 12% increase for the Pro Max.</p><p>I've seen comparisons to the eSIM version of the iPhone 17 Pro, which has a larger capacity compared to the SIM version. The eSIM iPhone 17 Pro comes with a 4,252 mAh battery that is bigger than the physical SIM version.</p><p>Meanwhile, the iPhone 17 Pro has the same 5,088 mAh in the eSIM version. </p><p>That all said, even if the battery is slightly smaller or only a bit bigger, the gains in battery life will likely come from the new A20 chipset and its expected performance and efficiency upgrades.</p><p>From what we can tell, the eSIM capacities for the iPhone 18 Pro models have not been released yet.</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/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><strong></strong></li><li><strong></strong><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 recap — Hands-on with the iPhone Duo and all the big announcements</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/phones/iphones/apples-just-extended-free-access-to-emergency-satellite-communication-for-another-year-its-the-third-time-this-has-happened"><strong>Apple's just extended free access to emergency satellite communication for another year — it's the third time this has happened</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/the-iphone-18-pro-may-be-faster-but-it-also-comes-with-a-potential-battery-downgrade</link>
                                                                            <description>
                            <![CDATA[ Two different leaks appear to reveal the performance of Apple's new A20 chips  and the new batteries in the iPhone 18 Pro. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">enTFtF6F3be89xG5wKBPTD</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/UHNuNim9UYH2mmGNTn3S4V-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 10 Sep 2026 18:39:40 +0000</pubDate>                                                                                                                                <updated>Thu, 10 Sep 2026 23:48:58 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ scott.younker@futurenet.com (Scott Younker) ]]></author>                    <dc:creator><![CDATA[ Scott Younker ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/RZsUpqcJ6Uj2q83oCUwNhQ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Scott Younker is the West Coast Reporter at Tom’s Guide. He covers all the latest tech news, including phones, computing and more. He’s been involved in tech since 2011 covering everything from cameras and swimming pool equipment to the latest gaming consoles and smart TVs. He is on a seemingly never ending hunt to build the easiest to use home media system. &lt;/p&gt;&lt;p&gt;Before Tom’s Guide, Scott worked for publications like &lt;em&gt;Digital Trends, Outdoor Photographer, Dead Beats Panel&lt;/em&gt;, and in a brief detour, &lt;em&gt;America’s Funniest Home Videos&lt;/em&gt;. Yes, he has seen more pratfalls, silly pets and ridiculous home movie fails than is reasonably healthy. &lt;/p&gt;&lt;p&gt;When not writing about the latest devices or advances in chipsets, be sure to ask about Scott about disc golf and sustainability, or just if you’re being cheeky, ask about his noodle arm. If you truly want to get nerdy, bring up board games and his ongoing losing streak. &lt;/p&gt;&lt;p&gt;Scott joined Tom&#039;s Guide in 2024 as the West Coast Reporter. He graduated from the School of Journalism at the University of Oregon with a degree in magazine journalism and a minor in communications. While there he blogged or wrote for several magazines including the Fluxx, Ethos and the Oregon Commentator. He briefly wrote and managed a moderately successful blog focused on web comics. &lt;br&gt;Send secure tips on Signal: scyo1.55.&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/UHNuNim9UYH2mmGNTn3S4V-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide/Apple]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple iPhone 18 Pro and the A20 Pro chip]]></media:description>                                                            <media:text><![CDATA[Apple iPhone 18 Pro and the A20 Pro chip]]></media:text>
                                <media:title type="plain"><![CDATA[Apple iPhone 18 Pro and the A20 Pro chip]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/UHNuNim9UYH2mmGNTn3S4V-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-hands-on-sneaky-awesome-upgrades-but-worth-the-price-hike">iPhone 18 Pro and iPhone 18 Pro Max </a>are finally here. Surprisingly, there is still information we don't know yet, including battery size (something Apple doesn't share) and how much better the A20 Pro chipset is compared to the A19 series.</p><p>Two different leaks may have given us some of that information. The first is a new <a href="https://browser.geekbench.com/v6/cpu/19143100" target="_blank">Geekbench listing</a> that appears to show how the A20 Pro works in the iPhone 18 Pro spotted by <a href="https://x.com/never_released/status/2097928549072052373" target="_blank">X user never_released</a>.</p><div class="youtube-video" data-nosnippet ><div class="video-aspect-box"><iframe data-lazy-priority="low" data-lazy-src="https://www.youtube-nocookie.com/embed/BZi0R_thP9M" allowfullscreen></iframe></div></div><p>If the results from this listing are typical, the single core of 4,719 and a multi-core 12,677 show that the A20 is about 25% faster than the A19 silicon. In its <a href="https://www.apple.com/newsroom/2026/09/apple-debuts-iphone-18-pro-and-iphone-18-pro-max/" target="_blank">press release</a>, Apple claims the A20 Pro has 50% more memory bandwidth and 40% faster than the A19 Pro. </p><div ><table><caption>A20 vs A19</caption><thead><tr><th class="firstcol " ><p>Phone</p></th><th  ><p>Processor</p></th><th  ><p>Geekbench results</p></th></tr></thead><tbody><tr><td class="firstcol " ><p>iPhone 17 Pro</p></td><td  ><p>A19 Pro</p></td><td  ><p>3834 / 9988</p></td></tr><tr><td class="firstcol " ><p>iPhone 17 Pro Max</p></td><td  ><p>A19 Pro</p></td><td  ><p>3871 / 9968</p></td></tr><tr><td class="firstcol " ><p>iPhone 18 Pro (leak)</p></td><td  ><p>A20 Pro</p></td><td  ><p>4719/12677</p></td></tr><tr><td class="firstcol " ><p>M5 MacBook Pro 14-inch</p></td><td  ><p>M5</p></td><td  ><p>4288/17926</p></td></tr></tbody></table></div><p>It's not quite 40% better, but the A20 Pro is still a significantly more powerful chip. In fact, I looked at <a href="https://www.tomsguide.com/computing/macbooks/macbook-pro-m5-benchmarks-are-in-heres-how-it-compares-to-m4-windows-laptops-and-more#section-performance-tests">our testing for the M5 chip</a>, and it compares very favorably to Apple's M5 chipset.</p><p>We've <a href="https://www.tomsguide.com/computing/laptops/apples-low-cost-macbook-could-prove-phone-chips-are-the-key-to-cheap-laptops-but-qualcomm-says-its-in-a-very-good-position-to-fight">argued before</a> and the A20 Pro seems to prove it, there is no reason Apple couldn't run its laptops on its own phone chips. The proof is in the <a href="https://www.tomsguide.com/computing/macbooks/i-tested-the-macbook-neo-for-4k-video-editing-and-it-surprisingly-didnt-suck-until-it-did">MacBook Neo</a>, but things could get even more powerful.</p><p>Now, this is all said with the caveat that Geekbench listings can be faked, and we have the iPhone 18 Pro in hand right now. We're sending the new iPhones to our testing lab where we'll put the phones through our own series of tests. </p><h2 id="a-battery-downgrade">A battery downgrade?</h2><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="euGqodDZHMhayDEp6Hikzh" name="how-check-iphone-battery-health-image.jpg" alt="how to check iphone battery health" src="https://cdn.mos.cms.futurecdn.net/euGqodDZHMhayDEp6Hikzh.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>Some of the imagery and press releases from Apple claimed that the battery in the iPhone 18 Pro and Pro Max is larger than the one in the iPhone 17 Pro models. It's hard to prove because Apple doesn't list battery size in its technical specifications, at least in the US. </p><p>In the EU, the company does list the capacity. <a href="https://www.macrumors.com/2026/09/09/iphone-18-pro-max-battery-capacities/" target="_blank">MacRumors</a> spotted the capacities for the SIM tray versions of the iPhone 18 Pro.</p><ul><li><strong>iPhone 18 Pro: </strong>4,056 mAh</li><li><strong>iPhone 17 Pro: </strong>4,252 mAh</li><li><strong>iPhone 18 Pro Max: </strong>5,391 mAh</li><li><strong>iPhone 17 Pro Max: </strong>5,088 mAh<strong> </strong></li></ul><p>Based on those numbers, that's a 1.7% increase for the Pro and almost a 12% increase for the Pro Max.</p><p>I've seen comparisons to the eSIM version of the iPhone 17 Pro, which has a larger capacity compared to the SIM version. The eSIM iPhone 17 Pro comes with a 4,252 mAh battery that is bigger than the physical SIM version.</p><p>Meanwhile, the iPhone 17 Pro has the same 5,088 mAh in the eSIM version. </p><p>That all said, even if the battery is slightly smaller or only a bit bigger, the gains in battery life will likely come from the new A20 chipset and its expected performance and efficiency upgrades.</p><p>From what we can tell, the eSIM capacities for the iPhone 18 Pro models have not been released yet.</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/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><strong></strong></li><li><strong></strong><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 recap — Hands-on with the iPhone Duo and all the big announcements</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/phones/iphones/apples-just-extended-free-access-to-emergency-satellite-communication-for-another-year-its-the-third-time-this-has-happened"><strong>Apple's just extended free access to emergency satellite communication for another year — it's the third time this has happened</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Don't let a drop ruin your day — these 9 iPhone Duo cases are total lifesavers ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple's new foldable iPhone Duo, which was officially revealed yesterday, is a super-desirable piece of tech. It offers a foldable screen that's a whopping 50 per cent larger than iPhone 18 Pro Max and has an impressive selection of features, including a 48MP camera.</p><p>It's also seriously expensive, coming in at $2000. If you're planning to get one then it's a no-brainer to also add on a case at the same time — after all, you're going to want to keep it in peak condition for as long as possible.</p><p>For this article I've rounded up nine cases that will keep your iPhone Duo safe and sound. There are two official cases from Apple, in navy blue and sand, along with a whole host of others from third party brands. More cases are coming very soon, but if you want to make sure you have one as soon as possible, then take a look at the selection below.</p>        <div class="featured_product_block featured_block_hero" data-id="961b46be-ad1c-11f1-8164-b310c43fbdec">            <a href="https://www.apple.com/us/shop/product/mkr84zm/a/iphone-duo-case-navy-blue" data-model-name="iPhone Duo Case (Navy Blue)" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/6PKpvHT4hMA4d2T2qjuZbS.jpg" alt="Iphone duo Case – Navy Blue"></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">iPhone Duo Case (Navy Blue)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b472c-ad1c-11f1-ae83-1903fb2732b3">            <a href="https://www.apple.com/us/shop/product/mkr94zm/a/iphone-duo-case-sand" data-model-name="iPhone Duo Case (Sand)" 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/9w6vfxMvanh8uwPegTEGuS.jpg" alt="Iphone duo Case – Sand"></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">iPhone Duo Case (Sand)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b4646-ad1c-11f1-9119-c162ec08355b">            <a href="https://www.amazon.com/BENTOBEN-Case-iPhone-Cover-Clear/dp/B0HG18V4RN/" data-model-name="Magnetic Case for iPhone Duo" 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/nQReqjELbmdesJWXYJXnrR.jpg" alt="Bentoben Magnetic for Iphone Duo Case Full Hinge Protection Slim,clear"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Bentoben</div>                                        <div class="featured__title">Magnetic Case for iPhone Duo</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b479a-ad1c-11f1-aa53-a300171e9316">            <a href="https://www.amazon.com/Magnetic-Phone-Ultra-Heavy-Protection/dp/B0HGQK86HR/" data-model-name="Magnetic for iPhone Duo Case (Black)" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:104.38%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/wvLipiMdcACkTRWSngQbeS.jpg" alt="Magnetic for Iphone Duo Case Heavy Duty Protection Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Jaroco</div>                                        <div class="featured__title">Magnetic for iPhone Duo Case (Black)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b47fe-ad1c-11f1-a2d1-dd806a754a3c">            <a href="https://www.amazon.com/FNTCASE-Phone-Ultra-Case-Compatible/dp/B0HF3LVQ9Q/" data-model-name="iPhone Duo Case (Clear Glitter)" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:118.76%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/WVSCfTqADi23273DnXiAXT.jpg" alt="Fntcase for Iphone Duo Case Compatible With Magsafe Clear Glitter"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Fntcase</div>                                        <div class="featured__title">iPhone Duo Case (Clear Glitter)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b4876-ad1c-11f1-9aaa-b7f015df839a">            <a href="https://www.amazon.com/Mkeke-Ultra-Clear-iPhone-Protection/dp/B0HB95RV5F/" data-model-name="iPhone Duo Case (Clear)" 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/FyQfQgW5bSqyvmYxNA8JjT.jpg" alt="Mkeke for Iphone Duo Case Clear With Full Hinge Protection"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Mkeke</div>                                        <div class="featured__title">iPhone Duo Case (Clear)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b4948-ad1c-11f1-b91a-2f26ebac5052">            <a href="https://www.amazon.com/Mkeke-Phone-Ultra-Techwoven-iPhone/dp/B0HB4P6XHB/" data-model-name="iPhone Duo Techwoven Case (Green)" 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/iasUcCB3dMb8vSWhwEBiwT.jpg" alt="Mkeke for Iphone Duo Case Techwoven Green"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Mkeke</div>                                        <div class="featured__title">iPhone Duo Techwoven Case (Green)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b49f2-ad1c-11f1-8773-216b8c9e7b4e">            <a href="https://www.amazon.com/Spigen-iPhFold-Case-Air-MagFit/dp/B0GV51YPRY/" data-model-name="Air Fit Pro Case for iPhone Duo Case (Black)" 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/uZxzAhL3y6aQzSnJhzSEDU.jpg" alt="Spigen Air Fit Pro Magfit for Iphone Duo Case, Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Spigen</div>                                        <div class="featured__title">Air Fit Pro Case for iPhone Duo Case (Black)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b4a60-ad1c-11f1-8b1a-558b47d5cec8">            <a href="https://www.amazon.com/Spigen-iPhFold-Tough-Armor-MagFit/dp/B0GV51GDHF/" data-model-name="Tough Armor Pro Case for iPhone Duo" 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/ZLGD3sgdEnHwJvVcQgJZMU.jpg" alt="Spigen Tough Armor Pro Magfit for Iphone Duo Case, Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Spigen</div>                                        <div class="featured__title">Tough Armor Pro Case for iPhone Duo</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/dont-let-a-drop-ruin-your-day-these-9-iphone-duo-cases-are-total-lifesavers</link>
                                                                            <description>
                            <![CDATA[ If you're planning on getting the new iPhone Duo then investing in a protective case is essential. We've rounded up some of the best official and third party cases here. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">xx8FiyoUkyJW9qQyff2mwm</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/p3kiE2k7kmnkcefksUgzDD-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 10 Sep 2026 16:21:57 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                                    <dc:creator><![CDATA[ Will Salmon ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/HpRWP7Mh9ErgRGoTvZBbBJ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Will Salmon is Tom&#039;s Guide&#039;s Collections Editor, curating advice on the best products to spend your money on. Will has been writing about tech and entertainment for almost 20 years, including stints as GamesRadar+&#039;s Streaming Editor, editing comics website Newsarama, and writing for lots and lots of magazines.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/p3kiE2k7kmnkcefksUgzDD-1280-80.jpg">
                                                            <media:credit><![CDATA[Apple / Edited with Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple iPhone Duo cases]]></media:description>                                                            <media:text><![CDATA[Apple iPhone Duo cases]]></media:text>
                                <media:title type="plain"><![CDATA[Apple iPhone Duo cases]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/p3kiE2k7kmnkcefksUgzDD-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple's new foldable iPhone Duo, which was officially revealed yesterday, is a super-desirable piece of tech. It offers a foldable screen that's a whopping 50 per cent larger than iPhone 18 Pro Max and has an impressive selection of features, including a 48MP camera.</p><p>It's also seriously expensive, coming in at $2000. If you're planning to get one then it's a no-brainer to also add on a case at the same time — after all, you're going to want to keep it in peak condition for as long as possible.</p><p>For this article I've rounded up nine cases that will keep your iPhone Duo safe and sound. There are two official cases from Apple, in navy blue and sand, along with a whole host of others from third party brands. More cases are coming very soon, but if you want to make sure you have one as soon as possible, then take a look at the selection below.</p>        <div class="featured_product_block featured_block_hero" data-id="961b46be-ad1c-11f1-8164-b310c43fbdec">            <a href="https://www.apple.com/us/shop/product/mkr84zm/a/iphone-duo-case-navy-blue" data-model-name="iPhone Duo Case (Navy Blue)" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/6PKpvHT4hMA4d2T2qjuZbS.jpg" alt="Iphone duo Case – Navy Blue"></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">iPhone Duo Case (Navy Blue)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b472c-ad1c-11f1-ae83-1903fb2732b3">            <a href="https://www.apple.com/us/shop/product/mkr94zm/a/iphone-duo-case-sand" data-model-name="iPhone Duo Case (Sand)" 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/9w6vfxMvanh8uwPegTEGuS.jpg" alt="Iphone duo Case – Sand"></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">iPhone Duo Case (Sand)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b4646-ad1c-11f1-9119-c162ec08355b">            <a href="https://www.amazon.com/BENTOBEN-Case-iPhone-Cover-Clear/dp/B0HG18V4RN/" data-model-name="Magnetic Case for iPhone Duo" 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/nQReqjELbmdesJWXYJXnrR.jpg" alt="Bentoben Magnetic for Iphone Duo Case Full Hinge Protection Slim,clear"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Bentoben</div>                                        <div class="featured__title">Magnetic Case for iPhone Duo</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b479a-ad1c-11f1-aa53-a300171e9316">            <a href="https://www.amazon.com/Magnetic-Phone-Ultra-Heavy-Protection/dp/B0HGQK86HR/" data-model-name="Magnetic for iPhone Duo Case (Black)" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:104.38%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/wvLipiMdcACkTRWSngQbeS.jpg" alt="Magnetic for Iphone Duo Case Heavy Duty Protection Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Jaroco</div>                                        <div class="featured__title">Magnetic for iPhone Duo Case (Black)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b47fe-ad1c-11f1-a2d1-dd806a754a3c">            <a href="https://www.amazon.com/FNTCASE-Phone-Ultra-Case-Compatible/dp/B0HF3LVQ9Q/" data-model-name="iPhone Duo Case (Clear Glitter)" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:118.76%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/WVSCfTqADi23273DnXiAXT.jpg" alt="Fntcase for Iphone Duo Case Compatible With Magsafe Clear Glitter"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Fntcase</div>                                        <div class="featured__title">iPhone Duo Case (Clear Glitter)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b4876-ad1c-11f1-9aaa-b7f015df839a">            <a href="https://www.amazon.com/Mkeke-Ultra-Clear-iPhone-Protection/dp/B0HB95RV5F/" data-model-name="iPhone Duo Case (Clear)" 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/FyQfQgW5bSqyvmYxNA8JjT.jpg" alt="Mkeke for Iphone Duo Case Clear With Full Hinge Protection"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Mkeke</div>                                        <div class="featured__title">iPhone Duo Case (Clear)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b4948-ad1c-11f1-b91a-2f26ebac5052">            <a href="https://www.amazon.com/Mkeke-Phone-Ultra-Techwoven-iPhone/dp/B0HB4P6XHB/" data-model-name="iPhone Duo Techwoven Case (Green)" 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/iasUcCB3dMb8vSWhwEBiwT.jpg" alt="Mkeke for Iphone Duo Case Techwoven Green"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Mkeke</div>                                        <div class="featured__title">iPhone Duo Techwoven Case (Green)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b49f2-ad1c-11f1-8773-216b8c9e7b4e">            <a href="https://www.amazon.com/Spigen-iPhFold-Case-Air-MagFit/dp/B0GV51YPRY/" data-model-name="Air Fit Pro Case for iPhone Duo Case (Black)" 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/uZxzAhL3y6aQzSnJhzSEDU.jpg" alt="Spigen Air Fit Pro Magfit for Iphone Duo Case, Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Spigen</div>                                        <div class="featured__title">Air Fit Pro Case for iPhone Duo Case (Black)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="961b4a60-ad1c-11f1-8b1a-558b47d5cec8">            <a href="https://www.amazon.com/Spigen-iPhFold-Tough-Armor-MagFit/dp/B0GV51GDHF/" data-model-name="Tough Armor Pro Case for iPhone Duo" 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/ZLGD3sgdEnHwJvVcQgJZMU.jpg" alt="Spigen Tough Armor Pro Magfit for Iphone Duo Case, Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Spigen</div>                                        <div class="featured__title">Tough Armor Pro Case for iPhone Duo</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple's just extended free access to emergency satellite communication for another year — it's the third time this has happened ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Back when Apple announced the first satellite connectivity features for <a href="https://www.tomsguide.com/reviews/iphone-14">iPhone 14</a>, it also said that access to them would only be free for two years. <a href="https://www.tomsguide.com/news/emergency-sos-via-satellite-coming-to-iphone-14-this-month-what-you-need-to-know">That was four years ago</a>, and Apple has <a href="https://www.tomsguide.com/news/iphone-14-users-are-getting-an-extra-year-of-satellite-features-for-free-but-not-iphone-15-owners">yet to charge users a dime</a> for continued satellite access — a practice it has just confirmed (via <a href="https://www.macrumors.com/2026/09/09/apple-extends-free-satellite-access/" target="_blank">MacRumors</a>) will continue for at least another year.</p><p>Satellite connectivity on iPhone is designed to give users the ability to stay connected, even in areas that have no cellular coverage. The first release was<a href="https://www.tomsguide.com/news/emergency-sos-via-satellite-coming-to-iphone-14-this-month-what-you-need-to-know"> Emergency SOS via satellite</a>, which lets you contact emergency services in the event that you need rescue. </p><p>Apple later added Messages via Satellite for non-emergency communication, Find my Via satellite and Roadside Assistance via satellite in certain regions. All of which utilize a Globalstar satellite connection to send messages in cellular dead zones. </p><p>iPhone 14 users were originally set to lose their free access in 2024, followed by<a href="https://www.tomsguide.com/reviews/apple-iphone-15"> iPhone 15 </a>in 2025 and <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-16-pro-review">iPhone 16 </a>this year. The continual extensions mean that they'll continue to be able to access Apple's myriad of satellite features without having to pay for yet another subscription. This is certainly a good thing, and the last thing we want is to be stuck in the middle of nowhere and unable to call for help because Apple's decided it wants another couple of bucks off you every month.</p><p>The funny thing is Apple has never actually said how much a hypothetical satellite subscription would actually cost. Or even whether it actually intends to charge users for satellite access in the near future. </p><p>Clearly, though, unlike <a href="https://www.tomsguide.com/phones/iphones/apple-ceo-tim-cook-confirmed-price-hikes-are-unavoidable-so-get-ready-to-pay-more">the rising cost of RAM</a>, Apple is quite happy to eat the cost of satellite connectivity for a little while longer. Considering this is a lifesaving feature, that's probably a very good investment for the company. Not just because saving customers' lives is good for business, but also because of the <a href="https://www.tomsguide.com/news/iphone-14-emergency-sos-just-saved-a-mans-life">positive publicity those cases can bring.</a></p><p>Things might change in the future, but for now iPhone users can be safe in the knowledge that their access to Emergency SOS via satellite, and other similar features, will remain free and uninterrupted for another year.</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/apple-quietly-jacks-the-prices-of-the-iphone-16-iphone-17-and-iphone-air-heres-how-much-youll-pay-now">Apple quietly jacks the prices of the iPhone 16, iPhone 17, and iPhone Air — here's how much you'll pay now</a></li><li><a href="https://www.tomsguide.com/phones/iphones/steve-jobs-said-there-would-never-be-an-iphone-stylus-but-iphone-duo-just-proved-him-wrong-and-itll-be-a-better-device-for-it">Steve Jobs said there would never be an iPhone stylus but iPhone Duo just proved him wrong — and it'll be a better device for it</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-hands-on-sneaky-awesome-upgrades-but-worth-the-price-hike">iPhone 18 Pro and Pro Max hands-on — 4 things I really like (and 2 I don't)</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/apples-just-extended-free-access-to-emergency-satellite-communication-for-another-year-its-the-third-time-this-has-happened</link>
                                                                            <description>
                            <![CDATA[ Anyone with an iPhone 14, iPhone 15 or iPhone 16 is going to get at least one more year of satellite access absolutely free. Here's what you need to know. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">bnW3ZvgvCcPdiUeeinSKEX</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/kDCc32MvivyFqr2EjCavmR-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 10 Sep 2026 15:08:48 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ tom.pritchard@futurenet.com (Tom Pritchard) ]]></author>                    <dc:creator><![CDATA[ Tom Pritchard ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/biCewUkKfSA6QnT2HxVc3f.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/kDCc32MvivyFqr2EjCavmR-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Share location via satellite iPhone 14]]></media:description>                                                            <media:text><![CDATA[Share location via satellite iPhone 14]]></media:text>
                                <media:title type="plain"><![CDATA[Share location via satellite iPhone 14]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/kDCc32MvivyFqr2EjCavmR-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Back when Apple announced the first satellite connectivity features for <a href="https://www.tomsguide.com/reviews/iphone-14">iPhone 14</a>, it also said that access to them would only be free for two years. <a href="https://www.tomsguide.com/news/emergency-sos-via-satellite-coming-to-iphone-14-this-month-what-you-need-to-know">That was four years ago</a>, and Apple has <a href="https://www.tomsguide.com/news/iphone-14-users-are-getting-an-extra-year-of-satellite-features-for-free-but-not-iphone-15-owners">yet to charge users a dime</a> for continued satellite access — a practice it has just confirmed (via <a href="https://www.macrumors.com/2026/09/09/apple-extends-free-satellite-access/" target="_blank">MacRumors</a>) will continue for at least another year.</p><p>Satellite connectivity on iPhone is designed to give users the ability to stay connected, even in areas that have no cellular coverage. The first release was<a href="https://www.tomsguide.com/news/emergency-sos-via-satellite-coming-to-iphone-14-this-month-what-you-need-to-know"> Emergency SOS via satellite</a>, which lets you contact emergency services in the event that you need rescue. </p><p>Apple later added Messages via Satellite for non-emergency communication, Find my Via satellite and Roadside Assistance via satellite in certain regions. All of which utilize a Globalstar satellite connection to send messages in cellular dead zones. </p><p>iPhone 14 users were originally set to lose their free access in 2024, followed by<a href="https://www.tomsguide.com/reviews/apple-iphone-15"> iPhone 15 </a>in 2025 and <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-16-pro-review">iPhone 16 </a>this year. The continual extensions mean that they'll continue to be able to access Apple's myriad of satellite features without having to pay for yet another subscription. This is certainly a good thing, and the last thing we want is to be stuck in the middle of nowhere and unable to call for help because Apple's decided it wants another couple of bucks off you every month.</p><p>The funny thing is Apple has never actually said how much a hypothetical satellite subscription would actually cost. Or even whether it actually intends to charge users for satellite access in the near future. </p><p>Clearly, though, unlike <a href="https://www.tomsguide.com/phones/iphones/apple-ceo-tim-cook-confirmed-price-hikes-are-unavoidable-so-get-ready-to-pay-more">the rising cost of RAM</a>, Apple is quite happy to eat the cost of satellite connectivity for a little while longer. Considering this is a lifesaving feature, that's probably a very good investment for the company. Not just because saving customers' lives is good for business, but also because of the <a href="https://www.tomsguide.com/news/iphone-14-emergency-sos-just-saved-a-mans-life">positive publicity those cases can bring.</a></p><p>Things might change in the future, but for now iPhone users can be safe in the knowledge that their access to Emergency SOS via satellite, and other similar features, will remain free and uninterrupted for another year.</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/apple-quietly-jacks-the-prices-of-the-iphone-16-iphone-17-and-iphone-air-heres-how-much-youll-pay-now">Apple quietly jacks the prices of the iPhone 16, iPhone 17, and iPhone Air — here's how much you'll pay now</a></li><li><a href="https://www.tomsguide.com/phones/iphones/steve-jobs-said-there-would-never-be-an-iphone-stylus-but-iphone-duo-just-proved-him-wrong-and-itll-be-a-better-device-for-it">Steve Jobs said there would never be an iPhone stylus but iPhone Duo just proved him wrong — and it'll be a better device for it</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-hands-on-sneaky-awesome-upgrades-but-worth-the-price-hike">iPhone 18 Pro and Pro Max hands-on — 4 things I really like (and 2 I don't)</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Keep your new iPhone 18 Pro or iPhone 18 Pro Max safe from day one: The cases to buy right now ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple made waves yesterday with the reveal of the iPhone 18 Pro and 18 Pro Max. This next generation of the groundbreaking smartphone promises a powerful new 48MP camera, the vapour‑cooled A20 Pro chip which can handle AI with ease, and enhanced battery life — especially in the Pro Max.</p><p>If you're forking out for one of these new devices then you're going to want to keep it looking perfect. That's where phone cases come in handy. In this article I've pulled together 12 of the best cases that are already available for the iPhone 18 Pro and 18 Pro Max.</p><p>We're kicking things off with some of Apple's official cases, before moving into a few of the many cool third part cases out there. Whichever you choose, they'll keep your beautiful new device in peak condition. </p>        <div class="featured_product_block featured_block_hero" data-id="bf74f93c-ad0e-11f1-920e-dd7c191d0157">            <a href="https://www.apple.com/shop/product/mk8w4zm/a/iphone-18-pro-silicone-case-with-magsafe-crisp-blue" data-model-name="iPhone 18 Pro Silicone Case (Crisp Blue)" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/uHedVSyjQ9sx5uhuhUik6Y.jpg" alt="Iphone 18 pro Silicone Case With Magsafe – Crisp Blue"></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">iPhone 18 Pro Silicone Case (Crisp Blue)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fad6-ad0e-11f1-8787-7d8896f2d435">            <a href="https://www.apple.com/shop/product/mkdu4zm/a/iphone-18-pro-clear-case-with-magsafe" data-model-name="iPhone 18 Pro Case (Clear)" 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/pRh66sTUErqxseEckzX4QY.jpg" alt="Iphone 18 pro Clear Case With Magsafe"></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">iPhone 18 Pro Case (Clear)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="78d79114-ad19-11f1-bee8-8946298be9fc">            <a href="https://www.apple.com/us/shop/product/mk904zm/a/iphone-18-pro-max-silicone-case-with-magsafe-magenta" data-model-name="iPphone 18 Pro Max Silicone Case (Magenta)" 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/Eoo5MMFkiK5oHoXAyKG7ML.jpg" alt="Iphone 18 Pro max Silicone Case With Magsafe – Magenta"></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">iPphone 18 Pro Max Silicone Case (Magenta)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="78d79196-ad19-11f1-9ba2-35048731dae2">            <a href="https://www.apple.com/shop/product/mkd64zm/a/iphone-18-pro-techwoven-case-with-magsafe-black/" data-model-name="iPhone 18 Pro Techwoven Case (Black)" 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/9u2FSUQ8qyrp9jha478LiG.jpg" alt="Iphone 18 pro Techwoven Case With Magsafe – Black"></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">iPhone 18 Pro Techwoven Case (Black)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fb44-ad0e-11f1-8c24-4d49971434f4">            <a href="https://www.apple.com/shop/product/mkdp4zm/a/iphone-18-pro-max-techwoven-case-with-magsafe-olive" data-model-name="iPhone 18 Pro Max Techwoven Case (Olive)" 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/PrgCLPbaNt7sWVf7XXM6cY.jpg" alt="Iphone 18 Pro max Techwoven Case With Magsafe – Olive"></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">iPhone 18 Pro Max Techwoven Case (Olive)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fc16-ad0e-11f1-b9ae-03b82ddd5881">            <a href="https://smartish.com/products/wallet-slayer-vol-1-card-case-for-iphone-18-pro" data-model-name="Wallet Slayer Vol. 1 for iPhone 18 Pro" 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/bybKaVG6FPCisRm43J8bhY.jpg" alt="Wallet Slayer Vol. 1 - Card Case for Iphone 18 Pro"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Smartish</div>                                        <div class="featured__title">Wallet Slayer Vol. 1 for iPhone 18 Pro</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fc7a-ad0e-11f1-9b00-e7c2b3b425e4">            <a href="https://velvetcaviar.com/en-gb/products/brown-sugar-polka-dot-iphone-case?variant=42638777352238" data-model-name="iPhone 18 Pro Case (Brown Sugar Polka Dot)" 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/txhAvEEa4mMpEBgLD6BSBZ.jpg" alt="Iphone 18 Pro"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Velvet Caviar</div>                                        <div class="featured__title">iPhone 18 Pro Case (Brown Sugar Polka Dot)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fcde-ad0e-11f1-b51a-73b405be5a58">            <a href="https://smartish.com/products/wallet-slayer-vol-2-card-case-for-iphone-18-pro" data-model-name="Wallet Slayer Vol. 2 for iPhone 18 Pro" 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/E6jCSUrEjRZD3LjYuUPwKZ.jpg" alt="Wallet Slayer Vol. 2 - Card Case for Iphone 18 Pro"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Smartish</div>                                        <div class="featured__title">Wallet Slayer Vol. 2 for iPhone 18 Pro</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fd42-ad0e-11f1-967c-5d5df7261673">            <a href="https://www.otterbox.com/products/iphone-17-pro-figura-series-case/" data-model-name="iPhone 18 Pro Figura Case (Crema White)" 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/XVNFhj7ZYRNjy9MS7pLEpZ.png" alt="Iphone 18 Pro and Iphone 17 Pro Figura Series Case - Crema White"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>OtterBox</div>                                        <div class="featured__title">iPhone 18 Pro Figura Case (Crema White)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fda6-ad0e-11f1-a4e3-c786c34da212">            <a href="https://www.amazon.com/dp/B0H9ZKWQNX" data-model-name="iPhone 18 Pro Gripzilla case (Kale Crew)" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:118.48%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/GBKQUzoTSHTnQCePMM5sMZ.jpg" alt="Smartish Iphone 18/17 Pro Case Magsafe, Gripzilla, Grip Cover, Kale Crew"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Smartish</div>                                        <div class="featured__title">iPhone 18 Pro Gripzilla case (Kale Crew)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fe6e-ad0e-11f1-bf52-a382f60248f9">            <a href="https://www.otterbox.com/products/iphone-17-pro-defender-series-pro-case-2026/" data-model-name="iPhone 18 Pro Defender Series Case" 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/Kd5bexuUEwMaEMf3NH4Goa.png" alt="Iphone 18 Pro and Iphone 17 Pro Defender Series Pro Case - Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>OtterBox</div>                                        <div class="featured__title">iPhone 18 Pro Defender Series Case</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fed2-ad0e-11f1-b0c2-2f45aa449b18">            <a href="https://www.casetify.com/product/dark-cherry-jelly-phone-case/iphone-18-pro/ultra-impact-case-glaze#/16011824-100007" data-model-name="Dark Cherry Jelly case for iPhone 18 Pro" 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/3k3WXT5ViPDjzz485VzMqa.jpg" alt="Dark Cherry Jelly"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>CASETiFY</div>                                        <div class="featured__title">Dark Cherry Jelly case for iPhone 18 Pro</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/keep-your-new-iphone-18-pro-or-iphone-18-pro-max-safe-from-day-one-the-cases-to-buy-right-now</link>
                                                                            <description>
                            <![CDATA[ If you're picking up the gorgeous new Apple iPhone 18 or iPhone 18 Pro then you're going to want to keep it safe from scratches and dings. Why not invest in one of these great protective cases? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">hWGNWecGbV6gMbbQgZ2o8f</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/jcoqLKXz9CjaToRGYvyKRR-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 10 Sep 2026 13:42:39 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                                    <dc:creator><![CDATA[ Will Salmon ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/HpRWP7Mh9ErgRGoTvZBbBJ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Will Salmon is Tom&#039;s Guide&#039;s Collections Editor, curating advice on the best products to spend your money on. Will has been writing about tech and entertainment for almost 20 years, including stints as GamesRadar+&#039;s Streaming Editor, editing comics website Newsarama, and writing for lots and lots of magazines.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/jcoqLKXz9CjaToRGYvyKRR-1280-80.jpg">
                                                            <media:credit><![CDATA[Apple / Edited with Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A selection of iPhone 18 Pro cases.]]></media:description>                                                            <media:text><![CDATA[A selection of iPhone 18 Pro cases.]]></media:text>
                                <media:title type="plain"><![CDATA[A selection of iPhone 18 Pro cases.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/jcoqLKXz9CjaToRGYvyKRR-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple made waves yesterday with the reveal of the iPhone 18 Pro and 18 Pro Max. This next generation of the groundbreaking smartphone promises a powerful new 48MP camera, the vapour‑cooled A20 Pro chip which can handle AI with ease, and enhanced battery life — especially in the Pro Max.</p><p>If you're forking out for one of these new devices then you're going to want to keep it looking perfect. That's where phone cases come in handy. In this article I've pulled together 12 of the best cases that are already available for the iPhone 18 Pro and 18 Pro Max.</p><p>We're kicking things off with some of Apple's official cases, before moving into a few of the many cool third part cases out there. Whichever you choose, they'll keep your beautiful new device in peak condition. </p>        <div class="featured_product_block featured_block_hero" data-id="bf74f93c-ad0e-11f1-920e-dd7c191d0157">            <a href="https://www.apple.com/shop/product/mk8w4zm/a/iphone-18-pro-silicone-case-with-magsafe-crisp-blue" data-model-name="iPhone 18 Pro Silicone Case (Crisp Blue)" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:100.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/uHedVSyjQ9sx5uhuhUik6Y.jpg" alt="Iphone 18 pro Silicone Case With Magsafe – Crisp Blue"></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">iPhone 18 Pro Silicone Case (Crisp Blue)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fad6-ad0e-11f1-8787-7d8896f2d435">            <a href="https://www.apple.com/shop/product/mkdu4zm/a/iphone-18-pro-clear-case-with-magsafe" data-model-name="iPhone 18 Pro Case (Clear)" 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/pRh66sTUErqxseEckzX4QY.jpg" alt="Iphone 18 pro Clear Case With Magsafe"></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">iPhone 18 Pro Case (Clear)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="78d79114-ad19-11f1-bee8-8946298be9fc">            <a href="https://www.apple.com/us/shop/product/mk904zm/a/iphone-18-pro-max-silicone-case-with-magsafe-magenta" data-model-name="iPphone 18 Pro Max Silicone Case (Magenta)" 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/Eoo5MMFkiK5oHoXAyKG7ML.jpg" alt="Iphone 18 Pro max Silicone Case With Magsafe – Magenta"></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">iPphone 18 Pro Max Silicone Case (Magenta)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="78d79196-ad19-11f1-9ba2-35048731dae2">            <a href="https://www.apple.com/shop/product/mkd64zm/a/iphone-18-pro-techwoven-case-with-magsafe-black/" data-model-name="iPhone 18 Pro Techwoven Case (Black)" 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/9u2FSUQ8qyrp9jha478LiG.jpg" alt="Iphone 18 pro Techwoven Case With Magsafe – Black"></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">iPhone 18 Pro Techwoven Case (Black)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fb44-ad0e-11f1-8c24-4d49971434f4">            <a href="https://www.apple.com/shop/product/mkdp4zm/a/iphone-18-pro-max-techwoven-case-with-magsafe-olive" data-model-name="iPhone 18 Pro Max Techwoven Case (Olive)" 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/PrgCLPbaNt7sWVf7XXM6cY.jpg" alt="Iphone 18 Pro max Techwoven Case With Magsafe – Olive"></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">iPhone 18 Pro Max Techwoven Case (Olive)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fc16-ad0e-11f1-b9ae-03b82ddd5881">            <a href="https://smartish.com/products/wallet-slayer-vol-1-card-case-for-iphone-18-pro" data-model-name="Wallet Slayer Vol. 1 for iPhone 18 Pro" 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/bybKaVG6FPCisRm43J8bhY.jpg" alt="Wallet Slayer Vol. 1 - Card Case for Iphone 18 Pro"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Smartish</div>                                        <div class="featured__title">Wallet Slayer Vol. 1 for iPhone 18 Pro</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fc7a-ad0e-11f1-9b00-e7c2b3b425e4">            <a href="https://velvetcaviar.com/en-gb/products/brown-sugar-polka-dot-iphone-case?variant=42638777352238" data-model-name="iPhone 18 Pro Case (Brown Sugar Polka Dot)" 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/txhAvEEa4mMpEBgLD6BSBZ.jpg" alt="Iphone 18 Pro"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Velvet Caviar</div>                                        <div class="featured__title">iPhone 18 Pro Case (Brown Sugar Polka Dot)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fcde-ad0e-11f1-b51a-73b405be5a58">            <a href="https://smartish.com/products/wallet-slayer-vol-2-card-case-for-iphone-18-pro" data-model-name="Wallet Slayer Vol. 2 for iPhone 18 Pro" 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/E6jCSUrEjRZD3LjYuUPwKZ.jpg" alt="Wallet Slayer Vol. 2 - Card Case for Iphone 18 Pro"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Smartish</div>                                        <div class="featured__title">Wallet Slayer Vol. 2 for iPhone 18 Pro</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fd42-ad0e-11f1-967c-5d5df7261673">            <a href="https://www.otterbox.com/products/iphone-17-pro-figura-series-case/" data-model-name="iPhone 18 Pro Figura Case (Crema White)" 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/XVNFhj7ZYRNjy9MS7pLEpZ.png" alt="Iphone 18 Pro and Iphone 17 Pro Figura Series Case - Crema White"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>OtterBox</div>                                        <div class="featured__title">iPhone 18 Pro Figura Case (Crema White)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fda6-ad0e-11f1-a4e3-c786c34da212">            <a href="https://www.amazon.com/dp/B0H9ZKWQNX" data-model-name="iPhone 18 Pro Gripzilla case (Kale Crew)" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check style='padding-top:118.48%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/GBKQUzoTSHTnQCePMM5sMZ.jpg" alt="Smartish Iphone 18/17 Pro Case Magsafe, Gripzilla, Grip Cover, Kale Crew"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>Smartish</div>                                        <div class="featured__title">iPhone 18 Pro Gripzilla case (Kale Crew)</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fe6e-ad0e-11f1-bf52-a382f60248f9">            <a href="https://www.otterbox.com/products/iphone-17-pro-defender-series-pro-case-2026/" data-model-name="iPhone 18 Pro Defender Series Case" 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/Kd5bexuUEwMaEMf3NH4Goa.png" alt="Iphone 18 Pro and Iphone 17 Pro Defender Series Pro Case - Black"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>OtterBox</div>                                        <div class="featured__title">iPhone 18 Pro Defender Series Case</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="bf74fed2-ad0e-11f1-b0c2-2f45aa449b18">            <a href="https://www.casetify.com/product/dark-cherry-jelly-phone-case/iphone-18-pro/ultra-impact-case-glaze#/16011824-100007" data-model-name="Dark Cherry Jelly case for iPhone 18 Pro" 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/3k3WXT5ViPDjzz485VzMqa.jpg" alt="Dark Cherry Jelly"></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                        <div class='featured__brand'>CASETiFY</div>                                        <div class="featured__title">Dark Cherry Jelly case for iPhone 18 Pro</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Steve Jobs said there would never be an iPhone stylus but iPhone Duo just proved him wrong — and it'll be a better device for it ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I have long argued that the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo</a> should break the<a href="https://www.tomsguide.com/phones/iphones/steve-jobs-hated-the-stylus-but-the-iphone-fold-is-going-to-need-one-heres-why"> original commandment Steve Jobs laid down</a> when the very first iPhone launched over 19 years ago. "Nobody wants a stylus," Jobs declared, "if you see a stylus, they blew it."</p><p>It's a decree that made sense at the time, but things have changed since 2007 — especially after the launch of the Apple Pencil for iPad in 2015.</p><p>Frankly, I'm of the opinion that Apple would have blown it if the foldable iPhone Duo <em>didn't</em> have a stylus. Rumors suggested things might be a little dicey on that front, but Apple confirmed that the Duo will support the<a href="https://www.tomsguide.com/hands-on/apple-pencil-usb-c-hands-on-is-this-pen-mightier"> Apple Pencil (USB-C)</a>. This is definitely a good thing, especially if Apple wants to angle the foldable as a productivity device</p><div class="product"><a data-dimension112="2d703e68-ad11-11f1-91b7-7183b6db0abe" data-action="Deal Block" data-label="Pencil USB-C" data-dimension48="Pencil USB-C" data-dimension25="$68" href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" 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="KvnFQiFWXqK8iVhZhkSEoP" name="Apple Pencil USB-C" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/KvnFQiFWXqK8iVhZhkSEoP.jpg" mos="" align="middle" fullscreen="" width="1080" height="1080" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Get ready for the iPhone Duo's October release by picking up the one compatible stylus before Apple tries to increase the price on us. While basic, the Apple Pencil USB-C includes tilt support, magnetic connectivity, low latency and pixel-perfect precision. It's also compatible with almost every recent iPad, and can be yours with $10 off the usual price.<a class="view-deal button" href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow" data-dimension112="2d703e68-ad11-11f1-91b7-7183b6db0abe" data-action="Deal Block" data-label="Pencil USB-C" data-dimension48="Pencil USB-C" data-dimension25="$68">View Deal</a></p></div><h2 id="iphone-duo-is-a-tablet-in-disguise">iPhone Duo is a tablet in disguise</h2><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="UDr8c5DLF9rP5aXyr9NwQ5" name="iphone duo software" alt="iphone duo two apps" src="https://cdn.mos.cms.futurecdn.net/UDr8c5DLF9rP5aXyr9NwQ5.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>Smartphones were very different when the original iPhone was released. Physical keyboards and styli were very common, because touchscreens of the time generally sucked. So Apple had an uphill battle trying to convince people that the iPhone's touchscreen could change all that. Throwing a stylus into the mix shortly afterwards would amount to Apple conceding that its multi-touch display couldn't hack it.</p><p>Apple did eventually get some heat for releasing the Apple Pencil eight years later, especially after Jobs' harsh words. But technically speaking, since it was only compatible with the iPad, Apple hadn't gone against Jobs' wishes. </p><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="Ck8JELAibFWVaimim8EYYK" name="iphone duo keyboard" alt="iPhone Duo hands on" src="https://cdn.mos.cms.futurecdn.net/Ck8JELAibFWVaimim8EYYK.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>Plus, that was around the time Apple started leveraging the iPad as a productivity device and meant the tablet would benefit from a little more finesse than stubby human digits could offer. A mouse isn't practical for a portable device, but a stylus can work pretty darn well. Especially when you consider that handwriting and drawing become real possibilities when you have that precision control.</p><p>I say that from the experience using my own iPad. I much prefer doing actual work on a laptop, with a full keyboard and mouse combination. But that doesn't mean the iPad isn't also a useful tool, and the addition of the stylus lets it do things that my other devices can't. </p><p>I'm not exaggerating when I say that the iPhone Duo is effectively an iPad hiding inside an iPhone. The 7.6-inch display is only a fraction of an inch shorter than the <a href="https://www.tomsguide.com/tablets/ipads/ipad-mini-7-review">iPad mini 7</a>, and the aspect ratio is roughly the same — around 4:3. So it makes sense that Apple would offer the iPhone Duo with all the same benefits of owning an iPad — stylus and all.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-XpBPVW"></div>                            </div>                            <script src="https://kwizly.com/embed/XpBPVW.js" async></script><h2 id="this-helps-the-duo-stand-out-from-other-foldables">This helps the Duo stand out from other foldables</h2><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="i4QF9zqZdmy4sZPuE8hXFa" name="iphone duo edit 4" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/i4QF9zqZdmy4sZPuE8hXFa.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>Despite the fact that tablets have had stylus support for years, foldables have not been so lucky. In fact only Samsung really took that particular feature seriously, but it later <a href="https://www.tomsguide.com/phones/galaxy-z-fold-7-ditched-the-s-pen-but-samsungs-working-on-a-new-version-for-future-foldables">removed the feature from the Galaxy Z Fold 7</a> with the goal of reducing the thickness of the design. Plus the S Pen was a special kind that only worked with foldable screens, and wasn't compatible with other stylus-friendly phones and tablets.</p><p>When the iPhone Duo launches later this year, it will have two distinct advantages. The first is that it will be the only mainstream foldable phone to actually support a stylus. The other is that it uses the exact same stylus as Apple's iPads, meaning you don't need a specific accessory that only works with the foldable screen. You're free to swap between devices just as you would if you owned multiple iPads.</p><p>The Apple Pencil USB-C is the cheapest stylus Apple makes too, and can often be found discounted outside of the usual big sales events. While it's not ideal to have to buy additional accessories for your $2,000 phone, you're at least not forced to buy the most expensive <a href="https://www.tomsguide.com/tablets/ipads/apple-announces-apple-pencil-pro-with-barrel-roll-and-squeeze-capabilities">Apple Pencil Pro.</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:4672px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="VgRgz4YKmo7SF9NC2Wmp28" name="IMG_3869.JPG" alt="Procreate app on iPad mini 7" src="https://cdn.mos.cms.futurecdn.net/VgRgz4YKmo7SF9NC2Wmp28.jpg" mos="" align="middle" fullscreen="" width="4672" height="2628" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Admittedly this also means that the Duo misses out on all the advanced features that come with the more advanced Apple Pencils. The Apple Pencil Pro and Apple Pencil 2 both offer pressure sensitivity, wireless pairing, a double tap feature, haptic feedback, with the Pro also supporting the barrel roll and squeeze gestures. Both models can also be connected to Apple's Find My network, in the event that you lose them.</p><p>The Apple Pencil USB-C is a lot more basic by comparison, though it does still offer all the general stylus features you'd expect. Plus, you have to remember that the Apple Pencil 2 and Pencil Pro can only be recharged wirelessly, via a compatible iPads magnetic connector. Since the iPhone Duo doesn't seem to have that feature, the more advanced styli would be totally useless.</p><p>Oh, and considering reports that Apple could have scrapped the Duo's stylus support over fears it may damage the foldable display, it does make sense that Apple doesn't want to encourage people to press too hard.</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:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CN7RzmKPJyev7oUAf2fdFa" name="iPhone duo gaming" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/CN7RzmKPJyev7oUAf2fdFa.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>There's a lot to like about the first foldable iPhone, as we discovered first hand during our <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo hands-on</a>. The phone is well designed, durable, and in the words of Tom's Guide's Global Editor in chief Mark Spoonauer, "there's something magical about using the iPhone Duo" thanks to how it can seamlessly transition between tablet and phone modes.</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><p>As expensive as the device is, this is  looking like a best of both situations. You have all the benefits of a smartphone, including pocketability and the smaller cover display, combined with the larger tablet screen for things like watching movies or getting work done. </p><p>You can only be so productive without the right tools, and just like robust multitasking, the addition of the Apple Pencil is one of them. It certainly makes that $2,000 price tag a little more palatable, knowing that you can get a full iPad experience on your phone without the normal iPhone limits.</p><p>As useful as having a stylus on your phone can be, I think this is Apple's limit when it comes to bringing one to iPhone. And you know what? I think I would be ok with that, so long as the larger-screen devices like iPhone Duo and iPads kept them around. Otherwise, that extra screen space would be going to waste.</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/apple-quietly-jacks-the-prices-of-the-iphone-16-iphone-17-and-iphone-air-heres-how-much-youll-pay-now">Apple quietly jacks the prices of the iPhone 16, iPhone 17, and iPhone Air — here's how much you'll pay now</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-hands-on-sneaky-awesome-upgrades-but-worth-the-price-hike">iPhone 18 Pro and Pro Max hands-on: Sneaky awesome upgrades, but worth the price hike?</a></li><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></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/steve-jobs-said-there-would-never-be-an-iphone-stylus-but-iphone-duo-just-proved-him-wrong-and-itll-be-a-better-device-for-it</link>
                                                                            <description>
                            <![CDATA[ Apple Pencil support turns the iPhone Duo from a larger phone into a bonafide tablet alternative. And it's going to be a much more productive device as a result. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">xsKs2C3qQjWjEzrh5S9v6A</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/RVQtVtADxHFrALUGQ9mGSR-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 10 Sep 2026 12:43:56 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ tom.pritchard@futurenet.com (Tom Pritchard) ]]></author>                    <dc:creator><![CDATA[ Tom Pritchard ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/biCewUkKfSA6QnT2HxVc3f.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/RVQtVtADxHFrALUGQ9mGSR-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iphone duo]]></media:description>                                                            <media:text><![CDATA[iphone duo]]></media:text>
                                <media:title type="plain"><![CDATA[iphone duo]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/RVQtVtADxHFrALUGQ9mGSR-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I have long argued that the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo</a> should break the<a href="https://www.tomsguide.com/phones/iphones/steve-jobs-hated-the-stylus-but-the-iphone-fold-is-going-to-need-one-heres-why"> original commandment Steve Jobs laid down</a> when the very first iPhone launched over 19 years ago. "Nobody wants a stylus," Jobs declared, "if you see a stylus, they blew it."</p><p>It's a decree that made sense at the time, but things have changed since 2007 — especially after the launch of the Apple Pencil for iPad in 2015.</p><p>Frankly, I'm of the opinion that Apple would have blown it if the foldable iPhone Duo <em>didn't</em> have a stylus. Rumors suggested things might be a little dicey on that front, but Apple confirmed that the Duo will support the<a href="https://www.tomsguide.com/hands-on/apple-pencil-usb-c-hands-on-is-this-pen-mightier"> Apple Pencil (USB-C)</a>. This is definitely a good thing, especially if Apple wants to angle the foldable as a productivity device</p><div class="product"><a data-dimension112="2d703e68-ad11-11f1-91b7-7183b6db0abe" data-action="Deal Block" data-label="Pencil USB-C" data-dimension48="Pencil USB-C" data-dimension25="$68" href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" 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="KvnFQiFWXqK8iVhZhkSEoP" name="Apple Pencil USB-C" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/KvnFQiFWXqK8iVhZhkSEoP.jpg" mos="" align="middle" fullscreen="" width="1080" height="1080" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>Get ready for the iPhone Duo's October release by picking up the one compatible stylus before Apple tries to increase the price on us. While basic, the Apple Pencil USB-C includes tilt support, magnetic connectivity, low latency and pixel-perfect precision. It's also compatible with almost every recent iPad, and can be yours with $10 off the usual price.<a class="view-deal button" href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow" data-dimension112="2d703e68-ad11-11f1-91b7-7183b6db0abe" data-action="Deal Block" data-label="Pencil USB-C" data-dimension48="Pencil USB-C" data-dimension25="$68">View Deal</a></p></div><h2 id="iphone-duo-is-a-tablet-in-disguise">iPhone Duo is a tablet in disguise</h2><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="UDr8c5DLF9rP5aXyr9NwQ5" name="iphone duo software" alt="iphone duo two apps" src="https://cdn.mos.cms.futurecdn.net/UDr8c5DLF9rP5aXyr9NwQ5.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>Smartphones were very different when the original iPhone was released. Physical keyboards and styli were very common, because touchscreens of the time generally sucked. So Apple had an uphill battle trying to convince people that the iPhone's touchscreen could change all that. Throwing a stylus into the mix shortly afterwards would amount to Apple conceding that its multi-touch display couldn't hack it.</p><p>Apple did eventually get some heat for releasing the Apple Pencil eight years later, especially after Jobs' harsh words. But technically speaking, since it was only compatible with the iPad, Apple hadn't gone against Jobs' wishes. </p><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="Ck8JELAibFWVaimim8EYYK" name="iphone duo keyboard" alt="iPhone Duo hands on" src="https://cdn.mos.cms.futurecdn.net/Ck8JELAibFWVaimim8EYYK.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>Plus, that was around the time Apple started leveraging the iPad as a productivity device and meant the tablet would benefit from a little more finesse than stubby human digits could offer. A mouse isn't practical for a portable device, but a stylus can work pretty darn well. Especially when you consider that handwriting and drawing become real possibilities when you have that precision control.</p><p>I say that from the experience using my own iPad. I much prefer doing actual work on a laptop, with a full keyboard and mouse combination. But that doesn't mean the iPad isn't also a useful tool, and the addition of the stylus lets it do things that my other devices can't. </p><p>I'm not exaggerating when I say that the iPhone Duo is effectively an iPad hiding inside an iPhone. The 7.6-inch display is only a fraction of an inch shorter than the <a href="https://www.tomsguide.com/tablets/ipads/ipad-mini-7-review">iPad mini 7</a>, and the aspect ratio is roughly the same — around 4:3. So it makes sense that Apple would offer the iPhone Duo with all the same benefits of owning an iPad — stylus and all.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-XpBPVW"></div>                            </div>                            <script src="https://kwizly.com/embed/XpBPVW.js" async></script><h2 id="this-helps-the-duo-stand-out-from-other-foldables">This helps the Duo stand out from other foldables</h2><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="i4QF9zqZdmy4sZPuE8hXFa" name="iphone duo edit 4" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/i4QF9zqZdmy4sZPuE8hXFa.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>Despite the fact that tablets have had stylus support for years, foldables have not been so lucky. In fact only Samsung really took that particular feature seriously, but it later <a href="https://www.tomsguide.com/phones/galaxy-z-fold-7-ditched-the-s-pen-but-samsungs-working-on-a-new-version-for-future-foldables">removed the feature from the Galaxy Z Fold 7</a> with the goal of reducing the thickness of the design. Plus the S Pen was a special kind that only worked with foldable screens, and wasn't compatible with other stylus-friendly phones and tablets.</p><p>When the iPhone Duo launches later this year, it will have two distinct advantages. The first is that it will be the only mainstream foldable phone to actually support a stylus. The other is that it uses the exact same stylus as Apple's iPads, meaning you don't need a specific accessory that only works with the foldable screen. You're free to swap between devices just as you would if you owned multiple iPads.</p><p>The Apple Pencil USB-C is the cheapest stylus Apple makes too, and can often be found discounted outside of the usual big sales events. While it's not ideal to have to buy additional accessories for your $2,000 phone, you're at least not forced to buy the most expensive <a href="https://www.tomsguide.com/tablets/ipads/apple-announces-apple-pencil-pro-with-barrel-roll-and-squeeze-capabilities">Apple Pencil Pro.</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:4672px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="VgRgz4YKmo7SF9NC2Wmp28" name="IMG_3869.JPG" alt="Procreate app on iPad mini 7" src="https://cdn.mos.cms.futurecdn.net/VgRgz4YKmo7SF9NC2Wmp28.jpg" mos="" align="middle" fullscreen="" width="4672" height="2628" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Admittedly this also means that the Duo misses out on all the advanced features that come with the more advanced Apple Pencils. The Apple Pencil Pro and Apple Pencil 2 both offer pressure sensitivity, wireless pairing, a double tap feature, haptic feedback, with the Pro also supporting the barrel roll and squeeze gestures. Both models can also be connected to Apple's Find My network, in the event that you lose them.</p><p>The Apple Pencil USB-C is a lot more basic by comparison, though it does still offer all the general stylus features you'd expect. Plus, you have to remember that the Apple Pencil 2 and Pencil Pro can only be recharged wirelessly, via a compatible iPads magnetic connector. Since the iPhone Duo doesn't seem to have that feature, the more advanced styli would be totally useless.</p><p>Oh, and considering reports that Apple could have scrapped the Duo's stylus support over fears it may damage the foldable display, it does make sense that Apple doesn't want to encourage people to press too hard.</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:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CN7RzmKPJyev7oUAf2fdFa" name="iPhone duo gaming" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/CN7RzmKPJyev7oUAf2fdFa.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>There's a lot to like about the first foldable iPhone, as we discovered first hand during our <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo hands-on</a>. The phone is well designed, durable, and in the words of Tom's Guide's Global Editor in chief Mark Spoonauer, "there's something magical about using the iPhone Duo" thanks to how it can seamlessly transition between tablet and phone modes.</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><p>As expensive as the device is, this is  looking like a best of both situations. You have all the benefits of a smartphone, including pocketability and the smaller cover display, combined with the larger tablet screen for things like watching movies or getting work done. </p><p>You can only be so productive without the right tools, and just like robust multitasking, the addition of the Apple Pencil is one of them. It certainly makes that $2,000 price tag a little more palatable, knowing that you can get a full iPad experience on your phone without the normal iPhone limits.</p><p>As useful as having a stylus on your phone can be, I think this is Apple's limit when it comes to bringing one to iPhone. And you know what? I think I would be ok with that, so long as the larger-screen devices like iPhone Duo and iPads kept them around. Otherwise, that extra screen space would be going to waste.</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/apple-quietly-jacks-the-prices-of-the-iphone-16-iphone-17-and-iphone-air-heres-how-much-youll-pay-now">Apple quietly jacks the prices of the iPhone 16, iPhone 17, and iPhone Air — here's how much you'll pay now</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-hands-on-sneaky-awesome-upgrades-but-worth-the-price-hike">iPhone 18 Pro and Pro Max hands-on: Sneaky awesome upgrades, but worth the price hike?</a></li><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></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.jpg" mos="" align="middle" fullscreen="" width="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.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.jpg" mos="" align="middle" fullscreen="" width="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.jpg" mos="" align="middle" fullscreen="" width="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.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.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.jpg" mos="" align="middle" fullscreen="" width="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-1280-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.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-1280-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-1280-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.jpg" mos="" align="middle" fullscreen="" width="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.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.jpg" mos="" align="middle" fullscreen="" width="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.jpg" mos="" align="middle" fullscreen="" width="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.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.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.jpg" mos="" align="middle" fullscreen="" width="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 quietly jacks the prices of the iPhone 16, iPhone 17, and iPhone Air — here's how much you'll pay now ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The big headline of Apple'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">Surprise and shine event</a> was the announcement of the new foldable <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> along with the <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 and Pro Max</a>, but behind the scenes was some not-so-welcome news.</p><p>Due to the ongoing component shortages, Apple quietly increased the prices of some of its older phones. The <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-16-review">iPhone 16</a>, <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-review">iPhone 17</a>, <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17e-review">iPhone 17e,</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air</a> all saw their prices go up by $100 on Apple's site. While you'll undoubtedly still be able to get discounts from carriers, the company's older phones are no longer as great a value as they once were. </p><p>Here's how Apple's older phones compare in terms of cost, storage, processor, and battery life, to the iPhone 18 Pro and 18 Pro Max.</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><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Starting Price</strong></p></td><td  ><p><strong>Storage</strong></p></td><td  ><p><strong>Processor</strong></p></td><td  ><p><strong>Battery life</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro Max</strong></p></td><td  ><p>$1,299</p></td><td  ><p>256GB</p></td><td  ><p>A20 Pro</p></td><td  ><p>up to 45 hours</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro</strong></p></td><td  ><p>$1,199</p></td><td  ><p>256GB</p></td><td  ><p>A20 Pro</p></td><td  ><p>up to 36 hours</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max*</strong></p></td><td  ><p>$1,199</p></td><td  ><p>256GB</p></td><td  ><p>A19 Pro</p></td><td  ><p>17:54</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro*</strong></p></td><td  ><p>$1,099</p></td><td  ><p>256GB</p></td><td  ><p>A19 Pro</p></td><td  ><p>15:32</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Air</strong></p></td><td  ><p>$1,099</p></td><td  ><p>256GB</p></td><td  ><p>A19 Pro</p></td><td  ><p>12:02</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17</strong></p></td><td  ><p>$899</p></td><td  ><p>256GB</p></td><td  ><p>A19</p></td><td  ><p>12:47</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 16</strong></p></td><td  ><p>$799</p></td><td  ><p>128GB</p></td><td  ><p>A18</p></td><td  ><p>12:13</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17e</strong></p></td><td  ><p>$699</p></td><td  ><p>256GB</p></td><td  ><p>A19</p></td><td  ><p>12:35</p></td></tr></tbody></table></div><p>The iPhone 17 Pro Max cost $1,199 when it was first released, and the iPhone 17 Pro was $1,099, so Apple is raising prices across all of the phones in its lineup. While Apple no longer sells those two phones directly, you can still get them through carriers at those prices.</p><p>However, what really sticks out is the iPhone 16; at $799, it's $100 more than the iPhone 17e, yet has half the storage and an older processor. The iPhone 16 does have a better camera setup and faster charging, but is that enough to justify its higher price?</p><p>Now, there's naturally going to be a gap between Apple's Pro models and its base units, but now that the company has narrowed it between its older phones and now-discontinued iPhone 17 Pro models, the calculus changes somewhat for those who don't need to get Apple's latest-and-greatest.</p><p>I haven't delved into other features, such as camera performance and Siri, but Apple is touting a huge boost in battery life — it claims that the 18 Pro Max will last up to 45 hours when playing video, an increase of 6 hours over the iPhone 17 Pro Max. While we've seen much more modest gains on the Tom's Guide battery test, a significant change here could go a long way to justifying its price.</p><p>We'll have to wait and see until early next year, when Apple is expected to announce the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-rumors-everything-we-know-so-far">iPhone 18</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-rumors-5-biggest-expected-upgrades">iPhone Air 2</a>; will they be the same price as the current models, or cost even more? </p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/news/live/apple-event-live-foldable-iphone-iphone-18-pro-max-apple-watch-12-and-all-the-big-news"><strong>Apple Event recap: iPhone Duo, iPhone 18 Pro Max, Apple Watch 12 and more</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-official-price-release-date-specs-and-everything-you-need-to-know"><strong>iPhone Duo is official — everything you need to know</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know"><strong>iPhone 18 Pro and iPhone 18 Pro Max are official — here's what you need to know</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/apple-quietly-jacks-the-prices-of-the-iphone-16-iphone-17-and-iphone-air-heres-how-much-youll-pay-now</link>
                                                                            <description>
                            <![CDATA[ Apple's last-gen phones now cost a little bit more. Here's how much the iPhone 16, iPhone 17, iPhone 17e, and iPhone Air command. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">kxrrSmqa33bE2JowAfqFQV</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/ND2Fj9V3sLxqBjwahh6s53-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 10 Sep 2026 07:30:00 +0000</pubDate>                                                                                                                                <updated>Thu, 10 Sep 2026 08:12:52 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ mike.prospero@futurenet.com (Mike Prospero) ]]></author>                    <dc:creator><![CDATA[ Mike Prospero ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/xeJFBrJwXQzCqXLZXBFBKQ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Michael A. Prospero is the U.S. Editor-in-Chief for Tom’s Guide.  In his spare time, he also tests out the latest drones, electric scooters, and smart home gadgets, such as video doorbells. Before his tenure at Tom&#039;s Guide, he was the Reviews Editor for Laptop Magazine, a reporter at Fast Company, the Times of Trenton, and, many eons back, an intern at George magazine. He received his undergraduate degree from Boston College, where he worked on the campus newspaper The Heights, and then attended the Columbia University school of Journalism. When he’s not testing out the latest running watch, electric scooter, or skiing or training for a marathon, he’s probably using the latest sous vide machine, smoker, or pizza oven, to the delight — or chagrin — of his family.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/ND2Fj9V3sLxqBjwahh6s53-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Air shown in hand]]></media:description>                                                            <media:text><![CDATA[iPhone Air shown in hand]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Air shown in hand]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/ND2Fj9V3sLxqBjwahh6s53-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The big headline of Apple'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">Surprise and shine event</a> was the announcement of the new foldable <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> along with the <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 and Pro Max</a>, but behind the scenes was some not-so-welcome news.</p><p>Due to the ongoing component shortages, Apple quietly increased the prices of some of its older phones. The <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-16-review">iPhone 16</a>, <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-review">iPhone 17</a>, <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17e-review">iPhone 17e,</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air</a> all saw their prices go up by $100 on Apple's site. While you'll undoubtedly still be able to get discounts from carriers, the company's older phones are no longer as great a value as they once were. </p><p>Here's how Apple's older phones compare in terms of cost, storage, processor, and battery life, to the iPhone 18 Pro and 18 Pro Max.</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><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Starting Price</strong></p></td><td  ><p><strong>Storage</strong></p></td><td  ><p><strong>Processor</strong></p></td><td  ><p><strong>Battery life</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro Max</strong></p></td><td  ><p>$1,299</p></td><td  ><p>256GB</p></td><td  ><p>A20 Pro</p></td><td  ><p>up to 45 hours</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro</strong></p></td><td  ><p>$1,199</p></td><td  ><p>256GB</p></td><td  ><p>A20 Pro</p></td><td  ><p>up to 36 hours</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max*</strong></p></td><td  ><p>$1,199</p></td><td  ><p>256GB</p></td><td  ><p>A19 Pro</p></td><td  ><p>17:54</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro*</strong></p></td><td  ><p>$1,099</p></td><td  ><p>256GB</p></td><td  ><p>A19 Pro</p></td><td  ><p>15:32</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Air</strong></p></td><td  ><p>$1,099</p></td><td  ><p>256GB</p></td><td  ><p>A19 Pro</p></td><td  ><p>12:02</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17</strong></p></td><td  ><p>$899</p></td><td  ><p>256GB</p></td><td  ><p>A19</p></td><td  ><p>12:47</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 16</strong></p></td><td  ><p>$799</p></td><td  ><p>128GB</p></td><td  ><p>A18</p></td><td  ><p>12:13</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17e</strong></p></td><td  ><p>$699</p></td><td  ><p>256GB</p></td><td  ><p>A19</p></td><td  ><p>12:35</p></td></tr></tbody></table></div><p>The iPhone 17 Pro Max cost $1,199 when it was first released, and the iPhone 17 Pro was $1,099, so Apple is raising prices across all of the phones in its lineup. While Apple no longer sells those two phones directly, you can still get them through carriers at those prices.</p><p>However, what really sticks out is the iPhone 16; at $799, it's $100 more than the iPhone 17e, yet has half the storage and an older processor. The iPhone 16 does have a better camera setup and faster charging, but is that enough to justify its higher price?</p><p>Now, there's naturally going to be a gap between Apple's Pro models and its base units, but now that the company has narrowed it between its older phones and now-discontinued iPhone 17 Pro models, the calculus changes somewhat for those who don't need to get Apple's latest-and-greatest.</p><p>I haven't delved into other features, such as camera performance and Siri, but Apple is touting a huge boost in battery life — it claims that the 18 Pro Max will last up to 45 hours when playing video, an increase of 6 hours over the iPhone 17 Pro Max. While we've seen much more modest gains on the Tom's Guide battery test, a significant change here could go a long way to justifying its price.</p><p>We'll have to wait and see until early next year, when Apple is expected to announce the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-rumors-everything-we-know-so-far">iPhone 18</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-rumors-5-biggest-expected-upgrades">iPhone Air 2</a>; will they be the same price as the current models, or cost even more? </p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/news/live/apple-event-live-foldable-iphone-iphone-18-pro-max-apple-watch-12-and-all-the-big-news"><strong>Apple Event recap: iPhone Duo, iPhone 18 Pro Max, Apple Watch 12 and more</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-official-price-release-date-specs-and-everything-you-need-to-know"><strong>iPhone Duo is official — everything you need to know</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know"><strong>iPhone 18 Pro and iPhone 18 Pro Max are official — here's what you need to know</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone 18 Pro and Pro Max hands-on — 4 things I really like (and 2 I don't) ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Yeah, there’s a smaller Dynamic Island and fancy new colors, but you’d be hard pressed to tell the difference between the <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 and iPhone 18 Pro Max</a> and the iPhone 17 Pro series at a glance.</p><p>Dig a bit deeper, however, and you’ll discover that the iPhone 18 Pro and Pro Max have some pretty big camera upgrades that photographers of all skill levels will appreciate. The main camera offers variable aperture for the first time. And there’s new pro controls that let you adjust everything from the aperture to the shutter speed.</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/BZi0R_thP9M" allowfullscreen></iframe></div></div><p>Other sneaky awesome upgrades include a much faster A20 Pro chip, improved vapor chamber cooling for better sustained performance and much longer rated battery life. However, you’re going to pay $100 more for both models. And there’s some other drawbacks. Are these the <a href="https://www.tomsguide.com/best-picks/best-phones">best phones</a> you can buy now? Here’s my first impressions.</p><h3 class="article-body__section" id="section-what-i-like"><span>What I like</span></h3><h2 id="variable-aperture-camera">Variable aperture camera</h2><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="HYuuDMJ2Ch2YMUKD2MbYWc" name="iPhone 18 Pro cameras" alt="iPhone 18 Pro cameras" src="https://cdn.mos.cms.futurecdn.net/HYuuDMJ2Ch2YMUKD2MbYWc.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 main 48MP fusion camera on the iPhone 18 Pro and Pro Max have six laser-cut blades that can transition between different apertures on the fly. This allows the camera to automatically open and close the shutter based on the conditions to give you optimal control of depth of field and lighting.</p><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="9GCbUtdmqto6e9mrgX2BJo" name="iPhone 18 Pro Max variable aperture" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/9GCbUtdmqto6e9mrgX2BJo.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>Even better, you can manually change the aperture from four different ranges, allowing you to choose the optimal setting for the photo at hand. For example, you can choose f/1.48 for portraits and have more of the background out of focus or go up to f/4.0 if you want all of the scene to look sharp.</p><p>I tried this out in a simulated bar setting and I captured a glass with two different aperture settings and noticed a stark difference in the images. We'll be doing a lot more testing to see if these flagships make our <a href="https://www.tomsguide.com/us/best-phone-cameras,review-2272.html">best camera phone</a> list.</p><h2 id="seriously-powerful-a20-pro-chip-with-better-cooling">Seriously powerful A20 Pro chip — with better cooling</h2><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="cTmx5d63stEFmgKNszEyDo" name="iPhone 18 Pro Max gameplay" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/cTmx5d63stEFmgKNszEyDo.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 A20 Pro is Apple’s first 2nm chip in a phone, and it promises a serious performance boost. The 6-core CPU has two super cores that are up to 20% faster than the A19 Pro, plus a new 7-core GPU that promises up to 40% faster graphics performance than the <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">iPhone 17 Pro Max</a>.</p><p>I tried out the new chip in the Monster Hunter game coming later this year, and the gameplay was super smooth. We’re talking up to 120 frames per second. </p><p>Just as important, the new larger vapor chamber cooling system is designed to deliver up to 40% better sustained performance than the iPhone 17 Pro. Apple also designed the A20 Pro chip so that the memory sits to the side instead of having a stacked configuration, which also helps dissipate heat.  </p><h2 id="even-longer-battery-life">Even longer battery life</h2><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="XEnBSEb3MMRqFRw7NPesBo" name="iPhone 18 Pro Max front" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/XEnBSEb3MMRqFRw7NPesBo.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 iPhone 17 Pro Max was already one of the longest lasting phones we’ve ever tested, ranking high on our <a href="https://www.tomsguide.com/us/smartphones-best-battery-life,review-2857.html">best phone battery life</a> list. But the iPhone 18 Pro Max could shatter endurance records.</p><p>Apple has rated this flagship for 45 hours of video playback and the iPhone 18 Pro for 36 hours. Compare that to 39 hours and 33 hours, respectively, for the iPhone 17 Pro Max and iPhone 17 Pro.</p><p>The charging on the iPhone 18 Pro series gets a boost as well. You can get up to 50% charge in just 15 minutes with a 60W charger. MagSafe charging can get you to 50% in 30 minutes via 35W.</p><h2 id="siri-ai-is-finally-smart-enough-mostly">Siri AI is finally smart enough (mostly)</h2><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="PetgCsR77oez9YPGe9HZFo" name="iPhone 18 Pro Max Siri 1" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/PetgCsR77oez9YPGe9HZFo.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>While Siri has been the butt of jokes for years, the new <a href="https://www.tomsguide.com/phones/iphones/i-spent-a-week-with-siri-ai-here-are-my-honest-pros-and-cons">Siri AI</a> that comes with iOS 27 is pretty impressive. For example, with Visual Intelligence in the camera app, I could simply point the iPhone 18 Pro at a poster with dates on it and the phone instantly recognized them and could add them to my calendar super fast.</p><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="ZufRK5rK4L6VvsJuhiSiHo" name="iPhone 18 Pro Max siri 2" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/ZufRK5rK4L6VvsJuhiSiHo.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 new Siri also understands personal context a lot better. You can ask to pull up information like your upcoming flight and it will instantly pop up on screen. You can then go full screen if you like to ask follow-up questions.</p><p>As much as I appreciate the new Siri, you can’t have a live conversation about what it’s seeing in real time as you can with <a href="https://www.tomsguide.com/ai/google-gemini/i-tested-gemini-live-for-24-hours-the-good-the-bad-and-the-weird">Gemini Live</a> or ChatGPT Voice mode. I feel like that’s a pretty big hole versus the leading AI assistants.</p><p>I can’t tell you how many times I’ve used Gemini Live in particular to troubleshoot things on the fly or ask questions about things in front of me. I’d like to see Apple beef up Siri in this regard to make it even more conversational.</p><h3 class="article-body__section" id="section-what-i-don-t-like"><span>What I don't like</span></h3><h2 id="higher-prices">Higher prices</h2><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="Yjffyuo5ef8MQZ2Juy52Co" name="iPhone 18 Pro Max display" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/Yjffyuo5ef8MQZ2Juy52Co.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>It’s simply a sign of the times at this point, but it’s not great that the iPhone 18 Pro and iPhone 18 Pro Max both get a $100 price hike. The iPhone 18 Pro now starts at $1,099 and the Pro Max will run you $1,199.</p><p>To be fair, the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review">Galaxy S26 Ultra</a> also starts at $1,299, but that doesn’t mean I have to like it.</p><h2 id="heavier-designs">Heavier designs</h2><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="TUHKFKjf3sxjBNZKbzJu8o" name="iPhone 18 Pro colors" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/TUHKFKjf3sxjBNZKbzJu8o.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>Maybe it’s the variable aperture camera, larger vapor chamber cooling area or bigger batteries — or all of the above. But the new iPhone 18 Pros are heavier than their predecessors.</p><p>The iPhone 18 Pro weighs 7.44 ounces (211 grams), compared to 7.27 ounces (206 grams for the iPhone 17 Pro. And the iPhone 18 Pro Max tips the scales at 8.78 ounces (249 grams) versus 8.22 ounces (233 grams) for the 17 Pro Max.</p><h2 id="iphone-18-pro-and-iphone-18-pro-max-outlook">iPhone 18 Pro and iPhone 18 Pro Max: Outlook</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2KC3s6kTk4wSqcLXPsQ99o" name="iPhone 18 Pro Max burgundy 2" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/2KC3s6kTk4wSqcLXPsQ99o.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 <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo</a> understandably is getting the most buzz, but not everyone wants or needs a foldable phone — and certainly not everyone can afford its $2,000 price. The iPhone 18 Pro and iPhone 18 Pro Max are for power users who don’t want to give up a traditional form factor or flagship features like a telephoto zoom.</p><p>In addition, the iPhone 18 Pros have longer rated battery life — especially the iPhone 18 Pro Max — and come with Face ID built in. You just have to be willing to live with a minor price hike versus the iPhone 17 Pros and heavier designs. </p><p>For my money I’d go for the iPhone 18 Pro Max for its better endurance and bigger display, but both of these phones are true pro-level devices.</p><p>Stay tuned for our full rated review.</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-hands-on-sneaky-awesome-upgrades-but-worth-the-price-hike</link>
                                                                            <description>
                            <![CDATA[ The iPhone 18 Pro and iPhone 18 Pro Max boast a variable aperture camera, powerful A20 Pro chip and extra-long battery life. Here's the pros and cons based on my first impressions. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">EQYfRGG9rWX2BXLyudwK84</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/PsAoKzRkrmCg46aQ53ywDo-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 10 Sep 2026 06:11:52 +0000</pubDate>                                                                                                                                <updated>Thu, 10 Sep 2026 21:44:30 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                                    <dc:creator><![CDATA[ Mark Spoonauer ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/wtAspSzVfcKLB4JEd39AMo.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Mark Spoonauer is the global editor in chief of Tom&#039;s Guide and has covered technology for over 20 years. He oversees the direction of Tom&#039;s Guide and leads a team of over 25 journalists to bring you our expert buying guides, reviews, news, how-to articles, deals and other coverage.&lt;/p&gt;&lt;p&gt;Mark has a passion for covering all things mobile, having reviewed dozens of smartphones and other gadgets. He enjoys testing the top mobile devices and putting them up against each other in our in-depth face-offs. He also works hand in hand with our editors and testing team to continually improve how we evaluate products. &lt;/p&gt;&lt;p&gt;Having led Tom&#039;s Guide since 2013, Mark has focused on growing the core tech coverage of the site while also expanding into new areas, such as entertainment, fitness and home, recruiting talented writers and editors to help our readers figure out what to buy and how to get the most out of the products and services they use every day. &lt;/p&gt;&lt;p&gt;Mark has spoken at key industry events and appears regularly on TV to discuss the latest trends, including &lt;a href=&quot;https://cheddar.com/media/pixel-watch-gets-a-release-date-at-google-i-o-2022&quot;&gt;Cheddar&lt;/a&gt;, Fox 5, &lt;a href=&quot;https://www.foxbusiness.com/technology/apple-march-event-5g-iphone&quot;&gt;Fox Business&lt;/a&gt; and other outlets. Mark was previously editor in chief of Laptop Mag, and his work has appeared in Wired, Popular Science and Inc. Follow him on Twitter at @mspoonauer.&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/PsAoKzRkrmCg46aQ53ywDo-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone 18 Pro Max]]></media:description>                                                            <media:text><![CDATA[iPhone 18 Pro Max]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone 18 Pro Max]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/PsAoKzRkrmCg46aQ53ywDo-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Yeah, there’s a smaller Dynamic Island and fancy new colors, but you’d be hard pressed to tell the difference between the <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 and iPhone 18 Pro Max</a> and the iPhone 17 Pro series at a glance.</p><p>Dig a bit deeper, however, and you’ll discover that the iPhone 18 Pro and Pro Max have some pretty big camera upgrades that photographers of all skill levels will appreciate. The main camera offers variable aperture for the first time. And there’s new pro controls that let you adjust everything from the aperture to the shutter speed.</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/BZi0R_thP9M" allowfullscreen></iframe></div></div><p>Other sneaky awesome upgrades include a much faster A20 Pro chip, improved vapor chamber cooling for better sustained performance and much longer rated battery life. However, you’re going to pay $100 more for both models. And there’s some other drawbacks. Are these the <a href="https://www.tomsguide.com/best-picks/best-phones">best phones</a> you can buy now? Here’s my first impressions.</p><h3 class="article-body__section" id="section-what-i-like"><span>What I like</span></h3><h2 id="variable-aperture-camera">Variable aperture camera</h2><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="HYuuDMJ2Ch2YMUKD2MbYWc" name="iPhone 18 Pro cameras" alt="iPhone 18 Pro cameras" src="https://cdn.mos.cms.futurecdn.net/HYuuDMJ2Ch2YMUKD2MbYWc.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 main 48MP fusion camera on the iPhone 18 Pro and Pro Max have six laser-cut blades that can transition between different apertures on the fly. This allows the camera to automatically open and close the shutter based on the conditions to give you optimal control of depth of field and lighting.</p><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="9GCbUtdmqto6e9mrgX2BJo" name="iPhone 18 Pro Max variable aperture" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/9GCbUtdmqto6e9mrgX2BJo.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>Even better, you can manually change the aperture from four different ranges, allowing you to choose the optimal setting for the photo at hand. For example, you can choose f/1.48 for portraits and have more of the background out of focus or go up to f/4.0 if you want all of the scene to look sharp.</p><p>I tried this out in a simulated bar setting and I captured a glass with two different aperture settings and noticed a stark difference in the images. We'll be doing a lot more testing to see if these flagships make our <a href="https://www.tomsguide.com/us/best-phone-cameras,review-2272.html">best camera phone</a> list.</p><h2 id="seriously-powerful-a20-pro-chip-with-better-cooling">Seriously powerful A20 Pro chip — with better cooling</h2><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="cTmx5d63stEFmgKNszEyDo" name="iPhone 18 Pro Max gameplay" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/cTmx5d63stEFmgKNszEyDo.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 A20 Pro is Apple’s first 2nm chip in a phone, and it promises a serious performance boost. The 6-core CPU has two super cores that are up to 20% faster than the A19 Pro, plus a new 7-core GPU that promises up to 40% faster graphics performance than the <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">iPhone 17 Pro Max</a>.</p><p>I tried out the new chip in the Monster Hunter game coming later this year, and the gameplay was super smooth. We’re talking up to 120 frames per second. </p><p>Just as important, the new larger vapor chamber cooling system is designed to deliver up to 40% better sustained performance than the iPhone 17 Pro. Apple also designed the A20 Pro chip so that the memory sits to the side instead of having a stacked configuration, which also helps dissipate heat.  </p><h2 id="even-longer-battery-life">Even longer battery life</h2><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="XEnBSEb3MMRqFRw7NPesBo" name="iPhone 18 Pro Max front" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/XEnBSEb3MMRqFRw7NPesBo.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 iPhone 17 Pro Max was already one of the longest lasting phones we’ve ever tested, ranking high on our <a href="https://www.tomsguide.com/us/smartphones-best-battery-life,review-2857.html">best phone battery life</a> list. But the iPhone 18 Pro Max could shatter endurance records.</p><p>Apple has rated this flagship for 45 hours of video playback and the iPhone 18 Pro for 36 hours. Compare that to 39 hours and 33 hours, respectively, for the iPhone 17 Pro Max and iPhone 17 Pro.</p><p>The charging on the iPhone 18 Pro series gets a boost as well. You can get up to 50% charge in just 15 minutes with a 60W charger. MagSafe charging can get you to 50% in 30 minutes via 35W.</p><h2 id="siri-ai-is-finally-smart-enough-mostly">Siri AI is finally smart enough (mostly)</h2><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="PetgCsR77oez9YPGe9HZFo" name="iPhone 18 Pro Max Siri 1" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/PetgCsR77oez9YPGe9HZFo.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>While Siri has been the butt of jokes for years, the new <a href="https://www.tomsguide.com/phones/iphones/i-spent-a-week-with-siri-ai-here-are-my-honest-pros-and-cons">Siri AI</a> that comes with iOS 27 is pretty impressive. For example, with Visual Intelligence in the camera app, I could simply point the iPhone 18 Pro at a poster with dates on it and the phone instantly recognized them and could add them to my calendar super fast.</p><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="ZufRK5rK4L6VvsJuhiSiHo" name="iPhone 18 Pro Max siri 2" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/ZufRK5rK4L6VvsJuhiSiHo.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 new Siri also understands personal context a lot better. You can ask to pull up information like your upcoming flight and it will instantly pop up on screen. You can then go full screen if you like to ask follow-up questions.</p><p>As much as I appreciate the new Siri, you can’t have a live conversation about what it’s seeing in real time as you can with <a href="https://www.tomsguide.com/ai/google-gemini/i-tested-gemini-live-for-24-hours-the-good-the-bad-and-the-weird">Gemini Live</a> or ChatGPT Voice mode. I feel like that’s a pretty big hole versus the leading AI assistants.</p><p>I can’t tell you how many times I’ve used Gemini Live in particular to troubleshoot things on the fly or ask questions about things in front of me. I’d like to see Apple beef up Siri in this regard to make it even more conversational.</p><h3 class="article-body__section" id="section-what-i-don-t-like"><span>What I don't like</span></h3><h2 id="higher-prices">Higher prices</h2><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="Yjffyuo5ef8MQZ2Juy52Co" name="iPhone 18 Pro Max display" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/Yjffyuo5ef8MQZ2Juy52Co.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>It’s simply a sign of the times at this point, but it’s not great that the iPhone 18 Pro and iPhone 18 Pro Max both get a $100 price hike. The iPhone 18 Pro now starts at $1,099 and the Pro Max will run you $1,199.</p><p>To be fair, the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review">Galaxy S26 Ultra</a> also starts at $1,299, but that doesn’t mean I have to like it.</p><h2 id="heavier-designs">Heavier designs</h2><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="TUHKFKjf3sxjBNZKbzJu8o" name="iPhone 18 Pro colors" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/TUHKFKjf3sxjBNZKbzJu8o.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>Maybe it’s the variable aperture camera, larger vapor chamber cooling area or bigger batteries — or all of the above. But the new iPhone 18 Pros are heavier than their predecessors.</p><p>The iPhone 18 Pro weighs 7.44 ounces (211 grams), compared to 7.27 ounces (206 grams for the iPhone 17 Pro. And the iPhone 18 Pro Max tips the scales at 8.78 ounces (249 grams) versus 8.22 ounces (233 grams) for the 17 Pro Max.</p><h2 id="iphone-18-pro-and-iphone-18-pro-max-outlook">iPhone 18 Pro and iPhone 18 Pro Max: Outlook</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2KC3s6kTk4wSqcLXPsQ99o" name="iPhone 18 Pro Max burgundy 2" alt="iPhone 18 Pro Max" src="https://cdn.mos.cms.futurecdn.net/2KC3s6kTk4wSqcLXPsQ99o.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 <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice">iPhone Duo</a> understandably is getting the most buzz, but not everyone wants or needs a foldable phone — and certainly not everyone can afford its $2,000 price. The iPhone 18 Pro and iPhone 18 Pro Max are for power users who don’t want to give up a traditional form factor or flagship features like a telephoto zoom.</p><p>In addition, the iPhone 18 Pros have longer rated battery life — especially the iPhone 18 Pro Max — and come with Face ID built in. You just have to be willing to live with a minor price hike versus the iPhone 17 Pros and heavier designs. </p><p>For my money I’d go for the iPhone 18 Pro Max for its better endurance and bigger display, but both of these phones are true pro-level devices.</p><p>Stay tuned for our full rated review.</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.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.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.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.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.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.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.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.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-1280-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.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-1280-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-1280-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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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-1280-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.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-1280-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-1280-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.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.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.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.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.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.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.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.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.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.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.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.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.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-1280-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.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-1280-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-1280-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.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.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.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.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.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.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[ Apple Event recap — Hands-on with the iPhone Duo and all the big announcements ]]></title>
                                                                                                <dc:content><![CDATA[ <div class="live-content"><p>This week's <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">Apple "Surprise and Shine" event</a> proved to be a historic moment for the company. Not only did it mark the first Apple event helmed by new <a href="https://www.tomsguide.com/phones/iphones/massive-changes-at-apple-john-ternus-takes-over-as-ceo-sept-1-while-tim-cook-moves-to-executive-chairman">CEO John Ternus</a>, but it also catapulted Apple into a new era with its first-ever foldable — 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>The iPhone Duo is packing a 5.4-inch cover screen alongside an expansive 7.6-inch inner display, effectively putting a phone and tablet in a single pocketable chassis. That cutting-edge new form factor, surprisingly enough, starts off at $1,999 / £1,999 cost. </p><p>And we've already got hands-on time with<a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice"> iPhone Duo</a>.</p><p>Beyond the foldable, Apple used the event to reveal other key products like its flagship iPhone 18 Pro and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-farhttps://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know">iPhone 18 Pro Max</a>, 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>, and the rugged <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-12-and-ultra-4-rumors-your-next-apple-watch-could-have-a-ceramic-casehttps://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a>. We also got an official reveal for the <a href="https://www.tomsguide.com/audio/airpods/apple-airpods-5-officially-announced-here-are-the-upgrades">AirPods 5</a>, along with new Siri AI and Apple Intelligence features.</p><p>Here’s everything that was announced at Apple’s biggest showcase of the year and our corresponding early verdicts after getting hands-on with the new tech.</p><h2 class="article-body__section" id="section-how-to-watch-apple-surprise-and-shine-event"><span>How to watch Apple “Surprise and Shine” event</span></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/39BalPDuTo0" allowfullscreen></iframe></div></div><p>You can stay up to date with the latest announcements from Apple’s September hardware event by tuning in to the official livestream, accessible directly via a browser on Apple's website. Alternatively, you can catch the stream through <a href="https://www.youtube.com/live/39BalPDuTo0?si=k4UmDQpUDktfCMRc">Apple's official YouTube channel, </a>the Apple TV app or embedded below.</p><h2 class="article-body__section" id="section-biggest-announcements"><span>Biggest announcements</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="sAFnnQsMDkhrRiPhTeYah9" name="iphone-18-pro-model-unselect-gallery-1-202609" alt="iphone 18 pro and pro max side by side" src="https://cdn.mos.cms.futurecdn.net/sAFnnQsMDkhrRiPhTeYah9.webp" mos="" align="middle" fullscreen="" width="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><ul><li><a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-official-price-release-date-specs-and-everything-you-need-to-know"><strong>iPhone Duo:</strong></a> Apple’s first foldable smartphone is debuts with an ultra-thin, book-style folding design, a 7.6-inch inner display, Touch ID integration and $1,999 price tag.</li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know"><strong>iPhone 18 Pro & iPhone 18 Pro Max:</strong> </a>Apple’s next-generation flagship Pro phones feature a powerful 2nm A20 Pro chip, smaller Dynamic Island cutouts, larger batteries, and exclusive camera enhancements like a variable aperture.</li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-announced-everything-you-need-to-know-about-the-new-flagship-apple-watch"><strong>Apple Watch Series 12:</strong></a> Apple's core smartwatch update introduce new health-tracking capabilities, refined internal hardware., and more sensors.</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:</strong></a><strong> </strong>The latest iteration of Apple’s outdoor-focused wearable is anticipated to deliver enhanced satellite connectivity, expanded battery life, and upgraded sensors.</li><li><strong></strong><a href="https://www.tomsguide.com/audio/airpods/airpods-ultra-everything-we-know-so-far-about-apples-camera-earbuds"><strong>AirPods 5:</strong></a> This upgraded version of the standard AirPods comes with a few upgrades and a design similar to that of AirPods 4. Expect 4 hours of listening with ANC and a $129 starting price for the version without ANC.</li></ul><h3 class="article-body__section" id="section-apple-event-live-updates"><span>Apple event: Live Updates</span></h3></div><div class="live-content"><time datetime="2026-09-09T14:17:10+00:00">September 9, 2026 – 10:17 AM</time><h2 id="where-could-the-iphone-duo-land-among-the-all-time-greats">Where could the iPhone Duo land among the all-time greats?</h2><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eJ9grX"></div>                            </div>                            <script src="https://kwizly.com/embed/eJ9grX.js" async></script><p>If the iPhone Duo delivers on its promise, it faces a serious legitimacy test when stacked against an all-time greatest list. Every transformative Apple hardware leap — from the original and my personal favorite, the iPhone 4, to the <a href="https://www.tomsguide.com/us/iphone-x,review-4800.html">iPhone X</a> redefining modern smartphones — fundamentally rewrote what a phone should be. By finally breaking into a foldable design, the Duo undeniably earns a spot as the company’s most ambitious iPhone in nearly a decade.</p><p>Yet true all-time greatness isn’t crowned on ambition alone. A steep $2,000 price tag, inevitable first-gen trade-offs like missing telephoto lenses or Face ID, and early ecosystem growing pains could mean the Duo may land more like the original Apple Watch or the first iPad. It's poised to disrupt the market, but whether it tops Apple's greatest releases remains to be seen. What do you think?</p></div><div class="live-content"><time datetime="2026-09-09T14:24:10+00:00">September 9, 2026 – 10:24 AM</time><h2 id="why-great-hardware-won-39-t-be-enough-to-save-the-iphone-duo">Why great hardware won't be enough to save the iPhone Duo</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2879px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="77ZTA3cHAT3JoQVSNWAUNW" name="Galaxy Z Fold 8-15" alt="Galaxy Z Fold 8 shown in hand" src="https://cdn.mos.cms.futurecdn.net/77ZTA3cHAT3JoQVSNWAUNW.jpg" mos="" align="middle" fullscreen="" width="2879" height="1619" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>While rumors obsess over crease-free displays and ultra-thin hinges, Apple’s upcoming foldable faces a much bigger hurdle: software.</p><p>This is exactly the one thing I argue that will make or break the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Duo</a>, seeing how an expensive 7.8-inch folding canvas doesn't stand a chance unless <a href="https://www.tomsguide.com/phones/iphones/ios-27-public-beta-hands-on-preview-the-new-siri-and-apple-intelligence-features-completely-changed-how-i-use-my-iphone">iOS 27</a> completely rethinks the user experience. In order to genuinely challenge rival foldables, like the <a href="https://www.tomsguide.com/phones/samsung-phones/ive-been-living-with-the-galaxy-z-fold-8-for-3-weeks-and-i-was-wrong">Galaxy Z Fold 8</a>, <a href="https://www.tomsguide.com/phones/iphones/the-iphone-fold-doesnt-stand-a-chance-unless-apple-introduces-these-3-features-in-ios-27">Apple needs to deliver on three critical fronts</a>: seamless app scaling with landscape-oriented dual-pane views, a truly dynamic multitasking system built for a folding screen, and a dedicated desktop mode that finally lets the iPhone double as a pocket computer.</p><p>Without software tailored specifically to the form factor, the Duo risks being a gorgeous piece of hardware holding back an oversized iOS.</p></div><div class="live-content"><time datetime="2026-09-09T14:29:18+00:00">September 9, 2026 – 10:29 AM</time><h2 id="we-39-re-on-the-ground-at-apple-park">We're on the ground at Apple Park!</h2>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@mspoonyg/video/7683540347611335949" data-video-id="7683540347611335949" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@mspoonyg" href="https://www.tiktok.com/@mspoonyg">@mspoonyg</a>                            <p></p><a target="_blank" title="♬ Sunlit Fingertips - Elliot Vex" href="https://www.tiktok.com/music/Sunlit-Fingertips-7677642997227603978">♬ Sunlit Fingertips - Elliot Vex</a></section>                    </blockquote></div>                <p>Even though we're still a few hours away from the start time of the event, we're finally on the ground and ready to tackle everything Apple has to announce.  Clearly the one that's getting the most buzz right now is none other than the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-apples-first-foldable-usd2-000-price-release-date-as-early-as-october">iPhone Duo</a>, but there are three things you should know about Apple's upcoming first foldable phone.</p></div><div class="live-content"><time datetime="2026-09-09T14:37:43+00:00">September 9, 2026 – 10:37 AM</time><h2 id="iphone-18-pro-likely-to-get-a-price-hike-but-it-39-s-not-as-bad-as-we-thought">iPhone 18 Pro likely to get a price hike, but it's not as bad as we thought</h2><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="KW28fSsFG3t4hnceTZj9a8" name="iPhone 17 Pro review" alt="iPhone 17 Pro review." src="https://cdn.mos.cms.futurecdn.net/KW28fSsFG3t4hnceTZj9a8.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>After months of rumors warning that Apple’s next flagship series could see prices spike by as much as $200 to $300, a new report from Bloomberg brings some relief: the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-is-almost-certainly-getting-a-price-hike-but-it-could-be-less-than-we-feared">increase is expected to be capped at $100</a>.</p><p>That would push the starting prices to $1,199 for the iPhone 18 Pro and $1,299 for the iPhone 18 Pro Max (each likely starting with 256GB). While nobody welcomes higher hardware costs, the bump merely aligns Apple with chief competitors. like Samsung's <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review">Galaxy S26 Ultra</a> and <a href="https://www.tomsguide.com/phones/google-pixel-phones/i-checked-out-the-pixel-11-pixel-11-pro-and-pixel-11-pro-xl-heres-the-one-i-recommend">Google's Pixel 11 Pro XL</a>.</p><p>However, given the bigger hardware upgrades rumored to come to the larger iPhone 18 Pro Max, people may be inclined to get the Pro Max over the Pro this year.</p></div><div class="live-content"><time datetime="2026-09-09T14:43:52+00:00">September 9, 2026 – 10:43 AM</time><h2 id="airpods-ultra-won-39-t-likely-be-announced-but-we-could-get-something-else">AirPods Ultra won't likely be announced, but we could get something else</h2><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="uKSSLPpfSUmKyg5PvvDumX" name="AirPods 4-1.jpg" alt="AirPods 4 on a table" src="https://cdn.mos.cms.futurecdn.net/uKSSLPpfSUmKyg5PvvDumX.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>Before Apple rolls out wilder concept designs like <a href="https://www.tomsguide.com/audio/airpods/airpods-ultra-everything-we-know-so-far-about-apples-camera-earbuds">camera-touting AirPods</a> that have dominated the rumor mills for some time now, the company might instead reveal the <a href="https://www.tomsguide.com/audio/airpods/airpods-5-everything-weve-heard-so-far-about-apples-next-wireless-earbuds">AirPods 5</a> at its event later today.</p><p>Expect the lineup to maintain its two-model approach — $129 for base and $179 for ANC — powered by a new H3 chip for crisper call isolation and better noise cancellation, plus rumored basic temperature tracking to bolster entry-level health metrics.</p></div><div class="live-content"><time datetime="2026-09-09T14:49:53+00:00">September 9, 2026 – 10:49 AM</time><h2 id="i-39-ve-chosen-the-smaller-iphone-pro-for-the-last-couple-of-years-but-that-changes-this-year">I've chosen the smaller iPhone Pro for the last couple of years, but that changes this year</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1280px;"><p class="vanilla-image-block" style="padding-top:55.78%;"><img id="WNJZg5wpSg4yem6kzvAjLN" name="iPhone 18 Pro and Max LIST Large" alt="iPhone 18 Pro vs iPhone 18 Pro Max." src="https://cdn.mos.cms.futurecdn.net/WNJZg5wpSg4yem6kzvAjLN.jpg" mos="" align="middle" fullscreen="" width="1280" height="714" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>For the past couple of generations, sticking with the standard 6.3-inch Pro has been an easy call. It offered the ideal pocketable design that I crave without compromising on flagship features, especially since Apple kept camera and processing hardware idential. But with the iPhone 18 Pro and Pro Max, I'm leaning dramatically towards the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks">iPhone 18 Pro Max</a>.</p><p>Between rumors of the Pro Max exclusively receiving a game-changing <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-be-the-first-iphone-to-get-a-variable-aperture-why-that-matters">variable aperture main camera</a>, packing a <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-tipped-to-be-heaviest-iphone-ever-heres-3-reasons-why-thats-a-good-thing">massive battery upgrade upwards of 5,500 mAh</a>, and delivering better thermal headroom for the new 2nm A20 Pro silicon, Apple seems intent on re-establishing the Max as the true hardware flagship.</p><p>What seals the deal, however, is the narrowing price gap. With early whispers of a massive price hike giving way to reports that the Pro lineup will see a more modest bump, the 18 Pro and 18 Pro Max are tipped to be <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-is-almost-certainly-getting-a-price-hike-but-it-could-be-less-than-we-feared">separated by just $100</a> — starting around $1,199 and $1,299 for matching 256GB baselines.</p></div><div class="live-content"><time datetime="2026-09-09T15:01:21+00:00">September 9, 2026 – 11:01 AM</time><h2 id="overhyped-versus-underhyped-gadgets-apple-could-reveal">Overhyped versus underhyped gadgets Apple could reveal</h2>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7683546163210882318" data-video-id="7683546163210882318" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ Wii Shop Channel Trap - OSRSBeatz" href="https://www.tiktok.com/music/Wii-Shop-Channel-Trap-6866382651020806146">♬ Wii Shop Channel Trap - OSRSBeatz</a></section>                    </blockquote></div>                <p>Our very own <a href="https://www.tomsguide.com/author/mark-spoonauer">Mark Spoonauer</a> and <a href="https://www.tomsguide.com/author/kate-kozuch">Kate Kozuch</a> are on the ground at Apple Park to cover everything at the "Surprise and Shine" event.</p><p>But before the keynote starts, they're breaking down all the biggest rumors ahead of the event. Specifically, they debate about the most overhyped and underhyped Apple devices that have been rumored for some time now.</p></div><div class="live-content"><time datetime="2026-09-09T15:09:56+00:00">September 9, 2026 – 11:09 AM</time><h2 id="i-love-the-galaxy-z-fold-8-so-i-have-higher-expectations-for-the-iphone-duo">I LOVE the Galaxy Z Fold 8, so I have higher expectations for the iPhone Duo</h2><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="F6qr2SDN3gLqxsmgpqVYsY" name="Fold 8 back 2" alt="Samsung Galaxy Z Fold 8" src="https://cdn.mos.cms.futurecdn.net/F6qr2SDN3gLqxsmgpqVYsY.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I'll be the first to admit that changing to a different aspect ratio is exactly what made me (and many others) fall in love with the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Samsung Galaxy Z Fold 8</a>. After spending eight generations relentlessly refining the book-style foldable, and the Galaxy Z Fold 8 feels like the culmination of that effort.</p><p>Between its razor-thin chassis, nearly imperceptible crease, and mature multitasking software, it finally turned the foldable promise into an uncompromising daily driver. Because the bar is set so ridiculously high, I have higher expectations for the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Duo</a>.</p><p>Entering the game this late means Apple can't just release a novel device because it has to solve the pain points that even seasoned foldable makers still wrestle with. If the Duo commands a rumored $2,000 price tag, it needs to deliver more than just premium industrial design.</p></div><div class="live-content"><time datetime="2026-09-09T15:15:16+00:00">September 9, 2026 – 11:15 AM</time><h2 id="does-not-having-a-telephoto-camera-a-dealbreaker-for-the-iphone-duo">Does not having a telephoto camera a dealbreaker for the iPhone Duo?</h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/eMmm53bfgmDEtzFSYozQXT.jpg" alt="Google Pixel 11 Pro Fold camera sample." /><figcaption>Google Pixel 11 Pro Fold.<small role="credit">John Velasco / Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/aZdupmmy6Wby3pQFYivZq.jpg" alt="Samsung Galaxy Z Fold 8 Ultra camera sample." /><figcaption>Samsung Galaxy Z Fold 8 Ultra.<small role="credit">John Velasco / Tom's Guide</small></figcaption></figure></figure><p>Dropping an estimated $2,000 on a flagship phone usually guarantees top-tier imaging hardware, which exposes one of the issues I have knowing that the iPhone Duo is rumored to not have a dedicated telephoto camera. I've put the <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold</a> and the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> through their paces, the gap between having dedicated zoom optics and relying on digital cropping is impossible to overlook.</p><p>In my real-world shooting, Google’s foldable holds the clear upper hand. The periscope setup on the Pixel 11 Pro Fold consistently pulls in sharper, cleaner detail at 5x and beyond — rendering the sign in the gallery above better than the Fold 8 Ultra.</p><p>If Apple relies purely on high-resolution sensor crop from the main camera to handle magnification, zoom quality is going to hit a hard ceiling past 2x. On a device built to showcase Apple’s hardware engineering at the highest level, skipping a dedicated telephoto feels like a compromise. What do you think?</p></div><div class="live-content"><time datetime="2026-09-09T15:22:50+00:00">September 9, 2026 – 11:22 AM</time><h2 id="badges-in-hand-let-39-s-go">Badges in hand, let's go!</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="q23RMr5p4b7YijuCqJ8BPe" name="Apple surprise and shine" alt="Apple surprise and shine." src="https://cdn.mos.cms.futurecdn.net/q23RMr5p4b7YijuCqJ8BPe.jpg" mos="" align="middle" fullscreen="" width="2000" height="1124" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>There's nothing quite like being at Apple Park for an iPhone event and now that we have our badges in hand, the countdown has begun. Without a doubt, we're eager to see what new gadgets Apple plans to reveal. Or perhaps get teasers on some other upcoming stuff the company's planning to officially reveal later one.</p></div><div class="live-content"><time datetime="2026-09-09T15:33:39+00:00">September 9, 2026 – 11:33 AM</time><h2 id="iphone-duo-could-end-up-being-the-thinnest-iphone-but-it-can-39-t-ignore-battery-life">iPhone Duo could end up being the thinnest iPhone, but it can't ignore battery life</h2><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Battery size (mAh)</strong></p></td><td  ><p><strong>Battery life (hrs:mins)</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra</strong></p></td><td  ><p>4,883 mAh rumored)</p></td><td  ><p>TBD</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 11 Pro Fold</strong></p></td><td  ><p>4,806 mAh</p></td><td  ><p>12:31</p></td></tr><tr><td class="firstcol " ><p><strong>Motorola Razr Fold</strong></p></td><td  ><p>6,000 mAh</p></td><td  ><p>14:44</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8 Ultra</strong>   </p></td><td  ><p>5,000 mAh</p></td><td  ><p>14:33</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 10 Pro Fold</strong></p></td><td  ><p>5,015 mAh</p></td><td  ><p>12:16</p></td></tr></tbody></table></div><p>If there's one lesson from our testing of the <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold</a>, it’s that driving two displays — especially an expansive inner folding screen — brutally punishes battery life.</p><p>In fact, Google's latest foldable struggled to move the needle in our battery drain test, proving that thin hinges and modest capacities leave little margin for error. What's notable, too, is how Samsung and Motorola are leaning on silicon-carbon batteries in their foldables. That chemistry doesn't just allow them to pack massive capacities, but it does so without making the phones inherently thicker.</p><p>If the iPhone Duo wants to justify its $2,000 price point, Apple's silicon efficiency and iOS 27 power management need to <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-battery-heres-what-we-know-so-far">deliver true all-day longevity</a>.</p></div><div class="live-content"><time datetime="2026-09-09T15:38:58+00:00">September 9, 2026 – 11:38 AM</time><h2 id="could-an-iphone-desktop-mode-finally-be-a-reality-i-hope-so">Could an iPhone desktop mode finally be a reality? I hope so</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5276px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AieHmWF2DYNhYEc6WiBT4n" name="Samsung DeX on Galaxy Z Flip 8" alt="Samsung DeX on Galaxy Z Flip 8." src="https://cdn.mos.cms.futurecdn.net/AieHmWF2DYNhYEc6WiBT4n.jpg" mos="" align="middle" fullscreen="" width="5276" height="2968" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Hear me out: I've been waiting for Apple to come out with an <a href="https://www.tomsguide.com/phones/iphones/ios-19-could-add-a-desktop-mode-to-iphone-and-thats-a-fantastic-idea">iPhone desktop mode</a> to rival what other phone makers are offering with their flagships. </p><p>For example, the new <a href="https://www.tomsguide.com/phones/samsung-phones/i-just-tried-the-new-samsung-dex-on-the-galaxy-z-fold-8-and-it-has-one-huge-upgrade">Samsung DeX</a> on the Galaxy Z Fold 8, Z Fold 8 Ultra, and Z Flip 8 prove that foldables can genuinely act as mini PCs, thanks to a major upgrade that introduces four distinct virtual workspaces capable of running up to 20 apps at once.</p><p>If the iPhone Duo enters the market as a $2,000 hybrid device, Apple can’t just offer oversized iOS icons. It needs an equivalent desktop mode that kicks in when tethered to an external monitor. Without desktop-style windowing and multi-workspace organization, Apple will struggle to match the raw productivity power Samsung has spent years refining.</p></div><div class="live-content"><time datetime="2026-09-09T15:44:36+00:00">September 9, 2026 – 11:44 AM</time><h2 id="a-quick-tour-of-the-food-spread-at-apple">A quick tour of the food spread at Apple!</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097706366362407317"><p lang="en" dir="ltr">The spread at Apple Park #appleevent pic.twitter.com/12f3aslcNO<a href="https://twitter.com/cantworkitout/status/2097706366362407317">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>There's nothing like seeing the food lined up at the Steve Jobs Theater as people enter the venue! When you're expecting big things later on, having this kind of variety is just what you need to survive a multi-hour hardware marathon.</p></div><div class="live-content"><time datetime="2026-09-09T15:48:49+00:00">September 9, 2026 – 11:48 AM</time><h2 id="last-minute-iphone-duo-rumors-you-should-know-about">Last-minute iPhone Duo rumors you should know about</h2>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7683555698168319246" data-video-id="7683555698168319246" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ Synthwave - Wiliam Geek" href="https://www.tiktok.com/music/Synthwave-7407812545971587089">♬ Synthwave - Wiliam Geek</a></section>                    </blockquote></div>                <p>Apple’s widely tipped to finally introduce its foldable, the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-apples-first-foldable-usd2-000-price-release-date-as-early-as-october">iPhone Duo</a>, pairing a 5.5-inch outer cover screen with an expansive 7.8-inch inner one that measures just 4.5mm unfolded.</p><p>Late leaks point to a starting price of $2,000 for 256GB of storage, undercutting early fears of an even steeper markup. However, chasing that ultra-thin chassis means accepting first-gen compromises, including a dual-camera setup with no dedicated telephoto lens and a rumored release date slipping into October.</p></div><div class="live-content"><time datetime="2026-09-09T15:53:58+00:00">September 9, 2026 – 11:53 AM</time><h2 id="the-crowd-continues-to-grow">The crowd continues to grow!</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="R7vRQPtNX85WSGDcKRXnoM" name="Apple surprise and shine" alt="Apple surprise and shine." src="https://cdn.mos.cms.futurecdn.net/R7vRQPtNX85WSGDcKRXnoM.jpg" mos="" align="middle" fullscreen="" width="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>We're less than an hour from when the festivities are slated to start, but the Steve Jobs Theater is quickly filling up with reporters, influencers, analysts, and guests who are eager to see what Apple reveals.</p></div><div class="live-content"><time datetime="2026-09-09T16:00:10+00:00">September 9, 2026 – 12:00 PM</time><h2 id="gurman-says-you-might-not-see-these-other-apple-devices-at-the-event">Gurman says you might not see these other Apple devices at the event</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097687667471466751"><p lang="en" dir="ltr">IF you don't see the Apple TV, HomePod mini, home display and touch MacBook today, don't worry. It's only September.<a href="https://twitter.com/cantworkitout/status/2097687667471466751">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p><a href="https://x.com/markgurman/status/2097687667471466751?s=46" target="_blank">Bloomberg's Mark Gurman</a> has been busy over the last 24 hours, but he doesn't expect to see announcements for other previously rumored devices, like an updated Apple TV 4K or a HomePod mini refresh.</p><p>Clearly, the company has its hands full with the iPhone 18 Pro, iPhone 18 Pro Max, and iPhone Duo — so it's no surprise that secondary hardware might sit out this event.</p></div><div class="live-content"><time datetime="2026-09-09T16:15:04+00:00">September 9, 2026 – 12:15 PM</time><h2 id="take-a-look-inside-the-countdown-is-on-at-steve-jobs-theater">Take a look inside: The countdown is on at Steve Jobs Theater!</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097719045890195758"><p lang="en" dir="ltr">Inside the #appleevent all this to see the AirPods 5? 😉 pic.twitter.com/gktcWhGEbR<a href="https://twitter.com/cantworkitout/status/2097719045890195758">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>We're officially headed down the glass stairs and into the auditorium! As you can see in the video, the space is quickly packing in with press, analysts, and creators securing their spots.</p></div><div class="live-content"><time datetime="2026-09-09T16:24:59+00:00">September 9, 2026 – 12:24 PM</time><h2 id="iphone-duo-is-probably-going-to-be-the-thinnest-iphone-ever">iPhone Duo is probably going to be the thinnest iPhone ever</h2><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Thinness</strong></p></td><td  ><p><strong>Weight</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra (rumored)</strong></p></td><td  ><p>4.5 – 4.8 mm</p></td><td  ><p>8.1 – 8.5 ounces (230 – 241 grams</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8</strong></p></td><td  ><p>4.5 mm</p></td><td  ><p>7.09 ounces (201 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8 Ultra</strong></p></td><td  ><p>4.1 mm</p></td><td  ><p>7.58 ounces (215 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Motorola Razr Fold</strong></p></td><td  ><p>4.7 mm</p></td><td  ><p>8.6 ounces (243 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 11 Pro Fold</strong></p></td><td  ><p>4.8 mm</p></td><td  ><p>8.64 ounces (245 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Oppo Find N6</strong></p></td><td  ><p>4.21 mm</p></td><td  ><p>7.94 ounces (225 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Honor Magic V6</strong></p></td><td  ><p>4 mm</p></td><td  ><p>7.72 ounces (219 grams)</p></td></tr></tbody></table></div><p>Notebook-style foldables have advantages over traditional slabs, like how they offer larger screens. However, the notable thing about the iPhone Duo is how it's shaping up to be <a href="https://www.tomsguide.com/phones/iphones/the-iphone-ultra-will-be-the-thinnest-iphone-ever-heres-how-it-will-stack-up-to-other-foldables">the thinnest iPhone ever</a>.</p><p>Tipped to measure just 4.5mm unfolded and around 9mm closed, the iPhone Duo easily undercuts the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air</a> to claim the title of thinnest iPhone in history. While it won't dethrone the razor-thin Galaxy Z Fold 8 Ultra or the featherweight Magic V6, its 230–241g weight and slim profile put it right in line with the iPhone 17 Pro Max — giving users a 7.8-inch inner canvas without the unwieldy bulk of early-generation foldables.</p></div><div class="live-content"><time datetime="2026-09-09T16:32:17+00:00">September 9, 2026 – 12:32 PM</time><h2 id="the-iphone-duo-could-justify-the-iphone-air-39-s-biggest-missteps">The iPhone Duo could justify the iPhone Air's biggest missteps</h2><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="bWRiHr2xAWuu7w7QFRLsq" name="iPhone Air-18" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/bWRiHr2xAWuu7w7QFRLsq.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>When Apple introduced the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air</a>, it proved the company could engineer an impossibly thin 5.6mm chassis — but it came at the cost of crippling compromises. Between a single rear camera, cramped battery life that trailed the rest of the lineup, and a downclocked chip, the Air prioritized sheer thinness over real-world practicality.</p><p>Yet, the iPhone Duo represents the exact redemption arc Apple needs. Rather than obsessing over thinness, Apple could use what it learns with the Duo to make the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-rumors-5-biggest-expected-upgrades">iPhone Air 2</a> way better.</p></div><div class="live-content"><time datetime="2026-09-09T16:35:08+00:00">September 9, 2026 – 12:35 PM</time><h2 id="apple-ceo-john-ternus-teases-what-could-be-a-variable-aperture-camera">Apple CEO John Ternus teases what could be a variable aperture camera</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097672038781763614"><p lang="en" dir="ltr">pic.twitter.com/CLu9eRDP5b<a href="https://twitter.com/cantworkitout/status/2097672038781763614">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>With less than 30 minutes from the start of the event, new <a href="https://x.com/johnternus/status/2097672038781763614?s=46" target="_blank">Apple CEO John Ternus shares a teaser video on X </a>showing what could be a variable aperture camera. You can watch in the clip above how the light shines down to what appears to be a lens. While this is interesting, we're eager to see how Apple sells a feature like this to the general consumer.</p></div><div class="live-content"><time datetime="2026-09-09T16:42:43+00:00">September 9, 2026 – 12:42 PM</time><h2 id="we-39-re-in-our-seats">We're in our seats!</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="jyYvdmjpA7iaMuFzwYbfhH" name="Apple surprise and shine" alt="Apple surprise and shine." src="https://cdn.mos.cms.futurecdn.net/jyYvdmjpA7iaMuFzwYbfhH.jpg" mos="" align="middle" fullscreen="" width="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 doors have opened up to the Steve Jobs Theater and we're in our seats ready to see what Apple has in store for us!</p></div><div class="live-content"><time datetime="2026-09-09T16:47:40+00:00">September 9, 2026 – 12:47 PM</time><h2 id="place-your-bet-where-does-the-iphone-duo-land-on-an-all-time-greatest-list">Place your bet — where does the iPhone Duo land on an all-time greatest list?</h2><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eJ9grX"></div>                            </div>                            <script src="https://kwizly.com/embed/eJ9grX.js" async></script><p>With time winding down, all eyes are on Apple and what you usher in a new era for the company. There's no arguing how the company's line of slate iPhone have dominated the landscape, but where does the iPhone Duo land on an all-time greatest list? Is it higher than any of the other notable classics above? Let us know.</p></div><div class="live-content"><time datetime="2026-09-09T16:56:07+00:00">September 9, 2026 – 12:56 PM</time><h2 id="this-is-your-5-minute-warning">This is your 5-minute warning</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/39BalPDuTo0" allowfullscreen></iframe></div></div><p>We're less than 5 minutes away from the start, so your best way of keeping up with the action is to watch the livestream above.</p></div><div class="live-content"><time datetime="2026-09-09T17:00:19+00:00">September 9, 2026 – 1:00 PM</time><h2 id="apple-ceo-john-ternus-takes-stage">Apple CEO John Ternus takes stage</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="jjLx7dhPBJeJTFHTLeQbzf" name="Apple surprise and shine" alt="Apple surprise and shine." src="https://cdn.mos.cms.futurecdn.net/jjLx7dhPBJeJTFHTLeQbzf.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>Apple's new CEO steps up and introduces the crowd here at the Steve Jobs Theater. "We want our products to be powerful but also simple," explains Ternus to the crowd. "We're going to continue changing the world."</p></div><div class="live-content"><time datetime="2026-09-09T17:02:23+00:00">September 9, 2026 – 1:02 PM</time><h2 id="39-you-want-a-great-opening-scene-39">'You want a great opening scene?'</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="5fZn2fC8XPiTJv7nS8MgzA" name="Apple Event — September 9 3-1 screenshot" alt="Not looking at an explosion, shot on iPhone at Apple Surprise and Shine" src="https://cdn.mos.cms.futurecdn.net/5fZn2fC8XPiTJv7nS8MgzA.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>Apple is kicking off its event with a short video that says it's shot on iPhone, which we presumably think is the iPhone 18 Pro or 18 Pro Max. It look pretty legit, complete with cinematic takes and action.</p></div><div class="live-content"><time datetime="2026-09-09T17:04:36+00:00">September 9, 2026 – 1:04 PM</time><h2 id="tim-cook-makes-a-39-main-character-39-cameo">Tim Cook makes a 'main character' cameo</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="HBxLGXdq6vvMba59EWmbCP" name="Apple Event — September 9 5-7 screenshot" alt="John Ternus at Apple Surprise and Shine" src="https://cdn.mos.cms.futurecdn.net/HBxLGXdq6vvMba59EWmbCP.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>Towards the end of the opening video, we see Tim Cook mentioning about the "main character," which he then proceeds to point behind him to reveal John Ternus.</p></div><div class="live-content"><time datetime="2026-09-09T17:07:35+00:00">September 9, 2026 – 1:07 PM</time><h2 id="iphone-is-the-personal-intelligent-hub">iPhone is the personal intelligent hub</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="q6M9jPsoxRU45XNxiS3off" name="Apple Event — September 9 7-28 screenshot" alt="John Ternus next to Apple software and hardware stack" src="https://cdn.mos.cms.futurecdn.net/q6M9jPsoxRU45XNxiS3off.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>Apple CEO John Ternus starts off the show talking about Apple Intelligence first, going on to say how the iPhone is the personal intelligent hub. "It's personal intelligence that's personal," explains Ternus.</p></div><div class="live-content"><time datetime="2026-09-09T17:10:43+00:00">September 9, 2026 – 1:10 PM</time><h2 id="apple-iphone-18-pro-and-18-pro-max-are-official">Apple iPhone 18 Pro and 18 Pro Max are official!</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Z3HUDir2Yvo6wraL8ESsy7" name="Apple Event — September 9 9-59 screenshot" alt="iPhone 18 Pro at Apple Surprise and Shine" src="https://cdn.mos.cms.futurecdn.net/Z3HUDir2Yvo6wraL8ESsy7.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>Ternus reveals the iPhone 18 Pro and 18 Pro Max first, going on to say how it has the longest battery life in an iPhone, most advanced cameras.</p><p>The video initially shows an iPhone 17 Pro that shot video of the moon but end by saying "this is what happens when you go to the moon and ask what's next."</p></div><div class="live-content"><time datetime="2026-09-09T17:12:59+00:00">September 9, 2026 – 1:12 PM</time><h2 id="siri-ai-brings-more-advanced-features">Siri AI brings more advanced features</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="mkxU4JkbkGwurkJH7N2xFY" name="Apple Event — September 9 13-49 screenshot" alt="Expressive voices in Siri AI at Apple Surprise and Shine" src="https://cdn.mos.cms.futurecdn.net/mkxU4JkbkGwurkJH7N2xFY.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>Before we learn more about the hardware for the iPhone 18 Pro and 18 Pro Max, Apple's taking the time to talk about new capabilities coming to its new phones. In addition to handling task automations, you'll also get the new Siri AI app to see all of your interactions.</p></div><div class="live-content"><time datetime="2026-09-09T17:17:02+00:00">September 9, 2026 – 1:17 PM</time><h2 id="apple-a20-pro-sets-a-new-bar-for-mobile-computing">Apple A20 Pro sets a new bar for mobile computing</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AzHo485TVydoAHMxQVcQk3" name="Apple Event — September 9 16-33 screenshot" alt="A20 Pro at Apple Surprise and Shine" src="https://cdn.mos.cms.futurecdn.net/AzHo485TVydoAHMxQVcQk3.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>Apple's newest silicon is built using the new 2-nanometer manufacturing process, consisting of a 6-core CPU and 4 efficiency cores, which deliver a 20% improvement. The GPU has 7-core design with 40% increased performance. </p></div><div class="live-content"><time datetime="2026-09-09T17:19:40+00:00">September 9, 2026 – 1:19 PM</time><h2 id="vapor-chamber-and-chip-packaging-will-deliver-maximum-performance-with-a20-pro-chip">Vapor chamber and chip packaging will deliver maximum performance with A20 Pro chip</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="DqUedc8StcXSG4MhugjDkP" name="Apple Event — September 9 19-34 screenshot" alt="iPhone 18 Pro new vapor chamber" src="https://cdn.mos.cms.futurecdn.net/DqUedc8StcXSG4MhugjDkP.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>A next-generation vapor chamber has three times the surface area, while a copper layer adds to its heat dissipation. As a result, it delivers a 40% sustained performance improvement.</p></div><div class="live-content"><time datetime="2026-09-09T17:21:38+00:00">September 9, 2026 – 1:21 PM</time><h2 id="improved-battery-life-performance-on-iphone-18-pros">Improved battery life performance on iPhone 18 Pros</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="taavmtuAbyi5bPdYnwydGb" name="Apple Event — September 9 21-23 screenshot" alt="iPhone 18 Pro battery life" src="https://cdn.mos.cms.futurecdn.net/taavmtuAbyi5bPdYnwydGb.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>On top of offering superior processing performance, the battery life is going to be much improved with up to  24 hours per charge with the iPhone 18 Pro and 30 hours with the Pro Max. Apple also says you get 50% battery life in 15 minutes.</p></div><div class="live-content"><time datetime="2026-09-09T17:24:22+00:00">September 9, 2026 – 1:24 PM</time><h2 id="variable-aperture-main-camera-confirmed">Variable aperture main camera confirmed!</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="zik8HSxbxZkhACoa7RNR5" name="Apple Event — September 9 23-15 screenshot" alt="Fusion Main Camera on iPhone 18 Pro" src="https://cdn.mos.cms.futurecdn.net/zik8HSxbxZkhACoa7RNR5.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>Apple didn't wait long to reveal the 48MP main camera with variable aperture on the iPhone 18 Pros, giving users even more creative shots.</p></div><div class="live-content"><time datetime="2026-09-09T17:26:01+00:00">September 9, 2026 – 1:26 PM</time><h2 id="pro-controls-paired-with-variable-aperture">Pro Controls paired with variable aperture</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="HhGRiHZ8d4hXRLpaxyqFEH" name="Apple Event — September 9 25-43 screenshot" alt="Pro Controls on iPhone 18 Pro" src="https://cdn.mos.cms.futurecdn.net/HhGRiHZ8d4hXRLpaxyqFEH.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>Apple's rolling through all the creative ways a variable aperture can be used effectively with Pro Controls, like being able to use variable aperture to create motion blur or also freeze photos.</p></div><div class="live-content"><time datetime="2026-09-09T17:29:17+00:00">September 9, 2026 – 1:29 PM</time><h2 id="upgraded-dynamic-island-is-smaller-shows-more-activities">Upgraded Dynamic Island is smaller, shows more Activities</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="mX23Fz2XDriJNsC4wUHxjm" name="Apple Event — September 9 29-33 screenshot" alt="Smaller Dynamic Island on iPhone 18 Pro" src="https://cdn.mos.cms.futurecdn.net/mX23Fz2XDriJNsC4wUHxjm.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>With the Dynamic Island on the iPhone 18 Pro and 18 Pro Max, Apple slims its size, but it's now able to show up to three Live Activities.</p></div><div class="live-content"><time datetime="2026-09-09T17:31:58+00:00">September 9, 2026 – 1:31 PM</time><h2 id="iphone-18-pro-and-18-pro-max-start-at-1-199-and-1-299">iPhone 18 Pro and 18 Pro Max start at $1,199 and $1,299</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="3nf798kyYtzdTgorhQMVMD" name="Apple Event — September 9 31-41 screenshot" alt="iPhone 18 Pro pricing" src="https://cdn.mos.cms.futurecdn.net/3nf798kyYtzdTgorhQMVMD.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>Apple spends a short time talking about new accessories that include cases and wrist straps, but the bigger reveal is the price of its new phones:</p><ul><li><strong>iPhone 18 Pro: </strong>$1,199</li><li><strong>iPhone 18 Pro Max:</strong> $1,299</li></ul></div><div class="live-content"><time datetime="2026-09-09T17:36:27+00:00">September 9, 2026 – 1:36 PM</time><h2 id="airpods-5-has-best-anc-in-an-open-ear-design">AirPods 5 has best ANC in an open-ear design</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bHwv6kAcCcAwYDSLpZumAf" name="Apple Event — September 9 36-26 screenshot" alt="AirPods 5 Pricing" src="https://cdn.mos.cms.futurecdn.net/bHwv6kAcCcAwYDSLpZumAf.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>AirPods 5 have an open ear fit with next-gen adaptive EQ, better Siri features, real-time Live Translation, durable design that handles rain, 4 hours of listening with ANC with up to 20 hours with charging case. It's priced at $129 without ANC.</p><p>Another model has a touch sensitive stem that offers 5 hours of battery with ANC, comes with wireless charging case, all priced at $149.</p></div><div class="live-content"><time datetime="2026-09-09T17:40:16+00:00">September 9, 2026 – 1:40 PM</time><h2 id="apple-watch-series-12-and-watch-ultra-4-revealed">Apple Watch Series 12 and Watch Ultra 4 revealed</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kzVjuUU8B5U9svoLLPJgJE" name="Apple Event — September 9 39-15 screenshot" alt="Apple Watch Ultra 4 and Apple Watch 12 at Apple Surprise and Shine" src="https://cdn.mos.cms.futurecdn.net/kzVjuUU8B5U9svoLLPJgJE.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>Advanced sensor array monitor sleep, health, and fitness. Both offer Health Sensing System, packs larger electrode area, better optical seniung with photodiode, larger, more power efficient green LEDs offer better tracking.</p><p>Background readings are taken every 5 seconds, record heart rate variability every 5 minutes.</p></div><div class="live-content"><time datetime="2026-09-09T17:43:50+00:00">September 9, 2026 – 1:43 PM</time><h2 id="new-apple-watches-focus-on-heart-rate-variability">New Apple Watches focus on heart rate variability</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='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.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>High-frequency heart rate data, which is now a complication you can add.</p><p>Health Sensing System offers Readiness tells you when to push or hold back. It analyzes your data to set goals and challenges for yourself, so the score changes dynamically to give you an overview.</p><p>Health Age gather metrics to give you what habits impact your age the most. You can even order a $119 lab work right through the app.</p></div><div class="live-content"><time datetime="2026-09-09T17:48:09+00:00">September 9, 2026 – 1:48 PM</time><h2 id="audio-intelligence-unlocks-more-helpful-tools-on-apple-watch">Audio Intelligence unlocks more helpful tools on Apple Watch</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='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.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>With built-in mics and new silicon, new Apple Intelligence features includes three new Audio Intelligence:</p><ul><li><strong>Sound Recognition</strong> that can discern sounds like alarms.</li><li><strong>Live Rewind</strong> that lets you go back in time 15 seconds and basically acts as a transcript.</li><li><strong>Siri Recap </strong>takes notes that can summarize.</li></ul></div><div class="live-content"><time datetime="2026-09-09T17:50:49+00:00">September 9, 2026 – 1:50 PM</time><h2 id="apple-watch-series-12-in-more-colors-and-finishes">Apple Watch Series 12 in more colors and finishes</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="FR2tN8LHY9N8dPaGWDFtfm" name="Apple Event — September 9 51-26 screenshot" alt="New Apple Watch 12 bands" src="https://cdn.mos.cms.futurecdn.net/FR2tN8LHY9N8dPaGWDFtfm.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>Apple Watch Series 12 come in more colors and finishes, including polish finishes and ceramic materials. There are also new bands, including from Nike.</p></div><div class="live-content"><time datetime="2026-09-09T17:52:55+00:00">September 9, 2026 – 1:52 PM</time><h2 id="apple-watch-ultra-4-starts-at-499">Apple Watch Ultra 4 starts at $499</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='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.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>Apple Watch Series 12 starts at $399, while Apple Watch Ultra 4 start at $799.  Thankfully they don't get any price hikes this year.</p></div><div class="live-content"><time datetime="2026-09-09T17:57:01+00:00">September 9, 2026 – 1:57 PM</time><h2 id="39-but-actually-there-39-s-one-more-thing-39-say-hello-to-iphone-duo">'But actually there's one more thing' — say hello to iPhone Duo</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wEQDPuXx2e5CdQr77P2MWf" name="Apple Event — September 9 57-37 screenshot" alt="iPhone Duo close din hand" src="https://cdn.mos.cms.futurecdn.net/wEQDPuXx2e5CdQr77P2MWf.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>While it appears it's a wrap with the Apple event, John Ternus says that there's just one more thing -- going on to reveal a foldable device called the iPhone Duo.</p><p>True to all the rumors and leaks, the iPhone Duo is a "wide" notebook style foldable phone. </p></div><div class="live-content"><time datetime="2026-09-09T17:59:45+00:00">September 9, 2026 – 1:59 PM</time><h2 id="iphone-duo-39-s-biggest-features-revealed">iPhone Duo's biggest features revealed</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="6C7CZojJWSoQwTvCAXJw4j" name="Apple Event — September 9 58-18 screenshot" alt="iPhone Duo closed and open" src="https://cdn.mos.cms.futurecdn.net/6C7CZojJWSoQwTvCAXJw4j.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><ul><li>FaceTime camera is hidden underneath the display</li><li>Hinge mechanism feels smooth with an integrated manet</li><li>Thinnest iPhone ever</li><li>Aero-space titanium</li><li>Largest display in an iPhone</li></ul></div><div class="live-content"><time datetime="2026-09-09T18:03:47+00:00">September 9, 2026 – 2:03 PM</time><h2 id="even-more-iphone-duo-specs-confirmed">Even more iPhone Duo specs confirmed</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="gwC2fHbKhjmGfVkQUeicvT" name="Apple Event — September 9 1-3-15 screenshot" alt="iPhone Duo colors" src="https://cdn.mos.cms.futurecdn.net/gwC2fHbKhjmGfVkQUeicvT.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><ul><li>7.6-inch Super Retina XDR display, 50% larger in size than iPhone 18 Pro Max.</li><li>5.4-inch outer display provides 90% of viewing screen of iPhone 18 Pro.</li><li>Apple Pencil support to come later.</li><li>Touch ID is integrated into the side button.</li><li>Unlock phone with Apple Watch.</li><li>Speakers on top and bottom edges.</li><li>Grade 5 titanium construction.</li><li>Ceramic Shield on back, Ceramic Shield 2 on front</li></ul></div><div class="live-content"><time datetime="2026-09-09T18:06:21+00:00">September 9, 2026 – 2:06 PM</time><h2 id="apps-adapt-to-how-you-position-the-iphone-duo">Apps adapt to how you position the iPhone Duo</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="hiCeFnGaANu9zsBVFBDn58" name="Apple Event — September 9 1-5-3 screenshot" alt="iPhone Duo side by side apps" src="https://cdn.mos.cms.futurecdn.net/hiCeFnGaANu9zsBVFBDn58.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>This is the biggest thing that will differentiate the iPhone Duo from other foldable phones, as apps will dynamically scale and change depending on how you orient and use it. The demo so far looks pretty convincing, but developers will need to optimize how they look.</p></div><div class="live-content"><time datetime="2026-09-09T18:09:34+00:00">September 9, 2026 – 2:09 PM</time><h2 id="iphone-dup-display-technology-reduces-glare-offers-superior-scratch-protection">iPhone Dup display technology reduces glare, offers superior scratch protection</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="owQW6oWKDWWSAKMEppqFYG" name="Apple Event — September 9 1-8-36 screenshot" alt="Nano Texture glass on iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/owQW6oWKDWWSAKMEppqFYG.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>Nano-texture finishes reduces glare with the main display. It also offers better scratch resistance. All of these layers won't distort over time, with the hinge that consists of over 100 components.</p></div><div class="live-content"><time datetime="2026-09-09T18:12:28+00:00">September 9, 2026 – 2:12 PM</time><h2 id="39-iphone-duo-is-esim-only-worldwide-39">'iPhone Duo is eSIM only worldwide'</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="N3UodsL4VX7ChTdLNtJP4c" name="Apple Event — September 9 1-10-47 screenshot" alt="iPhone Duo internals" src="https://cdn.mos.cms.futurecdn.net/N3UodsL4VX7ChTdLNtJP4c.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>In order to engineer its foldable phone and long battery life, the iPhone Duo is only going to be available as an eSIM-only option worldwide. You get all-day battery life up to 31 hours with the inner display, 44 hours outer display, and 24 hours when using both screens equally. When it come to charging, you'll get 50% in 20 minutes of charging.</p></div><div class="live-content"><time datetime="2026-09-09T18:15:22+00:00">September 9, 2026 – 2:15 PM</time><h2 id="iphone-duo-cameras-offer-new-ways-to-shoot">iPhone Duo cameras offer new ways to shoot</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="uQq56JKBF4Lu8qoNeXMbCF" name="Apple Event — September 9 1-15-9 screenshot" alt="Dual camera face time on iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/uQq56JKBF4Lu8qoNeXMbCF.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>Apple spends time talking about the dual-camera system in the iPhone Duo, including how the Center Stage camera can be used for FaceTime calls. Other creative ways include using the outer screen to capture better selfies.</p></div><div class="live-content"><time datetime="2026-09-09T18:16:48+00:00">September 9, 2026 – 2:16 PM</time><h2 id="iphone-duo-starts-at-1-999">iPhone Duo starts at $1,999</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="TCZapEDrdTsmRuR7ugKsKQ" name="Apple Event — September 9 1-16-20 screenshot" alt="iPhone Duo selfie proped up" src="https://cdn.mos.cms.futurecdn.net/TCZapEDrdTsmRuR7ugKsKQ.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>Apple finally reveals the iPhone Duo's price, which at $1,999, makes a compelling offer. Preorders start October 16 with availability set for October 12.</p></div><div class="live-content"><time datetime="2026-09-09T18:19:43+00:00">September 9, 2026 – 2:19 PM</time><h2 id="and-that-39-s-a-wrap">And that's a wrap!</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="QX3fugY6wAPCv4H622VaQg" name="Apple Event — September 9 1-19-35 screenshot" alt="Apple Surprise and Shine that's a wrap" src="https://cdn.mos.cms.futurecdn.net/QX3fugY6wAPCv4H622VaQg.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>Normally Apple's events are multi-hour marathons, but this one's rather concise. After finishing off its event with the iPhone Duo, Apple had nothing else to share apart from an ending scene that mentions how the event was shot on iPhone and edited on Mac. Stay tuned for our additional coverage!</p></div><div class="live-content"><time datetime="2026-09-09T18:49:08+00:00">September 9, 2026 – 2:49 PM</time><h2 id="which-reveal-were-you-most-impressed-with">Which reveal were you most impressed with?</h2><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-WVkdJO"></div>                            </div>                            <script src="https://kwizly.com/embed/WVkdJO.js" async></script><p>Between John Ternus's keynote debut, the long-awaited unveiling of the $1,999 iPhone Duo, and substantial hardware upgrades for the iPhone 18 Pro series, today wasn’t just another iterative September refresh.</p><p>Apple made a definitive statement that it’s ready to challenge Android's mature foldable dominance on its own terms — even if the omission of a telephoto lens and an October rollout invite scrutiny. Out of all the devices it announced at the event, which one gets your vote?</p></div><div class="live-content"><time datetime="2026-09-09T19:21:29+00:00">September 9, 2026 – 3:21 PM</time><h2 id="samsung-gets-sassy">Samsung gets sassy</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097748103478591990"><p lang="en" dir="ltr">Let us know when you're done reheating our leftovers 😉<a href="https://twitter.com/cantworkitout/status/2097748103478591990">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>Samsung functionally started the foldable phone trend nearly a decade ago with its original Galaxy Fold. </p><p>So, we were expecting some kind of response and the company got a little sassy on X posting:</p><p>"Let us know when you're done reheating our leftovers." </p></div><div class="live-content"><time datetime="2026-09-09T19:40:20+00:00">September 9, 2026 – 3:40 PM</time><h2 id="what-we-know-about-the-iphone-18-pro-and-pro-max">What we know about the iPhone 18 Pro and Pro Max</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="sAFnnQsMDkhrRiPhTeYah9" name="iphone-18-pro-model-unselect-gallery-1-202609" alt="iphone 18 pro and pro max side by side" src="https://cdn.mos.cms.futurecdn.net/sAFnnQsMDkhrRiPhTeYah9.webp" mos="" align="middle" fullscreen="" width="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 new iPhone Pro models aren't big departures from the previous generation but there are some things to get excited about.</p><p>Check out our article to find out <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know">everything you need to know about the iPhone 18 Pro and iPhone 18 Pro Max</a>.</p></div><div class="live-content"><time datetime="2026-09-09T19:59:41+00:00">September 9, 2026 – 3:59 PM</time><h2 id="expect-a-lot-of-microsoft-duo-jokes">Expect a lot of Microsoft Duo jokes</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097749286024863988"><p lang="en" dir="ltr">exclusive: hands-on with the Duo pic.twitter.com/chHv7xfq7R<a href="https://twitter.com/cantworkitout/status/2097749286024863988">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>For any tech journo who has been around a minute and a collector, expect to see a lot of Microsoft Duo jokes.</p><p>Here's an example from <a href="https://x.com/tomwarren/status/2097749286024863988?s=20" target="_blank">The Verge's Tom Warren</a>.</p></div><div class="live-content"><time datetime="2026-09-09T20:21:26+00:00">September 9, 2026 – 4:21 PM</time><h2 id="new-cheaper-airpods">New, cheaper AirPods</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bGcwz5CcYkGkaEMqtgpCEQ" name="Apple Event — September 9 33-22 screenshot" alt="AirPods 5" src="https://cdn.mos.cms.futurecdn.net/bGcwz5CcYkGkaEMqtgpCEQ.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>Apple revealed its new Airpods 5 in two versions, one with a wireless charging case and a base model, with active noise cancellation. </p><p>Both are cheaper than or the same price as the AirPods 4, making it one of the few devices to get a price cut.</p><p>Here's <a href="https://www.tomsguide.com/audio/airpods/apple-airpods-5-officially-announced-here-are-the-upgrades">everything you need to know about the AirPods 5</a>.</p></div><div class="live-content"><time datetime="2026-09-09T20:48:14+00:00">September 9, 2026 – 4:48 PM</time><h2 id="duo-wallpapers">Duo wallpapers</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097762805621637376"><p lang="en" dir="ltr">iPhone Duo Wallpaper (night)(from the usdz file) https://t.co/ToFZozJHCq pic.twitter.com/fjXSFwOgmH<a href="https://twitter.com/cantworkitout/status/2097762805621637376">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>If you're looking for Duo wallpapers, the <a href="https://x.com/BasicAppleGuy/status/2097762805621637376?s=20" target="_blank">Basic Apple Guy on X </a>has you covered. He posted images from the usdz file of two desert shots, one at night and one during day that you can grab.</p><p>These appear to be the same ones we saw during the presentation.</p></div><div class="live-content"><time datetime="2026-09-09T21:02:23+00:00">September 9, 2026 – 5:02 PM</time><h2 id="hands-on-with-the-duo">Hands on with the Duo</h2>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7683620247215049998" data-video-id="7683620247215049998" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ Minimal for news / news suspense(1169746) - Hiraoka Kotaro" href="https://www.tiktok.com/music/Minimal-for-news-news-suspense-1169746-7055051802865862658">♬ Minimal for news / news suspense(1169746) - Hiraoka Kotaro</a></section>                    </blockquote></div>                </div><div class="live-content"><time datetime="2026-09-09T21:29:43+00:00">September 9, 2026 – 5:29 PM</time><h2 id="initial-thoughts-on-the-iphone-duo">Initial thoughts on the iPhone Duo</h2><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="i4QF9zqZdmy4sZPuE8hXFa" name="iphone duo edit 4" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/i4QF9zqZdmy4sZPuE8hXFa.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>We've had some hands-on time with the iPhone Duo, and Tom's Guide Global Editor has some initial thoughts on Apple's first foldable iPhone.</p><p>Check out his<a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice"> iPhone Duo hands-on </a>article for all of the details.</p></div><div class="live-content"><time datetime="2026-09-09T22:04:53+00:00">September 9, 2026 – 6:04 PM</time><h2 id="apple-watch-series-12-and-watch-ultra-4">Apple Watch Series 12 and Watch Ultra 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: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.jpg" mos="" align="middle" fullscreen="" width="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's two new watches, the Series 12 and Ultra 4, aren't too different than their predecessors, but they do come with new chips, a couple of new sensors, and a number of health software upgrades.</p><p>Here's everything you need to know about 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> and the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a>.</p></div><div class="live-content"><time datetime="2026-09-09T22:33:44+00:00">September 9, 2026 – 6:33 PM</time><h2 id="older-lower-end-iphones-are-now-more-expensive">Older, lower-end iPhones are now more expensive</h2><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="ecRd2peLtxYXQxQQvJq3Ge" name="Apple iPhone 17 review" alt="Apple iPhone 17 review." src="https://cdn.mos.cms.futurecdn.net/ecRd2peLtxYXQxQQvJq3Ge.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>Apple only announced the iPhone 18 Pro and iPhone 18 Pro Max today, each with a $100 price increase compared to the iPhone 17 versions.</p><p>However, the lower-end older devices also got $100 price bumps. </p><p>Here are the new prices:</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Starting Price</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Air</strong></p></td><td  ><p>$1,099</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17</strong></p></td><td  ><p>$899</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 16</strong></p></td><td  ><p>$799</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17e</strong></p></td><td  ><p>$699</p></td></tr></tbody></table></div><p>Plus the 256GB version of the iPhone 16 has been axed and the iPhone 16 Plus is no longer for sale.</p></div><div class="live-content"><time datetime="2026-09-09T23:00:16+00:00">September 9, 2026 – 7:00 PM</time><h2 id="iphone-duo-vs-galaxy-z-fold-8">iPhone Duo vs Galaxy Z Fold 8</h2>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7683645046977072415" data-video-id="7683645046977072415" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ Loft Window - Slight Overcast" href="https://www.tiktok.com/music/Loft-Window-7674360528990554122">♬ Loft Window - Slight Overcast</a></section>                    </blockquote></div>                </div><div class="live-content"><time datetime="2026-09-09T23:34:34+00:00">September 9, 2026 – 7:34 PM</time><h2 id="going-hands-on-with-the-apple-watch-ultra-4">Going hands-on with the Apple Watch Ultra 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: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.jpg" mos="" align="middle" fullscreen="" width="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>Tom's Guide Fitness editor Jane McGuire was able to get some <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4#section-apple-watch-ultra-4-hands-on-review-battery-life">hands-on time with the Apple Watch Ultra 4</a>.</p><p>Initially, she was impressed but not every announced feature was available at launch and won't come until much later. So its kind of a wait and see moment. </p></div><div class="live-content"><time datetime="2026-09-10T00:18:46+00:00">September 9, 2026 – 8:18 PM</time><h2 id="hands-on-with-the-apple-watch-series-12">Hands-on with the Apple Watch Series 12</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='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.jpg" mos="" align="middle" fullscreen="" width="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>Fitness managing editor Jane McGuire also had a chance to go <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">hands-on with the Apple Watch Series 12</a>. Her initial impressions? It's a nice upgrade over the previous model, especially now that it has upgraded sensors and a much-needed Readiness score. Best of all? It's the same price as last year's model.</p></div><div class="live-content"><time datetime="2026-09-10T07:58:42+00:00">September 10, 2026 – 3:58 AM</time><h2 id="hands-on-with-the-18-pro-max">Hands-on with the 18 Pro Max</h2><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="HYuuDMJ2Ch2YMUKD2MbYWc" name="iPhone 18 Pro cameras" alt="iPhone 18 Pro cameras" src="https://cdn.mos.cms.futurecdn.net/HYuuDMJ2Ch2YMUKD2MbYWc.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>Alongside the excitement of the new iPhone Duo, we've also got some hands-on time with the iPhone 18 Pro Max. You can read what <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-hands-on-sneaky-awesome-upgrades-but-worth-the-price-hike">Global Editor in Chief Mark Spoonauer thought of Apple's new Pro model</a>.</p><p>In a nutshell, it's the camera upgrades that are likely to be the biggest draw for anyone looking to upgrade.</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/BZi0R_thP9M" allowfullscreen></iframe></div></div></div><div class="live-content"><time datetime="2026-09-10T11:37:15+00:00">September 10, 2026 – 7:37 AM</time><h2 id="apple-watch-ultra-4-reasons-to-buy-and-reasons-to-skip">Apple Watch Ultra 4: Reasons to buy and reasons to skip</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='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.jpg" mos="" align="middle" fullscreen="" width="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>Those fond of an outdoor adventure or two may be eyeing up 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>, especially thanks to improved battery life and enhanced heart rate tracking. Our resident smartwatch guru, Dan Bracaglia, has run through everything the rugged new wearable has to offer and come up with his reasons for and against upgrading.</p><p>Here are his <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">five reasons to buy the Apple Watch Ultra 4 and two reasons to skip it</a>.</p></div><div class="live-content"><time datetime="2026-09-10T11:54:02+00:00">September 10, 2026 – 7:54 AM</time><h2 id="sneaky-price-hikes-have-arrived">Sneaky price hikes have arrived</h2><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="fXQyeewX6f4cMRqqSucB2D" name="iphone17-1 (2)-2" alt="Sage iPhone 17 in hand" src="https://cdn.mos.cms.futurecdn.net/fXQyeewX6f4cMRqqSucB2D.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>While Apple was very upfront about the increased prices for iPhone 18 Pro and Pro Max, it wasn't so eager to advertise the fact those aren't the only devices getting a price hike. All the <a href="https://www.tomsguide.com/phones/iphones/apple-quietly-jacks-the-prices-of-the-iphone-16-iphone-17-and-iphone-air-heres-how-much-youll-pay-now">older iPhones are getting a $100 price bump as well</a>, including iPhone 17, iPhone 17e, iPhone 16 and iPhone Air.</p><p>Considering the newest of those phones came out in February and the oldest of them landed two whole years ago, we have to wonder what Apple is thinking. <a href="https://www.tomsguide.com/phones/iphones/dont-expect-an-iphone-17-discount-at-todays-iphone-event-heres-why">We never expected the iPhone 17 to get the usual price cut</a>, since the iPhone 18 never made an appearance at Surprise and shine, but even we didn't anticipate the prices going up.</p><p>Make sure to grab one of the latest and <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pre-order-deals-heres-how-to-get-apples-new-phones-for-free">best iPhone 17 deals</a> while you can, otherwise you're going to end up paying more than you bargained for.</p></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/news/live/apple-event-live-foldable-iphone-iphone-18-pro-max-apple-watch-12-and-all-the-big-news</link>
                                                                            <description>
                            <![CDATA[ Apple's Surprise and shine launch event is over, but it marked the introduction of the iPhone Duo, iPhone 18 Pro Max, and more. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">Yx29NF9fSEo7wygdrEKVkL</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/EkkdP6fQWMG4nM8U2iq7hX-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 14:16:48 +0000</pubDate>                                                                                                                                <updated>Thu, 10 Sep 2026 23:48:58 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/EkkdP6fQWMG4nM8U2iq7hX-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple Surprise and shine with Duo, 18 Pro Max, AirPods 5 and Apple Watch 12]]></media:description>                                                            <media:text><![CDATA[Apple Surprise and shine with Duo, 18 Pro Max, AirPods 5 and Apple Watch 12]]></media:text>
                                <media:title type="plain"><![CDATA[Apple Surprise and shine with Duo, 18 Pro Max, AirPods 5 and Apple Watch 12]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/EkkdP6fQWMG4nM8U2iq7hX-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <div class="live-content"><p>This week's <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">Apple "Surprise and Shine" event</a> proved to be a historic moment for the company. Not only did it mark the first Apple event helmed by new <a href="https://www.tomsguide.com/phones/iphones/massive-changes-at-apple-john-ternus-takes-over-as-ceo-sept-1-while-tim-cook-moves-to-executive-chairman">CEO John Ternus</a>, but it also catapulted Apple into a new era with its first-ever foldable — 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>The iPhone Duo is packing a 5.4-inch cover screen alongside an expansive 7.6-inch inner display, effectively putting a phone and tablet in a single pocketable chassis. That cutting-edge new form factor, surprisingly enough, starts off at $1,999 / £1,999 cost. </p><p>And we've already got hands-on time with<a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice"> iPhone Duo</a>.</p><p>Beyond the foldable, Apple used the event to reveal other key products like its flagship iPhone 18 Pro and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-farhttps://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know">iPhone 18 Pro Max</a>, 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>, and the rugged <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-12-and-ultra-4-rumors-your-next-apple-watch-could-have-a-ceramic-casehttps://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a>. We also got an official reveal for the <a href="https://www.tomsguide.com/audio/airpods/apple-airpods-5-officially-announced-here-are-the-upgrades">AirPods 5</a>, along with new Siri AI and Apple Intelligence features.</p><p>Here’s everything that was announced at Apple’s biggest showcase of the year and our corresponding early verdicts after getting hands-on with the new tech.</p><h2 class="article-body__section" id="section-how-to-watch-apple-surprise-and-shine-event"><span>How to watch Apple “Surprise and Shine” event</span></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/39BalPDuTo0" allowfullscreen></iframe></div></div><p>You can stay up to date with the latest announcements from Apple’s September hardware event by tuning in to the official livestream, accessible directly via a browser on Apple's website. Alternatively, you can catch the stream through <a href="https://www.youtube.com/live/39BalPDuTo0?si=k4UmDQpUDktfCMRc">Apple's official YouTube channel, </a>the Apple TV app or embedded below.</p><h2 class="article-body__section" id="section-biggest-announcements"><span>Biggest announcements</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="sAFnnQsMDkhrRiPhTeYah9" name="iphone-18-pro-model-unselect-gallery-1-202609" alt="iphone 18 pro and pro max side by side" src="https://cdn.mos.cms.futurecdn.net/sAFnnQsMDkhrRiPhTeYah9.webp" mos="" align="middle" fullscreen="" width="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><ul><li><a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-official-price-release-date-specs-and-everything-you-need-to-know"><strong>iPhone Duo:</strong></a> Apple’s first foldable smartphone is debuts with an ultra-thin, book-style folding design, a 7.6-inch inner display, Touch ID integration and $1,999 price tag.</li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know"><strong>iPhone 18 Pro & iPhone 18 Pro Max:</strong> </a>Apple’s next-generation flagship Pro phones feature a powerful 2nm A20 Pro chip, smaller Dynamic Island cutouts, larger batteries, and exclusive camera enhancements like a variable aperture.</li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-announced-everything-you-need-to-know-about-the-new-flagship-apple-watch"><strong>Apple Watch Series 12:</strong></a> Apple's core smartwatch update introduce new health-tracking capabilities, refined internal hardware., and more sensors.</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:</strong></a><strong> </strong>The latest iteration of Apple’s outdoor-focused wearable is anticipated to deliver enhanced satellite connectivity, expanded battery life, and upgraded sensors.</li><li><strong></strong><a href="https://www.tomsguide.com/audio/airpods/airpods-ultra-everything-we-know-so-far-about-apples-camera-earbuds"><strong>AirPods 5:</strong></a> This upgraded version of the standard AirPods comes with a few upgrades and a design similar to that of AirPods 4. Expect 4 hours of listening with ANC and a $129 starting price for the version without ANC.</li></ul><h3 class="article-body__section" id="section-apple-event-live-updates"><span>Apple event: Live Updates</span></h3></div><div class="live-content"><time datetime="2026-09-09T14:17:10+00:00">September 9, 2026 – 10:17 AM</time><h2 id="where-could-the-iphone-duo-land-among-the-all-time-greats">Where could the iPhone Duo land among the all-time greats?</h2><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eJ9grX"></div>                            </div>                            <script src="https://kwizly.com/embed/eJ9grX.js" async></script><p>If the iPhone Duo delivers on its promise, it faces a serious legitimacy test when stacked against an all-time greatest list. Every transformative Apple hardware leap — from the original and my personal favorite, the iPhone 4, to the <a href="https://www.tomsguide.com/us/iphone-x,review-4800.html">iPhone X</a> redefining modern smartphones — fundamentally rewrote what a phone should be. By finally breaking into a foldable design, the Duo undeniably earns a spot as the company’s most ambitious iPhone in nearly a decade.</p><p>Yet true all-time greatness isn’t crowned on ambition alone. A steep $2,000 price tag, inevitable first-gen trade-offs like missing telephoto lenses or Face ID, and early ecosystem growing pains could mean the Duo may land more like the original Apple Watch or the first iPad. It's poised to disrupt the market, but whether it tops Apple's greatest releases remains to be seen. What do you think?</p></div><div class="live-content"><time datetime="2026-09-09T14:24:10+00:00">September 9, 2026 – 10:24 AM</time><h2 id="why-great-hardware-won-39-t-be-enough-to-save-the-iphone-duo">Why great hardware won't be enough to save the iPhone Duo</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2879px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="77ZTA3cHAT3JoQVSNWAUNW" name="Galaxy Z Fold 8-15" alt="Galaxy Z Fold 8 shown in hand" src="https://cdn.mos.cms.futurecdn.net/77ZTA3cHAT3JoQVSNWAUNW.jpg" mos="" align="middle" fullscreen="" width="2879" height="1619" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>While rumors obsess over crease-free displays and ultra-thin hinges, Apple’s upcoming foldable faces a much bigger hurdle: software.</p><p>This is exactly the one thing I argue that will make or break the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Duo</a>, seeing how an expensive 7.8-inch folding canvas doesn't stand a chance unless <a href="https://www.tomsguide.com/phones/iphones/ios-27-public-beta-hands-on-preview-the-new-siri-and-apple-intelligence-features-completely-changed-how-i-use-my-iphone">iOS 27</a> completely rethinks the user experience. In order to genuinely challenge rival foldables, like the <a href="https://www.tomsguide.com/phones/samsung-phones/ive-been-living-with-the-galaxy-z-fold-8-for-3-weeks-and-i-was-wrong">Galaxy Z Fold 8</a>, <a href="https://www.tomsguide.com/phones/iphones/the-iphone-fold-doesnt-stand-a-chance-unless-apple-introduces-these-3-features-in-ios-27">Apple needs to deliver on three critical fronts</a>: seamless app scaling with landscape-oriented dual-pane views, a truly dynamic multitasking system built for a folding screen, and a dedicated desktop mode that finally lets the iPhone double as a pocket computer.</p><p>Without software tailored specifically to the form factor, the Duo risks being a gorgeous piece of hardware holding back an oversized iOS.</p></div><div class="live-content"><time datetime="2026-09-09T14:29:18+00:00">September 9, 2026 – 10:29 AM</time><h2 id="we-39-re-on-the-ground-at-apple-park">We're on the ground at Apple Park!</h2>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@mspoonyg/video/7683540347611335949" data-video-id="7683540347611335949" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@mspoonyg" href="https://www.tiktok.com/@mspoonyg">@mspoonyg</a>                            <p></p><a target="_blank" title="♬ Sunlit Fingertips - Elliot Vex" href="https://www.tiktok.com/music/Sunlit-Fingertips-7677642997227603978">♬ Sunlit Fingertips - Elliot Vex</a></section>                    </blockquote></div>                <p>Even though we're still a few hours away from the start time of the event, we're finally on the ground and ready to tackle everything Apple has to announce.  Clearly the one that's getting the most buzz right now is none other than the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-apples-first-foldable-usd2-000-price-release-date-as-early-as-october">iPhone Duo</a>, but there are three things you should know about Apple's upcoming first foldable phone.</p></div><div class="live-content"><time datetime="2026-09-09T14:37:43+00:00">September 9, 2026 – 10:37 AM</time><h2 id="iphone-18-pro-likely-to-get-a-price-hike-but-it-39-s-not-as-bad-as-we-thought">iPhone 18 Pro likely to get a price hike, but it's not as bad as we thought</h2><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="KW28fSsFG3t4hnceTZj9a8" name="iPhone 17 Pro review" alt="iPhone 17 Pro review." src="https://cdn.mos.cms.futurecdn.net/KW28fSsFG3t4hnceTZj9a8.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>After months of rumors warning that Apple’s next flagship series could see prices spike by as much as $200 to $300, a new report from Bloomberg brings some relief: the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-is-almost-certainly-getting-a-price-hike-but-it-could-be-less-than-we-feared">increase is expected to be capped at $100</a>.</p><p>That would push the starting prices to $1,199 for the iPhone 18 Pro and $1,299 for the iPhone 18 Pro Max (each likely starting with 256GB). While nobody welcomes higher hardware costs, the bump merely aligns Apple with chief competitors. like Samsung's <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review">Galaxy S26 Ultra</a> and <a href="https://www.tomsguide.com/phones/google-pixel-phones/i-checked-out-the-pixel-11-pixel-11-pro-and-pixel-11-pro-xl-heres-the-one-i-recommend">Google's Pixel 11 Pro XL</a>.</p><p>However, given the bigger hardware upgrades rumored to come to the larger iPhone 18 Pro Max, people may be inclined to get the Pro Max over the Pro this year.</p></div><div class="live-content"><time datetime="2026-09-09T14:43:52+00:00">September 9, 2026 – 10:43 AM</time><h2 id="airpods-ultra-won-39-t-likely-be-announced-but-we-could-get-something-else">AirPods Ultra won't likely be announced, but we could get something else</h2><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="uKSSLPpfSUmKyg5PvvDumX" name="AirPods 4-1.jpg" alt="AirPods 4 on a table" src="https://cdn.mos.cms.futurecdn.net/uKSSLPpfSUmKyg5PvvDumX.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>Before Apple rolls out wilder concept designs like <a href="https://www.tomsguide.com/audio/airpods/airpods-ultra-everything-we-know-so-far-about-apples-camera-earbuds">camera-touting AirPods</a> that have dominated the rumor mills for some time now, the company might instead reveal the <a href="https://www.tomsguide.com/audio/airpods/airpods-5-everything-weve-heard-so-far-about-apples-next-wireless-earbuds">AirPods 5</a> at its event later today.</p><p>Expect the lineup to maintain its two-model approach — $129 for base and $179 for ANC — powered by a new H3 chip for crisper call isolation and better noise cancellation, plus rumored basic temperature tracking to bolster entry-level health metrics.</p></div><div class="live-content"><time datetime="2026-09-09T14:49:53+00:00">September 9, 2026 – 10:49 AM</time><h2 id="i-39-ve-chosen-the-smaller-iphone-pro-for-the-last-couple-of-years-but-that-changes-this-year">I've chosen the smaller iPhone Pro for the last couple of years, but that changes this year</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1280px;"><p class="vanilla-image-block" style="padding-top:55.78%;"><img id="WNJZg5wpSg4yem6kzvAjLN" name="iPhone 18 Pro and Max LIST Large" alt="iPhone 18 Pro vs iPhone 18 Pro Max." src="https://cdn.mos.cms.futurecdn.net/WNJZg5wpSg4yem6kzvAjLN.jpg" mos="" align="middle" fullscreen="" width="1280" height="714" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>For the past couple of generations, sticking with the standard 6.3-inch Pro has been an easy call. It offered the ideal pocketable design that I crave without compromising on flagship features, especially since Apple kept camera and processing hardware idential. But with the iPhone 18 Pro and Pro Max, I'm leaning dramatically towards the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks">iPhone 18 Pro Max</a>.</p><p>Between rumors of the Pro Max exclusively receiving a game-changing <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-be-the-first-iphone-to-get-a-variable-aperture-why-that-matters">variable aperture main camera</a>, packing a <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-tipped-to-be-heaviest-iphone-ever-heres-3-reasons-why-thats-a-good-thing">massive battery upgrade upwards of 5,500 mAh</a>, and delivering better thermal headroom for the new 2nm A20 Pro silicon, Apple seems intent on re-establishing the Max as the true hardware flagship.</p><p>What seals the deal, however, is the narrowing price gap. With early whispers of a massive price hike giving way to reports that the Pro lineup will see a more modest bump, the 18 Pro and 18 Pro Max are tipped to be <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-is-almost-certainly-getting-a-price-hike-but-it-could-be-less-than-we-feared">separated by just $100</a> — starting around $1,199 and $1,299 for matching 256GB baselines.</p></div><div class="live-content"><time datetime="2026-09-09T15:01:21+00:00">September 9, 2026 – 11:01 AM</time><h2 id="overhyped-versus-underhyped-gadgets-apple-could-reveal">Overhyped versus underhyped gadgets Apple could reveal</h2>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7683546163210882318" data-video-id="7683546163210882318" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ Wii Shop Channel Trap - OSRSBeatz" href="https://www.tiktok.com/music/Wii-Shop-Channel-Trap-6866382651020806146">♬ Wii Shop Channel Trap - OSRSBeatz</a></section>                    </blockquote></div>                <p>Our very own <a href="https://www.tomsguide.com/author/mark-spoonauer">Mark Spoonauer</a> and <a href="https://www.tomsguide.com/author/kate-kozuch">Kate Kozuch</a> are on the ground at Apple Park to cover everything at the "Surprise and Shine" event.</p><p>But before the keynote starts, they're breaking down all the biggest rumors ahead of the event. Specifically, they debate about the most overhyped and underhyped Apple devices that have been rumored for some time now.</p></div><div class="live-content"><time datetime="2026-09-09T15:09:56+00:00">September 9, 2026 – 11:09 AM</time><h2 id="i-love-the-galaxy-z-fold-8-so-i-have-higher-expectations-for-the-iphone-duo">I LOVE the Galaxy Z Fold 8, so I have higher expectations for the iPhone Duo</h2><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="F6qr2SDN3gLqxsmgpqVYsY" name="Fold 8 back 2" alt="Samsung Galaxy Z Fold 8" src="https://cdn.mos.cms.futurecdn.net/F6qr2SDN3gLqxsmgpqVYsY.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I'll be the first to admit that changing to a different aspect ratio is exactly what made me (and many others) fall in love with the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Samsung Galaxy Z Fold 8</a>. After spending eight generations relentlessly refining the book-style foldable, and the Galaxy Z Fold 8 feels like the culmination of that effort.</p><p>Between its razor-thin chassis, nearly imperceptible crease, and mature multitasking software, it finally turned the foldable promise into an uncompromising daily driver. Because the bar is set so ridiculously high, I have higher expectations for the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Duo</a>.</p><p>Entering the game this late means Apple can't just release a novel device because it has to solve the pain points that even seasoned foldable makers still wrestle with. If the Duo commands a rumored $2,000 price tag, it needs to deliver more than just premium industrial design.</p></div><div class="live-content"><time datetime="2026-09-09T15:15:16+00:00">September 9, 2026 – 11:15 AM</time><h2 id="does-not-having-a-telephoto-camera-a-dealbreaker-for-the-iphone-duo">Does not having a telephoto camera a dealbreaker for the iPhone Duo?</h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/eMmm53bfgmDEtzFSYozQXT.jpg" alt="Google Pixel 11 Pro Fold camera sample." /><figcaption>Google Pixel 11 Pro Fold.<small role="credit">John Velasco / Tom's Guide</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/aZdupmmy6Wby3pQFYivZq.jpg" alt="Samsung Galaxy Z Fold 8 Ultra camera sample." /><figcaption>Samsung Galaxy Z Fold 8 Ultra.<small role="credit">John Velasco / Tom's Guide</small></figcaption></figure></figure><p>Dropping an estimated $2,000 on a flagship phone usually guarantees top-tier imaging hardware, which exposes one of the issues I have knowing that the iPhone Duo is rumored to not have a dedicated telephoto camera. I've put the <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold</a> and the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> through their paces, the gap between having dedicated zoom optics and relying on digital cropping is impossible to overlook.</p><p>In my real-world shooting, Google’s foldable holds the clear upper hand. The periscope setup on the Pixel 11 Pro Fold consistently pulls in sharper, cleaner detail at 5x and beyond — rendering the sign in the gallery above better than the Fold 8 Ultra.</p><p>If Apple relies purely on high-resolution sensor crop from the main camera to handle magnification, zoom quality is going to hit a hard ceiling past 2x. On a device built to showcase Apple’s hardware engineering at the highest level, skipping a dedicated telephoto feels like a compromise. What do you think?</p></div><div class="live-content"><time datetime="2026-09-09T15:22:50+00:00">September 9, 2026 – 11:22 AM</time><h2 id="badges-in-hand-let-39-s-go">Badges in hand, let's go!</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.20%;"><img id="q23RMr5p4b7YijuCqJ8BPe" name="Apple surprise and shine" alt="Apple surprise and shine." src="https://cdn.mos.cms.futurecdn.net/q23RMr5p4b7YijuCqJ8BPe.jpg" mos="" align="middle" fullscreen="" width="2000" height="1124" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>There's nothing quite like being at Apple Park for an iPhone event and now that we have our badges in hand, the countdown has begun. Without a doubt, we're eager to see what new gadgets Apple plans to reveal. Or perhaps get teasers on some other upcoming stuff the company's planning to officially reveal later one.</p></div><div class="live-content"><time datetime="2026-09-09T15:33:39+00:00">September 9, 2026 – 11:33 AM</time><h2 id="iphone-duo-could-end-up-being-the-thinnest-iphone-but-it-can-39-t-ignore-battery-life">iPhone Duo could end up being the thinnest iPhone, but it can't ignore battery life</h2><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Battery size (mAh)</strong></p></td><td  ><p><strong>Battery life (hrs:mins)</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra</strong></p></td><td  ><p>4,883 mAh rumored)</p></td><td  ><p>TBD</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 11 Pro Fold</strong></p></td><td  ><p>4,806 mAh</p></td><td  ><p>12:31</p></td></tr><tr><td class="firstcol " ><p><strong>Motorola Razr Fold</strong></p></td><td  ><p>6,000 mAh</p></td><td  ><p>14:44</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8 Ultra</strong>   </p></td><td  ><p>5,000 mAh</p></td><td  ><p>14:33</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 10 Pro Fold</strong></p></td><td  ><p>5,015 mAh</p></td><td  ><p>12:16</p></td></tr></tbody></table></div><p>If there's one lesson from our testing of the <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold</a>, it’s that driving two displays — especially an expansive inner folding screen — brutally punishes battery life.</p><p>In fact, Google's latest foldable struggled to move the needle in our battery drain test, proving that thin hinges and modest capacities leave little margin for error. What's notable, too, is how Samsung and Motorola are leaning on silicon-carbon batteries in their foldables. That chemistry doesn't just allow them to pack massive capacities, but it does so without making the phones inherently thicker.</p><p>If the iPhone Duo wants to justify its $2,000 price point, Apple's silicon efficiency and iOS 27 power management need to <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-battery-heres-what-we-know-so-far">deliver true all-day longevity</a>.</p></div><div class="live-content"><time datetime="2026-09-09T15:38:58+00:00">September 9, 2026 – 11:38 AM</time><h2 id="could-an-iphone-desktop-mode-finally-be-a-reality-i-hope-so">Could an iPhone desktop mode finally be a reality? I hope so</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:5276px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AieHmWF2DYNhYEc6WiBT4n" name="Samsung DeX on Galaxy Z Flip 8" alt="Samsung DeX on Galaxy Z Flip 8." src="https://cdn.mos.cms.futurecdn.net/AieHmWF2DYNhYEc6WiBT4n.jpg" mos="" align="middle" fullscreen="" width="5276" height="2968" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Hear me out: I've been waiting for Apple to come out with an <a href="https://www.tomsguide.com/phones/iphones/ios-19-could-add-a-desktop-mode-to-iphone-and-thats-a-fantastic-idea">iPhone desktop mode</a> to rival what other phone makers are offering with their flagships. </p><p>For example, the new <a href="https://www.tomsguide.com/phones/samsung-phones/i-just-tried-the-new-samsung-dex-on-the-galaxy-z-fold-8-and-it-has-one-huge-upgrade">Samsung DeX</a> on the Galaxy Z Fold 8, Z Fold 8 Ultra, and Z Flip 8 prove that foldables can genuinely act as mini PCs, thanks to a major upgrade that introduces four distinct virtual workspaces capable of running up to 20 apps at once.</p><p>If the iPhone Duo enters the market as a $2,000 hybrid device, Apple can’t just offer oversized iOS icons. It needs an equivalent desktop mode that kicks in when tethered to an external monitor. Without desktop-style windowing and multi-workspace organization, Apple will struggle to match the raw productivity power Samsung has spent years refining.</p></div><div class="live-content"><time datetime="2026-09-09T15:44:36+00:00">September 9, 2026 – 11:44 AM</time><h2 id="a-quick-tour-of-the-food-spread-at-apple">A quick tour of the food spread at Apple!</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097706366362407317"><p lang="en" dir="ltr">The spread at Apple Park #appleevent pic.twitter.com/12f3aslcNO<a href="https://twitter.com/cantworkitout/status/2097706366362407317">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>There's nothing like seeing the food lined up at the Steve Jobs Theater as people enter the venue! When you're expecting big things later on, having this kind of variety is just what you need to survive a multi-hour hardware marathon.</p></div><div class="live-content"><time datetime="2026-09-09T15:48:49+00:00">September 9, 2026 – 11:48 AM</time><h2 id="last-minute-iphone-duo-rumors-you-should-know-about">Last-minute iPhone Duo rumors you should know about</h2>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7683555698168319246" data-video-id="7683555698168319246" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ Synthwave - Wiliam Geek" href="https://www.tiktok.com/music/Synthwave-7407812545971587089">♬ Synthwave - Wiliam Geek</a></section>                    </blockquote></div>                <p>Apple’s widely tipped to finally introduce its foldable, the <a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-apples-first-foldable-usd2-000-price-release-date-as-early-as-october">iPhone Duo</a>, pairing a 5.5-inch outer cover screen with an expansive 7.8-inch inner one that measures just 4.5mm unfolded.</p><p>Late leaks point to a starting price of $2,000 for 256GB of storage, undercutting early fears of an even steeper markup. However, chasing that ultra-thin chassis means accepting first-gen compromises, including a dual-camera setup with no dedicated telephoto lens and a rumored release date slipping into October.</p></div><div class="live-content"><time datetime="2026-09-09T15:53:58+00:00">September 9, 2026 – 11:53 AM</time><h2 id="the-crowd-continues-to-grow">The crowd continues to grow!</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="R7vRQPtNX85WSGDcKRXnoM" name="Apple surprise and shine" alt="Apple surprise and shine." src="https://cdn.mos.cms.futurecdn.net/R7vRQPtNX85WSGDcKRXnoM.jpg" mos="" align="middle" fullscreen="" width="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>We're less than an hour from when the festivities are slated to start, but the Steve Jobs Theater is quickly filling up with reporters, influencers, analysts, and guests who are eager to see what Apple reveals.</p></div><div class="live-content"><time datetime="2026-09-09T16:00:10+00:00">September 9, 2026 – 12:00 PM</time><h2 id="gurman-says-you-might-not-see-these-other-apple-devices-at-the-event">Gurman says you might not see these other Apple devices at the event</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097687667471466751"><p lang="en" dir="ltr">IF you don't see the Apple TV, HomePod mini, home display and touch MacBook today, don't worry. It's only September.<a href="https://twitter.com/cantworkitout/status/2097687667471466751">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p><a href="https://x.com/markgurman/status/2097687667471466751?s=46" target="_blank">Bloomberg's Mark Gurman</a> has been busy over the last 24 hours, but he doesn't expect to see announcements for other previously rumored devices, like an updated Apple TV 4K or a HomePod mini refresh.</p><p>Clearly, the company has its hands full with the iPhone 18 Pro, iPhone 18 Pro Max, and iPhone Duo — so it's no surprise that secondary hardware might sit out this event.</p></div><div class="live-content"><time datetime="2026-09-09T16:15:04+00:00">September 9, 2026 – 12:15 PM</time><h2 id="take-a-look-inside-the-countdown-is-on-at-steve-jobs-theater">Take a look inside: The countdown is on at Steve Jobs Theater!</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097719045890195758"><p lang="en" dir="ltr">Inside the #appleevent all this to see the AirPods 5? 😉 pic.twitter.com/gktcWhGEbR<a href="https://twitter.com/cantworkitout/status/2097719045890195758">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>We're officially headed down the glass stairs and into the auditorium! As you can see in the video, the space is quickly packing in with press, analysts, and creators securing their spots.</p></div><div class="live-content"><time datetime="2026-09-09T16:24:59+00:00">September 9, 2026 – 12:24 PM</time><h2 id="iphone-duo-is-probably-going-to-be-the-thinnest-iphone-ever">iPhone Duo is probably going to be the thinnest iPhone ever</h2><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Thinness</strong></p></td><td  ><p><strong>Weight</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra (rumored)</strong></p></td><td  ><p>4.5 – 4.8 mm</p></td><td  ><p>8.1 – 8.5 ounces (230 – 241 grams</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8</strong></p></td><td  ><p>4.5 mm</p></td><td  ><p>7.09 ounces (201 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8 Ultra</strong></p></td><td  ><p>4.1 mm</p></td><td  ><p>7.58 ounces (215 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Motorola Razr Fold</strong></p></td><td  ><p>4.7 mm</p></td><td  ><p>8.6 ounces (243 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 11 Pro Fold</strong></p></td><td  ><p>4.8 mm</p></td><td  ><p>8.64 ounces (245 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Oppo Find N6</strong></p></td><td  ><p>4.21 mm</p></td><td  ><p>7.94 ounces (225 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Honor Magic V6</strong></p></td><td  ><p>4 mm</p></td><td  ><p>7.72 ounces (219 grams)</p></td></tr></tbody></table></div><p>Notebook-style foldables have advantages over traditional slabs, like how they offer larger screens. However, the notable thing about the iPhone Duo is how it's shaping up to be <a href="https://www.tomsguide.com/phones/iphones/the-iphone-ultra-will-be-the-thinnest-iphone-ever-heres-how-it-will-stack-up-to-other-foldables">the thinnest iPhone ever</a>.</p><p>Tipped to measure just 4.5mm unfolded and around 9mm closed, the iPhone Duo easily undercuts the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air</a> to claim the title of thinnest iPhone in history. While it won't dethrone the razor-thin Galaxy Z Fold 8 Ultra or the featherweight Magic V6, its 230–241g weight and slim profile put it right in line with the iPhone 17 Pro Max — giving users a 7.8-inch inner canvas without the unwieldy bulk of early-generation foldables.</p></div><div class="live-content"><time datetime="2026-09-09T16:32:17+00:00">September 9, 2026 – 12:32 PM</time><h2 id="the-iphone-duo-could-justify-the-iphone-air-39-s-biggest-missteps">The iPhone Duo could justify the iPhone Air's biggest missteps</h2><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="bWRiHr2xAWuu7w7QFRLsq" name="iPhone Air-18" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/bWRiHr2xAWuu7w7QFRLsq.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>When Apple introduced the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air</a>, it proved the company could engineer an impossibly thin 5.6mm chassis — but it came at the cost of crippling compromises. Between a single rear camera, cramped battery life that trailed the rest of the lineup, and a downclocked chip, the Air prioritized sheer thinness over real-world practicality.</p><p>Yet, the iPhone Duo represents the exact redemption arc Apple needs. Rather than obsessing over thinness, Apple could use what it learns with the Duo to make the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-rumors-5-biggest-expected-upgrades">iPhone Air 2</a> way better.</p></div><div class="live-content"><time datetime="2026-09-09T16:35:08+00:00">September 9, 2026 – 12:35 PM</time><h2 id="apple-ceo-john-ternus-teases-what-could-be-a-variable-aperture-camera">Apple CEO John Ternus teases what could be a variable aperture camera</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097672038781763614"><p lang="en" dir="ltr">pic.twitter.com/CLu9eRDP5b<a href="https://twitter.com/cantworkitout/status/2097672038781763614">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>With less than 30 minutes from the start of the event, new <a href="https://x.com/johnternus/status/2097672038781763614?s=46" target="_blank">Apple CEO John Ternus shares a teaser video on X </a>showing what could be a variable aperture camera. You can watch in the clip above how the light shines down to what appears to be a lens. While this is interesting, we're eager to see how Apple sells a feature like this to the general consumer.</p></div><div class="live-content"><time datetime="2026-09-09T16:42:43+00:00">September 9, 2026 – 12:42 PM</time><h2 id="we-39-re-in-our-seats">We're in our seats!</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="jyYvdmjpA7iaMuFzwYbfhH" name="Apple surprise and shine" alt="Apple surprise and shine." src="https://cdn.mos.cms.futurecdn.net/jyYvdmjpA7iaMuFzwYbfhH.jpg" mos="" align="middle" fullscreen="" width="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 doors have opened up to the Steve Jobs Theater and we're in our seats ready to see what Apple has in store for us!</p></div><div class="live-content"><time datetime="2026-09-09T16:47:40+00:00">September 9, 2026 – 12:47 PM</time><h2 id="place-your-bet-where-does-the-iphone-duo-land-on-an-all-time-greatest-list">Place your bet — where does the iPhone Duo land on an all-time greatest list?</h2><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eJ9grX"></div>                            </div>                            <script src="https://kwizly.com/embed/eJ9grX.js" async></script><p>With time winding down, all eyes are on Apple and what you usher in a new era for the company. There's no arguing how the company's line of slate iPhone have dominated the landscape, but where does the iPhone Duo land on an all-time greatest list? Is it higher than any of the other notable classics above? Let us know.</p></div><div class="live-content"><time datetime="2026-09-09T16:56:07+00:00">September 9, 2026 – 12:56 PM</time><h2 id="this-is-your-5-minute-warning">This is your 5-minute warning</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/39BalPDuTo0" allowfullscreen></iframe></div></div><p>We're less than 5 minutes away from the start, so your best way of keeping up with the action is to watch the livestream above.</p></div><div class="live-content"><time datetime="2026-09-09T17:00:19+00:00">September 9, 2026 – 1:00 PM</time><h2 id="apple-ceo-john-ternus-takes-stage">Apple CEO John Ternus takes stage</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="jjLx7dhPBJeJTFHTLeQbzf" name="Apple surprise and shine" alt="Apple surprise and shine." src="https://cdn.mos.cms.futurecdn.net/jjLx7dhPBJeJTFHTLeQbzf.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>Apple's new CEO steps up and introduces the crowd here at the Steve Jobs Theater. "We want our products to be powerful but also simple," explains Ternus to the crowd. "We're going to continue changing the world."</p></div><div class="live-content"><time datetime="2026-09-09T17:02:23+00:00">September 9, 2026 – 1:02 PM</time><h2 id="39-you-want-a-great-opening-scene-39">'You want a great opening scene?'</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="5fZn2fC8XPiTJv7nS8MgzA" name="Apple Event — September 9 3-1 screenshot" alt="Not looking at an explosion, shot on iPhone at Apple Surprise and Shine" src="https://cdn.mos.cms.futurecdn.net/5fZn2fC8XPiTJv7nS8MgzA.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>Apple is kicking off its event with a short video that says it's shot on iPhone, which we presumably think is the iPhone 18 Pro or 18 Pro Max. It look pretty legit, complete with cinematic takes and action.</p></div><div class="live-content"><time datetime="2026-09-09T17:04:36+00:00">September 9, 2026 – 1:04 PM</time><h2 id="tim-cook-makes-a-39-main-character-39-cameo">Tim Cook makes a 'main character' cameo</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="HBxLGXdq6vvMba59EWmbCP" name="Apple Event — September 9 5-7 screenshot" alt="John Ternus at Apple Surprise and Shine" src="https://cdn.mos.cms.futurecdn.net/HBxLGXdq6vvMba59EWmbCP.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>Towards the end of the opening video, we see Tim Cook mentioning about the "main character," which he then proceeds to point behind him to reveal John Ternus.</p></div><div class="live-content"><time datetime="2026-09-09T17:07:35+00:00">September 9, 2026 – 1:07 PM</time><h2 id="iphone-is-the-personal-intelligent-hub">iPhone is the personal intelligent hub</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="q6M9jPsoxRU45XNxiS3off" name="Apple Event — September 9 7-28 screenshot" alt="John Ternus next to Apple software and hardware stack" src="https://cdn.mos.cms.futurecdn.net/q6M9jPsoxRU45XNxiS3off.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>Apple CEO John Ternus starts off the show talking about Apple Intelligence first, going on to say how the iPhone is the personal intelligent hub. "It's personal intelligence that's personal," explains Ternus.</p></div><div class="live-content"><time datetime="2026-09-09T17:10:43+00:00">September 9, 2026 – 1:10 PM</time><h2 id="apple-iphone-18-pro-and-18-pro-max-are-official">Apple iPhone 18 Pro and 18 Pro Max are official!</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Z3HUDir2Yvo6wraL8ESsy7" name="Apple Event — September 9 9-59 screenshot" alt="iPhone 18 Pro at Apple Surprise and Shine" src="https://cdn.mos.cms.futurecdn.net/Z3HUDir2Yvo6wraL8ESsy7.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>Ternus reveals the iPhone 18 Pro and 18 Pro Max first, going on to say how it has the longest battery life in an iPhone, most advanced cameras.</p><p>The video initially shows an iPhone 17 Pro that shot video of the moon but end by saying "this is what happens when you go to the moon and ask what's next."</p></div><div class="live-content"><time datetime="2026-09-09T17:12:59+00:00">September 9, 2026 – 1:12 PM</time><h2 id="siri-ai-brings-more-advanced-features">Siri AI brings more advanced features</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="mkxU4JkbkGwurkJH7N2xFY" name="Apple Event — September 9 13-49 screenshot" alt="Expressive voices in Siri AI at Apple Surprise and Shine" src="https://cdn.mos.cms.futurecdn.net/mkxU4JkbkGwurkJH7N2xFY.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>Before we learn more about the hardware for the iPhone 18 Pro and 18 Pro Max, Apple's taking the time to talk about new capabilities coming to its new phones. In addition to handling task automations, you'll also get the new Siri AI app to see all of your interactions.</p></div><div class="live-content"><time datetime="2026-09-09T17:17:02+00:00">September 9, 2026 – 1:17 PM</time><h2 id="apple-a20-pro-sets-a-new-bar-for-mobile-computing">Apple A20 Pro sets a new bar for mobile computing</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AzHo485TVydoAHMxQVcQk3" name="Apple Event — September 9 16-33 screenshot" alt="A20 Pro at Apple Surprise and Shine" src="https://cdn.mos.cms.futurecdn.net/AzHo485TVydoAHMxQVcQk3.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>Apple's newest silicon is built using the new 2-nanometer manufacturing process, consisting of a 6-core CPU and 4 efficiency cores, which deliver a 20% improvement. The GPU has 7-core design with 40% increased performance. </p></div><div class="live-content"><time datetime="2026-09-09T17:19:40+00:00">September 9, 2026 – 1:19 PM</time><h2 id="vapor-chamber-and-chip-packaging-will-deliver-maximum-performance-with-a20-pro-chip">Vapor chamber and chip packaging will deliver maximum performance with A20 Pro chip</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="DqUedc8StcXSG4MhugjDkP" name="Apple Event — September 9 19-34 screenshot" alt="iPhone 18 Pro new vapor chamber" src="https://cdn.mos.cms.futurecdn.net/DqUedc8StcXSG4MhugjDkP.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>A next-generation vapor chamber has three times the surface area, while a copper layer adds to its heat dissipation. As a result, it delivers a 40% sustained performance improvement.</p></div><div class="live-content"><time datetime="2026-09-09T17:21:38+00:00">September 9, 2026 – 1:21 PM</time><h2 id="improved-battery-life-performance-on-iphone-18-pros">Improved battery life performance on iPhone 18 Pros</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="taavmtuAbyi5bPdYnwydGb" name="Apple Event — September 9 21-23 screenshot" alt="iPhone 18 Pro battery life" src="https://cdn.mos.cms.futurecdn.net/taavmtuAbyi5bPdYnwydGb.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>On top of offering superior processing performance, the battery life is going to be much improved with up to  24 hours per charge with the iPhone 18 Pro and 30 hours with the Pro Max. Apple also says you get 50% battery life in 15 minutes.</p></div><div class="live-content"><time datetime="2026-09-09T17:24:22+00:00">September 9, 2026 – 1:24 PM</time><h2 id="variable-aperture-main-camera-confirmed">Variable aperture main camera confirmed!</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="zik8HSxbxZkhACoa7RNR5" name="Apple Event — September 9 23-15 screenshot" alt="Fusion Main Camera on iPhone 18 Pro" src="https://cdn.mos.cms.futurecdn.net/zik8HSxbxZkhACoa7RNR5.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>Apple didn't wait long to reveal the 48MP main camera with variable aperture on the iPhone 18 Pros, giving users even more creative shots.</p></div><div class="live-content"><time datetime="2026-09-09T17:26:01+00:00">September 9, 2026 – 1:26 PM</time><h2 id="pro-controls-paired-with-variable-aperture">Pro Controls paired with variable aperture</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="HhGRiHZ8d4hXRLpaxyqFEH" name="Apple Event — September 9 25-43 screenshot" alt="Pro Controls on iPhone 18 Pro" src="https://cdn.mos.cms.futurecdn.net/HhGRiHZ8d4hXRLpaxyqFEH.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>Apple's rolling through all the creative ways a variable aperture can be used effectively with Pro Controls, like being able to use variable aperture to create motion blur or also freeze photos.</p></div><div class="live-content"><time datetime="2026-09-09T17:29:17+00:00">September 9, 2026 – 1:29 PM</time><h2 id="upgraded-dynamic-island-is-smaller-shows-more-activities">Upgraded Dynamic Island is smaller, shows more Activities</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="mX23Fz2XDriJNsC4wUHxjm" name="Apple Event — September 9 29-33 screenshot" alt="Smaller Dynamic Island on iPhone 18 Pro" src="https://cdn.mos.cms.futurecdn.net/mX23Fz2XDriJNsC4wUHxjm.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>With the Dynamic Island on the iPhone 18 Pro and 18 Pro Max, Apple slims its size, but it's now able to show up to three Live Activities.</p></div><div class="live-content"><time datetime="2026-09-09T17:31:58+00:00">September 9, 2026 – 1:31 PM</time><h2 id="iphone-18-pro-and-18-pro-max-start-at-1-199-and-1-299">iPhone 18 Pro and 18 Pro Max start at $1,199 and $1,299</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="3nf798kyYtzdTgorhQMVMD" name="Apple Event — September 9 31-41 screenshot" alt="iPhone 18 Pro pricing" src="https://cdn.mos.cms.futurecdn.net/3nf798kyYtzdTgorhQMVMD.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>Apple spends a short time talking about new accessories that include cases and wrist straps, but the bigger reveal is the price of its new phones:</p><ul><li><strong>iPhone 18 Pro: </strong>$1,199</li><li><strong>iPhone 18 Pro Max:</strong> $1,299</li></ul></div><div class="live-content"><time datetime="2026-09-09T17:36:27+00:00">September 9, 2026 – 1:36 PM</time><h2 id="airpods-5-has-best-anc-in-an-open-ear-design">AirPods 5 has best ANC in an open-ear design</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bHwv6kAcCcAwYDSLpZumAf" name="Apple Event — September 9 36-26 screenshot" alt="AirPods 5 Pricing" src="https://cdn.mos.cms.futurecdn.net/bHwv6kAcCcAwYDSLpZumAf.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>AirPods 5 have an open ear fit with next-gen adaptive EQ, better Siri features, real-time Live Translation, durable design that handles rain, 4 hours of listening with ANC with up to 20 hours with charging case. It's priced at $129 without ANC.</p><p>Another model has a touch sensitive stem that offers 5 hours of battery with ANC, comes with wireless charging case, all priced at $149.</p></div><div class="live-content"><time datetime="2026-09-09T17:40:16+00:00">September 9, 2026 – 1:40 PM</time><h2 id="apple-watch-series-12-and-watch-ultra-4-revealed">Apple Watch Series 12 and Watch Ultra 4 revealed</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kzVjuUU8B5U9svoLLPJgJE" name="Apple Event — September 9 39-15 screenshot" alt="Apple Watch Ultra 4 and Apple Watch 12 at Apple Surprise and Shine" src="https://cdn.mos.cms.futurecdn.net/kzVjuUU8B5U9svoLLPJgJE.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>Advanced sensor array monitor sleep, health, and fitness. Both offer Health Sensing System, packs larger electrode area, better optical seniung with photodiode, larger, more power efficient green LEDs offer better tracking.</p><p>Background readings are taken every 5 seconds, record heart rate variability every 5 minutes.</p></div><div class="live-content"><time datetime="2026-09-09T17:43:50+00:00">September 9, 2026 – 1:43 PM</time><h2 id="new-apple-watches-focus-on-heart-rate-variability">New Apple Watches focus on heart rate variability</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='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.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>High-frequency heart rate data, which is now a complication you can add.</p><p>Health Sensing System offers Readiness tells you when to push or hold back. It analyzes your data to set goals and challenges for yourself, so the score changes dynamically to give you an overview.</p><p>Health Age gather metrics to give you what habits impact your age the most. You can even order a $119 lab work right through the app.</p></div><div class="live-content"><time datetime="2026-09-09T17:48:09+00:00">September 9, 2026 – 1:48 PM</time><h2 id="audio-intelligence-unlocks-more-helpful-tools-on-apple-watch">Audio Intelligence unlocks more helpful tools on Apple Watch</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='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.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>With built-in mics and new silicon, new Apple Intelligence features includes three new Audio Intelligence:</p><ul><li><strong>Sound Recognition</strong> that can discern sounds like alarms.</li><li><strong>Live Rewind</strong> that lets you go back in time 15 seconds and basically acts as a transcript.</li><li><strong>Siri Recap </strong>takes notes that can summarize.</li></ul></div><div class="live-content"><time datetime="2026-09-09T17:50:49+00:00">September 9, 2026 – 1:50 PM</time><h2 id="apple-watch-series-12-in-more-colors-and-finishes">Apple Watch Series 12 in more colors and finishes</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="FR2tN8LHY9N8dPaGWDFtfm" name="Apple Event — September 9 51-26 screenshot" alt="New Apple Watch 12 bands" src="https://cdn.mos.cms.futurecdn.net/FR2tN8LHY9N8dPaGWDFtfm.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>Apple Watch Series 12 come in more colors and finishes, including polish finishes and ceramic materials. There are also new bands, including from Nike.</p></div><div class="live-content"><time datetime="2026-09-09T17:52:55+00:00">September 9, 2026 – 1:52 PM</time><h2 id="apple-watch-ultra-4-starts-at-499">Apple Watch Ultra 4 starts at $499</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='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.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>Apple Watch Series 12 starts at $399, while Apple Watch Ultra 4 start at $799.  Thankfully they don't get any price hikes this year.</p></div><div class="live-content"><time datetime="2026-09-09T17:57:01+00:00">September 9, 2026 – 1:57 PM</time><h2 id="39-but-actually-there-39-s-one-more-thing-39-say-hello-to-iphone-duo">'But actually there's one more thing' — say hello to iPhone Duo</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wEQDPuXx2e5CdQr77P2MWf" name="Apple Event — September 9 57-37 screenshot" alt="iPhone Duo close din hand" src="https://cdn.mos.cms.futurecdn.net/wEQDPuXx2e5CdQr77P2MWf.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>While it appears it's a wrap with the Apple event, John Ternus says that there's just one more thing -- going on to reveal a foldable device called the iPhone Duo.</p><p>True to all the rumors and leaks, the iPhone Duo is a "wide" notebook style foldable phone. </p></div><div class="live-content"><time datetime="2026-09-09T17:59:45+00:00">September 9, 2026 – 1:59 PM</time><h2 id="iphone-duo-39-s-biggest-features-revealed">iPhone Duo's biggest features revealed</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="6C7CZojJWSoQwTvCAXJw4j" name="Apple Event — September 9 58-18 screenshot" alt="iPhone Duo closed and open" src="https://cdn.mos.cms.futurecdn.net/6C7CZojJWSoQwTvCAXJw4j.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><ul><li>FaceTime camera is hidden underneath the display</li><li>Hinge mechanism feels smooth with an integrated manet</li><li>Thinnest iPhone ever</li><li>Aero-space titanium</li><li>Largest display in an iPhone</li></ul></div><div class="live-content"><time datetime="2026-09-09T18:03:47+00:00">September 9, 2026 – 2:03 PM</time><h2 id="even-more-iphone-duo-specs-confirmed">Even more iPhone Duo specs confirmed</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="gwC2fHbKhjmGfVkQUeicvT" name="Apple Event — September 9 1-3-15 screenshot" alt="iPhone Duo colors" src="https://cdn.mos.cms.futurecdn.net/gwC2fHbKhjmGfVkQUeicvT.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><ul><li>7.6-inch Super Retina XDR display, 50% larger in size than iPhone 18 Pro Max.</li><li>5.4-inch outer display provides 90% of viewing screen of iPhone 18 Pro.</li><li>Apple Pencil support to come later.</li><li>Touch ID is integrated into the side button.</li><li>Unlock phone with Apple Watch.</li><li>Speakers on top and bottom edges.</li><li>Grade 5 titanium construction.</li><li>Ceramic Shield on back, Ceramic Shield 2 on front</li></ul></div><div class="live-content"><time datetime="2026-09-09T18:06:21+00:00">September 9, 2026 – 2:06 PM</time><h2 id="apps-adapt-to-how-you-position-the-iphone-duo">Apps adapt to how you position the iPhone Duo</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="hiCeFnGaANu9zsBVFBDn58" name="Apple Event — September 9 1-5-3 screenshot" alt="iPhone Duo side by side apps" src="https://cdn.mos.cms.futurecdn.net/hiCeFnGaANu9zsBVFBDn58.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>This is the biggest thing that will differentiate the iPhone Duo from other foldable phones, as apps will dynamically scale and change depending on how you orient and use it. The demo so far looks pretty convincing, but developers will need to optimize how they look.</p></div><div class="live-content"><time datetime="2026-09-09T18:09:34+00:00">September 9, 2026 – 2:09 PM</time><h2 id="iphone-dup-display-technology-reduces-glare-offers-superior-scratch-protection">iPhone Dup display technology reduces glare, offers superior scratch protection</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="owQW6oWKDWWSAKMEppqFYG" name="Apple Event — September 9 1-8-36 screenshot" alt="Nano Texture glass on iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/owQW6oWKDWWSAKMEppqFYG.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>Nano-texture finishes reduces glare with the main display. It also offers better scratch resistance. All of these layers won't distort over time, with the hinge that consists of over 100 components.</p></div><div class="live-content"><time datetime="2026-09-09T18:12:28+00:00">September 9, 2026 – 2:12 PM</time><h2 id="39-iphone-duo-is-esim-only-worldwide-39">'iPhone Duo is eSIM only worldwide'</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="N3UodsL4VX7ChTdLNtJP4c" name="Apple Event — September 9 1-10-47 screenshot" alt="iPhone Duo internals" src="https://cdn.mos.cms.futurecdn.net/N3UodsL4VX7ChTdLNtJP4c.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>In order to engineer its foldable phone and long battery life, the iPhone Duo is only going to be available as an eSIM-only option worldwide. You get all-day battery life up to 31 hours with the inner display, 44 hours outer display, and 24 hours when using both screens equally. When it come to charging, you'll get 50% in 20 minutes of charging.</p></div><div class="live-content"><time datetime="2026-09-09T18:15:22+00:00">September 9, 2026 – 2:15 PM</time><h2 id="iphone-duo-cameras-offer-new-ways-to-shoot">iPhone Duo cameras offer new ways to shoot</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="uQq56JKBF4Lu8qoNeXMbCF" name="Apple Event — September 9 1-15-9 screenshot" alt="Dual camera face time on iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/uQq56JKBF4Lu8qoNeXMbCF.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>Apple spends time talking about the dual-camera system in the iPhone Duo, including how the Center Stage camera can be used for FaceTime calls. Other creative ways include using the outer screen to capture better selfies.</p></div><div class="live-content"><time datetime="2026-09-09T18:16:48+00:00">September 9, 2026 – 2:16 PM</time><h2 id="iphone-duo-starts-at-1-999">iPhone Duo starts at $1,999</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="TCZapEDrdTsmRuR7ugKsKQ" name="Apple Event — September 9 1-16-20 screenshot" alt="iPhone Duo selfie proped up" src="https://cdn.mos.cms.futurecdn.net/TCZapEDrdTsmRuR7ugKsKQ.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>Apple finally reveals the iPhone Duo's price, which at $1,999, makes a compelling offer. Preorders start October 16 with availability set for October 12.</p></div><div class="live-content"><time datetime="2026-09-09T18:19:43+00:00">September 9, 2026 – 2:19 PM</time><h2 id="and-that-39-s-a-wrap">And that's a wrap!</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="QX3fugY6wAPCv4H622VaQg" name="Apple Event — September 9 1-19-35 screenshot" alt="Apple Surprise and Shine that's a wrap" src="https://cdn.mos.cms.futurecdn.net/QX3fugY6wAPCv4H622VaQg.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>Normally Apple's events are multi-hour marathons, but this one's rather concise. After finishing off its event with the iPhone Duo, Apple had nothing else to share apart from an ending scene that mentions how the event was shot on iPhone and edited on Mac. Stay tuned for our additional coverage!</p></div><div class="live-content"><time datetime="2026-09-09T18:49:08+00:00">September 9, 2026 – 2:49 PM</time><h2 id="which-reveal-were-you-most-impressed-with">Which reveal were you most impressed with?</h2><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-WVkdJO"></div>                            </div>                            <script src="https://kwizly.com/embed/WVkdJO.js" async></script><p>Between John Ternus's keynote debut, the long-awaited unveiling of the $1,999 iPhone Duo, and substantial hardware upgrades for the iPhone 18 Pro series, today wasn’t just another iterative September refresh.</p><p>Apple made a definitive statement that it’s ready to challenge Android's mature foldable dominance on its own terms — even if the omission of a telephoto lens and an October rollout invite scrutiny. Out of all the devices it announced at the event, which one gets your vote?</p></div><div class="live-content"><time datetime="2026-09-09T19:21:29+00:00">September 9, 2026 – 3:21 PM</time><h2 id="samsung-gets-sassy">Samsung gets sassy</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097748103478591990"><p lang="en" dir="ltr">Let us know when you're done reheating our leftovers 😉<a href="https://twitter.com/cantworkitout/status/2097748103478591990">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>Samsung functionally started the foldable phone trend nearly a decade ago with its original Galaxy Fold. </p><p>So, we were expecting some kind of response and the company got a little sassy on X posting:</p><p>"Let us know when you're done reheating our leftovers." </p></div><div class="live-content"><time datetime="2026-09-09T19:40:20+00:00">September 9, 2026 – 3:40 PM</time><h2 id="what-we-know-about-the-iphone-18-pro-and-pro-max">What we know about the iPhone 18 Pro and Pro Max</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="sAFnnQsMDkhrRiPhTeYah9" name="iphone-18-pro-model-unselect-gallery-1-202609" alt="iphone 18 pro and pro max side by side" src="https://cdn.mos.cms.futurecdn.net/sAFnnQsMDkhrRiPhTeYah9.webp" mos="" align="middle" fullscreen="" width="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 new iPhone Pro models aren't big departures from the previous generation but there are some things to get excited about.</p><p>Check out our article to find out <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-are-official-heres-what-you-need-to-know">everything you need to know about the iPhone 18 Pro and iPhone 18 Pro Max</a>.</p></div><div class="live-content"><time datetime="2026-09-09T19:59:41+00:00">September 9, 2026 – 3:59 PM</time><h2 id="expect-a-lot-of-microsoft-duo-jokes">Expect a lot of Microsoft Duo jokes</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097749286024863988"><p lang="en" dir="ltr">exclusive: hands-on with the Duo pic.twitter.com/chHv7xfq7R<a href="https://twitter.com/cantworkitout/status/2097749286024863988">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>For any tech journo who has been around a minute and a collector, expect to see a lot of Microsoft Duo jokes.</p><p>Here's an example from <a href="https://x.com/tomwarren/status/2097749286024863988?s=20" target="_blank">The Verge's Tom Warren</a>.</p></div><div class="live-content"><time datetime="2026-09-09T20:21:26+00:00">September 9, 2026 – 4:21 PM</time><h2 id="new-cheaper-airpods">New, cheaper AirPods</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="bGcwz5CcYkGkaEMqtgpCEQ" name="Apple Event — September 9 33-22 screenshot" alt="AirPods 5" src="https://cdn.mos.cms.futurecdn.net/bGcwz5CcYkGkaEMqtgpCEQ.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>Apple revealed its new Airpods 5 in two versions, one with a wireless charging case and a base model, with active noise cancellation. </p><p>Both are cheaper than or the same price as the AirPods 4, making it one of the few devices to get a price cut.</p><p>Here's <a href="https://www.tomsguide.com/audio/airpods/apple-airpods-5-officially-announced-here-are-the-upgrades">everything you need to know about the AirPods 5</a>.</p></div><div class="live-content"><time datetime="2026-09-09T20:48:14+00:00">September 9, 2026 – 4:48 PM</time><h2 id="duo-wallpapers">Duo wallpapers</h2><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2097762805621637376"><p lang="en" dir="ltr">iPhone Duo Wallpaper (night)(from the usdz file) https://t.co/ToFZozJHCq pic.twitter.com/fjXSFwOgmH<a href="https://twitter.com/cantworkitout/status/2097762805621637376">September 9, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>If you're looking for Duo wallpapers, the <a href="https://x.com/BasicAppleGuy/status/2097762805621637376?s=20" target="_blank">Basic Apple Guy on X </a>has you covered. He posted images from the usdz file of two desert shots, one at night and one during day that you can grab.</p><p>These appear to be the same ones we saw during the presentation.</p></div><div class="live-content"><time datetime="2026-09-09T21:02:23+00:00">September 9, 2026 – 5:02 PM</time><h2 id="hands-on-with-the-duo">Hands on with the Duo</h2>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7683620247215049998" data-video-id="7683620247215049998" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ Minimal for news / news suspense(1169746) - Hiraoka Kotaro" href="https://www.tiktok.com/music/Minimal-for-news-news-suspense-1169746-7055051802865862658">♬ Minimal for news / news suspense(1169746) - Hiraoka Kotaro</a></section>                    </blockquote></div>                </div><div class="live-content"><time datetime="2026-09-09T21:29:43+00:00">September 9, 2026 – 5:29 PM</time><h2 id="initial-thoughts-on-the-iphone-duo">Initial thoughts on the iPhone Duo</h2><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="i4QF9zqZdmy4sZPuE8hXFa" name="iphone duo edit 4" alt="iPhone Duo" src="https://cdn.mos.cms.futurecdn.net/i4QF9zqZdmy4sZPuE8hXFa.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>We've had some hands-on time with the iPhone Duo, and Tom's Guide Global Editor has some initial thoughts on Apple's first foldable iPhone.</p><p>Check out his<a href="https://www.tomsguide.com/phones/iphones/iphone-duo-hands-on-apple-nailed-it-and-just-put-everyone-else-on-notice"> iPhone Duo hands-on </a>article for all of the details.</p></div><div class="live-content"><time datetime="2026-09-09T22:04:53+00:00">September 9, 2026 – 6:04 PM</time><h2 id="apple-watch-series-12-and-watch-ultra-4">Apple Watch Series 12 and Watch Ultra 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: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.jpg" mos="" align="middle" fullscreen="" width="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's two new watches, the Series 12 and Ultra 4, aren't too different than their predecessors, but they do come with new chips, a couple of new sensors, and a number of health software upgrades.</p><p>Here's everything you need to know about 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> and the <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4-is-official-all-the-upgrades-explained">Apple Watch Ultra 4</a>.</p></div><div class="live-content"><time datetime="2026-09-09T22:33:44+00:00">September 9, 2026 – 6:33 PM</time><h2 id="older-lower-end-iphones-are-now-more-expensive">Older, lower-end iPhones are now more expensive</h2><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="ecRd2peLtxYXQxQQvJq3Ge" name="Apple iPhone 17 review" alt="Apple iPhone 17 review." src="https://cdn.mos.cms.futurecdn.net/ecRd2peLtxYXQxQQvJq3Ge.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>Apple only announced the iPhone 18 Pro and iPhone 18 Pro Max today, each with a $100 price increase compared to the iPhone 17 versions.</p><p>However, the lower-end older devices also got $100 price bumps. </p><p>Here are the new prices:</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Starting Price</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Air</strong></p></td><td  ><p>$1,099</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17</strong></p></td><td  ><p>$899</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 16</strong></p></td><td  ><p>$799</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17e</strong></p></td><td  ><p>$699</p></td></tr></tbody></table></div><p>Plus the 256GB version of the iPhone 16 has been axed and the iPhone 16 Plus is no longer for sale.</p></div><div class="live-content"><time datetime="2026-09-09T23:00:16+00:00">September 9, 2026 – 7:00 PM</time><h2 id="iphone-duo-vs-galaxy-z-fold-8">iPhone Duo vs Galaxy Z Fold 8</h2>                    <div class= "tiktok-wrapper" style="min-height: 750px;"><blockquote class="tiktok-embed" cite="https://www.tiktok.com/@tomsguide/video/7683645046977072415" data-video-id="7683645046977072415" style="max-width: 605px; min-width: 325px;">                        <section>                            <a target="_blank" title="@tomsguide" href="https://www.tiktok.com/@tomsguide">@tomsguide</a>                            <p></p><a target="_blank" title="♬ Loft Window - Slight Overcast" href="https://www.tiktok.com/music/Loft-Window-7674360528990554122">♬ Loft Window - Slight Overcast</a></section>                    </blockquote></div>                </div><div class="live-content"><time datetime="2026-09-09T23:34:34+00:00">September 9, 2026 – 7:34 PM</time><h2 id="going-hands-on-with-the-apple-watch-ultra-4">Going hands-on with the Apple Watch Ultra 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: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.jpg" mos="" align="middle" fullscreen="" width="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>Tom's Guide Fitness editor Jane McGuire was able to get some <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-ultra-4#section-apple-watch-ultra-4-hands-on-review-battery-life">hands-on time with the Apple Watch Ultra 4</a>.</p><p>Initially, she was impressed but not every announced feature was available at launch and won't come until much later. So its kind of a wait and see moment. </p></div><div class="live-content"><time datetime="2026-09-10T00:18:46+00:00">September 9, 2026 – 8:18 PM</time><h2 id="hands-on-with-the-apple-watch-series-12">Hands-on with the Apple Watch Series 12</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='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.jpg" mos="" align="middle" fullscreen="" width="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>Fitness managing editor Jane McGuire also had a chance to go <a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12">hands-on with the Apple Watch Series 12</a>. Her initial impressions? It's a nice upgrade over the previous model, especially now that it has upgraded sensors and a much-needed Readiness score. Best of all? It's the same price as last year's model.</p></div><div class="live-content"><time datetime="2026-09-10T07:58:42+00:00">September 10, 2026 – 3:58 AM</time><h2 id="hands-on-with-the-18-pro-max">Hands-on with the 18 Pro Max</h2><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="HYuuDMJ2Ch2YMUKD2MbYWc" name="iPhone 18 Pro cameras" alt="iPhone 18 Pro cameras" src="https://cdn.mos.cms.futurecdn.net/HYuuDMJ2Ch2YMUKD2MbYWc.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>Alongside the excitement of the new iPhone Duo, we've also got some hands-on time with the iPhone 18 Pro Max. You can read what <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-hands-on-sneaky-awesome-upgrades-but-worth-the-price-hike">Global Editor in Chief Mark Spoonauer thought of Apple's new Pro model</a>.</p><p>In a nutshell, it's the camera upgrades that are likely to be the biggest draw for anyone looking to upgrade.</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/BZi0R_thP9M" allowfullscreen></iframe></div></div></div><div class="live-content"><time datetime="2026-09-10T11:37:15+00:00">September 10, 2026 – 7:37 AM</time><h2 id="apple-watch-ultra-4-reasons-to-buy-and-reasons-to-skip">Apple Watch Ultra 4: Reasons to buy and reasons to skip</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='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.jpg" mos="" align="middle" fullscreen="" width="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>Those fond of an outdoor adventure or two may be eyeing up 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>, especially thanks to improved battery life and enhanced heart rate tracking. Our resident smartwatch guru, Dan Bracaglia, has run through everything the rugged new wearable has to offer and come up with his reasons for and against upgrading.</p><p>Here are his <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">five reasons to buy the Apple Watch Ultra 4 and two reasons to skip it</a>.</p></div><div class="live-content"><time datetime="2026-09-10T11:54:02+00:00">September 10, 2026 – 7:54 AM</time><h2 id="sneaky-price-hikes-have-arrived">Sneaky price hikes have arrived</h2><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="fXQyeewX6f4cMRqqSucB2D" name="iphone17-1 (2)-2" alt="Sage iPhone 17 in hand" src="https://cdn.mos.cms.futurecdn.net/fXQyeewX6f4cMRqqSucB2D.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>While Apple was very upfront about the increased prices for iPhone 18 Pro and Pro Max, it wasn't so eager to advertise the fact those aren't the only devices getting a price hike. All the <a href="https://www.tomsguide.com/phones/iphones/apple-quietly-jacks-the-prices-of-the-iphone-16-iphone-17-and-iphone-air-heres-how-much-youll-pay-now">older iPhones are getting a $100 price bump as well</a>, including iPhone 17, iPhone 17e, iPhone 16 and iPhone Air.</p><p>Considering the newest of those phones came out in February and the oldest of them landed two whole years ago, we have to wonder what Apple is thinking. <a href="https://www.tomsguide.com/phones/iphones/dont-expect-an-iphone-17-discount-at-todays-iphone-event-heres-why">We never expected the iPhone 17 to get the usual price cut</a>, since the iPhone 18 never made an appearance at Surprise and shine, but even we didn't anticipate the prices going up.</p><p>Make sure to grab one of the latest and <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pre-order-deals-heres-how-to-get-apples-new-phones-for-free">best iPhone 17 deals</a> while you can, otherwise you're going to end up paying more than you bargained for.</p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone 18 Pro is almost certainly getting a price hike — but it could be less than we feared ]]></title>
                                                                                                <dc:content><![CDATA[ <p>There's been a lot of concern about how much the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks">iPhone 18 Pro Max</a> might cost following today's iPhone event — with some predictions suggesting we could see prices rise <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-see-absolutely-massive-price-hike-according-to-researchers">by as much as $300.</a> Thankfully we may have just got some respite, thanks to a mammoth report from <a href="https://www.bloomberg.com/news/articles/2026-09-09/apple-event-details-2-000-iphone-duo-apple-watch-series-12-recording-feature?accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb3VyY2UiOiJTdWJzY3JpYmVyR2lmdGVkQXJ0aWNsZSIsImlhdCI6MTc4ODkyNjc3OSwiZXhwIjoxNzg5NTMxNTc5LCJhcnRpY2xlSWQiOiJUTDJBRTFLSkg2VjUwMCIsImJjb25uZWN0SWQiOiJDNEVEQ0FFMUZBMDU0MEJFQTI0QTlGMjExQzFFOTA4MCJ9.aPv2WOdayT-dHgMEwgSmlY6vJOZzEflGX_csJZNWbXI&leadSource=article-gifting" target="_blank">Bloomberg.</a></p><p>According to the report, Apple will not be adding multiple hundreds of dollars onto the new iPhones' price tag. The price will apparently still go up as expected, but only by $100. In other words, <a href="https://www.tomsguide.com/computing/ram-price-crisis-2026-everything-you-need-to-know">RAMageddon</a> or not, this is a pretty typical price hike for a flagship phone.</p><p>We all knew a price hike was coming after Apple <a href="https://www.tomsguide.com/computing/macbooks/apple-price-hikes-are-official-heres-how-much-more-youll-pay-for-macbooks-and-ipads-now">raised the prices of the majority of its products earlier this year</a> — including Macs, iPads and various other devices. The only products saved from this fate were iPhones and Apple Watches, which kept their original prices. </p><p>At the time it was obvious that Apple was waiting for the September launch event <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-see-absolutely-massive-price-hike-according-to-researchers">to increase the prices of new models</a>, but we couldn't predict the severity of the price hike. Nobody likes paying increased prices, but considering Apple hasn't implemented a serious price increase for a number of years (in contrast to its rivals), $100 more is easily the best we could hope for.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-X81bve"></div>                            </div>                            <script src="https://kwizly.com/embed/X81bve.js" async></script><p>So how much are we likely to pay as a result? The<a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review"> iPhone 17 Pro</a> and<a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review"> iPhone 17 Pro Max</a> start at $1,099 and $1,199, respectively — a price tag that gets you 256GB of storage space. That means we're looking at starting prices of $1,199 for the iPhone 18 Pro and $1,299 for the iPhone 18 Pro Max.</p><p>For reference the cost of the<a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review"> Samsung Galaxy S26 Ultra</a> and <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-pro-xl-review">Google Pixel 11 Pro XL</a> both start at $1,299 for the same 256GB of storage. This means Apple is essentially bringing the iPhone 18 Pro Max's price in line with its rivals. However since the Pixel 11 Pro and <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-plus-review">Galaxy S26 Plus</a> both start at $1,099, it means the iPhone 18 Pro is actually a little more expensive. </p><p>Obviously you don't necessarily have to eat the extra $100 right away. There's always the option to spread the overall cost as part of a multi-year phone plan, though your payments will no doubt rise by a few dollars a month to compensate for the higher price tag. <a href="https://www.tomsguide.com/phones/iphones/should-you-lease-your-next-iphone-what-you-need-to-know-about-the-rumored-apple-upgrade-program">Apple also launched its own iPhone leasing program</a> earlier this year, which will also insulate customers from higher prices  — albeit at the cost of never actually owning their devices. All that's before you take trade in credit into account as well. </p><p>Do we like the fact that iPhone 18 Pro's prices are going to increase? Not at all, life is getting incredibly expensive, and the last thing we need is one more extra bill to worry about. But in the grand scheme of things, I'm just grateful that things aren't a lot worse.</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/im-thrilled-the-iphone-ultra-is-reportedly-getting-magsafe-but-theres-a-major-problem">I'm thrilled the iPhone Ultra is reportedly getting MagSafe, but there's a major problem</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-apples-first-foldable-usd2-000-price-release-date-as-early-as-october">iPhone Duo is Apple's first foldable — $2,000 price, Apple Pencil, release date 'as early as October'</a></li><li><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 September event LIVE blog: iPhone Duo, iPhone 18 Pro Max, Apple Watch 12 and last-minute leaks</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-18-pro-is-almost-certainly-getting-a-price-hike-but-it-could-be-less-than-we-feared</link>
                                                                            <description>
                            <![CDATA[ The topic of iPhone 18 Pro prices has been debated extensively, but it turns out the increase might not be as bad as some people feared. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">i4mCd3bFBBJr4etcLP5XFd</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/4zbVNxFtCw8JYgt53YYMKL-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 11:23:51 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ tom.pritchard@futurenet.com (Tom Pritchard) ]]></author>                    <dc:creator><![CDATA[ Tom Pritchard ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/biCewUkKfSA6QnT2HxVc3f.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/4zbVNxFtCw8JYgt53YYMKL-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iphone 17 pro max in red.]]></media:description>                                                            <media:text><![CDATA[iphone 17 pro max in red.]]></media:text>
                                <media:title type="plain"><![CDATA[iphone 17 pro max in red.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/4zbVNxFtCw8JYgt53YYMKL-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>There's been a lot of concern about how much the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks">iPhone 18 Pro Max</a> might cost following today's iPhone event — with some predictions suggesting we could see prices rise <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-see-absolutely-massive-price-hike-according-to-researchers">by as much as $300.</a> Thankfully we may have just got some respite, thanks to a mammoth report from <a href="https://www.bloomberg.com/news/articles/2026-09-09/apple-event-details-2-000-iphone-duo-apple-watch-series-12-recording-feature?accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb3VyY2UiOiJTdWJzY3JpYmVyR2lmdGVkQXJ0aWNsZSIsImlhdCI6MTc4ODkyNjc3OSwiZXhwIjoxNzg5NTMxNTc5LCJhcnRpY2xlSWQiOiJUTDJBRTFLSkg2VjUwMCIsImJjb25uZWN0SWQiOiJDNEVEQ0FFMUZBMDU0MEJFQTI0QTlGMjExQzFFOTA4MCJ9.aPv2WOdayT-dHgMEwgSmlY6vJOZzEflGX_csJZNWbXI&leadSource=article-gifting" target="_blank">Bloomberg.</a></p><p>According to the report, Apple will not be adding multiple hundreds of dollars onto the new iPhones' price tag. The price will apparently still go up as expected, but only by $100. In other words, <a href="https://www.tomsguide.com/computing/ram-price-crisis-2026-everything-you-need-to-know">RAMageddon</a> or not, this is a pretty typical price hike for a flagship phone.</p><p>We all knew a price hike was coming after Apple <a href="https://www.tomsguide.com/computing/macbooks/apple-price-hikes-are-official-heres-how-much-more-youll-pay-for-macbooks-and-ipads-now">raised the prices of the majority of its products earlier this year</a> — including Macs, iPads and various other devices. The only products saved from this fate were iPhones and Apple Watches, which kept their original prices. </p><p>At the time it was obvious that Apple was waiting for the September launch event <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-see-absolutely-massive-price-hike-according-to-researchers">to increase the prices of new models</a>, but we couldn't predict the severity of the price hike. Nobody likes paying increased prices, but considering Apple hasn't implemented a serious price increase for a number of years (in contrast to its rivals), $100 more is easily the best we could hope for.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-X81bve"></div>                            </div>                            <script src="https://kwizly.com/embed/X81bve.js" async></script><p>So how much are we likely to pay as a result? The<a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review"> iPhone 17 Pro</a> and<a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review"> iPhone 17 Pro Max</a> start at $1,099 and $1,199, respectively — a price tag that gets you 256GB of storage space. That means we're looking at starting prices of $1,199 for the iPhone 18 Pro and $1,299 for the iPhone 18 Pro Max.</p><p>For reference the cost of the<a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review"> Samsung Galaxy S26 Ultra</a> and <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-pro-xl-review">Google Pixel 11 Pro XL</a> both start at $1,299 for the same 256GB of storage. This means Apple is essentially bringing the iPhone 18 Pro Max's price in line with its rivals. However since the Pixel 11 Pro and <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-plus-review">Galaxy S26 Plus</a> both start at $1,099, it means the iPhone 18 Pro is actually a little more expensive. </p><p>Obviously you don't necessarily have to eat the extra $100 right away. There's always the option to spread the overall cost as part of a multi-year phone plan, though your payments will no doubt rise by a few dollars a month to compensate for the higher price tag. <a href="https://www.tomsguide.com/phones/iphones/should-you-lease-your-next-iphone-what-you-need-to-know-about-the-rumored-apple-upgrade-program">Apple also launched its own iPhone leasing program</a> earlier this year, which will also insulate customers from higher prices  — albeit at the cost of never actually owning their devices. All that's before you take trade in credit into account as well. </p><p>Do we like the fact that iPhone 18 Pro's prices are going to increase? Not at all, life is getting incredibly expensive, and the last thing we need is one more extra bill to worry about. But in the grand scheme of things, I'm just grateful that things aren't a lot worse.</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/im-thrilled-the-iphone-ultra-is-reportedly-getting-magsafe-but-theres-a-major-problem">I'm thrilled the iPhone Ultra is reportedly getting MagSafe, but there's a major problem</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-duo-is-apples-first-foldable-usd2-000-price-release-date-as-early-as-october">iPhone Duo is Apple's first foldable — $2,000 price, Apple Pencil, release date 'as early as October'</a></li><li><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 September event LIVE blog: iPhone Duo, iPhone 18 Pro Max, Apple Watch 12 and last-minute leaks</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ macOS 27 Golden Gate has me excited for the MacBook Ultra — here's why ]]></title>
                                                                                                <dc:content><![CDATA[ <p><a href="https://www.tomsguide.com/computing/macos/apple-macos-tahoe-review">macOS Tahoe</a> was one of the worst updates I’ve used in years. Not since <a href="https://www.tomsguide.com/computing/windows-operating-systems/windows-is-40-today-heres-the-20-best-and-worst-moments-in-windows-history">Windows Vista</a> have I seen so many design and usability mistakes—unusual for Apple, of all companies. Long known for its reputation in design and thinking about the user first, 2025’s Tahoe update for the <a href="https://www.tomsguide.com/best-picks/best-macbook">best Macs</a> felt like a huge misstep. But <a href="https://www.tomsguide.com/computing/macos/macos-27">macOS Golden Gate</a> feels like a redemption for Tahoe’s mistakes.</p><p>I’ve owned a Mac since 2005, when the computers transitioned from PowerPC processors to Intel processors. For several years, I’ve owned an <a href="https://www.tomsguide.com/reviews/macbook-pro-2021-14-inch">M1 Pro MacBook Pro</a>, and it’s one of the <a href="https://www.tomsguide.com/computing/laptops/best-laptops">best laptops</a> I’ve ever owned. From its keyboard to the display, everything felt like a home run after years of strange hardware design choices, like the butterfly keyboard.</p><p>But as we get close to the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks">iPhone 18 Pro</a> and the rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Ultra/Duo</a> foldable, I’m also looking forward to finally updating my Mac to macOS Golden Gate, the newest update that fixes almost all of Tahoe’s mistakes. However, its other design changes have me wondering what comes next for the Mac. So, with rumors of a touchscreen Mac allegedly called the <a href="https://www.tomsguide.com/computing/laptops/macbook-ultra-everything-we-know-so-far">MacBook Ultra</a>, here’s why I’m very tempted to upgrade when Golden Gate officially launches.</p><h2 id="golden-gate-redeems-macos">Golden Gate redeems macOS</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4349px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="6onBfgc6zZedV7zQBmGFw8" name="macOS 27 Golden Gate Siri AI-2" alt="macOS 27" src="https://cdn.mos.cms.futurecdn.net/6onBfgc6zZedV7zQBmGFw8.jpg" mos="" align="middle" fullscreen="" width="4349" height="2446" 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>After trying the <a href="https://www.tomsguide.com/computing/macos/macos-golden-gate-public-beta-hands-on-preview">macOS Golden Gate public beta</a> over the summer, I was struck by how good Liquid Glass finally looks on my Mac. Tahoe showcased the new design in all the wrong ways—from bizarre layers that separated columns within windows to mismatched window sizes. In Golden Gate, that’s nonexistent, with everything looking sharp and far easier on the eye when you’re working with multiple apps on one screen.</p><p>It’s restored my faith that Apple has clearly realized what a mistake Tahoe was in its design, and whilst I’ll be upgrading my current MacBook Pro to Golden Gate once it’s out, it also feels like it’s laying the foundation for the <a href="https://www.tomsguide.com/computing/laptops/macbook-ultra-everything-we-know-so-far">MacBook Ultra</a>.</p><p>For anyone unaware, this rumored Mac seems to be the opposite of the <a href="https://www.tomsguide.com/computing/macbooks/apple-macbook-neo-review">MacBook Neo</a>. Instead of being an entry point, the MacBook Ultra seems aimed at those who want the ultimate portable Mac at a high price. Alleged features include an OLED touchscreen, a first for the Mac to accept touch input, as well as coming with M6 Pro or Ultra chips that give even better performance and battery life.</p><p>Apple silicon has been a huge leap for the Mac. It’s hard to think back to a time when an Intel MacBook Pro could barely manage 4 hours under heavy load, or struggle with games like BioShock Infinite that were then 3 years old since their PC release. Now, even in 2026, my M1 Pro MacBook Pro can still play games like <a href="https://www.tomsguide.com/reviews/resident-evil-4">Resident Evil 4 Remake</a> and others with ease, and I rarely hear the fan whirl. So thinking about what a 5-year leap could do for my Mac gaming, alongside everything else, has me excited.</p><p>These rumored features, combined with macOS Golden Gate, make me consider the Ultra as my next Mac, since it replaces two devices in one go.</p><h2 id="the-ultra-could-also-be-an-ipad-replacement">The Ultra could also be an iPad replacement</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3000px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="Kg4cbghayrcgsaf6yZstBB" name="iPadOS 27-5" alt="iPadOS 27" src="https://cdn.mos.cms.futurecdn.net/Kg4cbghayrcgsaf6yZstBB.jpg" mos="" align="middle" fullscreen="" width="3000" height="1687" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I’ve been a fan of the <a href="https://www.tomsguide.com/best-picks/best-ipad">iPad</a> since its 2010 debut, and whilst recent software updates, especially <a href="https://www.tomsguide.com/computing/ipads/apple-ipados-26-review">iPadOS 26</a>, have made Apple’s tablet far more productive, its locked ecosystem has always made me go back to the Mac.</p><p>But there are moments when a touch-screen can work well, such as editing videos for TikTok via LumaFusion, or reading comics from my childhood. It’s why I can see these two examples, and many others, working well on a touchscreen Mac, without macOS leaving the mouse behind.</p><p>Golden Gate clearly hints towards a touchscreen Mac—from being able to slide down to refresh in Safari and Mail, to every button designed as if they’re meant to be touched by a finger. Even <a href="https://www.tomsguide.com/phones/iphones/i-spent-a-week-with-siri-ai-here-are-my-honest-pros-and-cons">Siri AI</a> lets users send an email, record a voice note, take a selfie, and more with their voice or via the Siri app. The newest macOS update looks set to be ready for the MacBook Ultra.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-XYx7ZO"></div>                            </div>                            <script src="https://kwizly.com/embed/XYx7ZO.js" async></script><h2 id="outlook">Outlook</h2><p>When an ultra-high-end Mac seems like it will improve on what my M1 MacBook Pro offers, while replacing the use cases I’ve had for my iPad Pro for several years, it feels like the natural next step for me and how I work. Even for Mac gaming, with ways to play Windows games via Crossover or decompilations like Donkey Kong 64 or GoldenEye, the extra power thanks to the M6 architecture will be a huge step up from what I’ve been using since 2021.</p><p>So while many will be excited to own an iPhone Ultra or an iPhone 18 Pro model, I’m more excited to use the MacBook Ultra. From the much-improved macOS Golden Gate update to the OLED touchscreen, it feels like the MacBook Ultra could be one of the best Macs to use for at least another five years. If that happens, then I'll have to say goodbye to my M1 MacBook Pro.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/computing/macbooks/apple-macbook-ultra-may-arrive-running-on-some-of-the-same-chips-as-macbook-pro-heres-why">Apple MacBook Ultra may run on some of the same chips as MacBook Pro</a></li><li><a href="https://www.tomsguide.com/computing/apple-desktops/apple-just-announced-the-new-mac-studio-with-m5-ultra-and-it-will-be-a-local-ai-powerhouse">Apple just announced the new Mac Studio with M5 Ultra</a></li><li><a href="https://www.tomsguide.com/computing/laptops/best-laptops-of-ifa-2026-wild-colors-ultrathin-designs-and-rollable-displays">Best laptops of IFA 2026: Wild colors, ultrathin designs and rollable displays</a></li></ul><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=laptops&brands=Apple&min_discount_ratio=0.95&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 normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters {      display: flex;      gap: 12px;      justify-content: center;      flex-wrap: wrap;    }    .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);      display: -webkit-box;      -webkit-line-clamp: 2;      -webkit-box-orient: vertical;      overflow: hidden;    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    .tg-df-container .tg-df-card-cta.tg-df-cta-savings-squad {      background-color: #3c8d0d;    }    .tg-df-card:hover .tg-df-card-cta.tg-df-cta-savings-squad,    .tg-df-card-cta.tg-df-cta-savings-squad:hover {      background-color: #2b6509;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 0;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 0 16px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }            .tg-df-filters {        width: calc(100% + 32px);        margin: 0 -16px;        padding: 0 16px 4px 16px;        display: flex;        justify-content: flex-start;        gap: 8px;        flex-wrap: nowrap;        overflow-x: auto;        -webkit-overflow-scrolling: touch;        scrollbar-width: none;      }      .tg-df-filters::after {        content: "";        display: block;        flex: 0 0 8px;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }            .tg-df-sort-wrapper {        flex: 0 0 max(42%, 130px);        min-width: 0;      }      .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;        -webkit-line-clamp: 3;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        -webkit-line-clamp: 3;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 16px;      text-align: center;      width: 100%;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right {      background-color: rgba(255, 255, 255, 0.4);      border: none;      box-shadow: none;      backdrop-filter: blur(4px);      -webkit-backdrop-filter: blur(4px);    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right { right: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-right { right: 0; }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left:hover,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);      border: none;    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-carousel-roundels::after {      content: "";      flex: 0 0 32px;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;      transition: font-weight 0.2s;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-label {      font-weight: 700;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;      display: inline-flex;      align-items: center;      justify-content: center;      min-height: 36px;      box-sizing: border-box;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::after {      content: "";      flex: 0 0 32px;    }    .tg-df-grid-wrapper {      position: relative;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card {      flex: 0 0 auto;      width: 100px;      border-radius: 15px;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      border: 2px solid #1e293b;      background: white;      color: #1e293b;      display: flex;      flex-direction: column;      justify-content: center;      align-items: center;      font-weight: 600;      font-size: 14px;      cursor: pointer;      padding: 16px;      text-align: center;      transition: all 0.2s;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card:hover {      background: #1e293b;      color: white;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      -webkit-line-clamp: 2;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {      -webkit-line-clamp: 3;    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.45);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #5aaf0b; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #4a9109; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>          \x3C/div>          \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">      \x3Cdiv class="tg-df-top-bar">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>                \x3Cdiv class="tg-df-settings-wrapper">          \x3Cbutton type="button" class="tg-df-settings-btn" aria-label="Settings" id="tg-df-settings-toggle">            \x3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">                \x3Cpath d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.73 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.49-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>            \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-settings-dropdown-backdrop" id="tg-df-settings-backdrop">\x3C/div>          \x3Cdiv class="tg-df-settings-dropdown" id="tg-df-settings-panel">            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Search Region\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-region-select">                \x3Coption value="auto">🌍 Auto-detect\x3C/option>                \x3Coption value="US">🇺🇸 United States (US)\x3C/option>                \x3Coption value="GB">🇬🇧 United Kingdom (UK)\x3C/option>                \x3Coption value="CA">🇨🇦 Canada (CA)\x3C/option>                \x3Coption value="AU">🇦🇺 Australia (AU)\x3C/option>                \x3Coption value="DE">🇩🇪 Germany (DE)\x3C/option>                \x3Coption value="FR">🇫🇷 France (FR)\x3C/option>                \x3Coption value="IT">🇮🇹 Italy (IT)\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Retailer\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-retailer-select">                \x3Coption value="">All Retailers\x3C/option>                \x3Coption value="Amazon">Amazon\x3C/option>                \x3Coption value="Walmart">Walmart\x3C/option>                \x3Coption value="Best Buy">Best Buy\x3C/option>                \x3Coption value="Target">Target\x3C/option>                \x3Coption value="John Lewis">John Lewis\x3C/option>                \x3Coption value="Currys">Currys\x3C/option>                \x3Coption value="Argos">Argos\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Offer Type\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-offer-type-select">                \x3Coption value="">All Offers\x3C/option>                \x3Coption value="amazon_prime">Amazon Prime\x3C/option>                \x3Coption value="recommended_promo">Recommended Promo\x3C/option>                \x3Coption value="amazon_lightning">Amazon Lightning Deal\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Result Count\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-rows-select">                \x3Coption value="3">3 Items\x3C/option>                \x3Coption value="4">4 Items\x3C/option>                \x3Coption value="6">6 Items\x3C/option>                \x3Coption value="8">8 Items\x3C/option>                \x3Coption value="12" selected>12 Items\x3C/option>                \x3Coption value="24">24 Items\x3C/option>                \x3Coption value="48">48 Items\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Deal Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Only show products with active offers or previous prices (was_price)\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-deal-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Editor Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Enable multi-select to copy deals to CMS\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-editor-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">View Mode\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-view-mode-select">                \x3Coption value="auto">Auto Collection\x3C/option>                \x3Coption value="carousel">Carousel\x3C/option>                \x3Coption value="savings_squad">Savings Squad\x3C/option>                \x3Coption value="grid">Grid (Columns)\x3C/option>                \x3Coption value="row">Row (List)\x3C/option>              \x3C/select>            \x3C/div>          \x3C/div>        \x3C/div>      \x3C/div>      \x3Cdiv class="tg-df-filters">        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/>          \x3C/svg>          \x3Cselect class="tg-df-sort-select" aria-label="Sort Deals">            \x3Coption value="date_desc">Newest First\x3C/option>            \x3Coption value="best_match">Sort by: Match\x3C/option>            \x3Coption value="price_asc">Price Low to High\x3C/option>            \x3Coption value="price_desc">Price High to Low\x3C/option>            \x3Coption value="discount_desc">Biggest Discount\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>        \x3C/div>      \x3C/div>    \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();            if (['carousel', 'carousel-compact', 'auto', 'grid', 'row'].includes(this.getViewMode())) { this.loadCarouselSpreadsheet(); }        }        getViewMode() {          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          if (mode === 'carousel' || mode === 'auto' || mode === 'grid' || mode === 'row') {             if (mode === 'carousel') this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container') && mode === 'carousel') {               this.root.classList.add('is-carousel');             } else if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Everything';             if (this.discountFilter && !params.has('min_discount_ratio')) {               this.discountFilter.value = '5';             }          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (params.has('bg_color')) {            const bg = params.get('bg_color');            if (bg === 'white') {              this.root.style.setProperty('background-color', '#ffffff', 'important');            } else if (bg === 'transparent') {              this.root.style.setProperty('background-color', 'transparent', 'important');            } else if (bg === 'light_blue') {              this.root.style.setProperty('background-color', '#E7F0FF', 'important');            }          } else {             this.root.style.removeProperty('background-color');          }                    if (params.has('view_mode')) {            if (this.viewModeSelect) {              this.viewModeSelect.value = params.get('view_mode');            } else {              this.viewModeOverride = params.get('view_mode');            }          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'discount_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            this.searchInput.value = this.currentQuery;          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'discount_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const roundels = this.root.querySelectorAll('.tg-df-carousel-cat.original-hardcoded');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              if (this.getViewMode() === 'savings_squad' && this.autocompleteDropdown && this.airedaleTags && query.length > 0) {                 const matches = this.airedaleTags.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase()).slice(0, 5);                 if (matches.length > 0) {                    this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                    this.autocompleteDropdown.classList.add('active');                 } else {                    this.autocompleteDropdown.classList.remove('active');                 }              } else if (this.autocompleteDropdown) {                 this.autocompleteDropdown.classList.remove('active');              }              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  this.deals = [];                  this.render();                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                this.activeDealTag = null;                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });              this.activeDealTag = null;              this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.fetchDeals(query);              }            });          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = this.viewModeSelect.value === 'savings_squad' ? 'date_desc' : 'discount_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const finalHref = cardLink.href || cardLink.getAttribute('href') || '';                let actualRevenueId = cardLink.getAttribute('data-revenue-id');                const revMatch = finalHref.match(/(?:subId1|xcust|clickref|ascsubtag)=[^&]*?(\d{18,20})(?:&|$)/i);                if (revMatch && revMatch[1]) {                  actualRevenueId = revMatch[1];                }                const rewrittenLink = finalHref;                const revenueId = actualRevenueId;                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }                async loadCarouselSpreadsheet() {          try {              const parseCSVRow = (str) => {                  let result = [], cur = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (inQuotes) {                          if (char === '"') {                              if (str[i + 1] === '"') { cur += '"'; i++; }                              else { inQuotes = false; }                          } else { cur += char; }                      } else {                          if (char === '"') { inQuotes = true; }                          else if (char === ',') { result.push(cur); cur = ''; }                          else { cur += char; }                      }                  }                  result.push(cur); return result;              };              const parseCSV = (str) => {                  const rows = []; let curRow = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (char === '"') inQuotes = !inQuotes;                      if ((char === '\n' || char === '\r') && !inQuotes) {                          if (char === '\r' && str[i+1] === '\n') i++;                          if (curRow) rows.push(parseCSVRow(curRow));                          curRow = '';                      } else { curRow += char; }                  }                  if (curRow) rows.push(parseCSVRow(curRow));                  return rows;              };              const preloadedCSV = decodeURIComponent(escape(atob("LCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNQ0KUm91bmRlbCB0ZXh0LEFsbCxUVnMsRm9vdHdlYXIsQXBwYXJlbCxNYXR0cmVzZXMsQXBwbGlhbmNlcyxXZWFyYWJsZSB0ZWNoLEhlYWRwaG9uZXMsU21hcnQgSG9tZSxTcGVha2VycyxMYXB0b3BzLFRhYmxldHMsQ29tcHV0aW5nLFBob25lcyxHYW1pbmcsTGVnbw0KUm91bmRlbCBpbWFnZSxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL2FpLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL3R2cy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvN2IzYTIyNGIwNzk2M2M2MjdiNmI5MDliZDc4MzM4MzZlMDJmZjgxOS5qcGcud2VicCxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy84NGRhYzVkNDhlZDJkNDQ4NTU5ZWJhNjdhY2U4MzE0Y2M2N2NjZDk0LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vc2hvcC1hc3NldHMvY2Fyb3VzZWwvbWF0dHJlc3Nlcy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvNzY4ZTk3Y2ViMDcxODAxZmFlMjA5MTBkMDgyMGIxNmY3NDdhZjkzOS5qcGcud2VicCxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL3dlbGxuZXNzLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL2hlYWRwaG9uZXMuanBnLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzg5NTM1YmVlYmUyMGRiYmQ0YTM0NmQ2ZDZiZGZlOTFkOGE4ODRhMjEuanBnLndlYnAsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9zaG9wLWFzc2V0cy9jYXJvdXNlbC9hdWRpby5qcGcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9zaG9wLWFzc2V0cy9jYXJvdXNlbC9sYXB0b3BzLmpwZyxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy8yMzk3NTY0ZWQ3YTVmZjk0N2U5YjZiMzBlNTRmNDc0OTRiODQxZjg5LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vc2hvcC1hc3NldHMvY2Fyb3VzZWwvY29tcHV0aW5nLmpwZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL3Bob25lcy5wbmcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9zaG9wLWFzc2V0cy9jYXJvdXNlbC9nYW1pbmcucG5nLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzRmNmM2MjFjYWMwYmMxYTg1ZDU5M2UzNTk0YmE1YjM0OWVmZmQyOTIuanBnLndlYnANClNlYXJjaCBRdWVyeSxFdmVyeXRoaW5nLFRlbGV2aXNpb25zLCJTbmVha2VycywgcnVubmluZyBzaG9lcywgc2FuZGFscyIsQ2xvdGhpbmcsTWF0dHJlc3NlcyxIb21lIEFwcGxpYW5jZXMsV2VhcmFibGVzICYgRml0bmVzcyBUZWNoLEhlYWRwaG9uZXMsSG9tZSBUZWNoLFNwZWFrZXJzLExhcHRvcHMsVGFibGV0cyxDb21wdXRpbmcsUGhvbmVzLEdhbWluZyxDb25zdHJ1Y3Rpb24gVG95cw0KRGlzY291bnQgQW1vdW50LG1pbiA1JSxtaW4gMTAlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUNClByaWNlIFJhbmdlLCwsLCxtaW4gJDQwMCwsLCxtaW4gJDI1LCxtaW4gJDMwMCwsLG1pbiAkMTAwLCwNCkJyYW5kIFNlbGVjdGlvbiwsLCwsLCwsLCwsLCwsLCwNCkZpbHRlciBidXR0b25zLCwsLCwsLCwsLCwsLCwsLA0KMSxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMNCjIsQW1hem9uIGRlYWxzLFVuZGVyICQxMDAwLDUwJSBvZmYsQWRpZGFzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsNTAlIG9mZixBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscw0KMyxPdmVyICQ0MDAsVW5kZXIgJDUwMCxIb2thLE5pa2UsU2FhdHZhLE5pbmphLDQwJSBvZmYsSkxhYiwsSkJMLERlbGwsLEFzdXMsQXBwbGUsQ29uc29sZXMsU3RhciBXYXJzDQo0LFVuZGVyICQxMDAwLDUwJSBvZmYsU2tlY2hlcnMsVW5kZXIgQXJtb3VyLEhlbGl4LFNoYXJrLEdhcm1pbixBbmtlciBTb3VuZGNvcmUsUmluZyxTb25vcyxBcHBsZSxBcHBsZSxUUC1saW5rLFNhbXN1bmcsQWNjZXNzb3JpZXMsVW5kZXIgJDI1DQo1LFVuZGVyICQ1MDAsTEcsQXNpY3MsQ29sdW1iaWEsRHJlYW1DbG91ZCxLZXVyaWcsQXBwbGUsU29ueSxHb3ZlZSxUcmliaXQsTGVub3ZvLFNhbXN1bmcsRWVybyxHb29nbGUsR2FtZXMsVW5kZXIgJDUwDQo2LDUwJSBvZmYsU2Ftc3VuZyxOaWtlLFBhdGFnb25pYSxOZWN0YXIsRGUnTG9uZ2hpLEFtYXpmaXQsQXBwbGUsS2FzYSBzbWFydCxTb255LEFsaWVud2FyZSxUQ0wsTmV0Z2VhcixNb3Rvcm9sYSxOaW50ZW5kbyxCb3RhbmljYWxzDQo3LEFtYXpvbixIaXNlbnNlLE5ldyBCYWxhbmNlLEFyYyd0ZXJ5eCxUZW1wdXItcGVkaWMsRHlzb24sRml0Yml0LEJlYXRzLFBoaWxpcHMgSHVlLEFua2VyLEFjZXIsT25lUGx1cyxEZWxsLE9uZVBsdXMsU29ueSxEaXNuZXkNCjgsQXBwbGUsVENMLEFkaWRhcyxDYXJoYXJ0dCxCZWFyLEJpc3NlbGwsU2Ftc3VuZyxFYXJmdW4sQmxpbmssQmVhdHMsTVNJLE1pY3Jvc29mdCxBY2VyLE5vdGhpbmcsWGJveCxNYXJ2ZWwNCjksLFNvbnksU2F1Y29ueSxUaGUgTm9ydGggRmFjZSxTaWVuYSxOdXRyaWJ1bGxldCxPdXJhLFNhbXN1bmcsR29vZ2xlIE5lc3QgLE1hcnNoYWxsLFNhbXN1bmcsTGVub3ZvLExlbm92bywsLFBva2Vtb24NCjEwLCxSb2t1LEJpcmtlbnN0b2NrLENSWiBZb2dhLFdpbmtCZWRzLEJsYWNrIGFuZCBEZWNrZXIsUmluZ2Nvbm4sQ01GLEV1ZnksU2Ftc3VuZyxNaWNyb3NvZnQsUmVNYXJrYWJsZSxBbGllbndhcmUsLCwNCjExLCwsQnJvb2tzLFRoZSBHeW0gUGVvcGxlLEJyb29rbHluIGJlZGRpbmcsTmVzcHJlc3NvLCwxTW9yZSxBcmxvLCxSYXplciwsQ29yc2FpciwsLA0KMTIsLCxDcm9jcywsRWlnaHQgU2xlZXAsQ3Vpc2luYXJ0LCxKQkwsLCwsLEhQLCwsDQpOb3RlcywsLCwsLCwsLCwsLCwsLCwNCiwsIlByaW9yaXRpc2UgYmlnZ2VzdCAlLyQgZGlzY291bnQsIFR2cyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGV2ZW4gaWYgdGhleSBhcmUgc3RpbGwgZXhwZW5zaXZlIiwiTm8gcGF0dGVybiB0byBwcmljaW5nL2Rpc2NvdW50LCByZWFkZXJzIG1haW5seSBzaG9wIGJ5IGJyYW5kL3JlY29nbmlzYWJsZSBzaG9lcyIsIk5vIHBhdHRlcm4gdG8gcHJpY2luZy9kaXNjb3VudCwgcmVhZGVycyBtYWlubHkgc2hvcCBieSBicmFuZCIsIkEgbGFiZWwgd2lsbCBkZWZpbml0ZWx5IGhlbHAgaGVyZSBlLmcuIGJlc3QgZm9yIHNpZGUgc2xlZXBlciwgYmVzdCBtZW1vcnkgZm9hbSIsIkFwcGxpYW5jZXMgaXMgYSBiaWcgY2F0ZWdvcnksIGlzIGl0IHBvc3NpYmxlIHRvIHNwbGl0IGludG8ga2l0Y2hlbiBhcHBsaWFuY2VzLCBmbG9vcmNhcmUsIGFpciBoZWFsdGgvY29vbGluZz8gT3Igc2ltaWxhciIsIkZvY3VzIG9uIHZhbHVlIGZvciBtb25leSwgR2FybWlucyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiBwb3B1bGFyIGV2ZW4gdGhvdWdoIHRoZXkgYXJlIHN0aWxsICQ1MDAiLCwsLCxJbmNsdWRlIEtpbmRsZXMsSSB3b3VsZCBpbmNsdWRlIHdpZmkgcm91dGVycyBoZXJlIGluc3RlYWQgb2Ygc21hcnQgaG9tZSxDYW4gd2Ugc3VyZmFjZSBwaG9uZSBwcm92aWRlciBkZWFscz8gVC1tb2JpbGUgYW5kIHZlcml6b24gd291bGQgbWFrZSBhIGxvdCBtb3JlIG1vbmV5IHRoYW4gQW1hem9uLCwNCiwsaGF2aW5nIGEgJ2Jlc3QgZm9yJyBsYWJlbCB3b3VsZCBiZSBoZWxwZnVsIGUuZy4gYmVzdCBmb3IgYnJpZ2h0IHJvb20sQ2FuIHdlIHN0b3Aga2lkcyBzaG9lcyBmcm9tIHB1bGxpbmcgdGhyb3VnaD8sIldpbGwgdGhpcyBpbmNsdWRlIGFjY2Vzc29yaWVzIGUuZy4gY2FwcywgYmFncywgaWYgc28gbWFrZSBzdXJlIHRoZXNlIGFyZSBtaXhlZCB0aHJvdWdob3V0IGNsb3RoaW5nIGRlYWxzIixXaWxsIHRoaXMgaW5jbHVkZSB0b3BwZXJzIGFuZCBwaWxsb3dzPyBTZWVpbmcgbW9yZSBtb21lbnR1bSB3aXRoIHRoaXMgY2F0ZWdvcnkgcmVjZW50bHkgc28gYSBiZWRkaW5nIHRhYiBtaWdodCB3b3JrLCwiTmVlZCB0byBtYWtlIHN1cmUgYmFuZHMsIHNjcmVlbiBwcm90ZWN0b3JzIGV0Yy4gZG9uJ3QgcHVsbCBpbnRvIGhlcmUiLCwsLCwsLCwsDQosLCJQcmlvcml0aXNlIDY1JycgYW5kIDU1JyBpbmNoIFRWcywgdGhlbiBiaWdnZXIgc2NyZWVucyBiZWZvcmUgdGhlIHNtYWxsZXIgc2l6ZXMiLCwsUXVlZW4gaXMgdGhlIG1vc3QgcG9wdWxhciBzaXplIGluIHRoZSBVUyAtIHByaW9yaXRpc2UgZGVhbHMgZm9yIHRoaXMgc2l6ZSwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpDYXRlZ29yaWVzIHRvIGNvbnNpZGVyLCxQcm9kdWN0cyBpbmNsdWRlZCwsLCwsLCwsLCwsLCwsDQpVbmRlciAkNTA/LCxBaXIgdGFncywsLCwsLCwsLCwsLCwsDQosLFBvcnRhYmxlIGNoYXJnZXJzL3dpcmVsZXNzIGNoYXJnZXJzLCwsLCwsLCwsLCwsLCwNCiwsIldhdGVyIGJvdHRsZXMgKHN0YW5sZXlzLCBPd2FsYSwgSHlkcm8gZmxhc2ssIFlldGkpIiwsLCwsLCwsLCwsLCwsDQosLEhhbmQgaGVsZCBmYW5zLCwsLCwsLCwsLCwsLCwNCiwsLCwsLCwsLCwsLCwsLCwNCmhvbWUgb2ZmaWNlLCxvZmZpY2UgY2hhaXJzLCwsLCwsLCwsLCwsLCwNCiwsc3RhbmRpbmcgZGVza3MsLCwsLCwsLCwsLCwsLA0KLCxtb25pdG9ycywsLCwsLCwsLCwsLCwsDQosLEtleWJvYXJkcywsLCwsLCwsLCwsLCwsDQosLGRvY2tpbmcgc3RhdGlvbiwsLCwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpHYW1pbmcsLENvbnNvbGVzLCwsLCwsLCwsLCwsLCwNCiwsQWNjZXNzb3JpZXMsLCwsLCwsLCwsLCwsLA0KLCxHYW1lcywsLCwsLCwsLCwsLCwsDQosLENvdWxkIGluY2x1ZGUgTGVnbz8sLCwsLCwsLCwsLCwsLA==")));              const text = preloadedCSV;              const parsed = parseCSV(text);                            const rowsByName = {};              let filterStart = -1;              parsed.forEach((rc, i) => {                 if (rc && rc.length > 0 && rc[0]) rowsByName[rc[0]] = rc;                 if (rc && rc.length > 0 && rc[0] === 'Filter buttons') filterStart = i;              });                            const cols = [];              if(rowsByName['Roundel text']) {                const headerRow = rowsByName['Roundel text'];                for(let col = 1; col < headerRow.length; col++) {                   let label = headerRow[col];                   if (!label) continue;                                      let q = rowsByName['Search Query'] && rowsByName['Search Query'][col] ? rowsByName['Search Query'][col] : '';                   let img = rowsByName['Roundel image'] && rowsByName['Roundel image'][col] ? rowsByName['Roundel image'][col] : '';                   let ds = rowsByName['Discount Amount'] && rowsByName['Discount Amount'][col] ? rowsByName['Discount Amount'][col] : '';                   let pr = rowsByName['Price Range'] && rowsByName['Price Range'][col] ? rowsByName['Price Range'][col] : '';                   let rt = rowsByName['Retailer'] && rowsByName['Retailer'][col] ? rowsByName['Retailer'][col] : '';                   let ot = rowsByName['Offer Type'] && rowsByName['Offer Type'][col] ? rowsByName['Offer Type'][col] : '';                                      let filters = [];                   if(filterStart > 0) {                     for(let r = filterStart + 1; r < parsed.length; r++) {                         if(!parsed[r] || parsed[r][0] === 'Notes' || parsed[r][0] === 'Categories to consider') break;                         let f = parsed[r][col];                         if(f) filters.push(f);                     }                   }                   cols.push({ label, img, q, ds, pr, rt, ot, filters });                }              }              this.carouselData = cols;              if (this.carouselData && this.carouselData.length > 0) {                 const isMatched = this.carouselData.some(c => c.q === this.currentQuery || c.label === this.currentQuery);                 if (!isMatched) {                    const first = this.carouselData[0];                    this.currentQuery = first.q || first.label;                    if (this.priceFilter) this.priceFilter.value = 'all';                    if (this.customPriceMin) this.customPriceMin.value = '';                    if (this.customPriceMax) this.customPriceMax.value = '';                    let dPr = first.pr || 'all';                    if (typeof dPr === 'string' && dPr !== 'all') {                       let prLower = dPr.toLowerCase();                       if (prLower.includes('min') || prLower.includes('over')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else if (prLower.includes('max') || prLower.includes('under')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       }                    }                    let dAm = '0';                    if(first.ds && typeof first.ds === 'string') {                       let m = first.ds.match(/(\d+)/);                       if(m) dAm = m[1];                    }                    if (this.discountFilter) this.discountFilter.value = dAm;                    if (this.offerTypeSelect) this.offerTypeSelect.value = first.ot || '';                    if (this.retailerSelect) this.retailerSelect.value = first.rt || '';                    this.selectedBrands = [];                    if (this.brandDropdown) {                        const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                        chks.forEach(chk => chk.checked = false);                    }                    if (this.searchInput) this.searchInput.value = this.currentQuery;                 }              }              this.renderCarouselUI();          } catch(e){ console.warn(e); }        }                renderCarouselUI() {           const roundelWrapper = this.root.querySelector('.tg-df-carousel-roundels');           if(!roundelWrapper || !this.carouselData) return;                      let html = '';           this.carouselData.forEach(r => {              const q = r.q || r.label;              const isActive = (this.currentQuery === q || this.currentQuery === r.label) ? 'active' : '';              const imgHtml = r.img ? `\x3Cimg src="${r.img}" alt="${r.label}" />` : `\x3Csvg width="32" height="32" fill="#1F69FF" viewBox="0 0 24 24">\x3Cpath d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>\x3C/svg>`;              html += `                \x3Cdiv class="tg-df-roundel tg-df-carousel-cat ${isActive}" data-label="${this.escapeHTML(r.label)}">                  \x3Cdiv class="tg-df-roundel-img-box">${imgHtml}\x3C/div>                  \x3Cspan class="tg-df-roundel-label">${this.escapeHTML(r.label)}\x3C/span>                \x3C/div>              `;           });           roundelWrapper.innerHTML = html;                      // Rebind clicks           const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');           roundels.forEach(rNode => {             rNode.addEventListener('click', () => {                const r = this.carouselData.find(c => c.label === rNode.getAttribute('data-label'));                 if(!r) return;                                  if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: r.label,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = r.q || r.label;                const labelTitle = this.root.querySelector('#tg-df-carousel-title-label');                if (labelTitle) labelTitle.textContent = 'Best ' + this.currentQuery;                if (this.priceFilter) this.priceFilter.value = 'all';                if (this.customPriceMin) this.customPriceMin.value = '';                if (this.customPriceMax) this.customPriceMax.value = '';                let dPr = r.pr || 'all';                if (typeof dPr === 'string' && dPr !== 'all') {                   let prLower = dPr.toLowerCase();                   if (prLower.includes('min') || prLower.includes('over')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMin) this.customPriceMin.value = m[1];                   } else if (prLower.includes('max') || prLower.includes('under')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMax) this.customPriceMax.value = m[1];                   }                }                                let discountAmount = '0';                if(r.ds && typeof r.ds === 'string') {                   let m = r.ds.match(/(\d+)/);                   if(m) discountAmount = m[1];                }                if (this.discountFilter) this.discountFilter.value = discountAmount;                if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                                // Clear brands                    this.selectedBrands = [];                    if (this.brandDropdown) {                    const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                    chks.forEach(chk => chk.checked = false);                }                                if (this.searchInput) this.searchInput.value = this.currentQuery;                                roundels.forEach(ro => ro.classList.remove('active'));                if (rNode) rNode.classList.add('active');                                this.renderCarouselFilters(r);                this.fetchDeals(this.currentQuery);             });           });                      // Auto-highlight active           const activeR = this.carouselData.find(c => c.q === this.currentQuery || c.label === this.currentQuery);           if(activeR) this.renderCarouselFilters(activeR);        }                renderCarouselFilters(r) {           const filtersWrap = this.root.querySelector('.tg-df-carousel-filters-wrap');           if(!filtersWrap) return;                      let html = `\x3Cbutton class="tg-df-carousel-filter-btn" data-type="all">All\x3C/button>`;                      r.filters.forEach(f => {              let fL = f.toLowerCase();              let icon = '';              let logic = `data-type="custom" data-v="${this.escapeHTML(f)}"`;              if (fL === 'amazon deals' || fL === 'prime deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>`;              } else if (fL === 'lightning deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>`;              } else {                 if (fL.includes('lightning')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap">\x3Cpolygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2">\x3C/polygon>\x3C/svg>`;                 } else if (fL.includes('% off')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>`;                 } else if (fL.includes('under') || fL.includes('min ')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>`;                 }                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>${icon} ${this.escapeHTML(f)}\x3C/button>`;              }           });                      filtersWrap.innerHTML = html;                      const btns = filtersWrap.querySelectorAll('button');           btns.forEach(b => {             b.addEventListener('click', () => {                const type = b.getAttribute('data-type');                if (type === 'custom') {                   const v = b.getAttribute('data-v');                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-custom-${(v||'').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, name: 'Custom Filter', label: v });                }                if (type === 'all') {                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: 'filter-clear-all', name: 'Clear all', label: 'Clear all filters' });                   // reset everything                   btns.forEach(btn => btn.classList.remove('active'));                   b.classList.add('active');                                      // Reset prices                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   if (this.brandDropdown) {                     const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                     chks.forEach(chk => chk.checked = false);                   }                } else {                   const v = b.getAttribute('data-v');                   const fL = v.toLowerCase();                                      let mapRet = ['amazon', 'walmart', 'best buy', 'target', 'john lewis', 'currys', 'argos'];                   const getCategory = (s) => {                      if (s === 'lightning deals' || s === 'amazon deals' || s === 'prime deals') return 'offer';                      if (s.includes('% off')) return 'discount';                      if (s.includes('under') || s.includes('over') || s.includes('min') || s.includes('max')) return 'price';                      if (mapRet.includes(s)) return 'retailer';                      return 'brand';                   };                   const cat = getCategory(fL);                   const wasActive = b.classList.contains('active');                   if (cat !== 'brand') {                      btns.forEach(btn => {                          if (btn === b) return;                          if (btn.getAttribute('data-type') === 'all') return;                          const bV = btn.getAttribute('data-v');                          if (!bV) return;                          if (getCategory(bV.toLowerCase()) === cat) btn.classList.remove('active');                      });                   }                   if (wasActive) b.classList.remove('active');                   else b.classList.add('active');                   let anyActive = Array.from(btns).some(btn => btn !== btns[0] && btn.classList.contains('active'));                   if (!anyActive) {                       btns[0].click();                       return;                   } else {                       btns[0].classList.remove('active');                   }                                      if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   btns.forEach(btn => {                       if (!btn.classList.contains('active') || btn.getAttribute('data-type') === 'all') return;                       const vv = btn.getAttribute('data-v');                       const vl = vv.toLowerCase();                                              if (vl === 'lightning deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_lightning';                       } else if (vl === 'amazon deals' || vl === 'prime deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_prime';                       } else if (vl.includes('% off')) {                          let m = vl.match(/(\d+)%/);                          if (m && this.discountFilter) this.discountFilter.value = m[1];                       } else if (vl.includes('under') || vl.includes('max')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       } else if (vl.includes('min') || vl.includes('over')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else {                          let foundR = mapRet.find(x => x === vl);                          if (foundR) {                             let realR = ['Amazon', 'Walmart', 'Best Buy', 'Target', 'John Lewis', 'Currys', 'Argos'].find(x => x.toLowerCase() === vl);                             if (this.retailerSelect) this.retailerSelect.value = realR;                          } else {                             this.selectedBrands.push(vv);                          }                       }                   });                                      if (this.brandDropdown) {                       const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                       chks.forEach(c => c.checked = this.selectedBrands.includes(c.value));                   }                                      if (r.pr && typeof r.pr === 'string') {                       let prL = r.pr.toLowerCase();                       if (prL.includes('under $')) {                           let m = prL.match(/under \$(\d+)/i);                           if (m && this.customPriceMax && !this.customPriceMax.value) this.customPriceMax.value = m[1];                       }                   }                }                                this.fetchDeals(this.currentQuery);             });           });                      // default to highlighting first           btns[0].classList.add('active');        }async fetchDeals(query, append = false) {          if (!append) {             this.showLoading();             this.deals = [];             this.displayLimit = this.getRowsLimit();          } else {             this.displayLimit += this.getRowsLimit();          }                    try {            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad(append);            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query, append);               } else {                 await this.fetchHawkDeals(query, append);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query, append);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const url = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let dynamicBrandsCounts = {};                    targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                   dynamicBrandsCounts[data.brand] = (dynamicBrandsCounts[data.brand] || 0) + 1;                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || ''                });             });          });                    const airedaleBrandsList = Object.keys(dynamicBrandsCounts).map(b => ({              formatted_value: b,              count: dynamicBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.getFilteredDeals().slice(0, this.displayLimit), this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query, append = false) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (append && this.deals.length > 0) {            url.searchParams.append('offset', this.deals.length.toString());          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.getFilteredDeals().slice(0, this.displayLimit), this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.getFilteredDeals().slice(0, this.displayLimit), this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: this.decodeHTML(item.name || item.title || item.model_name || item.product_name || 'Unknown Product'),            brand: this.decodeHTML(item.brand || ''),            productName: this.decodeHTML(item.model_name || item.product_name || item.name || ''),            merchant: this.decodeHTML(item.merchant_name || item.merchant || item.retailer || 'Retailer'),            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : (this.getViewMode() === 'savings_squad' ? 'date_desc' : 'discount_desc');          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin-top:8px;">${_div}                ${_div}              ${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const finalHref = btn.href || btn.getAttribute('href') || '';                let actualRevenueId = btn.getAttribute('data-revenue-id');                const revMatch = finalHref.match(/(?:subId1|xcust|clickref|ascsubtag)=[^&]*?(\d{18,20})(?:&|$)/i);                if (revMatch && revMatch[1]) {                  actualRevenueId = revMatch[1];                }                const rewrittenLink = finalHref;                const revenueId = actualRevenueId;                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)} (${this.airedaleTagCounts[tag] || 0})${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = isSavingsSquadMode ? 'View Deal' : 'Check Price';              if (isSavingsSquadMode) {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                  ${_div}                `;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = `                \x3Cdiv class="tg-df-card-merchant-wrapper">                  \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                ${_div}                \x3Cdiv class="tg-df-card-price-group">                  ${isSavingsSquadMode ? '' : `                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                  `}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description">\x3Cp>${this.escapeHTML(deal.description)}${_p}${_div}` : ''}                      ${_div}                    ${_div}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>${deal.isCheckPrice ? 'Check Price' : 'View Deal'}${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cp style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 12px; line-height: 1.4;">${this.escapeHTML(deal.description)}${_p}` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${priceGroupHtml}                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta ${isSavingsSquadMode ? 'tg-df-cta-savings-squad' : ''}" style="text-decoration: none;">${ctaText}${_a}                  ${_div}                ${_div}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit || ((this.getViewMode() === 'carousel' || this.getViewMode() === 'auto') && displayDeals.length > 0 && displayDeals.length % ((this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12) === 0)) {            if (this.getViewMode() === 'carousel') {               dealsHtml += `                 \x3Cbutton type="button" class="tg-df-load-more-card tg-df-load-more">                   \x3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-bottom: 8px;">\x3Cpath d="M5 12h14">\x3C/path>\x3Cpath d="m12 5 7 7-7 7">\x3C/path>\x3C/svg>                   Load More                 ${_button}               `;            } else {               dealsHtml += `                 \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                   \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; align-items: center;">Load More${_button}                 ${_div}               `;            }          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let rightChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             let leftChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-left');             if (this.getViewMode() === 'carousel') {                 // The observer set up in setupScrollListeners handles visibility.                 if (rightChevron) rightChevron.style.display = 'flex';                 if (leftChevron) leftChevron.style.display = 'none'; // reset correctly             } else {                 if (rightChevron) rightChevron.style.display = 'none';                 if (leftChevron) leftChevron.style.display = 'none';             }          }                    const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', async () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              if (displayDeals.length <= this.displayLimit) {                 loadMoreBtn.innerHTML = `                  <svg class="tg-df-spinner" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 8px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>                  Loading...                 `;                 loadMoreBtn.disabled = true;                 await this.fetchDeals(this.currentQuery, true);              } else {                 this.displayLimit += this.getRowsLimit();                 this.render();              }            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            setTimeout(() => {               if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');               document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));            }, 50);          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/computing/macbooks/macos-27-golden-gate-has-me-excited-for-the-macbook-ultra-heres-why</link>
                                                                            <description>
                            <![CDATA[ After the disappointing macOS Tahoe, Golden Gate looks like a huge improvement. And it also has me tempted by the rumored MacBook Ultra. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">DhERMXDA5AYv6uzCR9D3G9</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/gQb27riPj5CeJQa2gZqQVC-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 10:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[MacBooks]]></category>
                                                    <category><![CDATA[Computing]]></category>
                                                    <category><![CDATA[Laptops]]></category>
                                                                                                                    <dc:creator><![CDATA[ Daryl Baxter ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/P9iJP4ECuoNHX6uZuFdine.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Daryl&#039;s first writing piece was during his days at Nottingham Trent University in 2012, where his interview with original Tomb Raider composer Nathan McCree was published in the Uni magazine across all its campuses, helping Daryl to discover the career he wanted to follow. Even though he was currently studying (and eventually graduated) a degree in Computer Systems (Networks) at the time.&lt;/p&gt;&lt;p&gt;He had been working as tech support in many forms while freelancing on the side, when he decided to freelance full-time towards the end of 2018. Eventually, it led to a position building out a new tech site at Gfinity, and after 18 months, moved to Tom&#039;s Guide&#039;s sister site TechRadar to help build out the Software &amp; Downloads section.&lt;/p&gt;&lt;p&gt;During this, Daryl also published a now bestselling book that&#039;s available in most shops in town and online, called &#039;&lt;a href=&quot;https://www.pen-and-sword.co.uk/The-Making-of-Tomb-Raider-Hardback/p/20165&quot; target=&quot;_blank&quot;&gt;The Making of Tomb Raider&lt;/a&gt;&#039;, which tells the story of the beginnings of Lara Croft, up until the original team disbanded at the release of Tomb Raider 2 in 1997. His second book, &#039;&lt;a href=&quot;https://www.pen-and-sword.co.uk/50-Years-of-Boss-Fights-Hardback/p/50605&quot; target=&quot;_blank&quot;&gt;50 Years of Boss Fights&lt;/a&gt;&#039;, came out in June 2024, and he has a newsletter called &#039;&lt;a href=&quot;https://darylbaxter.com/springboard/&quot; target=&quot;_blank&quot;&gt;Springboard&lt;/a&gt;&#039;.&lt;/p&gt;&lt;p&gt;But in his spare time, he&#039;s usually found in a coffee shop, playing many retro games. Alongside this, he&#039;s currently replaying Tomb Raider VI thanks to the Remastered Collection, as well as quoting Simpsons quotes to whomever is nearby.&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/gQb27riPj5CeJQa2gZqQVC-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[MacBook Pro 16-inch M5 Pro on a desk]]></media:description>                                                            <media:text><![CDATA[MacBook Pro 16-inch M5 Pro on a desk]]></media:text>
                                <media:title type="plain"><![CDATA[MacBook Pro 16-inch M5 Pro on a desk]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/gQb27riPj5CeJQa2gZqQVC-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p><a href="https://www.tomsguide.com/computing/macos/apple-macos-tahoe-review">macOS Tahoe</a> was one of the worst updates I’ve used in years. Not since <a href="https://www.tomsguide.com/computing/windows-operating-systems/windows-is-40-today-heres-the-20-best-and-worst-moments-in-windows-history">Windows Vista</a> have I seen so many design and usability mistakes—unusual for Apple, of all companies. Long known for its reputation in design and thinking about the user first, 2025’s Tahoe update for the <a href="https://www.tomsguide.com/best-picks/best-macbook">best Macs</a> felt like a huge misstep. But <a href="https://www.tomsguide.com/computing/macos/macos-27">macOS Golden Gate</a> feels like a redemption for Tahoe’s mistakes.</p><p>I’ve owned a Mac since 2005, when the computers transitioned from PowerPC processors to Intel processors. For several years, I’ve owned an <a href="https://www.tomsguide.com/reviews/macbook-pro-2021-14-inch">M1 Pro MacBook Pro</a>, and it’s one of the <a href="https://www.tomsguide.com/computing/laptops/best-laptops">best laptops</a> I’ve ever owned. From its keyboard to the display, everything felt like a home run after years of strange hardware design choices, like the butterfly keyboard.</p><p>But as we get close to the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks">iPhone 18 Pro</a> and the rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Ultra/Duo</a> foldable, I’m also looking forward to finally updating my Mac to macOS Golden Gate, the newest update that fixes almost all of Tahoe’s mistakes. However, its other design changes have me wondering what comes next for the Mac. So, with rumors of a touchscreen Mac allegedly called the <a href="https://www.tomsguide.com/computing/laptops/macbook-ultra-everything-we-know-so-far">MacBook Ultra</a>, here’s why I’m very tempted to upgrade when Golden Gate officially launches.</p><h2 id="golden-gate-redeems-macos">Golden Gate redeems macOS</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4349px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="6onBfgc6zZedV7zQBmGFw8" name="macOS 27 Golden Gate Siri AI-2" alt="macOS 27" src="https://cdn.mos.cms.futurecdn.net/6onBfgc6zZedV7zQBmGFw8.jpg" mos="" align="middle" fullscreen="" width="4349" height="2446" 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>After trying the <a href="https://www.tomsguide.com/computing/macos/macos-golden-gate-public-beta-hands-on-preview">macOS Golden Gate public beta</a> over the summer, I was struck by how good Liquid Glass finally looks on my Mac. Tahoe showcased the new design in all the wrong ways—from bizarre layers that separated columns within windows to mismatched window sizes. In Golden Gate, that’s nonexistent, with everything looking sharp and far easier on the eye when you’re working with multiple apps on one screen.</p><p>It’s restored my faith that Apple has clearly realized what a mistake Tahoe was in its design, and whilst I’ll be upgrading my current MacBook Pro to Golden Gate once it’s out, it also feels like it’s laying the foundation for the <a href="https://www.tomsguide.com/computing/laptops/macbook-ultra-everything-we-know-so-far">MacBook Ultra</a>.</p><p>For anyone unaware, this rumored Mac seems to be the opposite of the <a href="https://www.tomsguide.com/computing/macbooks/apple-macbook-neo-review">MacBook Neo</a>. Instead of being an entry point, the MacBook Ultra seems aimed at those who want the ultimate portable Mac at a high price. Alleged features include an OLED touchscreen, a first for the Mac to accept touch input, as well as coming with M6 Pro or Ultra chips that give even better performance and battery life.</p><p>Apple silicon has been a huge leap for the Mac. It’s hard to think back to a time when an Intel MacBook Pro could barely manage 4 hours under heavy load, or struggle with games like BioShock Infinite that were then 3 years old since their PC release. Now, even in 2026, my M1 Pro MacBook Pro can still play games like <a href="https://www.tomsguide.com/reviews/resident-evil-4">Resident Evil 4 Remake</a> and others with ease, and I rarely hear the fan whirl. So thinking about what a 5-year leap could do for my Mac gaming, alongside everything else, has me excited.</p><p>These rumored features, combined with macOS Golden Gate, make me consider the Ultra as my next Mac, since it replaces two devices in one go.</p><h2 id="the-ultra-could-also-be-an-ipad-replacement">The Ultra could also be an iPad replacement</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3000px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="Kg4cbghayrcgsaf6yZstBB" name="iPadOS 27-5" alt="iPadOS 27" src="https://cdn.mos.cms.futurecdn.net/Kg4cbghayrcgsaf6yZstBB.jpg" mos="" align="middle" fullscreen="" width="3000" height="1687" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I’ve been a fan of the <a href="https://www.tomsguide.com/best-picks/best-ipad">iPad</a> since its 2010 debut, and whilst recent software updates, especially <a href="https://www.tomsguide.com/computing/ipads/apple-ipados-26-review">iPadOS 26</a>, have made Apple’s tablet far more productive, its locked ecosystem has always made me go back to the Mac.</p><p>But there are moments when a touch-screen can work well, such as editing videos for TikTok via LumaFusion, or reading comics from my childhood. It’s why I can see these two examples, and many others, working well on a touchscreen Mac, without macOS leaving the mouse behind.</p><p>Golden Gate clearly hints towards a touchscreen Mac—from being able to slide down to refresh in Safari and Mail, to every button designed as if they’re meant to be touched by a finger. Even <a href="https://www.tomsguide.com/phones/iphones/i-spent-a-week-with-siri-ai-here-are-my-honest-pros-and-cons">Siri AI</a> lets users send an email, record a voice note, take a selfie, and more with their voice or via the Siri app. The newest macOS update looks set to be ready for the MacBook Ultra.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-XYx7ZO"></div>                            </div>                            <script src="https://kwizly.com/embed/XYx7ZO.js" async></script><h2 id="outlook">Outlook</h2><p>When an ultra-high-end Mac seems like it will improve on what my M1 MacBook Pro offers, while replacing the use cases I’ve had for my iPad Pro for several years, it feels like the natural next step for me and how I work. Even for Mac gaming, with ways to play Windows games via Crossover or decompilations like Donkey Kong 64 or GoldenEye, the extra power thanks to the M6 architecture will be a huge step up from what I’ve been using since 2021.</p><p>So while many will be excited to own an iPhone Ultra or an iPhone 18 Pro model, I’m more excited to use the MacBook Ultra. From the much-improved macOS Golden Gate update to the OLED touchscreen, it feels like the MacBook Ultra could be one of the best Macs to use for at least another five years. If that happens, then I'll have to say goodbye to my M1 MacBook Pro.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/computing/macbooks/apple-macbook-ultra-may-arrive-running-on-some-of-the-same-chips-as-macbook-pro-heres-why">Apple MacBook Ultra may run on some of the same chips as MacBook Pro</a></li><li><a href="https://www.tomsguide.com/computing/apple-desktops/apple-just-announced-the-new-mac-studio-with-m5-ultra-and-it-will-be-a-local-ai-powerhouse">Apple just announced the new Mac Studio with M5 Ultra</a></li><li><a href="https://www.tomsguide.com/computing/laptops/best-laptops-of-ifa-2026-wild-colors-ultrathin-designs-and-rollable-displays">Best laptops of IFA 2026: Wild colors, ultrathin designs and rollable displays</a></li></ul><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=laptops&brands=Apple&min_discount_ratio=0.95&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 normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters {      display: flex;      gap: 12px;      justify-content: center;      flex-wrap: wrap;    }    .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);      display: -webkit-box;      -webkit-line-clamp: 2;      -webkit-box-orient: vertical;      overflow: hidden;    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    .tg-df-container .tg-df-card-cta.tg-df-cta-savings-squad {      background-color: #3c8d0d;    }    .tg-df-card:hover .tg-df-card-cta.tg-df-cta-savings-squad,    .tg-df-card-cta.tg-df-cta-savings-squad:hover {      background-color: #2b6509;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 0;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 0 16px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }            .tg-df-filters {        width: calc(100% + 32px);        margin: 0 -16px;        padding: 0 16px 4px 16px;        display: flex;        justify-content: flex-start;        gap: 8px;        flex-wrap: nowrap;        overflow-x: auto;        -webkit-overflow-scrolling: touch;        scrollbar-width: none;      }      .tg-df-filters::after {        content: "";        display: block;        flex: 0 0 8px;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }            .tg-df-sort-wrapper {        flex: 0 0 max(42%, 130px);        min-width: 0;      }      .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;        -webkit-line-clamp: 3;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        -webkit-line-clamp: 3;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 16px;      text-align: center;      width: 100%;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right {      background-color: rgba(255, 255, 255, 0.4);      border: none;      box-shadow: none;      backdrop-filter: blur(4px);      -webkit-backdrop-filter: blur(4px);    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right { right: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-right { right: 0; }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left:hover,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);      border: none;    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-carousel-roundels::after {      content: "";      flex: 0 0 32px;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;      transition: font-weight 0.2s;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-label {      font-weight: 700;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;      display: inline-flex;      align-items: center;      justify-content: center;      min-height: 36px;      box-sizing: border-box;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::after {      content: "";      flex: 0 0 32px;    }    .tg-df-grid-wrapper {      position: relative;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card {      flex: 0 0 auto;      width: 100px;      border-radius: 15px;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      border: 2px solid #1e293b;      background: white;      color: #1e293b;      display: flex;      flex-direction: column;      justify-content: center;      align-items: center;      font-weight: 600;      font-size: 14px;      cursor: pointer;      padding: 16px;      text-align: center;      transition: all 0.2s;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card:hover {      background: #1e293b;      color: white;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      -webkit-line-clamp: 2;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {      -webkit-line-clamp: 3;    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.45);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #5aaf0b; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #4a9109; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>          \x3C/div>          \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">      \x3Cdiv class="tg-df-top-bar">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>                \x3Cdiv class="tg-df-settings-wrapper">          \x3Cbutton type="button" class="tg-df-settings-btn" aria-label="Settings" id="tg-df-settings-toggle">            \x3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">                \x3Cpath d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.73 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.49-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>            \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-settings-dropdown-backdrop" id="tg-df-settings-backdrop">\x3C/div>          \x3Cdiv class="tg-df-settings-dropdown" id="tg-df-settings-panel">            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Search Region\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-region-select">                \x3Coption value="auto">🌍 Auto-detect\x3C/option>                \x3Coption value="US">🇺🇸 United States (US)\x3C/option>                \x3Coption value="GB">🇬🇧 United Kingdom (UK)\x3C/option>                \x3Coption value="CA">🇨🇦 Canada (CA)\x3C/option>                \x3Coption value="AU">🇦🇺 Australia (AU)\x3C/option>                \x3Coption value="DE">🇩🇪 Germany (DE)\x3C/option>                \x3Coption value="FR">🇫🇷 France (FR)\x3C/option>                \x3Coption value="IT">🇮🇹 Italy (IT)\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Retailer\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-retailer-select">                \x3Coption value="">All Retailers\x3C/option>                \x3Coption value="Amazon">Amazon\x3C/option>                \x3Coption value="Walmart">Walmart\x3C/option>                \x3Coption value="Best Buy">Best Buy\x3C/option>                \x3Coption value="Target">Target\x3C/option>                \x3Coption value="John Lewis">John Lewis\x3C/option>                \x3Coption value="Currys">Currys\x3C/option>                \x3Coption value="Argos">Argos\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Offer Type\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-offer-type-select">                \x3Coption value="">All Offers\x3C/option>                \x3Coption value="amazon_prime">Amazon Prime\x3C/option>                \x3Coption value="recommended_promo">Recommended Promo\x3C/option>                \x3Coption value="amazon_lightning">Amazon Lightning Deal\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Result Count\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-rows-select">                \x3Coption value="3">3 Items\x3C/option>                \x3Coption value="4">4 Items\x3C/option>                \x3Coption value="6">6 Items\x3C/option>                \x3Coption value="8">8 Items\x3C/option>                \x3Coption value="12" selected>12 Items\x3C/option>                \x3Coption value="24">24 Items\x3C/option>                \x3Coption value="48">48 Items\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Deal Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Only show products with active offers or previous prices (was_price)\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-deal-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Editor Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Enable multi-select to copy deals to CMS\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-editor-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">View Mode\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-view-mode-select">                \x3Coption value="auto">Auto Collection\x3C/option>                \x3Coption value="carousel">Carousel\x3C/option>                \x3Coption value="savings_squad">Savings Squad\x3C/option>                \x3Coption value="grid">Grid (Columns)\x3C/option>                \x3Coption value="row">Row (List)\x3C/option>              \x3C/select>            \x3C/div>          \x3C/div>        \x3C/div>      \x3C/div>      \x3Cdiv class="tg-df-filters">        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/>          \x3C/svg>          \x3Cselect class="tg-df-sort-select" aria-label="Sort Deals">            \x3Coption value="date_desc">Newest First\x3C/option>            \x3Coption value="best_match">Sort by: Match\x3C/option>            \x3Coption value="price_asc">Price Low to High\x3C/option>            \x3Coption value="price_desc">Price High to Low\x3C/option>            \x3Coption value="discount_desc">Biggest Discount\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>        \x3C/div>      \x3C/div>    \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();            if (['carousel', 'carousel-compact', 'auto', 'grid', 'row'].includes(this.getViewMode())) { this.loadCarouselSpreadsheet(); }        }        getViewMode() {          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          if (mode === 'carousel' || mode === 'auto' || mode === 'grid' || mode === 'row') {             if (mode === 'carousel') this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container') && mode === 'carousel') {               this.root.classList.add('is-carousel');             } else if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Everything';             if (this.discountFilter && !params.has('min_discount_ratio')) {               this.discountFilter.value = '5';             }          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (params.has('bg_color')) {            const bg = params.get('bg_color');            if (bg === 'white') {              this.root.style.setProperty('background-color', '#ffffff', 'important');            } else if (bg === 'transparent') {              this.root.style.setProperty('background-color', 'transparent', 'important');            } else if (bg === 'light_blue') {              this.root.style.setProperty('background-color', '#E7F0FF', 'important');            }          } else {             this.root.style.removeProperty('background-color');          }                    if (params.has('view_mode')) {            if (this.viewModeSelect) {              this.viewModeSelect.value = params.get('view_mode');            } else {              this.viewModeOverride = params.get('view_mode');            }          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'discount_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            this.searchInput.value = this.currentQuery;          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'discount_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const roundels = this.root.querySelectorAll('.tg-df-carousel-cat.original-hardcoded');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              if (this.getViewMode() === 'savings_squad' && this.autocompleteDropdown && this.airedaleTags && query.length > 0) {                 const matches = this.airedaleTags.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase()).slice(0, 5);                 if (matches.length > 0) {                    this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                    this.autocompleteDropdown.classList.add('active');                 } else {                    this.autocompleteDropdown.classList.remove('active');                 }              } else if (this.autocompleteDropdown) {                 this.autocompleteDropdown.classList.remove('active');              }              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  this.deals = [];                  this.render();                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                this.activeDealTag = null;                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });              this.activeDealTag = null;              this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.fetchDeals(query);              }            });          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = this.viewModeSelect.value === 'savings_squad' ? 'date_desc' : 'discount_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const finalHref = cardLink.href || cardLink.getAttribute('href') || '';                let actualRevenueId = cardLink.getAttribute('data-revenue-id');                const revMatch = finalHref.match(/(?:subId1|xcust|clickref|ascsubtag)=[^&]*?(\d{18,20})(?:&|$)/i);                if (revMatch && revMatch[1]) {                  actualRevenueId = revMatch[1];                }                const rewrittenLink = finalHref;                const revenueId = actualRevenueId;                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }                async loadCarouselSpreadsheet() {          try {              const parseCSVRow = (str) => {                  let result = [], cur = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (inQuotes) {                          if (char === '"') {                              if (str[i + 1] === '"') { cur += '"'; i++; }                              else { inQuotes = false; }                          } else { cur += char; }                      } else {                          if (char === '"') { inQuotes = true; }                          else if (char === ',') { result.push(cur); cur = ''; }                          else { cur += char; }                      }                  }                  result.push(cur); return result;              };              const parseCSV = (str) => {                  const rows = []; let curRow = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (char === '"') inQuotes = !inQuotes;                      if ((char === '\n' || char === '\r') && !inQuotes) {                          if (char === '\r' && str[i+1] === '\n') i++;                          if (curRow) rows.push(parseCSVRow(curRow));                          curRow = '';                      } else { curRow += char; }                  }                  if (curRow) rows.push(parseCSVRow(curRow));                  return rows;              };              const preloadedCSV = decodeURIComponent(escape(atob("LCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNQ0KUm91bmRlbCB0ZXh0LEFsbCxUVnMsRm9vdHdlYXIsQXBwYXJlbCxNYXR0cmVzZXMsQXBwbGlhbmNlcyxXZWFyYWJsZSB0ZWNoLEhlYWRwaG9uZXMsU21hcnQgSG9tZSxTcGVha2VycyxMYXB0b3BzLFRhYmxldHMsQ29tcHV0aW5nLFBob25lcyxHYW1pbmcsTGVnbw0KUm91bmRlbCBpbWFnZSxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL2FpLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL3R2cy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvN2IzYTIyNGIwNzk2M2M2MjdiNmI5MDliZDc4MzM4MzZlMDJmZjgxOS5qcGcud2VicCxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy84NGRhYzVkNDhlZDJkNDQ4NTU5ZWJhNjdhY2U4MzE0Y2M2N2NjZDk0LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vc2hvcC1hc3NldHMvY2Fyb3VzZWwvbWF0dHJlc3Nlcy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvNzY4ZTk3Y2ViMDcxODAxZmFlMjA5MTBkMDgyMGIxNmY3NDdhZjkzOS5qcGcud2VicCxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL3dlbGxuZXNzLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL2hlYWRwaG9uZXMuanBnLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzg5NTM1YmVlYmUyMGRiYmQ0YTM0NmQ2ZDZiZGZlOTFkOGE4ODRhMjEuanBnLndlYnAsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9zaG9wLWFzc2V0cy9jYXJvdXNlbC9hdWRpby5qcGcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9zaG9wLWFzc2V0cy9jYXJvdXNlbC9sYXB0b3BzLmpwZyxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy8yMzk3NTY0ZWQ3YTVmZjk0N2U5YjZiMzBlNTRmNDc0OTRiODQxZjg5LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vc2hvcC1hc3NldHMvY2Fyb3VzZWwvY29tcHV0aW5nLmpwZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL3Bob25lcy5wbmcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9zaG9wLWFzc2V0cy9jYXJvdXNlbC9nYW1pbmcucG5nLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzRmNmM2MjFjYWMwYmMxYTg1ZDU5M2UzNTk0YmE1YjM0OWVmZmQyOTIuanBnLndlYnANClNlYXJjaCBRdWVyeSxFdmVyeXRoaW5nLFRlbGV2aXNpb25zLCJTbmVha2VycywgcnVubmluZyBzaG9lcywgc2FuZGFscyIsQ2xvdGhpbmcsTWF0dHJlc3NlcyxIb21lIEFwcGxpYW5jZXMsV2VhcmFibGVzICYgRml0bmVzcyBUZWNoLEhlYWRwaG9uZXMsSG9tZSBUZWNoLFNwZWFrZXJzLExhcHRvcHMsVGFibGV0cyxDb21wdXRpbmcsUGhvbmVzLEdhbWluZyxDb25zdHJ1Y3Rpb24gVG95cw0KRGlzY291bnQgQW1vdW50LG1pbiA1JSxtaW4gMTAlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUNClByaWNlIFJhbmdlLCwsLCxtaW4gJDQwMCwsLCxtaW4gJDI1LCxtaW4gJDMwMCwsLG1pbiAkMTAwLCwNCkJyYW5kIFNlbGVjdGlvbiwsLCwsLCwsLCwsLCwsLCwNCkZpbHRlciBidXR0b25zLCwsLCwsLCwsLCwsLCwsLA0KMSxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMNCjIsQW1hem9uIGRlYWxzLFVuZGVyICQxMDAwLDUwJSBvZmYsQWRpZGFzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsNTAlIG9mZixBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscw0KMyxPdmVyICQ0MDAsVW5kZXIgJDUwMCxIb2thLE5pa2UsU2FhdHZhLE5pbmphLDQwJSBvZmYsSkxhYiwsSkJMLERlbGwsLEFzdXMsQXBwbGUsQ29uc29sZXMsU3RhciBXYXJzDQo0LFVuZGVyICQxMDAwLDUwJSBvZmYsU2tlY2hlcnMsVW5kZXIgQXJtb3VyLEhlbGl4LFNoYXJrLEdhcm1pbixBbmtlciBTb3VuZGNvcmUsUmluZyxTb25vcyxBcHBsZSxBcHBsZSxUUC1saW5rLFNhbXN1bmcsQWNjZXNzb3JpZXMsVW5kZXIgJDI1DQo1LFVuZGVyICQ1MDAsTEcsQXNpY3MsQ29sdW1iaWEsRHJlYW1DbG91ZCxLZXVyaWcsQXBwbGUsU29ueSxHb3ZlZSxUcmliaXQsTGVub3ZvLFNhbXN1bmcsRWVybyxHb29nbGUsR2FtZXMsVW5kZXIgJDUwDQo2LDUwJSBvZmYsU2Ftc3VuZyxOaWtlLFBhdGFnb25pYSxOZWN0YXIsRGUnTG9uZ2hpLEFtYXpmaXQsQXBwbGUsS2FzYSBzbWFydCxTb255LEFsaWVud2FyZSxUQ0wsTmV0Z2VhcixNb3Rvcm9sYSxOaW50ZW5kbyxCb3RhbmljYWxzDQo3LEFtYXpvbixIaXNlbnNlLE5ldyBCYWxhbmNlLEFyYyd0ZXJ5eCxUZW1wdXItcGVkaWMsRHlzb24sRml0Yml0LEJlYXRzLFBoaWxpcHMgSHVlLEFua2VyLEFjZXIsT25lUGx1cyxEZWxsLE9uZVBsdXMsU29ueSxEaXNuZXkNCjgsQXBwbGUsVENMLEFkaWRhcyxDYXJoYXJ0dCxCZWFyLEJpc3NlbGwsU2Ftc3VuZyxFYXJmdW4sQmxpbmssQmVhdHMsTVNJLE1pY3Jvc29mdCxBY2VyLE5vdGhpbmcsWGJveCxNYXJ2ZWwNCjksLFNvbnksU2F1Y29ueSxUaGUgTm9ydGggRmFjZSxTaWVuYSxOdXRyaWJ1bGxldCxPdXJhLFNhbXN1bmcsR29vZ2xlIE5lc3QgLE1hcnNoYWxsLFNhbXN1bmcsTGVub3ZvLExlbm92bywsLFBva2Vtb24NCjEwLCxSb2t1LEJpcmtlbnN0b2NrLENSWiBZb2dhLFdpbmtCZWRzLEJsYWNrIGFuZCBEZWNrZXIsUmluZ2Nvbm4sQ01GLEV1ZnksU2Ftc3VuZyxNaWNyb3NvZnQsUmVNYXJrYWJsZSxBbGllbndhcmUsLCwNCjExLCwsQnJvb2tzLFRoZSBHeW0gUGVvcGxlLEJyb29rbHluIGJlZGRpbmcsTmVzcHJlc3NvLCwxTW9yZSxBcmxvLCxSYXplciwsQ29yc2FpciwsLA0KMTIsLCxDcm9jcywsRWlnaHQgU2xlZXAsQ3Vpc2luYXJ0LCxKQkwsLCwsLEhQLCwsDQpOb3RlcywsLCwsLCwsLCwsLCwsLCwNCiwsIlByaW9yaXRpc2UgYmlnZ2VzdCAlLyQgZGlzY291bnQsIFR2cyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGV2ZW4gaWYgdGhleSBhcmUgc3RpbGwgZXhwZW5zaXZlIiwiTm8gcGF0dGVybiB0byBwcmljaW5nL2Rpc2NvdW50LCByZWFkZXJzIG1haW5seSBzaG9wIGJ5IGJyYW5kL3JlY29nbmlzYWJsZSBzaG9lcyIsIk5vIHBhdHRlcm4gdG8gcHJpY2luZy9kaXNjb3VudCwgcmVhZGVycyBtYWlubHkgc2hvcCBieSBicmFuZCIsIkEgbGFiZWwgd2lsbCBkZWZpbml0ZWx5IGhlbHAgaGVyZSBlLmcuIGJlc3QgZm9yIHNpZGUgc2xlZXBlciwgYmVzdCBtZW1vcnkgZm9hbSIsIkFwcGxpYW5jZXMgaXMgYSBiaWcgY2F0ZWdvcnksIGlzIGl0IHBvc3NpYmxlIHRvIHNwbGl0IGludG8ga2l0Y2hlbiBhcHBsaWFuY2VzLCBmbG9vcmNhcmUsIGFpciBoZWFsdGgvY29vbGluZz8gT3Igc2ltaWxhciIsIkZvY3VzIG9uIHZhbHVlIGZvciBtb25leSwgR2FybWlucyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiBwb3B1bGFyIGV2ZW4gdGhvdWdoIHRoZXkgYXJlIHN0aWxsICQ1MDAiLCwsLCxJbmNsdWRlIEtpbmRsZXMsSSB3b3VsZCBpbmNsdWRlIHdpZmkgcm91dGVycyBoZXJlIGluc3RlYWQgb2Ygc21hcnQgaG9tZSxDYW4gd2Ugc3VyZmFjZSBwaG9uZSBwcm92aWRlciBkZWFscz8gVC1tb2JpbGUgYW5kIHZlcml6b24gd291bGQgbWFrZSBhIGxvdCBtb3JlIG1vbmV5IHRoYW4gQW1hem9uLCwNCiwsaGF2aW5nIGEgJ2Jlc3QgZm9yJyBsYWJlbCB3b3VsZCBiZSBoZWxwZnVsIGUuZy4gYmVzdCBmb3IgYnJpZ2h0IHJvb20sQ2FuIHdlIHN0b3Aga2lkcyBzaG9lcyBmcm9tIHB1bGxpbmcgdGhyb3VnaD8sIldpbGwgdGhpcyBpbmNsdWRlIGFjY2Vzc29yaWVzIGUuZy4gY2FwcywgYmFncywgaWYgc28gbWFrZSBzdXJlIHRoZXNlIGFyZSBtaXhlZCB0aHJvdWdob3V0IGNsb3RoaW5nIGRlYWxzIixXaWxsIHRoaXMgaW5jbHVkZSB0b3BwZXJzIGFuZCBwaWxsb3dzPyBTZWVpbmcgbW9yZSBtb21lbnR1bSB3aXRoIHRoaXMgY2F0ZWdvcnkgcmVjZW50bHkgc28gYSBiZWRkaW5nIHRhYiBtaWdodCB3b3JrLCwiTmVlZCB0byBtYWtlIHN1cmUgYmFuZHMsIHNjcmVlbiBwcm90ZWN0b3JzIGV0Yy4gZG9uJ3QgcHVsbCBpbnRvIGhlcmUiLCwsLCwsLCwsDQosLCJQcmlvcml0aXNlIDY1JycgYW5kIDU1JyBpbmNoIFRWcywgdGhlbiBiaWdnZXIgc2NyZWVucyBiZWZvcmUgdGhlIHNtYWxsZXIgc2l6ZXMiLCwsUXVlZW4gaXMgdGhlIG1vc3QgcG9wdWxhciBzaXplIGluIHRoZSBVUyAtIHByaW9yaXRpc2UgZGVhbHMgZm9yIHRoaXMgc2l6ZSwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpDYXRlZ29yaWVzIHRvIGNvbnNpZGVyLCxQcm9kdWN0cyBpbmNsdWRlZCwsLCwsLCwsLCwsLCwsDQpVbmRlciAkNTA/LCxBaXIgdGFncywsLCwsLCwsLCwsLCwsDQosLFBvcnRhYmxlIGNoYXJnZXJzL3dpcmVsZXNzIGNoYXJnZXJzLCwsLCwsLCwsLCwsLCwNCiwsIldhdGVyIGJvdHRsZXMgKHN0YW5sZXlzLCBPd2FsYSwgSHlkcm8gZmxhc2ssIFlldGkpIiwsLCwsLCwsLCwsLCwsDQosLEhhbmQgaGVsZCBmYW5zLCwsLCwsLCwsLCwsLCwNCiwsLCwsLCwsLCwsLCwsLCwNCmhvbWUgb2ZmaWNlLCxvZmZpY2UgY2hhaXJzLCwsLCwsLCwsLCwsLCwNCiwsc3RhbmRpbmcgZGVza3MsLCwsLCwsLCwsLCwsLA0KLCxtb25pdG9ycywsLCwsLCwsLCwsLCwsDQosLEtleWJvYXJkcywsLCwsLCwsLCwsLCwsDQosLGRvY2tpbmcgc3RhdGlvbiwsLCwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpHYW1pbmcsLENvbnNvbGVzLCwsLCwsLCwsLCwsLCwNCiwsQWNjZXNzb3JpZXMsLCwsLCwsLCwsLCwsLA0KLCxHYW1lcywsLCwsLCwsLCwsLCwsDQosLENvdWxkIGluY2x1ZGUgTGVnbz8sLCwsLCwsLCwsLCwsLA==")));              const text = preloadedCSV;              const parsed = parseCSV(text);                            const rowsByName = {};              let filterStart = -1;              parsed.forEach((rc, i) => {                 if (rc && rc.length > 0 && rc[0]) rowsByName[rc[0]] = rc;                 if (rc && rc.length > 0 && rc[0] === 'Filter buttons') filterStart = i;              });                            const cols = [];              if(rowsByName['Roundel text']) {                const headerRow = rowsByName['Roundel text'];                for(let col = 1; col < headerRow.length; col++) {                   let label = headerRow[col];                   if (!label) continue;                                      let q = rowsByName['Search Query'] && rowsByName['Search Query'][col] ? rowsByName['Search Query'][col] : '';                   let img = rowsByName['Roundel image'] && rowsByName['Roundel image'][col] ? rowsByName['Roundel image'][col] : '';                   let ds = rowsByName['Discount Amount'] && rowsByName['Discount Amount'][col] ? rowsByName['Discount Amount'][col] : '';                   let pr = rowsByName['Price Range'] && rowsByName['Price Range'][col] ? rowsByName['Price Range'][col] : '';                   let rt = rowsByName['Retailer'] && rowsByName['Retailer'][col] ? rowsByName['Retailer'][col] : '';                   let ot = rowsByName['Offer Type'] && rowsByName['Offer Type'][col] ? rowsByName['Offer Type'][col] : '';                                      let filters = [];                   if(filterStart > 0) {                     for(let r = filterStart + 1; r < parsed.length; r++) {                         if(!parsed[r] || parsed[r][0] === 'Notes' || parsed[r][0] === 'Categories to consider') break;                         let f = parsed[r][col];                         if(f) filters.push(f);                     }                   }                   cols.push({ label, img, q, ds, pr, rt, ot, filters });                }              }              this.carouselData = cols;              if (this.carouselData && this.carouselData.length > 0) {                 const isMatched = this.carouselData.some(c => c.q === this.currentQuery || c.label === this.currentQuery);                 if (!isMatched) {                    const first = this.carouselData[0];                    this.currentQuery = first.q || first.label;                    if (this.priceFilter) this.priceFilter.value = 'all';                    if (this.customPriceMin) this.customPriceMin.value = '';                    if (this.customPriceMax) this.customPriceMax.value = '';                    let dPr = first.pr || 'all';                    if (typeof dPr === 'string' && dPr !== 'all') {                       let prLower = dPr.toLowerCase();                       if (prLower.includes('min') || prLower.includes('over')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else if (prLower.includes('max') || prLower.includes('under')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       }                    }                    let dAm = '0';                    if(first.ds && typeof first.ds === 'string') {                       let m = first.ds.match(/(\d+)/);                       if(m) dAm = m[1];                    }                    if (this.discountFilter) this.discountFilter.value = dAm;                    if (this.offerTypeSelect) this.offerTypeSelect.value = first.ot || '';                    if (this.retailerSelect) this.retailerSelect.value = first.rt || '';                    this.selectedBrands = [];                    if (this.brandDropdown) {                        const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                        chks.forEach(chk => chk.checked = false);                    }                    if (this.searchInput) this.searchInput.value = this.currentQuery;                 }              }              this.renderCarouselUI();          } catch(e){ console.warn(e); }        }                renderCarouselUI() {           const roundelWrapper = this.root.querySelector('.tg-df-carousel-roundels');           if(!roundelWrapper || !this.carouselData) return;                      let html = '';           this.carouselData.forEach(r => {              const q = r.q || r.label;              const isActive = (this.currentQuery === q || this.currentQuery === r.label) ? 'active' : '';              const imgHtml = r.img ? `\x3Cimg src="${r.img}" alt="${r.label}" />` : `\x3Csvg width="32" height="32" fill="#1F69FF" viewBox="0 0 24 24">\x3Cpath d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>\x3C/svg>`;              html += `                \x3Cdiv class="tg-df-roundel tg-df-carousel-cat ${isActive}" data-label="${this.escapeHTML(r.label)}">                  \x3Cdiv class="tg-df-roundel-img-box">${imgHtml}\x3C/div>                  \x3Cspan class="tg-df-roundel-label">${this.escapeHTML(r.label)}\x3C/span>                \x3C/div>              `;           });           roundelWrapper.innerHTML = html;                      // Rebind clicks           const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');           roundels.forEach(rNode => {             rNode.addEventListener('click', () => {                const r = this.carouselData.find(c => c.label === rNode.getAttribute('data-label'));                 if(!r) return;                                  if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: r.label,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = r.q || r.label;                const labelTitle = this.root.querySelector('#tg-df-carousel-title-label');                if (labelTitle) labelTitle.textContent = 'Best ' + this.currentQuery;                if (this.priceFilter) this.priceFilter.value = 'all';                if (this.customPriceMin) this.customPriceMin.value = '';                if (this.customPriceMax) this.customPriceMax.value = '';                let dPr = r.pr || 'all';                if (typeof dPr === 'string' && dPr !== 'all') {                   let prLower = dPr.toLowerCase();                   if (prLower.includes('min') || prLower.includes('over')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMin) this.customPriceMin.value = m[1];                   } else if (prLower.includes('max') || prLower.includes('under')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMax) this.customPriceMax.value = m[1];                   }                }                                let discountAmount = '0';                if(r.ds && typeof r.ds === 'string') {                   let m = r.ds.match(/(\d+)/);                   if(m) discountAmount = m[1];                }                if (this.discountFilter) this.discountFilter.value = discountAmount;                if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                                // Clear brands                    this.selectedBrands = [];                    if (this.brandDropdown) {                    const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                    chks.forEach(chk => chk.checked = false);                }                                if (this.searchInput) this.searchInput.value = this.currentQuery;                                roundels.forEach(ro => ro.classList.remove('active'));                if (rNode) rNode.classList.add('active');                                this.renderCarouselFilters(r);                this.fetchDeals(this.currentQuery);             });           });                      // Auto-highlight active           const activeR = this.carouselData.find(c => c.q === this.currentQuery || c.label === this.currentQuery);           if(activeR) this.renderCarouselFilters(activeR);        }                renderCarouselFilters(r) {           const filtersWrap = this.root.querySelector('.tg-df-carousel-filters-wrap');           if(!filtersWrap) return;                      let html = `\x3Cbutton class="tg-df-carousel-filter-btn" data-type="all">All\x3C/button>`;                      r.filters.forEach(f => {              let fL = f.toLowerCase();              let icon = '';              let logic = `data-type="custom" data-v="${this.escapeHTML(f)}"`;              if (fL === 'amazon deals' || fL === 'prime deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>`;              } else if (fL === 'lightning deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>`;              } else {                 if (fL.includes('lightning')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap">\x3Cpolygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2">\x3C/polygon>\x3C/svg>`;                 } else if (fL.includes('% off')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>`;                 } else if (fL.includes('under') || fL.includes('min ')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>`;                 }                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>${icon} ${this.escapeHTML(f)}\x3C/button>`;              }           });                      filtersWrap.innerHTML = html;                      const btns = filtersWrap.querySelectorAll('button');           btns.forEach(b => {             b.addEventListener('click', () => {                const type = b.getAttribute('data-type');                if (type === 'custom') {                   const v = b.getAttribute('data-v');                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-custom-${(v||'').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, name: 'Custom Filter', label: v });                }                if (type === 'all') {                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: 'filter-clear-all', name: 'Clear all', label: 'Clear all filters' });                   // reset everything                   btns.forEach(btn => btn.classList.remove('active'));                   b.classList.add('active');                                      // Reset prices                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   if (this.brandDropdown) {                     const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                     chks.forEach(chk => chk.checked = false);                   }                } else {                   const v = b.getAttribute('data-v');                   const fL = v.toLowerCase();                                      let mapRet = ['amazon', 'walmart', 'best buy', 'target', 'john lewis', 'currys', 'argos'];                   const getCategory = (s) => {                      if (s === 'lightning deals' || s === 'amazon deals' || s === 'prime deals') return 'offer';                      if (s.includes('% off')) return 'discount';                      if (s.includes('under') || s.includes('over') || s.includes('min') || s.includes('max')) return 'price';                      if (mapRet.includes(s)) return 'retailer';                      return 'brand';                   };                   const cat = getCategory(fL);                   const wasActive = b.classList.contains('active');                   if (cat !== 'brand') {                      btns.forEach(btn => {                          if (btn === b) return;                          if (btn.getAttribute('data-type') === 'all') return;                          const bV = btn.getAttribute('data-v');                          if (!bV) return;                          if (getCategory(bV.toLowerCase()) === cat) btn.classList.remove('active');                      });                   }                   if (wasActive) b.classList.remove('active');                   else b.classList.add('active');                   let anyActive = Array.from(btns).some(btn => btn !== btns[0] && btn.classList.contains('active'));                   if (!anyActive) {                       btns[0].click();                       return;                   } else {                       btns[0].classList.remove('active');                   }                                      if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   btns.forEach(btn => {                       if (!btn.classList.contains('active') || btn.getAttribute('data-type') === 'all') return;                       const vv = btn.getAttribute('data-v');                       const vl = vv.toLowerCase();                                              if (vl === 'lightning deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_lightning';                       } else if (vl === 'amazon deals' || vl === 'prime deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_prime';                       } else if (vl.includes('% off')) {                          let m = vl.match(/(\d+)%/);                          if (m && this.discountFilter) this.discountFilter.value = m[1];                       } else if (vl.includes('under') || vl.includes('max')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       } else if (vl.includes('min') || vl.includes('over')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else {                          let foundR = mapRet.find(x => x === vl);                          if (foundR) {                             let realR = ['Amazon', 'Walmart', 'Best Buy', 'Target', 'John Lewis', 'Currys', 'Argos'].find(x => x.toLowerCase() === vl);                             if (this.retailerSelect) this.retailerSelect.value = realR;                          } else {                             this.selectedBrands.push(vv);                          }                       }                   });                                      if (this.brandDropdown) {                       const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                       chks.forEach(c => c.checked = this.selectedBrands.includes(c.value));                   }                                      if (r.pr && typeof r.pr === 'string') {                       let prL = r.pr.toLowerCase();                       if (prL.includes('under $')) {                           let m = prL.match(/under \$(\d+)/i);                           if (m && this.customPriceMax && !this.customPriceMax.value) this.customPriceMax.value = m[1];                       }                   }                }                                this.fetchDeals(this.currentQuery);             });           });                      // default to highlighting first           btns[0].classList.add('active');        }async fetchDeals(query, append = false) {          if (!append) {             this.showLoading();             this.deals = [];             this.displayLimit = this.getRowsLimit();          } else {             this.displayLimit += this.getRowsLimit();          }                    try {            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad(append);            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query, append);               } else {                 await this.fetchHawkDeals(query, append);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query, append);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const url = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let dynamicBrandsCounts = {};                    targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                   dynamicBrandsCounts[data.brand] = (dynamicBrandsCounts[data.brand] || 0) + 1;                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || ''                });             });          });                    const airedaleBrandsList = Object.keys(dynamicBrandsCounts).map(b => ({              formatted_value: b,              count: dynamicBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.getFilteredDeals().slice(0, this.displayLimit), this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query, append = false) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (append && this.deals.length > 0) {            url.searchParams.append('offset', this.deals.length.toString());          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.getFilteredDeals().slice(0, this.displayLimit), this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.getFilteredDeals().slice(0, this.displayLimit), this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: this.decodeHTML(item.name || item.title || item.model_name || item.product_name || 'Unknown Product'),            brand: this.decodeHTML(item.brand || ''),            productName: this.decodeHTML(item.model_name || item.product_name || item.name || ''),            merchant: this.decodeHTML(item.merchant_name || item.merchant || item.retailer || 'Retailer'),            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : (this.getViewMode() === 'savings_squad' ? 'date_desc' : 'discount_desc');          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin-top:8px;">${_div}                ${_div}              ${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const finalHref = btn.href || btn.getAttribute('href') || '';                let actualRevenueId = btn.getAttribute('data-revenue-id');                const revMatch = finalHref.match(/(?:subId1|xcust|clickref|ascsubtag)=[^&]*?(\d{18,20})(?:&|$)/i);                if (revMatch && revMatch[1]) {                  actualRevenueId = revMatch[1];                }                const rewrittenLink = finalHref;                const revenueId = actualRevenueId;                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)} (${this.airedaleTagCounts[tag] || 0})${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = isSavingsSquadMode ? 'View Deal' : 'Check Price';              if (isSavingsSquadMode) {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                  ${_div}                `;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = `                \x3Cdiv class="tg-df-card-merchant-wrapper">                  \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                ${_div}                \x3Cdiv class="tg-df-card-price-group">                  ${isSavingsSquadMode ? '' : `                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                  `}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description">\x3Cp>${this.escapeHTML(deal.description)}${_p}${_div}` : ''}                      ${_div}                    ${_div}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>${deal.isCheckPrice ? 'Check Price' : 'View Deal'}${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cp style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 12px; line-height: 1.4;">${this.escapeHTML(deal.description)}${_p}` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${priceGroupHtml}                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta ${isSavingsSquadMode ? 'tg-df-cta-savings-squad' : ''}" style="text-decoration: none;">${ctaText}${_a}                  ${_div}                ${_div}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit || ((this.getViewMode() === 'carousel' || this.getViewMode() === 'auto') && displayDeals.length > 0 && displayDeals.length % ((this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12) === 0)) {            if (this.getViewMode() === 'carousel') {               dealsHtml += `                 \x3Cbutton type="button" class="tg-df-load-more-card tg-df-load-more">                   \x3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-bottom: 8px;">\x3Cpath d="M5 12h14">\x3C/path>\x3Cpath d="m12 5 7 7-7 7">\x3C/path>\x3C/svg>                   Load More                 ${_button}               `;            } else {               dealsHtml += `                 \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                   \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; align-items: center;">Load More${_button}                 ${_div}               `;            }          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let rightChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             let leftChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-left');             if (this.getViewMode() === 'carousel') {                 // The observer set up in setupScrollListeners handles visibility.                 if (rightChevron) rightChevron.style.display = 'flex';                 if (leftChevron) leftChevron.style.display = 'none'; // reset correctly             } else {                 if (rightChevron) rightChevron.style.display = 'none';                 if (leftChevron) leftChevron.style.display = 'none';             }          }                    const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', async () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              if (displayDeals.length <= this.displayLimit) {                 loadMoreBtn.innerHTML = `                  <svg class="tg-df-spinner" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 8px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>                  Loading...                 `;                 loadMoreBtn.disabled = true;                 await this.fetchDeals(this.currentQuery, true);              } else {                 this.displayLimit += this.getRowsLimit();                 this.render();              }            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            setTimeout(() => {               if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');               document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));            }, 50);          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I'm thrilled the iPhone Ultra is reportedly getting MagSafe, but there's a major problem ]]></title>
                                                                                                <dc:content><![CDATA[ <p>When early dummy units of the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Ultra</a> first surfaced, I immediately fixated on the <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-dummy-unit-leaks-and-im-not-sure-how-i-feel-about-this-design-heres-why">lack of a cutout for MagSafe</a> on the back of the phone. Honestly, it felt like a glaring omission — though I soon rationalized the decision after considering the intricate hinge mechanism and razor-thin profile Apple was chasing.</p><p>Thankfully, the most recent leaks suggest that <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-leak-may-have-revealed-final-design-and-magsafe-confirmation-what-we-know">MagSafe will indeed make the cut</a> for the iPhone Ultra after all. Given that I constantly test <a href="https://www.tomsguide.com/phones/i-always-carry-this-3-in-1-magsafe-charger-in-my-backpack-and-its-55-percent-off-right-now">3-in-1 MagSafe chargers</a> and <a href="https://www.tomsguide.com/phones/the-supcase-magflip-stand-is-the-swiss-army-knife-of-magsafe-wallets-heres-why">MagSafe-compatible wallets</a>, the news brings a huge sigh of relief. However, that excitement comes with the reality check that the phone’s unconventional footprint could make fitting my favorite accessories problematic.</p><p>With limited surface area flanking the camera module on the back half of the device, bulkier gear like wallets and oversized battery packs might overhang the edges — forcing me to completely rethink what I carry.</p><h2 id="positioning-matters">Positioning matters</h2><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="hh33LkoPUzesXQf2A99DT9" name="Nomad Leather Mag Wallet" alt="Nomad Leather Mag Wallet on iPhone 17 Pro case." src="https://cdn.mos.cms.futurecdn.net/hh33LkoPUzesXQf2A99DT9.jpg" mos="" align="middle" fullscreen="" width="4327" height="2434" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>For the past month, I’ve been rocking the <a href="https://www.tomsguide.com/phones/i-tried-this-new-magsafe-wallet-that-looks-better-the-longer-i-use-it-heres-what-it-is">Nomad Leather Mag Wallet</a> for its minimalist look. It fits cleanly on the back of my <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a>, but it would likely clash on the iPhone Ultra.</p><p>That’s because across recent iPhone generations, the internal magnetic ring has always been centered relative to the chassis. On a standard rectangular phone, like my iPhone 17 Pro or <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-pro-xl-review">Pixel 11 Pro XL</a>, this gives MagSafe wallets plenty of room to fit snugly and seamlessly.</p><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="Tkap4dToZHHY8rqqJCVLJH" name="Aulumu G03 Multi-Tool MagSafe Wallet" alt="Aulumu G03 Multi-Tool MagSafe Wallet." src="https://cdn.mos.cms.futurecdn.net/Tkap4dToZHHY8rqqJCVLJH.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>Now, if Apple keeps that familiar centered positioning on the Ultra, it’s going to cause issues. With a potentially wider and shorter profile, the distance from that center point to the bottom edge narrows. That means existing MagSafe wallets are almost guaranteed to overhang by a fair amount, inherently compromising both fit and security.</p><p>MagSafe relies heavily on flush friction and flat alignment to prevent accidental detachment; if an existing wallet protrudes past the bottom rim, that exposed lip acts as a lever arm every time you slide the phone into a pocket.</p><p>To keep current MagSafe accessories from dangling, Apple would need to shift the internal magnetic ring noticeably higher toward the camera bar. By doing this, Apple would reclaim that critical vertical clearance, ensuring existing accessories sit flush against the glass with as little overhang as possible. This doesn't just affect MagSafe wallets, but also other gear like MagSafe charging stands.</p><h2 id="why-magsafe-is-a-must-on-the-iphone-ultra">Why MagSafe is a MUST on the iPhone Ultra</h2><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="nFQ5LxSy5qktGbHNdYnqFo" name="Pixelsnap accessories" alt="Pixelsnap accessories on Pixel 10." src="https://cdn.mos.cms.futurecdn.net/nFQ5LxSy5qktGbHNdYnqFo.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>Leaving MagSafe off the table simply isn't an option for Apple. The company learned that lesson the hard way after <a href="https://www.tomsguide.com/phones/iphones/iphone-16e-is-missing-this-one-crucial-feature-and-it-could-be-a-deal-breaker-for-me">stripping built-in magnets</a> from the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-16e-review">iPhone 16e</a> to cut costs — a glaring omission that sparked immediate pushback from my colleagues and me before Apple swiftly added support on the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17e-review">iPhone 17e</a>.</p><p>More importantly, the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air</a> already proved that Apple's hardware engineers can fit a full magnetic array into a razor-thin chassis without blowing out the internal volume or compromising heat dissipation. If it works on an impossibly slim frame, the iPhone Ultra has no excuse to leave it behind — which is why I’d be happy to see Apple shift its placement higher up the chassis.</p><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="5ricqEKiHkMSNMbKw4uvTJ" name="Satechi OntheGo 7-in-1 Multiport Adapter" alt="Satechi OntheGo 7-in-1 Multiport Adapter connected to iPhone." src="https://cdn.mos.cms.futurecdn.net/5ricqEKiHkMSNMbKw4uvTJ.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>The competitive pressure is equally impossible to ignore, especially with Google pulling off built-in Qi2 magnetic arrays on the <a href="https://www.tomsguide.com/phones/google-pixel-phones/pixel-10-pro-fold-review">Pixel 10 Pro Fold</a> and 11 Pro Fold. Book-style foldables are notoriously starved for internal space, yet Google managed to bake full magnetic ring support directly into its folding chassis while trimming down thickness.</p><p>I’m sure Apple doesn’t want that exclusivity reserved for its chief rival, especially when the entire category of magnetic phone accessories was popularized by the iPhone in the first place. Surrendering that convenience on its most experimental form factor while Google nails it on a foldable would be a tough look.</p><p>Ultimately, when you're paying top-tier money for a premium gadget like this, core functionality can’t be treated as an optional luxury. MagSafe isn't just a quirky wireless charging gimmick anymore because it's evolved into a massive ecosystem of everyday wallets, battery packs, car mounts, and desktop stands that iPhone users have invested in for years.</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/live/apple-surprise-and-shine-live-iphone-ultra-iphone-18-pro-max-apple-watch-series-12-and-all-the-latest-news">Apple 'Surprise and Shine' event live blog — iPhone Ultra, iPhone 18 Pro, Apple Watch 12 and all the last-minute leaks</a></li><li><a href="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">I’ve written about Apple Watch for a decade: Here’s the rumored upgrade to the Apple Watch 12 I’m most excited about</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-phones-inspiration-ifa-2026">iPhone 18 Pro, iPhone Ultra and beyond — here are the latest mobile features I saw at IFA 2026 that Apple needs to steal</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/im-thrilled-the-iphone-ultra-is-reportedly-getting-magsafe-but-theres-a-major-problem</link>
                                                                            <description>
                            <![CDATA[ The latest reports hint that Apple will indeed have MagSafe support on the iPhone Ultra, but it does present a major challenge in how some will fit on the device. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">eg2Awv6er3ADwm7pYdwhbf</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/3DgcQTY6GxnJpRLpkfJ9rW-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 10:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/3DgcQTY6GxnJpRLpkfJ9rW-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide / John Velasco]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Aulumu G09 Infinite 360° MagSafe Stand.]]></media:description>                                                            <media:text><![CDATA[Aulumu G09 Infinite 360° MagSafe Stand.]]></media:text>
                                <media:title type="plain"><![CDATA[Aulumu G09 Infinite 360° MagSafe Stand.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/3DgcQTY6GxnJpRLpkfJ9rW-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When early dummy units of the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Ultra</a> first surfaced, I immediately fixated on the <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-dummy-unit-leaks-and-im-not-sure-how-i-feel-about-this-design-heres-why">lack of a cutout for MagSafe</a> on the back of the phone. Honestly, it felt like a glaring omission — though I soon rationalized the decision after considering the intricate hinge mechanism and razor-thin profile Apple was chasing.</p><p>Thankfully, the most recent leaks suggest that <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-leak-may-have-revealed-final-design-and-magsafe-confirmation-what-we-know">MagSafe will indeed make the cut</a> for the iPhone Ultra after all. Given that I constantly test <a href="https://www.tomsguide.com/phones/i-always-carry-this-3-in-1-magsafe-charger-in-my-backpack-and-its-55-percent-off-right-now">3-in-1 MagSafe chargers</a> and <a href="https://www.tomsguide.com/phones/the-supcase-magflip-stand-is-the-swiss-army-knife-of-magsafe-wallets-heres-why">MagSafe-compatible wallets</a>, the news brings a huge sigh of relief. However, that excitement comes with the reality check that the phone’s unconventional footprint could make fitting my favorite accessories problematic.</p><p>With limited surface area flanking the camera module on the back half of the device, bulkier gear like wallets and oversized battery packs might overhang the edges — forcing me to completely rethink what I carry.</p><h2 id="positioning-matters">Positioning matters</h2><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="hh33LkoPUzesXQf2A99DT9" name="Nomad Leather Mag Wallet" alt="Nomad Leather Mag Wallet on iPhone 17 Pro case." src="https://cdn.mos.cms.futurecdn.net/hh33LkoPUzesXQf2A99DT9.jpg" mos="" align="middle" fullscreen="" width="4327" height="2434" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>For the past month, I’ve been rocking the <a href="https://www.tomsguide.com/phones/i-tried-this-new-magsafe-wallet-that-looks-better-the-longer-i-use-it-heres-what-it-is">Nomad Leather Mag Wallet</a> for its minimalist look. It fits cleanly on the back of my <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a>, but it would likely clash on the iPhone Ultra.</p><p>That’s because across recent iPhone generations, the internal magnetic ring has always been centered relative to the chassis. On a standard rectangular phone, like my iPhone 17 Pro or <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-pro-xl-review">Pixel 11 Pro XL</a>, this gives MagSafe wallets plenty of room to fit snugly and seamlessly.</p><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="Tkap4dToZHHY8rqqJCVLJH" name="Aulumu G03 Multi-Tool MagSafe Wallet" alt="Aulumu G03 Multi-Tool MagSafe Wallet." src="https://cdn.mos.cms.futurecdn.net/Tkap4dToZHHY8rqqJCVLJH.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>Now, if Apple keeps that familiar centered positioning on the Ultra, it’s going to cause issues. With a potentially wider and shorter profile, the distance from that center point to the bottom edge narrows. That means existing MagSafe wallets are almost guaranteed to overhang by a fair amount, inherently compromising both fit and security.</p><p>MagSafe relies heavily on flush friction and flat alignment to prevent accidental detachment; if an existing wallet protrudes past the bottom rim, that exposed lip acts as a lever arm every time you slide the phone into a pocket.</p><p>To keep current MagSafe accessories from dangling, Apple would need to shift the internal magnetic ring noticeably higher toward the camera bar. By doing this, Apple would reclaim that critical vertical clearance, ensuring existing accessories sit flush against the glass with as little overhang as possible. This doesn't just affect MagSafe wallets, but also other gear like MagSafe charging stands.</p><h2 id="why-magsafe-is-a-must-on-the-iphone-ultra">Why MagSafe is a MUST on the iPhone Ultra</h2><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="nFQ5LxSy5qktGbHNdYnqFo" name="Pixelsnap accessories" alt="Pixelsnap accessories on Pixel 10." src="https://cdn.mos.cms.futurecdn.net/nFQ5LxSy5qktGbHNdYnqFo.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>Leaving MagSafe off the table simply isn't an option for Apple. The company learned that lesson the hard way after <a href="https://www.tomsguide.com/phones/iphones/iphone-16e-is-missing-this-one-crucial-feature-and-it-could-be-a-deal-breaker-for-me">stripping built-in magnets</a> from the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-16e-review">iPhone 16e</a> to cut costs — a glaring omission that sparked immediate pushback from my colleagues and me before Apple swiftly added support on the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17e-review">iPhone 17e</a>.</p><p>More importantly, the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air</a> already proved that Apple's hardware engineers can fit a full magnetic array into a razor-thin chassis without blowing out the internal volume or compromising heat dissipation. If it works on an impossibly slim frame, the iPhone Ultra has no excuse to leave it behind — which is why I’d be happy to see Apple shift its placement higher up the chassis.</p><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="5ricqEKiHkMSNMbKw4uvTJ" name="Satechi OntheGo 7-in-1 Multiport Adapter" alt="Satechi OntheGo 7-in-1 Multiport Adapter connected to iPhone." src="https://cdn.mos.cms.futurecdn.net/5ricqEKiHkMSNMbKw4uvTJ.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>The competitive pressure is equally impossible to ignore, especially with Google pulling off built-in Qi2 magnetic arrays on the <a href="https://www.tomsguide.com/phones/google-pixel-phones/pixel-10-pro-fold-review">Pixel 10 Pro Fold</a> and 11 Pro Fold. Book-style foldables are notoriously starved for internal space, yet Google managed to bake full magnetic ring support directly into its folding chassis while trimming down thickness.</p><p>I’m sure Apple doesn’t want that exclusivity reserved for its chief rival, especially when the entire category of magnetic phone accessories was popularized by the iPhone in the first place. Surrendering that convenience on its most experimental form factor while Google nails it on a foldable would be a tough look.</p><p>Ultimately, when you're paying top-tier money for a premium gadget like this, core functionality can’t be treated as an optional luxury. MagSafe isn't just a quirky wireless charging gimmick anymore because it's evolved into a massive ecosystem of everyday wallets, battery packs, car mounts, and desktop stands that iPhone users have invested in for years.</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/live/apple-surprise-and-shine-live-iphone-ultra-iphone-18-pro-max-apple-watch-series-12-and-all-the-latest-news">Apple 'Surprise and Shine' event live blog — iPhone Ultra, iPhone 18 Pro, Apple Watch 12 and all the last-minute leaks</a></li><li><a href="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">I’ve written about Apple Watch for a decade: Here’s the rumored upgrade to the Apple Watch 12 I’m most excited about</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-phones-inspiration-ifa-2026">iPhone 18 Pro, iPhone Ultra and beyond — here are the latest mobile features I saw at IFA 2026 that Apple needs to steal</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ My phone refused to charge past 80% until I changed this one buried setting ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I woke up yesterday morning, grabbed my iPhone off charge, and immediately felt a wave of annoyance. I had a full day ahead, but my phone screen was sitting at a frustratingly specific 80% charge.</p><p>At first, I assumed my charging cable was loose, or on its last legs. But after purchasing a replacement and experiencing the same issue, I realized it wasn't a hardware failure — my phone was doing this on purpose.</p><p>It turns out iOS includes a battery setting designed to protect your device’s long-term health. While preventing chemical wear on lithium-ion batteries is great in theory, it’s a nightmare when you actually need full charge to get through the day. </p><p>Fortunately, if your iPhone is holding back on battery life, there is a quick fix to get back to 100%. </p><section class="howto-block">                    <h3>1. Open your Settings menu</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/f3wYfR4cPJ67tKLZZQ8HKc.jpg"                                        alt="Battery highlighted in iPhone settings"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/f3wYfR4cPJ67tKLZZQ8HKc.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Tom's Guide )</div></figure>                    <p><p>Open the <strong>Settings</strong> app on your iPhone, scroll down the main list, and <strong>tap Battery</strong>.</p></p>                </section><section class="howto-block">                    <h3>2. Access your charging options</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/cq8FvQSnR3V6WH74XzFfXi.jpg"                                        alt="Charging highlighted in iPhone settings "                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/cq8FvQSnR3V6WH74XzFfXi.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Tom's Guide)</div></figure>                    <p><p>Tap on <strong>Charging</strong> (or <strong>Battery Health & Charging</strong> if you are running an older version of iOS).</p></p>                </section><section class="howto-block">                    <h3>3. Adjust your charge limit back to 100%</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/sZFWTpnP3WYX7genUhfAn.jpg"                                        alt="Optimized battery charging disabled iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/sZFWTpnP3WYX7genUhfAn.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Tom's Guide )</div></figure>                    <p><p>If you are on an iPhone 15 or newer<strong>, drag the Charge Limit slider all the way up to 100%</strong>. </p><p>On older devices, tap <strong>Charging Optimization</strong> <strong>and switch it to None or turn off</strong> <strong>Optimized Battery Charging</strong>.</p><p>Since disabling the cap, my iPhone reaches a full 100% charge every single night. </p><p>If you worry about long-term battery degradation, you can always slide the cap back down before going to bed if you need to. </p></p>                </section><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ey40EX"></div>                            </div>                            <script src="https://kwizly.com/embed/ey40EX.js" async></script><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide </span></h3><ul><li><a href="https://www.tomsguide.com/phones/iphones/creating-calendar-events-in-ios-27-just-got-ridiculously-easy-and-im-never-going-back">Creating calendar events in iOS 27 just got ridiculously easy, and I’m never going back</a></li><li><a href="https://www.tomsguide.com/phones/iphones/ios-27-finally-gives-you-total-control-over-your-iphone-lock-screen-and-heres-what-to-change-first">iOS 27 finally gives you total control over your iPhone lock screen — here's what to change first</a></li><li><a href="https://www.tomsguide.com/phones/iphones/ios-27-quietly-fixes-the-most-annoying-iphone-workaround-we-all-use">iOS 27 finally fixes the most annoying iPhone workaround we all use</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/my-phone-refused-to-charge-past-80-percent-until-i-changed-this-one-buried-setting</link>
                                                                            <description>
                            <![CDATA[ Learn why your iPhone keeps stopping at an 80% charge and how to turn off the hidden iOS setting holding back your battery life. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">CDZzLc3Y4VNfZP9x5aKo3c</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/9pcTmny5rBahQV3Wvb5aM5-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 08:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ kaycee.hill@futurenet.com (Kaycee Hill) ]]></author>                    <dc:creator><![CDATA[ Kaycee Hill ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/xHn6RmpEqg87cvtLwrBu9G.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/9pcTmny5rBahQV3Wvb5aM5-1280-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone with USB-C charging cable ]]></media:description>                                                            <media:text><![CDATA[iPhone with USB-C charging cable ]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone with USB-C charging cable ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/9pcTmny5rBahQV3Wvb5aM5-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I woke up yesterday morning, grabbed my iPhone off charge, and immediately felt a wave of annoyance. I had a full day ahead, but my phone screen was sitting at a frustratingly specific 80% charge.</p><p>At first, I assumed my charging cable was loose, or on its last legs. But after purchasing a replacement and experiencing the same issue, I realized it wasn't a hardware failure — my phone was doing this on purpose.</p><p>It turns out iOS includes a battery setting designed to protect your device’s long-term health. While preventing chemical wear on lithium-ion batteries is great in theory, it’s a nightmare when you actually need full charge to get through the day. </p><p>Fortunately, if your iPhone is holding back on battery life, there is a quick fix to get back to 100%. </p><section class="howto-block">                    <h3>1. Open your Settings menu</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/f3wYfR4cPJ67tKLZZQ8HKc.jpg"                                        alt="Battery highlighted in iPhone settings"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/f3wYfR4cPJ67tKLZZQ8HKc.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Tom's Guide )</div></figure>                    <p><p>Open the <strong>Settings</strong> app on your iPhone, scroll down the main list, and <strong>tap Battery</strong>.</p></p>                </section><section class="howto-block">                    <h3>2. Access your charging options</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/cq8FvQSnR3V6WH74XzFfXi.jpg"                                        alt="Charging highlighted in iPhone settings "                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/cq8FvQSnR3V6WH74XzFfXi.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Tom's Guide)</div></figure>                    <p><p>Tap on <strong>Charging</strong> (or <strong>Battery Health & Charging</strong> if you are running an older version of iOS).</p></p>                </section><section class="howto-block">                    <h3>3. Adjust your charge limit back to 100%</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/sZFWTpnP3WYX7genUhfAn.jpg"                                        alt="Optimized battery charging disabled iPhone"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/sZFWTpnP3WYX7genUhfAn.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Tom's Guide )</div></figure>                    <p><p>If you are on an iPhone 15 or newer<strong>, drag the Charge Limit slider all the way up to 100%</strong>. </p><p>On older devices, tap <strong>Charging Optimization</strong> <strong>and switch it to None or turn off</strong> <strong>Optimized Battery Charging</strong>.</p><p>Since disabling the cap, my iPhone reaches a full 100% charge every single night. </p><p>If you worry about long-term battery degradation, you can always slide the cap back down before going to bed if you need to. </p></p>                </section><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ey40EX"></div>                            </div>                            <script src="https://kwizly.com/embed/ey40EX.js" async></script><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide </span></h3><ul><li><a href="https://www.tomsguide.com/phones/iphones/creating-calendar-events-in-ios-27-just-got-ridiculously-easy-and-im-never-going-back">Creating calendar events in iOS 27 just got ridiculously easy, and I’m never going back</a></li><li><a href="https://www.tomsguide.com/phones/iphones/ios-27-finally-gives-you-total-control-over-your-iphone-lock-screen-and-heres-what-to-change-first">iOS 27 finally gives you total control over your iPhone lock screen — here's what to change first</a></li><li><a href="https://www.tomsguide.com/phones/iphones/ios-27-quietly-fixes-the-most-annoying-iphone-workaround-we-all-use">iOS 27 finally fixes the most annoying iPhone workaround we all use</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone Duo is reportedly Apple's first foldable — $2,000 price, release date 'as early as October' ]]></title>
                                                                                                <dc:content><![CDATA[ <p>With the <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 September event</a> now upon us, it looks like we have some concrete details for Apple's first foldable phone. <a href="https://www.bloomberg.com/news/articles/2026-09-09/apple-event-details-2-000-iphone-duo-apple-watch-series-12-recording-feature">Bloomberg's Mark Gurman</a> just issued a last-minute report that reveals that the device will indeed be called the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Duo</a> and not the iPhone Ultra or iPhone Fold.</p><p>We also get some potentially bad news about the release date — and somewhat good news about the price. Here's what you need to know. </p><ul><li><strong>Name:</strong> The foldable iPhone will reportedly be called the iPhone Duo, not the iPhone Ultra</li><li><strong>Price: </strong>The iPhone Duo will start at $2,000 for 256GB of storage and go up to as high as $3,000</li><li><strong>Release date: </strong>Gurman says that the iPhone Duo will go on sale "as early as October" which means it could go beyond that</li><li><strong>Colors:</strong> It will come in white and dark blue</li><li><strong>Apple Pencil support is in: </strong>Despite conflicting earlier rumors it looks like this is happening</li></ul><h2 id="the-name-is-iphone-duo">The name is iPhone Duo</h2><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="oqerWy42bqvSRMhJh5NbQU" name="iPhone Ultra in hand" alt="iPhone Ultra render in hand" src="https://cdn.mos.cms.futurecdn.net/oqerWy42bqvSRMhJh5NbQU.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: Apple Track)</span></figcaption></figure><p>We've heard everything from the iPhone Ultra to iPhone Fold, but right now Gurman is calling the foldable iPhone the iPhone Duo. So this could be the final moniker, despite this rumor being shot down previously.</p><p>I suspect Apple is using this name so it can play up the dual-nature of the device, as you're getting a phone and tablet in one gadget. And you ostensibly get two screens when the phone is open when running apps side by side.</p><h2 id="iphone-duo-price">iPhone Duo price</h2><p>The iPhone Duo will reportedly start at $2,000, not the $2,200 to $2,500 we had heard previously. This would be $100 more than the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a>, which has a similar wide form factor. But it would also be $100 less than the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a>.</p><h2 id="iphone-duo-release-date">iPhone Duo release date</h2><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="TrT3r6fXvJDENQATkwjnxN" name="John Ternus.GettyImages-2264179980" alt="John Ternus in front of the Apple logo" src="https://cdn.mos.cms.futurecdn.net/TrT3r6fXvJDENQATkwjnxN.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Getty Images)</span></figcaption></figure><p>The bad news is that Gurman says the iPhone Duo will go on sale "as early as October," which means it could be delayed versus the iPhone 18 Pro and iPhone 18 Pro Max. Let's hope this doesn't slip beyond that.</p><h2 id="apple-pencil-surprise">Apple Pencil surprise</h2><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="sYasfB8wb4t79sAYCWFV6Y" name="image (4).png" alt="Apple Pencil" src="https://cdn.mos.cms.futurecdn.net/sYasfB8wb4t79sAYCWFV6Y.png" 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)</span></figcaption></figure><p>Although Gurman previous reported that the iPhone Duo was being tested with an Apple Pencil, it didn't appear as though it would be ready for launch. Now he's saying that the iPhone Duo will have "support for the Apple Pencil stylus."</p><p>This would give the iPhone Duo and advantage of the Galaxy Z Fold 8 series, which does not support the S Pen.</p><h2 id="iphone-duo-cameras-and-specs">iPhone Duo cameras and specs</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1046px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="457m5Jom872mCevr5ASKqe" name="Foundry iphone ultra" alt="iPhone Ultra render shown in hand" src="https://cdn.mos.cms.futurecdn.net/457m5Jom872mCevr5ASKqe.jpg" mos="" align="middle" fullscreen="" width="1046" height="588" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Foundry)</span></figcaption></figure><p>The iPhone Duo will be powered by the A20 Pro chip and Apple's C2 modem. It will also offer dual rear 48MP cameras (main and wide), as well as 12MP selfie camera. So you won't get a telephoto lens.</p><p>Gurman also describes a "magnetic hinge system."</p><p>Keep it locked to our <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 September event live blog</a> for all the last-minute rumors and leaks</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-duo-is-apples-first-foldable-usd2-000-price-release-date-as-early-as-october</link>
                                                                            <description>
                            <![CDATA[ A last-minute report says Apple's foldable phone will be called the iPhone Duo and that it will start at $2,000 and be released as soon as early October. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">rrgiDdh27QprNieU2E4Kth</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/un7nTe9PGfFqthRVsZ3DFP-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 05:40:42 +0000</pubDate>                                                                                                                                <updated>Wed, 09 Sep 2026 13:12:20 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                                    <dc:creator><![CDATA[ Mark Spoonauer ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/wtAspSzVfcKLB4JEd39AMo.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Mark Spoonauer is the global editor in chief of Tom&#039;s Guide and has covered technology for over 20 years. He oversees the direction of Tom&#039;s Guide and leads a team of over 25 journalists to bring you our expert buying guides, reviews, news, how-to articles, deals and other coverage.&lt;/p&gt;&lt;p&gt;Mark has a passion for covering all things mobile, having reviewed dozens of smartphones and other gadgets. He enjoys testing the top mobile devices and putting them up against each other in our in-depth face-offs. He also works hand in hand with our editors and testing team to continually improve how we evaluate products. &lt;/p&gt;&lt;p&gt;Having led Tom&#039;s Guide since 2013, Mark has focused on growing the core tech coverage of the site while also expanding into new areas, such as entertainment, fitness and home, recruiting talented writers and editors to help our readers figure out what to buy and how to get the most out of the products and services they use every day. &lt;/p&gt;&lt;p&gt;Mark has spoken at key industry events and appears regularly on TV to discuss the latest trends, including &lt;a href=&quot;https://cheddar.com/media/pixel-watch-gets-a-release-date-at-google-i-o-2022&quot;&gt;Cheddar&lt;/a&gt;, Fox 5, &lt;a href=&quot;https://www.foxbusiness.com/technology/apple-march-event-5g-iphone&quot;&gt;Fox Business&lt;/a&gt; and other outlets. Mark was previously editor in chief of Laptop Mag, and his work has appeared in Wired, Popular Science and Inc. Follow him on Twitter at @mspoonauer.&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/un7nTe9PGfFqthRVsZ3DFP-1280-80.jpg">
                                                            <media:credit><![CDATA[AppleTrack]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Ultra shown folded open from the outside]]></media:description>                                                            <media:text><![CDATA[iPhone Ultra shown folded open from the outside]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Ultra shown folded open from the outside]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/un7nTe9PGfFqthRVsZ3DFP-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>With the <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 September event</a> now upon us, it looks like we have some concrete details for Apple's first foldable phone. <a href="https://www.bloomberg.com/news/articles/2026-09-09/apple-event-details-2-000-iphone-duo-apple-watch-series-12-recording-feature">Bloomberg's Mark Gurman</a> just issued a last-minute report that reveals that the device will indeed be called the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Duo</a> and not the iPhone Ultra or iPhone Fold.</p><p>We also get some potentially bad news about the release date — and somewhat good news about the price. Here's what you need to know. </p><ul><li><strong>Name:</strong> The foldable iPhone will reportedly be called the iPhone Duo, not the iPhone Ultra</li><li><strong>Price: </strong>The iPhone Duo will start at $2,000 for 256GB of storage and go up to as high as $3,000</li><li><strong>Release date: </strong>Gurman says that the iPhone Duo will go on sale "as early as October" which means it could go beyond that</li><li><strong>Colors:</strong> It will come in white and dark blue</li><li><strong>Apple Pencil support is in: </strong>Despite conflicting earlier rumors it looks like this is happening</li></ul><h2 id="the-name-is-iphone-duo">The name is iPhone Duo</h2><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="oqerWy42bqvSRMhJh5NbQU" name="iPhone Ultra in hand" alt="iPhone Ultra render in hand" src="https://cdn.mos.cms.futurecdn.net/oqerWy42bqvSRMhJh5NbQU.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: Apple Track)</span></figcaption></figure><p>We've heard everything from the iPhone Ultra to iPhone Fold, but right now Gurman is calling the foldable iPhone the iPhone Duo. So this could be the final moniker, despite this rumor being shot down previously.</p><p>I suspect Apple is using this name so it can play up the dual-nature of the device, as you're getting a phone and tablet in one gadget. And you ostensibly get two screens when the phone is open when running apps side by side.</p><h2 id="iphone-duo-price">iPhone Duo price</h2><p>The iPhone Duo will reportedly start at $2,000, not the $2,200 to $2,500 we had heard previously. This would be $100 more than the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a>, which has a similar wide form factor. But it would also be $100 less than the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a>.</p><h2 id="iphone-duo-release-date">iPhone Duo release date</h2><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="TrT3r6fXvJDENQATkwjnxN" name="John Ternus.GettyImages-2264179980" alt="John Ternus in front of the Apple logo" src="https://cdn.mos.cms.futurecdn.net/TrT3r6fXvJDENQATkwjnxN.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Getty Images)</span></figcaption></figure><p>The bad news is that Gurman says the iPhone Duo will go on sale "as early as October," which means it could be delayed versus the iPhone 18 Pro and iPhone 18 Pro Max. Let's hope this doesn't slip beyond that.</p><h2 id="apple-pencil-surprise">Apple Pencil surprise</h2><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="sYasfB8wb4t79sAYCWFV6Y" name="image (4).png" alt="Apple Pencil" src="https://cdn.mos.cms.futurecdn.net/sYasfB8wb4t79sAYCWFV6Y.png" 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)</span></figcaption></figure><p>Although Gurman previous reported that the iPhone Duo was being tested with an Apple Pencil, it didn't appear as though it would be ready for launch. Now he's saying that the iPhone Duo will have "support for the Apple Pencil stylus."</p><p>This would give the iPhone Duo and advantage of the Galaxy Z Fold 8 series, which does not support the S Pen.</p><h2 id="iphone-duo-cameras-and-specs">iPhone Duo cameras and specs</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1046px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="457m5Jom872mCevr5ASKqe" name="Foundry iphone ultra" alt="iPhone Ultra render shown in hand" src="https://cdn.mos.cms.futurecdn.net/457m5Jom872mCevr5ASKqe.jpg" mos="" align="middle" fullscreen="" width="1046" height="588" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Foundry)</span></figcaption></figure><p>The iPhone Duo will be powered by the A20 Pro chip and Apple's C2 modem. It will also offer dual rear 48MP cameras (main and wide), as well as 12MP selfie camera. So you won't get a telephoto lens.</p><p>Gurman also describes a "magnetic hinge system."</p><p>Keep it locked to our <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 September event live blog</a> for all the last-minute rumors and leaks</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ The iPhone Ultra is about to kickstart a wide foldable revolution — here's why ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Sometimes the smartest analysis comes from your viewers, and that was the case with one of the comments on my <a href="https://www.youtube.com/watch?v=rQHEN3kngZo&t">video interview with Bloomberg's Mark Gurman</a> on the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Ultra</a> ahead of its big launch.</p><p>One of the key questions I posed to Gurman was a simple one:  "Why does someone need a foldable?"</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/rQHEN3kngZo" allowfullscreen></iframe></div></div><p>Here's the answer from <a href="https://www.youtube.com/@Knightairman1">@Knightairman1: </a>"Why do you need a foldable. So you carry less with you.  I have a fold 8. My 4th foldable. In one device i have a phone, a small tablet...Can I carry more and make the experience even better without taking up the space of another tablet or laptop, yes I can.  That's the point of a foldable."</p><p>This comment was in reference to the very well received <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Samsung Galaxy Z Fold 8</a>, but it also applies to the iPhone Ultra because they're supposed to share very similar passport-style designs when closed. </p><h2 id="iphone-ultra-iphone-mini-that-transforms">iPhone Ultra = iPhone mini that transforms</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:59.00%;"><img id="un7nTe9PGfFqthRVsZ3DFP" name="AppleTrack iphone fold" alt="iPhone Ultra shown folded open from the outside" src="https://cdn.mos.cms.futurecdn.net/un7nTe9PGfFqthRVsZ3DFP.jpg" mos="" align="middle" fullscreen="" width="1200" height="708" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: AppleTrack)</span></figcaption></figure><p>The iPhone Ultra is expected to feature a 5.4-5.5-inch cover display, the same size as the now discontinued <a href="https://www.tomsguide.com/reviews/iphone-13-mini">iPhone 13 mini</a>. That was the last mini sized iPhone Apple released. But there is a key difference with the iPhone Ultra's front panel.</p><p>However, the iPhone Ultra's screen is significantly wider than the one found on the iPhone mini.</p><p>While the iPhone mini had a taller aspect ratio of 19.5:9, the iPhone Ultra is expected to have a wider ratio of 3:2. The latter is optimized not just for more comfortable typing but for making social videos more immersive.</p><p>The appeal of Passport/widescreen foldables is obvious from its shape," said Avi Greengart, founder and lead analyst for Techsponential. "If you plan to use your phone to consume content, this is the right phone for you."</p><p>Plus, in landscape or tent mode, you'll be able to use the iPhone Ultra as a mini TV.</p><p>Wider front displays do involve a trade-off, though. They can be awkward to reach across with one hand. </p><h2 id="but-it-39-s-like-an-ipad-mini-too">But it's like an iPad mini, 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:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oqerWy42bqvSRMhJh5NbQU" name="iPhone Ultra in hand" alt="iPhone Ultra render in hand" src="https://cdn.mos.cms.futurecdn.net/oqerWy42bqvSRMhJh5NbQU.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: Apple Track)</span></figcaption></figure><p>When open, the iPhone Ultra will reportedly boast a 7.8-inch main display — perhaps with not much of a crease at all, if the rumors and leaks are true.</p><p>This panel would give you a wide 4:3 aspect ratio that's hopefully ideal for watching TVs and movies in landscape mode, and a 3:4 ratio in portrait mode for scrolling through TikTok, reading ebooks and surfing the web.</p><p>To be fair, the iPad mini has a larger 8.3-inch display, but for many 7.8 inches will be close enough for a killer combo of phone and tablet.</p><h2 id="wide-phones-that-aren-39-t-foldables-maybe">Wide phones that aren't foldables? Maybe</h2><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="FjLWLSYwXNchfWh7RUWQXH" name="Huawei Pura X View" alt="Huawei Pura X View" src="https://cdn.mos.cms.futurecdn.net/FjLWLSYwXNchfWh7RUWQXH.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: Huawei)</span></figcaption></figure><p>Meanwhile, the Chinese company Huawei has already unveiled a wide-passport style phone that's not a foldable in the <a href="https://consumer.huawei.com/cn/phones/pura-x-view/" target="_blank">Huawei Pura X View</a>.</p><p>As reported by <a href="https://www.androidcentral.com/phones/huawei/the-wide-screen-revolution-might-soon-come-to-a-non-foldable-near-you">Android Central</a>, the Pura X View has a 6.39-inch OLED display with a unique 16:9.5 aspect ratio, super slim bezels, and a 96.1% screen-to-body ratio.</p><p>The wider screen delivers around 16% more video space and 21% more reading space in portrait orientation than standard tall, narrow flagships.</p><p>Now, 6.39 inches is not exactly mini, but it is compared to most of today's flagship phones. I think people like the idea of something compact so long as it can deliver an immersive viewing experience.</p><p>But would consumers embrace a wide-screen phone that doesn't fold? </p><p>"Without the larger interior display, that's a weird shape without obvious app or content benefits," Greengart said. "Unless Apple or Samsung pushed hard, U.S. carriers are unlikely to take the risk of stocking and subsidizing them."</p><p>However, while a wide phone on its own could be an ergonomic mismatch, when paired with an unfolding 7.8-inch inner screen, the wide cover display becomes an asset rather than a liability.</p><h2 id="why-apple-could-lead-the-wide-phone-revolution">Why Apple could lead the wide phone revolution</h2><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="g5Ndi778wD3dSpn6XzB5te" name="iPhone Ultra Back AppleTrack-2" alt="iPhone Ultra render shown in hand" src="https://cdn.mos.cms.futurecdn.net/g5Ndi778wD3dSpn6XzB5te.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: AppleTrack)</span></figcaption></figure><p>There's already a handful of widescreen foldables available, and Samsung has particularly strong momentum with the Fold 8 series. </p><p>But according to IDC, Apple is expected to capture 31% of units sold in its very first year, and it will become the market leader with 40% unit share in 2027.</p><p>A big part of Apple's appeal is the ecosystem factor, and the fact that it has been optimizing both its iOS 27 operating system and its apps for its widescreen foldable.</p><p>As reported by <a href="https://www.bloomberg.com/news/articles/2026-09-08/apple-s-2-000-plus-foldable-iphone-was-a-decade-in-the-making">Bloomberg's Gurman</a> this week, Apple believes it "has a leg up in software over the more fragmented Android ecosystem."</p><p>Android foldables historically suffer from unoptimized app scaling. Apple’s ability to enforce iOS 27 and iPadOS-like layout guidelines means apps should natively adapt to 3:2 and 4:3 ratios from day one. </p><p>So it appears that Apple could wind up leading the widescreen foldable charge, and I would not be surprised if those companies that don't currently make a wide foldable (Google, Motorola?) wind up switching to that form factor very soon.</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-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-all-the-last-minute-rumors-and-leaks"><strong>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: All the last minute rumors and leaks</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-5-last-minute-leaks-worth-knowing-about"><strong>Apple Watch Series 12 last-minute leaks — 5 upgrades coming your way</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know"><strong>iPhone Ultra expected release date, price, colors, pre-orders, specs and everything you need to know</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/the-iphone-ultra-could-spur-a-new-wide-phone-revolution-heres-why</link>
                                                                            <description>
                            <![CDATA[ The aspect ratio of the iPhone Ultra could spur other companies to making similar devices. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">nq2SwP4BpQvKTY8KBBfxgP</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/uZcqBzcPrfQi6sxsPWkjg3-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 05:15:00 +0000</pubDate>                                                                                                                                <updated>Wed, 09 Sep 2026 08:27:19 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                                    <dc:creator><![CDATA[ Mark Spoonauer ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/wtAspSzVfcKLB4JEd39AMo.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Mark Spoonauer is the global editor in chief of Tom&#039;s Guide and has covered technology for over 20 years. He oversees the direction of Tom&#039;s Guide and leads a team of over 25 journalists to bring you our expert buying guides, reviews, news, how-to articles, deals and other coverage.&lt;/p&gt;&lt;p&gt;Mark has a passion for covering all things mobile, having reviewed dozens of smartphones and other gadgets. He enjoys testing the top mobile devices and putting them up against each other in our in-depth face-offs. He also works hand in hand with our editors and testing team to continually improve how we evaluate products. &lt;/p&gt;&lt;p&gt;Having led Tom&#039;s Guide since 2013, Mark has focused on growing the core tech coverage of the site while also expanding into new areas, such as entertainment, fitness and home, recruiting talented writers and editors to help our readers figure out what to buy and how to get the most out of the products and services they use every day. &lt;/p&gt;&lt;p&gt;Mark has spoken at key industry events and appears regularly on TV to discuss the latest trends, including &lt;a href=&quot;https://cheddar.com/media/pixel-watch-gets-a-release-date-at-google-i-o-2022&quot;&gt;Cheddar&lt;/a&gt;, Fox 5, &lt;a href=&quot;https://www.foxbusiness.com/technology/apple-march-event-5g-iphone&quot;&gt;Fox Business&lt;/a&gt; and other outlets. Mark was previously editor in chief of Laptop Mag, and his work has appeared in Wired, Popular Science and Inc. Follow him on Twitter at @mspoonauer.&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/uZcqBzcPrfQi6sxsPWkjg3-1280-80.jpg">
                                                            <media:credit><![CDATA[MacRumors]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Ultra shown laying down open]]></media:description>                                                            <media:text><![CDATA[iPhone Ultra shown laying down open]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Ultra shown laying down open]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/uZcqBzcPrfQi6sxsPWkjg3-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Sometimes the smartest analysis comes from your viewers, and that was the case with one of the comments on my <a href="https://www.youtube.com/watch?v=rQHEN3kngZo&t">video interview with Bloomberg's Mark Gurman</a> on the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Ultra</a> ahead of its big launch.</p><p>One of the key questions I posed to Gurman was a simple one:  "Why does someone need a foldable?"</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/rQHEN3kngZo" allowfullscreen></iframe></div></div><p>Here's the answer from <a href="https://www.youtube.com/@Knightairman1">@Knightairman1: </a>"Why do you need a foldable. So you carry less with you.  I have a fold 8. My 4th foldable. In one device i have a phone, a small tablet...Can I carry more and make the experience even better without taking up the space of another tablet or laptop, yes I can.  That's the point of a foldable."</p><p>This comment was in reference to the very well received <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Samsung Galaxy Z Fold 8</a>, but it also applies to the iPhone Ultra because they're supposed to share very similar passport-style designs when closed. </p><h2 id="iphone-ultra-iphone-mini-that-transforms">iPhone Ultra = iPhone mini that transforms</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:59.00%;"><img id="un7nTe9PGfFqthRVsZ3DFP" name="AppleTrack iphone fold" alt="iPhone Ultra shown folded open from the outside" src="https://cdn.mos.cms.futurecdn.net/un7nTe9PGfFqthRVsZ3DFP.jpg" mos="" align="middle" fullscreen="" width="1200" height="708" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: AppleTrack)</span></figcaption></figure><p>The iPhone Ultra is expected to feature a 5.4-5.5-inch cover display, the same size as the now discontinued <a href="https://www.tomsguide.com/reviews/iphone-13-mini">iPhone 13 mini</a>. That was the last mini sized iPhone Apple released. But there is a key difference with the iPhone Ultra's front panel.</p><p>However, the iPhone Ultra's screen is significantly wider than the one found on the iPhone mini.</p><p>While the iPhone mini had a taller aspect ratio of 19.5:9, the iPhone Ultra is expected to have a wider ratio of 3:2. The latter is optimized not just for more comfortable typing but for making social videos more immersive.</p><p>The appeal of Passport/widescreen foldables is obvious from its shape," said Avi Greengart, founder and lead analyst for Techsponential. "If you plan to use your phone to consume content, this is the right phone for you."</p><p>Plus, in landscape or tent mode, you'll be able to use the iPhone Ultra as a mini TV.</p><p>Wider front displays do involve a trade-off, though. They can be awkward to reach across with one hand. </p><h2 id="but-it-39-s-like-an-ipad-mini-too">But it's like an iPad mini, 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:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oqerWy42bqvSRMhJh5NbQU" name="iPhone Ultra in hand" alt="iPhone Ultra render in hand" src="https://cdn.mos.cms.futurecdn.net/oqerWy42bqvSRMhJh5NbQU.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: Apple Track)</span></figcaption></figure><p>When open, the iPhone Ultra will reportedly boast a 7.8-inch main display — perhaps with not much of a crease at all, if the rumors and leaks are true.</p><p>This panel would give you a wide 4:3 aspect ratio that's hopefully ideal for watching TVs and movies in landscape mode, and a 3:4 ratio in portrait mode for scrolling through TikTok, reading ebooks and surfing the web.</p><p>To be fair, the iPad mini has a larger 8.3-inch display, but for many 7.8 inches will be close enough for a killer combo of phone and tablet.</p><h2 id="wide-phones-that-aren-39-t-foldables-maybe">Wide phones that aren't foldables? Maybe</h2><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="FjLWLSYwXNchfWh7RUWQXH" name="Huawei Pura X View" alt="Huawei Pura X View" src="https://cdn.mos.cms.futurecdn.net/FjLWLSYwXNchfWh7RUWQXH.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: Huawei)</span></figcaption></figure><p>Meanwhile, the Chinese company Huawei has already unveiled a wide-passport style phone that's not a foldable in the <a href="https://consumer.huawei.com/cn/phones/pura-x-view/" target="_blank">Huawei Pura X View</a>.</p><p>As reported by <a href="https://www.androidcentral.com/phones/huawei/the-wide-screen-revolution-might-soon-come-to-a-non-foldable-near-you">Android Central</a>, the Pura X View has a 6.39-inch OLED display with a unique 16:9.5 aspect ratio, super slim bezels, and a 96.1% screen-to-body ratio.</p><p>The wider screen delivers around 16% more video space and 21% more reading space in portrait orientation than standard tall, narrow flagships.</p><p>Now, 6.39 inches is not exactly mini, but it is compared to most of today's flagship phones. I think people like the idea of something compact so long as it can deliver an immersive viewing experience.</p><p>But would consumers embrace a wide-screen phone that doesn't fold? </p><p>"Without the larger interior display, that's a weird shape without obvious app or content benefits," Greengart said. "Unless Apple or Samsung pushed hard, U.S. carriers are unlikely to take the risk of stocking and subsidizing them."</p><p>However, while a wide phone on its own could be an ergonomic mismatch, when paired with an unfolding 7.8-inch inner screen, the wide cover display becomes an asset rather than a liability.</p><h2 id="why-apple-could-lead-the-wide-phone-revolution">Why Apple could lead the wide phone revolution</h2><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="g5Ndi778wD3dSpn6XzB5te" name="iPhone Ultra Back AppleTrack-2" alt="iPhone Ultra render shown in hand" src="https://cdn.mos.cms.futurecdn.net/g5Ndi778wD3dSpn6XzB5te.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: AppleTrack)</span></figcaption></figure><p>There's already a handful of widescreen foldables available, and Samsung has particularly strong momentum with the Fold 8 series. </p><p>But according to IDC, Apple is expected to capture 31% of units sold in its very first year, and it will become the market leader with 40% unit share in 2027.</p><p>A big part of Apple's appeal is the ecosystem factor, and the fact that it has been optimizing both its iOS 27 operating system and its apps for its widescreen foldable.</p><p>As reported by <a href="https://www.bloomberg.com/news/articles/2026-09-08/apple-s-2-000-plus-foldable-iphone-was-a-decade-in-the-making">Bloomberg's Gurman</a> this week, Apple believes it "has a leg up in software over the more fragmented Android ecosystem."</p><p>Android foldables historically suffer from unoptimized app scaling. Apple’s ability to enforce iOS 27 and iPadOS-like layout guidelines means apps should natively adapt to 3:2 and 4:3 ratios from day one. </p><p>So it appears that Apple could wind up leading the widescreen foldable charge, and I would not be surprised if those companies that don't currently make a wide foldable (Google, Motorola?) wind up switching to that form factor very soon.</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-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-all-the-last-minute-rumors-and-leaks"><strong>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: All the last minute rumors and leaks</strong></a></li><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-5-last-minute-leaks-worth-knowing-about"><strong>Apple Watch Series 12 last-minute leaks — 5 upgrades coming your way</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know"><strong>iPhone Ultra expected release date, price, colors, pre-orders, specs and everything you need to know</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Don't expect an iPhone 17 discount at today's iPhone event — here's why ]]></title>
                                                                                                <dc:content><![CDATA[ <p>This year's<a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september"> iPhone launch event </a>is not like its predecessors. Rather than releasing a whole wave of new iPhones, <a href="https://www.tomsguide.com/phones/iphone-18-release-just-tipped-for-major-shakeup-heres-when-all-the-new-models-could-launch">Apple is ignoring the non-Pro models</a>. This means the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-7-biggest-rumors-so-far">iPhone 18</a> likely won't be arriving until sometime in early 2027, leaving the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-review">iPhone 17 </a>as the de-factor entry-level iPhone flagship for a few more months.</p><p>That throws a whole wrench into the established pattern of Apple events. Normally new iPhones mean that the Pro models get discontinued, while the non-Pro models stick around for another year at a reduced price — usually $100 or so less than before. We're not having a traditional iPhone event this year and that leaves a bunch of unanswered questions.</p><p>What happens when there's no new standard model to take over? Is the iPhone 17 going to get that same price cut after the launch of iPhone 18 Pro? Will the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-16-review">iPhone 16</a> still be available at the Apple Store after tomorrow?</p><h2 id="apple-doesn-39-t-really-offer-big-discounts">Apple doesn't really offer big discounts</h2><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="fVuHZ9RCFaSQuBg6DJ4zHD" name="iphone17-3 (1)-2" alt="iPhone 17 home screen" src="https://cdn.mos.cms.futurecdn.net/fVuHZ9RCFaSQuBg6DJ4zHD.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>Apple products don't go on sale very often, and when they do it's almost always from a third party retailer that's knocked a few bucks off the normal price during a big sales event — or following the launch of a new model. </p><p>Apple itself usually avoids this tactic, and offers its products at full price all year round. Even the company's <a href="https://www.tomsguide.com/phones/iphones/apples-celebrating-black-friday-with-a-special-weekend-shopping-event-here-are-the-deals-on-offer">Black Friday deals</a> typically involve free gift cards <em>after</em> you've purchased something else at full price. The annual iPhone price cut is usually the most we can get out of a the company, and that's only because Apple keeps it around as a slightly cheaper alternative to a newer model.</p><p>Without the iPhone 18 to take center stage, there's absolutely no reason why Apple would discount the iPhone 17. A price cut at this stage might help sell more iPhone 17s before the holidays, but that's likely to come at the cost of iPhone 18 sales when the phone does eventually launch. </p><p>Not to mention the fact the reason the iPhone 18 was delayed is because Apple reportedly <a href="https://www.tomsguide.com/phones/iphones/iphone-18-could-be-launching-later-than-expected-and-i-think-thats-a-terrible-plan">wants to push people into buying the more expensive Pro models</a>. The last thing Apple is going to do is mess that strategy up by lowering the price of the older phone. And considering it hasn't officially been replaced, there's little need to incentivize sales by offering a lower price tag.</p><p>So the iPhone 17 continues, existing as the lower cost and less impressive alternative to the<a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far"> iPhone 18 Pro </a>and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">Pro Max</a>. Albeit with a slightly bigger age gap than normal.</p><h2 id="we-can-39-t-forget-about-price-hikes-either">We can't forget about price hikes either</h2><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="XsiTj7kxY5xtiZMvD3h7ud" name="Apple iPhone 17 review" alt="Apple iPhone 17 review." src="https://cdn.mos.cms.futurecdn.net/XsiTj7kxY5xtiZMvD3h7ud.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>2026 has been the year of increased prices in the tech world, and it's mostly down to the fact the <a href="https://www.tomsguide.com/computing/ram-price-crisis-2026-everything-you-need-to-know">cost of RAM and storage has gone through the roof</a>. AI companies have been buying up all the supply, and that means everyone else had to start paying out of the nose for such basic components.</p><p>For this reason, <a href="https://www.tomsguide.com/computing/macbooks/apple-price-hikes-are-official-heres-how-much-more-youll-pay-for-macbooks-and-ipads-now">Apple increased the price of most of its products</a> earlier this summer, with only the iPhone and Apple Watch being spared. But it was clear that the iPhone was on borrowed time, and that price hikes would almost certainly happen during the iPhone launch event.</p><p>With that in mind, it's even less likely that Apple would reduce the price of the iPhone 17. If iPhones are now more expensive to make, it doesn't make a whole lot of sense to start slashing prices. More so when you remember that <a href="https://www.tomsguide.com/phones/iphones/analysts-warn-the-iphone-18-price-hike-could-be-worse-than-we-thought">the iPhone 18 likely would have suffered a price hike as well,</a> which would have made an iPhone 17 price cut even more unlikely.</p><p>In other words, no matter which way you look at it, it was unlikely that the iPhone 17 would be getting discounted following the Surprise and shine launch event. If you think about it, considering what usually happens to standard model iPhones, keeping the price static is just another kind of price hike.</p><h2 id="bottom-line-2">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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ecRd2peLtxYXQxQQvJq3Ge" name="Apple iPhone 17 review" alt="Apple iPhone 17 review." src="https://cdn.mos.cms.futurecdn.net/ecRd2peLtxYXQxQQvJq3Ge.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>If you were planning on buying an iPhone 17 anytime soon, then you're going to be disappointed by the lack of discounts. With no iPhone 18 coming, there's little reason for Apple to actually drop the price. Especially not with the ever-rising cost of making phones.</p><p>That said, this doesn't necessarily mean that you won't be able to find iPhone 17 discounts at all. Third party retailers and carriers already offer deals, since they're going to want to prioritize the newest models. That means we could see money off the total cost of the iPhone 17, or enticing deals that give you discounted rates when you sign up for a multi-year phone plan, or trade in your older device.</p><p>As for what happens next year when the iPhone 18 is released, that's anyone's guess. With the lower-cost iPhone 18e set to launch around the same time, that could be the end of the line for iPhone 17. Or Apple could offer some kind of discount to help sell whatever iPhone 17 stock still remains in six months time. As for the iPhone 16, your guess is as good as mine.</p><p>We're just going to have to wait and see how that pans out. </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-ultra-tipped-to-cost-usd2-000-and-still-lose-a-crucial-feature-im-weirdly-conflicted-about-it">iPhone Ultra tipped to cost $2,000 and still lose a crucial feature — I'm weirdly conflicted about it</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-features-just-leaked-before-launch-including-aperture-based-image-corrections">iPhone 18 Pro camera features just leaked before launch — including ‘aperture based image corrections’</a></li><li><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 September event LIVE blog: iPhone Ultra, iPhone 18 Pro Max and last-minute leaks</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/dont-expect-an-iphone-17-discount-at-todays-iphone-event-heres-why</link>
                                                                            <description>
                            <![CDATA[ The iPhone 18 isn't arriving this week, and that means the future of the iPhone 17 is likely to be more expensive than we'd hoped. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">ukvH5fY6g4C4Y4kov8AQqH</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/fXQyeewX6f4cMRqqSucB2D-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 09 Sep 2026 04:30:00 +0000</pubDate>                                                                                                                                <updated>Wed, 09 Sep 2026 08:27:47 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ tom.pritchard@futurenet.com (Tom Pritchard) ]]></author>                    <dc:creator><![CDATA[ Tom Pritchard ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/biCewUkKfSA6QnT2HxVc3f.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/fXQyeewX6f4cMRqqSucB2D-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Sage iPhone 17 in hand]]></media:description>                                                            <media:text><![CDATA[Sage iPhone 17 in hand]]></media:text>
                                <media:title type="plain"><![CDATA[Sage iPhone 17 in hand]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/fXQyeewX6f4cMRqqSucB2D-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>This year's<a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september"> iPhone launch event </a>is not like its predecessors. Rather than releasing a whole wave of new iPhones, <a href="https://www.tomsguide.com/phones/iphone-18-release-just-tipped-for-major-shakeup-heres-when-all-the-new-models-could-launch">Apple is ignoring the non-Pro models</a>. This means the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-7-biggest-rumors-so-far">iPhone 18</a> likely won't be arriving until sometime in early 2027, leaving the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-review">iPhone 17 </a>as the de-factor entry-level iPhone flagship for a few more months.</p><p>That throws a whole wrench into the established pattern of Apple events. Normally new iPhones mean that the Pro models get discontinued, while the non-Pro models stick around for another year at a reduced price — usually $100 or so less than before. We're not having a traditional iPhone event this year and that leaves a bunch of unanswered questions.</p><p>What happens when there's no new standard model to take over? Is the iPhone 17 going to get that same price cut after the launch of iPhone 18 Pro? Will the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-16-review">iPhone 16</a> still be available at the Apple Store after tomorrow?</p><h2 id="apple-doesn-39-t-really-offer-big-discounts">Apple doesn't really offer big discounts</h2><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="fVuHZ9RCFaSQuBg6DJ4zHD" name="iphone17-3 (1)-2" alt="iPhone 17 home screen" src="https://cdn.mos.cms.futurecdn.net/fVuHZ9RCFaSQuBg6DJ4zHD.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>Apple products don't go on sale very often, and when they do it's almost always from a third party retailer that's knocked a few bucks off the normal price during a big sales event — or following the launch of a new model. </p><p>Apple itself usually avoids this tactic, and offers its products at full price all year round. Even the company's <a href="https://www.tomsguide.com/phones/iphones/apples-celebrating-black-friday-with-a-special-weekend-shopping-event-here-are-the-deals-on-offer">Black Friday deals</a> typically involve free gift cards <em>after</em> you've purchased something else at full price. The annual iPhone price cut is usually the most we can get out of a the company, and that's only because Apple keeps it around as a slightly cheaper alternative to a newer model.</p><p>Without the iPhone 18 to take center stage, there's absolutely no reason why Apple would discount the iPhone 17. A price cut at this stage might help sell more iPhone 17s before the holidays, but that's likely to come at the cost of iPhone 18 sales when the phone does eventually launch. </p><p>Not to mention the fact the reason the iPhone 18 was delayed is because Apple reportedly <a href="https://www.tomsguide.com/phones/iphones/iphone-18-could-be-launching-later-than-expected-and-i-think-thats-a-terrible-plan">wants to push people into buying the more expensive Pro models</a>. The last thing Apple is going to do is mess that strategy up by lowering the price of the older phone. And considering it hasn't officially been replaced, there's little need to incentivize sales by offering a lower price tag.</p><p>So the iPhone 17 continues, existing as the lower cost and less impressive alternative to the<a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far"> iPhone 18 Pro </a>and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">Pro Max</a>. Albeit with a slightly bigger age gap than normal.</p><h2 id="we-can-39-t-forget-about-price-hikes-either">We can't forget about price hikes either</h2><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="XsiTj7kxY5xtiZMvD3h7ud" name="Apple iPhone 17 review" alt="Apple iPhone 17 review." src="https://cdn.mos.cms.futurecdn.net/XsiTj7kxY5xtiZMvD3h7ud.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>2026 has been the year of increased prices in the tech world, and it's mostly down to the fact the <a href="https://www.tomsguide.com/computing/ram-price-crisis-2026-everything-you-need-to-know">cost of RAM and storage has gone through the roof</a>. AI companies have been buying up all the supply, and that means everyone else had to start paying out of the nose for such basic components.</p><p>For this reason, <a href="https://www.tomsguide.com/computing/macbooks/apple-price-hikes-are-official-heres-how-much-more-youll-pay-for-macbooks-and-ipads-now">Apple increased the price of most of its products</a> earlier this summer, with only the iPhone and Apple Watch being spared. But it was clear that the iPhone was on borrowed time, and that price hikes would almost certainly happen during the iPhone launch event.</p><p>With that in mind, it's even less likely that Apple would reduce the price of the iPhone 17. If iPhones are now more expensive to make, it doesn't make a whole lot of sense to start slashing prices. More so when you remember that <a href="https://www.tomsguide.com/phones/iphones/analysts-warn-the-iphone-18-price-hike-could-be-worse-than-we-thought">the iPhone 18 likely would have suffered a price hike as well,</a> which would have made an iPhone 17 price cut even more unlikely.</p><p>In other words, no matter which way you look at it, it was unlikely that the iPhone 17 would be getting discounted following the Surprise and shine launch event. If you think about it, considering what usually happens to standard model iPhones, keeping the price static is just another kind of price hike.</p><h2 id="bottom-line-2">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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ecRd2peLtxYXQxQQvJq3Ge" name="Apple iPhone 17 review" alt="Apple iPhone 17 review." src="https://cdn.mos.cms.futurecdn.net/ecRd2peLtxYXQxQQvJq3Ge.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>If you were planning on buying an iPhone 17 anytime soon, then you're going to be disappointed by the lack of discounts. With no iPhone 18 coming, there's little reason for Apple to actually drop the price. Especially not with the ever-rising cost of making phones.</p><p>That said, this doesn't necessarily mean that you won't be able to find iPhone 17 discounts at all. Third party retailers and carriers already offer deals, since they're going to want to prioritize the newest models. That means we could see money off the total cost of the iPhone 17, or enticing deals that give you discounted rates when you sign up for a multi-year phone plan, or trade in your older device.</p><p>As for what happens next year when the iPhone 18 is released, that's anyone's guess. With the lower-cost iPhone 18e set to launch around the same time, that could be the end of the line for iPhone 17. Or Apple could offer some kind of discount to help sell whatever iPhone 17 stock still remains in six months time. As for the iPhone 16, your guess is as good as mine.</p><p>We're just going to have to wait and see how that pans out. </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-ultra-tipped-to-cost-usd2-000-and-still-lose-a-crucial-feature-im-weirdly-conflicted-about-it">iPhone Ultra tipped to cost $2,000 and still lose a crucial feature — I'm weirdly conflicted about it</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-features-just-leaked-before-launch-including-aperture-based-image-corrections">iPhone 18 Pro camera features just leaked before launch — including ‘aperture based image corrections’</a></li><li><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 September event LIVE blog: iPhone Ultra, iPhone 18 Pro Max and last-minute leaks</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone Ultra last-minute report touts 'industry-leading' build quality — and a $2,199 starting price ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple's take on a foldable phone is finally arriving as part of John Ternus' first <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#mrfhud=true">Apple event</a> as the CEO of the tech giant. </p><p>Just about everything about the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Ultra</a> has been revealed in the run-up to the Surprise and Shine reveal. The price has been nebulous, beyond rumors of over $2,000. </p><p>However, a new report from <a href="https://www.bloomberg.com/news/articles/2026-09-08/apple-s-2-000-plus-foldable-iphone-was-a-decade-in-the-making" target="_blank">Bloomberg's Mark Gurman</a> has revealed a possible starting price of $2,100 that could touch close to $3,000 for higher-end configurations. He also claims that the device will be made from high-quality materials following a decade of development.</p><h2 id="iphone-ultra-price-and-build-quality">iPhone Ultra price and build quality</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="BXFPFEcaHQrVivQScPBNff" name="iPhone Ultra" alt="iPhone Ultra." src="https://cdn.mos.cms.futurecdn.net/BXFPFEcaHQrVivQScPBNff.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Unfortunately, Gurman doesn't indicate how many storage variants the iPhone Ultra will get. </p><p>The reports notes that Apple is considering pricing the Ultra as high as $2,199 for the base model, presumably with 256GB of storage like the iPhone Pro models. As a comparison, the iPhone 17 Pro starts $1,099 for its 256GB base version. Just keep in mind that the iPhone 18 Pro is expected to get a $200-$250 price hike.</p><p>With RAM prices still affecting everything, higher storage tiers could go as high as $3,000. That's likely going to be the 1TB or 2TB version. As an example, the iPhone 17 Pro Max with 2TB costs $1,999. The 17 Pro only has a 1TB version for $1,499.</p><p>As is Apple's style, this thing should look and feel premium. The hinge is made out of titanium and aluminum and a customer Corning glass cover. The company has reportedly developed a new flexible cover glass for the display that helps nearly eliminate the crease in the screen.</p><p>Apple apparently believes the quality is "industry-leading" especially compared to other foldable phones. </p><p>In addition, Bloomberg's Gurman reports that Apple believes it has a "leg up in software over the more fragmented Android ecosystem."</p><p>That's because Apple has optimized its apps to work better on the wide display and has made other tweaks to iOS.</p><h2 id="a-long-history">A long history</h2><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:52.83%;"><img id="dDjXCWbkNeS7fx6nnQNpff" name="iPhone flip.png" alt="iPhone Flip concept" src="https://cdn.mos.cms.futurecdn.net/dDjXCWbkNeS7fx6nnQNpff.png" mos="" align="middle" fullscreen="" width="1024" height="541" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: #iOS Beta News/YouTube/Tom's Guide)</span></figcaption></figure><p>Per Gurman, work on the iPhone Ultra began in earnest in 2019 after former CEO Tim Cook returned from a tour of Asia and saw people using foldables from other companies. Allegedly, Cook became convinced that Apple needed its own version.</p><p>Cook may have sped up the process but we've heard rumors of a foldable iPhone since at least 2015 when we first heard rumblings of something dubbed the <a href="https://www.tomsguide.com/news/apple-folding-iphone-patent-with-improved-hinge">iPhone Flip</a>. Though that version <a href="https://www.tomsguide.com/us/apple-foldable-iphone-patent,news-29538.html">was a clamshell </a>more akin to the Motorola Razr and <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-flip-8-review">Samsung Galaxy Z Flip 8</a>.</p><p>In the last couple of years, it was redubbed the<a href="https://www.tomsguide.com/phones/iphones/forget-the-iphone-17-foldable-iphone-tipped-to-debut-next-year-with-four-cameras-touch-id-and-apple-cellular-modem"> iPhone Fold</a> and the design apparently shifted from a clamshell to the more common book-style that we see in the <a href="https://www.tomsguide.com/phones/samsung-phones/ive-been-living-with-the-galaxy-z-fold-8-for-3-weeks-and-i-was-wrong">Galaxy Z Fold 8</a> and <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Fold 8 Ultra.</a> Rumors have suggested that a clamshell variant is <a href="https://www.tomsguide.com/phones/iphones/massive-apple-leaks-reveal-iphone-roadmap-new-flip-foldable-and-iphone-20-on-the-way">still in the works</a>.</p><p>It also wasn't the first expected Apple foldable device. For years, it's been suggested that Apple would debut a foldable iPad or some kind of hybrid MacBook/iPad with an 18.8-inch display. Gurman has claimed in the past that the design ran into development problems, and in his latest reports indicates that Cook's enthusiasm for the phone altered the direction of Apple's focus.</p><p>We'll find out more tomorrow at Ternus' first event and Tom's Guide will be there person to share all the news and updates with you. Be sure to keep us in your tabs and follow along with our<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"> live coverage</a>.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-5-last-minute-leaks-worth-knowing-about">Apple Watch Series 12 last-minute leaks — 5 upgrades coming your way</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-all-the-last-minute-rumors-and-leaks">iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: All the last minute rumors and leaks</a></li><li><a href="https://www.tomsguide.com/computing/macbooks/huge-new-apple-report-details-all-41-products-coming-under-new-ceo-john-ternus">Huge new Apple report details all 41 products coming under new CEO John Ternus</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-ultra-last-minute-report-touts-industry-leading-build-quality-and-a-usd2-199-starting-price</link>
                                                                            <description>
                            <![CDATA[ A new report reveals a potential price and some qualities about the upcoming iPhone Ultra ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">fhvHvQfBQ5ar9WQW8VSNU8</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/aUJZxCfMMXC3m2nKLVB2dV-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 08 Sep 2026 20:32:18 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ scott.younker@futurenet.com (Scott Younker) ]]></author>                    <dc:creator><![CDATA[ Scott Younker ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/RZsUpqcJ6Uj2q83oCUwNhQ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Scott Younker is the West Coast Reporter at Tom’s Guide. He covers all the latest tech news, including phones, computing and more. He’s been involved in tech since 2011 covering everything from cameras and swimming pool equipment to the latest gaming consoles and smart TVs. He is on a seemingly never ending hunt to build the easiest to use home media system. &lt;/p&gt;&lt;p&gt;Before Tom’s Guide, Scott worked for publications like &lt;em&gt;Digital Trends, Outdoor Photographer, Dead Beats Panel&lt;/em&gt;, and in a brief detour, &lt;em&gt;America’s Funniest Home Videos&lt;/em&gt;. Yes, he has seen more pratfalls, silly pets and ridiculous home movie fails than is reasonably healthy. &lt;/p&gt;&lt;p&gt;When not writing about the latest devices or advances in chipsets, be sure to ask about Scott about disc golf and sustainability, or just if you’re being cheeky, ask about his noodle arm. If you truly want to get nerdy, bring up board games and his ongoing losing streak. &lt;/p&gt;&lt;p&gt;Scott joined Tom&#039;s Guide in 2024 as the West Coast Reporter. He graduated from the School of Journalism at the University of Oregon with a degree in magazine journalism and a minor in communications. While there he blogged or wrote for several magazines including the Fluxx, Ethos and the Oregon Commentator. He briefly wrote and managed a moderately successful blog focused on web comics. &lt;br&gt;Send secure tips on Signal: scyo1.55.&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/aUJZxCfMMXC3m2nKLVB2dV-1280-80.jpg">
                                                            <media:credit><![CDATA[Majin Bu on X]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Fold design ]]></media:description>                                                            <media:text><![CDATA[iPhone Fold design ]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Fold design ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/aUJZxCfMMXC3m2nKLVB2dV-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple's take on a foldable phone is finally arriving as part of John Ternus' first <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#mrfhud=true">Apple event</a> as the CEO of the tech giant. </p><p>Just about everything about the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-expected-release-date-price-colors-pre-orders-specs-and-everything-you-need-to-know">iPhone Ultra</a> has been revealed in the run-up to the Surprise and Shine reveal. The price has been nebulous, beyond rumors of over $2,000. </p><p>However, a new report from <a href="https://www.bloomberg.com/news/articles/2026-09-08/apple-s-2-000-plus-foldable-iphone-was-a-decade-in-the-making" target="_blank">Bloomberg's Mark Gurman</a> has revealed a possible starting price of $2,100 that could touch close to $3,000 for higher-end configurations. He also claims that the device will be made from high-quality materials following a decade of development.</p><h2 id="iphone-ultra-price-and-build-quality">iPhone Ultra price and build quality</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="BXFPFEcaHQrVivQScPBNff" name="iPhone Ultra" alt="iPhone Ultra." src="https://cdn.mos.cms.futurecdn.net/BXFPFEcaHQrVivQScPBNff.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Unfortunately, Gurman doesn't indicate how many storage variants the iPhone Ultra will get. </p><p>The reports notes that Apple is considering pricing the Ultra as high as $2,199 for the base model, presumably with 256GB of storage like the iPhone Pro models. As a comparison, the iPhone 17 Pro starts $1,099 for its 256GB base version. Just keep in mind that the iPhone 18 Pro is expected to get a $200-$250 price hike.</p><p>With RAM prices still affecting everything, higher storage tiers could go as high as $3,000. That's likely going to be the 1TB or 2TB version. As an example, the iPhone 17 Pro Max with 2TB costs $1,999. The 17 Pro only has a 1TB version for $1,499.</p><p>As is Apple's style, this thing should look and feel premium. The hinge is made out of titanium and aluminum and a customer Corning glass cover. The company has reportedly developed a new flexible cover glass for the display that helps nearly eliminate the crease in the screen.</p><p>Apple apparently believes the quality is "industry-leading" especially compared to other foldable phones. </p><p>In addition, Bloomberg's Gurman reports that Apple believes it has a "leg up in software over the more fragmented Android ecosystem."</p><p>That's because Apple has optimized its apps to work better on the wide display and has made other tweaks to iOS.</p><h2 id="a-long-history">A long history</h2><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:52.83%;"><img id="dDjXCWbkNeS7fx6nnQNpff" name="iPhone flip.png" alt="iPhone Flip concept" src="https://cdn.mos.cms.futurecdn.net/dDjXCWbkNeS7fx6nnQNpff.png" mos="" align="middle" fullscreen="" width="1024" height="541" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: #iOS Beta News/YouTube/Tom's Guide)</span></figcaption></figure><p>Per Gurman, work on the iPhone Ultra began in earnest in 2019 after former CEO Tim Cook returned from a tour of Asia and saw people using foldables from other companies. Allegedly, Cook became convinced that Apple needed its own version.</p><p>Cook may have sped up the process but we've heard rumors of a foldable iPhone since at least 2015 when we first heard rumblings of something dubbed the <a href="https://www.tomsguide.com/news/apple-folding-iphone-patent-with-improved-hinge">iPhone Flip</a>. Though that version <a href="https://www.tomsguide.com/us/apple-foldable-iphone-patent,news-29538.html">was a clamshell </a>more akin to the Motorola Razr and <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-flip-8-review">Samsung Galaxy Z Flip 8</a>.</p><p>In the last couple of years, it was redubbed the<a href="https://www.tomsguide.com/phones/iphones/forget-the-iphone-17-foldable-iphone-tipped-to-debut-next-year-with-four-cameras-touch-id-and-apple-cellular-modem"> iPhone Fold</a> and the design apparently shifted from a clamshell to the more common book-style that we see in the <a href="https://www.tomsguide.com/phones/samsung-phones/ive-been-living-with-the-galaxy-z-fold-8-for-3-weeks-and-i-was-wrong">Galaxy Z Fold 8</a> and <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Fold 8 Ultra.</a> Rumors have suggested that a clamshell variant is <a href="https://www.tomsguide.com/phones/iphones/massive-apple-leaks-reveal-iphone-roadmap-new-flip-foldable-and-iphone-20-on-the-way">still in the works</a>.</p><p>It also wasn't the first expected Apple foldable device. For years, it's been suggested that Apple would debut a foldable iPad or some kind of hybrid MacBook/iPad with an 18.8-inch display. Gurman has claimed in the past that the design ran into development problems, and in his latest reports indicates that Cook's enthusiasm for the phone altered the direction of Apple's focus.</p><p>We'll find out more tomorrow at Ternus' first event and Tom's Guide will be there person to share all the news and updates with you. Be sure to keep us in your tabs and follow along with our<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"> live coverage</a>.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/wellness/smartwatches/apple-watch-series-12-5-last-minute-leaks-worth-knowing-about">Apple Watch Series 12 last-minute leaks — 5 upgrades coming your way</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-all-the-last-minute-rumors-and-leaks">iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: All the last minute rumors and leaks</a></li><li><a href="https://www.tomsguide.com/computing/macbooks/huge-new-apple-report-details-all-41-products-coming-under-new-ceo-john-ternus">Huge new Apple report details all 41 products coming under new CEO John Ternus</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: All the last minute rumors and leaks ]]></title>
                                                                                                <dc:content><![CDATA[ <p><a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">Apple's Surprise and shine iPhone launch event</a> is going to be quite different, in that there are only three new iPhones being released instead of the usual five But those three newbies are all premium devices, and that makes deciding between them a much trickier endeavor.</p><p>With no standard <a href="https://www.tomsguide.com/phones/iphones/iphone-18-7-biggest-rumors-so-far">iPhone 18</a> on the horizon, it's not just a case of picking between the regular iPhone and one of two Pro-tier sizes</p><p>Prospective iPhone users that don't want to wait until<a href="https://www.tomsguide.com/phones/iphone-18-release-just-tipped-for-major-shakeup-heres-when-all-the-new-models-could-launch"> iPhone 18's early 2027 launch</a> need to decide whether they should stick with a Pro or go Ultra. But what exactly is different between all these new iPhones? Various leaks and rumors show that it's not quite as simple as one of them folds and the other two don't. </p><p>Here's what we know about <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a> vs <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-pro-max-5-big-upgrades-that-could-make-them-my-all-time-favorite-iphones">iPhone 18 Pro Max </a>vs <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra,</a> and what the differences between all three upcoming iPhones are expected to be. For more, check out our <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 September Event live blog</a> for all the last-minute leaks and the big news as its announced.</p><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-rumored-specs"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Rumored Specs</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p><strong>iPhone 18 Pro</strong></p></th><th  ><p><strong>iPhone 18 Pro Max</strong></p></th><th  ><p><strong>iPhone Ultra</strong></p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p>$1,099 - $1,199</p></td><td  ><p>$1,199 – $1,399</p></td><td  ><p>$2,000 to $2,500</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>6.3-inch OLED</p></td><td  ><p>6.9-inch OLED</p></td><td  ><p>7.8 inches / 5.4 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>A20 Pro</p></td><td  ><p>A20 Pro</p></td><td  ><p>A20</p></td></tr><tr><td class="firstcol " ><p><strong>RAM</strong></p></td><td  ><p>12GB</p></td><td  ><p>12GB</p></td><td  ><p>12GB</p></td></tr><tr><td class="firstcol " ><p><strong>Front Cameras</strong></p></td><td  ><p>18MP</p></td><td  ><p>18MP</p></td><td  ><p>24MP, 24MP</p></td></tr><tr><td class="firstcol " ><p><strong>Rear Cameras</strong></p></td><td  ><p>48MP main, 48MP ultrawide, 48MP Telephoto w/4x optical zoom</p></td><td  ><p>48MP main, 48MP ultrawide, 48MP Telephoto w/4x optical zoom</p></td><td  ><p>48MP, 48MP</p></td></tr><tr><td class="firstcol " ><p><strong>Battery</strong></p></td><td  ><p>5,288 mAh</p></td><td  ><p>5,321 mAh</p></td><td  ><p>4,883 mAh</p></td></tr><tr><td class="firstcol " ><p><strong>Colors</strong></p></td><td  ><p>Dark Cherry, Light Blue, and Silver-Gray</p></td><td  ><p>Dark Cherry, Light Blue, and Silver-Gray</p></td><td  ><p>Black, White/Silver</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-price-release-date"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Price & Release Date</span></h3><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="7iBdM6RkBx9vY5PWZDt6ef" name="iPhone 18 pro edit" alt="iPhone 18 Pro mockup" src="https://cdn.mos.cms.futurecdn.net/7iBdM6RkBx9vY5PWZDt6ef.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: Aptenod / YouTube)</span></figcaption></figure><p>Price will be a major sticking point with the next wave of iPhones, due to the fact that prices are almost certainly going up. iPhones have never been cheap, but the ongoing issues with <a href="https://www.tomsguide.com/computing/ram-price-crisis-2026-everything-you-need-to-know">RAMageddon</a> and the skyrocketing cost of both memory and storage means Apple's is all but certain to increase the price of entry. Especially after <a href="https://www.tomsguide.com/computing/macbooks/apple-price-hikes-are-official-heres-how-much-more-youll-pay-for-macbooks-and-ipads-now">raising prices of almost every product it sells </a>earlier this summer.</p><p>Analysts have predicted that the iPhone 18 Pro Max could be as much as $200 (or higher) more expensive than the <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">iPhone 17 Pro Max</a>. If that is the case, we could see the cost of <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-iphone-18-pro-prices-leak-days-before-apple-event-heres-my-final-bet-on-what-youll-pay">Apple's largest phone rise to over $1,400</a></p><p>Even if the price hike isn't that high, I'd be surprised if Apple didn't tack on an extra $100 to both iPhone 18 Pro and iPhone 18 Pro Max. In that instance both phones would start at $1,199 and $1,299, respectively. </p><p>iPhone Ultra is expected to be considerably more expensive than a non-folding iPhone, with rumors suggesting we could see a <a href="https://www.tomsguide.com/phones/iphones/usd1-299-iphone-18-pro-max-analyst-now-predicts-usd200-price-hike-for-apples-next-flagship-phone">starting price somewhere around $2,400 and $2,500</a>. However, recently <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-iphone-18-pro-prices-leak-days-before-apple-event-heres-my-final-bet-on-what-youll-pay">leaked Australian prices</a> suggest we could see a price closer to $1,999. While expensive, that would be a lot more palatable, especially since the $2,099 <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Samsung Galaxy Z Fold 8 Ultra</a> is already on sale.</p><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="xwKrhoCavwDLpAZfXJCkBh" name="iPhone Fold mockup 1" alt="iPhone Fold 3D printed mockup" src="https://cdn.mos.cms.futurecdn.net/xwKrhoCavwDLpAZfXJCkBh.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: Subsy @ MakerWorld)</span></figcaption></figure><p>As for availability, we don't expect any significant changes for the iPhone 18 Pros. Apple is a creature of habit, and pre-orders for new numbered iPhones typically begin the same week as the launch event. </p><p>With the Apple event on September 9, we would normally predict pre-orders would open on Friday September 11. Though it's predicted that Apple will want open pre-orders a day later on September 12 to avoid the anniversary of 9/11. The actual release date will likely be the following Friday, on September 18.</p><p>Things aren't quite so simple with the iPhone Ultra, due to various reports that Apple is struggling to produce enough units. No two sources seem to be able to agree on when the foldable iPhone will actually release, with some <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-delay-rumors-shot-down-in-new-report-now-apples-first-foldable-phone-may-launch-alongside-iphone-18-pro-after-all">saying it'll happen at the same time as iPhone 18 Pro</a>, and <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-delay-leak-right-after-samsungs-triumphant-galaxy-fold-8-launch-has-me-sick-of-waiting-for-apples-foldable">others claiming it'll be much later in the year</a>. </p><p>One recent report also suggested that a global launch is out of the question for the time being, since <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-is-apples-biggest-product-for-years-but-supply-chain-issues-mean-not-everyone-may-get-it-at-launch">Apple may stagger the release schedule in different regions</a> — starting with the U.S. The one thing there does seem to be consensus on is the fact that supply is likely to be limited. But with a price tag that high, it isn't likely that people will be rushing out to buy one.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ePaL2W"></div>                            </div>                            <script src="https://kwizly.com/embed/ePaL2W.js" async></script><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-design-display"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Design & 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:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AeiETujmXpR8qSnb9eKRrM" name="iPhone Fold edit 1" alt="iPhone Fold rendering" src="https://cdn.mos.cms.futurecdn.net/AeiETujmXpR8qSnb9eKRrM.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>We're not expecting any significant design changes for the iPhone 18 Pro or Pro Max, which means the two phones will probably look pretty similar to the iPhone 17 Pro and iPhone 17 Pro Max at first glance. In other words we should expect to see the same 6.3-inch and 6.9-inch displays, alongside the raised camera bar Apple refers to as the "forged plateau."</p><p> It's unclear if Apple will do anything to fix the <a href="https://www.tomsguide.com/phones/iphones/i-knew-better-than-to-carry-around-a-naked-phone-then-my-iphone-17-pro-max-met-the-asphalt">durability issues that affected</a> the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a> series. Multiple Tom's Guide employees were affected by "<a href="https://www.tomsguide.com/phones/iphones/iphone-17-scratchgate-ive-had-my-iphone-17-pro-for-over-a-week-and-its-already-scuffed">scratchgate</a>," as it was known, to varying degrees. We haven't heard rumors about this, though, so I wouldn't expect anything more than token changes to the exterior metal.</p><p>That said, we have heard rumors that the iPhone 18 Pro Max will be thicker and the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-tipped-to-be-heaviest-iphone-ever-heres-3-reasons-why-thats-a-good-thing">heaviest iPhone Apple has ever made,</a> clocking in at 240g/8.47oz. It's not clear why, but it's possible that a switch to stronger and heavier materials could account for some of the extra weight — alongside changes like larger batteries and the variable aperture camera lens</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2490px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="Gv7fyY2QJ4jPcPsj7so3fX" name="iPhone 18 Pro Max Macworld" alt="iPhone 18 Pro Max render" src="https://cdn.mos.cms.futurecdn.net/Gv7fyY2QJ4jPcPsj7so3fX.jpg" mos="" align="middle" fullscreen="" width="2490" height="1401" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Macworld/Tom's Guide)</span></figcaption></figure><p>The iPhone Ultra, on the other hand, is shaping up to be unlike any iPhone we've seen before. <a href="https://www.tomsguide.com/phones/iphones/apples-foldable-iphone-ultra-just-leaked-in-new-photos-and-we-have-a-release-date-update">Dummy units show</a> a phone that is shorter and wider than a typical iPhone, and that's just the 5.4-inch cover display. The phone will unfold to reveal a 7.8-inch cover foldable display, which is a similar size and shape to the <a href="https://www.tomsguide.com/tablets/ipads/ipad-mini-7-review">iPad mini 7</a>.</p><p>Apple has apparently focussed on the durability of the Ultra, with an iPhone Air-style body made from titanium. Also rumored is a <a href="https://www.tomsguide.com/phones/foldable-iphone-just-tipped-for-revolutionary-liquid-metal-hinge">liquid metal hinge</a>, a structural glass mid-frame and <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-report-reveals-this-is-how-apple-is-killing-the-crease">ultra-thin display glass </a>for extra support on the foldable screen. This will also apparently have the added bonus of e<a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-heres-how-apple-is-reportedly-erasing-the-crease-for-its-foldable-phone">liminating the display crease</a>, though we've yet to see whether it's actually invisible or not.</p><p>In contrast to the iPhone 18 Pro Max, the Ultra is expected to be ultra-thin and lightweight, with around 4.5mm of thickness when unfolded. That's thinner than the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air</a>, which already felt like it was impossibly thin. Reports suggest it may weigh a similar amount as the Pro Max, despite the thin titanium design, which makes sense when you remember that this is effectively two phones in one.</p><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-performance"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Performance</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UHNuNim9UYH2mmGNTn3S4V" name="Apple-iPhone 18 Pro-A20-Pro_LIST" alt="Apple iPhone 18 Pro and the A20 Pro chip" src="https://cdn.mos.cms.futurecdn.net/UHNuNim9UYH2mmGNTn3S4V.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/Apple)</span></figcaption></figure><p>The iPhone Ultra may bear the Ultra moniker, but its performance may not be at the same level. Rumor has it that the foldable may come with an<a href="https://www.tomsguide.com/phones/iphones/iphone-fold-tipped-for-a20-pro-chip-apples-first-2nm-processor-to-power-new-foldable-phone"> A20 chipset</a>, compared to the<a href="https://www.tomsguide.com/phones/iphones/apple-a20-pro-chip-why-its-such-a-big-deal-for-the-iphone-ultra-and-iphone-18-pro-max"> A20 Pro on the iPhone 18 Pro and Pro Max</a>. However, it will still reportedly still be built on TSMC's 2nm process, which is expected to offer a 15% improvement in speed and 20% boost to efficiency.</p><p>The A20 Pro is also expected to be built on the 2nm process. This will apparently offer an 18% boost to performance power and 30% boost in energy efficiency. The new C2 modem is also expected to be included, which will reportedly add an additional energy saving onto the pile.</p><p>We should expect all three to come with 12GB of RAM, which is currently the minimum <a href="https://www.tomsguide.com/ai/apple-intelligence/some-ai-features-arent-available-on-older-iphones-but-are-you-actually-missing-that-much">needed to power some of the more intensive Siri AI features </a>that launched with iOS 27 — including the new dictation and expressive voices.</p><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-cameras"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Cameras</span></h3><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="7iBdM6RkBx9vY5PWZDt6ef" name="iPhone 18 pro edit" alt="iPhone 18 Pro mockup" src="https://cdn.mos.cms.futurecdn.net/7iBdM6RkBx9vY5PWZDt6ef.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: Aptenod / YouTube)</span></figcaption></figure><p>We're not expecting any major changes with the iPhone 18 Pro and Pro Max's cameras this year, which means we're likely to see the same trio of 48MP lenses covering the duties of primary, ultrawide and telephoto photography — plus a new 24MP Center Stage selfie camera. </p><p>However there are still some changes rumored, including the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-be-the-first-iphone-to-get-a-variable-aperture-why-that-matters">inclusion of variable aperture</a>, and an <a href="https://www.tomsguide.com/phones/the-rumors-might-be-wrong-iphone-18s-camera-control-could-evolve-not-end">adjustment to the Camera Control button</a>. Variable aperture would allow iPhone users to adjust the amount of light that enters the camera lens on the fly.  Newly incovered code references in the iOS 27 beta suggest that this is on the way, thanks to a new feature called <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-features-just-leaked-before-launch-including-aperture-based-image-corrections">"aperture based image corrections.</a>"</p><p>Various rumors have discussed the <a href="https://www.tomsguide.com/phones/the-rumors-might-be-wrong-iphone-18s-camera-control-could-evolve-not-end">possible changes to Camera Control</a>, including tweaking its capacitive capabilities and ditching the current design in favor of a mechanical button. Whether any of those predictions will come true or not isn't clear right now, but it's unlikely that any of those changes will affect the iPhone Ultra as much as they do the iPhone 18 Pro.</p><p>The main thing to note about the iPhone Ultra is that it only has two main cameras, which are expected to be 48MP main and ultrawide lenses. The lack of a dedicated telephoto lens is expected to be a point of contention among the die-hard iPhone fans likely to buy this device. Apple does offer limited "optical quality" digital zooming, but that's never going to replace the quality of a standalone zooming lens. Especially not with a 48MP main camera.</p><p>We're expecting to see two selfie cameras, both offering 24MP, but it's unclear whether they will utilize a hole-punch design or if they will be hidden under the display. My gut says the former, but renders and dummy units haven't been particularly forthcoming on this point. </p><p>Don't expect to see Face ID, though, since reports claim Apple is ditching Face ID in favor of a <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-could-feature-something-iphone-users-have-been-missing-for-years">Touch ID fingerprint sensor in the power button.</a></p><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-battery"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Battery</span></h3><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="aUJZxCfMMXC3m2nKLVB2dV" name="iPhone Fold final design 1" alt="iPhone Fold design" src="https://cdn.mos.cms.futurecdn.net/aUJZxCfMMXC3m2nKLVB2dV.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: Majin Bu on X)</span></figcaption></figure><p>Battery size has never been high on Apple's list of priorities, but that hasn't stopped the company offering some of the best phone battery life in recent years. The iPhone 18 Pro and Pro Max may take that a little further, by offering even larger batteries than we've seen before. In fact, the Pro Max could rise to as high as <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-tipped-to-be-heaviest-iphone-ever-heres-3-reasons-why-thats-a-good-thing">5,567 mAh</a>.</p><p>Combined with the extra efficiency of the A20 Pro chipset, and inherent optimization between every aspect of iPhone's Apple-made software and hardware we're expecting to see a <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-battery-rumors-it-could-be-a-record-breaking-year-for-apple">noticeable boost in battery life.</a></p><p>Those factors will also likely aid the iPhone Ultra, though the larger internal screen will likely eat up more battery life than you'd expect from a non-folding model. That's true of Samsung foldables anyway, with the 5,000 mAh Galaxy Z Fold 8 Ultra lasting a few hours less than a similar 5,000 mAh battery in the Galaxy S26 Ultra.</p><p>Reports have suggested we'll see a 4,833 mAh battery, which sits in the middle of the iPhone 18 Pro and 18 Pro Max's rumored battery packs. Though we'll have to wait and see how that might translate into real-world battery life. </p><p>Expect all three phones to come with MagSafe wireless charging, as well as varying degrees of fast wired charging — though since Apple is also pretty secretive about charging speeds we may have to wait before we can figure out just how fast each model is.</p><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-software"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Software</span></h3><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="K5SQbjBSv85JzgqYxoY5Lm" name="iPhone iOS 27 LIST_alt6" alt="iOS 27 icon shown on an iPhone screen" src="https://cdn.mos.cms.futurecdn.net/K5SQbjBSv85JzgqYxoY5Lm.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/Apple/Shutterstock)</span></figcaption></figure><p>Software is one of the few things that iPhone users don't need to worry about, since the general experience is the same regardless of which kind of phone you use. Often there are exclusive features to the Pro models, though that typically only affects the people who would want to buy the non Pro models like iPhone 18 or iPhone Air 2. I don't see Apple restricting the iPhone Ultra from accessing any premium features without a very good reason.</p><p>The software on the iPhone Ultra is going to have to be very different, on account of it essentially being an iPhone and iPad rolled into a single device. This isn't likely to affect the kind of features that are on offer, but it does mean iPhone Ultra's software is going to have to <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-is-coming-and-theres-already-evidence-of-its-existence-in-ios-27-beta">ensure apps can adapt to both screens</a> — and transition whatever you're doing when you switch to a different display.</p><p>Likewise it would be a missed opportunity if Apple didn't offer some kind of multitasking capabilities that weren't available (or not as useful) on regular iPhones. Sadly we haven't heard anything about that, so it remains a mystery as to how iPhone Ultra will let users have multiple app windows open at once.</p><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-outlook"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone 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:1510px;"><p class="vanilla-image-block" style="padding-top:56.29%;"><img id="USff7EuiMbLVdzsuAfG4hQ" name="iPhone Ultra" alt="iPhone Ultra against colorful background." src="https://cdn.mos.cms.futurecdn.net/USff7EuiMbLVdzsuAfG4hQ.jpg" mos="" align="middle" fullscreen="" width="1510" height="850" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The differences between iPhone 18 Pro and Pro Max are likely to be (mostly) superficial and based around the differing sizes of both phones. However, the fact that variable aperture may be exclusive to the Pro Max means there may be some things further differentiating the two devices.</p><p>However the iPhone Ultra is set to be unlike any other device Apple has produced so far, which throws a wrench into the usual decision-making process. The fact we've never seen a foldable iPhone before means it's difficult to get an idea of what to expect — and how the Ultra will differ from other foldables already on sale. </p><p>Choosing between them all is not quite a matter of ticking off the right boxes and seeing which phone fits your needs the best. You're signing up for a very different iPhone experience than most people are used to. It's also worth considering that the Ultra has been nerfed in some key areas, but the benefit of having a larger and more productive screen could help make up for it.</p><p>Then again, if you can't justify spending over $2,000 on a brand new smartphone, the point might be totally moot.</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-ultra-tipped-to-cost-usd2-000-and-still-lose-a-crucial-feature-im-weirdly-conflicted-about-it">iPhone Ultra tipped to cost $2,000 and still lose a crucial feature — I'm weirdly conflicted about it</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-battery-heres-what-we-know-so-far">iPhone Ultra battery: here's what we know so far</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-phones-inspiration-ifa-2026">iPhone 18 Pro, iPhone Ultra and beyond — here are the latest mobile features I saw at IFA 2026 that Apple needs to steal</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-all-the-last-minute-rumors-and-leaks</link>
                                                                            <description>
                            <![CDATA[ This year's iPhone launch is going to be totally different. Here's everything we know about all three phones — and how they compare to each other. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">s2wsuuaY9YPTtPhhNQqziS</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/SvPAakbKThKtFC7wM3gWdi-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 08 Sep 2026 15:25:36 +0000</pubDate>                                                                                                                                <updated>Tue, 08 Sep 2026 18:41:27 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ tom.pritchard@futurenet.com (Tom Pritchard) ]]></author>                    <dc:creator><![CDATA[ Tom Pritchard ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/biCewUkKfSA6QnT2HxVc3f.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/SvPAakbKThKtFC7wM3gWdi-1280-80.jpg">
                                                            <media:credit><![CDATA[Majin Bu on X / Future edited with Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Ultra vs iPhone 18 Pro Max]]></media:description>                                                            <media:text><![CDATA[iPhone Ultra vs iPhone 18 Pro Max]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Ultra vs iPhone 18 Pro Max]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/SvPAakbKThKtFC7wM3gWdi-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p><a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">Apple's Surprise and shine iPhone launch event</a> is going to be quite different, in that there are only three new iPhones being released instead of the usual five But those three newbies are all premium devices, and that makes deciding between them a much trickier endeavor.</p><p>With no standard <a href="https://www.tomsguide.com/phones/iphones/iphone-18-7-biggest-rumors-so-far">iPhone 18</a> on the horizon, it's not just a case of picking between the regular iPhone and one of two Pro-tier sizes</p><p>Prospective iPhone users that don't want to wait until<a href="https://www.tomsguide.com/phones/iphone-18-release-just-tipped-for-major-shakeup-heres-when-all-the-new-models-could-launch"> iPhone 18's early 2027 launch</a> need to decide whether they should stick with a Pro or go Ultra. But what exactly is different between all these new iPhones? Various leaks and rumors show that it's not quite as simple as one of them folds and the other two don't. </p><p>Here's what we know about <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a> vs <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-pro-max-5-big-upgrades-that-could-make-them-my-all-time-favorite-iphones">iPhone 18 Pro Max </a>vs <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra,</a> and what the differences between all three upcoming iPhones are expected to be. For more, check out our <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 September Event live blog</a> for all the last-minute leaks and the big news as its announced.</p><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-rumored-specs"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Rumored Specs</span></h3><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p><strong>iPhone 18 Pro</strong></p></th><th  ><p><strong>iPhone 18 Pro Max</strong></p></th><th  ><p><strong>iPhone Ultra</strong></p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p>$1,099 - $1,199</p></td><td  ><p>$1,199 – $1,399</p></td><td  ><p>$2,000 to $2,500</p></td></tr><tr><td class="firstcol " ><p><strong>Display</strong></p></td><td  ><p>6.3-inch OLED</p></td><td  ><p>6.9-inch OLED</p></td><td  ><p>7.8 inches / 5.4 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Processor</strong></p></td><td  ><p>A20 Pro</p></td><td  ><p>A20 Pro</p></td><td  ><p>A20</p></td></tr><tr><td class="firstcol " ><p><strong>RAM</strong></p></td><td  ><p>12GB</p></td><td  ><p>12GB</p></td><td  ><p>12GB</p></td></tr><tr><td class="firstcol " ><p><strong>Front Cameras</strong></p></td><td  ><p>18MP</p></td><td  ><p>18MP</p></td><td  ><p>24MP, 24MP</p></td></tr><tr><td class="firstcol " ><p><strong>Rear Cameras</strong></p></td><td  ><p>48MP main, 48MP ultrawide, 48MP Telephoto w/4x optical zoom</p></td><td  ><p>48MP main, 48MP ultrawide, 48MP Telephoto w/4x optical zoom</p></td><td  ><p>48MP, 48MP</p></td></tr><tr><td class="firstcol " ><p><strong>Battery</strong></p></td><td  ><p>5,288 mAh</p></td><td  ><p>5,321 mAh</p></td><td  ><p>4,883 mAh</p></td></tr><tr><td class="firstcol " ><p><strong>Colors</strong></p></td><td  ><p>Dark Cherry, Light Blue, and Silver-Gray</p></td><td  ><p>Dark Cherry, Light Blue, and Silver-Gray</p></td><td  ><p>Black, White/Silver</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-price-release-date"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Price & Release Date</span></h3><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="7iBdM6RkBx9vY5PWZDt6ef" name="iPhone 18 pro edit" alt="iPhone 18 Pro mockup" src="https://cdn.mos.cms.futurecdn.net/7iBdM6RkBx9vY5PWZDt6ef.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: Aptenod / YouTube)</span></figcaption></figure><p>Price will be a major sticking point with the next wave of iPhones, due to the fact that prices are almost certainly going up. iPhones have never been cheap, but the ongoing issues with <a href="https://www.tomsguide.com/computing/ram-price-crisis-2026-everything-you-need-to-know">RAMageddon</a> and the skyrocketing cost of both memory and storage means Apple's is all but certain to increase the price of entry. Especially after <a href="https://www.tomsguide.com/computing/macbooks/apple-price-hikes-are-official-heres-how-much-more-youll-pay-for-macbooks-and-ipads-now">raising prices of almost every product it sells </a>earlier this summer.</p><p>Analysts have predicted that the iPhone 18 Pro Max could be as much as $200 (or higher) more expensive than the <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">iPhone 17 Pro Max</a>. If that is the case, we could see the cost of <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-iphone-18-pro-prices-leak-days-before-apple-event-heres-my-final-bet-on-what-youll-pay">Apple's largest phone rise to over $1,400</a></p><p>Even if the price hike isn't that high, I'd be surprised if Apple didn't tack on an extra $100 to both iPhone 18 Pro and iPhone 18 Pro Max. In that instance both phones would start at $1,199 and $1,299, respectively. </p><p>iPhone Ultra is expected to be considerably more expensive than a non-folding iPhone, with rumors suggesting we could see a <a href="https://www.tomsguide.com/phones/iphones/usd1-299-iphone-18-pro-max-analyst-now-predicts-usd200-price-hike-for-apples-next-flagship-phone">starting price somewhere around $2,400 and $2,500</a>. However, recently <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-iphone-18-pro-prices-leak-days-before-apple-event-heres-my-final-bet-on-what-youll-pay">leaked Australian prices</a> suggest we could see a price closer to $1,999. While expensive, that would be a lot more palatable, especially since the $2,099 <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Samsung Galaxy Z Fold 8 Ultra</a> is already on sale.</p><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="xwKrhoCavwDLpAZfXJCkBh" name="iPhone Fold mockup 1" alt="iPhone Fold 3D printed mockup" src="https://cdn.mos.cms.futurecdn.net/xwKrhoCavwDLpAZfXJCkBh.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: Subsy @ MakerWorld)</span></figcaption></figure><p>As for availability, we don't expect any significant changes for the iPhone 18 Pros. Apple is a creature of habit, and pre-orders for new numbered iPhones typically begin the same week as the launch event. </p><p>With the Apple event on September 9, we would normally predict pre-orders would open on Friday September 11. Though it's predicted that Apple will want open pre-orders a day later on September 12 to avoid the anniversary of 9/11. The actual release date will likely be the following Friday, on September 18.</p><p>Things aren't quite so simple with the iPhone Ultra, due to various reports that Apple is struggling to produce enough units. No two sources seem to be able to agree on when the foldable iPhone will actually release, with some <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-delay-rumors-shot-down-in-new-report-now-apples-first-foldable-phone-may-launch-alongside-iphone-18-pro-after-all">saying it'll happen at the same time as iPhone 18 Pro</a>, and <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-delay-leak-right-after-samsungs-triumphant-galaxy-fold-8-launch-has-me-sick-of-waiting-for-apples-foldable">others claiming it'll be much later in the year</a>. </p><p>One recent report also suggested that a global launch is out of the question for the time being, since <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-is-apples-biggest-product-for-years-but-supply-chain-issues-mean-not-everyone-may-get-it-at-launch">Apple may stagger the release schedule in different regions</a> — starting with the U.S. The one thing there does seem to be consensus on is the fact that supply is likely to be limited. But with a price tag that high, it isn't likely that people will be rushing out to buy one.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ePaL2W"></div>                            </div>                            <script src="https://kwizly.com/embed/ePaL2W.js" async></script><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-design-display"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Design & 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:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AeiETujmXpR8qSnb9eKRrM" name="iPhone Fold edit 1" alt="iPhone Fold rendering" src="https://cdn.mos.cms.futurecdn.net/AeiETujmXpR8qSnb9eKRrM.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>We're not expecting any significant design changes for the iPhone 18 Pro or Pro Max, which means the two phones will probably look pretty similar to the iPhone 17 Pro and iPhone 17 Pro Max at first glance. In other words we should expect to see the same 6.3-inch and 6.9-inch displays, alongside the raised camera bar Apple refers to as the "forged plateau."</p><p> It's unclear if Apple will do anything to fix the <a href="https://www.tomsguide.com/phones/iphones/i-knew-better-than-to-carry-around-a-naked-phone-then-my-iphone-17-pro-max-met-the-asphalt">durability issues that affected</a> the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a> series. Multiple Tom's Guide employees were affected by "<a href="https://www.tomsguide.com/phones/iphones/iphone-17-scratchgate-ive-had-my-iphone-17-pro-for-over-a-week-and-its-already-scuffed">scratchgate</a>," as it was known, to varying degrees. We haven't heard rumors about this, though, so I wouldn't expect anything more than token changes to the exterior metal.</p><p>That said, we have heard rumors that the iPhone 18 Pro Max will be thicker and the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-tipped-to-be-heaviest-iphone-ever-heres-3-reasons-why-thats-a-good-thing">heaviest iPhone Apple has ever made,</a> clocking in at 240g/8.47oz. It's not clear why, but it's possible that a switch to stronger and heavier materials could account for some of the extra weight — alongside changes like larger batteries and the variable aperture camera lens</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2490px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="Gv7fyY2QJ4jPcPsj7so3fX" name="iPhone 18 Pro Max Macworld" alt="iPhone 18 Pro Max render" src="https://cdn.mos.cms.futurecdn.net/Gv7fyY2QJ4jPcPsj7so3fX.jpg" mos="" align="middle" fullscreen="" width="2490" height="1401" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Macworld/Tom's Guide)</span></figcaption></figure><p>The iPhone Ultra, on the other hand, is shaping up to be unlike any iPhone we've seen before. <a href="https://www.tomsguide.com/phones/iphones/apples-foldable-iphone-ultra-just-leaked-in-new-photos-and-we-have-a-release-date-update">Dummy units show</a> a phone that is shorter and wider than a typical iPhone, and that's just the 5.4-inch cover display. The phone will unfold to reveal a 7.8-inch cover foldable display, which is a similar size and shape to the <a href="https://www.tomsguide.com/tablets/ipads/ipad-mini-7-review">iPad mini 7</a>.</p><p>Apple has apparently focussed on the durability of the Ultra, with an iPhone Air-style body made from titanium. Also rumored is a <a href="https://www.tomsguide.com/phones/foldable-iphone-just-tipped-for-revolutionary-liquid-metal-hinge">liquid metal hinge</a>, a structural glass mid-frame and <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-report-reveals-this-is-how-apple-is-killing-the-crease">ultra-thin display glass </a>for extra support on the foldable screen. This will also apparently have the added bonus of e<a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-heres-how-apple-is-reportedly-erasing-the-crease-for-its-foldable-phone">liminating the display crease</a>, though we've yet to see whether it's actually invisible or not.</p><p>In contrast to the iPhone 18 Pro Max, the Ultra is expected to be ultra-thin and lightweight, with around 4.5mm of thickness when unfolded. That's thinner than the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air</a>, which already felt like it was impossibly thin. Reports suggest it may weigh a similar amount as the Pro Max, despite the thin titanium design, which makes sense when you remember that this is effectively two phones in one.</p><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-performance"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Performance</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UHNuNim9UYH2mmGNTn3S4V" name="Apple-iPhone 18 Pro-A20-Pro_LIST" alt="Apple iPhone 18 Pro and the A20 Pro chip" src="https://cdn.mos.cms.futurecdn.net/UHNuNim9UYH2mmGNTn3S4V.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/Apple)</span></figcaption></figure><p>The iPhone Ultra may bear the Ultra moniker, but its performance may not be at the same level. Rumor has it that the foldable may come with an<a href="https://www.tomsguide.com/phones/iphones/iphone-fold-tipped-for-a20-pro-chip-apples-first-2nm-processor-to-power-new-foldable-phone"> A20 chipset</a>, compared to the<a href="https://www.tomsguide.com/phones/iphones/apple-a20-pro-chip-why-its-such-a-big-deal-for-the-iphone-ultra-and-iphone-18-pro-max"> A20 Pro on the iPhone 18 Pro and Pro Max</a>. However, it will still reportedly still be built on TSMC's 2nm process, which is expected to offer a 15% improvement in speed and 20% boost to efficiency.</p><p>The A20 Pro is also expected to be built on the 2nm process. This will apparently offer an 18% boost to performance power and 30% boost in energy efficiency. The new C2 modem is also expected to be included, which will reportedly add an additional energy saving onto the pile.</p><p>We should expect all three to come with 12GB of RAM, which is currently the minimum <a href="https://www.tomsguide.com/ai/apple-intelligence/some-ai-features-arent-available-on-older-iphones-but-are-you-actually-missing-that-much">needed to power some of the more intensive Siri AI features </a>that launched with iOS 27 — including the new dictation and expressive voices.</p><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-cameras"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Cameras</span></h3><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="7iBdM6RkBx9vY5PWZDt6ef" name="iPhone 18 pro edit" alt="iPhone 18 Pro mockup" src="https://cdn.mos.cms.futurecdn.net/7iBdM6RkBx9vY5PWZDt6ef.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: Aptenod / YouTube)</span></figcaption></figure><p>We're not expecting any major changes with the iPhone 18 Pro and Pro Max's cameras this year, which means we're likely to see the same trio of 48MP lenses covering the duties of primary, ultrawide and telephoto photography — plus a new 24MP Center Stage selfie camera. </p><p>However there are still some changes rumored, including the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-be-the-first-iphone-to-get-a-variable-aperture-why-that-matters">inclusion of variable aperture</a>, and an <a href="https://www.tomsguide.com/phones/the-rumors-might-be-wrong-iphone-18s-camera-control-could-evolve-not-end">adjustment to the Camera Control button</a>. Variable aperture would allow iPhone users to adjust the amount of light that enters the camera lens on the fly.  Newly incovered code references in the iOS 27 beta suggest that this is on the way, thanks to a new feature called <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-features-just-leaked-before-launch-including-aperture-based-image-corrections">"aperture based image corrections.</a>"</p><p>Various rumors have discussed the <a href="https://www.tomsguide.com/phones/the-rumors-might-be-wrong-iphone-18s-camera-control-could-evolve-not-end">possible changes to Camera Control</a>, including tweaking its capacitive capabilities and ditching the current design in favor of a mechanical button. Whether any of those predictions will come true or not isn't clear right now, but it's unlikely that any of those changes will affect the iPhone Ultra as much as they do the iPhone 18 Pro.</p><p>The main thing to note about the iPhone Ultra is that it only has two main cameras, which are expected to be 48MP main and ultrawide lenses. The lack of a dedicated telephoto lens is expected to be a point of contention among the die-hard iPhone fans likely to buy this device. Apple does offer limited "optical quality" digital zooming, but that's never going to replace the quality of a standalone zooming lens. Especially not with a 48MP main camera.</p><p>We're expecting to see two selfie cameras, both offering 24MP, but it's unclear whether they will utilize a hole-punch design or if they will be hidden under the display. My gut says the former, but renders and dummy units haven't been particularly forthcoming on this point. </p><p>Don't expect to see Face ID, though, since reports claim Apple is ditching Face ID in favor of a <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-could-feature-something-iphone-users-have-been-missing-for-years">Touch ID fingerprint sensor in the power button.</a></p><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-battery"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Battery</span></h3><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="aUJZxCfMMXC3m2nKLVB2dV" name="iPhone Fold final design 1" alt="iPhone Fold design" src="https://cdn.mos.cms.futurecdn.net/aUJZxCfMMXC3m2nKLVB2dV.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: Majin Bu on X)</span></figcaption></figure><p>Battery size has never been high on Apple's list of priorities, but that hasn't stopped the company offering some of the best phone battery life in recent years. The iPhone 18 Pro and Pro Max may take that a little further, by offering even larger batteries than we've seen before. In fact, the Pro Max could rise to as high as <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-tipped-to-be-heaviest-iphone-ever-heres-3-reasons-why-thats-a-good-thing">5,567 mAh</a>.</p><p>Combined with the extra efficiency of the A20 Pro chipset, and inherent optimization between every aspect of iPhone's Apple-made software and hardware we're expecting to see a <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-battery-rumors-it-could-be-a-record-breaking-year-for-apple">noticeable boost in battery life.</a></p><p>Those factors will also likely aid the iPhone Ultra, though the larger internal screen will likely eat up more battery life than you'd expect from a non-folding model. That's true of Samsung foldables anyway, with the 5,000 mAh Galaxy Z Fold 8 Ultra lasting a few hours less than a similar 5,000 mAh battery in the Galaxy S26 Ultra.</p><p>Reports have suggested we'll see a 4,833 mAh battery, which sits in the middle of the iPhone 18 Pro and 18 Pro Max's rumored battery packs. Though we'll have to wait and see how that might translate into real-world battery life. </p><p>Expect all three phones to come with MagSafe wireless charging, as well as varying degrees of fast wired charging — though since Apple is also pretty secretive about charging speeds we may have to wait before we can figure out just how fast each model is.</p><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-software"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Software</span></h3><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="K5SQbjBSv85JzgqYxoY5Lm" name="iPhone iOS 27 LIST_alt6" alt="iOS 27 icon shown on an iPhone screen" src="https://cdn.mos.cms.futurecdn.net/K5SQbjBSv85JzgqYxoY5Lm.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/Apple/Shutterstock)</span></figcaption></figure><p>Software is one of the few things that iPhone users don't need to worry about, since the general experience is the same regardless of which kind of phone you use. Often there are exclusive features to the Pro models, though that typically only affects the people who would want to buy the non Pro models like iPhone 18 or iPhone Air 2. I don't see Apple restricting the iPhone Ultra from accessing any premium features without a very good reason.</p><p>The software on the iPhone Ultra is going to have to be very different, on account of it essentially being an iPhone and iPad rolled into a single device. This isn't likely to affect the kind of features that are on offer, but it does mean iPhone Ultra's software is going to have to <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-is-coming-and-theres-already-evidence-of-its-existence-in-ios-27-beta">ensure apps can adapt to both screens</a> — and transition whatever you're doing when you switch to a different display.</p><p>Likewise it would be a missed opportunity if Apple didn't offer some kind of multitasking capabilities that weren't available (or not as useful) on regular iPhones. Sadly we haven't heard anything about that, so it remains a mystery as to how iPhone Ultra will let users have multiple app windows open at once.</p><h3 class="article-body__section" id="section-iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-outlook"><span>iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone 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:1510px;"><p class="vanilla-image-block" style="padding-top:56.29%;"><img id="USff7EuiMbLVdzsuAfG4hQ" name="iPhone Ultra" alt="iPhone Ultra against colorful background." src="https://cdn.mos.cms.futurecdn.net/USff7EuiMbLVdzsuAfG4hQ.jpg" mos="" align="middle" fullscreen="" width="1510" height="850" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The differences between iPhone 18 Pro and Pro Max are likely to be (mostly) superficial and based around the differing sizes of both phones. However, the fact that variable aperture may be exclusive to the Pro Max means there may be some things further differentiating the two devices.</p><p>However the iPhone Ultra is set to be unlike any other device Apple has produced so far, which throws a wrench into the usual decision-making process. The fact we've never seen a foldable iPhone before means it's difficult to get an idea of what to expect — and how the Ultra will differ from other foldables already on sale. </p><p>Choosing between them all is not quite a matter of ticking off the right boxes and seeing which phone fits your needs the best. You're signing up for a very different iPhone experience than most people are used to. It's also worth considering that the Ultra has been nerfed in some key areas, but the benefit of having a larger and more productive screen could help make up for it.</p><p>Then again, if you can't justify spending over $2,000 on a brand new smartphone, the point might be totally moot.</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-ultra-tipped-to-cost-usd2-000-and-still-lose-a-crucial-feature-im-weirdly-conflicted-about-it">iPhone Ultra tipped to cost $2,000 and still lose a crucial feature — I'm weirdly conflicted about it</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-battery-heres-what-we-know-so-far">iPhone Ultra battery: here's what we know so far</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-phones-inspiration-ifa-2026">iPhone 18 Pro, iPhone Ultra and beyond — here are the latest mobile features I saw at IFA 2026 that Apple needs to steal</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone 18 Pro camera features just leaked before launch — including ‘aperture based image corrections’ ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max </a>isn't going to be revealed until the <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" target="_blank">Apple event</a> tomorrow, but a bunch of possible camera features just leaked, and it comes from the most trustworthy source of all: Apple's own code. Specifically the code for the iOS 27 beta, with a deep dive from <a href="https://www.macrumors.com/2026/09/07/five-iphone-18-pro-camera-features-seemingly-leak/" target="_blank">Macrumors</a> forum member <a href="https://forums.macrumors.com/threads/five-ios-27-camera-features-apple-hasnt-shown-yet.2488539/" target="_blank">pdfu</a> uncovering references to five new camera features.</p><p>It's unclear whether these features are destined to arrive with the iPhone 18 Pro this week, or whether they'll be added as part of a future software update. But some of them do seem to suggest that the rumors of a <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-rumored-to-get-variable-aperture-lens-on-main-camera-why-that-matters">variable aperture lens</a> may be true after all.</p><p>Here are the five referenced features that could be coming to iPhone 18 Pro and Pro Max:</p><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="TBYraHW2jopiVsMRak8QgV" name="iPhone 18 Pro colors Weibo" alt="iPhone 18 Pro colors: purple, brown, burgundy" src="https://cdn.mos.cms.futurecdn.net/TBYraHW2jopiVsMRak8QgV.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><strong>Exposure scopes: </strong>This feature will apparently allow the camera app to display a waveform or histogram to help users gauge exposure levels when taking photos. </p><p>A histogram is capable of showing how much of the image is too dark or bright, as well as everything in between. A waveform is capable of displaying similar information, but makes it a lot easier to identify specific areas of the image in the process.</p><p><strong>Focus peaking and highlight warnings: </strong>These two features add an overlay featuring new information on the camera screen. Focus peaking highlights objects that are in the sharpest focus, while a separate overlay can warn you when parts of the photo are being overexposed. </p><p>Apparently these warnings will be able to utilize solid or pulsing colors, diagonal stripes and checkerboard pattern options.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2272px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="KwwUMqX3DXXqj5wDYpEhRo" name="Screenshot 2026-01-20 at 12.43.51" alt="iPhone 18 Pro leak-based render, showing the rear cameras" src="https://cdn.mos.cms.futurecdn.net/KwwUMqX3DXXqj5wDYpEhRo.jpg" mos="" align="middle" fullscreen="" width="2272" height="1278" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Front Page Tech)</span></figcaption></figure><p><strong>Repeated self-timer shots: </strong>Currently the iPhone camera app only lets you take a single timed shot at a time, but code references suggest the option to repeat the process is on the way. </p><p>In this instance it won't be a case of multiple shots being taken back to back, instead the countdown will restart as soon as the first photo is taken — giving you time to repose without having to set the whole process up again.</p><p><strong>Manual focus: </strong>A mainstay on standalone cameras, and one that Apple has attempted before in iOS 26. Apple removed the focus slider in the iOS 27 beta, but it looks like it might be coming back. </p><p>The focus code is there, but it's seemingly being restricted to devices that ship with iOS 27 — which means it'll be restricted to the newest iPhones and not devices that have been released before.</p><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="7iBdM6RkBx9vY5PWZDt6ef" name="iPhone 18 pro edit" alt="iPhone 18 Pro mockup" src="https://cdn.mos.cms.futurecdn.net/7iBdM6RkBx9vY5PWZDt6ef.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: Aptenod / YouTube)</span></figcaption></figure><p><strong>Aperture-based image correction: </strong>This one appears to be a change to the way iPhones process photos, and that could be more directly tied to the variable aperture lens. </p><p>This feature will apparently let iOS 27 adjust lens corrections based on the aperture setting, and blends four different reference points to smooth out the result after the fact.</p><p>The first three features could apply to any iPhone running iOS 27, but the latter two are the most interesting. Obviously aperture on iPhone cameras doesn't change that much between lenses, though it's not as though they're all identical. </p><p>However, the fact that the iPhone 18 Pro Max is expected to have variable aperture would make aperture-based corrections a much more important feature — especially if you can customize it, rather than sticking with pre-set aperture settings. Likewise, the fact that the manual focus is seemingly limited to new iPhones means there could be a big focus on new camera capabilities — even if the hardware is staying more or less the same.</p><p>None of these features are accessible in the current version of the iOS 27 beta, which suggests they won't be landing with the public release of the software. So we'll have to wait until the Surprise and shine event to find out whether they're exclusive to the iPhone 18 Pro and Ultra, or if they may be coming to a future iOS 27 update.</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/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">Apple iPhone 18 event — all the new products expected to launch at the 'Surprise and shine' event</a></li><li><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 'Surprise and Shine' event live blog — iPhone Ultra, iPhone 18 Pro, Apple Watch 12 and all the last-minute leaks</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-phones-inspiration-ifa-2026">iPhone 18 Pro, iPhone Ultra and beyond — here are the latest mobile features I saw at IFA 2026 that Apple needs to steal</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-features-just-leaked-before-launch-including-aperture-based-image-corrections</link>
                                                                            <description>
                            <![CDATA[ iPhone 18 Pro Max's variable aperture is looking even more likely thanks to a code leak from the latest iOS 27 beta ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">Y2haiM4Ehqm2Gbn4x7UZNK</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/4zbVNxFtCw8JYgt53YYMKL-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 08 Sep 2026 12:24:39 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ tom.pritchard@futurenet.com (Tom Pritchard) ]]></author>                    <dc:creator><![CDATA[ Tom Pritchard ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/biCewUkKfSA6QnT2HxVc3f.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/4zbVNxFtCw8JYgt53YYMKL-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iphone 17 pro max in red.]]></media:description>                                                            <media:text><![CDATA[iphone 17 pro max in red.]]></media:text>
                                <media:title type="plain"><![CDATA[iphone 17 pro max in red.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/4zbVNxFtCw8JYgt53YYMKL-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max </a>isn't going to be revealed until the <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" target="_blank">Apple event</a> tomorrow, but a bunch of possible camera features just leaked, and it comes from the most trustworthy source of all: Apple's own code. Specifically the code for the iOS 27 beta, with a deep dive from <a href="https://www.macrumors.com/2026/09/07/five-iphone-18-pro-camera-features-seemingly-leak/" target="_blank">Macrumors</a> forum member <a href="https://forums.macrumors.com/threads/five-ios-27-camera-features-apple-hasnt-shown-yet.2488539/" target="_blank">pdfu</a> uncovering references to five new camera features.</p><p>It's unclear whether these features are destined to arrive with the iPhone 18 Pro this week, or whether they'll be added as part of a future software update. But some of them do seem to suggest that the rumors of a <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-rumored-to-get-variable-aperture-lens-on-main-camera-why-that-matters">variable aperture lens</a> may be true after all.</p><p>Here are the five referenced features that could be coming to iPhone 18 Pro and Pro Max:</p><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="TBYraHW2jopiVsMRak8QgV" name="iPhone 18 Pro colors Weibo" alt="iPhone 18 Pro colors: purple, brown, burgundy" src="https://cdn.mos.cms.futurecdn.net/TBYraHW2jopiVsMRak8QgV.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><strong>Exposure scopes: </strong>This feature will apparently allow the camera app to display a waveform or histogram to help users gauge exposure levels when taking photos. </p><p>A histogram is capable of showing how much of the image is too dark or bright, as well as everything in between. A waveform is capable of displaying similar information, but makes it a lot easier to identify specific areas of the image in the process.</p><p><strong>Focus peaking and highlight warnings: </strong>These two features add an overlay featuring new information on the camera screen. Focus peaking highlights objects that are in the sharpest focus, while a separate overlay can warn you when parts of the photo are being overexposed. </p><p>Apparently these warnings will be able to utilize solid or pulsing colors, diagonal stripes and checkerboard pattern options.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2272px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="KwwUMqX3DXXqj5wDYpEhRo" name="Screenshot 2026-01-20 at 12.43.51" alt="iPhone 18 Pro leak-based render, showing the rear cameras" src="https://cdn.mos.cms.futurecdn.net/KwwUMqX3DXXqj5wDYpEhRo.jpg" mos="" align="middle" fullscreen="" width="2272" height="1278" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Front Page Tech)</span></figcaption></figure><p><strong>Repeated self-timer shots: </strong>Currently the iPhone camera app only lets you take a single timed shot at a time, but code references suggest the option to repeat the process is on the way. </p><p>In this instance it won't be a case of multiple shots being taken back to back, instead the countdown will restart as soon as the first photo is taken — giving you time to repose without having to set the whole process up again.</p><p><strong>Manual focus: </strong>A mainstay on standalone cameras, and one that Apple has attempted before in iOS 26. Apple removed the focus slider in the iOS 27 beta, but it looks like it might be coming back. </p><p>The focus code is there, but it's seemingly being restricted to devices that ship with iOS 27 — which means it'll be restricted to the newest iPhones and not devices that have been released before.</p><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="7iBdM6RkBx9vY5PWZDt6ef" name="iPhone 18 pro edit" alt="iPhone 18 Pro mockup" src="https://cdn.mos.cms.futurecdn.net/7iBdM6RkBx9vY5PWZDt6ef.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: Aptenod / YouTube)</span></figcaption></figure><p><strong>Aperture-based image correction: </strong>This one appears to be a change to the way iPhones process photos, and that could be more directly tied to the variable aperture lens. </p><p>This feature will apparently let iOS 27 adjust lens corrections based on the aperture setting, and blends four different reference points to smooth out the result after the fact.</p><p>The first three features could apply to any iPhone running iOS 27, but the latter two are the most interesting. Obviously aperture on iPhone cameras doesn't change that much between lenses, though it's not as though they're all identical. </p><p>However, the fact that the iPhone 18 Pro Max is expected to have variable aperture would make aperture-based corrections a much more important feature — especially if you can customize it, rather than sticking with pre-set aperture settings. Likewise, the fact that the manual focus is seemingly limited to new iPhones means there could be a big focus on new camera capabilities — even if the hardware is staying more or less the same.</p><p>None of these features are accessible in the current version of the iOS 27 beta, which suggests they won't be landing with the public release of the software. So we'll have to wait until the Surprise and shine event to find out whether they're exclusive to the iPhone 18 Pro and Ultra, or if they may be coming to a future iOS 27 update.</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/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">Apple iPhone 18 event — all the new products expected to launch at the 'Surprise and shine' event</a></li><li><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 'Surprise and Shine' event live blog — iPhone Ultra, iPhone 18 Pro, Apple Watch 12 and all the last-minute leaks</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-phones-inspiration-ifa-2026">iPhone 18 Pro, iPhone Ultra and beyond — here are the latest mobile features I saw at IFA 2026 that Apple needs to steal</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple A20 Pro chip: why it’s such a big deal for the iPhone Ultra and iPhone 18 Pro Max ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Every silicon cycle promises incremental gains in speed and efficiency, but Apple’s upcoming <a href="https://www.tomsguide.com/phones/iphones/iphone-18-countdown-starts-now-5-rumored-upgrades-apple-could-be-giving-its-pro-models">A20 Pro</a> could mark a genuine architectural leap. As we head into 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> this week in Cupertino, all eyes are locked on the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max</a> — and specifically, whether the shift to TSMC’s rumored 2-nanometer process lives up to expectations.</p><p>Across the board, this jump is poised to deliver substantial gains in throughput and thermal efficiency, both of which will be pivotal if Apple introduces its first foldable phone. Still, before crowning it a game-changer, the A20 Pro has to prove its worth under real-world workloads.</p><h2 id="iphone-18-pro-max-could-crush-the-flagship-competition">iPhone 18 Pro Max could crush the flagship competition</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2p68W9mHAAZd9qESYGbtvV" name="iPhone 17 Pro Max-22" alt="iPhone 17 Pro Max" src="https://cdn.mos.cms.futurecdn.net/2p68W9mHAAZd9qESYGbtvV.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Both the iPhone 18 Pro and 18 Pro Max are tipped to gain the A20 Pro, but the larger flagship will naturally face greater scrutiny when going head-to-head with the <a href="https://www.tomsguide.com/us/best-android-phones,review-6051.html">best Android phones</a> around. I’m talking about marquee devices I’ve tested, like the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review">Galaxy S26 Ultra</a> and <a href="https://www.tomsguide.com/phones/oneplus-phones/oneplus-15-review">OnePlus 15</a>, which have already proven their muscle thanks to Qualcomm’s <a href="https://www.tomsguide.com/phones/android-phones/qualcomms-snapdragon-8-elite-gen-5-promises-big-performance-and-ai-upgrades-and-we-could-see-them-in-the-galaxy-s26-ultra">Snapdragon 8 Elite Gen 5 chipset</a>.</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Chipset</strong></p></td><td  ><p><strong>Geekbench 6 (single-core/multi-core score)</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro Max</strong></p></td><td  ><p>A20 Pro (rumored)</p></td><td  ><p>TBD</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max</strong></p></td><td  ><p>A19 Pro</p></td><td  ><p>4,120 / 11,850</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro</strong></p></td><td  ><p>A20 Pro (rumored)</p></td><td  ><p>TBD</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro</strong></p></td><td  ><p>A19 Pro</p></td><td  ><p>3,871 / 9,968</p></td></tr><tr><td class="firstcol " ><p><strong>Galaxy S26 Ultra</strong></p></td><td  ><p>Snapdragon 8 Elite Gen 5</p></td><td  ><p>3,785 / 11,563</p></td></tr><tr><td class="firstcol " ><p><strong>OnePlus 15</strong></p></td><td  ><p>Snapdragon 8 Elite Gen 5</p></td><td  ><p>3,618 / 11,116</p></td></tr><tr><td class="firstcol " ><p><strong>Pixel 11 Pro XL</strong></p></td><td  ><p>Tensor G6</p></td><td  ><p>2,713 / 7,453</p></td></tr></tbody></table></div><p>The bar for the A20 Pro is undeniably high, especially considering the outgoing iPhone 17 Pro Max already leads the pack with staggering <strong>4,120 single-core and 11,850 multi-core scores </strong>— comfortably ahead of both the Galaxy S26 Ultra and OnePlus 15. Meanwhile, despite being less than a month old, the Tensor G6 powering the <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-pro-xl-review">Pixel 11 Pro XL</a> falls flat in comparison.</p><p>For the A20 Pro to truly assert itself as the dominant leader, it'll need to push single-core speeds well beyond the 4,500 mark and stretch multi-core past 13,000. Reaching those figures would be impressive on its own, but imagine if the A20 Pro actually surpasses those estimates. Doing so would point the spotlight on Qualcomm, putting even more pressure on its subsequent flagship silicon to keep pace with next year's Android flagships.</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Chipset</strong></p></td><td  ><p><strong>3DMark Wild Life Unlimited (Score / FPS)</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro Max</strong></p></td><td  ><p>A20 Pro (rumored)</p></td><td  ><p>TBD</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max</strong></p></td><td  ><p>A19 Pro</p></td><td  ><p>26,637 / 159.53 fps</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro</strong></p></td><td  ><p>A20 Pro (rumored)</p></td><td  ><p>TBD</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro</strong></p></td><td  ><p>A19 Pro</p></td><td  ><p>26,451 / 158.37 fps</p></td></tr><tr><td class="firstcol " ><p><strong>Galaxy S26 Ultra</strong></p></td><td  ><p>Snapdragon 8 Elite Gen 5</p></td><td  ><p>29,937 / 179.27 fps</p></td></tr><tr><td class="firstcol " ><p><strong>OnePlus 15</strong></p></td><td  ><p>Snapdragon 8 Elite Gen 5</p></td><td  ><p>29,029 / 173.83 fps</p></td></tr><tr><td class="firstcol " ><p><strong>Pixel 11 Pro XL</strong></p></td><td  ><p>Tensor G6</p></td><td  ><p>14,465 / 86.62 fps</p></td></tr></tbody></table></div><p>While Apple has traditionally proven successful in Geekbench, graphics performance has become Qualcomm’s bread and butter — and the 3DMark numbers above show the uphill battle facing the iPhone 18 Pro Max. The Snapdragon 8 Elite Gen 5 currently holds the graphical crown, with the Galaxy S26 Ultra leading the charge at 29,937 (179.27 fps) and the OnePlus 15 not far behind at 29,029 (173.83 fps). Meanwhile, the current iPhone 17 Pro Max tops out at 26,637 (159.53 fps) — a figure closely mirrored by the smaller iPhone 17 Pro at 26,451 (158.37 fps).</p><p>For the iPhone 18 Pro Max and its rumored A20 Pro chip to snatch the crown back from Samsung and OnePlus, a rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-tipped-to-be-heaviest-iphone-ever-heres-3-reasons-why-thats-a-good-thing">stainless steel vapor chamber</a> could be what ultimately gives it the edge. Sure, this cooling system is reportedly going to cause the iPhone 18 Pro Max to balloon a bit in weight, but it might be a compromise well worth making.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eBEd0X"></div>                            </div>                            <script src="https://kwizly.com/embed/eBEd0X.js" async></script><h2 id="iphone-ultra-will-be-more-demanding">iPhone Ultra will be more demanding</h2><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="rFoptYkFTJF2yfL5s5dJue" name="iPhone Ultra.Matt Talks Tech.YouTube-2" alt="iPhone Ultra render shown partially open" src="https://cdn.mos.cms.futurecdn.net/rFoptYkFTJF2yfL5s5dJue.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: Matt Talks Tech/YouTube)</span></figcaption></figure><p>While the iPhone 18 Pro Max reaps clear gaming and computational benefits, the A20 Pro is even more crucial for another device in Apple's pipeline: the foldable iPhone Ultra.</p><p>Notebook-style foldables present engineering challenges of their own, requiring far more background management to deliver a seamless phone-meets-tablet experience. The rumored 7.8-inch main display of the iPhone Ultra should be a major test all on its own, as both the software and processor attempt to handle dynamic app scaling.</p><p>I’ve said this countless times by now, but <a href="https://www.tomsguide.com/phones/iphones/ive-tested-every-major-foldable-phone-this-year-and-the-iphone-ultra-can-beat-them-all-with-this-one-killer-feature">app continuity will be the defining, make-or-break test for Apple's foldable</a>. Seamlessly moving an active app from an external cover screen to an expansive inner panel demands instantaneous re-rendering, so the A20 Pro's processing power can't stutter.</p><p>This foldable will be far more demanding than the standard iPhone 18 Pro Max, particularly if it aims to offer true side-by-side app multitasking. Heavy workflows — like streaming a video call while editing a spreadsheet and running Apple Intelligence models in the background — place immense strain on system resources. Apple can't afford to overlook the power efficiency of the A20 Pro here, or the foldable risks facing the same issues that plague Android foldables I’ve tested, like the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> and <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold</a>.</p><p>For Apple to convince power users that a foldable iPhone is a legitimate desktop-class productivity powerhouse, the software experience must be flawless. With the A20 Pro under the hood, Apple could ensure that dynamic split-screen layouts, drag-and-drop multitasking, and on-the-fly display transitions feel just as responsive as interacting with a single app on a standard screen.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/phones/motorola-phones/motorola-2026-foldables-compared-book-style-powerhouse-vs-elite-compact-flip"><strong>Motorola 2026 foldables compared: book-style powerhouse vs elite compact flip</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/ive-tested-every-major-foldable-phone-this-year-and-the-iphone-ultra-can-beat-them-all-with-this-one-killer-feature"><strong>I've tested every major foldable phone this year, and the iPhone Ultra can beat them all with this one killer feature</strong></a></li><li><a href="https://www.tomsguide.com/phones/android-phones/i-pushed-the-latest-foldables-from-samsung-motorola-and-honor-into-a-no-mercy-battle-royale-and-there-can-be-only-one-winner"><strong>I pushed the latest foldables from Samsung, Motorola and Honor into a no‑mercy battle royale and there was one clear winner</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/apple-a20-pro-chip-why-its-such-a-big-deal-for-the-iphone-ultra-and-iphone-18-pro-max</link>
                                                                            <description>
                            <![CDATA[ The A20 Pro could give Apple the processing muscle and thermal efficiency it needs to outpace flagship Android rivals with the iPhone 18 Pro Max and iPhone Ultra. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">kNZU5pdZrAFzFoF3AXhfpT</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/UHNuNim9UYH2mmGNTn3S4V-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 07 Sep 2026 04:30:00 +0000</pubDate>                                                                                                                                <updated>Mon, 07 Sep 2026 08:21:20 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/UHNuNim9UYH2mmGNTn3S4V-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide/Apple]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple iPhone 18 Pro and the A20 Pro chip]]></media:description>                                                            <media:text><![CDATA[Apple iPhone 18 Pro and the A20 Pro chip]]></media:text>
                                <media:title type="plain"><![CDATA[Apple iPhone 18 Pro and the A20 Pro chip]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/UHNuNim9UYH2mmGNTn3S4V-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Every silicon cycle promises incremental gains in speed and efficiency, but Apple’s upcoming <a href="https://www.tomsguide.com/phones/iphones/iphone-18-countdown-starts-now-5-rumored-upgrades-apple-could-be-giving-its-pro-models">A20 Pro</a> could mark a genuine architectural leap. As we head into 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> this week in Cupertino, all eyes are locked on the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max</a> — and specifically, whether the shift to TSMC’s rumored 2-nanometer process lives up to expectations.</p><p>Across the board, this jump is poised to deliver substantial gains in throughput and thermal efficiency, both of which will be pivotal if Apple introduces its first foldable phone. Still, before crowning it a game-changer, the A20 Pro has to prove its worth under real-world workloads.</p><h2 id="iphone-18-pro-max-could-crush-the-flagship-competition">iPhone 18 Pro Max could crush the flagship competition</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2p68W9mHAAZd9qESYGbtvV" name="iPhone 17 Pro Max-22" alt="iPhone 17 Pro Max" src="https://cdn.mos.cms.futurecdn.net/2p68W9mHAAZd9qESYGbtvV.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Both the iPhone 18 Pro and 18 Pro Max are tipped to gain the A20 Pro, but the larger flagship will naturally face greater scrutiny when going head-to-head with the <a href="https://www.tomsguide.com/us/best-android-phones,review-6051.html">best Android phones</a> around. I’m talking about marquee devices I’ve tested, like the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review">Galaxy S26 Ultra</a> and <a href="https://www.tomsguide.com/phones/oneplus-phones/oneplus-15-review">OnePlus 15</a>, which have already proven their muscle thanks to Qualcomm’s <a href="https://www.tomsguide.com/phones/android-phones/qualcomms-snapdragon-8-elite-gen-5-promises-big-performance-and-ai-upgrades-and-we-could-see-them-in-the-galaxy-s26-ultra">Snapdragon 8 Elite Gen 5 chipset</a>.</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Chipset</strong></p></td><td  ><p><strong>Geekbench 6 (single-core/multi-core score)</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro Max</strong></p></td><td  ><p>A20 Pro (rumored)</p></td><td  ><p>TBD</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max</strong></p></td><td  ><p>A19 Pro</p></td><td  ><p>4,120 / 11,850</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro</strong></p></td><td  ><p>A20 Pro (rumored)</p></td><td  ><p>TBD</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro</strong></p></td><td  ><p>A19 Pro</p></td><td  ><p>3,871 / 9,968</p></td></tr><tr><td class="firstcol " ><p><strong>Galaxy S26 Ultra</strong></p></td><td  ><p>Snapdragon 8 Elite Gen 5</p></td><td  ><p>3,785 / 11,563</p></td></tr><tr><td class="firstcol " ><p><strong>OnePlus 15</strong></p></td><td  ><p>Snapdragon 8 Elite Gen 5</p></td><td  ><p>3,618 / 11,116</p></td></tr><tr><td class="firstcol " ><p><strong>Pixel 11 Pro XL</strong></p></td><td  ><p>Tensor G6</p></td><td  ><p>2,713 / 7,453</p></td></tr></tbody></table></div><p>The bar for the A20 Pro is undeniably high, especially considering the outgoing iPhone 17 Pro Max already leads the pack with staggering <strong>4,120 single-core and 11,850 multi-core scores </strong>— comfortably ahead of both the Galaxy S26 Ultra and OnePlus 15. Meanwhile, despite being less than a month old, the Tensor G6 powering the <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-pro-xl-review">Pixel 11 Pro XL</a> falls flat in comparison.</p><p>For the A20 Pro to truly assert itself as the dominant leader, it'll need to push single-core speeds well beyond the 4,500 mark and stretch multi-core past 13,000. Reaching those figures would be impressive on its own, but imagine if the A20 Pro actually surpasses those estimates. Doing so would point the spotlight on Qualcomm, putting even more pressure on its subsequent flagship silicon to keep pace with next year's Android flagships.</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Chipset</strong></p></td><td  ><p><strong>3DMark Wild Life Unlimited (Score / FPS)</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro Max</strong></p></td><td  ><p>A20 Pro (rumored)</p></td><td  ><p>TBD</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max</strong></p></td><td  ><p>A19 Pro</p></td><td  ><p>26,637 / 159.53 fps</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro</strong></p></td><td  ><p>A20 Pro (rumored)</p></td><td  ><p>TBD</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro</strong></p></td><td  ><p>A19 Pro</p></td><td  ><p>26,451 / 158.37 fps</p></td></tr><tr><td class="firstcol " ><p><strong>Galaxy S26 Ultra</strong></p></td><td  ><p>Snapdragon 8 Elite Gen 5</p></td><td  ><p>29,937 / 179.27 fps</p></td></tr><tr><td class="firstcol " ><p><strong>OnePlus 15</strong></p></td><td  ><p>Snapdragon 8 Elite Gen 5</p></td><td  ><p>29,029 / 173.83 fps</p></td></tr><tr><td class="firstcol " ><p><strong>Pixel 11 Pro XL</strong></p></td><td  ><p>Tensor G6</p></td><td  ><p>14,465 / 86.62 fps</p></td></tr></tbody></table></div><p>While Apple has traditionally proven successful in Geekbench, graphics performance has become Qualcomm’s bread and butter — and the 3DMark numbers above show the uphill battle facing the iPhone 18 Pro Max. The Snapdragon 8 Elite Gen 5 currently holds the graphical crown, with the Galaxy S26 Ultra leading the charge at 29,937 (179.27 fps) and the OnePlus 15 not far behind at 29,029 (173.83 fps). Meanwhile, the current iPhone 17 Pro Max tops out at 26,637 (159.53 fps) — a figure closely mirrored by the smaller iPhone 17 Pro at 26,451 (158.37 fps).</p><p>For the iPhone 18 Pro Max and its rumored A20 Pro chip to snatch the crown back from Samsung and OnePlus, a rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-tipped-to-be-heaviest-iphone-ever-heres-3-reasons-why-thats-a-good-thing">stainless steel vapor chamber</a> could be what ultimately gives it the edge. Sure, this cooling system is reportedly going to cause the iPhone 18 Pro Max to balloon a bit in weight, but it might be a compromise well worth making.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eBEd0X"></div>                            </div>                            <script src="https://kwizly.com/embed/eBEd0X.js" async></script><h2 id="iphone-ultra-will-be-more-demanding">iPhone Ultra will be more demanding</h2><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="rFoptYkFTJF2yfL5s5dJue" name="iPhone Ultra.Matt Talks Tech.YouTube-2" alt="iPhone Ultra render shown partially open" src="https://cdn.mos.cms.futurecdn.net/rFoptYkFTJF2yfL5s5dJue.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: Matt Talks Tech/YouTube)</span></figcaption></figure><p>While the iPhone 18 Pro Max reaps clear gaming and computational benefits, the A20 Pro is even more crucial for another device in Apple's pipeline: the foldable iPhone Ultra.</p><p>Notebook-style foldables present engineering challenges of their own, requiring far more background management to deliver a seamless phone-meets-tablet experience. The rumored 7.8-inch main display of the iPhone Ultra should be a major test all on its own, as both the software and processor attempt to handle dynamic app scaling.</p><p>I’ve said this countless times by now, but <a href="https://www.tomsguide.com/phones/iphones/ive-tested-every-major-foldable-phone-this-year-and-the-iphone-ultra-can-beat-them-all-with-this-one-killer-feature">app continuity will be the defining, make-or-break test for Apple's foldable</a>. Seamlessly moving an active app from an external cover screen to an expansive inner panel demands instantaneous re-rendering, so the A20 Pro's processing power can't stutter.</p><p>This foldable will be far more demanding than the standard iPhone 18 Pro Max, particularly if it aims to offer true side-by-side app multitasking. Heavy workflows — like streaming a video call while editing a spreadsheet and running Apple Intelligence models in the background — place immense strain on system resources. Apple can't afford to overlook the power efficiency of the A20 Pro here, or the foldable risks facing the same issues that plague Android foldables I’ve tested, like the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> and <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold</a>.</p><p>For Apple to convince power users that a foldable iPhone is a legitimate desktop-class productivity powerhouse, the software experience must be flawless. With the A20 Pro under the hood, Apple could ensure that dynamic split-screen layouts, drag-and-drop multitasking, and on-the-fly display transitions feel just as responsive as interacting with a single app on a standard screen.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/phones/motorola-phones/motorola-2026-foldables-compared-book-style-powerhouse-vs-elite-compact-flip"><strong>Motorola 2026 foldables compared: book-style powerhouse vs elite compact flip</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/ive-tested-every-major-foldable-phone-this-year-and-the-iphone-ultra-can-beat-them-all-with-this-one-killer-feature"><strong>I've tested every major foldable phone this year, and the iPhone Ultra can beat them all with this one killer feature</strong></a></li><li><a href="https://www.tomsguide.com/phones/android-phones/i-pushed-the-latest-foldables-from-samsung-motorola-and-honor-into-a-no-mercy-battle-royale-and-there-can-be-only-one-winner"><strong>I pushed the latest foldables from Samsung, Motorola and Honor into a no‑mercy battle royale and there was one clear winner</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone 18 Pro Max battery rumors: it could be a record-breaking year for Apple ]]></title>
                                                                                                <dc:content><![CDATA[ <p>When I put the <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">iPhone 17 Pro Max</a> through our <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-battery-life-test-results-are-in-this-blew-us-away">Tom’s Guide battery test last year</a>, the results were nothing short of impressive. The flagship logged massive endurance gains over its predecessor, earning easy spots among our <a href="https://www.tomsguide.com/us/smartphones-best-battery-life,review-2857.html">best phone battery life</a> contenders. Yet, those marks will likely take a back seat to what's coming in the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max</a>.</p><p>If recent iPhone 18 Pro Max battery rumors hold up, last year’s benchmark numbers may end up looking like modest stepping stones. We could be looking at a record-breaking generation for Apple’s premier flagship. While reports point to a tangible capacity increase, that only tells part of the story.</p><p>The real secret weapon lies beneath the glass — centered on a next-generation silicon architecture tipped to redefine overall efficiency.</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/rQHEN3kngZo" allowfullscreen></iframe></div></div><h2 id="a-larger-battery-is-a-good-foundation">A larger battery is a good foundation</h2><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="NUTShzQj5MbSQ7h8SLWLoQ" name="iPhone 18 Pro Max red" alt="iPhone 18 Pro Max dummy unit in dark cherry" src="https://cdn.mos.cms.futurecdn.net/NUTShzQj5MbSQ7h8SLWLoQ.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: Unbox Therapy)</span></figcaption></figure><p>Back in July, I covered leaked <a href="https://weibo.com/6048569942/5316883085788374" target="_blank">regulatory filings</a> pointing to a notable capacity upgrade for the iPhone 18 Pro Max. While I initially scoffed at early claims that it might be the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-tipped-to-be-heaviest-iphone-ever-heres-3-reasons-why-thats-a-good-thing">heaviest iPhone to date</a>, that added weight makes sense if Apple is stuffing a much larger cell inside. Leaks tip the new battery somewhere between 5,391 mAh and 5,567 mAh, with the latter being the U.S.-bound an eSIM-only model. Either way, that’s roughly a 10% leap over the iPhone 17 Pro Max’s 5,088 mAh capacity.</p><p>What’s particularly intriguing is that Apple is reportedly hitting these numbers without switching to <a href="https://www.tomsguide.com/phones/i-interviewed-honor-and-oneplus-about-their-silicon-carbon-battery-tech-apple-and-google-are-quickly-falling-behind">silicon-carbon technology</a>. Competitors like OnePlus — and more recently Samsung on the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> — have adopted silicon-carbon anodes to radically hike energy density without adding unnecessary bloat. Apple, by contrast, seems content sticking to traditional lithium-ion cells.</p><p>Here’s how the rumored iPhone 18 Pro Max battery specs compares to its predecessor and direct flagship competitors in battery capacity and our labs testing:</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Battery Capacity (mAh)</strong></p></td><td  ><p><strong>Battery Life (hrs:mins)</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro Max (rumored)</strong></p></td><td  ><p>5,391 – 5,567 mAh</p></td><td  ><p>TBD</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max</strong></p></td><td  ><p>5,088 mAh</p></td><td  ><p>17:54</p></td></tr><tr><td class="firstcol " ><p><strong>OnePlus 15</strong></p></td><td  ><p>7,300 mAh</p></td><td  ><p>25:13</p></td></tr><tr><td class="firstcol " ><p><strong>Galaxy S26 Ultra</strong></p></td><td  ><p>5,000 mAh</p></td><td  ><p>16:10</p></td></tr><tr><td class="firstcol " ><p><strong>Pixel 11 Pro XL</strong></p></td><td  ><p>5,115 mAh</p></td><td  ><p>14:28</p></td></tr></tbody></table></div><p>While the <a href="https://www.tomsguide.com/phones/oneplus-phones/oneplus-15-review">OnePlus 15</a> holds the two-day endurance crown thanks to that mamouth 7,300 mAh silicon-carbon battery, the iPhone 18 Pro Max's reported 5,567 mAh cell with Apple’s next-gen silicon could comfortably push the iPhone 18 Pro Max past the 19- or 20-hour threshold. That alone would substantially widen the gap between Cupertino and its closest rivals from Samsung and Google.</p><h2 id="a20-pro-could-be-the-key">A20 Pro could be the key</h2><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="UHNuNim9UYH2mmGNTn3S4V" name="Apple-iPhone 18 Pro-A20-Pro_LIST" alt="Apple iPhone 18 Pro and the A20 Pro chip" src="https://cdn.mos.cms.futurecdn.net/UHNuNim9UYH2mmGNTn3S4V.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/Apple)</span></figcaption></figure><p>Battery capacity isn't everything, and Apple has repeatedly proven that efficiency often beats raw size. While a larger physical cell lays the groundwork, the true genius in extending battery life lies in the silicon it's packing. Apple is widely tipped to debut the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-iphone-18-pro-a20-chip-leak-reveals-the-biggest-gpu-ever-inside-an-iphone">A20 Pro</a>, bringing along TSMC’s 2-nanometer manufacturing process — a major generational leap over the 3nm architecture powering previous flagships.</p><p>Early leaks suggest the A20 Pro could slash power consumption by up to 30% compared to the A19 Pro. Pair that level of efficiency with a bigger physical battery, and Apple has a recipe to shatter expectations. Given how the iPhone 17 Pro Max held up on a 3nm node, reaching 20 hours on our benchmark test should be well within the iPhone 18 Pro Max's grasp.</p><p>Hitting that 20-hour threshold requires an 11.7% improvement over the current iPhone 17 Pro Max result — essentially the baseline expectation I have for this hardware jump. But if Apple pushes the silicon's efficiency performance closer to 30%, which I've seen in previous generations, the calculations would put the runtime past the 23-hour mark. That wouldn't just set a new standard for Apple, it would crown the iPhone 18 Pro Max as the longest-lasting iPhone in history.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eBEd0X"></div>                            </div>                            <script src="https://kwizly.com/embed/eBEd0X.js" async></script><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-now-just-tipped-for-3-colors-heres-your-options">iPhone 18 Pro now tipped for just 3 colors — here's your options</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-vs-iphone-17-pro-should-you-upgrade-this-year">iPhone 18 Pro vs. iPhone 17 Pro: Should you upgrade this year?</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-which-upcoming-iphone-is-right-for-you">iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Which upcoming iPhone is right for you?</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-battery-rumors-it-could-be-a-record-breaking-year-for-apple</link>
                                                                            <description>
                            <![CDATA[ Between a rumored capacity jump to roughly 5,567 mAh and improved power efficiency of the 2nm A20 Pro chip, the iPhone 18 Pro Max battery life could be exceptional. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">JNNeTLGkdbMjLQ9zXJRfZf</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/4zbVNxFtCw8JYgt53YYMKL-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 06 Sep 2026 10:00:00 +0000</pubDate>                                                                                                                                <updated>Sun, 06 Sep 2026 12:21:56 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/4zbVNxFtCw8JYgt53YYMKL-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iphone 17 pro max in red.]]></media:description>                                                            <media:text><![CDATA[iphone 17 pro max in red.]]></media:text>
                                <media:title type="plain"><![CDATA[iphone 17 pro max in red.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/4zbVNxFtCw8JYgt53YYMKL-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When I put the <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">iPhone 17 Pro Max</a> through our <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-battery-life-test-results-are-in-this-blew-us-away">Tom’s Guide battery test last year</a>, the results were nothing short of impressive. The flagship logged massive endurance gains over its predecessor, earning easy spots among our <a href="https://www.tomsguide.com/us/smartphones-best-battery-life,review-2857.html">best phone battery life</a> contenders. Yet, those marks will likely take a back seat to what's coming in the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max</a>.</p><p>If recent iPhone 18 Pro Max battery rumors hold up, last year’s benchmark numbers may end up looking like modest stepping stones. We could be looking at a record-breaking generation for Apple’s premier flagship. While reports point to a tangible capacity increase, that only tells part of the story.</p><p>The real secret weapon lies beneath the glass — centered on a next-generation silicon architecture tipped to redefine overall efficiency.</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/rQHEN3kngZo" allowfullscreen></iframe></div></div><h2 id="a-larger-battery-is-a-good-foundation">A larger battery is a good foundation</h2><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="NUTShzQj5MbSQ7h8SLWLoQ" name="iPhone 18 Pro Max red" alt="iPhone 18 Pro Max dummy unit in dark cherry" src="https://cdn.mos.cms.futurecdn.net/NUTShzQj5MbSQ7h8SLWLoQ.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: Unbox Therapy)</span></figcaption></figure><p>Back in July, I covered leaked <a href="https://weibo.com/6048569942/5316883085788374" target="_blank">regulatory filings</a> pointing to a notable capacity upgrade for the iPhone 18 Pro Max. While I initially scoffed at early claims that it might be the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-tipped-to-be-heaviest-iphone-ever-heres-3-reasons-why-thats-a-good-thing">heaviest iPhone to date</a>, that added weight makes sense if Apple is stuffing a much larger cell inside. Leaks tip the new battery somewhere between 5,391 mAh and 5,567 mAh, with the latter being the U.S.-bound an eSIM-only model. Either way, that’s roughly a 10% leap over the iPhone 17 Pro Max’s 5,088 mAh capacity.</p><p>What’s particularly intriguing is that Apple is reportedly hitting these numbers without switching to <a href="https://www.tomsguide.com/phones/i-interviewed-honor-and-oneplus-about-their-silicon-carbon-battery-tech-apple-and-google-are-quickly-falling-behind">silicon-carbon technology</a>. Competitors like OnePlus — and more recently Samsung on the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> — have adopted silicon-carbon anodes to radically hike energy density without adding unnecessary bloat. Apple, by contrast, seems content sticking to traditional lithium-ion cells.</p><p>Here’s how the rumored iPhone 18 Pro Max battery specs compares to its predecessor and direct flagship competitors in battery capacity and our labs testing:</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Battery Capacity (mAh)</strong></p></td><td  ><p><strong>Battery Life (hrs:mins)</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro Max (rumored)</strong></p></td><td  ><p>5,391 – 5,567 mAh</p></td><td  ><p>TBD</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max</strong></p></td><td  ><p>5,088 mAh</p></td><td  ><p>17:54</p></td></tr><tr><td class="firstcol " ><p><strong>OnePlus 15</strong></p></td><td  ><p>7,300 mAh</p></td><td  ><p>25:13</p></td></tr><tr><td class="firstcol " ><p><strong>Galaxy S26 Ultra</strong></p></td><td  ><p>5,000 mAh</p></td><td  ><p>16:10</p></td></tr><tr><td class="firstcol " ><p><strong>Pixel 11 Pro XL</strong></p></td><td  ><p>5,115 mAh</p></td><td  ><p>14:28</p></td></tr></tbody></table></div><p>While the <a href="https://www.tomsguide.com/phones/oneplus-phones/oneplus-15-review">OnePlus 15</a> holds the two-day endurance crown thanks to that mamouth 7,300 mAh silicon-carbon battery, the iPhone 18 Pro Max's reported 5,567 mAh cell with Apple’s next-gen silicon could comfortably push the iPhone 18 Pro Max past the 19- or 20-hour threshold. That alone would substantially widen the gap between Cupertino and its closest rivals from Samsung and Google.</p><h2 id="a20-pro-could-be-the-key">A20 Pro could be the key</h2><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="UHNuNim9UYH2mmGNTn3S4V" name="Apple-iPhone 18 Pro-A20-Pro_LIST" alt="Apple iPhone 18 Pro and the A20 Pro chip" src="https://cdn.mos.cms.futurecdn.net/UHNuNim9UYH2mmGNTn3S4V.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/Apple)</span></figcaption></figure><p>Battery capacity isn't everything, and Apple has repeatedly proven that efficiency often beats raw size. While a larger physical cell lays the groundwork, the true genius in extending battery life lies in the silicon it's packing. Apple is widely tipped to debut the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-iphone-18-pro-a20-chip-leak-reveals-the-biggest-gpu-ever-inside-an-iphone">A20 Pro</a>, bringing along TSMC’s 2-nanometer manufacturing process — a major generational leap over the 3nm architecture powering previous flagships.</p><p>Early leaks suggest the A20 Pro could slash power consumption by up to 30% compared to the A19 Pro. Pair that level of efficiency with a bigger physical battery, and Apple has a recipe to shatter expectations. Given how the iPhone 17 Pro Max held up on a 3nm node, reaching 20 hours on our benchmark test should be well within the iPhone 18 Pro Max's grasp.</p><p>Hitting that 20-hour threshold requires an 11.7% improvement over the current iPhone 17 Pro Max result — essentially the baseline expectation I have for this hardware jump. But if Apple pushes the silicon's efficiency performance closer to 30%, which I've seen in previous generations, the calculations would put the runtime past the 23-hour mark. That wouldn't just set a new standard for Apple, it would crown the iPhone 18 Pro Max as the longest-lasting iPhone in history.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eBEd0X"></div>                            </div>                            <script src="https://kwizly.com/embed/eBEd0X.js" async></script><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-now-just-tipped-for-3-colors-heres-your-options">iPhone 18 Pro now tipped for just 3 colors — here's your options</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-vs-iphone-17-pro-should-you-upgrade-this-year">iPhone 18 Pro vs. iPhone 17 Pro: Should you upgrade this year?</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-which-upcoming-iphone-is-right-for-you">iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Which upcoming iPhone is right for you?</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone Ultra — here's how Apple is reportedly erasing the crease for its foldable phone ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Seven years after Samsung made foldables a category with the <a href="https://www.tomsguide.com/us/galaxy-fold-problems-bad-for-foldable-phones,news-29895.html">troubled launch</a> of the <a href="https://www.tomsguide.com/reviews/samsung-galaxy-fold">original Galaxy Fold</a>, Apple is finally ready to join the race. The <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone#section-iphone-ultra-crease-free-display">iPhone Ultra</a> is expected to be unveiled at next week’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> on September 9. </p><p>The foldable market has come a long way since the problem-filled early days of Fall 2019, but one thing that hasn’t been completely addressed is the visible crease where the two sides of a folding screen meet.</p><p>Apple has long been rumored to be seeking to “<a href="https://www.tomsguide.com/phones/iphone-flip-tipped-to-eliminate-the-biggest-design-flaw-with-foldable-phones-heres-how">eliminate the crease at all costs</a>.” Here’s what we know about the company’s plans so far.</p><h2 id="foldable-creases-what-s-the-problem">Foldable creases: What’s the problem?</h2><p>In order to bend, foldable screens obviously require more flexibility than standard screens, typically opting for a plastic polymer or ultra-thin glass. As foldables are opened and closed, the repeated stress of bending creates a permanent crease, accelerated by the hinge mechanism that exerts pressure on the screen.</p><p>You can see how this looks on the picture below, of the <a href="https://www.tomsguide.com/reviews/honor-magic-vs-review">Honor Magic Vs</a>.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oVh7A5DHRcSoVGhujGXDRb" name="Honor Magic VS-3.jpg" alt="The Honor Magic Vs' display crease" src="https://cdn.mos.cms.futurecdn.net/oVh7A5DHRcSoVGhujGXDRb.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>While a crease doesn’t impact usage, some view it as a visible eyesore, and you can sometimes feel it while touching the screen. Understandably, buyers also aren’t keen on any visual imperfections on devices that typically start in four figures, though <a href="https://www.tomsguide.com/phones/samsung-phones/im-not-convinced-crease-free-foldables-like-the-galaxy-z-fold-8-actually-matter-prove-me-wrong">our very own Tom Pritchard thinks the problem is overstated</a>.</p><h2 id="how-the-iphone-ultra-is-tackling-the-crease">How the iPhone Ultra is tackling the crease</h2><p>Apple is reportedly <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-3-technologies-apple-is-reportedly-using-to-finally-kill-the-crease">combining three different approaches to fix the problem</a>.</p><p>The first is the <a href="https://www.tomsguide.com/phones/iphones/apple-may-be-using-titanium-and-a-liquid-metal-hinge-in-the-iphone-fold-heres-how-this-could-make-it-the-best-foldable-phone-yet">adoption of a liquid metal hinge</a>, which is <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-design-could-be-the-first-apple-iphone-ever-with-this-combo">capable of handling repeated lifetime bends</a> while spreading the tension through the glass. </p><p>The second is the panel itself. Not only does it reportedly feature two layers of ultra-thin glass to reduce the impact of a crease over time, but <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-report-reveals-this-is-how-apple-is-killing-the-crease">its thickness isn’t uniform</a>. Instead, it’s thinner at the center where it bends the most, and thicker towards the edges to offer some impact resistance.  </p><p>Finally, Apple is said to be using an optically clear adhesive glue. This is designed to maintain liquid properties to fill in microscopic gaps that would eventually contribute to a visible crease. </p><p>Will this make the crease invisible, or merely less obvious? The Weibo account <a href="https://weibo.com/5821279480/QtqvkBpT5" target="_blank">Fixed Focus Digital</a> claims the latter, measuring a crease of less than 0.15mm, and an angle of less than 2.5 degrees. This is obviously out of the box, and we’ll need thousands of test hours to see how this changes over time. </p><p>Apple isn’t the first company to try and reduce the appearance of the crease. Samsung has been trying making progress over multiple generations, <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-finally-figures-out-a-near-lack-of-crease-in-the-galaxy-z-fold-6-se">reducing it significantly with the Galaxy Z Fold 6 SE</a>, and <a href="https://www.tomsguide.com/phones/samsung-phones/ive-seen-the-galaxy-z-fold-8s-flex-titanium-screen-and-apple-should-be-nervous">claiming near victory</a> with the recent <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a>. </p><p>However, our Managing Editor Jason England has found that it can <a href="https://www.tomsguide.com/phones/samsung-phones/the-tech-world-hyped-up-the-galaxy-z-fold-8s-crease-free-display-heres-a-reality-check-after-7-days">creep back after repeated use.</a> We’ll have to see if a similar fate awaits Apple’s solution.</p><h2 id="will-the-iphone-ultra-hinge-be-reliable">Will the iPhone Ultra hinge be reliable?</h2><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="oqerWy42bqvSRMhJh5NbQU" name="iPhone Ultra in hand" alt="iPhone Ultra render in hand" src="https://cdn.mos.cms.futurecdn.net/oqerWy42bqvSRMhJh5NbQU.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: Apple Track)</span></figcaption></figure><p>Despite early reports of reliability concerns in Cupertino, it seems like things are back on track. </p><p><a href="https://www.tomsguide.com/phones/iphones/iphone-fold-achieves-a-visually-crease-free-state-according-to-leaker-but-fears-over-the-hinge-could-lead-to-delays">Back in May</a>, the leaker <a href="https://weibo.com/5143897135/5299248285615219" target="_blank">Instant Digital</a> claimed that “its reliability after frequent opening and closing consistently fails to meet Apple's quality control standards,” suggesting this could cause a delay.</p><p>As we’re expecting the phone imminently just four months later, we can safely assume that Apple has fixed the issue — or it was exaggerated in the first place. Indeed, Bloomberg’s Mark Gurman reports that people he’s spoken to who have had early access to the device <a href="https://www.tomsguide.com/phones/iphones/foldable-iphone-ultra-is-apparently-wowing-early-users-but-the-camera-setup-is-still-the-elephant-in-the-room">praise the durability of the hinge</a>. </p><p>It’s worth noting that since the seventh generation, Samsung has indicated that<a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-7-can-survive-half-a-million-folds-according-to-independent-testing-and-thats-a-massive-upgrade"> its Galaxy Z Fold devices can be opened and closed more than 500,000 times</a>. Assuming 100 interactions per day, that’s over ten years of use, meaning that reliability is no longer the foldable Achilles’ Heel it once was. </p><h2 id="the-big-reveal">The big reveal</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:56.29%;"><img id="USff7EuiMbLVdzsuAfG4hQ" name="iPhone Ultra" alt="iPhone Ultra against colorful background." src="https://cdn.mos.cms.futurecdn.net/USff7EuiMbLVdzsuAfG4hQ.jpg" mos="" align="middle" fullscreen="" width="1510" height="850" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Of course, all of this comes from leaks and rumors, and while the sources have been extremely reliable in the past, we won’t know for sure what Apple has in store until the iPhone Ultra is officially unveiled.</p><p>Fortunately, we don’t have long to wait. The company’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 is scheduled for Wednesday September 9</a>, at 10 a.m. PT or 1:00 p.m. ET. Expect the iPhone Ultra to be the main focus of the event, though we’ll also get a good look at the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a> series and <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>. </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-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone"><strong>iPhone Ultra rumored release date, price, colors and all the latest leaks</strong></a></li><li><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"><strong>Apple Watch Ultra 4 — these are the upgrades Apple needs to make to remain the smartwatch king</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far"><strong>iPhone 18 Pro Max rumors and leaks: Everything we know so far</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-ultra-heres-how-apple-is-reportedly-erasing-the-crease-for-its-foldable-phone</link>
                                                                            <description>
                            <![CDATA[ How Apple is apparently addressing foldables’ Achilles’ Heel ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">P3gZG77qtUuD5z9PwvZmpa</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/BXFPFEcaHQrVivQScPBNff-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 05 Sep 2026 15:00:01 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                                    <dc:creator><![CDATA[ Alan Martin ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/xMmhmPSssqZHHFWveDgSs7.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/BXFPFEcaHQrVivQScPBNff-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Ultra.]]></media:description>                                                            <media:text><![CDATA[iPhone Ultra.]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Ultra.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/BXFPFEcaHQrVivQScPBNff-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Seven years after Samsung made foldables a category with the <a href="https://www.tomsguide.com/us/galaxy-fold-problems-bad-for-foldable-phones,news-29895.html">troubled launch</a> of the <a href="https://www.tomsguide.com/reviews/samsung-galaxy-fold">original Galaxy Fold</a>, Apple is finally ready to join the race. The <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone#section-iphone-ultra-crease-free-display">iPhone Ultra</a> is expected to be unveiled at next week’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> on September 9. </p><p>The foldable market has come a long way since the problem-filled early days of Fall 2019, but one thing that hasn’t been completely addressed is the visible crease where the two sides of a folding screen meet.</p><p>Apple has long been rumored to be seeking to “<a href="https://www.tomsguide.com/phones/iphone-flip-tipped-to-eliminate-the-biggest-design-flaw-with-foldable-phones-heres-how">eliminate the crease at all costs</a>.” Here’s what we know about the company’s plans so far.</p><h2 id="foldable-creases-what-s-the-problem">Foldable creases: What’s the problem?</h2><p>In order to bend, foldable screens obviously require more flexibility than standard screens, typically opting for a plastic polymer or ultra-thin glass. As foldables are opened and closed, the repeated stress of bending creates a permanent crease, accelerated by the hinge mechanism that exerts pressure on the screen.</p><p>You can see how this looks on the picture below, of the <a href="https://www.tomsguide.com/reviews/honor-magic-vs-review">Honor Magic Vs</a>.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oVh7A5DHRcSoVGhujGXDRb" name="Honor Magic VS-3.jpg" alt="The Honor Magic Vs' display crease" src="https://cdn.mos.cms.futurecdn.net/oVh7A5DHRcSoVGhujGXDRb.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>While a crease doesn’t impact usage, some view it as a visible eyesore, and you can sometimes feel it while touching the screen. Understandably, buyers also aren’t keen on any visual imperfections on devices that typically start in four figures, though <a href="https://www.tomsguide.com/phones/samsung-phones/im-not-convinced-crease-free-foldables-like-the-galaxy-z-fold-8-actually-matter-prove-me-wrong">our very own Tom Pritchard thinks the problem is overstated</a>.</p><h2 id="how-the-iphone-ultra-is-tackling-the-crease">How the iPhone Ultra is tackling the crease</h2><p>Apple is reportedly <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-3-technologies-apple-is-reportedly-using-to-finally-kill-the-crease">combining three different approaches to fix the problem</a>.</p><p>The first is the <a href="https://www.tomsguide.com/phones/iphones/apple-may-be-using-titanium-and-a-liquid-metal-hinge-in-the-iphone-fold-heres-how-this-could-make-it-the-best-foldable-phone-yet">adoption of a liquid metal hinge</a>, which is <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-design-could-be-the-first-apple-iphone-ever-with-this-combo">capable of handling repeated lifetime bends</a> while spreading the tension through the glass. </p><p>The second is the panel itself. Not only does it reportedly feature two layers of ultra-thin glass to reduce the impact of a crease over time, but <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-report-reveals-this-is-how-apple-is-killing-the-crease">its thickness isn’t uniform</a>. Instead, it’s thinner at the center where it bends the most, and thicker towards the edges to offer some impact resistance.  </p><p>Finally, Apple is said to be using an optically clear adhesive glue. This is designed to maintain liquid properties to fill in microscopic gaps that would eventually contribute to a visible crease. </p><p>Will this make the crease invisible, or merely less obvious? The Weibo account <a href="https://weibo.com/5821279480/QtqvkBpT5" target="_blank">Fixed Focus Digital</a> claims the latter, measuring a crease of less than 0.15mm, and an angle of less than 2.5 degrees. This is obviously out of the box, and we’ll need thousands of test hours to see how this changes over time. </p><p>Apple isn’t the first company to try and reduce the appearance of the crease. Samsung has been trying making progress over multiple generations, <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-finally-figures-out-a-near-lack-of-crease-in-the-galaxy-z-fold-6-se">reducing it significantly with the Galaxy Z Fold 6 SE</a>, and <a href="https://www.tomsguide.com/phones/samsung-phones/ive-seen-the-galaxy-z-fold-8s-flex-titanium-screen-and-apple-should-be-nervous">claiming near victory</a> with the recent <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a>. </p><p>However, our Managing Editor Jason England has found that it can <a href="https://www.tomsguide.com/phones/samsung-phones/the-tech-world-hyped-up-the-galaxy-z-fold-8s-crease-free-display-heres-a-reality-check-after-7-days">creep back after repeated use.</a> We’ll have to see if a similar fate awaits Apple’s solution.</p><h2 id="will-the-iphone-ultra-hinge-be-reliable">Will the iPhone Ultra hinge be reliable?</h2><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="oqerWy42bqvSRMhJh5NbQU" name="iPhone Ultra in hand" alt="iPhone Ultra render in hand" src="https://cdn.mos.cms.futurecdn.net/oqerWy42bqvSRMhJh5NbQU.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: Apple Track)</span></figcaption></figure><p>Despite early reports of reliability concerns in Cupertino, it seems like things are back on track. </p><p><a href="https://www.tomsguide.com/phones/iphones/iphone-fold-achieves-a-visually-crease-free-state-according-to-leaker-but-fears-over-the-hinge-could-lead-to-delays">Back in May</a>, the leaker <a href="https://weibo.com/5143897135/5299248285615219" target="_blank">Instant Digital</a> claimed that “its reliability after frequent opening and closing consistently fails to meet Apple's quality control standards,” suggesting this could cause a delay.</p><p>As we’re expecting the phone imminently just four months later, we can safely assume that Apple has fixed the issue — or it was exaggerated in the first place. Indeed, Bloomberg’s Mark Gurman reports that people he’s spoken to who have had early access to the device <a href="https://www.tomsguide.com/phones/iphones/foldable-iphone-ultra-is-apparently-wowing-early-users-but-the-camera-setup-is-still-the-elephant-in-the-room">praise the durability of the hinge</a>. </p><p>It’s worth noting that since the seventh generation, Samsung has indicated that<a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-7-can-survive-half-a-million-folds-according-to-independent-testing-and-thats-a-massive-upgrade"> its Galaxy Z Fold devices can be opened and closed more than 500,000 times</a>. Assuming 100 interactions per day, that’s over ten years of use, meaning that reliability is no longer the foldable Achilles’ Heel it once was. </p><h2 id="the-big-reveal">The big reveal</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:56.29%;"><img id="USff7EuiMbLVdzsuAfG4hQ" name="iPhone Ultra" alt="iPhone Ultra against colorful background." src="https://cdn.mos.cms.futurecdn.net/USff7EuiMbLVdzsuAfG4hQ.jpg" mos="" align="middle" fullscreen="" width="1510" height="850" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Of course, all of this comes from leaks and rumors, and while the sources have been extremely reliable in the past, we won’t know for sure what Apple has in store until the iPhone Ultra is officially unveiled.</p><p>Fortunately, we don’t have long to wait. The company’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 is scheduled for Wednesday September 9</a>, at 10 a.m. PT or 1:00 p.m. ET. Expect the iPhone Ultra to be the main focus of the event, though we’ll also get a good look at the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a> series and <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>. </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-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone"><strong>iPhone Ultra rumored release date, price, colors and all the latest leaks</strong></a></li><li><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"><strong>Apple Watch Ultra 4 — these are the upgrades Apple needs to make to remain the smartwatch king</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far"><strong>iPhone 18 Pro Max rumors and leaks: Everything we know so far</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ The iPhone Ultra will be the thinnest iPhone ever — here’s how it will stack up to other foldables ]]></title>
                                                                                                <dc:content><![CDATA[ <p>When you’re about to launch your first-ever foldable device, you know it needs to leave a lasting impression. That’s why design is paramount to making the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> compelling — a device already tipped to be the <a href="https://www.tomsguide.com/phones/iphones/forget-the-iphone-17-air-iphone-fold-just-tipped-to-be-thinnest-iphone-ever">thinnest iPhone ever</a>.</p><p>Apple’s entry into the foldable market isn't just another product launch because it’s a defining moment that will set the hardware benchmark for what an ultra-premium, notebook-style foldable should be. While Apple has the chance to set a new standard with its record-breaking thin chassis, it faces fierce competition from rivals like Samsung, Motorola, and Google, who have spent years iterating their designs.</p><p>Here’s what the rumors and leaks say about how thin Apple could make the iPhone Ultra.</p><h2 id="it-s-going-to-be-thinner-than-the-iphone-air">It’s going to be thinner than the iPhone Air</h2><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="bWRiHr2xAWuu7w7QFRLsq" name="iPhone Air-18" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/bWRiHr2xAWuu7w7QFRLsq.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>There’s very little doubt by now that the iPhone Ultra is going to be a solid contender for <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phone</a> when it’s released. In fact, one of the biggest reasons for that comes from a longstanding rumor that it will be the thinnest iPhone ever at 4.5 mm unfolded — something reliable leaker <a href="https://www.tomsguide.com/phones/iphones/forget-the-iphone-17-air-iphone-fold-just-tipped-to-be-thinnest-iphone-ever">Ming-Chi Kuo has claimed</a> for more than a year now.</p><p>At under 5 mm, it would easily undercut the ultra-slim <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air’s</a> impressive 5.64mm chassis and blow past traditional slates like the standard <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-review">iPhone 17</a>. What’s even more impressive is how the Ultra still retains a thin construction when closed, with rumors suggesting it would sit around 9mm to 9.5mm thick — only marginally thicker than the current <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">17 Pro Max</a>.</p><p>Comparing the folded and unfolded states to Apple’s current lineup highlights just how dramatic this level of engineering is:</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Thinness</strong></p></td><td  ><p><strong>Weight</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra</strong></p></td><td  ><p>4.5 – 4.8 mm</p></td><td  ><p>8.1 – 8.5 ounces (230 – 241 grams</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Air</strong></p></td><td  ><p>5.64 mm</p></td><td  ><p>5.82 ounces (165 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17</strong></p></td><td  ><p>7.95 mm</p></td><td  ><p>6.24 ounces (177 greams)</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17e</strong></p></td><td  ><p>7.8 mm</p></td><td  ><p>5.96 ounces (169 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro</strong></p></td><td  ><p>8.75 mm</p></td><td  ><p>7.27 ounces (206 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max</strong></p></td><td  ><p>8.75 mm</p></td><td  ><p>8.22 ounces (233 grams)</p></td></tr></tbody></table></div><p>The weight story reveals the inevitable balancing act of having a phone with dual screens. Leaks suggest the iPhone Ultra will tip the scales between 8.1 and 8.5 ounces (230 to 241 grams). While that's substantially heavier than the current iPhone Air and iPhone 17, it puts Apple’s first foldable directly in line with the iPhone 17 Pro Max — giving users a tablet-sized 7.8-inch inner display without adding meaningful heft beyond Apple’s largest flagship.</p><h2 id="impressively-thin-but-not-the-thinnest">Impressively thin, but not the thinnest</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3307px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="xRWSRBZAfeXroRwi8p4z5F" name="Galaxy Z Fold 8 Ultra review-7" alt="samsung galaxy z fold 8 ultra review images" src="https://cdn.mos.cms.futurecdn.net/xRWSRBZAfeXroRwi8p4z5F.jpg" mos="" align="middle" fullscreen="" width="3307" height="1860" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">The Galaxy Fold 8 Ultra is just 4.1mm thin  </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>While the iPhone Ultra’s rumored 4.5 mm unfolded profile would make it a standout within Apple’s lineup, it still wouldn’t be the thinnest notebook-style foldable on the market. Backed by years of iterative engineering, Android rivals have pushed physical dimensions to the absolute limit.</p><p>Here in the U.S., Samsung’s <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> holds the title with its astounding 4.1 mm profile when unfolded. Seeing is believing, as the ultra-thin chassis leaves you wondering how companies like Samsung manage to cram high-end hardware into such slender frames. However, even Samsung’s latest flagship is a smidge thicker than the reigning global titleholder: the <a href="https://www.tomsguide.com/phones/android-phones/honor-magic-v6-hands-on-review">Honor Magic V6</a>, which shaves even more off its waistline with a 4.0mm unfolded build.</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Thinness</strong></p></td><td  ><p><strong>Weight</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra</strong></p></td><td  ><p>4.5 – 4.8 mm</p></td><td  ><p>8.1 – 8.5 ounces (230 – 241 grams</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8</strong></p></td><td  ><p>4.5 mm</p></td><td  ><p>7.09 ounces (201 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8 Ultra</strong></p></td><td  ><p>4.1 mm</p></td><td  ><p>7.58 ounces (215 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Motorola Razr Fold</strong></p></td><td  ><p>4.7 mm</p></td><td  ><p>8.6 ounces (243 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 11 Pro Fold</strong></p></td><td  ><p>4.8 mm</p></td><td  ><p>8.64 ounces (245 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Oppo Find N6</strong></p></td><td  ><p>4.21 mm</p></td><td  ><p>7.94 ounces (225 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Honor Magic V6</strong></p></td><td  ><p>4 mm</p></td><td  ><p>7.72 ounces (219 grams)</p></td></tr></tbody></table></div><p>In terms of heft, the iPhone Ultra's estimated weight of 230 to 241 grams puts it squarely in the middle of the pack. It won't quite match the featherweight engineering of Samsung's standard <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a> (201 grams) or the Honor Magic V6 (219 grams), but it comfortably undercuts chunkier alternatives like the <a href="https://www.tomsguide.com/phones/motorola-phones/motorola-razr-fold-review">Motorola Razr Fold</a> (228 grams) and <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold</a> (245 grams).</p><p>For a first-generation foldable, matching the thickness and ergonomics of established devices proves Apple isn't treating the iPhone Ultra as an experiment, but as a refined flagship designed to compete head-to-head on from day one.</p><h2 id="but-it-could-come-at-a-cost">But it could come at a cost</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1046px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="457m5Jom872mCevr5ASKqe" name="Foundry iphone ultra" alt="iPhone Ultra render shown in hand" src="https://cdn.mos.cms.futurecdn.net/457m5Jom872mCevr5ASKqe.jpg" mos="" align="middle" fullscreen="" width="1046" height="588" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Foundry)</span></figcaption></figure><p>Even if the iPhone Ultra doesn’t walk away with the undisputed crown for the world’s thinnest foldable, the engineering behind its design will still be a milestone for Apple. Thinness is only half the battle because if Apple manages to pair its slim chassis with a truly crease-less inner display, MagSafe connectivity, and the strong performance of an A20 Pro chip, it could set a new gold standard for foldables.</p><p>The ultimate test, however, will be the price tag. Leaks and rumors hint that the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-price-rumors-heres-how-much-you-can-expect-to-pay-for-apples-first-foldable">iPhone Ultra price</a> could land anywhere between $2,000 and $2,500, so the iPhone Ultra’s eye-watering cost could easily be a dealbreaker for mainstream buyers. Yet, if Apple somehow delivers on its ambitions, that steep price could establish the Ultra as worth every penny.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xm8a0O"></div>                            </div>                            <script src="https://kwizly.com/embed/Xm8a0O.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/computing/mobile-apps/mapquest-is-suddenly-no-4-in-the-apple-app-store-heres-why">'We're not changing it': MapQuest hits No. 1 in App Store after refusing to rename Lake Ontario to Lake America</a></li><li><a href="https://www.tomsguide.com/phones/iphones/last-minute-iphone-ultra-report-shoots-down-apple-pencil-but-this-is-how-it-could-have-worked">iPhone Ultra tested with Apple Pencil but not happening at launch — this is how it could work</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-upgrades-everything-we-know-about-the-new-sensor">iPhone 18 Pro camera upgrades — everything we know about the new sensor</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/the-iphone-ultra-will-be-the-thinnest-iphone-ever-heres-how-it-will-stack-up-to-other-foldables</link>
                                                                            <description>
                            <![CDATA[ While the iPhone Ultra is poised to become Apple’s thinnest device ever at 4.5mm unfolded, there are still a couple of other notebook foldables that are thinner. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">kZiMc3qAVmgamtVvVbER8e</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/uZcqBzcPrfQi6sxsPWkjg3-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 05 Sep 2026 07:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/uZcqBzcPrfQi6sxsPWkjg3-1280-80.jpg">
                                                            <media:credit><![CDATA[MacRumors]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Ultra shown laying down open]]></media:description>                                                            <media:text><![CDATA[iPhone Ultra shown laying down open]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Ultra shown laying down open]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/uZcqBzcPrfQi6sxsPWkjg3-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When you’re about to launch your first-ever foldable device, you know it needs to leave a lasting impression. That’s why design is paramount to making the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> compelling — a device already tipped to be the <a href="https://www.tomsguide.com/phones/iphones/forget-the-iphone-17-air-iphone-fold-just-tipped-to-be-thinnest-iphone-ever">thinnest iPhone ever</a>.</p><p>Apple’s entry into the foldable market isn't just another product launch because it’s a defining moment that will set the hardware benchmark for what an ultra-premium, notebook-style foldable should be. While Apple has the chance to set a new standard with its record-breaking thin chassis, it faces fierce competition from rivals like Samsung, Motorola, and Google, who have spent years iterating their designs.</p><p>Here’s what the rumors and leaks say about how thin Apple could make the iPhone Ultra.</p><h2 id="it-s-going-to-be-thinner-than-the-iphone-air">It’s going to be thinner than the iPhone Air</h2><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="bWRiHr2xAWuu7w7QFRLsq" name="iPhone Air-18" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/bWRiHr2xAWuu7w7QFRLsq.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>There’s very little doubt by now that the iPhone Ultra is going to be a solid contender for <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phone</a> when it’s released. In fact, one of the biggest reasons for that comes from a longstanding rumor that it will be the thinnest iPhone ever at 4.5 mm unfolded — something reliable leaker <a href="https://www.tomsguide.com/phones/iphones/forget-the-iphone-17-air-iphone-fold-just-tipped-to-be-thinnest-iphone-ever">Ming-Chi Kuo has claimed</a> for more than a year now.</p><p>At under 5 mm, it would easily undercut the ultra-slim <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air’s</a> impressive 5.64mm chassis and blow past traditional slates like the standard <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-review">iPhone 17</a>. What’s even more impressive is how the Ultra still retains a thin construction when closed, with rumors suggesting it would sit around 9mm to 9.5mm thick — only marginally thicker than the current <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">17 Pro Max</a>.</p><p>Comparing the folded and unfolded states to Apple’s current lineup highlights just how dramatic this level of engineering is:</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Thinness</strong></p></td><td  ><p><strong>Weight</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra</strong></p></td><td  ><p>4.5 – 4.8 mm</p></td><td  ><p>8.1 – 8.5 ounces (230 – 241 grams</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Air</strong></p></td><td  ><p>5.64 mm</p></td><td  ><p>5.82 ounces (165 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17</strong></p></td><td  ><p>7.95 mm</p></td><td  ><p>6.24 ounces (177 greams)</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17e</strong></p></td><td  ><p>7.8 mm</p></td><td  ><p>5.96 ounces (169 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro</strong></p></td><td  ><p>8.75 mm</p></td><td  ><p>7.27 ounces (206 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max</strong></p></td><td  ><p>8.75 mm</p></td><td  ><p>8.22 ounces (233 grams)</p></td></tr></tbody></table></div><p>The weight story reveals the inevitable balancing act of having a phone with dual screens. Leaks suggest the iPhone Ultra will tip the scales between 8.1 and 8.5 ounces (230 to 241 grams). While that's substantially heavier than the current iPhone Air and iPhone 17, it puts Apple’s first foldable directly in line with the iPhone 17 Pro Max — giving users a tablet-sized 7.8-inch inner display without adding meaningful heft beyond Apple’s largest flagship.</p><h2 id="impressively-thin-but-not-the-thinnest">Impressively thin, but not the thinnest</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3307px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="xRWSRBZAfeXroRwi8p4z5F" name="Galaxy Z Fold 8 Ultra review-7" alt="samsung galaxy z fold 8 ultra review images" src="https://cdn.mos.cms.futurecdn.net/xRWSRBZAfeXroRwi8p4z5F.jpg" mos="" align="middle" fullscreen="" width="3307" height="1860" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="caption-text">The Galaxy Fold 8 Ultra is just 4.1mm thin  </span><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>While the iPhone Ultra’s rumored 4.5 mm unfolded profile would make it a standout within Apple’s lineup, it still wouldn’t be the thinnest notebook-style foldable on the market. Backed by years of iterative engineering, Android rivals have pushed physical dimensions to the absolute limit.</p><p>Here in the U.S., Samsung’s <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> holds the title with its astounding 4.1 mm profile when unfolded. Seeing is believing, as the ultra-thin chassis leaves you wondering how companies like Samsung manage to cram high-end hardware into such slender frames. However, even Samsung’s latest flagship is a smidge thicker than the reigning global titleholder: the <a href="https://www.tomsguide.com/phones/android-phones/honor-magic-v6-hands-on-review">Honor Magic V6</a>, which shaves even more off its waistline with a 4.0mm unfolded build.</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Thinness</strong></p></td><td  ><p><strong>Weight</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra</strong></p></td><td  ><p>4.5 – 4.8 mm</p></td><td  ><p>8.1 – 8.5 ounces (230 – 241 grams</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8</strong></p></td><td  ><p>4.5 mm</p></td><td  ><p>7.09 ounces (201 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8 Ultra</strong></p></td><td  ><p>4.1 mm</p></td><td  ><p>7.58 ounces (215 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Motorola Razr Fold</strong></p></td><td  ><p>4.7 mm</p></td><td  ><p>8.6 ounces (243 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 11 Pro Fold</strong></p></td><td  ><p>4.8 mm</p></td><td  ><p>8.64 ounces (245 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Oppo Find N6</strong></p></td><td  ><p>4.21 mm</p></td><td  ><p>7.94 ounces (225 grams)</p></td></tr><tr><td class="firstcol " ><p><strong>Honor Magic V6</strong></p></td><td  ><p>4 mm</p></td><td  ><p>7.72 ounces (219 grams)</p></td></tr></tbody></table></div><p>In terms of heft, the iPhone Ultra's estimated weight of 230 to 241 grams puts it squarely in the middle of the pack. It won't quite match the featherweight engineering of Samsung's standard <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a> (201 grams) or the Honor Magic V6 (219 grams), but it comfortably undercuts chunkier alternatives like the <a href="https://www.tomsguide.com/phones/motorola-phones/motorola-razr-fold-review">Motorola Razr Fold</a> (228 grams) and <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold</a> (245 grams).</p><p>For a first-generation foldable, matching the thickness and ergonomics of established devices proves Apple isn't treating the iPhone Ultra as an experiment, but as a refined flagship designed to compete head-to-head on from day one.</p><h2 id="but-it-could-come-at-a-cost">But it could come at a cost</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1046px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="457m5Jom872mCevr5ASKqe" name="Foundry iphone ultra" alt="iPhone Ultra render shown in hand" src="https://cdn.mos.cms.futurecdn.net/457m5Jom872mCevr5ASKqe.jpg" mos="" align="middle" fullscreen="" width="1046" height="588" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Foundry)</span></figcaption></figure><p>Even if the iPhone Ultra doesn’t walk away with the undisputed crown for the world’s thinnest foldable, the engineering behind its design will still be a milestone for Apple. Thinness is only half the battle because if Apple manages to pair its slim chassis with a truly crease-less inner display, MagSafe connectivity, and the strong performance of an A20 Pro chip, it could set a new gold standard for foldables.</p><p>The ultimate test, however, will be the price tag. Leaks and rumors hint that the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-price-rumors-heres-how-much-you-can-expect-to-pay-for-apples-first-foldable">iPhone Ultra price</a> could land anywhere between $2,000 and $2,500, so the iPhone Ultra’s eye-watering cost could easily be a dealbreaker for mainstream buyers. Yet, if Apple somehow delivers on its ambitions, that steep price could establish the Ultra as worth every penny.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xm8a0O"></div>                            </div>                            <script src="https://kwizly.com/embed/Xm8a0O.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/computing/mobile-apps/mapquest-is-suddenly-no-4-in-the-apple-app-store-heres-why">'We're not changing it': MapQuest hits No. 1 in App Store after refusing to rename Lake Ontario to Lake America</a></li><li><a href="https://www.tomsguide.com/phones/iphones/last-minute-iphone-ultra-report-shoots-down-apple-pencil-but-this-is-how-it-could-have-worked">iPhone Ultra tested with Apple Pencil but not happening at launch — this is how it could work</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-upgrades-everything-we-know-about-the-new-sensor">iPhone 18 Pro camera upgrades — everything we know about the new sensor</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone Ultra battery: here's what we know so far ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Everything about the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> is going to be scrutinized under a much larger magnifying glass, so Apple can’t afford to gloss over some of the foldable’s biggest rumored features. One of the greatest areas of concern centers on battery life, given that it’s tipped to become the thinnest iPhone ever.</p><p>Delivering all-day endurance in a foldable is notoriously difficult, especially when you factor in that these devices have expansive main displays compared to traditional slates. I’ve tested many of the <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phones</a>, and our lab testing reveals the obvious: battery life remains a major area of opportunity.</p><p>Knowing that Apple needs to strike a careful balance between battery endurance and a thin, lightweight construction, I’ll break down all the leaks and rumors surrounding the iPhone Ultra’s battery — while examining what its main rivals offer in terms of stamina.</p><h2 id="split-battery-design">Split battery design</h2><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="LCYKZkLw26qbVSSwHPj5f3" name="iPhone Ultra front 1.AppleTrack-2" alt="iPhone Ultra shown from the front screen" src="https://cdn.mos.cms.futurecdn.net/LCYKZkLw26qbVSSwHPj5f3.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: AppleTrack)</span></figcaption></figure><p>Based on <a href="https://9to5mac.com/2026/07/10/iphone-ultra-battery-details-allegedly-revealed-in-new-leak/" target="_blank">regulatory filings</a> released back in July and shared by <a href="https://redirect.viglink.com/?format=go&jsonp=vglnk_178836639774212&key=c1c7d488bb2df8a8b659d5d41634d304&libId=mtkaf4l7010023dg000ULc89q00an&loc=https%3A%2F%2F9to5mac.com%2F2026%2F07%2F10%2Fiphone-ultra-battery-details-allegedly-revealed-in-new-leak%2F&ccpaConsent=1---&v=1&out=https%3A%2F%2Fweibo.com%2F6048569942%2FR82ilujPp&ref=https%3A%2F%2Fwww.google.com%2F&title=iPhone%20Ultra%20battery%20details%20allegedly%20revealed%20in%20new%20leak%20-%209to5Mac&txt=leaker%20Digital%20Chat%20Station" target="_blank">leaker Digital Chat Station</a>, Apple could be leaning toward a dual-cell split battery design for the iPhone Ultra to evenly distribute weight across its folding chassis. The configuration revealed in the filings pairs a 1,921 mAh cell with a larger 2,962 mAh one, bringing the total combined rated capacity to 4,883 mAh.</p><p>Unlike many of its rivals, Apple isn’t planning to bank on <a href="https://www.tomsguide.com/phones/i-interviewed-honor-and-oneplus-about-their-silicon-carbon-battery-tech-apple-and-google-are-quickly-falling-behind">silicon-carbon battery tech</a> to power its upcoming foldable. While competitors leverage high-density silicon anodes that allow them to cram massive capacities into their foldables without adding bulk to their frames, Apple's decision to stick with conventional lithium-ion cells means the iPhone Ultra won't lead the pack in raw capacity.</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Battery Size</strong></p></td><td  ><p><strong>Thinness</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra</strong></p></td><td  ><p>4,883 mAh (rumored)</p></td><td  ><p>4.5 – 4.8 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8</strong></p></td><td  ><p>4,800 mAh</p></td><td  ><p>4.5 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8 Ultra</strong></p></td><td  ><p>5,000 mAh</p></td><td  ><p>4.1 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Motorola Razr Fold</strong></p></td><td  ><p>6,000 mAh</p></td><td  ><p>4.7 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 11 Pro Fold</strong></p></td><td  ><p>4,806 mAh</p></td><td  ><p>4.8 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Oppo Find N6</strong></p></td><td  ><p>6,000 mAh</p></td><td  ><p>4.21 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Honor Magic V6</strong></p></td><td  ><p>6,660 mAh</p></td><td  ><p>4 mm</p></td></tr></tbody></table></div><p>The chart above highlights the disparity in raw capacity the iPhone Ultra faces against its main rivals. At 4,883 mAh, the iPhone Ultra would lag near the bottom of the pack, eclipsing only the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a> and <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold</a>. On the other end of the spectrum, the <a href="https://www.tomsguide.com/phones/motorola-phones/motorola-razr-fold-review">Motorola Razr Fold</a>, Oppo Find N6, and <a href="https://www.tomsguide.com/phones/android-phones/honor-magic-v6-hands-on-review">Honor Magic V6</a> all boast capacities of 6,000 mAh or more.</p><h2 id="battery-life-is-a-big-concern">Battery life is a big concern</h2><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Battery Life (hrs:mins)</strong></p></td><td  ><p><strong>Battery Size</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra</strong></p></td><td  ><p>N/A</p></td><td  ><p>4,883 mAh (rumored)</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8</strong></p></td><td  ><p>12:20</p></td><td  ><p>4,800 mAh</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8 Ultra</strong></p></td><td  ><p>14:33</p></td><td  ><p>5,000 mAh</p></td></tr><tr><td class="firstcol " ><p><strong>Motorola Razr Fold</strong></p></td><td  ><p>14:44</p></td><td  ><p>6,000 mAh</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 11 Pro Fold</strong></p></td><td  ><p>12:31</p></td><td  ><p>4,806 mAh</p></td></tr></tbody></table></div><p>I’ve already mentioned how foldables don’t have the same level of endurance as traditional flagship models, but they are making dramatic improvements. Our own lab testing results show that the landscape is shifting rapidly for notebook-style foldables, raising the stakes for the iPhone Ultra.</p><p>Looking at the Tom’s Guide battery drain test — which involves having a device continuously surf the web over cellular at 150 nits of screen brightness until depletion — you can see how larger battery capacities inherently deliver longer battery life in the chart above.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-WwgEzW"></div>                            </div>                            <script src="https://kwizly.com/embed/WwgEzW.js" async></script><p>Leading the pack is the <a href="https://www.tomsguide.com/phones/motorola-phones/motorola-razr-fold-battery-life-test-results-are-in-and-it-sets-a-new-record-for-notebook-style-foldables">Motorola Razr Fold at 14 hours and 44 minutes</a>, with the <a href="https://www.tomsguide.com/phones/samsung-phones/galaxy-z-fold-8-vs-fold-8-ultra-vs-flip-8-battery-tests-silicon-carbon-pays-off">Galaxy Z Fold 8 Ultra not too far behind at 14 hours and 33 minutes</a>. I think we have a good indication of where the iPhone Ultra could land based on the Galaxy Z Fold 8 and Pixel 11 Pro Fold's performances.</p><p>If the iPhone Ultra does indeed end up packing a 4,883 mAh battery, I suspect it'll clear the 12.5-hour hump with ease — and possibly land closer to the 13-hour mark. While that would still fall short of the leaders, it will come down to something else entirely to prove that the iPhone Ultra is a legitimate endurance contender.</p><h2 id="a20-pro-could-have-the-biggest-impact">A20 Pro could have the biggest impact</h2><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="7xgeny3EiX7o4SBUKkurFP" name="Apple-Silicon-A20-Pro_LIST" alt="Apple A20 Pro chip" src="https://cdn.mos.cms.futurecdn.net/7xgeny3EiX7o4SBUKkurFP.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: Apple/Tom's Guide)</span></figcaption></figure><p>I know firsthand that size is only one part of the equation because I only need to look at the devices topping our <a href="https://www.tomsguide.com/us/smartphones-best-battery-life,review-2857.html">best phone battery life</a> guide to be reminded of that. Despite leaks and rumors indicating that the iPhone Ultra will have a much smaller battery capacity than its rivals, endurance will ultimately come down to the efficiency of what's running under the hood. Specifically, I’m referring to the rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-tipped-for-a20-pro-chip-apples-first-2nm-processor-to-power-new-foldable-phone">A20 Pro chip</a>, reportedly built on TSMC’s next-generation 2nm architecture.</p><p>The A20 Pro could represent Apple’s biggest efficiency leap in years. Moving down to a 2nm architecture doesn’t just promise a performance bump — it should drastically slash power draw across the board. That advantage will be critical for balancing the heavy power draw demanded by the iPhone Ultra’s dual displays.</p><p>If Apple can optimize power delivery to key hardware components, the iPhone Ultra could significantly stretch its endurance between charges. Given the sizable battery life gains between recent flagship generations, the A20 Pro might just defy everyone's expectations (including mine). While matching the 14+ hour times posted by rival foldables seems far-fetched based solely on a 4,883 mAh cell, the raw efficiency of a 2nm silicon could easily bridge the gap.</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-ultra-exclusive-gurman-on-price-release-date-and-secret-weapon-versus-android">iPhone Ultra exclusive: Gurman on price, release date rumors and 'day one' weapon against Android</a></li><li><a href="https://www.tomsguide.com/computing/mobile-apps/mapquest-is-suddenly-no-4-in-the-apple-app-store-heres-why">'We're not changing it': MapQuest hits No. 1 in App Store after refusing to rename Lake Ontario to Lake America</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-18-pro-max-unboxed-ahead-of-apple-event-these-could-be-the-final-designs">iPhone Ultra and 18 Pro Max unboxed ahead of Apple event — these could be the final designs</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-ultra-battery-heres-what-we-know-so-far</link>
                                                                            <description>
                            <![CDATA[ While the iPhone Ultra's rumored 4,883 mAh split battery would trail rival foldables, its battery life performance could lean on something else. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">CHYp9VhhYgoXEgnfpkndBW</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/457m5Jom872mCevr5ASKqe-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 05 Sep 2026 04:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/457m5Jom872mCevr5ASKqe-1280-80.jpg">
                                                            <media:credit><![CDATA[Foundry]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Ultra render shown in hand]]></media:description>                                                            <media:text><![CDATA[iPhone Ultra render shown in hand]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Ultra render shown in hand]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/457m5Jom872mCevr5ASKqe-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Everything about the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> is going to be scrutinized under a much larger magnifying glass, so Apple can’t afford to gloss over some of the foldable’s biggest rumored features. One of the greatest areas of concern centers on battery life, given that it’s tipped to become the thinnest iPhone ever.</p><p>Delivering all-day endurance in a foldable is notoriously difficult, especially when you factor in that these devices have expansive main displays compared to traditional slates. I’ve tested many of the <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phones</a>, and our lab testing reveals the obvious: battery life remains a major area of opportunity.</p><p>Knowing that Apple needs to strike a careful balance between battery endurance and a thin, lightweight construction, I’ll break down all the leaks and rumors surrounding the iPhone Ultra’s battery — while examining what its main rivals offer in terms of stamina.</p><h2 id="split-battery-design">Split battery design</h2><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="LCYKZkLw26qbVSSwHPj5f3" name="iPhone Ultra front 1.AppleTrack-2" alt="iPhone Ultra shown from the front screen" src="https://cdn.mos.cms.futurecdn.net/LCYKZkLw26qbVSSwHPj5f3.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: AppleTrack)</span></figcaption></figure><p>Based on <a href="https://9to5mac.com/2026/07/10/iphone-ultra-battery-details-allegedly-revealed-in-new-leak/" target="_blank">regulatory filings</a> released back in July and shared by <a href="https://redirect.viglink.com/?format=go&jsonp=vglnk_178836639774212&key=c1c7d488bb2df8a8b659d5d41634d304&libId=mtkaf4l7010023dg000ULc89q00an&loc=https%3A%2F%2F9to5mac.com%2F2026%2F07%2F10%2Fiphone-ultra-battery-details-allegedly-revealed-in-new-leak%2F&ccpaConsent=1---&v=1&out=https%3A%2F%2Fweibo.com%2F6048569942%2FR82ilujPp&ref=https%3A%2F%2Fwww.google.com%2F&title=iPhone%20Ultra%20battery%20details%20allegedly%20revealed%20in%20new%20leak%20-%209to5Mac&txt=leaker%20Digital%20Chat%20Station" target="_blank">leaker Digital Chat Station</a>, Apple could be leaning toward a dual-cell split battery design for the iPhone Ultra to evenly distribute weight across its folding chassis. The configuration revealed in the filings pairs a 1,921 mAh cell with a larger 2,962 mAh one, bringing the total combined rated capacity to 4,883 mAh.</p><p>Unlike many of its rivals, Apple isn’t planning to bank on <a href="https://www.tomsguide.com/phones/i-interviewed-honor-and-oneplus-about-their-silicon-carbon-battery-tech-apple-and-google-are-quickly-falling-behind">silicon-carbon battery tech</a> to power its upcoming foldable. While competitors leverage high-density silicon anodes that allow them to cram massive capacities into their foldables without adding bulk to their frames, Apple's decision to stick with conventional lithium-ion cells means the iPhone Ultra won't lead the pack in raw capacity.</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Battery Size</strong></p></td><td  ><p><strong>Thinness</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra</strong></p></td><td  ><p>4,883 mAh (rumored)</p></td><td  ><p>4.5 – 4.8 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8</strong></p></td><td  ><p>4,800 mAh</p></td><td  ><p>4.5 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8 Ultra</strong></p></td><td  ><p>5,000 mAh</p></td><td  ><p>4.1 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Motorola Razr Fold</strong></p></td><td  ><p>6,000 mAh</p></td><td  ><p>4.7 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 11 Pro Fold</strong></p></td><td  ><p>4,806 mAh</p></td><td  ><p>4.8 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Oppo Find N6</strong></p></td><td  ><p>6,000 mAh</p></td><td  ><p>4.21 mm</p></td></tr><tr><td class="firstcol " ><p><strong>Honor Magic V6</strong></p></td><td  ><p>6,660 mAh</p></td><td  ><p>4 mm</p></td></tr></tbody></table></div><p>The chart above highlights the disparity in raw capacity the iPhone Ultra faces against its main rivals. At 4,883 mAh, the iPhone Ultra would lag near the bottom of the pack, eclipsing only the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a> and <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold</a>. On the other end of the spectrum, the <a href="https://www.tomsguide.com/phones/motorola-phones/motorola-razr-fold-review">Motorola Razr Fold</a>, Oppo Find N6, and <a href="https://www.tomsguide.com/phones/android-phones/honor-magic-v6-hands-on-review">Honor Magic V6</a> all boast capacities of 6,000 mAh or more.</p><h2 id="battery-life-is-a-big-concern">Battery life is a big concern</h2><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Battery Life (hrs:mins)</strong></p></td><td  ><p><strong>Battery Size</strong></p></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra</strong></p></td><td  ><p>N/A</p></td><td  ><p>4,883 mAh (rumored)</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8</strong></p></td><td  ><p>12:20</p></td><td  ><p>4,800 mAh</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8 Ultra</strong></p></td><td  ><p>14:33</p></td><td  ><p>5,000 mAh</p></td></tr><tr><td class="firstcol " ><p><strong>Motorola Razr Fold</strong></p></td><td  ><p>14:44</p></td><td  ><p>6,000 mAh</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 11 Pro Fold</strong></p></td><td  ><p>12:31</p></td><td  ><p>4,806 mAh</p></td></tr></tbody></table></div><p>I’ve already mentioned how foldables don’t have the same level of endurance as traditional flagship models, but they are making dramatic improvements. Our own lab testing results show that the landscape is shifting rapidly for notebook-style foldables, raising the stakes for the iPhone Ultra.</p><p>Looking at the Tom’s Guide battery drain test — which involves having a device continuously surf the web over cellular at 150 nits of screen brightness until depletion — you can see how larger battery capacities inherently deliver longer battery life in the chart above.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-WwgEzW"></div>                            </div>                            <script src="https://kwizly.com/embed/WwgEzW.js" async></script><p>Leading the pack is the <a href="https://www.tomsguide.com/phones/motorola-phones/motorola-razr-fold-battery-life-test-results-are-in-and-it-sets-a-new-record-for-notebook-style-foldables">Motorola Razr Fold at 14 hours and 44 minutes</a>, with the <a href="https://www.tomsguide.com/phones/samsung-phones/galaxy-z-fold-8-vs-fold-8-ultra-vs-flip-8-battery-tests-silicon-carbon-pays-off">Galaxy Z Fold 8 Ultra not too far behind at 14 hours and 33 minutes</a>. I think we have a good indication of where the iPhone Ultra could land based on the Galaxy Z Fold 8 and Pixel 11 Pro Fold's performances.</p><p>If the iPhone Ultra does indeed end up packing a 4,883 mAh battery, I suspect it'll clear the 12.5-hour hump with ease — and possibly land closer to the 13-hour mark. While that would still fall short of the leaders, it will come down to something else entirely to prove that the iPhone Ultra is a legitimate endurance contender.</p><h2 id="a20-pro-could-have-the-biggest-impact">A20 Pro could have the biggest impact</h2><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="7xgeny3EiX7o4SBUKkurFP" name="Apple-Silicon-A20-Pro_LIST" alt="Apple A20 Pro chip" src="https://cdn.mos.cms.futurecdn.net/7xgeny3EiX7o4SBUKkurFP.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: Apple/Tom's Guide)</span></figcaption></figure><p>I know firsthand that size is only one part of the equation because I only need to look at the devices topping our <a href="https://www.tomsguide.com/us/smartphones-best-battery-life,review-2857.html">best phone battery life</a> guide to be reminded of that. Despite leaks and rumors indicating that the iPhone Ultra will have a much smaller battery capacity than its rivals, endurance will ultimately come down to the efficiency of what's running under the hood. Specifically, I’m referring to the rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-tipped-for-a20-pro-chip-apples-first-2nm-processor-to-power-new-foldable-phone">A20 Pro chip</a>, reportedly built on TSMC’s next-generation 2nm architecture.</p><p>The A20 Pro could represent Apple’s biggest efficiency leap in years. Moving down to a 2nm architecture doesn’t just promise a performance bump — it should drastically slash power draw across the board. That advantage will be critical for balancing the heavy power draw demanded by the iPhone Ultra’s dual displays.</p><p>If Apple can optimize power delivery to key hardware components, the iPhone Ultra could significantly stretch its endurance between charges. Given the sizable battery life gains between recent flagship generations, the A20 Pro might just defy everyone's expectations (including mine). While matching the 14+ hour times posted by rival foldables seems far-fetched based solely on a 4,883 mAh cell, the raw efficiency of a 2nm silicon could easily bridge the gap.</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-ultra-exclusive-gurman-on-price-release-date-and-secret-weapon-versus-android">iPhone Ultra exclusive: Gurman on price, release date rumors and 'day one' weapon against Android</a></li><li><a href="https://www.tomsguide.com/computing/mobile-apps/mapquest-is-suddenly-no-4-in-the-apple-app-store-heres-why">'We're not changing it': MapQuest hits No. 1 in App Store after refusing to rename Lake Ontario to Lake America</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-18-pro-max-unboxed-ahead-of-apple-event-these-could-be-the-final-designs">iPhone Ultra and 18 Pro Max unboxed ahead of Apple event — these could be the final designs</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Huge new Apple report details all 41 products coming under new CEO John Ternus ]]></title>
                                                                                                <dc:content><![CDATA[ <p>John Ternus has finally taken over as CEO of Apple, and his term could kickstart a wave of new and redefined Apple devices. It all starts next week with the <a href="https://www.tomsguide.com/phones/iphones/apple-sept-9-event-all-9-new-products-were-expecting-to-see">"Surprise and Shine" iPhone event</a>.</p><p>However, that's just the beginning, and <a href="https://www.bloomberg.com/news/articles/2026-09-04/what-to-expect-at-sept-9-apple-event-foldable-iphone-iphone-18-pro-watch">Bloomberg's Mark Gurman</a> just released a massive report that highlights 41 devices that could be released in the next three years and beyond. </p><p>That includes new devices like the foldable <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> and Apple's <a href="https://www.tomsguide.com/computing/smart-glasses/apple-glasses-everything-we-know-so-far">first foray into smart glasses</a>. </p><h2 id="later-2026-and-early-2027">Later 2026 and Early 2027</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="BXFPFEcaHQrVivQScPBNff" name="iPhone Ultra" alt="iPhone Ultra." src="https://cdn.mos.cms.futurecdn.net/BXFPFEcaHQrVivQScPBNff.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Most every device meant to launch in the next six months should arrive during one of two events: the September 9 iPhone soiree and an announcement in October or early November. </p><p>Mostly, the difference here is that new MacBooks are usually announced in mid-fall, usually with a new chipset. </p><p>The key devices to be aware of in the next few months include Apple's first foldable<a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-latest-release-date-rumors-heres-when-we-expect-it-to-launch" target="_blank"> iPhone</a><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-latest-release-date-rumors-heres-when-we-expect-it-to-launch"> Ultra</a> and the <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">iPhone 18 Pro</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max</a> models, all of which are expected to launch next week. There's also the first iPad mini <a href="https://www.tomsguide.com/computing/ipads/first-oled-ipad-mini-tipped-for-october-launch-heres-why-im-excited-and-worried">with an OLED </a><a href="https://www.tomsguide.com/computing/ipads/first-oled-ipad-mini-tipped-for-october-launch-heres-why-im-excited-and-worried" target="_blank">screen </a>and the rumored HomePad with a screen, which should be Apple's next steps into smart home devices.</p><p>There's also the rumored <a href="https://www.tomsguide.com/computing/laptops/macbook-ultra-everything-we-know-so-far">MacBook Ultra</a>, a high-end version of Apple's Pro laptop with a touch display and OLED panel. Personally, I'm interested in the refreshed  <a href="https://www.tomsguide.com/entertainment/streaming-devices/apple-tv-4k-could-get-its-long-awaited-refresh-this-year-what-we-know-so-far">Apple TV 4K </a> with a faster chip and more Siri features. Though that has been rumored for years now and has yet to actually be released.</p><ul><li><strong>iPhone Ultra</strong></li><li><strong>iPhone 18 Pro and Pro Max</strong></li><li><strong>Apple Watch Series 12 and Ultra 4</strong></li><li><strong>AirPods 5</strong></li><li><strong>Apple TV 4K set-top box</strong></li><li><strong>HomePod mini</strong></li><li><strong>HomePad</strong></li><li><strong>iPad mini with OLED screen</strong></li><li><strong>M6 iMac refresh</strong></li><li><strong>M6 14-inch MacBook Pro refresh</strong></li><li><strong>MacBook Ultra</strong></li></ul><h2 id="in-development-for-2027">In development for 2027</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="tbGfgnwudZZvAWqyL687hg" name="Tim-Cook-Apple-Glasses-LEDE2" alt="Tim Cook with Apple Glass render" src="https://cdn.mos.cms.futurecdn.net/tbGfgnwudZZvAWqyL687hg.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Martin Hajek/ iDrop News/ Shutterstock/ Tom’s Guide)</span></figcaption></figure><p>Next year is when we could start seeing some truly updated designs for Apple's products from the all-glass iPhone 20 to redesigned Apple Watches and even more smart home products. </p><p>Some devices will be a simple chip refresh, like the M6 MacBook Air or the <a href="https://www.tomsguide.com/computing/macbooks/macbook-neo-could-get-these-two-major-performance-upgrades-in-2027-but-i-want-apple-to-fix-this-instead">A19 Pro MacBook Neo,</a> which proved so popular the first go-round that Apple <a href="https://www.tomsguide.com/computing/macbooks/macbook-neo-inventory-has-reportedly-sold-out-what-you-need-to-know">couldn't keep it in stock</a>.</p><p>A slew of iPads, from a refreshed <a href="https://www.tomsguide.com/computing/ipads/ipad-12-just-got-teased-by-an-accessory-maker-and-theres-a-disappointing-bit-of-news">iPad 12</a> to an <a href="https://www.tomsguide.com/computing/ipads/ipad-air-oled-tipped-for-long-overdue-2027-launch-but-at-what-cost">iPad Air OLED</a> are also expected next year.</p><p>iPhones will get weird next year starting in the spring where Apple <a href="https://www.tomsguide.com/phones/iphones/iphone-18-tipped-for-cost-cutting-downgrades-heres-what-we-know">splits the launch </a>of the iPhone 18 series. We should see the<a href="https://www.tomsguide.com/phones/iphone-18-release-just-tipped-for-major-shakeup-heres-when-all-the-new-models-could-launch"> vanilla iPhone 18</a>, alongside the iPhone 18e and<a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-rumors-5-biggest-expected-upgrades"> iPhone Air 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:1456px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="r2pW7STcGyqWJttRcb5SAH" name="iPhone 20 render" alt="iPhone 20 render" src="https://cdn.mos.cms.futurecdn.net/r2pW7STcGyqWJttRcb5SAH.jpg" mos="" align="middle" fullscreen="" width="1456" height="819" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: AppleTrack)</span></figcaption></figure><p>In the back half of the year, the 20th anniversary iPhone could feature one of the largest design changes in years. The biggest is a curvy all-glass wraparound design that seamlessly covers the entire phone. An analyst <a href="https://www.tomsguide.com/phones/iphones/all-glass-iphone-20-reportedly-canceled-20th-anniversary-iphone-hits-major-setback">claimed this design was canceled</a> in August, but Mark Gurman pushed back, saying that it's still on track. There are <a href="https://www.tomsguide.com/phones/iphones/new-iphone-20-video-reveals-the-8-biggest-upgrades-to-expect-from-the-20th-anniversary-iphone">more potential changes, </a>but the glass look will be immediately noticeable.</p><p>We were expecting to see <a href="https://www.tomsguide.com/audio/airpods/airpods-ultra-everything-we-know-so-far-about-apples-camera-earbuds">camera-laden AirPods</a> this year after leaked code and videos appeared, but Gurman claims these have been delayed until 2027. The cameras would enable Siri AI to "see" the world around you and respond to queries. People are voicing privacy concerns already, but presumably the cameras would not record photos or video.</p><p>Finally, <a href="https://www.tomsguide.com/computing/vr-ar/lighter-and-cheaper-apple-vision-pro-2-sounds-like-a-headset-youll-actually-buy-but-heres-why-you-shouldnt">Tim Cook was allegedly obsessed</a> with <a href="https://www.tomsguide.com/computing/smart-glasses/apple-glasses-everything-we-know-so-far">Apple Glasses</a>, but it's not clear if Ternus shares that same excitement. Apple's take on the form should arrive next year and be similar to the Meta Ray-Ban allowing you to take calls, pictures and videos but lacking a display. Rumors had slated the glasses for 2028 but a summer report claimed <a href="https://www.tomsguide.com/computing/smart-glasses/apple-is-rethinking-its-future-product-roadmap-after-losing-smart-glasses-chief-to-openai-analysts-say">Apple was rethinking its roadmap</a> after Vision head Paul Meade left for OpenAI.</p><ul><li><strong>M6 MacBook Air</strong></li><li><strong>A19 Pro MacBook Neo</strong></li><li><strong>Entry-level iPad refresh</strong></li><li><strong>iPad Air OLED</strong></li><li><strong>iPad Pro</strong></li><li><strong>New Apple Pencils</strong>.</li><li><strong>iPhone 18 and 18e</strong></li><li><strong>iPhone Air 2</strong></li><li><strong>M7 14-inch MacBook Pro</strong></li><li><strong>AirPods with cameras</strong></li><li><strong>In-home security sensor and system</strong>.</li><li><strong>Apple Glasses</strong></li><li><strong>iPhone 20 (XX)</strong></li><li><strong>iPhone Ultra 2</strong></li><li><strong>Redesigned Apple Watches</strong></li><li><strong>M7 Pro and M7 Max MacBooks</strong></li></ul><h2 id="2028-2029-and-beyond">2028, 2029 and beyond</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="h6GpFcSGTZ9Rtx4HpLMVE7" name="apple-campus.jpeg" alt="Apple Event" src="https://cdn.mos.cms.futurecdn.net/h6GpFcSGTZ9Rtx4HpLMVE7.jpeg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>The next batch of potential Apple devices could be released any time between 2028 and 2030. Some are chip and OLED updates, but a couple are new devices that we haven't seen from Apple before.</p><p>The <a href="https://www.tomsguide.com/home/smart-home/apples-next-big-thing-could-be-a-dollar1000-home-robot-ipad-combo">HomePod on a robot arm</a> was rumored two years ago and apparently will actually debut in the next couple of years. Per Gurman, this version will have a 9-inch display and advanced AI features. </p><p>Before the rumor mill settled on the foldable iPhone, Apple's first foldable device was actually supposed to be a  <a href="https://www.tomsguide.com/tablets/ipads/apple-reportedly-has-an-18-8-inch-foldable-ipad-prototype-with-under-display-face-id">giant foldable 18-inch iPad</a> or MacBook. Apparently, this is still in the works and <a href="https://www.tomsguide.com/computing/ipads/apples-giant-foldable-ipad-likely-wont-launch-until-2028-what-weve-heard">could launch in 2028</a>. Gurman claims manufacturing issues pushed a potential launch back.</p><p>Apple allegedly wants to release its own AR glasses à la the <a href="https://www.tomsguide.com/computing/smart-glasses/ive-been-wearing-the-meta-ray-ban-display-smart-glasses-for-24-hours-heres-what-i-like-and-hate">Meta Ray-Ban Display</a>. The glasses would superimpose data on your real-world view. There's no specific release year for these, but they could arrive before 2030.</p><p>Apple is apparently working on an AI pendant as well. <a href="https://www.tomsguide.com/computing/apples-ai-wearable-roadmap-is-getting-wild-prepare-for-ai-pendant-smart-glasses-and-airpods-with-cameras">The Apple version </a>would work with your iPhone and use AI and the camera for tasks.</p><ul><li><strong>HomePad with a robot arm</strong></li><li><strong>M7 Max and M7 Ultra Mac Studio</strong></li><li><strong>Apple Vision Pro revamp</strong></li><li><strong>AI Pendant</strong></li><li><strong>Larger foldable iPhone</strong></li><li><strong>Foldable iPad  </strong></li><li><strong>MacBook Air OLED</strong></li><li><strong>Higher-end iMac OLED</strong></li><li><strong>Augmented reality glasses</strong></li></ul><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/smart-home/apple-homepad-rumored-release-date-price-and-all-the-latest-leaks">Apple HomePad rumored release date, price and all the latest leaks</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-price-rumors-heres-how-much-you-can-expect-to-pay-for-apples-first-foldable">iPhone Ultra price rumors — here's how much you can expect to pay for Apple’s first foldable</a></li><li><a href="https://www.tomsguide.com/computing/laptops/nvidias-rtx-spark-n1x-drops-this-october-why-apple-silicon-should-be-terrified-and-our-price-predictions">Nvidia’s RTX Spark N1X launches this October: My price predictions for the potential MacBook Pro killer</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/computing/macbooks/huge-new-apple-report-details-all-41-products-coming-under-new-ceo-john-ternus</link>
                                                                            <description>
                            <![CDATA[ A massive report reveals about 41 devices that Apple could launch in the next three years. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">b6F32CnPvCcV3mLyRLeoJV</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/TrT3r6fXvJDENQATkwjnxN-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 04 Sep 2026 19:32:30 +0000</pubDate>                                                                                                                                <updated>Fri, 04 Sep 2026 22:28:53 +0000</updated>
                                                                                                                                            <category><![CDATA[MacBooks]]></category>
                                                    <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Apple TV]]></category>
                                                    <category><![CDATA[Smart Home]]></category>
                                                    <category><![CDATA[Smart Glasses]]></category>
                                                    <category><![CDATA[Computing Peripherals]]></category>
                                                    <category><![CDATA[Laptops]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                    <category><![CDATA[Entertainment]]></category>
                                                    <category><![CDATA[Streaming]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                    <category><![CDATA[VR & AR]]></category>
                                                                                                <author><![CDATA[ scott.younker@futurenet.com (Scott Younker) ]]></author>                    <dc:creator><![CDATA[ Scott Younker ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/RZsUpqcJ6Uj2q83oCUwNhQ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Scott Younker is the West Coast Reporter at Tom’s Guide. He covers all the latest tech news, including phones, computing and more. He’s been involved in tech since 2011 covering everything from cameras and swimming pool equipment to the latest gaming consoles and smart TVs. He is on a seemingly never ending hunt to build the easiest to use home media system. &lt;/p&gt;&lt;p&gt;Before Tom’s Guide, Scott worked for publications like &lt;em&gt;Digital Trends, Outdoor Photographer, Dead Beats Panel&lt;/em&gt;, and in a brief detour, &lt;em&gt;America’s Funniest Home Videos&lt;/em&gt;. Yes, he has seen more pratfalls, silly pets and ridiculous home movie fails than is reasonably healthy. &lt;/p&gt;&lt;p&gt;When not writing about the latest devices or advances in chipsets, be sure to ask about Scott about disc golf and sustainability, or just if you’re being cheeky, ask about his noodle arm. If you truly want to get nerdy, bring up board games and his ongoing losing streak. &lt;/p&gt;&lt;p&gt;Scott joined Tom&#039;s Guide in 2024 as the West Coast Reporter. He graduated from the School of Journalism at the University of Oregon with a degree in magazine journalism and a minor in communications. While there he blogged or wrote for several magazines including the Fluxx, Ethos and the Oregon Commentator. He briefly wrote and managed a moderately successful blog focused on web comics. &lt;br&gt;Send secure tips on Signal: scyo1.55.&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/TrT3r6fXvJDENQATkwjnxN-1280-80.jpg">
                                                            <media:credit><![CDATA[Getty Images]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[John Ternus in front of the Apple logo]]></media:description>                                                            <media:text><![CDATA[John Ternus in front of the Apple logo]]></media:text>
                                <media:title type="plain"><![CDATA[John Ternus in front of the Apple logo]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/TrT3r6fXvJDENQATkwjnxN-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>John Ternus has finally taken over as CEO of Apple, and his term could kickstart a wave of new and redefined Apple devices. It all starts next week with the <a href="https://www.tomsguide.com/phones/iphones/apple-sept-9-event-all-9-new-products-were-expecting-to-see">"Surprise and Shine" iPhone event</a>.</p><p>However, that's just the beginning, and <a href="https://www.bloomberg.com/news/articles/2026-09-04/what-to-expect-at-sept-9-apple-event-foldable-iphone-iphone-18-pro-watch">Bloomberg's Mark Gurman</a> just released a massive report that highlights 41 devices that could be released in the next three years and beyond. </p><p>That includes new devices like the foldable <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> and Apple's <a href="https://www.tomsguide.com/computing/smart-glasses/apple-glasses-everything-we-know-so-far">first foray into smart glasses</a>. </p><h2 id="later-2026-and-early-2027">Later 2026 and Early 2027</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="BXFPFEcaHQrVivQScPBNff" name="iPhone Ultra" alt="iPhone Ultra." src="https://cdn.mos.cms.futurecdn.net/BXFPFEcaHQrVivQScPBNff.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Most every device meant to launch in the next six months should arrive during one of two events: the September 9 iPhone soiree and an announcement in October or early November. </p><p>Mostly, the difference here is that new MacBooks are usually announced in mid-fall, usually with a new chipset. </p><p>The key devices to be aware of in the next few months include Apple's first foldable<a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-latest-release-date-rumors-heres-when-we-expect-it-to-launch" target="_blank"> iPhone</a><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-latest-release-date-rumors-heres-when-we-expect-it-to-launch"> Ultra</a> and the <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">iPhone 18 Pro</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max</a> models, all of which are expected to launch next week. There's also the first iPad mini <a href="https://www.tomsguide.com/computing/ipads/first-oled-ipad-mini-tipped-for-october-launch-heres-why-im-excited-and-worried">with an OLED </a><a href="https://www.tomsguide.com/computing/ipads/first-oled-ipad-mini-tipped-for-october-launch-heres-why-im-excited-and-worried" target="_blank">screen </a>and the rumored HomePad with a screen, which should be Apple's next steps into smart home devices.</p><p>There's also the rumored <a href="https://www.tomsguide.com/computing/laptops/macbook-ultra-everything-we-know-so-far">MacBook Ultra</a>, a high-end version of Apple's Pro laptop with a touch display and OLED panel. Personally, I'm interested in the refreshed  <a href="https://www.tomsguide.com/entertainment/streaming-devices/apple-tv-4k-could-get-its-long-awaited-refresh-this-year-what-we-know-so-far">Apple TV 4K </a> with a faster chip and more Siri features. Though that has been rumored for years now and has yet to actually be released.</p><ul><li><strong>iPhone Ultra</strong></li><li><strong>iPhone 18 Pro and Pro Max</strong></li><li><strong>Apple Watch Series 12 and Ultra 4</strong></li><li><strong>AirPods 5</strong></li><li><strong>Apple TV 4K set-top box</strong></li><li><strong>HomePod mini</strong></li><li><strong>HomePad</strong></li><li><strong>iPad mini with OLED screen</strong></li><li><strong>M6 iMac refresh</strong></li><li><strong>M6 14-inch MacBook Pro refresh</strong></li><li><strong>MacBook Ultra</strong></li></ul><h2 id="in-development-for-2027">In development for 2027</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="tbGfgnwudZZvAWqyL687hg" name="Tim-Cook-Apple-Glasses-LEDE2" alt="Tim Cook with Apple Glass render" src="https://cdn.mos.cms.futurecdn.net/tbGfgnwudZZvAWqyL687hg.jpg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Martin Hajek/ iDrop News/ Shutterstock/ Tom’s Guide)</span></figcaption></figure><p>Next year is when we could start seeing some truly updated designs for Apple's products from the all-glass iPhone 20 to redesigned Apple Watches and even more smart home products. </p><p>Some devices will be a simple chip refresh, like the M6 MacBook Air or the <a href="https://www.tomsguide.com/computing/macbooks/macbook-neo-could-get-these-two-major-performance-upgrades-in-2027-but-i-want-apple-to-fix-this-instead">A19 Pro MacBook Neo,</a> which proved so popular the first go-round that Apple <a href="https://www.tomsguide.com/computing/macbooks/macbook-neo-inventory-has-reportedly-sold-out-what-you-need-to-know">couldn't keep it in stock</a>.</p><p>A slew of iPads, from a refreshed <a href="https://www.tomsguide.com/computing/ipads/ipad-12-just-got-teased-by-an-accessory-maker-and-theres-a-disappointing-bit-of-news">iPad 12</a> to an <a href="https://www.tomsguide.com/computing/ipads/ipad-air-oled-tipped-for-long-overdue-2027-launch-but-at-what-cost">iPad Air OLED</a> are also expected next year.</p><p>iPhones will get weird next year starting in the spring where Apple <a href="https://www.tomsguide.com/phones/iphones/iphone-18-tipped-for-cost-cutting-downgrades-heres-what-we-know">splits the launch </a>of the iPhone 18 series. We should see the<a href="https://www.tomsguide.com/phones/iphone-18-release-just-tipped-for-major-shakeup-heres-when-all-the-new-models-could-launch"> vanilla iPhone 18</a>, alongside the iPhone 18e and<a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-rumors-5-biggest-expected-upgrades"> iPhone Air 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:1456px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="r2pW7STcGyqWJttRcb5SAH" name="iPhone 20 render" alt="iPhone 20 render" src="https://cdn.mos.cms.futurecdn.net/r2pW7STcGyqWJttRcb5SAH.jpg" mos="" align="middle" fullscreen="" width="1456" height="819" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: AppleTrack)</span></figcaption></figure><p>In the back half of the year, the 20th anniversary iPhone could feature one of the largest design changes in years. The biggest is a curvy all-glass wraparound design that seamlessly covers the entire phone. An analyst <a href="https://www.tomsguide.com/phones/iphones/all-glass-iphone-20-reportedly-canceled-20th-anniversary-iphone-hits-major-setback">claimed this design was canceled</a> in August, but Mark Gurman pushed back, saying that it's still on track. There are <a href="https://www.tomsguide.com/phones/iphones/new-iphone-20-video-reveals-the-8-biggest-upgrades-to-expect-from-the-20th-anniversary-iphone">more potential changes, </a>but the glass look will be immediately noticeable.</p><p>We were expecting to see <a href="https://www.tomsguide.com/audio/airpods/airpods-ultra-everything-we-know-so-far-about-apples-camera-earbuds">camera-laden AirPods</a> this year after leaked code and videos appeared, but Gurman claims these have been delayed until 2027. The cameras would enable Siri AI to "see" the world around you and respond to queries. People are voicing privacy concerns already, but presumably the cameras would not record photos or video.</p><p>Finally, <a href="https://www.tomsguide.com/computing/vr-ar/lighter-and-cheaper-apple-vision-pro-2-sounds-like-a-headset-youll-actually-buy-but-heres-why-you-shouldnt">Tim Cook was allegedly obsessed</a> with <a href="https://www.tomsguide.com/computing/smart-glasses/apple-glasses-everything-we-know-so-far">Apple Glasses</a>, but it's not clear if Ternus shares that same excitement. Apple's take on the form should arrive next year and be similar to the Meta Ray-Ban allowing you to take calls, pictures and videos but lacking a display. Rumors had slated the glasses for 2028 but a summer report claimed <a href="https://www.tomsguide.com/computing/smart-glasses/apple-is-rethinking-its-future-product-roadmap-after-losing-smart-glasses-chief-to-openai-analysts-say">Apple was rethinking its roadmap</a> after Vision head Paul Meade left for OpenAI.</p><ul><li><strong>M6 MacBook Air</strong></li><li><strong>A19 Pro MacBook Neo</strong></li><li><strong>Entry-level iPad refresh</strong></li><li><strong>iPad Air OLED</strong></li><li><strong>iPad Pro</strong></li><li><strong>New Apple Pencils</strong>.</li><li><strong>iPhone 18 and 18e</strong></li><li><strong>iPhone Air 2</strong></li><li><strong>M7 14-inch MacBook Pro</strong></li><li><strong>AirPods with cameras</strong></li><li><strong>In-home security sensor and system</strong>.</li><li><strong>Apple Glasses</strong></li><li><strong>iPhone 20 (XX)</strong></li><li><strong>iPhone Ultra 2</strong></li><li><strong>Redesigned Apple Watches</strong></li><li><strong>M7 Pro and M7 Max MacBooks</strong></li></ul><h2 id="2028-2029-and-beyond">2028, 2029 and beyond</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.30%;"><img id="h6GpFcSGTZ9Rtx4HpLMVE7" name="apple-campus.jpeg" alt="Apple Event" src="https://cdn.mos.cms.futurecdn.net/h6GpFcSGTZ9Rtx4HpLMVE7.jpeg" mos="" align="middle" fullscreen="" width="2000" height="1126" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Apple)</span></figcaption></figure><p>The next batch of potential Apple devices could be released any time between 2028 and 2030. Some are chip and OLED updates, but a couple are new devices that we haven't seen from Apple before.</p><p>The <a href="https://www.tomsguide.com/home/smart-home/apples-next-big-thing-could-be-a-dollar1000-home-robot-ipad-combo">HomePod on a robot arm</a> was rumored two years ago and apparently will actually debut in the next couple of years. Per Gurman, this version will have a 9-inch display and advanced AI features. </p><p>Before the rumor mill settled on the foldable iPhone, Apple's first foldable device was actually supposed to be a  <a href="https://www.tomsguide.com/tablets/ipads/apple-reportedly-has-an-18-8-inch-foldable-ipad-prototype-with-under-display-face-id">giant foldable 18-inch iPad</a> or MacBook. Apparently, this is still in the works and <a href="https://www.tomsguide.com/computing/ipads/apples-giant-foldable-ipad-likely-wont-launch-until-2028-what-weve-heard">could launch in 2028</a>. Gurman claims manufacturing issues pushed a potential launch back.</p><p>Apple allegedly wants to release its own AR glasses à la the <a href="https://www.tomsguide.com/computing/smart-glasses/ive-been-wearing-the-meta-ray-ban-display-smart-glasses-for-24-hours-heres-what-i-like-and-hate">Meta Ray-Ban Display</a>. The glasses would superimpose data on your real-world view. There's no specific release year for these, but they could arrive before 2030.</p><p>Apple is apparently working on an AI pendant as well. <a href="https://www.tomsguide.com/computing/apples-ai-wearable-roadmap-is-getting-wild-prepare-for-ai-pendant-smart-glasses-and-airpods-with-cameras">The Apple version </a>would work with your iPhone and use AI and the camera for tasks.</p><ul><li><strong>HomePad with a robot arm</strong></li><li><strong>M7 Max and M7 Ultra Mac Studio</strong></li><li><strong>Apple Vision Pro revamp</strong></li><li><strong>AI Pendant</strong></li><li><strong>Larger foldable iPhone</strong></li><li><strong>Foldable iPad  </strong></li><li><strong>MacBook Air OLED</strong></li><li><strong>Higher-end iMac OLED</strong></li><li><strong>Augmented reality glasses</strong></li></ul><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/home/smart-home/apple-homepad-rumored-release-date-price-and-all-the-latest-leaks">Apple HomePad rumored release date, price and all the latest leaks</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-price-rumors-heres-how-much-you-can-expect-to-pay-for-apples-first-foldable">iPhone Ultra price rumors — here's how much you can expect to pay for Apple’s first foldable</a></li><li><a href="https://www.tomsguide.com/computing/laptops/nvidias-rtx-spark-n1x-drops-this-october-why-apple-silicon-should-be-terrified-and-our-price-predictions">Nvidia’s RTX Spark N1X launches this October: My price predictions for the potential MacBook Pro killer</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone Ultra and iPhone 18 Pro prices predicted ahead of Apple event — here's what you could pay ]]></title>
                                                                                                <dc:content><![CDATA[ <p>In less than a week, 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> will officially reveal the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">Pro Max</a>, as well as the foldable <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a>. The latter is the company's first attempt to make one of the <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phones,</a> and the price is one of the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-price-rumors-heres-how-much-more-you-could-pay-this-year">biggest questions still left to answer</a>.</p><p>There's no doubt the iPhone Ultra is going to be a premium device, and a <strong>lot of internet chatter seems to back up the idea that it'll start at $1,999</strong>. That's what Bloomberg reporter Mark Gurman predicted when he <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-exclusive-gurman-on-price-release-date-and-secret-weapon-versus-android">spoke exclusively to Tom's Guide,</a> and it's less than the $2,500 (or even $3,000) price some analysts were predicting earlier this year.</p><div ><table><caption>New iPhone Prices</caption><tbody><tr><td class="firstcol " ><p><strong>Model</strong></p></td><td  ><p><strong>Price</strong></p></td><td  ></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro</strong></p></td><td  ><p>$1,099 – $1,199</p></td><td  ></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro Max</strong></p></td><td  ><p>$1,319 – $1,439</p></td><td  ></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra</strong></p></td><td  ><p>$2,099 – $2,299</p></td><td  ></td></tr></tbody></table></div><p><em>Source: Trendforce</em></p><p>This week, Australian pricing for the phones was shared on X and allegedly came from network carrier Vodafone (h/t <a href="https://x.com/ev_downunder/status/2095354055807889671" target="_blank">@ev_downunder</a> on X). It lists the base model at AU$3,699, which converts to roughly $2,666.</p><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2095354055807889671"><p lang="en" dir="ltr">Just confirmed with Vodafone Australia that the iPhone Fold will be available to pre-order on 12 Sep 2026!Leaked pricing:256GB: 3,699 AUD.512GB: 4,199 AUD.1TB: 4,699 AUD.<a href="https://twitter.com/cantworkitout/status/2095354055807889671">September 3, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>That<strong> direct comparison with US pricing isn't important</strong> — because pricing can vary based on things like tariffs. Instead, let's look at the <strong>percentage increase over the iPhone 17 Pro</strong>. In Australia, the iPhone Ultra would be 85% more expensive than last year's iPhone 17 Pro (AU$1,999). Applying that same logic to the USA, <strong>if the iPhone Ultra is 80% more expensive than last year's iPhone 17 Pro, the starting price would be about $1,999</strong>.</p><p>Leaks suggest the iPhone 18 Pro and iPhone 18 Pro Max will have a 10% and 11% price increase, respectively.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Oo209W"></div>                            </div>                            <script src="https://kwizly.com/embed/Oo209W.js" async></script><h2 id="analyst-predictions">Analyst predictions</h2><p>Yesterday, market research firm TrendForce released new analysis on the price of Apple's upcoming devices, and it paints a slightly more negative picture. According to the analysts, the iPhone 18 series and the iPhone Fold could see price rises of up to 20%.</p><p>"Given the weak global macroeconomic environment, more cautious consumer spending, and Apple’s strategy of continuing to expand its market presence, TrendForce expects the company to adopt a relatively moderate pricing approach," the researchers <a href="https://www.trendforce.com/presscenter/news/20260903-13213.html" target="_blank">wrote</a>. </p><p>"Prices for the new models are projected to rise by around 10–20%, with Apple absorbing some of the higher costs to help preserve market share.</p><p>"For the highly anticipated iPhone 18 Fold, improvements in crease reduction will be a key technological highlight, while its position as Apple’s first foldable will also make its pricing an important benchmark for future generations. TrendForce estimates that the device will carry a starting price of US$2,099–2,299, while top-end configurations could exceed $3,000."</p><h2 id="my-prediction">My 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:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="6FHyAxxnJefkHt5VktYaf3" name="iPhone Ultra half open.AppleTrack-2" alt="iPhone Ultra shown held in hand partially open" src="https://cdn.mos.cms.futurecdn.net/6FHyAxxnJefkHt5VktYaf3.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: AppleTrack)</span></figcaption></figure><p>Taking both the leaks and the latest research into account, I think Apple will attempt to bring the iPhone Ultra in at the $1,999 price for the starting configuration. It will allow the marketing team to pitch the device as "sub-$2,000," and then Apple will push the pricing up for the higher storage configurations.</p><p>Here's <strong>my own estimate of what the pricing for the new iPhones will be</strong>. We can see how close I came after the September 9 event:</p><div ><table><caption>iPhone 18 series pricing (predictions)</caption><tbody><tr><td class="firstcol " ><p><strong>Storage</strong></p></td><td  ><p><strong>iPhone 18 Pro</strong></p></td><td  ><p><strong>iPhone 18 Pro Max</strong></p></td><td  ><p><strong>iPhone Ultra</strong></p></td></tr><tr><td class="firstcol " ><p>256GB</p></td><td  ><p>$1,199 / £1,199</p></td><td  ><p>$1,299 / £1,299</p></td><td  ><p>$1,999 / £1,999</p></td></tr><tr><td class="firstcol " ><p>512GB</p></td><td  ><p>$1,399 / £1,399</p></td><td  ><p>$1,499 / £1,499</p></td><td  ><p>$2,399 / £2,399</p></td></tr><tr><td class="firstcol " ><p>1TB</p></td><td  ><p>$1,599 / £1,599  </p></td><td  ><p>$1,699 / £1,699</p></td><td  ><p>$2,699 / £2,699</p></td></tr><tr><td class="firstcol " ><p>2TB</p></td><td  ><p>N/A</p></td><td  ><p>$2,099 / £2,099</p></td><td  ><p>$3,099 / £3,099</p></td></tr></tbody></table></div><p>As you'll see, once you start to scale up the storage, the iPhone Ultra becomes eye-wateringly expensive. But the reason for that is simple: this is not meant to be a mass-market device. It's the same as the <a href="https://www.tomsguide.com/computing/smart-glasses/apple-vision-pro-review">Apple Vision Pro</a>, which also launched with an <a href="https://www.tomsguide.com/computing/vr-ar/i-just-tried-apple-vision-pro-for-the-first-time-3-things-i-liked-and-1-i-didnt">astronomically high price</a>. </p><p>The TrendForce research mentioned above also estimates that foldables will account for only around 2% of the global smartphone market in 2026. It's true that the market will expand — but for now, only a very small proportion of Apple fans and tech enthusiasts will buy the iPhone Ultra.</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/rQHEN3kngZo" allowfullscreen></iframe></div></div><p>If you've got your own thoughts on the iPhone Ultra or the new Pro phones, I'd love to hear about them in the comments below. Will you be making an upgrade this year? How much are you willing to spend? Let me know!</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-18-pro-max-vs-iphone-17-pro-max-5-biggest-rumored-upgrades">iPhone 18 Pro Max vs iPhone 17 Pro Max: 5 biggest rumored upgrades</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-price-rumors-heres-how-much-more-you-could-pay-this-year">iPhone 18 Pro and iPhone 18 Pro Max price rumors — here's how much more you could pay this year</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-price-rumors-heres-how-much-you-can-expect-to-pay-for-apples-first-foldable">iPhone Ultra price rumors — here's how much you can expect to pay for Apple’s first foldable</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-ultra-and-iphone-18-pro-prices-leak-days-before-apple-event-heres-my-final-bet-on-what-youll-pay</link>
                                                                            <description>
                            <![CDATA[ A recent leak from a network carrier gives us an indication of what the iPhone Ultra could cost when it launches next week. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">VkNJWjumGN9TnEXiMiP5b9</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/zzWJVAdVMiSAiHb5rnQrPZ-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 04 Sep 2026 11:11:51 +0000</pubDate>                                                                                                                                <updated>Sat, 05 Sep 2026 01:22:24 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ jeff.parsons@futurenet.com (Jeff Parsons) ]]></author>                    <dc:creator><![CDATA[ Jeff Parsons ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/7z3UTGGrmSokMKxTWHmhjX.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Jeff is U.K. Editor-in-Chief for Tom’s Guide looking after the day-to-day output of the site’s British contingent. &lt;/p&gt;&lt;p&gt;Rising early and heading straight for the coffee machine, Jeff loves nothing more than dialling into the zeitgeist of the day’s tech news. A journalist for over a decade, he&#039;s travelled around the world testing and reviewing any gadget he can get his hands on.&lt;/p&gt;&lt;p&gt;Before joining the team at Tom’s Guide, Jeff covered technology and science for two of the U.K.’s biggest national news sites: Metro.co.uk and the Daily Mirror. Memorable moments include getting lost in Vienna in an electric Audi, touring Lockheed Martin’s mile-long jet factory in Fort Worth and filming a Netflix documentary about Elon Musk in West London.&lt;/p&gt;&lt;p&gt;When not plugged into the current news agenda, editing or commissioning a series of articles or debating the merits of Apple vs Android, Jeff can usually be found out for a run trying to shave precious seconds off his PB. Or lifting weights in a vain attempt to offset the ageing process.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/zzWJVAdVMiSAiHb5rnQrPZ-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Ultra and iPhone 18 Pro Max]]></media:description>                                                            <media:text><![CDATA[iPhone Ultra and iPhone 18 Pro Max]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Ultra and iPhone 18 Pro Max]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/zzWJVAdVMiSAiHb5rnQrPZ-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>In less than a week, 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> will officially reveal the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">Pro Max</a>, as well as the foldable <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a>. The latter is the company's first attempt to make one of the <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phones,</a> and the price is one of the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-price-rumors-heres-how-much-more-you-could-pay-this-year">biggest questions still left to answer</a>.</p><p>There's no doubt the iPhone Ultra is going to be a premium device, and a <strong>lot of internet chatter seems to back up the idea that it'll start at $1,999</strong>. That's what Bloomberg reporter Mark Gurman predicted when he <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-exclusive-gurman-on-price-release-date-and-secret-weapon-versus-android">spoke exclusively to Tom's Guide,</a> and it's less than the $2,500 (or even $3,000) price some analysts were predicting earlier this year.</p><div ><table><caption>New iPhone Prices</caption><tbody><tr><td class="firstcol " ><p><strong>Model</strong></p></td><td  ><p><strong>Price</strong></p></td><td  ></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro</strong></p></td><td  ><p>$1,099 – $1,199</p></td><td  ></td></tr><tr><td class="firstcol " ><p><strong>iPhone 18 Pro Max</strong></p></td><td  ><p>$1,319 – $1,439</p></td><td  ></td></tr><tr><td class="firstcol " ><p><strong>iPhone Ultra</strong></p></td><td  ><p>$2,099 – $2,299</p></td><td  ></td></tr></tbody></table></div><p><em>Source: Trendforce</em></p><p>This week, Australian pricing for the phones was shared on X and allegedly came from network carrier Vodafone (h/t <a href="https://x.com/ev_downunder/status/2095354055807889671" target="_blank">@ev_downunder</a> on X). It lists the base model at AU$3,699, which converts to roughly $2,666.</p><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2095354055807889671"><p lang="en" dir="ltr">Just confirmed with Vodafone Australia that the iPhone Fold will be available to pre-order on 12 Sep 2026!Leaked pricing:256GB: 3,699 AUD.512GB: 4,199 AUD.1TB: 4,699 AUD.<a href="https://twitter.com/cantworkitout/status/2095354055807889671">September 3, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>That<strong> direct comparison with US pricing isn't important</strong> — because pricing can vary based on things like tariffs. Instead, let's look at the <strong>percentage increase over the iPhone 17 Pro</strong>. In Australia, the iPhone Ultra would be 85% more expensive than last year's iPhone 17 Pro (AU$1,999). Applying that same logic to the USA, <strong>if the iPhone Ultra is 80% more expensive than last year's iPhone 17 Pro, the starting price would be about $1,999</strong>.</p><p>Leaks suggest the iPhone 18 Pro and iPhone 18 Pro Max will have a 10% and 11% price increase, respectively.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Oo209W"></div>                            </div>                            <script src="https://kwizly.com/embed/Oo209W.js" async></script><h2 id="analyst-predictions">Analyst predictions</h2><p>Yesterday, market research firm TrendForce released new analysis on the price of Apple's upcoming devices, and it paints a slightly more negative picture. According to the analysts, the iPhone 18 series and the iPhone Fold could see price rises of up to 20%.</p><p>"Given the weak global macroeconomic environment, more cautious consumer spending, and Apple’s strategy of continuing to expand its market presence, TrendForce expects the company to adopt a relatively moderate pricing approach," the researchers <a href="https://www.trendforce.com/presscenter/news/20260903-13213.html" target="_blank">wrote</a>. </p><p>"Prices for the new models are projected to rise by around 10–20%, with Apple absorbing some of the higher costs to help preserve market share.</p><p>"For the highly anticipated iPhone 18 Fold, improvements in crease reduction will be a key technological highlight, while its position as Apple’s first foldable will also make its pricing an important benchmark for future generations. TrendForce estimates that the device will carry a starting price of US$2,099–2,299, while top-end configurations could exceed $3,000."</p><h2 id="my-prediction">My 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:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="6FHyAxxnJefkHt5VktYaf3" name="iPhone Ultra half open.AppleTrack-2" alt="iPhone Ultra shown held in hand partially open" src="https://cdn.mos.cms.futurecdn.net/6FHyAxxnJefkHt5VktYaf3.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: AppleTrack)</span></figcaption></figure><p>Taking both the leaks and the latest research into account, I think Apple will attempt to bring the iPhone Ultra in at the $1,999 price for the starting configuration. It will allow the marketing team to pitch the device as "sub-$2,000," and then Apple will push the pricing up for the higher storage configurations.</p><p>Here's <strong>my own estimate of what the pricing for the new iPhones will be</strong>. We can see how close I came after the September 9 event:</p><div ><table><caption>iPhone 18 series pricing (predictions)</caption><tbody><tr><td class="firstcol " ><p><strong>Storage</strong></p></td><td  ><p><strong>iPhone 18 Pro</strong></p></td><td  ><p><strong>iPhone 18 Pro Max</strong></p></td><td  ><p><strong>iPhone Ultra</strong></p></td></tr><tr><td class="firstcol " ><p>256GB</p></td><td  ><p>$1,199 / £1,199</p></td><td  ><p>$1,299 / £1,299</p></td><td  ><p>$1,999 / £1,999</p></td></tr><tr><td class="firstcol " ><p>512GB</p></td><td  ><p>$1,399 / £1,399</p></td><td  ><p>$1,499 / £1,499</p></td><td  ><p>$2,399 / £2,399</p></td></tr><tr><td class="firstcol " ><p>1TB</p></td><td  ><p>$1,599 / £1,599  </p></td><td  ><p>$1,699 / £1,699</p></td><td  ><p>$2,699 / £2,699</p></td></tr><tr><td class="firstcol " ><p>2TB</p></td><td  ><p>N/A</p></td><td  ><p>$2,099 / £2,099</p></td><td  ><p>$3,099 / £3,099</p></td></tr></tbody></table></div><p>As you'll see, once you start to scale up the storage, the iPhone Ultra becomes eye-wateringly expensive. But the reason for that is simple: this is not meant to be a mass-market device. It's the same as the <a href="https://www.tomsguide.com/computing/smart-glasses/apple-vision-pro-review">Apple Vision Pro</a>, which also launched with an <a href="https://www.tomsguide.com/computing/vr-ar/i-just-tried-apple-vision-pro-for-the-first-time-3-things-i-liked-and-1-i-didnt">astronomically high price</a>. </p><p>The TrendForce research mentioned above also estimates that foldables will account for only around 2% of the global smartphone market in 2026. It's true that the market will expand — but for now, only a very small proportion of Apple fans and tech enthusiasts will buy the iPhone Ultra.</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/rQHEN3kngZo" allowfullscreen></iframe></div></div><p>If you've got your own thoughts on the iPhone Ultra or the new Pro phones, I'd love to hear about them in the comments below. Will you be making an upgrade this year? How much are you willing to spend? Let me know!</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-18-pro-max-vs-iphone-17-pro-max-5-biggest-rumored-upgrades">iPhone 18 Pro Max vs iPhone 17 Pro Max: 5 biggest rumored upgrades</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-price-rumors-heres-how-much-more-you-could-pay-this-year">iPhone 18 Pro and iPhone 18 Pro Max price rumors — here's how much more you could pay this year</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-price-rumors-heres-how-much-you-can-expect-to-pay-for-apples-first-foldable">iPhone Ultra price rumors — here's how much you can expect to pay for Apple’s first foldable</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Apple HomePad rumored release date, price and all the latest leaks ]]></title>
                                                                                                <dc:content><![CDATA[ <p>At <a href="https://www.tomsguide.com/phones/iphones/apple-sept-9-event-all-9-new-products-were-expecting-to-see">Apple's "Surprise and Shine" event</a>, we're expected to see the new iPhone 18 lineup — including a <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-11-things-you-need-to-know-about-the-foldable-iphone-ahead-of-the-apple-event">foldable iPhone</a> — new AirPods, a new Apple Watch, and potentially, the long-awaited Apple HomePad, a new smart home device that combines a smart speaker and display in one. </p><p>Rumors of this device have been circulating for years, but it could finally be unveiled this week. Here's everything we know about the HomePad in advance.</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/dmRYxGgfHiM" allowfullscreen></iframe></div></div><h2 id="what-39-s-this-thing-going-to-be-called">What's this thing going to be called?</h2><p>One thing's for sure: No one quite knows what Apple is going to call this new device. It could be the HomePad, a portmanteau of HomePod and iPad, it could be called the HomeHub, or — and this would be the most boring option — HomePod Display.</p><h2 id="rumored-release-date-and-price">Rumored release date and price</h2><p>Apple's HomePad has been rumored to launch for several years now  — Bloomberg's <a href="https://www.bloomberg.com/news/articles/2024-11-12/apple-home-hub-detailed-apple-intelligence-homeos-square-ipad-like-design?utm_medium=social&cmpid=socialflow-twitter-business&utm_source=twitter&utm_campaign=socialflow-organic&utm_content=business" target="_blank">Marc Gurman originally reported</a> that we were going to see a wall-mounted device back in 2025 — but issues with Siri pushed things back.</p><p>However, now that Apple Intelligence has finally rolled out — and there's a new and improved <a href="https://www.tomsguide.com/ai/apple-finally-fixed-siri-heres-all-the-features-for-the-new-siri-ai-announced-at-wwdc">Siri AI</a> — Apple's new smart home device could actually come to pass this year. </p><p>Some reports have thrown around a price of $350 for the HomePad, which seems low, given that the <a href="https://www.tomsguide.com/reviews/apple-homepod-2nd-generation">HomePod 2</a> itself is $349; it used to cost $299, but component prices have driven it up by $50 since it launched. </p><p>If I had to guess, I would expect a tablet-like device to cost somewhere around $499.</p><h2 id="design">Design</h2><p>Apple's new smart home device will have a screen attached to some sort of speaker base. </p><p>My best guess is that it'll look something like the <a href="https://www.tomsguide.com/reviews/amazon-echo-show-10-3rd-gen">Amazon Echo Show 10 (3rd gen)</a>, which not only had an articulating screen, but could also turn to follow you around the room. However, with the advent of digital face tracking — something we've seen for years with Apple's Center Stage feature on its iPads and Macbooks — it's unlikely that the company would needlessly complicate things with something that moves mechanically.</p><p>Still, <a href="https://www.bloomberg.com/news/articles/2024-08-14/apple-pushes-ahead-with-tabletop-home-device-in-shift-to-robotics" target="_blank">separate rumors from two years ago</a> point to a tabletop robot that can do just that. Whether that's still on Apple's roadmap remains to be seen, as both Amazon's Echo Show 10 and the Facebook (Meta) Portal, which had a similar feature, have both been discontinued. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1225px;"><p class="vanilla-image-block" style="padding-top:54.86%;"><img id="3L5iH9oAM9MeQ6CKoBf8ce" name="Apple HomePad render on a wall" alt="What the Apple HomePad could look like mounted to a wall" src="https://cdn.mos.cms.futurecdn.net/3L5iH9oAM9MeQ6CKoBf8ce.png" mos="" align="middle" fullscreen="" width="1225" height="672" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: AppleTrack)</span></figcaption></figure><p>Apple could also be working on two variants of the HomePad: a tabletop version and a wall-mounted model, similar to the Amazon Echo Show 15 and 21. <a href="https://www.macrumors.com/2026/03/06/homepad-now-rumored-to-launch-even-later/" target="_blank">According to MacRumors</a>, the tabletop version could have a squarish 7-inch display, along with a front-facing camera. </p><h2 id="interface">Interface</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1078px;"><p class="vanilla-image-block" style="padding-top:68.00%;"><img id="fiFTZKs4eCZmfTmcxsb3xm" name="Apple HomePad rumored interface" alt="A rendering of what the HomePad interface could look like" src="https://cdn.mos.cms.futurecdn.net/fiFTZKs4eCZmfTmcxsb3xm.png" mos="" align="middle" fullscreen="" width="1078" height="733" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: AppleTrack)</span></figcaption></figure><p>While the HomePad may have a tablet as its face, it might function more like an Apple Watch than an iPad. That's at least according to <a href="https://www.engadget.com/2239524/things-i-learned-about-the-rumored-homepod-display-from-macos-beta-code/">one rumor reported by Engadget</a>, which found code references in OS Tahoe with Watch-like "faces," which will act like the wearable, rather than apps on the tablet. </p><p>Users will be able to pick apps from a Face Gallery, and the widgets could change throughout the day, to reflect different conditions both in and around your house. Additionally, the device will be able to recognize who's looking at it, and then tailor the display to that person's preferences.</p><h2 id="outlook-2">Outlook</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:937px;"><p class="vanilla-image-block" style="padding-top:56.78%;"><img id="UTT7t3hMzHYkrWjWJjmuk5" name="Apple HomePad render" alt="Apple HomePad render" src="https://cdn.mos.cms.futurecdn.net/UTT7t3hMzHYkrWjWJjmuk5.png" mos="" align="middle" fullscreen="" width="937" height="532" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: AppleTrack)</span></figcaption></figure><p>The Apple HomePad has been a long time coming, but is it too late? Amazon has its array of smart displays, but abandoned the form factor that Apple looks to be adopting. </p><p>Google, too, has also given up on a smart home display. The Google Pixel Tablet was meant to be not just an Android slate, but also a de facto smart home hub when connected to its dock. However, a year after it launched, Google no longer bundled the dock with the tablet, and a year after that, it discontinued the tablet entirely. </p><p>So, if Apple does launch a new smart home display, I will be very curious to see how it can differentiate itself from what's come before — and make a compelling argument for why it belongs in my house.</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/apple-sept-9-event-all-9-new-products-were-expecting-to-see"><strong>Apple Sept. 9 event — all 9 new products we're expecting to see</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone"><strong>iPhone Ultra rumored release date, price, colors and all the latest leaks</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far"><strong>iPhone 18 Pro Max rumors and leaks: Everything we know so far</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/home/smart-home/apple-homepad-rumored-release-date-price-and-all-the-latest-leaks</link>
                                                                            <description>
                            <![CDATA[ Apple could finally release the HomePad in 2026; here's what all the rumors are saying about this new smart home device. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">o2bccA85AEEXwsMfeLgU4D</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/B6MnXqXydDoWsymRMX2gHT-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Fri, 04 Sep 2026 10:30:00 +0000</pubDate>                                                                                                                                <updated>Tue, 08 Sep 2026 11:23:23 +0000</updated>
                                                                                                                                            <category><![CDATA[Smart Home]]></category>
                                                    <category><![CDATA[Home]]></category>
                                                                                                <author><![CDATA[ mike.prospero@futurenet.com (Mike Prospero) ]]></author>                    <dc:creator><![CDATA[ Mike Prospero ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/xeJFBrJwXQzCqXLZXBFBKQ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Michael A. Prospero is the U.S. Editor-in-Chief for Tom’s Guide.  In his spare time, he also tests out the latest drones, electric scooters, and smart home gadgets, such as video doorbells. Before his tenure at Tom&#039;s Guide, he was the Reviews Editor for Laptop Magazine, a reporter at Fast Company, the Times of Trenton, and, many eons back, an intern at George magazine. He received his undergraduate degree from Boston College, where he worked on the campus newspaper The Heights, and then attended the Columbia University school of Journalism. When he’s not testing out the latest running watch, electric scooter, or skiing or training for a marathon, he’s probably using the latest sous vide machine, smoker, or pizza oven, to the delight — or chagrin — of his family.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/png" url="https://cdn.mos.cms.futurecdn.net/B6MnXqXydDoWsymRMX2gHT-1280-80.png">
                                                            <media:credit><![CDATA[AppleTrack]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A render of what the Apple HomePad could look like]]></media:description>                                                            <media:text><![CDATA[A render of what the Apple HomePad could look like]]></media:text>
                                <media:title type="plain"><![CDATA[A render of what the Apple HomePad could look like]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/B6MnXqXydDoWsymRMX2gHT-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>At <a href="https://www.tomsguide.com/phones/iphones/apple-sept-9-event-all-9-new-products-were-expecting-to-see">Apple's "Surprise and Shine" event</a>, we're expected to see the new iPhone 18 lineup — including a <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-11-things-you-need-to-know-about-the-foldable-iphone-ahead-of-the-apple-event">foldable iPhone</a> — new AirPods, a new Apple Watch, and potentially, the long-awaited Apple HomePad, a new smart home device that combines a smart speaker and display in one. </p><p>Rumors of this device have been circulating for years, but it could finally be unveiled this week. Here's everything we know about the HomePad in advance.</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/dmRYxGgfHiM" allowfullscreen></iframe></div></div><h2 id="what-39-s-this-thing-going-to-be-called">What's this thing going to be called?</h2><p>One thing's for sure: No one quite knows what Apple is going to call this new device. It could be the HomePad, a portmanteau of HomePod and iPad, it could be called the HomeHub, or — and this would be the most boring option — HomePod Display.</p><h2 id="rumored-release-date-and-price">Rumored release date and price</h2><p>Apple's HomePad has been rumored to launch for several years now  — Bloomberg's <a href="https://www.bloomberg.com/news/articles/2024-11-12/apple-home-hub-detailed-apple-intelligence-homeos-square-ipad-like-design?utm_medium=social&cmpid=socialflow-twitter-business&utm_source=twitter&utm_campaign=socialflow-organic&utm_content=business" target="_blank">Marc Gurman originally reported</a> that we were going to see a wall-mounted device back in 2025 — but issues with Siri pushed things back.</p><p>However, now that Apple Intelligence has finally rolled out — and there's a new and improved <a href="https://www.tomsguide.com/ai/apple-finally-fixed-siri-heres-all-the-features-for-the-new-siri-ai-announced-at-wwdc">Siri AI</a> — Apple's new smart home device could actually come to pass this year. </p><p>Some reports have thrown around a price of $350 for the HomePad, which seems low, given that the <a href="https://www.tomsguide.com/reviews/apple-homepod-2nd-generation">HomePod 2</a> itself is $349; it used to cost $299, but component prices have driven it up by $50 since it launched. </p><p>If I had to guess, I would expect a tablet-like device to cost somewhere around $499.</p><h2 id="design">Design</h2><p>Apple's new smart home device will have a screen attached to some sort of speaker base. </p><p>My best guess is that it'll look something like the <a href="https://www.tomsguide.com/reviews/amazon-echo-show-10-3rd-gen">Amazon Echo Show 10 (3rd gen)</a>, which not only had an articulating screen, but could also turn to follow you around the room. However, with the advent of digital face tracking — something we've seen for years with Apple's Center Stage feature on its iPads and Macbooks — it's unlikely that the company would needlessly complicate things with something that moves mechanically.</p><p>Still, <a href="https://www.bloomberg.com/news/articles/2024-08-14/apple-pushes-ahead-with-tabletop-home-device-in-shift-to-robotics" target="_blank">separate rumors from two years ago</a> point to a tabletop robot that can do just that. Whether that's still on Apple's roadmap remains to be seen, as both Amazon's Echo Show 10 and the Facebook (Meta) Portal, which had a similar feature, have both been discontinued. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1225px;"><p class="vanilla-image-block" style="padding-top:54.86%;"><img id="3L5iH9oAM9MeQ6CKoBf8ce" name="Apple HomePad render on a wall" alt="What the Apple HomePad could look like mounted to a wall" src="https://cdn.mos.cms.futurecdn.net/3L5iH9oAM9MeQ6CKoBf8ce.png" mos="" align="middle" fullscreen="" width="1225" height="672" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: AppleTrack)</span></figcaption></figure><p>Apple could also be working on two variants of the HomePad: a tabletop version and a wall-mounted model, similar to the Amazon Echo Show 15 and 21. <a href="https://www.macrumors.com/2026/03/06/homepad-now-rumored-to-launch-even-later/" target="_blank">According to MacRumors</a>, the tabletop version could have a squarish 7-inch display, along with a front-facing camera. </p><h2 id="interface">Interface</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1078px;"><p class="vanilla-image-block" style="padding-top:68.00%;"><img id="fiFTZKs4eCZmfTmcxsb3xm" name="Apple HomePad rumored interface" alt="A rendering of what the HomePad interface could look like" src="https://cdn.mos.cms.futurecdn.net/fiFTZKs4eCZmfTmcxsb3xm.png" mos="" align="middle" fullscreen="" width="1078" height="733" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: AppleTrack)</span></figcaption></figure><p>While the HomePad may have a tablet as its face, it might function more like an Apple Watch than an iPad. That's at least according to <a href="https://www.engadget.com/2239524/things-i-learned-about-the-rumored-homepod-display-from-macos-beta-code/">one rumor reported by Engadget</a>, which found code references in OS Tahoe with Watch-like "faces," which will act like the wearable, rather than apps on the tablet. </p><p>Users will be able to pick apps from a Face Gallery, and the widgets could change throughout the day, to reflect different conditions both in and around your house. Additionally, the device will be able to recognize who's looking at it, and then tailor the display to that person's preferences.</p><h2 id="outlook-2">Outlook</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:937px;"><p class="vanilla-image-block" style="padding-top:56.78%;"><img id="UTT7t3hMzHYkrWjWJjmuk5" name="Apple HomePad render" alt="Apple HomePad render" src="https://cdn.mos.cms.futurecdn.net/UTT7t3hMzHYkrWjWJjmuk5.png" mos="" align="middle" fullscreen="" width="937" height="532" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: AppleTrack)</span></figcaption></figure><p>The Apple HomePad has been a long time coming, but is it too late? Amazon has its array of smart displays, but abandoned the form factor that Apple looks to be adopting. </p><p>Google, too, has also given up on a smart home display. The Google Pixel Tablet was meant to be not just an Android slate, but also a de facto smart home hub when connected to its dock. However, a year after it launched, Google no longer bundled the dock with the tablet, and a year after that, it discontinued the tablet entirely. </p><p>So, if Apple does launch a new smart home display, I will be very curious to see how it can differentiate itself from what's come before — and make a compelling argument for why it belongs in my house.</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/apple-sept-9-event-all-9-new-products-were-expecting-to-see"><strong>Apple Sept. 9 event — all 9 new products we're expecting to see</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone"><strong>iPhone Ultra rumored release date, price, colors and all the latest leaks</strong></a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far"><strong>iPhone 18 Pro Max rumors and leaks: Everything we know so far</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I held the Asus ProArt P14 next to my MacBook Pro 14 — and Apple should be genuinely terrified of Nvidia’s RTX Spark ]]></title>
                                                                                                <dc:content><![CDATA[ <p>As I keep saying, there’s a big two-device compromise problem. I love my 14-inch MacBook Pro for its rigidity, battery life, silent thermals, great ergonomics, and raw performance for my prosumer workload. But macOS locks me out of native PC gaming (mostly), so I need <em>another </em>machine to do that.</p><p>So when <a href="https://www.tomsguide.com/computing/laptops/nvidias-rtx-spark-n1x-drops-this-october-why-apple-silicon-should-be-terrified-and-our-price-predictions">Nvidia’s RTX Spark</a> was announced, I saw the possibility of a future daily driver pull into view — the everything machine I’d always wanted. And then when I held the Asus ProArt P14 in my right hand and the <a href="https://www.tomsguide.com/computing/macbooks/macbook-pro-m5-review">14-inch M5 MacBook Pro</a> in my left, it became clear I’d found my top pick of Team Green’s roster.</p><p>That’s because Asus didn’t just build a competitor; they pretty obviously reverse-engineered the MacBook Pro’s footprint and low-profile industrial aesthetic. It was going to take a lot to get me to switch from my Apple lifestyle, but coming as close to the Apple feel as possible is a helpful start, to say the least!</p><p>So for the first time, a Windows machine has the silicon architecture to challenge Apple Silicon, and Asus is packing it into a machine that rolls tanks onto the MacBook Pro’s turf.</p><h2 class="article-body__section" id="section-design-and-build-spotting-the-physical-differences"><span>Design and build: spotting the physical differences</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:2252px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="ctV2oQ993HC4K2YGEhyUp3" name="Asus ProArt P14 vs MacBook Pro M5-4" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/ctV2oQ993HC4K2YGEhyUp3.jpg" mos="" align="middle" fullscreen="" width="2252" height="1267" 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><div ><table><thead><tr><th class="firstcol " ><p>Laptop</p></th><th  ><p>Dimensions</p></th><th  ><p>Weight</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Asus ProArt P14</strong></p></td><td  ><p>12.2 x 8.6 x 0.6 inches</p></td><td  ><p>3.3 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>M5 MacBook Pro</strong></p></td><td  ><p>12.3 x 8.7 x 0.6 inches </p></td><td  ><p>3.4 pounds</p></td></tr></tbody></table></div><p>Stacking them directly, you can see how much Asus took inspiration from Apple, as the ProArt P14 matches the MacBook Pro 14 almost millimeter for millimeter. But there are subtle differences.</p><p>First is the finish. Apple’s anodized aluminum has a smoother, more metallic texture, whereas Asus’ stealthy matte charcoal coating has a much more interesting texture under your fingers.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1939px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="TEfbvPPiTx8rkw63wxqVp3" name="Asus ProArt P14 vs MacBook Pro M5-3" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/TEfbvPPiTx8rkw63wxqVp3.jpg" mos="" align="middle" fullscreen="" width="1939" height="1091" 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>And second is the weight balance. Holding them both one-handed, the Pro definitely feels denser, but the distribution feels better balanced. Whereas in the ProArt P14, it’s lighter but more heavily weighted toward thermal management at the back of the system (more on that later).</p><p>Ports-wise, both are effectively set up for creators with full-size HDMI, high-speed USB-C, a headphone jack, and a full-size SD card slot. But the ProArt flex here comes with the legacy USB-A port on the right flank — a minor detail that saves you from carrying dongles.</p><h3 class="article-body__section" id="section-screen-showdown-2-8k-oled-vs-liquid-retina-xdr"><span>Screen showdown: 2.8K OLED vs Liquid Retina XDR</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="YfDkKjavVW2VjBgLTRD9u3" name="Asus ProArt P14 vs MacBook Pro M5-2" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/YfDkKjavVW2VjBgLTRD9u3.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><div ><table><thead><tr><th class="firstcol " ><p>Laptop</p></th><th  ><p>Display</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Asus ProArt P14</strong></p></td><td  ><p>14-inch 2.8K (2800 x 1800) 16:10 OLED</p></td></tr><tr><td class="firstcol " ><p><strong>M5 MacBook Pro</strong></p></td><td  ><p>14.2-inch (3024 x 1964) Liquid Retina XDR Mini-LED</p></td></tr></tbody></table></div><p>So when it comes to picking between these screens, I know the default is to say “OLED is better,” but there are levels to this.</p><p>Because yes, the infinite contrast, instant pixel response times for gaming, zero blooming, and no camera notch give the ProArt P14 an advantage. It’s a gorgeous display — this is Asus’ bread and butter after all, as colors melt off the screen.</p><p>But the MacBook Pro (I’m assuming, as we won’t know until full testing — this is just based on what’s always happened before) will likely have a higher sustained peak brightness for outdoor work.</p><p>Really, it comes down to what you’re going to do with it. For gaming and color-accurate video grading in indoor/studio settings, the OLED wins on pure punch. However, for working out and about in bright coffee shops, Apple’s Mini-LED will probably retain the top spot.</p><h3 class="article-body__section" id="section-the-tactile-friction-point-key-feel-and-trackpad"><span>The tactile friction point: Key feel and trackpad</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2283px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="PjazzbgGFaXr5deUkzKUu3" name="Asus ProArt P14 vs MacBook Pro M5" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/PjazzbgGFaXr5deUkzKUu3.jpg" mos="" align="middle" fullscreen="" width="2283" height="1284" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The MacBook Pro has always been one of my favorites ergonomically speaking —packing shallow but snappy scissor keyboard switches set in a well. It feels familiar, reliable, and fatigue-free, but it does lack the travel for deep gaming presses.</p><p>Meanwhile, the ProArt P14’s keys have a deeper dish, a little more key travel, and a softer landing underneath. The added depth creates a more satisfying impact, and the WASD stability for gaming feels a little better. But the slight added mushiness may come back to haunt me if I type all day.</p><p>Then there’s the trackpads. Now don’t get me wrong, the ProArt’s physical trackpad is massive and smooth, with a nice tactility to the physical click. But Apple’s Force Touch haptics are basically witchcraft, with an identical click anywhere on the glass and zero chance of any mechanical dead zones.</p><h3 class="article-body__section" id="section-under-the-hood"><span>Under the hood</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9i5mcD3e3DmixKtuq3mnzU" name="Asus ProArt P14 vs MacBook Pro M5" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/9i5mcD3e3DmixKtuq3mnzU.jpg" mos="" align="middle" fullscreen="" width="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>Currently, I’m on an M5 MacBook Pro, but you can spec it up to M5 Pro or M5 Max with unified memory shared between CPU and GPU cores. The end result is lightning-fast performance across all your tasks that has always been one step ahead of the competition from Qualcomm, Intel, and AMD.</p><p>And now, the ProArt P14 is taking on Apple with the RTX Spark N1X platform — marrying an Arm-based Nvidia Grace CPU with a dedicated Blackwell RTX GPU, backed up by up to 128GB of unified memory.</p><p>In terms of how much you can spec it, ProArt P14 configurations start from that baseline N1X with fewer cores and 24GB of memory, so the versatility of configs means you can run the full gamut against the MacBook 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="5X7LesSj9fyDU8yrouBoSU" name="Asus ProArt P14 vs MacBook Pro M5" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/5X7LesSj9fyDU8yrouBoSU.jpg" mos="" align="middle" fullscreen="" width="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’s machine falls down in modern AAA PC gaming backlogs — some of it works through Metal compatibility, but most will be left to crippling emulation or cloud streaming.</p><p>But with N1X’s CUDA cores, the ProArt P14 can run 1440p games at 100 FPS, complete with DLSS support and anti-cheat compatibility. Beyond that, I expect they’ll be pretty evenly matched in creator performance and AI. Differences there will come down to the software optimization for the silicon.</p><h3 class="article-body__section" id="section-the-potential-dealbreakers"><span>The potential dealbreakers</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="pbfBZx7ZmNxAR8JxpPcEHU" name="Asus ProArt P14 vs MacBook Pro M5" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/pbfBZx7ZmNxAR8JxpPcEHU.jpg" mos="" align="middle" fullscreen="" width="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’m just going to summarize some quick things that may become the thorn in the ProArt P14’s side once we get one in the labs to fully test.</p><ul><li><strong>The fan noise: </strong>When I tested the <a href="https://www.tomsguide.com/computing/gaming-laptops/i-tested-6-rtx-spark-laptops-for-gaming-and-the-winner-completely-shocked-me">ProArt P14 for gaming</a>, it was the loudest RTX Spark laptop in the room. The MacBook Pro stays near-silent during everyday tasks, and hopefully the P14 is the same — but it’s clear that an insane amount of Nvidia silicon requires aggressive airflow.</li><li><strong>Battery endurance: </strong>Nvidia is claiming “all-day” battery life and the same performance both on and off the charger. During my testing, I can confirm the latter, but we don’t know about the former yet! If it can achieve that 12-14+ hours of mixed real-world productivity, Apple loses its biggest single advantage.</li><li><strong>The price: </strong>The MacBook Pro starts at $1,999. To get the equivalent amount of memory (24GB), that price goes up to $2,199. This is the big question mark for N1X laptops, and hopefully they’ll be competitive on cost.</li></ul><h2 class="article-body__section" id="section-early-verdict"><span>Early verdict</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="RPrRBEsYKHxXze25EpotYU" name="Asus ProArt P14 vs MacBook Pro M5" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/RPrRBEsYKHxXze25EpotYU.jpg" mos="" align="middle" fullscreen="" width="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 way-too-early verdict, as I’m piecing together the few times I’ve had to test the ProArt P14 and its potential against months of MacBook Pro use. But I’ll give it a stab.</p><section class="howto-block">                    <h3>Switch to the Asus ProArt P14 if</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/r2srK5bDXmnczCLfapywsU.jpg"                                        alt="Asus ProArt P14 vs MacBook Pro M5"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/r2srK5bDXmnczCLfapywsU.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>You refuse to carry two laptops ever again. If you want a sleek, premium aluminum daily driver that can handle your prosumer work by day and play games by night, the ProArt P14 is the first Windows laptop that really steps on the MacBook Pro's throat.</p></p>                </section><section class="howto-block">                    <h3>Stick with the MacBook Pro 14 if</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/aeAsuGHPsdeNftt767USaK.jpg"                                        alt="MacBook Pro M5"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/aeAsuGHPsdeNftt767USaK.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Tom's Guide)</div></figure>                    <p><p>Gaming isn't a priority; you prioritize whisper-quiet operation, a uniform haptic trackpad, and a pure macOS creative pipeline. Battery endurance is proven on this machine, but the jury’s still out until we get the P14 in for testing.</p></p>                </section><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/gaming/handheld-gaming/i-tested-acers-wild-flip-and-swivel-handheld-why-project-dualplay-mini-is-the-ultimate-netbook-love-letter">I tested Acer’s wild flip-and-swivel handheld — why Project DualPlay Mini is the ultimate netbook love letter</a></li><li><a href="https://www.tomsguide.com/gaming/pc-gaming/i-tested-the-real-dlss-5-forget-the-leaked-mods-its-not-an-ai-filter-this-is-nvidias-photorealistic-game-changer">I wanted to hate Nvidia’s DLSS 5 ‘AI filter’ — but the real DLSS 5 is photorealistic black magic</a></li><li><a href="https://www.tomsguide.com/gaming/playstation/as-a-pc-snob-i-wanted-to-catch-gta-6-making-console-compromises-instead-im-in-awe-of-the-trickery">As a PC snob, I wanted to catch GTA 6 making console compromises. Instead, I’m in awe of the trickery</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/computing/laptops/macbook-pro-14-inch-vs-asus-proart-p14-nvidia-rtx-spark</link>
                                                                            <description>
                            <![CDATA[ I compared the Asus ProArt P14 directly against the MacBook Pro 14. With an Nvidia RTX Spark N1X inside, here is why Apple Silicon faces its biggest threat. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">33izTM5yiYMybq5eKoynuK</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/J3R2bCJ8gw5H7tBVt5kWvC-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 04 Sep 2026 09:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Laptops]]></category>
                                                    <category><![CDATA[Computing Peripherals]]></category>
                                                                                                                    <dc:creator><![CDATA[ Jason England ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/v4fSq5U4uZUEtGY2BwNuJ6.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Jason brings a decade of tech and gaming journalism experience to his role as a Managing Editor of Computing at Tom&#039;s Guide. He has previously written for Laptop Mag, Tom&#039;s Hardware, Kotaku, Stuff and BBC Science Focus. In his spare time, you&#039;ll find Jason looking for good dogs to pet or thinking about eating pizza if he isn&#039;t already.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <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/J3R2bCJ8gw5H7tBVt5kWvC-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Asus ProArt P14 vs MacBook Pro M5]]></media:description>                                                            <media:text><![CDATA[Asus ProArt P14 vs MacBook Pro M5]]></media:text>
                                <media:title type="plain"><![CDATA[Asus ProArt P14 vs MacBook Pro M5]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/J3R2bCJ8gw5H7tBVt5kWvC-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>As I keep saying, there’s a big two-device compromise problem. I love my 14-inch MacBook Pro for its rigidity, battery life, silent thermals, great ergonomics, and raw performance for my prosumer workload. But macOS locks me out of native PC gaming (mostly), so I need <em>another </em>machine to do that.</p><p>So when <a href="https://www.tomsguide.com/computing/laptops/nvidias-rtx-spark-n1x-drops-this-october-why-apple-silicon-should-be-terrified-and-our-price-predictions">Nvidia’s RTX Spark</a> was announced, I saw the possibility of a future daily driver pull into view — the everything machine I’d always wanted. And then when I held the Asus ProArt P14 in my right hand and the <a href="https://www.tomsguide.com/computing/macbooks/macbook-pro-m5-review">14-inch M5 MacBook Pro</a> in my left, it became clear I’d found my top pick of Team Green’s roster.</p><p>That’s because Asus didn’t just build a competitor; they pretty obviously reverse-engineered the MacBook Pro’s footprint and low-profile industrial aesthetic. It was going to take a lot to get me to switch from my Apple lifestyle, but coming as close to the Apple feel as possible is a helpful start, to say the least!</p><p>So for the first time, a Windows machine has the silicon architecture to challenge Apple Silicon, and Asus is packing it into a machine that rolls tanks onto the MacBook Pro’s turf.</p><h2 class="article-body__section" id="section-design-and-build-spotting-the-physical-differences"><span>Design and build: spotting the physical differences</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:2252px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="ctV2oQ993HC4K2YGEhyUp3" name="Asus ProArt P14 vs MacBook Pro M5-4" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/ctV2oQ993HC4K2YGEhyUp3.jpg" mos="" align="middle" fullscreen="" width="2252" height="1267" 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><div ><table><thead><tr><th class="firstcol " ><p>Laptop</p></th><th  ><p>Dimensions</p></th><th  ><p>Weight</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Asus ProArt P14</strong></p></td><td  ><p>12.2 x 8.6 x 0.6 inches</p></td><td  ><p>3.3 pounds</p></td></tr><tr><td class="firstcol " ><p><strong>M5 MacBook Pro</strong></p></td><td  ><p>12.3 x 8.7 x 0.6 inches </p></td><td  ><p>3.4 pounds</p></td></tr></tbody></table></div><p>Stacking them directly, you can see how much Asus took inspiration from Apple, as the ProArt P14 matches the MacBook Pro 14 almost millimeter for millimeter. But there are subtle differences.</p><p>First is the finish. Apple’s anodized aluminum has a smoother, more metallic texture, whereas Asus’ stealthy matte charcoal coating has a much more interesting texture under your fingers.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1939px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="TEfbvPPiTx8rkw63wxqVp3" name="Asus ProArt P14 vs MacBook Pro M5-3" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/TEfbvPPiTx8rkw63wxqVp3.jpg" mos="" align="middle" fullscreen="" width="1939" height="1091" 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>And second is the weight balance. Holding them both one-handed, the Pro definitely feels denser, but the distribution feels better balanced. Whereas in the ProArt P14, it’s lighter but more heavily weighted toward thermal management at the back of the system (more on that later).</p><p>Ports-wise, both are effectively set up for creators with full-size HDMI, high-speed USB-C, a headphone jack, and a full-size SD card slot. But the ProArt flex here comes with the legacy USB-A port on the right flank — a minor detail that saves you from carrying dongles.</p><h3 class="article-body__section" id="section-screen-showdown-2-8k-oled-vs-liquid-retina-xdr"><span>Screen showdown: 2.8K OLED vs Liquid Retina XDR</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="YfDkKjavVW2VjBgLTRD9u3" name="Asus ProArt P14 vs MacBook Pro M5-2" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/YfDkKjavVW2VjBgLTRD9u3.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><div ><table><thead><tr><th class="firstcol " ><p>Laptop</p></th><th  ><p>Display</p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Asus ProArt P14</strong></p></td><td  ><p>14-inch 2.8K (2800 x 1800) 16:10 OLED</p></td></tr><tr><td class="firstcol " ><p><strong>M5 MacBook Pro</strong></p></td><td  ><p>14.2-inch (3024 x 1964) Liquid Retina XDR Mini-LED</p></td></tr></tbody></table></div><p>So when it comes to picking between these screens, I know the default is to say “OLED is better,” but there are levels to this.</p><p>Because yes, the infinite contrast, instant pixel response times for gaming, zero blooming, and no camera notch give the ProArt P14 an advantage. It’s a gorgeous display — this is Asus’ bread and butter after all, as colors melt off the screen.</p><p>But the MacBook Pro (I’m assuming, as we won’t know until full testing — this is just based on what’s always happened before) will likely have a higher sustained peak brightness for outdoor work.</p><p>Really, it comes down to what you’re going to do with it. For gaming and color-accurate video grading in indoor/studio settings, the OLED wins on pure punch. However, for working out and about in bright coffee shops, Apple’s Mini-LED will probably retain the top spot.</p><h3 class="article-body__section" id="section-the-tactile-friction-point-key-feel-and-trackpad"><span>The tactile friction point: Key feel and trackpad</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2283px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="PjazzbgGFaXr5deUkzKUu3" name="Asus ProArt P14 vs MacBook Pro M5" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/PjazzbgGFaXr5deUkzKUu3.jpg" mos="" align="middle" fullscreen="" width="2283" height="1284" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The MacBook Pro has always been one of my favorites ergonomically speaking —packing shallow but snappy scissor keyboard switches set in a well. It feels familiar, reliable, and fatigue-free, but it does lack the travel for deep gaming presses.</p><p>Meanwhile, the ProArt P14’s keys have a deeper dish, a little more key travel, and a softer landing underneath. The added depth creates a more satisfying impact, and the WASD stability for gaming feels a little better. But the slight added mushiness may come back to haunt me if I type all day.</p><p>Then there’s the trackpads. Now don’t get me wrong, the ProArt’s physical trackpad is massive and smooth, with a nice tactility to the physical click. But Apple’s Force Touch haptics are basically witchcraft, with an identical click anywhere on the glass and zero chance of any mechanical dead zones.</p><h3 class="article-body__section" id="section-under-the-hood"><span>Under the hood</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9i5mcD3e3DmixKtuq3mnzU" name="Asus ProArt P14 vs MacBook Pro M5" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/9i5mcD3e3DmixKtuq3mnzU.jpg" mos="" align="middle" fullscreen="" width="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>Currently, I’m on an M5 MacBook Pro, but you can spec it up to M5 Pro or M5 Max with unified memory shared between CPU and GPU cores. The end result is lightning-fast performance across all your tasks that has always been one step ahead of the competition from Qualcomm, Intel, and AMD.</p><p>And now, the ProArt P14 is taking on Apple with the RTX Spark N1X platform — marrying an Arm-based Nvidia Grace CPU with a dedicated Blackwell RTX GPU, backed up by up to 128GB of unified memory.</p><p>In terms of how much you can spec it, ProArt P14 configurations start from that baseline N1X with fewer cores and 24GB of memory, so the versatility of configs means you can run the full gamut against the MacBook 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="5X7LesSj9fyDU8yrouBoSU" name="Asus ProArt P14 vs MacBook Pro M5" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/5X7LesSj9fyDU8yrouBoSU.jpg" mos="" align="middle" fullscreen="" width="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’s machine falls down in modern AAA PC gaming backlogs — some of it works through Metal compatibility, but most will be left to crippling emulation or cloud streaming.</p><p>But with N1X’s CUDA cores, the ProArt P14 can run 1440p games at 100 FPS, complete with DLSS support and anti-cheat compatibility. Beyond that, I expect they’ll be pretty evenly matched in creator performance and AI. Differences there will come down to the software optimization for the silicon.</p><h3 class="article-body__section" id="section-the-potential-dealbreakers"><span>The potential dealbreakers</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="pbfBZx7ZmNxAR8JxpPcEHU" name="Asus ProArt P14 vs MacBook Pro M5" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/pbfBZx7ZmNxAR8JxpPcEHU.jpg" mos="" align="middle" fullscreen="" width="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’m just going to summarize some quick things that may become the thorn in the ProArt P14’s side once we get one in the labs to fully test.</p><ul><li><strong>The fan noise: </strong>When I tested the <a href="https://www.tomsguide.com/computing/gaming-laptops/i-tested-6-rtx-spark-laptops-for-gaming-and-the-winner-completely-shocked-me">ProArt P14 for gaming</a>, it was the loudest RTX Spark laptop in the room. The MacBook Pro stays near-silent during everyday tasks, and hopefully the P14 is the same — but it’s clear that an insane amount of Nvidia silicon requires aggressive airflow.</li><li><strong>Battery endurance: </strong>Nvidia is claiming “all-day” battery life and the same performance both on and off the charger. During my testing, I can confirm the latter, but we don’t know about the former yet! If it can achieve that 12-14+ hours of mixed real-world productivity, Apple loses its biggest single advantage.</li><li><strong>The price: </strong>The MacBook Pro starts at $1,999. To get the equivalent amount of memory (24GB), that price goes up to $2,199. This is the big question mark for N1X laptops, and hopefully they’ll be competitive on cost.</li></ul><h2 class="article-body__section" id="section-early-verdict"><span>Early verdict</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="RPrRBEsYKHxXze25EpotYU" name="Asus ProArt P14 vs MacBook Pro M5" alt="Asus ProArt P14 vs MacBook Pro M5" src="https://cdn.mos.cms.futurecdn.net/RPrRBEsYKHxXze25EpotYU.jpg" mos="" align="middle" fullscreen="" width="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 way-too-early verdict, as I’m piecing together the few times I’ve had to test the ProArt P14 and its potential against months of MacBook Pro use. But I’ll give it a stab.</p><section class="howto-block">                    <h3>Switch to the Asus ProArt P14 if</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/r2srK5bDXmnczCLfapywsU.jpg"                                        alt="Asus ProArt P14 vs MacBook Pro M5"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/r2srK5bDXmnczCLfapywsU.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Future)</div></figure>                    <p><p>You refuse to carry two laptops ever again. If you want a sleek, premium aluminum daily driver that can handle your prosumer work by day and play games by night, the ProArt P14 is the first Windows laptop that really steps on the MacBook Pro's throat.</p></p>                </section><section class="howto-block">                    <h3>Stick with the MacBook Pro 14 if</h3>                    <figure>                            <p class="bordeaux-image-check">                                <img    src="https://cdn.mos.cms.futurecdn.net/aeAsuGHPsdeNftt767USaK.jpg"                                        alt="MacBook Pro M5"                                        onerror="this.parentNode.replaceChild(window.missingImage(),this)"                                        data-pin-media="https://cdn.mos.cms.futurecdn.net/aeAsuGHPsdeNftt767USaK.jpg"                                        class="expandable van-old-layout-image">                            </p><div class="credit">(Image: © Tom's Guide)</div></figure>                    <p><p>Gaming isn't a priority; you prioritize whisper-quiet operation, a uniform haptic trackpad, and a pure macOS creative pipeline. Battery endurance is proven on this machine, but the jury’s still out until we get the P14 in for testing.</p></p>                </section><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/gaming/handheld-gaming/i-tested-acers-wild-flip-and-swivel-handheld-why-project-dualplay-mini-is-the-ultimate-netbook-love-letter">I tested Acer’s wild flip-and-swivel handheld — why Project DualPlay Mini is the ultimate netbook love letter</a></li><li><a href="https://www.tomsguide.com/gaming/pc-gaming/i-tested-the-real-dlss-5-forget-the-leaked-mods-its-not-an-ai-filter-this-is-nvidias-photorealistic-game-changer">I wanted to hate Nvidia’s DLSS 5 ‘AI filter’ — but the real DLSS 5 is photorealistic black magic</a></li><li><a href="https://www.tomsguide.com/gaming/playstation/as-a-pc-snob-i-wanted-to-catch-gta-6-making-console-compromises-instead-im-in-awe-of-the-trickery">As a PC snob, I wanted to catch GTA 6 making console compromises. Instead, I’m in awe of the trickery</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 15 best Apple Labor Day deals — AirPods, iPads and MacBooks from just $99 ]]></title>
                                                                                                <dc:content><![CDATA[ <p><a href="https://www.tomsguide.com/computing/laptops/labor-day-sales-2026-my-ultimate-guide-to-the-best-end-of-summer-deals">Labor Day </a>weekend brings some of the biggest sales of the summer, making it the perfect time to score a great deal before the season comes to an end. Apple products are no exception. If you’re in the market for some new tech, Amazon is offering attractive discounts on a wide range of premium Apple devices.</p><p>Right now, you can <a href="https://www.amazon.com/stores/Apple/page/77D9E1F7-0337-4282-9DB6-B6B8FB2DC98D?" target="_blank" rel="nofollow">shop deals on AirPods, iPads, MacBooks, accessories and more</a>. One of my favorite finds is <a href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQV9W97Q" target="_blank" rel="nofollow">$100 off the iPad 11" (Wi-Fi/128GB)</a>. You can also grab the <a href="https://www.amazon.com/dp/B0DGHMNQ5Z/" target="_blank" rel="nofollow">Apple AirPods 4 for just $99</a> or <a href="https://www.amazon.com/dp/B0GR6BVYS5" target="_blank" rel="nofollow">the MacBook Neo for just $689</a>. Plus, there's  tons of must-have accessories starting at $14. </p><p>Sure, these aren't the lowest prices we've ever seen on the popular products, but the deals are certainly still worth considering. So if you're ready to upgrade your tech for the new season (without spending a fortune) take a look at these rare Apple deals. </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong></strong><a href="https://www.amazon.com/stores/Apple/page/77D9E1F7-0337-4282-9DB6-B6B8FB2DC98D?" target="_blank" rel="nofollow"><strong>shop all Apple deals on Amazon</strong></a><strong>   </strong></li><li><strong>Apple EarPods (Lightning): </strong><a href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow"><strong>was $19 now $14</strong></a></li><li><strong>Apple AirTag: </strong><a href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow"><strong>was $29 now $24</strong></a></li><li><strong>AirPods 4: </strong><a href="https://www.amazon.com/Apple-Bluetooth-Headphones-Personalized-Effortless/dp/B0DGHMNQ5Z" target="_blank" rel="nofollow"><strong>was $129 now $99</strong></a></li><li><strong>Apple iPad 11" (Wi-Fi/128GB): </strong><a href="https://www.amazon.com/Apple-iPad-11-inch-Display-All-Day/dp/B0DZ7871B8?" target="_blank" rel="nofollow"><strong>was $449 now $399</strong></a></li><li><strong>AirPods Max 2: </strong><a href="https://www.amazon.com/dp/B0GSRYXZM5?th=1" target="_blank" rel="nofollow"><strong>was $549 now $479</strong></a></li><li><strong>11" iPad Air (M4): </strong><a href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQV9W97Q" target="_blank" rel="nofollow"><strong>was $749 now $649</strong></a></li><li><strong>15" MacBook Air (M5): </strong><a href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" target="_blank" rel="nofollow"><strong>was $1,499 now $1,459</strong></a></li></ul><h3 class="article-body__section" id="section-accessories"><span>Accessories</span></h3><div class="product"><a data-dimension112="6ec03854-a79f-11f1-9244-9d400cdded84" data-action="Deal Block" data-label="EarPods (Lightning)" data-dimension48="EarPods (Lightning)" data-dimension25="$14" href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1040px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Ys3T2v7S48cnc2sK2hLS9U" name="apple earpods with lightning connector.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Ys3T2v7S48cnc2sK2hLS9U.jpg" mos="" align="middle" fullscreen="" width="1040" height="1040" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow" data-dimension112="6ec03854-a79f-11f1-9244-9d400cdded84" data-action="Deal Block" data-label="EarPods (Lightning)" data-dimension48="EarPods (Lightning)" data-dimension25="$14">EarPods (Lightning): was $19 now $14</a></strong><br>If you like listening to your music the old-fashioned way, this pair of wired EarPods has a Lightning connector, allowing them to be used with older Apple devices. For this price, you might as well grab a pair!<a class="view-deal button" href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow" data-dimension112="6ec03854-a79f-11f1-9244-9d400cdded84" data-action="Deal Block" data-label="EarPods (Lightning)" data-dimension48="EarPods (Lightning)" data-dimension25="$14">View Deal</a></p></div><div class="product"><a data-dimension112="6ec038b8-a79f-11f1-984a-61415f55f1e7" data-action="Deal Block" data-label="20W USB-C Compact Power Adapter" data-dimension48="20W USB-C Compact Power Adapter" data-dimension25="$14" href="https://www.amazon.com/Apple-20W-USB-C-Power-Adapter/dp/B0DJFW7PNM" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:649px;"><p class="vanilla-image-block" style="padding-top:149.61%;"><img id="mhEQ7c2rj34AhoPSdBToNX" name="20W USB-C Compact Power Adapter" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mhEQ7c2rj34AhoPSdBToNX.jpg" mos="" align="middle" fullscreen="" width="649" height="971" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-20W-USB-C-Power-Adapter/dp/B0DJFW7PNM" target="_blank" rel="nofollow" data-dimension112="6ec038b8-a79f-11f1-984a-61415f55f1e7" data-action="Deal Block" data-label="20W USB-C Compact Power Adapter" data-dimension48="20W USB-C Compact Power Adapter" data-dimension25="$14">20W USB-C Compact Power Adapter: was $19 now $14</a></strong><br>This is one of those essentials everyone needs, so you might as well buy one while it's on sale. It offers 20W fast charging for iPhone 8 and up.<a class="view-deal button" href="https://www.amazon.com/Apple-20W-USB-C-Power-Adapter/dp/B0DJFW7PNM" target="_blank" rel="nofollow" data-dimension112="6ec038b8-a79f-11f1-984a-61415f55f1e7" data-action="Deal Block" data-label="20W USB-C Compact Power Adapter" data-dimension48="20W USB-C Compact Power Adapter" data-dimension25="$14">View Deal</a></p></div><div class="product"><a data-dimension112="6ec0391c-a79f-11f1-96b7-89b11a6cf127" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$24" href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:600px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="EzmCNB37HYZTKq3XSMqvTY" name="Apple AirTag 2 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/EzmCNB37HYZTKq3XSMqvTY.jpg" mos="" align="middle" fullscreen="" width="600" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow" data-dimension112="6ec0391c-a79f-11f1-96b7-89b11a6cf127" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$24">AirTag (2nd Gen): was $29 now $24</a></strong><br>Apple's second generation AirTag offers better range, precision finding, a louder speaking and a bunch of extra improvements to help you track your lost keys and bags.<a class="view-deal button" href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow" data-dimension112="6ec0391c-a79f-11f1-96b7-89b11a6cf127" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$24">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03980-a79f-11f1-a29a-2dd41899a718" data-action="Deal Block" data-label="Pencil (USB-C)" data-dimension48="Pencil (USB-C)" data-dimension25="$69" href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="LCuHYQPiVnordwa3UuoKE6" name="1721134277.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LCuHYQPiVnordwa3UuoKE6.jpg" mos="" align="middle" fullscreen="" width="500" height="500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow" data-dimension112="6ec03980-a79f-11f1-a29a-2dd41899a718" data-action="Deal Block" data-label="Pencil (USB-C)" data-dimension48="Pencil (USB-C)" data-dimension25="$69">Pencil (USB-C): was $79 now $69</a></strong><br>If you want a cheaper stylus that covers the basics, than the Apple Pencil USB-C is the one for you. With pixel-perfect precision, low-latency and magnets to attach to your tablet, this is the no-frills approach to writing ad drawing on your tablet.<a class="view-deal button" href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow" data-dimension112="6ec03980-a79f-11f1-a29a-2dd41899a718" data-action="Deal Block" data-label="Pencil (USB-C)" data-dimension48="Pencil (USB-C)" data-dimension25="$69">View Deal</a></p></div><h3 class="article-body__section" id="section-airpods"><span>AirPods</span></h3><div class="product"><a data-dimension112="6ec03a48-a79f-11f1-8739-0f8bef113611" data-action="Deal Block" data-label="AirPods 4" data-dimension48="AirPods 4" data-dimension25="$99" href="https://www.amazon.com/dp/B0DGHMNQ5Z/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1000px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="kTKCG8gCBjg4vScr6CMgoN" name="AirPods 4 BG image.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/kTKCG8gCBjg4vScr6CMgoN.jpg" mos="" align="middle" fullscreen="" width="1000" height="1200" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The AirPods 4 are about as barebones as AirPods come, but they're still packed with features. Spatial Audio is on board for example, something you'd have to pay more for on the old model. 5 hours of battery isn't the very best, but they're a great on boarding place for the AirPods line.<a class="view-deal button" href="https://www.amazon.com/dp/B0DGHMNQ5Z/" target="_blank" rel="nofollow" data-dimension112="6ec03a48-a79f-11f1-8739-0f8bef113611" data-action="Deal Block" data-label="AirPods 4" data-dimension48="AirPods 4" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03aac-a79f-11f1-95e8-c5a95ef0cdf0" data-action="Deal Block" data-label="AirPods 4 w/ ANC" data-dimension48="AirPods 4 w/ ANC" data-dimension25="$148" href="https://www.amazon.com/Apple-Headphones-Cancellation-Transparency-Personalized/dp/B0DGJ7HYG1" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:93.08%;"><img id="iW6XqU9SoqpTBgf9epawof" name="Apple AirPods 4 deal block.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iW6XqU9SoqpTBgf9epawof.jpg" mos="" align="middle" fullscreen="" width="679" height="632" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-Headphones-Cancellation-Transparency-Personalized/dp/B0DGJ7HYG1" target="_blank" rel="nofollow" data-dimension112="6ec03aac-a79f-11f1-95e8-c5a95ef0cdf0" data-action="Deal Block" data-label="AirPods 4 w/ ANC" data-dimension48="AirPods 4 w/ ANC" data-dimension25="$148">AirPods 4 w/ ANC: was $179 now $148</a></strong><br>These AirPods 4 have all the same great features as the base AirPods 4, except they also include Active Noise Cancellation. They also feature Adaptive Audio, Transparency mode, and Voice Isolation. It's a modest, but welcome price cut.<a class="view-deal button" href="https://www.amazon.com/Apple-Headphones-Cancellation-Transparency-Personalized/dp/B0DGJ7HYG1" target="_blank" rel="nofollow" data-dimension112="6ec03aac-a79f-11f1-95e8-c5a95ef0cdf0" data-action="Deal Block" data-label="AirPods 4 w/ ANC" data-dimension48="AirPods 4 w/ ANC" data-dimension25="$148">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03b10-a79f-11f1-b03f-9f84bb0967cd" data-action="Deal Block" data-label="AirPods Pro 3" data-dimension48="AirPods Pro 3" data-dimension25="$199" href="https://www.amazon.com/Apple-Cancellation-Translation-Headphones-High-Fidelity/dp/B0FQFB8FMG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:842px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="FYzcjQSdtuwidVacXmMNL5" name="AirPods Pro 3.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FYzcjQSdtuwidVacXmMNL5.jpg" mos="" align="middle" fullscreen="" width="842" height="842" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The AirPods Pro 3 bring the heat with 10 hours of battery life, improved sound, and superior active noise canceling. In our <a href="https://www.tomsguide.com/audio/airpods/apple-airpods-pro-3-review" data-dimension112="6ec03b10-a79f-11f1-b03f-9f84bb0967cd" data-action="Deal Block" data-label="AirPods Pro 3" data-dimension48="AirPods Pro 3" data-dimension25="$199">AirPods Pro 3 review</a> we said the Editor's Choice buds deliver the upgrade iPhone users have been waiting for with improved battery life, stronger noise cancellation, and smart new features like Live Translation, which delivers real-time translations to your ears. <a class="view-deal button" href="https://www.amazon.com/Apple-Cancellation-Translation-Headphones-High-Fidelity/dp/B0FQFB8FMG" target="_blank" rel="nofollow" data-dimension112="6ec03b10-a79f-11f1-b03f-9f84bb0967cd" data-action="Deal Block" data-label="AirPods Pro 3" data-dimension48="AirPods Pro 3" data-dimension25="$199">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03b74-a79f-11f1-917a-67d5e6e20c2d" data-action="Deal Block" data-label="AirPods Max 2" data-dimension48="AirPods Max 2" data-dimension25="$479" href="https://www.amazon.com/dp/B0GSRYXZM5?th=1" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="TSi2XMUrFhYn5nqrGBsd59" name="airpods max 2 deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/TSi2XMUrFhYn5nqrGBsd59.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>These are some of the best headphones we've ever used. With seamless Apple ecosystem integration, well-balanced sound, and excellent comfort, the AirPods Max 2 will make you want to listen to music. You have to try them to believe them and at this price, it's almost a steal.<a class="view-deal button" href="https://www.amazon.com/dp/B0GSRYXZM5?th=1" target="_blank" rel="nofollow" data-dimension112="6ec03b74-a79f-11f1-917a-67d5e6e20c2d" data-action="Deal Block" data-label="AirPods Max 2" data-dimension48="AirPods Max 2" data-dimension25="$479">View Deal</a></p></div><h3 class="article-body__section" id="section-ipads"><span>iPads</span></h3><div class="product"><a data-dimension112="6ec03c3c-a79f-11f1-887f-013c752ed41b" data-action="Deal Block" data-label="iPad 11" (Wi-Fi/128GB)" data-dimension48="iPad 11" (Wi-Fi/128GB)" data-dimension25="$399" href="https://www.amazon.com/Apple-iPad-11-inch-Display-All-Day/dp/B0DZ7871B8?" 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="bkpUUC6QZQWzqjtNLa4NNW" name="iPad 11 deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bkpUUC6QZQWzqjtNLa4NNW.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/Apple-iPad-11-inch-Display-All-Day/dp/B0DZ7871B8?" target="_blank" rel="nofollow" data-dimension112="6ec03c3c-a79f-11f1-887f-013c752ed41b" data-action="Deal Block" data-label='iPad 11" (Wi-Fi/128GB)' data-dimension48='iPad 11" (Wi-Fi/128GB)' data-dimension25="$399">iPad 11" (Wi-Fi/128GB): was $449 now $399</a></strong><br>Apple's latest iPad (11th Gen) can just about do it all thanks to its upgraded A16 chip, larger 128GB base storage and longer battery at over 11 hours (it even beats the iPad Air M3 and iPad mini 7). In our 4-star <a href="https://www.tomsguide.com/computing/ipads/ipad-11-2025-review">iPad 11 review</a>, we called it the Apple tablet for most. <a class="view-deal button" href="https://www.amazon.com/Apple-iPad-11-inch-Display-All-Day/dp/B0DZ7871B8?" target="_blank" rel="nofollow" data-dimension112="6ec03c3c-a79f-11f1-887f-013c752ed41b" data-action="Deal Block" data-label="iPad 11" (Wi-Fi/128GB)" data-dimension48="iPad 11" (Wi-Fi/128GB)" data-dimension25="$399">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03ca0-a79f-11f1-948f-35f5ace62c2c" data-action="Deal Block" data-label="iPad mini 7" data-dimension48="iPad mini 7" data-dimension25="$569" href="https://www.amazon.com/dp/B0DK3W4YHS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1203px;"><p class="vanilla-image-block" style="padding-top:124.69%;"><img id="G2PjHEjHsRfuddfWSzPBjd" name="iPad mini 2024 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/G2PjHEjHsRfuddfWSzPBjd.jpg" mos="" align="middle" fullscreen="" width="1203" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The iPad mini is getting a discount, and any price cut to this small tablet is welcome. We're big fans of its incredibly portable design and long battery life (it lasted 10 hours in our battery life tests.) It comes with speedy performance thanks to Apple's A17 Pro chip, and has a gorgeous 8.3-inch (2,266 x 1,488) Liquid Retina display. You also get 12MP cameras on the front and back and Wi-Fi 6e support. In our <a href="https://www.tomsguide.com/tablets/ipads/ipad-mini-7-review" data-dimension112="6ec03ca0-a79f-11f1-948f-35f5ace62c2c" data-action="Deal Block" data-label="iPad mini 7" data-dimension48="iPad mini 7" data-dimension25="$569">iPad mini 7 review</a>, we said it delivers the full iPad experience in a tiny size. <a class="view-deal button" href="https://www.amazon.com/dp/B0DK3W4YHS" target="_blank" rel="nofollow" data-dimension112="6ec03ca0-a79f-11f1-948f-35f5ace62c2c" data-action="Deal Block" data-label="iPad mini 7" data-dimension48="iPad mini 7" data-dimension25="$569">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03d04-a79f-11f1-8529-fbbc22392543" data-action="Deal Block" data-label="11" iPad Air (WiFi/128GB)" data-dimension48="11" iPad Air (WiFi/128GB)" data-dimension25="$649" href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQV9W97Q" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1325px;"><p class="vanilla-image-block" style="padding-top:113.21%;"><img id="NVZkwX7FuVd3CYdiYHdsgm" name="iPad Air 11 2024 deal block.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/NVZkwX7FuVd3CYdiYHdsgm.jpg" mos="" align="middle" fullscreen="" width="1325" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQV9W97Q" target="_blank" rel="nofollow" data-dimension112="6ec03d04-a79f-11f1-8529-fbbc22392543" data-action="Deal Block" data-label='11" iPad Air (WiFi/128GB)' data-dimension48='11" iPad Air (WiFi/128GB)' data-dimension25="$649">11" iPad Air (WiFi/128GB): was $749 now $649</a></strong><br>The 2026 iPad Air packs Apple's M4 processor, which Apple states is up to 30 percent faster than iPad Air with M3. It also has an 11-inch LED (2360 x 1640) display, 128GB of storage, 12MP rear camera, and 12MP front camera. The tablet now supports Wi-Fi 7 a well as Bluetooth 6 and Thread. In our <a href="https://www.tomsguide.com/computing/ipads/apple-ipad-air-m4-review-small-tweaks-to-the-gold-standard">iPad Air M4 review</a>, we said the upgrades are modest, but the iPad Air remains the best tablet out there. <a class="view-deal button" href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQV9W97Q" target="_blank" rel="nofollow" data-dimension112="6ec03d04-a79f-11f1-8529-fbbc22392543" data-action="Deal Block" data-label="11" iPad Air (WiFi/128GB)" data-dimension48="11" iPad Air (WiFi/128GB)" data-dimension25="$649">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03d68-a79f-11f1-97a7-358460a12fa3" data-action="Deal Block" data-label="13" iPad Air (WiFi/128GB)" data-dimension48="13" iPad Air (WiFi/128GB)" data-dimension25="$849" href="https://www.amazon.com/Apple-iPad-Air-13-inch-M4/dp/B0GQVDGCD2" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1368px;"><p class="vanilla-image-block" style="padding-top:109.65%;"><img id="5LtYHnqoh7QQJRLor82SEG" name="iPad Air 13 2024 deal block.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/5LtYHnqoh7QQJRLor82SEG.jpg" mos="" align="middle" fullscreen="" width="1368" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-iPad-Air-13-inch-M4/dp/B0GQVDGCD2" target="_blank" rel="nofollow" data-dimension112="6ec03d68-a79f-11f1-97a7-358460a12fa3" data-action="Deal Block" data-label='13" iPad Air (WiFi/128GB)' data-dimension48='13" iPad Air (WiFi/128GB)' data-dimension25="$849">13" iPad Air (WiFi/128GB): was $949 now $849</a></strong><br>This larger size iPad Air sports the same M4 processor, but it's coupled with a 13-inch LED (2732 x 2048) display. Otherwise, it packs the same 128GB of storage, 12MP rear camera, and 12MP front camera. You also get Wi-Fi 7 support, Bluetooth 6, and Thread. The larger display and more potent CPU should make this a great tablet for gaming. <a class="view-deal button" href="https://www.amazon.com/Apple-iPad-Air-13-inch-M4/dp/B0GQVDGCD2" target="_blank" rel="nofollow" data-dimension112="6ec03d68-a79f-11f1-97a7-358460a12fa3" data-action="Deal Block" data-label="13" iPad Air (WiFi/128GB)" data-dimension48="13" iPad Air (WiFi/128GB)" data-dimension25="$849">View Deal</a></p></div><h3 class="article-body__section" id="section-macbooks"><span>MacBooks</span></h3><div class="product"><a data-dimension112="6ec03e30-a79f-11f1-af90-b164c2674e97" data-action="Deal Block" data-label="MacBook Neo" data-dimension48="MacBook Neo" data-dimension25="$689" href="https://www.amazon.com/dp/B0GR6BVYS5" 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:61.07%;"><img id="Lg4Dvg68j9SbB5CPNrTEpH" name="MacBook Neo deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg" mos="" align="middle" fullscreen="" width="1500" height="916" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The MacBook Neo sports a 13-inch Liquid Retina (2408 x 1506) display, A18 Pro chipset, 8GB of RAM, 256GB SSD, and 1080p FaceTime HD camera. There's also the option to add TouchID and a 512GB SSD for a total price of $799. The 2.7-lb. laptop is available in Indigo, Blush, Citrus, and Silver. In our <a href="https://www.tomsguide.com/computing/macbooks/apple-macbook-neo-review" data-dimension112="6ec03e30-a79f-11f1-af90-b164c2674e97" data-action="Deal Block" data-label="MacBook Neo" data-dimension48="MacBook Neo" data-dimension25="$689">MacBook Neo review</a>, we said no other laptop comes close to the Neo in terms of bang for your buck — even with its new/higher $699 price tag. <a class="view-deal button" href="https://www.amazon.com/dp/B0GR6BVYS5" target="_blank" rel="nofollow" data-dimension112="6ec03e30-a79f-11f1-af90-b164c2674e97" data-action="Deal Block" data-label="MacBook Neo" data-dimension48="MacBook Neo" data-dimension25="$689">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03e94-a79f-11f1-a1ba-9b6820202503" data-action="Deal Block" data-label="15" MacBook Air (M5)" data-dimension48="15" MacBook Air (M5)" data-dimension25="$1459" href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" 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:60.73%;"><img id="R5hxVnj9RteJKiej8tQbLH" name="MacBook Air M5 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/R5hxVnj9RteJKiej8tQbLH.jpg" mos="" align="middle" fullscreen="" width="1500" height="911" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" target="_blank" rel="nofollow" data-dimension112="6ec03e94-a79f-11f1-a1ba-9b6820202503" data-action="Deal Block" data-label='15" MacBook Air (M5)' data-dimension48='15" MacBook Air (M5)' data-dimension25="$1459">15" MacBook Air (M5): was $1499 now $1459</a></strong><br>It's a modest discount, but right now you can get the 15-inch MacBook Air M5 for a few bucks off. The new laptop features a 15.3-inch (2880 x 1864) display, Apple M5 chipset, 16GB of RAM, 512GB SSD, and support for WiFi 7 and Bluetooth 6. <br><strong>Price check: </strong><a href="https://www.bestbuy.com/product/apple-macbook-air-15-inch-laptop-m5-chip-with-10-core-cpu-and-10-core-gpu-16gb-memory-512gb-ssd-midnight/JJGCQLKQL9/sku/6571043" target="_blank" rel="nofollow"><strong>$1,499 @ Best Buy</strong></a><strong></strong><a class="view-deal button" href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" target="_blank" rel="nofollow" data-dimension112="6ec03e94-a79f-11f1-a1ba-9b6820202503" data-action="Deal Block" data-label="15" MacBook Air (M5)" data-dimension48="15" MacBook Air (M5)" data-dimension25="$1459">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03ef8-a79f-11f1-851f-fd91d0aba15d" data-action="Deal Block" data-label="MacBook Pro 14" (M5/1TB)" data-dimension48="MacBook Pro 14" (M5/1TB)" data-dimension25="$1849" href="https://www.amazon.com/dp/B0FWD623D1" 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:60.53%;"><img id="GnpQTG2JTWSenJyfrWydnm" name="MacBook Pro M5 deals" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GnpQTG2JTWSenJyfrWydnm.jpg" mos="" align="middle" fullscreen="" width="1500" height="908" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0FWD623D1" target="_blank" rel="nofollow" data-dimension112="6ec03ef8-a79f-11f1-851f-fd91d0aba15d" data-action="Deal Block" data-label='MacBook Pro 14" (M5/1TB)' data-dimension48='MacBook Pro 14" (M5/1TB)' data-dimension25="$1849">MacBook Pro 14" (M5/1TB): was $1999 now $1849</a></strong><br>The new MacBook Pro features Apple's latest M5 chipset, with a 10-core CPU and 10-core GPU. It's designed to deliver a huge boost in AI and graphics performance for everyone from students to creatives. In our <a href="https://www.tomsguide.com/computing/macbooks/macbook-pro-m5-review">MacBook Pro M5 review</a> we said the Editor's Choice machine is a fantastic option for power users who demand a powerful and portable notebook with epic (18 hour) battery life. The base model features a 14.2-inch 3024 x 1964 Retina display, Apple M5 CPU, 16GB of RAM, and a 512GB SSD.<a class="view-deal button" href="https://www.amazon.com/dp/B0FWD623D1" target="_blank" rel="nofollow" data-dimension112="6ec03ef8-a79f-11f1-851f-fd91d0aba15d" data-action="Deal Block" data-label="MacBook Pro 14" (M5/1TB)" data-dimension48="MacBook Pro 14" (M5/1TB)" data-dimension25="$1849">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=school&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/sales-events/15-best-apple-labor-day-deals-airpods-ipads-and-macbooks-from-just-usd99</link>
                                                                            <description>
                            <![CDATA[ Apple deals just dropped on Amazon. Check out the best deals you can shop now on AirPods, MacBooks, iPads, accessories and more. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">yrVQJgv6nm6HxKLk63eMiM</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Utwg2LCRoYp5Y7R3MbxTxH-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 03 Sep 2026 14:57:17 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Sales Events]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/Utwg2LCRoYp5Y7R3MbxTxH-1280-80.jpg">
                                                            <media:credit><![CDATA[Amazon / edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple deals]]></media:description>                                                            <media:text><![CDATA[Apple deals]]></media:text>
                                <media:title type="plain"><![CDATA[Apple deals]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Utwg2LCRoYp5Y7R3MbxTxH-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p><a href="https://www.tomsguide.com/computing/laptops/labor-day-sales-2026-my-ultimate-guide-to-the-best-end-of-summer-deals">Labor Day </a>weekend brings some of the biggest sales of the summer, making it the perfect time to score a great deal before the season comes to an end. Apple products are no exception. If you’re in the market for some new tech, Amazon is offering attractive discounts on a wide range of premium Apple devices.</p><p>Right now, you can <a href="https://www.amazon.com/stores/Apple/page/77D9E1F7-0337-4282-9DB6-B6B8FB2DC98D?" target="_blank" rel="nofollow">shop deals on AirPods, iPads, MacBooks, accessories and more</a>. One of my favorite finds is <a href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQV9W97Q" target="_blank" rel="nofollow">$100 off the iPad 11" (Wi-Fi/128GB)</a>. You can also grab the <a href="https://www.amazon.com/dp/B0DGHMNQ5Z/" target="_blank" rel="nofollow">Apple AirPods 4 for just $99</a> or <a href="https://www.amazon.com/dp/B0GR6BVYS5" target="_blank" rel="nofollow">the MacBook Neo for just $689</a>. Plus, there's  tons of must-have accessories starting at $14. </p><p>Sure, these aren't the lowest prices we've ever seen on the popular products, but the deals are certainly still worth considering. So if you're ready to upgrade your tech for the new season (without spending a fortune) take a look at these rare Apple deals. </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong></strong><a href="https://www.amazon.com/stores/Apple/page/77D9E1F7-0337-4282-9DB6-B6B8FB2DC98D?" target="_blank" rel="nofollow"><strong>shop all Apple deals on Amazon</strong></a><strong>   </strong></li><li><strong>Apple EarPods (Lightning): </strong><a href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow"><strong>was $19 now $14</strong></a></li><li><strong>Apple AirTag: </strong><a href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow"><strong>was $29 now $24</strong></a></li><li><strong>AirPods 4: </strong><a href="https://www.amazon.com/Apple-Bluetooth-Headphones-Personalized-Effortless/dp/B0DGHMNQ5Z" target="_blank" rel="nofollow"><strong>was $129 now $99</strong></a></li><li><strong>Apple iPad 11" (Wi-Fi/128GB): </strong><a href="https://www.amazon.com/Apple-iPad-11-inch-Display-All-Day/dp/B0DZ7871B8?" target="_blank" rel="nofollow"><strong>was $449 now $399</strong></a></li><li><strong>AirPods Max 2: </strong><a href="https://www.amazon.com/dp/B0GSRYXZM5?th=1" target="_blank" rel="nofollow"><strong>was $549 now $479</strong></a></li><li><strong>11" iPad Air (M4): </strong><a href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQV9W97Q" target="_blank" rel="nofollow"><strong>was $749 now $649</strong></a></li><li><strong>15" MacBook Air (M5): </strong><a href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" target="_blank" rel="nofollow"><strong>was $1,499 now $1,459</strong></a></li></ul><h3 class="article-body__section" id="section-accessories"><span>Accessories</span></h3><div class="product"><a data-dimension112="6ec03854-a79f-11f1-9244-9d400cdded84" data-action="Deal Block" data-label="EarPods (Lightning)" data-dimension48="EarPods (Lightning)" data-dimension25="$14" href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1040px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Ys3T2v7S48cnc2sK2hLS9U" name="apple earpods with lightning connector.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Ys3T2v7S48cnc2sK2hLS9U.jpg" mos="" align="middle" fullscreen="" width="1040" height="1040" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow" data-dimension112="6ec03854-a79f-11f1-9244-9d400cdded84" data-action="Deal Block" data-label="EarPods (Lightning)" data-dimension48="EarPods (Lightning)" data-dimension25="$14">EarPods (Lightning): was $19 now $14</a></strong><br>If you like listening to your music the old-fashioned way, this pair of wired EarPods has a Lightning connector, allowing them to be used with older Apple devices. For this price, you might as well grab a pair!<a class="view-deal button" href="https://www.amazon.com/Apple-EarPods-Headphones-Lightning-Connector/dp/B0D7FVQ1ZB/" target="_blank" rel="nofollow" data-dimension112="6ec03854-a79f-11f1-9244-9d400cdded84" data-action="Deal Block" data-label="EarPods (Lightning)" data-dimension48="EarPods (Lightning)" data-dimension25="$14">View Deal</a></p></div><div class="product"><a data-dimension112="6ec038b8-a79f-11f1-984a-61415f55f1e7" data-action="Deal Block" data-label="20W USB-C Compact Power Adapter" data-dimension48="20W USB-C Compact Power Adapter" data-dimension25="$14" href="https://www.amazon.com/Apple-20W-USB-C-Power-Adapter/dp/B0DJFW7PNM" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:649px;"><p class="vanilla-image-block" style="padding-top:149.61%;"><img id="mhEQ7c2rj34AhoPSdBToNX" name="20W USB-C Compact Power Adapter" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mhEQ7c2rj34AhoPSdBToNX.jpg" mos="" align="middle" fullscreen="" width="649" height="971" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-20W-USB-C-Power-Adapter/dp/B0DJFW7PNM" target="_blank" rel="nofollow" data-dimension112="6ec038b8-a79f-11f1-984a-61415f55f1e7" data-action="Deal Block" data-label="20W USB-C Compact Power Adapter" data-dimension48="20W USB-C Compact Power Adapter" data-dimension25="$14">20W USB-C Compact Power Adapter: was $19 now $14</a></strong><br>This is one of those essentials everyone needs, so you might as well buy one while it's on sale. It offers 20W fast charging for iPhone 8 and up.<a class="view-deal button" href="https://www.amazon.com/Apple-20W-USB-C-Power-Adapter/dp/B0DJFW7PNM" target="_blank" rel="nofollow" data-dimension112="6ec038b8-a79f-11f1-984a-61415f55f1e7" data-action="Deal Block" data-label="20W USB-C Compact Power Adapter" data-dimension48="20W USB-C Compact Power Adapter" data-dimension25="$14">View Deal</a></p></div><div class="product"><a data-dimension112="6ec0391c-a79f-11f1-96b7-89b11a6cf127" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$24" href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:600px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="EzmCNB37HYZTKq3XSMqvTY" name="Apple AirTag 2 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/EzmCNB37HYZTKq3XSMqvTY.jpg" mos="" align="middle" fullscreen="" width="600" height="600" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow" data-dimension112="6ec0391c-a79f-11f1-96b7-89b11a6cf127" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$24">AirTag (2nd Gen): was $29 now $24</a></strong><br>Apple's second generation AirTag offers better range, precision finding, a louder speaking and a bunch of extra improvements to help you track your lost keys and bags.<a class="view-deal button" href="https://www.amazon.com/gp/aw/d/B0GJTFXNRX/" target="_blank" rel="nofollow" data-dimension112="6ec0391c-a79f-11f1-96b7-89b11a6cf127" data-action="Deal Block" data-label="AirTag (2nd Gen)" data-dimension48="AirTag (2nd Gen)" data-dimension25="$24">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03980-a79f-11f1-a29a-2dd41899a718" data-action="Deal Block" data-label="Pencil (USB-C)" data-dimension48="Pencil (USB-C)" data-dimension25="$69" href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="LCuHYQPiVnordwa3UuoKE6" name="1721134277.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LCuHYQPiVnordwa3UuoKE6.jpg" mos="" align="middle" fullscreen="" width="500" height="500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow" data-dimension112="6ec03980-a79f-11f1-a29a-2dd41899a718" data-action="Deal Block" data-label="Pencil (USB-C)" data-dimension48="Pencil (USB-C)" data-dimension25="$69">Pencil (USB-C): was $79 now $69</a></strong><br>If you want a cheaper stylus that covers the basics, than the Apple Pencil USB-C is the one for you. With pixel-perfect precision, low-latency and magnets to attach to your tablet, this is the no-frills approach to writing ad drawing on your tablet.<a class="view-deal button" href="https://www.amazon.com/Apple-MUWA3AM-A-Pencil-USB-C/dp/B0CL7J12YK" target="_blank" rel="nofollow" data-dimension112="6ec03980-a79f-11f1-a29a-2dd41899a718" data-action="Deal Block" data-label="Pencil (USB-C)" data-dimension48="Pencil (USB-C)" data-dimension25="$69">View Deal</a></p></div><h3 class="article-body__section" id="section-airpods"><span>AirPods</span></h3><div class="product"><a data-dimension112="6ec03a48-a79f-11f1-8739-0f8bef113611" data-action="Deal Block" data-label="AirPods 4" data-dimension48="AirPods 4" data-dimension25="$99" href="https://www.amazon.com/dp/B0DGHMNQ5Z/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1000px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="kTKCG8gCBjg4vScr6CMgoN" name="AirPods 4 BG image.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/kTKCG8gCBjg4vScr6CMgoN.jpg" mos="" align="middle" fullscreen="" width="1000" height="1200" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The AirPods 4 are about as barebones as AirPods come, but they're still packed with features. Spatial Audio is on board for example, something you'd have to pay more for on the old model. 5 hours of battery isn't the very best, but they're a great on boarding place for the AirPods line.<a class="view-deal button" href="https://www.amazon.com/dp/B0DGHMNQ5Z/" target="_blank" rel="nofollow" data-dimension112="6ec03a48-a79f-11f1-8739-0f8bef113611" data-action="Deal Block" data-label="AirPods 4" data-dimension48="AirPods 4" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03aac-a79f-11f1-95e8-c5a95ef0cdf0" data-action="Deal Block" data-label="AirPods 4 w/ ANC" data-dimension48="AirPods 4 w/ ANC" data-dimension25="$148" href="https://www.amazon.com/Apple-Headphones-Cancellation-Transparency-Personalized/dp/B0DGJ7HYG1" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:679px;"><p class="vanilla-image-block" style="padding-top:93.08%;"><img id="iW6XqU9SoqpTBgf9epawof" name="Apple AirPods 4 deal block.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iW6XqU9SoqpTBgf9epawof.jpg" mos="" align="middle" fullscreen="" width="679" height="632" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-Headphones-Cancellation-Transparency-Personalized/dp/B0DGJ7HYG1" target="_blank" rel="nofollow" data-dimension112="6ec03aac-a79f-11f1-95e8-c5a95ef0cdf0" data-action="Deal Block" data-label="AirPods 4 w/ ANC" data-dimension48="AirPods 4 w/ ANC" data-dimension25="$148">AirPods 4 w/ ANC: was $179 now $148</a></strong><br>These AirPods 4 have all the same great features as the base AirPods 4, except they also include Active Noise Cancellation. They also feature Adaptive Audio, Transparency mode, and Voice Isolation. It's a modest, but welcome price cut.<a class="view-deal button" href="https://www.amazon.com/Apple-Headphones-Cancellation-Transparency-Personalized/dp/B0DGJ7HYG1" target="_blank" rel="nofollow" data-dimension112="6ec03aac-a79f-11f1-95e8-c5a95ef0cdf0" data-action="Deal Block" data-label="AirPods 4 w/ ANC" data-dimension48="AirPods 4 w/ ANC" data-dimension25="$148">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03b10-a79f-11f1-b03f-9f84bb0967cd" data-action="Deal Block" data-label="AirPods Pro 3" data-dimension48="AirPods Pro 3" data-dimension25="$199" href="https://www.amazon.com/Apple-Cancellation-Translation-Headphones-High-Fidelity/dp/B0FQFB8FMG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:842px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="FYzcjQSdtuwidVacXmMNL5" name="AirPods Pro 3.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FYzcjQSdtuwidVacXmMNL5.jpg" mos="" align="middle" fullscreen="" width="842" height="842" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The AirPods Pro 3 bring the heat with 10 hours of battery life, improved sound, and superior active noise canceling. In our <a href="https://www.tomsguide.com/audio/airpods/apple-airpods-pro-3-review" data-dimension112="6ec03b10-a79f-11f1-b03f-9f84bb0967cd" data-action="Deal Block" data-label="AirPods Pro 3" data-dimension48="AirPods Pro 3" data-dimension25="$199">AirPods Pro 3 review</a> we said the Editor's Choice buds deliver the upgrade iPhone users have been waiting for with improved battery life, stronger noise cancellation, and smart new features like Live Translation, which delivers real-time translations to your ears. <a class="view-deal button" href="https://www.amazon.com/Apple-Cancellation-Translation-Headphones-High-Fidelity/dp/B0FQFB8FMG" target="_blank" rel="nofollow" data-dimension112="6ec03b10-a79f-11f1-b03f-9f84bb0967cd" data-action="Deal Block" data-label="AirPods Pro 3" data-dimension48="AirPods Pro 3" data-dimension25="$199">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03b74-a79f-11f1-917a-67d5e6e20c2d" data-action="Deal Block" data-label="AirPods Max 2" data-dimension48="AirPods Max 2" data-dimension25="$479" href="https://www.amazon.com/dp/B0GSRYXZM5?th=1" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="TSi2XMUrFhYn5nqrGBsd59" name="airpods max 2 deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/TSi2XMUrFhYn5nqrGBsd59.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>These are some of the best headphones we've ever used. With seamless Apple ecosystem integration, well-balanced sound, and excellent comfort, the AirPods Max 2 will make you want to listen to music. You have to try them to believe them and at this price, it's almost a steal.<a class="view-deal button" href="https://www.amazon.com/dp/B0GSRYXZM5?th=1" target="_blank" rel="nofollow" data-dimension112="6ec03b74-a79f-11f1-917a-67d5e6e20c2d" data-action="Deal Block" data-label="AirPods Max 2" data-dimension48="AirPods Max 2" data-dimension25="$479">View Deal</a></p></div><h3 class="article-body__section" id="section-ipads"><span>iPads</span></h3><div class="product"><a data-dimension112="6ec03c3c-a79f-11f1-887f-013c752ed41b" data-action="Deal Block" data-label="iPad 11" (Wi-Fi/128GB)" data-dimension48="iPad 11" (Wi-Fi/128GB)" data-dimension25="$399" href="https://www.amazon.com/Apple-iPad-11-inch-Display-All-Day/dp/B0DZ7871B8?" 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="bkpUUC6QZQWzqjtNLa4NNW" name="iPad 11 deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bkpUUC6QZQWzqjtNLa4NNW.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/Apple-iPad-11-inch-Display-All-Day/dp/B0DZ7871B8?" target="_blank" rel="nofollow" data-dimension112="6ec03c3c-a79f-11f1-887f-013c752ed41b" data-action="Deal Block" data-label='iPad 11" (Wi-Fi/128GB)' data-dimension48='iPad 11" (Wi-Fi/128GB)' data-dimension25="$399">iPad 11" (Wi-Fi/128GB): was $449 now $399</a></strong><br>Apple's latest iPad (11th Gen) can just about do it all thanks to its upgraded A16 chip, larger 128GB base storage and longer battery at over 11 hours (it even beats the iPad Air M3 and iPad mini 7). In our 4-star <a href="https://www.tomsguide.com/computing/ipads/ipad-11-2025-review">iPad 11 review</a>, we called it the Apple tablet for most. <a class="view-deal button" href="https://www.amazon.com/Apple-iPad-11-inch-Display-All-Day/dp/B0DZ7871B8?" target="_blank" rel="nofollow" data-dimension112="6ec03c3c-a79f-11f1-887f-013c752ed41b" data-action="Deal Block" data-label="iPad 11" (Wi-Fi/128GB)" data-dimension48="iPad 11" (Wi-Fi/128GB)" data-dimension25="$399">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03ca0-a79f-11f1-948f-35f5ace62c2c" data-action="Deal Block" data-label="iPad mini 7" data-dimension48="iPad mini 7" data-dimension25="$569" href="https://www.amazon.com/dp/B0DK3W4YHS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1203px;"><p class="vanilla-image-block" style="padding-top:124.69%;"><img id="G2PjHEjHsRfuddfWSzPBjd" name="iPad mini 2024 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/G2PjHEjHsRfuddfWSzPBjd.jpg" mos="" align="middle" fullscreen="" width="1203" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The iPad mini is getting a discount, and any price cut to this small tablet is welcome. We're big fans of its incredibly portable design and long battery life (it lasted 10 hours in our battery life tests.) It comes with speedy performance thanks to Apple's A17 Pro chip, and has a gorgeous 8.3-inch (2,266 x 1,488) Liquid Retina display. You also get 12MP cameras on the front and back and Wi-Fi 6e support. In our <a href="https://www.tomsguide.com/tablets/ipads/ipad-mini-7-review" data-dimension112="6ec03ca0-a79f-11f1-948f-35f5ace62c2c" data-action="Deal Block" data-label="iPad mini 7" data-dimension48="iPad mini 7" data-dimension25="$569">iPad mini 7 review</a>, we said it delivers the full iPad experience in a tiny size. <a class="view-deal button" href="https://www.amazon.com/dp/B0DK3W4YHS" target="_blank" rel="nofollow" data-dimension112="6ec03ca0-a79f-11f1-948f-35f5ace62c2c" data-action="Deal Block" data-label="iPad mini 7" data-dimension48="iPad mini 7" data-dimension25="$569">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03d04-a79f-11f1-8529-fbbc22392543" data-action="Deal Block" data-label="11" iPad Air (WiFi/128GB)" data-dimension48="11" iPad Air (WiFi/128GB)" data-dimension25="$649" href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQV9W97Q" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1325px;"><p class="vanilla-image-block" style="padding-top:113.21%;"><img id="NVZkwX7FuVd3CYdiYHdsgm" name="iPad Air 11 2024 deal block.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/NVZkwX7FuVd3CYdiYHdsgm.jpg" mos="" align="middle" fullscreen="" width="1325" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQV9W97Q" target="_blank" rel="nofollow" data-dimension112="6ec03d04-a79f-11f1-8529-fbbc22392543" data-action="Deal Block" data-label='11" iPad Air (WiFi/128GB)' data-dimension48='11" iPad Air (WiFi/128GB)' data-dimension25="$649">11" iPad Air (WiFi/128GB): was $749 now $649</a></strong><br>The 2026 iPad Air packs Apple's M4 processor, which Apple states is up to 30 percent faster than iPad Air with M3. It also has an 11-inch LED (2360 x 1640) display, 128GB of storage, 12MP rear camera, and 12MP front camera. The tablet now supports Wi-Fi 7 a well as Bluetooth 6 and Thread. In our <a href="https://www.tomsguide.com/computing/ipads/apple-ipad-air-m4-review-small-tweaks-to-the-gold-standard">iPad Air M4 review</a>, we said the upgrades are modest, but the iPad Air remains the best tablet out there. <a class="view-deal button" href="https://www.amazon.com/Apple-iPad-Air-11-inch-M4/dp/B0GQV9W97Q" target="_blank" rel="nofollow" data-dimension112="6ec03d04-a79f-11f1-8529-fbbc22392543" data-action="Deal Block" data-label="11" iPad Air (WiFi/128GB)" data-dimension48="11" iPad Air (WiFi/128GB)" data-dimension25="$649">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03d68-a79f-11f1-97a7-358460a12fa3" data-action="Deal Block" data-label="13" iPad Air (WiFi/128GB)" data-dimension48="13" iPad Air (WiFi/128GB)" data-dimension25="$849" href="https://www.amazon.com/Apple-iPad-Air-13-inch-M4/dp/B0GQVDGCD2" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1368px;"><p class="vanilla-image-block" style="padding-top:109.65%;"><img id="5LtYHnqoh7QQJRLor82SEG" name="iPad Air 13 2024 deal block.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/5LtYHnqoh7QQJRLor82SEG.jpg" mos="" align="middle" fullscreen="" width="1368" height="1500" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-iPad-Air-13-inch-M4/dp/B0GQVDGCD2" target="_blank" rel="nofollow" data-dimension112="6ec03d68-a79f-11f1-97a7-358460a12fa3" data-action="Deal Block" data-label='13" iPad Air (WiFi/128GB)' data-dimension48='13" iPad Air (WiFi/128GB)' data-dimension25="$849">13" iPad Air (WiFi/128GB): was $949 now $849</a></strong><br>This larger size iPad Air sports the same M4 processor, but it's coupled with a 13-inch LED (2732 x 2048) display. Otherwise, it packs the same 128GB of storage, 12MP rear camera, and 12MP front camera. You also get Wi-Fi 7 support, Bluetooth 6, and Thread. The larger display and more potent CPU should make this a great tablet for gaming. <a class="view-deal button" href="https://www.amazon.com/Apple-iPad-Air-13-inch-M4/dp/B0GQVDGCD2" target="_blank" rel="nofollow" data-dimension112="6ec03d68-a79f-11f1-97a7-358460a12fa3" data-action="Deal Block" data-label="13" iPad Air (WiFi/128GB)" data-dimension48="13" iPad Air (WiFi/128GB)" data-dimension25="$849">View Deal</a></p></div><h3 class="article-body__section" id="section-macbooks"><span>MacBooks</span></h3><div class="product"><a data-dimension112="6ec03e30-a79f-11f1-af90-b164c2674e97" data-action="Deal Block" data-label="MacBook Neo" data-dimension48="MacBook Neo" data-dimension25="$689" href="https://www.amazon.com/dp/B0GR6BVYS5" 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:61.07%;"><img id="Lg4Dvg68j9SbB5CPNrTEpH" name="MacBook Neo deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg" mos="" align="middle" fullscreen="" width="1500" height="916" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p>The MacBook Neo sports a 13-inch Liquid Retina (2408 x 1506) display, A18 Pro chipset, 8GB of RAM, 256GB SSD, and 1080p FaceTime HD camera. There's also the option to add TouchID and a 512GB SSD for a total price of $799. The 2.7-lb. laptop is available in Indigo, Blush, Citrus, and Silver. In our <a href="https://www.tomsguide.com/computing/macbooks/apple-macbook-neo-review" data-dimension112="6ec03e30-a79f-11f1-af90-b164c2674e97" data-action="Deal Block" data-label="MacBook Neo" data-dimension48="MacBook Neo" data-dimension25="$689">MacBook Neo review</a>, we said no other laptop comes close to the Neo in terms of bang for your buck — even with its new/higher $699 price tag. <a class="view-deal button" href="https://www.amazon.com/dp/B0GR6BVYS5" target="_blank" rel="nofollow" data-dimension112="6ec03e30-a79f-11f1-af90-b164c2674e97" data-action="Deal Block" data-label="MacBook Neo" data-dimension48="MacBook Neo" data-dimension25="$689">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03e94-a79f-11f1-a1ba-9b6820202503" data-action="Deal Block" data-label="15" MacBook Air (M5)" data-dimension48="15" MacBook Air (M5)" data-dimension25="$1459" href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" 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:60.73%;"><img id="R5hxVnj9RteJKiej8tQbLH" name="MacBook Air M5 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/R5hxVnj9RteJKiej8tQbLH.jpg" mos="" align="middle" fullscreen="" width="1500" height="911" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" target="_blank" rel="nofollow" data-dimension112="6ec03e94-a79f-11f1-a1ba-9b6820202503" data-action="Deal Block" data-label='15" MacBook Air (M5)' data-dimension48='15" MacBook Air (M5)' data-dimension25="$1459">15" MacBook Air (M5): was $1499 now $1459</a></strong><br>It's a modest discount, but right now you can get the 15-inch MacBook Air M5 for a few bucks off. The new laptop features a 15.3-inch (2880 x 1864) display, Apple M5 chipset, 16GB of RAM, 512GB SSD, and support for WiFi 7 and Bluetooth 6. <br><strong>Price check: </strong><a href="https://www.bestbuy.com/product/apple-macbook-air-15-inch-laptop-m5-chip-with-10-core-cpu-and-10-core-gpu-16gb-memory-512gb-ssd-midnight/JJGCQLKQL9/sku/6571043" target="_blank" rel="nofollow"><strong>$1,499 @ Best Buy</strong></a><strong></strong><a class="view-deal button" href="https://www.amazon.com/Apple-2026-MacBook-15-inch-Laptop/dp/B0GR1N82GJ" target="_blank" rel="nofollow" data-dimension112="6ec03e94-a79f-11f1-a1ba-9b6820202503" data-action="Deal Block" data-label="15" MacBook Air (M5)" data-dimension48="15" MacBook Air (M5)" data-dimension25="$1459">View Deal</a></p></div><div class="product"><a data-dimension112="6ec03ef8-a79f-11f1-851f-fd91d0aba15d" data-action="Deal Block" data-label="MacBook Pro 14" (M5/1TB)" data-dimension48="MacBook Pro 14" (M5/1TB)" data-dimension25="$1849" href="https://www.amazon.com/dp/B0FWD623D1" 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:60.53%;"><img id="GnpQTG2JTWSenJyfrWydnm" name="MacBook Pro M5 deals" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GnpQTG2JTWSenJyfrWydnm.jpg" mos="" align="middle" fullscreen="" width="1500" height="908" attribution="" endorsement="" credit="" class=""></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0FWD623D1" target="_blank" rel="nofollow" data-dimension112="6ec03ef8-a79f-11f1-851f-fd91d0aba15d" data-action="Deal Block" data-label='MacBook Pro 14" (M5/1TB)' data-dimension48='MacBook Pro 14" (M5/1TB)' data-dimension25="$1849">MacBook Pro 14" (M5/1TB): was $1999 now $1849</a></strong><br>The new MacBook Pro features Apple's latest M5 chipset, with a 10-core CPU and 10-core GPU. It's designed to deliver a huge boost in AI and graphics performance for everyone from students to creatives. In our <a href="https://www.tomsguide.com/computing/macbooks/macbook-pro-m5-review">MacBook Pro M5 review</a> we said the Editor's Choice machine is a fantastic option for power users who demand a powerful and portable notebook with epic (18 hour) battery life. The base model features a 14.2-inch 3024 x 1964 Retina display, Apple M5 CPU, 16GB of RAM, and a 512GB SSD.<a class="view-deal button" href="https://www.amazon.com/dp/B0FWD623D1" target="_blank" rel="nofollow" data-dimension112="6ec03ef8-a79f-11f1-851f-fd91d0aba15d" data-action="Deal Block" data-label="MacBook Pro 14" (M5/1TB)" data-dimension48="MacBook Pro 14" (M5/1TB)" data-dimension25="$1849">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=school&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[ iPhone 18 Pro and iPhone Ultra A20 Pro chip leak reveals biggest GPU ever inside an iPhone ]]></title>
                                                                                                <dc:content><![CDATA[ <p>A new alleged shot of the die for Apple's A20 Pro chipset gives us our first look at the new chip, which should be built on the TSMC 2nm process. The new chip is expected to power both the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a> and the rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a>.</p><p>The leak comes from <a href="https://weibo.com/7215797790/RfPk17V5Y" target="_blank">Weibo user "White rice fried white rice" </a>(machine translated), who posted some images of the die and an analysis of how it might be laid out. Based on their reporting, it seems the chip has been significantly redesigned.</p><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:55.75%;"><img id="3BhrW6hUMjoHVpt25uJJ88" name="Untitled" alt="Alleged Apple A20 Pro die" src="https://cdn.mos.cms.futurecdn.net/3BhrW6hUMjoHVpt25uJJ88.png" mos="" align="middle" fullscreen="" width="2000" height="1115" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: White rice fried white rice (Weibo))</span></figcaption></figure><p>Here's what the new chip appears to feature:</p><ul><li>7-core GPU vs 6 core on the A19 Pro</li><li>4 efficiency and 2 performance CPU cores</li><li>8MB L2 cache for efficiency cores vs 6MB on the A19</li><li>16MB L2 cache for performance cores (same as the A19 Pro)</li><li>96-bit LPDDR5X memory interface</li></ul><p>What does that all mean? At its most basic level, the larger GPU and more cache memory should translate into faster gaming, graphics and overall performance on the iPhone 18 Pro, <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro Max</a> and iPhone Ultra. Plus, if the leak is accurate that 7-core GPU would be the largest ever used by Apple.</p><p>The leak is fairly speculative on the layout, as they apparently tried several before landing on one that was the "most reasonable."</p><p>The die does not have a labeled NPU or ISP block, important since the NPU will be responsible for AI features. Presumably, that will be bigger as well, which is likely why the CPU is shifted compared to the A19 Pro.</p><h2 id="how-does-that-the-a20-pro-compare-to-android-phones">How does that the A20 Pro compare to Android phones?</h2><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="hq4JHJuwbxiJS6kxfZneS7" name="snapdragon-8-elite-5" alt="Snapdragon 8 Elite Gen 5 chipset" src="https://cdn.mos.cms.futurecdn.net/hq4JHJuwbxiJS6kxfZneS7.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>Samsung, Apple's main rival, has been utilizing the powerful Qualcomm <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-just-confirmed-the-most-obvious-galaxy-z-fold-8-upgrade-but-im-still-surprised">Snapdragon 8 Elite Gen 5</a> silicon. Both the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review">Galaxy S26 Ultra</a> and the foldable <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8</a> are multitasking powerhouses thanks to Qualcomm's chip.</p><p>In our internal tests, both proved quite powerful and outperformed the iPhone 17 Pro Max with the A19 Pro chipset, especially in multicore testing and graphics benchmarks.</p><div ><table><caption>Chip comparisons</caption><thead><tr><th class="firstcol " ><p>Phone</p></th><th  ><p>3DMark Solar Bay Unlimited</p></th></tr></thead><tbody><tr><td class="firstcol " ><p>iPhone 17 Pro Max</p></td><td  ><p>46.6/ 12,260</p></td></tr><tr><td class="firstcol " ><p>Galaxy S26 Ultra</p></td><td  ><p>49.37/ 12,984</p></td></tr><tr><td class="firstcol " ><p>Galaxy Z Fold 8</p></td><td  ><p>47.35/ 12,454</p></td></tr><tr><td class="firstcol " ><p>Motorola Razr Fold</p></td><td  ><p>35.12/ 9,413</p></td></tr></tbody></table></div><p>Apple and Samsung trade performance as each new generation releases. Similarly, while the S26 Ultra and Z Fold 8 are currently front running, it's not by a significant ammount.</p><p>If the A20 Pro is as powerful as it seems, the iPhone 18 Pro Max and iPhone Ultra should equal or surpass what Samsung and Qualcomm are doing.</p><p>Both iPhones are expected to launch at the <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">Apple event</a> on Sept. 9 alongside at least <a href="https://www.tomsguide.com/phones/iphones/apple-sept-9-event-all-9-new-products-were-expecting-to-see">seven other devices</a>. Bookmark Tom's Guide as we'll be on hand to cover all the latest news.</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-18-pro-now-just-tipped-for-3-colors-heres-your-options">iPhone 18 Pro now tipped for just 3 colors — here's your options</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-vs-iphone-17-pro-should-you-upgrade-this-year">iPhone 18 Pro vs. iPhone 17 Pro: Should you upgrade this year?</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-which-upcoming-iphone-is-right-for-you">iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Which upcoming iPhone is right for you?</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-ultra-and-iphone-18-pro-a20-chip-leak-reveals-the-biggest-gpu-ever-inside-an-iphone</link>
                                                                            <description>
                            <![CDATA[ A new leak reveals a look at the A20 Pro chipset that will power the iPhone 18 Pro and iPhone Ultra. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">hDkJAxR7fhcnfXCED2RomE</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/UHNuNim9UYH2mmGNTn3S4V-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 03 Sep 2026 11:36:18 +0000</pubDate>                                                                                                                                <updated>Thu, 03 Sep 2026 12:26:41 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ scott.younker@futurenet.com (Scott Younker) ]]></author>                    <dc:creator><![CDATA[ Scott Younker ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/RZsUpqcJ6Uj2q83oCUwNhQ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Scott Younker is the West Coast Reporter at Tom’s Guide. He covers all the latest tech news, including phones, computing and more. He’s been involved in tech since 2011 covering everything from cameras and swimming pool equipment to the latest gaming consoles and smart TVs. He is on a seemingly never ending hunt to build the easiest to use home media system. &lt;/p&gt;&lt;p&gt;Before Tom’s Guide, Scott worked for publications like &lt;em&gt;Digital Trends, Outdoor Photographer, Dead Beats Panel&lt;/em&gt;, and in a brief detour, &lt;em&gt;America’s Funniest Home Videos&lt;/em&gt;. Yes, he has seen more pratfalls, silly pets and ridiculous home movie fails than is reasonably healthy. &lt;/p&gt;&lt;p&gt;When not writing about the latest devices or advances in chipsets, be sure to ask about Scott about disc golf and sustainability, or just if you’re being cheeky, ask about his noodle arm. If you truly want to get nerdy, bring up board games and his ongoing losing streak. &lt;/p&gt;&lt;p&gt;Scott joined Tom&#039;s Guide in 2024 as the West Coast Reporter. He graduated from the School of Journalism at the University of Oregon with a degree in magazine journalism and a minor in communications. While there he blogged or wrote for several magazines including the Fluxx, Ethos and the Oregon Commentator. He briefly wrote and managed a moderately successful blog focused on web comics. &lt;br&gt;Send secure tips on Signal: scyo1.55.&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/UHNuNim9UYH2mmGNTn3S4V-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide/Apple]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Apple iPhone 18 Pro and the A20 Pro chip]]></media:description>                                                            <media:text><![CDATA[Apple iPhone 18 Pro and the A20 Pro chip]]></media:text>
                                <media:title type="plain"><![CDATA[Apple iPhone 18 Pro and the A20 Pro chip]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/UHNuNim9UYH2mmGNTn3S4V-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>A new alleged shot of the die for Apple's A20 Pro chipset gives us our first look at the new chip, which should be built on the TSMC 2nm process. The new chip is expected to power both the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a> and the rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a>.</p><p>The leak comes from <a href="https://weibo.com/7215797790/RfPk17V5Y" target="_blank">Weibo user "White rice fried white rice" </a>(machine translated), who posted some images of the die and an analysis of how it might be laid out. Based on their reporting, it seems the chip has been significantly redesigned.</p><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:55.75%;"><img id="3BhrW6hUMjoHVpt25uJJ88" name="Untitled" alt="Alleged Apple A20 Pro die" src="https://cdn.mos.cms.futurecdn.net/3BhrW6hUMjoHVpt25uJJ88.png" mos="" align="middle" fullscreen="" width="2000" height="1115" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: White rice fried white rice (Weibo))</span></figcaption></figure><p>Here's what the new chip appears to feature:</p><ul><li>7-core GPU vs 6 core on the A19 Pro</li><li>4 efficiency and 2 performance CPU cores</li><li>8MB L2 cache for efficiency cores vs 6MB on the A19</li><li>16MB L2 cache for performance cores (same as the A19 Pro)</li><li>96-bit LPDDR5X memory interface</li></ul><p>What does that all mean? At its most basic level, the larger GPU and more cache memory should translate into faster gaming, graphics and overall performance on the iPhone 18 Pro, <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro Max</a> and iPhone Ultra. Plus, if the leak is accurate that 7-core GPU would be the largest ever used by Apple.</p><p>The leak is fairly speculative on the layout, as they apparently tried several before landing on one that was the "most reasonable."</p><p>The die does not have a labeled NPU or ISP block, important since the NPU will be responsible for AI features. Presumably, that will be bigger as well, which is likely why the CPU is shifted compared to the A19 Pro.</p><h2 id="how-does-that-the-a20-pro-compare-to-android-phones">How does that the A20 Pro compare to Android phones?</h2><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="hq4JHJuwbxiJS6kxfZneS7" name="snapdragon-8-elite-5" alt="Snapdragon 8 Elite Gen 5 chipset" src="https://cdn.mos.cms.futurecdn.net/hq4JHJuwbxiJS6kxfZneS7.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>Samsung, Apple's main rival, has been utilizing the powerful Qualcomm <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-just-confirmed-the-most-obvious-galaxy-z-fold-8-upgrade-but-im-still-surprised">Snapdragon 8 Elite Gen 5</a> silicon. Both the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review">Galaxy S26 Ultra</a> and the foldable <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8</a> are multitasking powerhouses thanks to Qualcomm's chip.</p><p>In our internal tests, both proved quite powerful and outperformed the iPhone 17 Pro Max with the A19 Pro chipset, especially in multicore testing and graphics benchmarks.</p><div ><table><caption>Chip comparisons</caption><thead><tr><th class="firstcol " ><p>Phone</p></th><th  ><p>3DMark Solar Bay Unlimited</p></th></tr></thead><tbody><tr><td class="firstcol " ><p>iPhone 17 Pro Max</p></td><td  ><p>46.6/ 12,260</p></td></tr><tr><td class="firstcol " ><p>Galaxy S26 Ultra</p></td><td  ><p>49.37/ 12,984</p></td></tr><tr><td class="firstcol " ><p>Galaxy Z Fold 8</p></td><td  ><p>47.35/ 12,454</p></td></tr><tr><td class="firstcol " ><p>Motorola Razr Fold</p></td><td  ><p>35.12/ 9,413</p></td></tr></tbody></table></div><p>Apple and Samsung trade performance as each new generation releases. Similarly, while the S26 Ultra and Z Fold 8 are currently front running, it's not by a significant ammount.</p><p>If the A20 Pro is as powerful as it seems, the iPhone 18 Pro Max and iPhone Ultra should equal or surpass what Samsung and Qualcomm are doing.</p><p>Both iPhones are expected to launch at the <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">Apple event</a> on Sept. 9 alongside at least <a href="https://www.tomsguide.com/phones/iphones/apple-sept-9-event-all-9-new-products-were-expecting-to-see">seven other devices</a>. Bookmark Tom's Guide as we'll be on hand to cover all the latest news.</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-18-pro-now-just-tipped-for-3-colors-heres-your-options">iPhone 18 Pro now tipped for just 3 colors — here's your options</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-vs-iphone-17-pro-should-you-upgrade-this-year">iPhone 18 Pro vs. iPhone 17 Pro: Should you upgrade this year?</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-vs-iphone-18-pro-max-vs-iphone-ultra-which-upcoming-iphone-is-right-for-you">iPhone 18 Pro vs iPhone 18 Pro Max vs iPhone Ultra: Which upcoming iPhone is right for you?</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone Air 2 rumors — 5 biggest expected upgrades ]]></title>
                                                                                                <dc:content><![CDATA[ <p>When I first got my hands on the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air</a>, I was instantly head over heels for its rail-thin construction — but my admiration faded the more I used it. While its refined design clearly deserves praise, the compromises I soon found with it quickly became impossible to ignore. In fact, I’ve previously argued that the standard <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-review">iPhone 17</a> was the superior phone between the two.</p><p>With the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-all-the-rumors-so-far">iPhone Air 2</a>, Apple clearly knows it has to redeem itself in a big way. Early rumors and leaks suggest Apple is aiming to fix the pain points that discouraged consumers from choosing it over more capable alternatives like the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">17 Pro Max</a>. Considering that Apple is reportedly delaying its launch to focus on the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a>, <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a>, and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">18 Pro Max</a> for its 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> next week, these rumored upgrades should make the extra wait worthwhile.</p><p>Here are the 7 biggest expected upgrades I’m most excited to see in the iPhone Air 2.</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/rQHEN3kngZo" allowfullscreen></iframe></div></div><h2 id="dual-cameras">Dual cameras</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="EF83KhnbdoXXHL2a2aAfu" name="iPhone Air-3" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/EF83KhnbdoXXHL2a2aAfu.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Perhaps the single biggest missed opportunity with the original iPhone Air was settling for a lone rear camera, an omission that I felt was glaring for a device carrying a flagship-tier price tag. That’s why I’m thrilled about leaks hinting that Apple is developing a <a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-could-fix-one-of-the-biggest-problems-heres-what-we-know">dual-camera system for the iPhone Air 2</a>, reportedly pairing a 48MP main camera with a 48MP ultrawide shooter.</p><p>It’s the exact utility I expect from a premium phone. An ultrawide lens unlocks several practical advantages, from capturing more expansive scenes to feeding the depth data needed for more natural subject separation in portrait mode. From a content creation standpoint, that wider field of view changes everything. Because I typically avoid using lower-resolution front cameras for vlogging, having an ultrawide sensor on the back makes walk-and-talk recording easier.</p><h2 id="a20-chip">A20 chip</h2><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="eJ4UG55pYzcocwWMYAtwF3" name="iPhone Air-1-2" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/eJ4UG55pYzcocwWMYAtwF3.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>This rumor stirs up some controversy: rather than getting the flagship A20 Pro silicon expected to debut on the iPhone 18 Pro models, the iPhone Air 2 is rumored to settle for the standard <a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-leak-just-gave-us-a-ton-of-information-new-color-new-camera-and-a-new-processor">A20 chip instead</a>.</p><p>For reference, the original iPhone Air relies on a downclocked version of the A19 Pro. Even so, the leap to a 2nm manufacturing process should give the iPhone Air 2 more than enough muscle to handle whatever is thrown its way, all while delivering the thermal efficiency an ultra-slim chassis desperately needs.</p><h2 id="higher-capacity-battery-cell">Higher capacity battery cell</h2><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="YSJJkpkAGgxQzjDuwtz863" name="iPhone Air-19" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/YSJJkpkAGgxQzjDuwtz863.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>When real estate is at a premium for an ultra-thin device, battery life is always a major concern — and the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-battery-life-tested">iPhone Air certainly proved that</a>. In fact, it posted the shortest result in our custom battery drain test among last year’s lineup, averaging just 12 hours and 2 minutes.</p><p>Rumors suggest Apple intends to directly address this shortcoming by outfitting the iPhone Air 2 with a larger-capacity battery. <a href="https://weibo.com/6048569942/R7zsmexgd" target="_blank">Supply chain leaks</a> point to a 3,500 mAh cell, an upgrade over the original model’s 3,149 mAh pack. That works out to roughly an 11% increase, which is substantial given the tight physical constraints of an ultra-slim frame. Paired with the power-efficiency gains expected from the 2nm A20 chip, it feels entirely possible for the Air 2 to approach the 14-hour mark in our testing.</p><h2 id="smaller-dynamic-island-cutout">Smaller Dynamic Island cutout</h2><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="ND2Fj9V3sLxqBjwahh6s53" name="iPhone Air" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/ND2Fj9V3sLxqBjwahh6s53.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>This next upgrade is lower on my wishlist because the pill cutout never felt like a major distraction on the current model, but reports suggest the Dynamic Island’s footprint will be significantly reduced. While we haven’t seen leaked images or renders depicting the new dimensions just yet, I suspect this slimmer cutout will look strikingly similar to what we’ve seen in <a href="https://www.tomsguide.com/phones/iphones/its-about-time-leaked-iphone-18-pro-images-show-off-shrinking-dynamic-island">leaked renders for the iPhone 18 Pro</a>.</p><p>Shaving down the cutout’s width would immediately make full-screen media, gaming, and everyday reading feel more immersive. Just as importantly, shrinking the hardware footprint without sacrificing software utility — such as <a href="https://www.tomsguide.com/how-to/how-to-adjust-live-activities-updates-on-your-iphone">Live Activities</a> and background alerts — would give the Air 2 a cleaner, less intrusive aesthetic.</p><h2 id="lavender-colorway">Lavender colorway</h2><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="KFDpjxdB4rtP68S2yvVhv" name="iPhone Air-LIST1" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/KFDpjxdB4rtP68S2yvVhv.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>If there’s one thing the iPhone 17 Pro and 17 Pro Max proved to me, it’s how much a standout hero color can make all the difference. While Apple offered four colorways for the original iPhone Air, they were all a bit too muted for my liking — and a far cry from the piercing hue that catapulted <a href="https://www.tomsguide.com/phones/iphones/im-buying-a-new-iphone-17-pro-max-but-only-because-its-orange">Cosmic Orange up the sales charts on the 17 Pro models</a>.</p><p>Leaks indicate Apple plans to introduce a fresh <a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-leak-just-gave-us-a-ton-of-information-new-color-new-camera-and-a-new-processor">light purple finish</a> — described by tipsters as closer to a soft lavender tone — that is expected to replace the current Sky Blue option alongside Space Black, Cloud White, and Light Gold. A vibrant pastel like this feels tailor-made for an ultra-slim chassis, and it's exactly the kind of visual refresh that could persuade shoppers to give the Air 2 a serious second look.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OR9DNW"></div>                            </div>                            <script src="https://kwizly.com/embed/OR9DNW.js" async></script><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-exclusive-gurman-on-price-release-date-and-secret-weapon-versus-android">iPhone Ultra exclusive: Gurman on price, release date rumors and 'day one' weapon against Android</a></li><li><a href="https://www.tomsguide.com/computing/mobile-apps/mapquest-is-suddenly-no-4-in-the-apple-app-store-heres-why">'We're not changing it': MapQuest hits No. 1 in App Store after refusing to rename Lake Ontario to Lake America</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-18-pro-max-unboxed-ahead-of-apple-event-these-could-be-the-final-designs">iPhone Ultra and 18 Pro Max unboxed ahead of Apple event — these could be the final designs</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-air-2-rumors-5-biggest-expected-upgrades</link>
                                                                            <description>
                            <![CDATA[ I break down all the iPhone Air 2 rumors to explain all the biggest upgrades that Apple's next generation, ultra-thin iPhone is expected to get when it launches. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">ctjDoSybbZQg4pa7MSbtgT</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/bWRiHr2xAWuu7w7QFRLsq-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 03 Sep 2026 08:00:00 +0000</pubDate>                                                                                                                                <updated>Thu, 03 Sep 2026 08:07:01 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/bWRiHr2xAWuu7w7QFRLsq-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Air shown in hand]]></media:description>                                                            <media:text><![CDATA[iPhone Air shown in hand]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Air shown in hand]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/bWRiHr2xAWuu7w7QFRLsq-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When I first got my hands on the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-review">iPhone Air</a>, I was instantly head over heels for its rail-thin construction — but my admiration faded the more I used it. While its refined design clearly deserves praise, the compromises I soon found with it quickly became impossible to ignore. In fact, I’ve previously argued that the standard <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-review">iPhone 17</a> was the superior phone between the two.</p><p>With the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-all-the-rumors-so-far">iPhone Air 2</a>, Apple clearly knows it has to redeem itself in a big way. Early rumors and leaks suggest Apple is aiming to fix the pain points that discouraged consumers from choosing it over more capable alternatives like the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">17 Pro Max</a>. Considering that Apple is reportedly delaying its launch to focus on the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a>, <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a>, and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">18 Pro Max</a> for its 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> next week, these rumored upgrades should make the extra wait worthwhile.</p><p>Here are the 7 biggest expected upgrades I’m most excited to see in the iPhone Air 2.</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/rQHEN3kngZo" allowfullscreen></iframe></div></div><h2 id="dual-cameras">Dual cameras</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="EF83KhnbdoXXHL2a2aAfu" name="iPhone Air-3" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/EF83KhnbdoXXHL2a2aAfu.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Perhaps the single biggest missed opportunity with the original iPhone Air was settling for a lone rear camera, an omission that I felt was glaring for a device carrying a flagship-tier price tag. That’s why I’m thrilled about leaks hinting that Apple is developing a <a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-could-fix-one-of-the-biggest-problems-heres-what-we-know">dual-camera system for the iPhone Air 2</a>, reportedly pairing a 48MP main camera with a 48MP ultrawide shooter.</p><p>It’s the exact utility I expect from a premium phone. An ultrawide lens unlocks several practical advantages, from capturing more expansive scenes to feeding the depth data needed for more natural subject separation in portrait mode. From a content creation standpoint, that wider field of view changes everything. Because I typically avoid using lower-resolution front cameras for vlogging, having an ultrawide sensor on the back makes walk-and-talk recording easier.</p><h2 id="a20-chip">A20 chip</h2><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="eJ4UG55pYzcocwWMYAtwF3" name="iPhone Air-1-2" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/eJ4UG55pYzcocwWMYAtwF3.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>This rumor stirs up some controversy: rather than getting the flagship A20 Pro silicon expected to debut on the iPhone 18 Pro models, the iPhone Air 2 is rumored to settle for the standard <a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-leak-just-gave-us-a-ton-of-information-new-color-new-camera-and-a-new-processor">A20 chip instead</a>.</p><p>For reference, the original iPhone Air relies on a downclocked version of the A19 Pro. Even so, the leap to a 2nm manufacturing process should give the iPhone Air 2 more than enough muscle to handle whatever is thrown its way, all while delivering the thermal efficiency an ultra-slim chassis desperately needs.</p><h2 id="higher-capacity-battery-cell">Higher capacity battery cell</h2><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="YSJJkpkAGgxQzjDuwtz863" name="iPhone Air-19" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/YSJJkpkAGgxQzjDuwtz863.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>When real estate is at a premium for an ultra-thin device, battery life is always a major concern — and the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-battery-life-tested">iPhone Air certainly proved that</a>. In fact, it posted the shortest result in our custom battery drain test among last year’s lineup, averaging just 12 hours and 2 minutes.</p><p>Rumors suggest Apple intends to directly address this shortcoming by outfitting the iPhone Air 2 with a larger-capacity battery. <a href="https://weibo.com/6048569942/R7zsmexgd" target="_blank">Supply chain leaks</a> point to a 3,500 mAh cell, an upgrade over the original model’s 3,149 mAh pack. That works out to roughly an 11% increase, which is substantial given the tight physical constraints of an ultra-slim frame. Paired with the power-efficiency gains expected from the 2nm A20 chip, it feels entirely possible for the Air 2 to approach the 14-hour mark in our testing.</p><h2 id="smaller-dynamic-island-cutout">Smaller Dynamic Island cutout</h2><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="ND2Fj9V3sLxqBjwahh6s53" name="iPhone Air" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/ND2Fj9V3sLxqBjwahh6s53.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>This next upgrade is lower on my wishlist because the pill cutout never felt like a major distraction on the current model, but reports suggest the Dynamic Island’s footprint will be significantly reduced. While we haven’t seen leaked images or renders depicting the new dimensions just yet, I suspect this slimmer cutout will look strikingly similar to what we’ve seen in <a href="https://www.tomsguide.com/phones/iphones/its-about-time-leaked-iphone-18-pro-images-show-off-shrinking-dynamic-island">leaked renders for the iPhone 18 Pro</a>.</p><p>Shaving down the cutout’s width would immediately make full-screen media, gaming, and everyday reading feel more immersive. Just as importantly, shrinking the hardware footprint without sacrificing software utility — such as <a href="https://www.tomsguide.com/how-to/how-to-adjust-live-activities-updates-on-your-iphone">Live Activities</a> and background alerts — would give the Air 2 a cleaner, less intrusive aesthetic.</p><h2 id="lavender-colorway">Lavender colorway</h2><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="KFDpjxdB4rtP68S2yvVhv" name="iPhone Air-LIST1" alt="iPhone Air shown in hand" src="https://cdn.mos.cms.futurecdn.net/KFDpjxdB4rtP68S2yvVhv.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>If there’s one thing the iPhone 17 Pro and 17 Pro Max proved to me, it’s how much a standout hero color can make all the difference. While Apple offered four colorways for the original iPhone Air, they were all a bit too muted for my liking — and a far cry from the piercing hue that catapulted <a href="https://www.tomsguide.com/phones/iphones/im-buying-a-new-iphone-17-pro-max-but-only-because-its-orange">Cosmic Orange up the sales charts on the 17 Pro models</a>.</p><p>Leaks indicate Apple plans to introduce a fresh <a href="https://www.tomsguide.com/phones/iphones/iphone-air-2-leak-just-gave-us-a-ton-of-information-new-color-new-camera-and-a-new-processor">light purple finish</a> — described by tipsters as closer to a soft lavender tone — that is expected to replace the current Sky Blue option alongside Space Black, Cloud White, and Light Gold. A vibrant pastel like this feels tailor-made for an ultra-slim chassis, and it's exactly the kind of visual refresh that could persuade shoppers to give the Air 2 a serious second look.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OR9DNW"></div>                            </div>                            <script src="https://kwizly.com/embed/OR9DNW.js" async></script><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-exclusive-gurman-on-price-release-date-and-secret-weapon-versus-android">iPhone Ultra exclusive: Gurman on price, release date rumors and 'day one' weapon against Android</a></li><li><a href="https://www.tomsguide.com/computing/mobile-apps/mapquest-is-suddenly-no-4-in-the-apple-app-store-heres-why">'We're not changing it': MapQuest hits No. 1 in App Store after refusing to rename Lake Ontario to Lake America</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-18-pro-max-unboxed-ahead-of-apple-event-these-could-be-the-final-designs">iPhone Ultra and 18 Pro Max unboxed ahead of Apple event — these could be the final designs</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone Ultra price rumors — here's how much you can expect to pay for Apple’s first foldable ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple is clearly late to the foldable game, but with its <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> a little over a week away, the buzz around the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> is kicking into high gear. While the prospect of Apple’s first foldable device hitting the market is genuinely exciting, there’s one thing I can’t shake: its rumored price.</p><p>That’s because I’ve tested many of the <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phones</a> around, including recent releases like the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> and <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold</a>. I've been tracking every iPhone Ultra price rumor over the last few months, and the scattered predictions are cause for concern. There’s no denying that this device is heading into ultra-luxury territory, but if history has any bearing, Apple can’t afford to price it out of reach.</p><h2 id="iphone-ultra-could-be-2-000-to-2-500">iPhone Ultra could be $2,000 to $2,500</h2><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>256GB</strong></p></td><td  ><p><strong>512GB</strong></p></td><td  ><p><strong>1TB</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Apple iPhone Ultra (low estimate)</strong></p></td><td  ><p>$2,100</p></td><td  ><p>$2,300</p></td><td  ><p>$2,300</p></td></tr><tr><td class="firstcol " ><p><strong>Apple iPhone Ultra (mid estimate)</strong></p></td><td  ><p>$2,300</p></td><td  ><p>$2,500</p></td><td  ><p>$2,700</p></td></tr><tr><td class="firstcol " ><p><strong>Apple iPhone Ultra (high estimate)</strong></p></td><td  ><p>$2,500</p></td><td  ><p>$2,700</p></td><td  ><p>$2,900</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8 Ultra</strong></p></td><td  ><p>$2,099</p></td><td  ><p>$2,299</p></td><td  ><p>$2,699</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 11 Pro Fold</strong></p></td><td  ><p>$1,899</p></td><td  ><p>$2,019</p></td><td  ><p>$2,249</p></td></tr><tr><td class="firstcol " ><p><strong>Motorola Razr Fold</strong></p></td><td  ><p>N/A</p></td><td  ><p>$1,899</p></td><td  ><p>N/A</p></td></tr></tbody></table></div><p>Analysts have been estimating the foldable’s price for a while now, with the latest reports indicating that the iPhone Ultra could fetch anywhere from <a href="https://www.tomsguide.com/phones/iphones/apple-expects-10-million-people-to-buy-a-usd2-500-iphone-ultra-and-its-a-huge-gamble">$2,000 to $2,500</a>. As much as I’d love for Apple to undercut the competition by keeping it closer to $2,000, realistically I think it will land north of the Galaxy Z Fold 8 Ultra’s $2,099 starting price.</p><p>So far, though, reports haven't clarified how those price points align with specific storage configurations. At the baseline tier, a 256GB iPhone Ultra could start around $2,100 to directly match what Samsung charges for its top-of-the-line foldable. On the higher end of the spectrum, it could easily reach a whopping $2,500 for the baseline option — with upwards of $2,900 for 1TB. Personally, I feel $2,300 is the most realistic sweet spot.</p><p>As shown in the chart above, here's how the iPhone Ultra is expected to stack up against its direct rivals across each storage tier. Based on Apple’s current price structure with the iPhone 17 Pro Max, each storage tier is separated by roughly $200.</p><h2 id="reasons-why-it-could-cost-so-much">Reasons why it could cost so much</h2><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="LCYKZkLw26qbVSSwHPj5f3" name="iPhone Ultra front 1.AppleTrack-2" alt="iPhone Ultra shown from the front screen" src="https://cdn.mos.cms.futurecdn.net/LCYKZkLw26qbVSSwHPj5f3.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: AppleTrack)</span></figcaption></figure><p>Apple is stepping into uncharted territory with the iPhone Ultra, so it’s understandable why it could command a premium. While the form factor appears to <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-dummy-unit-video-just-gave-us-a-10-minute-tour-of-apples-first-foldable-phone-see-how-the-wide-design-compares-to-pixel-fold-and-ipad-pro-and-a-serious-wobble-issue">feature a wider aspect ratio</a> than rival book-style models that have been on the market for years, there are practical engineering reasons behind a potential $2,000+ starting price.</p><p>One of the biggest drivers is the <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-invisible-crease-sounds-great-but-this-is-the-feature-apple-cant-afford-to-ignore">nearly invisible crease</a> Apple has reportedly developed to make the inner display look seamless. No manufacturer has truly eliminated this aesthetic compromise, as most current foldables still exhibit a noticeable indentation. Even if you aren't bothered by a standard crease, engineering it out entirely adds serious manufacturing costs.</p><p>However, Samsung has done a very impressive job of minimizing the crease with the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a> series, thanks to its <a href="https://www.tomsguide.com/phones/samsung-phones/ive-seen-the-galaxy-z-fold-8s-flex-titanium-screen-and-apple-should-be-nervous">Flex Titanium</a> tech.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:6480px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="498pZixUYujeSrnk6S2u89" name="Google Pixel 11 Pro Fold review" alt="Google Pixel 11 Pro Fold review." src="https://cdn.mos.cms.futurecdn.net/498pZixUYujeSrnk6S2u89.jpg" mos="" align="middle" fullscreen="" width="6480" height="3645" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Under the hood, <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-tipped-for-a20-pro-chip-apples-first-2nm-processor-to-power-new-foldable-phone">Apple’s A20 Pro chip</a> is tipped to leverage a cutting-edge 2nm process node. Paired with broad component cost increases across the supply chain, that silicon upgrade could push the iPhone Ultra's bill of materials substantially higher. No hardware maker is immune to these pressures — both Google and Samsung launched their latest foldables with $100 price hikes over their previous generations.</p><p>The most compelling justification for a higher price tag may come down to the software experience in <a href="https://www.tomsguide.com/phones/iphones/ios-27-public-beta-hands-on-preview-the-new-siri-and-apple-intelligence-features-completely-changed-how-i-use-my-iphone">iOS 27</a>. Beyond <a href="https://www.tomsguide.com/phones/iphones/i-spent-a-week-with-siri-ai-here-are-my-honest-pros-and-cons">Siri AI</a> and Apple Intelligence features, the real differentiator is system-level optimization for dynamic app scaling and fluid transitions.</p><p>Android hardware partners still <a href="https://www.tomsguide.com/phones/iphones/ive-tested-every-major-foldable-phone-this-year-and-the-iphone-ultra-can-beat-them-all-with-this-one-killer-feature">wrestle with consistent multi-window layouts</a>, so if Apple nails seamless transitions across both screens in both portrait and landscape modes, that polished software experience could easily help justify the markup.</p><h2 id="history-can-t-afford-to-repeat-itself">History can’t afford to repeat itself</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2485px;"><p class="vanilla-image-block" style="padding-top:55.09%;"><img id="CCHHSG6TBnD4P2XRXnpw6W" name="Apple Vision Pro - Putting it on-2.jpg" alt="Putting on Vision Pro" src="https://cdn.mos.cms.futurecdn.net/CCHHSG6TBnD4P2XRXnpw6W.jpg" mos="" align="middle" fullscreen="" width="2485" height="1369" attribution="" endorsement="" 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 playing a delicate game when it comes to pricing. I can’t help but think about the lukewarm adoption of the <a href="https://www.tomsguide.com/computing/smart-glasses/apple-vision-pro-review">Apple Vision Pro</a>, which many attribute directly to its exorbitant starting price. The iPhone Ultra could easily run into a similar wall if it launches at $2,500.</p><p>I’ve long argued that foldables drive the most meaningful hardware innovation today, and consumers are often willing to pay a premium for a genuinely extraordinary experience. Yet, devices like the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-trifold-review">Samsung Galaxy Z TriFold</a> proved that pricing can be fatal, with its <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-kills-the-galaxy-z-trifold-after-just-three-months-and-im-hardly-surprised-heres-why">$2,899 sticker shock largely to blame</a>.</p><p>That’s why I can't emphasize enough that $2,300 is the real sweet spot for the iPhone Ultra. It isn't so astronomical that it scares away buyers accustomed to paying $1,000+ for standard flagships, while still allowing Apple to command a premium that reflects the engineering behind it.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ONVEJO"></div>                            </div>                            <script src="https://kwizly.com/embed/ONVEJO.js" async></script><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-vs-galaxy-z-fold-8-ultra-heres-the-flagship-foldable-id-recommend">iPhone Ultra vs. Galaxy Z Fold 8 Ultra — here's the flagship foldable I'd recommend based on the rumors</a></li><li><a href="https://www.tomsguide.com/phones/google-pixel-phones/ive-been-testing-pixel-11-pro-xl-for-a-week-heres-why-hilight-is-the-most-disappointing-new-feature">I've been testing Pixel 11 Pro XL for a week — here's why HiLight is the most disappointing new feature</a></li><li><a href="https://www.tomsguide.com/phones/iphones/i-tried-this-magsafe-game-controller-and-it-puts-other-bluetooth-gamepads-to-shame-plus-its-usd20-off-right-now">I tried this MagSafe game controller and it puts other Bluetooth gamepads to shame — plus it’s $20 off right now</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-ultra-price-rumors-heres-how-much-you-can-expect-to-pay-for-apples-first-foldable</link>
                                                                            <description>
                            <![CDATA[ iPhone Ultra price rumors have Apple's first foldable device all over the spectrum, with estimates hinting at $2,500+ for a baseline storage model. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">3EvnnKd2Yw6VaE2GJiM7eN</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/oqerWy42bqvSRMhJh5NbQU-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 03 Sep 2026 04:30:00 +0000</pubDate>                                                                                                                                <updated>Thu, 03 Sep 2026 08:07:01 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/oqerWy42bqvSRMhJh5NbQU-1280-80.jpg">
                                                            <media:credit><![CDATA[Apple Track]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Ultra render in hand]]></media:description>                                                            <media:text><![CDATA[iPhone Ultra render in hand]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Ultra render in hand]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/oqerWy42bqvSRMhJh5NbQU-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple is clearly late to the foldable game, but with its <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> a little over a week away, the buzz around the <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> is kicking into high gear. While the prospect of Apple’s first foldable device hitting the market is genuinely exciting, there’s one thing I can’t shake: its rumored price.</p><p>That’s because I’ve tested many of the <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phones</a> around, including recent releases like the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> and <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold</a>. I've been tracking every iPhone Ultra price rumor over the last few months, and the scattered predictions are cause for concern. There’s no denying that this device is heading into ultra-luxury territory, but if history has any bearing, Apple can’t afford to price it out of reach.</p><h2 id="iphone-ultra-could-be-2-000-to-2-500">iPhone Ultra could be $2,000 to $2,500</h2><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>256GB</strong></p></td><td  ><p><strong>512GB</strong></p></td><td  ><p><strong>1TB</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Apple iPhone Ultra (low estimate)</strong></p></td><td  ><p>$2,100</p></td><td  ><p>$2,300</p></td><td  ><p>$2,300</p></td></tr><tr><td class="firstcol " ><p><strong>Apple iPhone Ultra (mid estimate)</strong></p></td><td  ><p>$2,300</p></td><td  ><p>$2,500</p></td><td  ><p>$2,700</p></td></tr><tr><td class="firstcol " ><p><strong>Apple iPhone Ultra (high estimate)</strong></p></td><td  ><p>$2,500</p></td><td  ><p>$2,700</p></td><td  ><p>$2,900</p></td></tr><tr><td class="firstcol " ><p><strong>Samsung Galaxy Z Fold 8 Ultra</strong></p></td><td  ><p>$2,099</p></td><td  ><p>$2,299</p></td><td  ><p>$2,699</p></td></tr><tr><td class="firstcol " ><p><strong>Google Pixel 11 Pro Fold</strong></p></td><td  ><p>$1,899</p></td><td  ><p>$2,019</p></td><td  ><p>$2,249</p></td></tr><tr><td class="firstcol " ><p><strong>Motorola Razr Fold</strong></p></td><td  ><p>N/A</p></td><td  ><p>$1,899</p></td><td  ><p>N/A</p></td></tr></tbody></table></div><p>Analysts have been estimating the foldable’s price for a while now, with the latest reports indicating that the iPhone Ultra could fetch anywhere from <a href="https://www.tomsguide.com/phones/iphones/apple-expects-10-million-people-to-buy-a-usd2-500-iphone-ultra-and-its-a-huge-gamble">$2,000 to $2,500</a>. As much as I’d love for Apple to undercut the competition by keeping it closer to $2,000, realistically I think it will land north of the Galaxy Z Fold 8 Ultra’s $2,099 starting price.</p><p>So far, though, reports haven't clarified how those price points align with specific storage configurations. At the baseline tier, a 256GB iPhone Ultra could start around $2,100 to directly match what Samsung charges for its top-of-the-line foldable. On the higher end of the spectrum, it could easily reach a whopping $2,500 for the baseline option — with upwards of $2,900 for 1TB. Personally, I feel $2,300 is the most realistic sweet spot.</p><p>As shown in the chart above, here's how the iPhone Ultra is expected to stack up against its direct rivals across each storage tier. Based on Apple’s current price structure with the iPhone 17 Pro Max, each storage tier is separated by roughly $200.</p><h2 id="reasons-why-it-could-cost-so-much">Reasons why it could cost so much</h2><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="LCYKZkLw26qbVSSwHPj5f3" name="iPhone Ultra front 1.AppleTrack-2" alt="iPhone Ultra shown from the front screen" src="https://cdn.mos.cms.futurecdn.net/LCYKZkLw26qbVSSwHPj5f3.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: AppleTrack)</span></figcaption></figure><p>Apple is stepping into uncharted territory with the iPhone Ultra, so it’s understandable why it could command a premium. While the form factor appears to <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-dummy-unit-video-just-gave-us-a-10-minute-tour-of-apples-first-foldable-phone-see-how-the-wide-design-compares-to-pixel-fold-and-ipad-pro-and-a-serious-wobble-issue">feature a wider aspect ratio</a> than rival book-style models that have been on the market for years, there are practical engineering reasons behind a potential $2,000+ starting price.</p><p>One of the biggest drivers is the <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-invisible-crease-sounds-great-but-this-is-the-feature-apple-cant-afford-to-ignore">nearly invisible crease</a> Apple has reportedly developed to make the inner display look seamless. No manufacturer has truly eliminated this aesthetic compromise, as most current foldables still exhibit a noticeable indentation. Even if you aren't bothered by a standard crease, engineering it out entirely adds serious manufacturing costs.</p><p>However, Samsung has done a very impressive job of minimizing the crease with the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-review-wide-for-the-win">Galaxy Z Fold 8</a> series, thanks to its <a href="https://www.tomsguide.com/phones/samsung-phones/ive-seen-the-galaxy-z-fold-8s-flex-titanium-screen-and-apple-should-be-nervous">Flex Titanium</a> tech.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:6480px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="498pZixUYujeSrnk6S2u89" name="Google Pixel 11 Pro Fold review" alt="Google Pixel 11 Pro Fold review." src="https://cdn.mos.cms.futurecdn.net/498pZixUYujeSrnk6S2u89.jpg" mos="" align="middle" fullscreen="" width="6480" height="3645" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Under the hood, <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-tipped-for-a20-pro-chip-apples-first-2nm-processor-to-power-new-foldable-phone">Apple’s A20 Pro chip</a> is tipped to leverage a cutting-edge 2nm process node. Paired with broad component cost increases across the supply chain, that silicon upgrade could push the iPhone Ultra's bill of materials substantially higher. No hardware maker is immune to these pressures — both Google and Samsung launched their latest foldables with $100 price hikes over their previous generations.</p><p>The most compelling justification for a higher price tag may come down to the software experience in <a href="https://www.tomsguide.com/phones/iphones/ios-27-public-beta-hands-on-preview-the-new-siri-and-apple-intelligence-features-completely-changed-how-i-use-my-iphone">iOS 27</a>. Beyond <a href="https://www.tomsguide.com/phones/iphones/i-spent-a-week-with-siri-ai-here-are-my-honest-pros-and-cons">Siri AI</a> and Apple Intelligence features, the real differentiator is system-level optimization for dynamic app scaling and fluid transitions.</p><p>Android hardware partners still <a href="https://www.tomsguide.com/phones/iphones/ive-tested-every-major-foldable-phone-this-year-and-the-iphone-ultra-can-beat-them-all-with-this-one-killer-feature">wrestle with consistent multi-window layouts</a>, so if Apple nails seamless transitions across both screens in both portrait and landscape modes, that polished software experience could easily help justify the markup.</p><h2 id="history-can-t-afford-to-repeat-itself">History can’t afford to repeat itself</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2485px;"><p class="vanilla-image-block" style="padding-top:55.09%;"><img id="CCHHSG6TBnD4P2XRXnpw6W" name="Apple Vision Pro - Putting it on-2.jpg" alt="Putting on Vision Pro" src="https://cdn.mos.cms.futurecdn.net/CCHHSG6TBnD4P2XRXnpw6W.jpg" mos="" align="middle" fullscreen="" width="2485" height="1369" attribution="" endorsement="" 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 playing a delicate game when it comes to pricing. I can’t help but think about the lukewarm adoption of the <a href="https://www.tomsguide.com/computing/smart-glasses/apple-vision-pro-review">Apple Vision Pro</a>, which many attribute directly to its exorbitant starting price. The iPhone Ultra could easily run into a similar wall if it launches at $2,500.</p><p>I’ve long argued that foldables drive the most meaningful hardware innovation today, and consumers are often willing to pay a premium for a genuinely extraordinary experience. Yet, devices like the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-trifold-review">Samsung Galaxy Z TriFold</a> proved that pricing can be fatal, with its <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-kills-the-galaxy-z-trifold-after-just-three-months-and-im-hardly-surprised-heres-why">$2,899 sticker shock largely to blame</a>.</p><p>That’s why I can't emphasize enough that $2,300 is the real sweet spot for the iPhone Ultra. It isn't so astronomical that it scares away buyers accustomed to paying $1,000+ for standard flagships, while still allowing Apple to command a premium that reflects the engineering behind it.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ONVEJO"></div>                            </div>                            <script src="https://kwizly.com/embed/ONVEJO.js" async></script><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-vs-galaxy-z-fold-8-ultra-heres-the-flagship-foldable-id-recommend">iPhone Ultra vs. Galaxy Z Fold 8 Ultra — here's the flagship foldable I'd recommend based on the rumors</a></li><li><a href="https://www.tomsguide.com/phones/google-pixel-phones/ive-been-testing-pixel-11-pro-xl-for-a-week-heres-why-hilight-is-the-most-disappointing-new-feature">I've been testing Pixel 11 Pro XL for a week — here's why HiLight is the most disappointing new feature</a></li><li><a href="https://www.tomsguide.com/phones/iphones/i-tried-this-magsafe-game-controller-and-it-puts-other-bluetooth-gamepads-to-shame-plus-its-usd20-off-right-now">I tried this MagSafe game controller and it puts other Bluetooth gamepads to shame — plus it’s $20 off right now</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone 18 Pro vs. iPhone 17 Pro: Should you upgrade this year? ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Choosing whether or not to upgrade from the excellent <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a> to the forthcoming <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a> may give some Apple fans pause for thought this year. Why? Because Apple is heavily expected to debut the brand-new <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> at its <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> next week.</p><p>The decision becomes whether or not to remain with what's tried and tested, or jump ship to a new form factor that could result in greater productivity and a host of other benefits the <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phones</a> have to offer. On the other hand, you're likely going to sacrifice camera performance, which is typically something Pro users value highly.</p><p>In fact, the photography improvements Apple is allegedly making could be your biggest incentive to switch up from last-year's iPhone 17 Pro to iPhone 18 Pro. And even though the Pro phones aren't cheap, you're still going to save money based on what the Ultra is rumored to cost.</p><p>Although we now have a fixed date for the iPhone 18 Pro event, Apple's phones are still a while away from hitting shelves. Thankfully, we've got a pretty good idea of what's coming and I'm here to provide your iPhone 17 Pro vs iPhone 18 Pro comparison so if you do decide to skip the Ultra, you can see what improvements you'll get by staying with the Pro model.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ODm7mX"></div>                            </div>                            <script src="https://kwizly.com/embed/ODm7mX.js" async></script><h2 class="article-body__section" id="section-iphone-17-pro-vs-iphone-18-pro-specifications"><span>iPhone 17 Pro vs. iPhone 18 Pro: specifications</span></h2><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p><strong>iPhone 17 Pro</strong></p></th><th  ><p><strong>iPhone 18 Pro (rumored)</strong></p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Display size</strong></p></td><td  ><p>6.3 inches</p></td><td  ><p>6.3 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Refresh rate</strong></p></td><td  ><p>120Hz</p></td><td  ><p>120Hz</p></td></tr><tr><td class="firstcol " ><p><strong>CPU</strong></p></td><td  ><p>A19 Pro</p></td><td  ><p>A20 Pro</p></td></tr><tr><td class="firstcol " ><p><strong>Memory</strong></p></td><td  ><p>12GB</p></td><td  ><p>12GB</p></td></tr><tr><td class="firstcol " ><p><strong>Storage</strong></p></td><td  ><p>256GB, 512GB, 1TB,</p></td><td  ><p>256GB, 512GB, 1TB</p></td></tr><tr><td class="firstcol " ><p><strong>Cameras</strong></p></td><td  ><p>48MP main (f/1.78), 48MP ultrawide (f/2.2), 48MP telephoto with 4x optical zoom (f/2.8)</p></td><td  ><p>48MP main with variable aperture, 48MP ultrawide, 48MP telephoto with 5x optical zoom</p></td></tr><tr><td class="firstcol " ><p><strong>Battery Size</strong></p></td><td  ><p>4,252 mAh</p></td><td  ><p>4,288 mAh</p></td></tr><tr><td class="firstcol " ><p><strong>Software</strong></p></td><td  ><p>iOS 27</p></td><td  ><p>iOS 27</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>5.91 x 2.83 x 0.34 inches (150 x 71 x 8.75 mm)</p></td><td  ><p>5.91 × 2.83 × 0.34 inches (150 x 71.9 x 8.75 mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>7.20 ounces (204 grams)</p></td><td  ><p>7.26 ounces (206 grams)</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-iphone-17-pro-vs-iphone-18-pro-price"><span>iPhone 17 Pro vs. iPhone 18 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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="rU7TbT6sxLh7AYrw6yRmoi" name="iPhone 17 Pro and Max-16" alt="iPhone 17 Pro and Pro Max held in the hand/" src="https://cdn.mos.cms.futurecdn.net/rU7TbT6sxLh7AYrw6yRmoi.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Let's start with release dates first. Apple's "Surprise and shine" event is on September 9 and pre-orders typically open on the Friday after the event. However, Apple's iPhone 18 Pro event is on a Wednesday this year, rather than a Tuesday. The latest rumors claim pre-orders will open on September 12 with sales beginning September 18.</p><p>Pricing is less certain but it's almost universally accepted that Apple <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-price-rumors-heres-how-much-more-you-could-pay-this-year">is going to raise prices this year</a>. The iPhone 17 Pro held the line nicely at $999 for its base configuration, but reports suggest Apple may increase the price of its Pro models this year due to rising memory and component costs.</p><p>Globally, some analysts have predicted increases of up to $100 or even $200 depending on the model and storage configuration. If you're on a strict budget, the slightly older 17 Pro might soon see some excellent carrier discounts.</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/rQHEN3kngZo" allowfullscreen></iframe></div></div><h2 class="article-body__section" id="section-iphone-17-pro-vs-iphone-18-pro-design-and-display"><span>iPhone 17 Pro vs. iPhone 18 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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="EPuTcyWZVdJGZNc54Ww6E9" name="iPhone 17 Pro review" alt="iPhone 17 Pro review." src="https://cdn.mos.cms.futurecdn.net/EPuTcyWZVdJGZNc54Ww6E9.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>At a glance, you might have trouble telling the iPhone 18 Pro apart from the iPhone 17 Pro. Both phones are tipped to retain the ergonomic 6.3-inch form factor, a size that nicely balances usability and screen real estate. The iPhone 17 Pro made waves with its aluminum unibody design and Ceramic Shield 2 back, and the 18 Pro is expected to maintain that unified look.</p><p>The most notable design shift could be on the front. Apple is reportedly working on a smaller Dynamic Island for the 18 Pro, finally freeing up a bit more display space. </p><p>Furthermore, the 18 Pro's screen is rumored to receive an efficiency upgrade through newer LTPO+ technology, delivering improved outdoor brightness and better energy efficiency compared to the standard LTPO XDR OLED panel on the iPhone 17 Pro.</p><p>Where you're of course going to see a change is in the color scheme. The iPhone 17 Pro is hard to miss thanks to its Cosmic Orange finish but the rumor is the iPhone 18 Pro will be a little more elegant.</p><p>The iPhone 18 Pro (and 18 Pro Max) are likely to feature the rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-leaked-colors-include-a-stunning-new-dark-cherry-option">Dark Cherry and Light Blue</a> options tipped for this year's lineup. Other color options will very likely include silver and dark gray.</p><h2 class="article-body__section" id="section-iphone-17-pro-vs-iphone-18-pro-cameras"><span>iPhone 17 Pro vs. iPhone 18 Pro: Cameras</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="7iBdM6RkBx9vY5PWZDt6ef" name="iPhone 18 pro edit" alt="iPhone 18 Pro mockup" src="https://cdn.mos.cms.futurecdn.net/7iBdM6RkBx9vY5PWZDt6ef.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: Aptenod / YouTube)</span></figcaption></figure><p>The camera system could be the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-upgrades-everything-we-know-about-the-new-sensor">single biggest upgrade on the iPhone 18 Pro</a> and your main reason for switching up from last year's model. While the iPhone 17 Pro boasts a phenomenal 48MP main lens with a fixed f/1.78 aperture alongside a 48MP ultrawide and 48MP telephoto, the iPhone 18 Pro is set to take mobile photography to the next level.</p><p>Apple is reportedly outfitting the iPhone 18 Pro with a variable-aperture main camera. This would give users true hardware-level control over depth of field and how much light reaches the sensor, heavily outclassing the digital portrait blur we've relied on for years. Add in a new stacked image sensor that improves dynamic range and low-light noise performance, and the 18 Pro could be the undisputed champion for smartphone photographers.</p><p>The only sticking point in that is there have been some rumors that variable aperture could be <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-camera-may-get-this-major-upgrade-but-why-isnt-iphone-18-pro-getting-it-too">exclusive to the Pro Max</a>. The hypothesis is the mechanics required for a variable lens will only fit in a larger phone, ruling out the smaller Pro. This would undoubtedly be a huge blow for those of us that prefer Apple's smaller phones and could be a big reason why you choose to remain with the iPhone 17 Pro over its successor.</p><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="EHpBdnKc9CNvu4GiNaPbH9" name="iPhone 17 Pro review" alt="iPhone 17 Pro taking a photo." src="https://cdn.mos.cms.futurecdn.net/EHpBdnKc9CNvu4GiNaPbH9.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>One more thing to mention is that there have been claims Apple will remove the capacitive capabilities of the Camera Control button for the iPhone 18 Pro. This is due to some users accidentally launching the camera app inadvertently and could be very helpful if you use your iPhone as your main camera.</p><p>Bottom line is that variable aperture on the iPhone 18 Pro could make or break whether or not a lot of people decide to upgrade from the 17 Pro.</p><h2 class="article-body__section" id="section-iphone-17-pro-vs-iphone-18-pro-performance-and-battery"><span>iPhone 17 Pro vs. iPhone 18 Pro: performance and battery</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2p68W9mHAAZd9qESYGbtvV" name="iPhone 17 Pro Max-22" alt="iPhone 17 Pro Max gaming." src="https://cdn.mos.cms.futurecdn.net/2p68W9mHAAZd9qESYGbtvV.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The iPhone 17 Pro is no slouch, thanks to the A19 Pro chip built on a 3-nanometer process. However, the iPhone 18 Pro is expected to be powered by Apple's next-generation A20 Pro chip, manufactured using TSMC's cutting-edge 2nm process. </p><p>This move to a smaller manufacturing process should allow Apple to significantly improve both raw performance and power efficiency.</p><p>Because of this newfound efficiency — and a slight physical battery increase from the 17 Pro's 4,252 mAh up to roughly 4,288 mAh on the 18 Pro — battery life could take a leap forward. </p><p>You can expect the iPhone 18 Pro to easily outlast its predecessor, when it comes to both longevity and overall performance. As always, anyone who wants the fastest possible speed and the most power will always benefit from upgrading to the newest model.</p><h2 class="article-body__section" id="section-iphone-18-pro-max-vs-iphone-18-pro-software-and-apple-intelligence"><span>iPhone 18 Pro Max vs. iPhone 18 Pro: Software and Apple Intelligence</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:3490px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="qdS9MAp79UU3D85qwZjEV6" name="iOS 27 Siri AI" alt="iOS 27 Siri AI running on iPhone 17 Pro." src="https://cdn.mos.cms.futurecdn.net/qdS9MAp79UU3D85qwZjEV6.jpg" mos="" align="middle" fullscreen="" width="3490" height="1963" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Both the iPhone 17 Pro and the iPhone 18 Pro will have access to Apple's latest software tricks, but this year's model will run <a href="https://www.tomsguide.com/phones/iphones/ios-27-public-beta-hands-on-preview-the-new-siri-and-apple-intelligence-features-completely-changed-how-i-use-my-iphone">iOS 27</a> out of the box. The 17 Pro, meanwhile, launched with <a href="https://www.tomsguide.com/phones/iphones/ios-26-review-new-features-liquid-glass">iOS 26</a> but will be eligible for the update in the coming weeks.</p><p>The real difference lies in hardware integration for Apple Intelligence. With 12GB of RAM on both devices, the AI playing field looks level on paper. However, leaks suggest the A20 Pro mentioned earlier features advanced packaging that integrates RAM more closely with the processor, freeing up bandwidth for lightning-fast on-device AI tasks. </p><p>The 18 Pro will simply handle complex generative prompts and on-the-fly photo editing faster than the 17 Pro.</p><p>We'll have to wait to find out if there are any iPhone 18 Pro-specific software or AI features (perhaps around the variable aperture) but for the most part, the 17 Pro will remain able to use almost all the software features Apple has to offer for at least a few more years yet.</p><h2 class="article-body__section" id="section-iphone-17-pro-vs-iphone-18-pro-final-thoughts"><span>iPhone 17 Pro vs. iPhone 18 Pro: Final thoughts</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:1280px;"><p class="vanilla-image-block" style="padding-top:55.78%;"><img id="WNJZg5wpSg4yem6kzvAjLN" name="iPhone 18 Pro and Max LIST Large" alt="iPhone 18 Pro vs iPhone 18 Pro Max." src="https://cdn.mos.cms.futurecdn.net/WNJZg5wpSg4yem6kzvAjLN.jpg" mos="" align="middle" fullscreen="" width="1280" height="714" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>If you're already rocking an iPhone 17 Pro, I feel it's going to be tough to justify an upgrade based on what's already at your disposal. Apple's 2025 effort has a gorgeous 6.3-inch display, a triple 48MP camera setup, and 12GB of RAM to power Apple Intelligence. It’s an incredibly capable device that still has years of top-tier life left in it.</p><p>That said, if you’re a power user or a serious smartphone photographer, the iPhone 18 Pro’s rumored variable aperture, highly efficient 2nm A20 Pro chip, and significantly larger battery might just be too tempting to pass up. Just keep in mind that the variable aperture and longer zoom could be limited to the iPhone 18 Pro Max.</p><p>We'll find out for sure once new Apple CEO John Ternus takes the stage to make these phones official and reveal what the final prices are going to be. In the meantime, let me know in the comments below whether you think an iPhone 18 Pro upgrade is a must-have or if you're content to hold on to the iPhone 17 Pro for a few more years.</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-ultra-exclusive-gurman-on-price-release-date-and-secret-weapon-versus-android">iPhone Ultra exclusive: Gurman on price, release date rumors and 'day one' weapon against Android</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-upgrades-everything-we-know-about-the-new-sensor">iPhone 18 Pro camera upgrades — everything we know about the new sensor</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-18-pro-max-unboxed-ahead-of-apple-event-these-could-be-the-final-designs">iPhone Ultra and 18 Pro Max unboxed ahead of Apple event — these could be the final designs</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-18-pro-vs-iphone-17-pro-should-you-upgrade-this-year</link>
                                                                            <description>
                            <![CDATA[ Apple is weeks away from unveiling the iPhone 18 Pro with some major changes in store, but is it enough to tempt you to upgrade? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">AkyahUpUR3bfVwQR7oueoC</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/zCyBevGh6S2Dj9C2BFrhtn-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 02 Sep 2026 07:30:00 +0000</pubDate>                                                                                                                                <updated>Wed, 02 Sep 2026 08:33:21 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ jeff.parsons@futurenet.com (Jeff Parsons) ]]></author>                    <dc:creator><![CDATA[ Jeff Parsons ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/7z3UTGGrmSokMKxTWHmhjX.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Jeff is U.K. Editor-in-Chief for Tom’s Guide looking after the day-to-day output of the site’s British contingent. &lt;/p&gt;&lt;p&gt;Rising early and heading straight for the coffee machine, Jeff loves nothing more than dialling into the zeitgeist of the day’s tech news. A journalist for over a decade, he&#039;s travelled around the world testing and reviewing any gadget he can get his hands on.&lt;/p&gt;&lt;p&gt;Before joining the team at Tom’s Guide, Jeff covered technology and science for two of the U.K.’s biggest national news sites: Metro.co.uk and the Daily Mirror. Memorable moments include getting lost in Vienna in an electric Audi, touring Lockheed Martin’s mile-long jet factory in Fort Worth and filming a Netflix documentary about Elon Musk in West London.&lt;/p&gt;&lt;p&gt;When not plugged into the current news agenda, editing or commissioning a series of articles or debating the merits of Apple vs Android, Jeff can usually be found out for a run trying to shave precious seconds off his PB. Or lifting weights in a vain attempt to offset the ageing process.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/zCyBevGh6S2Dj9C2BFrhtn-1280-80.jpg">
                                                            <media:credit><![CDATA[Unbox Therapy / Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone 18 Pro vs iPhone 17 Pro.]]></media:description>                                                            <media:text><![CDATA[iPhone 18 Pro vs iPhone 17 Pro.]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone 18 Pro vs iPhone 17 Pro.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/zCyBevGh6S2Dj9C2BFrhtn-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Choosing whether or not to upgrade from the excellent <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a> to the forthcoming <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro</a> may give some Apple fans pause for thought this year. Why? Because Apple is heavily expected to debut the brand-new <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> at its <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> next week.</p><p>The decision becomes whether or not to remain with what's tried and tested, or jump ship to a new form factor that could result in greater productivity and a host of other benefits the <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phones</a> have to offer. On the other hand, you're likely going to sacrifice camera performance, which is typically something Pro users value highly.</p><p>In fact, the photography improvements Apple is allegedly making could be your biggest incentive to switch up from last-year's iPhone 17 Pro to iPhone 18 Pro. And even though the Pro phones aren't cheap, you're still going to save money based on what the Ultra is rumored to cost.</p><p>Although we now have a fixed date for the iPhone 18 Pro event, Apple's phones are still a while away from hitting shelves. Thankfully, we've got a pretty good idea of what's coming and I'm here to provide your iPhone 17 Pro vs iPhone 18 Pro comparison so if you do decide to skip the Ultra, you can see what improvements you'll get by staying with the Pro model.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ODm7mX"></div>                            </div>                            <script src="https://kwizly.com/embed/ODm7mX.js" async></script><h2 class="article-body__section" id="section-iphone-17-pro-vs-iphone-18-pro-specifications"><span>iPhone 17 Pro vs. iPhone 18 Pro: specifications</span></h2><div ><table><thead><tr><th class="firstcol empty" ></th><th  ><p><strong>iPhone 17 Pro</strong></p></th><th  ><p><strong>iPhone 18 Pro (rumored)</strong></p></th></tr></thead><tbody><tr><td class="firstcol " ><p><strong>Display size</strong></p></td><td  ><p>6.3 inches</p></td><td  ><p>6.3 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Refresh rate</strong></p></td><td  ><p>120Hz</p></td><td  ><p>120Hz</p></td></tr><tr><td class="firstcol " ><p><strong>CPU</strong></p></td><td  ><p>A19 Pro</p></td><td  ><p>A20 Pro</p></td></tr><tr><td class="firstcol " ><p><strong>Memory</strong></p></td><td  ><p>12GB</p></td><td  ><p>12GB</p></td></tr><tr><td class="firstcol " ><p><strong>Storage</strong></p></td><td  ><p>256GB, 512GB, 1TB,</p></td><td  ><p>256GB, 512GB, 1TB</p></td></tr><tr><td class="firstcol " ><p><strong>Cameras</strong></p></td><td  ><p>48MP main (f/1.78), 48MP ultrawide (f/2.2), 48MP telephoto with 4x optical zoom (f/2.8)</p></td><td  ><p>48MP main with variable aperture, 48MP ultrawide, 48MP telephoto with 5x optical zoom</p></td></tr><tr><td class="firstcol " ><p><strong>Battery Size</strong></p></td><td  ><p>4,252 mAh</p></td><td  ><p>4,288 mAh</p></td></tr><tr><td class="firstcol " ><p><strong>Software</strong></p></td><td  ><p>iOS 27</p></td><td  ><p>iOS 27</p></td></tr><tr><td class="firstcol " ><p><strong>Dimensions</strong></p></td><td  ><p>5.91 x 2.83 x 0.34 inches (150 x 71 x 8.75 mm)</p></td><td  ><p>5.91 × 2.83 × 0.34 inches (150 x 71.9 x 8.75 mm)</p></td></tr><tr><td class="firstcol " ><p><strong>Weight</strong></p></td><td  ><p>7.20 ounces (204 grams)</p></td><td  ><p>7.26 ounces (206 grams)</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-iphone-17-pro-vs-iphone-18-pro-price"><span>iPhone 17 Pro vs. iPhone 18 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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="rU7TbT6sxLh7AYrw6yRmoi" name="iPhone 17 Pro and Max-16" alt="iPhone 17 Pro and Pro Max held in the hand/" src="https://cdn.mos.cms.futurecdn.net/rU7TbT6sxLh7AYrw6yRmoi.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Let's start with release dates first. Apple's "Surprise and shine" event is on September 9 and pre-orders typically open on the Friday after the event. However, Apple's iPhone 18 Pro event is on a Wednesday this year, rather than a Tuesday. The latest rumors claim pre-orders will open on September 12 with sales beginning September 18.</p><p>Pricing is less certain but it's almost universally accepted that Apple <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-price-rumors-heres-how-much-more-you-could-pay-this-year">is going to raise prices this year</a>. The iPhone 17 Pro held the line nicely at $999 for its base configuration, but reports suggest Apple may increase the price of its Pro models this year due to rising memory and component costs.</p><p>Globally, some analysts have predicted increases of up to $100 or even $200 depending on the model and storage configuration. If you're on a strict budget, the slightly older 17 Pro might soon see some excellent carrier discounts.</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/rQHEN3kngZo" allowfullscreen></iframe></div></div><h2 class="article-body__section" id="section-iphone-17-pro-vs-iphone-18-pro-design-and-display"><span>iPhone 17 Pro vs. iPhone 18 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:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="EPuTcyWZVdJGZNc54Ww6E9" name="iPhone 17 Pro review" alt="iPhone 17 Pro review." src="https://cdn.mos.cms.futurecdn.net/EPuTcyWZVdJGZNc54Ww6E9.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>At a glance, you might have trouble telling the iPhone 18 Pro apart from the iPhone 17 Pro. Both phones are tipped to retain the ergonomic 6.3-inch form factor, a size that nicely balances usability and screen real estate. The iPhone 17 Pro made waves with its aluminum unibody design and Ceramic Shield 2 back, and the 18 Pro is expected to maintain that unified look.</p><p>The most notable design shift could be on the front. Apple is reportedly working on a smaller Dynamic Island for the 18 Pro, finally freeing up a bit more display space. </p><p>Furthermore, the 18 Pro's screen is rumored to receive an efficiency upgrade through newer LTPO+ technology, delivering improved outdoor brightness and better energy efficiency compared to the standard LTPO XDR OLED panel on the iPhone 17 Pro.</p><p>Where you're of course going to see a change is in the color scheme. The iPhone 17 Pro is hard to miss thanks to its Cosmic Orange finish but the rumor is the iPhone 18 Pro will be a little more elegant.</p><p>The iPhone 18 Pro (and 18 Pro Max) are likely to feature the rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-leaked-colors-include-a-stunning-new-dark-cherry-option">Dark Cherry and Light Blue</a> options tipped for this year's lineup. Other color options will very likely include silver and dark gray.</p><h2 class="article-body__section" id="section-iphone-17-pro-vs-iphone-18-pro-cameras"><span>iPhone 17 Pro vs. iPhone 18 Pro: Cameras</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="7iBdM6RkBx9vY5PWZDt6ef" name="iPhone 18 pro edit" alt="iPhone 18 Pro mockup" src="https://cdn.mos.cms.futurecdn.net/7iBdM6RkBx9vY5PWZDt6ef.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: Aptenod / YouTube)</span></figcaption></figure><p>The camera system could be the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-upgrades-everything-we-know-about-the-new-sensor">single biggest upgrade on the iPhone 18 Pro</a> and your main reason for switching up from last year's model. While the iPhone 17 Pro boasts a phenomenal 48MP main lens with a fixed f/1.78 aperture alongside a 48MP ultrawide and 48MP telephoto, the iPhone 18 Pro is set to take mobile photography to the next level.</p><p>Apple is reportedly outfitting the iPhone 18 Pro with a variable-aperture main camera. This would give users true hardware-level control over depth of field and how much light reaches the sensor, heavily outclassing the digital portrait blur we've relied on for years. Add in a new stacked image sensor that improves dynamic range and low-light noise performance, and the 18 Pro could be the undisputed champion for smartphone photographers.</p><p>The only sticking point in that is there have been some rumors that variable aperture could be <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-camera-may-get-this-major-upgrade-but-why-isnt-iphone-18-pro-getting-it-too">exclusive to the Pro Max</a>. The hypothesis is the mechanics required for a variable lens will only fit in a larger phone, ruling out the smaller Pro. This would undoubtedly be a huge blow for those of us that prefer Apple's smaller phones and could be a big reason why you choose to remain with the iPhone 17 Pro over its successor.</p><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="EHpBdnKc9CNvu4GiNaPbH9" name="iPhone 17 Pro review" alt="iPhone 17 Pro taking a photo." src="https://cdn.mos.cms.futurecdn.net/EHpBdnKc9CNvu4GiNaPbH9.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide / John Velasco)</span></figcaption></figure><p>One more thing to mention is that there have been claims Apple will remove the capacitive capabilities of the Camera Control button for the iPhone 18 Pro. This is due to some users accidentally launching the camera app inadvertently and could be very helpful if you use your iPhone as your main camera.</p><p>Bottom line is that variable aperture on the iPhone 18 Pro could make or break whether or not a lot of people decide to upgrade from the 17 Pro.</p><h2 class="article-body__section" id="section-iphone-17-pro-vs-iphone-18-pro-performance-and-battery"><span>iPhone 17 Pro vs. iPhone 18 Pro: performance and battery</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="2p68W9mHAAZd9qESYGbtvV" name="iPhone 17 Pro Max-22" alt="iPhone 17 Pro Max gaming." src="https://cdn.mos.cms.futurecdn.net/2p68W9mHAAZd9qESYGbtvV.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The iPhone 17 Pro is no slouch, thanks to the A19 Pro chip built on a 3-nanometer process. However, the iPhone 18 Pro is expected to be powered by Apple's next-generation A20 Pro chip, manufactured using TSMC's cutting-edge 2nm process. </p><p>This move to a smaller manufacturing process should allow Apple to significantly improve both raw performance and power efficiency.</p><p>Because of this newfound efficiency — and a slight physical battery increase from the 17 Pro's 4,252 mAh up to roughly 4,288 mAh on the 18 Pro — battery life could take a leap forward. </p><p>You can expect the iPhone 18 Pro to easily outlast its predecessor, when it comes to both longevity and overall performance. As always, anyone who wants the fastest possible speed and the most power will always benefit from upgrading to the newest model.</p><h2 class="article-body__section" id="section-iphone-18-pro-max-vs-iphone-18-pro-software-and-apple-intelligence"><span>iPhone 18 Pro Max vs. iPhone 18 Pro: Software and Apple Intelligence</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:3490px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="qdS9MAp79UU3D85qwZjEV6" name="iOS 27 Siri AI" alt="iOS 27 Siri AI running on iPhone 17 Pro." src="https://cdn.mos.cms.futurecdn.net/qdS9MAp79UU3D85qwZjEV6.jpg" mos="" align="middle" fullscreen="" width="3490" height="1963" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Both the iPhone 17 Pro and the iPhone 18 Pro will have access to Apple's latest software tricks, but this year's model will run <a href="https://www.tomsguide.com/phones/iphones/ios-27-public-beta-hands-on-preview-the-new-siri-and-apple-intelligence-features-completely-changed-how-i-use-my-iphone">iOS 27</a> out of the box. The 17 Pro, meanwhile, launched with <a href="https://www.tomsguide.com/phones/iphones/ios-26-review-new-features-liquid-glass">iOS 26</a> but will be eligible for the update in the coming weeks.</p><p>The real difference lies in hardware integration for Apple Intelligence. With 12GB of RAM on both devices, the AI playing field looks level on paper. However, leaks suggest the A20 Pro mentioned earlier features advanced packaging that integrates RAM more closely with the processor, freeing up bandwidth for lightning-fast on-device AI tasks. </p><p>The 18 Pro will simply handle complex generative prompts and on-the-fly photo editing faster than the 17 Pro.</p><p>We'll have to wait to find out if there are any iPhone 18 Pro-specific software or AI features (perhaps around the variable aperture) but for the most part, the 17 Pro will remain able to use almost all the software features Apple has to offer for at least a few more years yet.</p><h2 class="article-body__section" id="section-iphone-17-pro-vs-iphone-18-pro-final-thoughts"><span>iPhone 17 Pro vs. iPhone 18 Pro: Final thoughts</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:1280px;"><p class="vanilla-image-block" style="padding-top:55.78%;"><img id="WNJZg5wpSg4yem6kzvAjLN" name="iPhone 18 Pro and Max LIST Large" alt="iPhone 18 Pro vs iPhone 18 Pro Max." src="https://cdn.mos.cms.futurecdn.net/WNJZg5wpSg4yem6kzvAjLN.jpg" mos="" align="middle" fullscreen="" width="1280" height="714" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>If you're already rocking an iPhone 17 Pro, I feel it's going to be tough to justify an upgrade based on what's already at your disposal. Apple's 2025 effort has a gorgeous 6.3-inch display, a triple 48MP camera setup, and 12GB of RAM to power Apple Intelligence. It’s an incredibly capable device that still has years of top-tier life left in it.</p><p>That said, if you’re a power user or a serious smartphone photographer, the iPhone 18 Pro’s rumored variable aperture, highly efficient 2nm A20 Pro chip, and significantly larger battery might just be too tempting to pass up. Just keep in mind that the variable aperture and longer zoom could be limited to the iPhone 18 Pro Max.</p><p>We'll find out for sure once new Apple CEO John Ternus takes the stage to make these phones official and reveal what the final prices are going to be. In the meantime, let me know in the comments below whether you think an iPhone 18 Pro upgrade is a must-have or if you're content to hold on to the iPhone 17 Pro for a few more years.</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-ultra-exclusive-gurman-on-price-release-date-and-secret-weapon-versus-android">iPhone Ultra exclusive: Gurman on price, release date rumors and 'day one' weapon against Android</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-upgrades-everything-we-know-about-the-new-sensor">iPhone 18 Pro camera upgrades — everything we know about the new sensor</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-18-pro-max-unboxed-ahead-of-apple-event-these-could-be-the-final-designs">iPhone Ultra and 18 Pro Max unboxed ahead of Apple event — these could be the final designs</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone 18 Pro now tipped for just 3 colors — here's your options ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple will <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">debut the iPhone 18 Pro</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max</a> next week, and a new leak from a regular tipster names three new colors for the new phones. </p><p>On Monday, an <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-18-pro-max-unboxed-ahead-of-apple-event-these-could-be-the-final-designs">unboxing video</a> purported to reveal dummy units of the iPhone 18 Pro Max and the foldable <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a>. That video showed the phone in four colors: a maroon-ish color, black, silver and blue.</p><p>However, today's leak from <a href="https://www.weibo.com/5821279480/Rg4zqqQ05" target="_blank">Weibo user Fixed Focos Digital</a> only highlights three shades. Mostly, FFD seems to confirm previous rumors that the highlight color this year will be dark cherry which replaces last year's bright Cosmic Orange.</p><p><strong>They predict these iPhone 18 Pro colors:</strong></p><ul><li>Dark Cherry/burgundy</li><li>Sky Blue</li><li>Black</li></ul><p>In a follow-up post, they claimed that they had seen no evidence of a silver variant being released this year. Last year, the iPhone 17 Pro was released in three colors: cosmic orange, deep blue and silver. </p><p>If this rumor holds up, Apple is looking to replace the full lineup of shades with all-new options this year. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-X750KW"></div>                            </div>                            <script src="https://kwizly.com/embed/X750KW.js" async></script><p>Outside of black, sky blue isn't a new color. We've seen it before in the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-announced-and-its-a-whole-new-kind-of-iphone">iPhone Air </a>and MacBook Air, which tended to be more subtle and somewhat silvery depending on the lighting. </p><p>Ditching a black or space grey colorway was <a href="https://www.tomsguide.com/phones/iphones/im-buying-a-new-iphone-17-pro-max-but-only-because-its-orange">controversial last year</a>, so bringing it back might be Apple throwing a bone to our more goth-minded neighbors.</p><p>We'll know more about the colors, the new iPhones, and a<a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september"> slew of other potential devices</a> on September 9 when new CEO John Ternus hosts his first major Apple event. It should be an interesting spectacle.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/computing/mobile-apps/mapquest-is-suddenly-no-4-in-the-apple-app-store-heres-why">'We're not changing it': MapQuest hits No. 1 in App Store after refusing to rename Lake Ontario to Lake America</a></li><li><a href="https://www.tomsguide.com/phones/iphones/last-minute-iphone-ultra-report-shoots-down-apple-pencil-but-this-is-how-it-could-have-worked">iPhone Ultra tested with Apple Pencil but not happening at launch — this is how it could work</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-upgrades-everything-we-know-about-the-new-sensor">iPhone 18 Pro camera upgrades — everything we know about the new sensor</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-18-pro-now-just-tipped-for-3-colors-heres-your-options</link>
                                                                            <description>
                            <![CDATA[ A new leak appears to reveal three colors for the iPhone 18 Pro models, and one colors that won't be available. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">K4M92sygj7wtYDqmGH8FkY</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/NUTShzQj5MbSQ7h8SLWLoQ-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 01 Sep 2026 19:08:29 +0000</pubDate>                                                                                                                                <updated>Tue, 01 Sep 2026 19:08:44 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ scott.younker@futurenet.com (Scott Younker) ]]></author>                    <dc:creator><![CDATA[ Scott Younker ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/RZsUpqcJ6Uj2q83oCUwNhQ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Scott Younker is the West Coast Reporter at Tom’s Guide. He covers all the latest tech news, including phones, computing and more. He’s been involved in tech since 2011 covering everything from cameras and swimming pool equipment to the latest gaming consoles and smart TVs. He is on a seemingly never ending hunt to build the easiest to use home media system. &lt;/p&gt;&lt;p&gt;Before Tom’s Guide, Scott worked for publications like &lt;em&gt;Digital Trends, Outdoor Photographer, Dead Beats Panel&lt;/em&gt;, and in a brief detour, &lt;em&gt;America’s Funniest Home Videos&lt;/em&gt;. Yes, he has seen more pratfalls, silly pets and ridiculous home movie fails than is reasonably healthy. &lt;/p&gt;&lt;p&gt;When not writing about the latest devices or advances in chipsets, be sure to ask about Scott about disc golf and sustainability, or just if you’re being cheeky, ask about his noodle arm. If you truly want to get nerdy, bring up board games and his ongoing losing streak. &lt;/p&gt;&lt;p&gt;Scott joined Tom&#039;s Guide in 2024 as the West Coast Reporter. He graduated from the School of Journalism at the University of Oregon with a degree in magazine journalism and a minor in communications. While there he blogged or wrote for several magazines including the Fluxx, Ethos and the Oregon Commentator. He briefly wrote and managed a moderately successful blog focused on web comics. &lt;br&gt;Send secure tips on Signal: scyo1.55.&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/NUTShzQj5MbSQ7h8SLWLoQ-1280-80.jpg">
                                                            <media:credit><![CDATA[Unbox Therapy]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone 18 Pro Max dummy unit in dark cherry]]></media:description>                                                            <media:text><![CDATA[iPhone 18 Pro Max dummy unit in dark cherry]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone 18 Pro Max dummy unit in dark cherry]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/NUTShzQj5MbSQ7h8SLWLoQ-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple will <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">debut the iPhone 18 Pro</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max</a> next week, and a new leak from a regular tipster names three new colors for the new phones. </p><p>On Monday, an <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-and-18-pro-max-unboxed-ahead-of-apple-event-these-could-be-the-final-designs">unboxing video</a> purported to reveal dummy units of the iPhone 18 Pro Max and the foldable <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a>. That video showed the phone in four colors: a maroon-ish color, black, silver and blue.</p><p>However, today's leak from <a href="https://www.weibo.com/5821279480/Rg4zqqQ05" target="_blank">Weibo user Fixed Focos Digital</a> only highlights three shades. Mostly, FFD seems to confirm previous rumors that the highlight color this year will be dark cherry which replaces last year's bright Cosmic Orange.</p><p><strong>They predict these iPhone 18 Pro colors:</strong></p><ul><li>Dark Cherry/burgundy</li><li>Sky Blue</li><li>Black</li></ul><p>In a follow-up post, they claimed that they had seen no evidence of a silver variant being released this year. Last year, the iPhone 17 Pro was released in three colors: cosmic orange, deep blue and silver. </p><p>If this rumor holds up, Apple is looking to replace the full lineup of shades with all-new options this year. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-X750KW"></div>                            </div>                            <script src="https://kwizly.com/embed/X750KW.js" async></script><p>Outside of black, sky blue isn't a new color. We've seen it before in the <a href="https://www.tomsguide.com/phones/iphones/iphone-air-announced-and-its-a-whole-new-kind-of-iphone">iPhone Air </a>and MacBook Air, which tended to be more subtle and somewhat silvery depending on the lighting. </p><p>Ditching a black or space grey colorway was <a href="https://www.tomsguide.com/phones/iphones/im-buying-a-new-iphone-17-pro-max-but-only-because-its-orange">controversial last year</a>, so bringing it back might be Apple throwing a bone to our more goth-minded neighbors.</p><p>We'll know more about the colors, the new iPhones, and a<a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september"> slew of other potential devices</a> on September 9 when new CEO John Ternus hosts his first major Apple event. It should be an interesting spectacle.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/computing/mobile-apps/mapquest-is-suddenly-no-4-in-the-apple-app-store-heres-why">'We're not changing it': MapQuest hits No. 1 in App Store after refusing to rename Lake Ontario to Lake America</a></li><li><a href="https://www.tomsguide.com/phones/iphones/last-minute-iphone-ultra-report-shoots-down-apple-pencil-but-this-is-how-it-could-have-worked">iPhone Ultra tested with Apple Pencil but not happening at launch — this is how it could work</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-upgrades-everything-we-know-about-the-new-sensor">iPhone 18 Pro camera upgrades — everything we know about the new sensor</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ ‘Few people understand what it takes to build products that change the world the way John does’ — Tim Cook signs off as CEO as Ternus takes over ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Today is John Ternus's first day as Apple CEO, taking over from Tim Cook, who led the company for 15 years following the death of co-founder Steve Jobs. Ternus will have his first big test in just over a week, when Apple <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">hosts its "Surprise and shine" event</a> to officially reveal the foldable <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a>.</p><p>Tim Cook's time at the helm of Apple will likely be looked back on as a masterclass in supply chain management, product optimisation and building out Apple's services business. There were some misfires, but over the course of a decade-and-a-half, Cook built Apple into the technological juggernaut it is today.</p><p>As he left office yesterday, Cook penned a heartfelt and emotional memo to all Apple staff. As well as reflecting on his time as leader, he also expressed supreme confidence in John Ternus, the former senior vice president of Hardware Engineering.</p><p>Here is Tim Cook's memo in full:</p><p><em>Team, </em></p><p><em>Today is my last day as CEO of Apple. This is a moment I always knew would come one day, and yet it is still hard to believe it has arrived and I am writing these words. I love this company and the team behind it, and I couldn’t let this day pass without sending a note to you, to tell you how grateful I am for the outpouring of affection you’ve sent my way, for the way you’ve shown up each and every day, and most of all, for the privilege of a lifetime serving as your leader. </em></p><p><em>The truth is, whatever there is to say about my success, I know it is all because of you. You have brought out the best in me. In all my life, I have never seen or been with such an extraordinary team of people before, and every day I get to see more examples of that. </em></p><p><em>There is something truly special about Apple. I am most proud of what an annual report could never capture. This place is proof that culture triumphs over everything. We share a belief that what we build matters, and that we have both the opportunity and the responsibility to leave the world better than we found it. That purpose is part of what makes this place extraordinary. Apple helps nurture it, but I believe it lived within each of you long before you arrived here. It is what brought you to this company and what continues to drive the work you do every day. Together, we have created something far greater than any one of us could have imagined or accomplished alone. And that’s the secret to our success. We bring out the best in each other. We lift each other up. We have made it possible to leave our “dent in the universe,” as Steve once described it, because of who we are and what we believe, because of what we value and how we see the world. How fortunate we are. How fortunate I am. </em></p><p><em>As you know, I am not leaving Apple. But I am stepping away from a role that I have loved deeply. I will miss this work in ways I can only begin to imagine, even as I remain completely at peace with my decision. I will miss leading you and being with you for every step, even as I take enormous comfort in handing the helm to someone as brilliant and wonderful and capable as John. Few people understand what it takes to build products that change the world the way John does and I could not be more excited for his leadership. </em></p><p><em>I hope you know how much I appreciate you and what an honor it has been to be your CEO. Most of all, I hope you will continue to be proud to be part of this remarkable place we call Apple and always give it your very best. When we bring our whole selves to this work, with care for one another and for the people we serve, there is no limit to the profound difference we can make. </em></p><p><em>I look forward to seeing you in my new role at Apple Park and around the world. </em></p><p><em>With all I have and all I am, I am always </em></p><p><em>Yours, </em></p><p><em>Tim </em></p><p>As well as the memo, Cook also posted a tweet yesterday, thanking Apple's global community for the inspiration it gave him.</p><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2094448088199078236"><p lang="en" dir="ltr">Sending lots of love to the Apple community on my last day as CEO. My title changes tomorrow, but the love I have for the Apple community never will. Thank you for being a constant source of inspiration. My gratitude is endless, and I’m excited for the next chapter!<a href="https://twitter.com/cantworkitout/status/2094448088199078236">August 31, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>Ternus, meanwhile, will have the springboard of Apple's "Surprise and shine" event with which to launch himself into the role. But it won't be without challenges. Apple has a lot of catching up to do in the AI race and, earlier this year, the company was forced to raise prices across most of its products due to the memory crisis buffeting the tech industry.</p><p>Days before he was named the new CEO of Apple, <a href="https://www.tomsguide.com/computing/macbooks/i-interviewed-john-ternus-right-before-he-was-named-apple-ceo-heres-the-5-quotes-that-stand-out-to-me">Tom's Guide had the chance to speak with Ternus</a> about the company's next chapter. Check it out below and let me know in the comments how successful you think Ternus will be as Apple CEO. Will he measure up to Tim Cook? I'd love to know your thoughts. </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/kkBudtxgor0" allowfullscreen></iframe></div></div><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ODm77X"></div>                            </div>                            <script src="https://kwizly.com/embed/ODm77X.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-12-and-ultra-4-rumors-your-next-apple-watch-could-have-a-ceramic-case">Apple Watch 12 and Ultra 4 rumors: Your next Apple Watch could have a ceramic case</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-upgrades-everything-we-know-about-the-new-sensor">iPhone 18 Pro camera upgrades — everything we know about the new sensor</a></li><li><a href="https://www.tomsguide.com/computing/mobile-apps/mapquest-is-suddenly-no-4-in-the-apple-app-store-heres-why">MapQuest is suddenly No. 4 in the Apple App Store — here's why</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/read-tim-cooks-emotional-memo-to-apple-staff-in-full-as-john-ternus-takes-over-as-ceo</link>
                                                                            <description>
                            <![CDATA[ Tim Cook reflected on his time as Apple's CEO with a heartfelt memo to the company staff as his successor takes over. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">qRTbkDQEZEjkPCkgaZ7Bce</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/XK7W9gHWEgHPdh5kir8n9-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 01 Sep 2026 10:35:15 +0000</pubDate>                                                                                                                                <updated>Tue, 01 Sep 2026 11:46:05 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ jeff.parsons@futurenet.com (Jeff Parsons) ]]></author>                    <dc:creator><![CDATA[ Jeff Parsons ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/7z3UTGGrmSokMKxTWHmhjX.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Jeff is U.K. Editor-in-Chief for Tom’s Guide looking after the day-to-day output of the site’s British contingent. &lt;/p&gt;&lt;p&gt;Rising early and heading straight for the coffee machine, Jeff loves nothing more than dialling into the zeitgeist of the day’s tech news. A journalist for over a decade, he&#039;s travelled around the world testing and reviewing any gadget he can get his hands on.&lt;/p&gt;&lt;p&gt;Before joining the team at Tom’s Guide, Jeff covered technology and science for two of the U.K.’s biggest national news sites: Metro.co.uk and the Daily Mirror. Memorable moments include getting lost in Vienna in an electric Audi, touring Lockheed Martin’s mile-long jet factory in Fort Worth and filming a Netflix documentary about Elon Musk in West London.&lt;/p&gt;&lt;p&gt;When not plugged into the current news agenda, editing or commissioning a series of articles or debating the merits of Apple vs Android, Jeff can usually be found out for a run trying to shave precious seconds off his PB. Or lifting weights in a vain attempt to offset the ageing process.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/XK7W9gHWEgHPdh5kir8n9-1280-80.jpg">
                                                            <media:credit><![CDATA[Apple]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[John Ternus and Tim Cook]]></media:description>                                                            <media:text><![CDATA[John Ternus and Tim Cook]]></media:text>
                                <media:title type="plain"><![CDATA[John Ternus and Tim Cook]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/XK7W9gHWEgHPdh5kir8n9-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Today is John Ternus's first day as Apple CEO, taking over from Tim Cook, who led the company for 15 years following the death of co-founder Steve Jobs. Ternus will have his first big test in just over a week, when Apple <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">hosts its "Surprise and shine" event</a> to officially reveal the foldable <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a>.</p><p>Tim Cook's time at the helm of Apple will likely be looked back on as a masterclass in supply chain management, product optimisation and building out Apple's services business. There were some misfires, but over the course of a decade-and-a-half, Cook built Apple into the technological juggernaut it is today.</p><p>As he left office yesterday, Cook penned a heartfelt and emotional memo to all Apple staff. As well as reflecting on his time as leader, he also expressed supreme confidence in John Ternus, the former senior vice president of Hardware Engineering.</p><p>Here is Tim Cook's memo in full:</p><p><em>Team, </em></p><p><em>Today is my last day as CEO of Apple. This is a moment I always knew would come one day, and yet it is still hard to believe it has arrived and I am writing these words. I love this company and the team behind it, and I couldn’t let this day pass without sending a note to you, to tell you how grateful I am for the outpouring of affection you’ve sent my way, for the way you’ve shown up each and every day, and most of all, for the privilege of a lifetime serving as your leader. </em></p><p><em>The truth is, whatever there is to say about my success, I know it is all because of you. You have brought out the best in me. In all my life, I have never seen or been with such an extraordinary team of people before, and every day I get to see more examples of that. </em></p><p><em>There is something truly special about Apple. I am most proud of what an annual report could never capture. This place is proof that culture triumphs over everything. We share a belief that what we build matters, and that we have both the opportunity and the responsibility to leave the world better than we found it. That purpose is part of what makes this place extraordinary. Apple helps nurture it, but I believe it lived within each of you long before you arrived here. It is what brought you to this company and what continues to drive the work you do every day. Together, we have created something far greater than any one of us could have imagined or accomplished alone. And that’s the secret to our success. We bring out the best in each other. We lift each other up. We have made it possible to leave our “dent in the universe,” as Steve once described it, because of who we are and what we believe, because of what we value and how we see the world. How fortunate we are. How fortunate I am. </em></p><p><em>As you know, I am not leaving Apple. But I am stepping away from a role that I have loved deeply. I will miss this work in ways I can only begin to imagine, even as I remain completely at peace with my decision. I will miss leading you and being with you for every step, even as I take enormous comfort in handing the helm to someone as brilliant and wonderful and capable as John. Few people understand what it takes to build products that change the world the way John does and I could not be more excited for his leadership. </em></p><p><em>I hope you know how much I appreciate you and what an honor it has been to be your CEO. Most of all, I hope you will continue to be proud to be part of this remarkable place we call Apple and always give it your very best. When we bring our whole selves to this work, with care for one another and for the people we serve, there is no limit to the profound difference we can make. </em></p><p><em>I look forward to seeing you in my new role at Apple Park and around the world. </em></p><p><em>With all I have and all I am, I am always </em></p><p><em>Yours, </em></p><p><em>Tim </em></p><p>As well as the memo, Cook also posted a tweet yesterday, thanking Apple's global community for the inspiration it gave him.</p><div class="see-more see-more--clipped"><figure><blockquote class="twitter-tweet hawk-ignore" data-lang="en" cite="https://twitter.com/cantworkitout/status/2094448088199078236"><p lang="en" dir="ltr">Sending lots of love to the Apple community on my last day as CEO. My title changes tomorrow, but the love I have for the Apple community never will. Thank you for being a constant source of inspiration. My gratitude is endless, and I’m excited for the next chapter!<a href="https://twitter.com/cantworkitout/status/2094448088199078236">August 31, 2026</a></p></blockquote></figure><div class="see-more__filter"></div></div><p>Ternus, meanwhile, will have the springboard of Apple's "Surprise and shine" event with which to launch himself into the role. But it won't be without challenges. Apple has a lot of catching up to do in the AI race and, earlier this year, the company was forced to raise prices across most of its products due to the memory crisis buffeting the tech industry.</p><p>Days before he was named the new CEO of Apple, <a href="https://www.tomsguide.com/computing/macbooks/i-interviewed-john-ternus-right-before-he-was-named-apple-ceo-heres-the-5-quotes-that-stand-out-to-me">Tom's Guide had the chance to speak with Ternus</a> about the company's next chapter. Check it out below and let me know in the comments how successful you think Ternus will be as Apple CEO. Will he measure up to Tim Cook? I'd love to know your thoughts. </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/kkBudtxgor0" allowfullscreen></iframe></div></div><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-ODm77X"></div>                            </div>                            <script src="https://kwizly.com/embed/ODm77X.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-12-and-ultra-4-rumors-your-next-apple-watch-could-have-a-ceramic-case">Apple Watch 12 and Ultra 4 rumors: Your next Apple Watch could have a ceramic case</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-upgrades-everything-we-know-about-the-new-sensor">iPhone 18 Pro camera upgrades — everything we know about the new sensor</a></li><li><a href="https://www.tomsguide.com/computing/mobile-apps/mapquest-is-suddenly-no-4-in-the-apple-app-store-heres-why">MapQuest is suddenly No. 4 in the Apple App Store — here's why</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone 18 Pro camera upgrades — everything we know about the new sensor ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Apple has officially confirmed that its annual iPhone event will kick off on September 9 under the tagline "<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 Sunshine</a>." </p><p>The much-rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra </a>will steal all the headlines, but we're also expecting to see the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro </a>and Pro Max models as well — the base iPhone 18 and iPhone 18 Plus are reportedly making their <a href="https://www.tomsguide.com/phones/iphone-18-release-just-tipped-for-major-shakeup-heres-when-all-the-new-models-could-launch">debut in spring of 2027</a> alongside the iPhone 18e.</p><p>The iPhone 18 series may be a small upgrade over the iPhone 17 lineup, but we are expecting some updates, including to the cameras. Here's what we expect to see:</p><h2 id="iphone-18-pro-cameras">iPhone 18 Pro cameras</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="XeBMoitt9imyHJpoGeKYzA" name="iPhone 16 Pro Max Camera Control button" alt="Closeup of iPhone 16 Pro Max Camera Control button." src="https://cdn.mos.cms.futurecdn.net/XeBMoitt9imyHJpoGeKYzA.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>From every report we've read so far, the iPhone 18 Pro should feature the same triple 48MP camera setup as the current Pro models. Those three cameras will cover the main, ultrawide, and 4x telephoto lenses. </p><p>Plus, there should be an 18MP Center Stage front camera, the same as the iPhone 17 Pro. </p><p>One big change is a <a href="https://www.tomsguide.com/phones/the-rumors-might-be-wrong-iphone-18s-camera-control-could-evolve-not-end">Camera Control adjustment. </a>Since being introduced with the iPhone 16 Pro, the Camera Control button has proven controversial. There is no shortage of <a href="https://www.reddit.com/r/iphone/comments/1psdcn1/what_do_you_guys_think_of_the_camera_control/" target="_blank">Reddit threads</a> filled with <a href="https://www.reddit.com/r/iphone/comments/1guvdu8/2_months_laterthe_camera_control_button_is_still/" target="_blank">both praise</a> and <a href="https://www.reddit.com/r/iPhone16Pro/comments/1o227ir/i_hate_the_camera_control_button/" target="_blank">criticism of the new button</a>.  </p><p>However, rumors suggest that Apple is refining it for the 18 Pro by removing its capacitive capabilities but retaining its ability to change settings.</p><p>But there is one feature the iPhone 18 Pro might not get.</p><h2 id="only-for-the-iphone-18-pro-max">Only for the iPhone 18 Pro Max</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:800px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oKvNH64TKmxa9BBeNd67Wd" name="Xiaomi 14 Ultra variable aperture gif animation 4.GIF" alt="Xiaomi 14 Ultra variable aperture gif animation." src="https://cdn.mos.cms.futurecdn.net/oKvNH64TKmxa9BBeNd67Wd.gif" mos="" align="middle" fullscreen="" width="800" height="450" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Xiaomi)</span></figcaption></figure><p>The cameras on the Pro Max version of the iPhone 18 could enjoy at least two advantages over the standard Pro models: a longer zoom and a variable-aperture camera. </p><p>Rumors hint at a <a href="https://www.tomsguide.com/phones/iphones/3-big-reasons-to-buy-iphone-18-pro-max-over-the-iphone-18-pro-this-year">6x optical zoom for the iPhone 18 Pro Max</a>, while the Pro model would only feature a 5x zoom.</p><p>The bigger change is the rumor that <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-be-the-first-iphone-to-get-a-variable-aperture-why-that-matters">Apple is going to add a variable aperture camera</a> to at least one model this year. This would give you more manual control over the size of the aperture. What that means in practice is that you get better control over the depth of field in your shots, so you should get sharper close-ups and better performance in low-light situations.</p><p>However, it's not clear if this will come to both Pro models or just the Max. Some rumor mongers have posited that it will be<a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-camera-may-get-this-major-upgrade-but-why-isnt-iphone-18-pro-getting-it-too"> locked to the Pro Max</a>. The speculation is that the thinner iPhone 18 Pro won't be able to fit the mechanics required for a variable lens. </p><p>We'll find out in less than a fortnight. In the meantime, keep Tom's Guide in your tabs, and we'll keep you updated with all the latest Apple news and rumors.</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-ultra-and-18-pro-max-unboxed-ahead-of-apple-event-these-could-be-the-final-designs">iPhone Ultra and 18 Pro Max unboxed ahead of Apple event — these could be the final designs</a></li><li><a href="https://www.tomsguide.com/phones/iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-heres-how-apples-and-samsungs-flagships-could-compare">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra — Here's how Apple's and Samsung's flagships could compare</a></li><li><a href="https://www.tomsguide.com/phones/iphones/last-minute-iphone-ultra-report-shoots-down-apple-pencil-but-this-is-how-it-could-have-worked">iPhone Ultra tested with Apple Pencil but not happening at launch — this is how it could work</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-18-pro-camera-upgrades-everything-we-know-about-the-new-sensor</link>
                                                                            <description>
                            <![CDATA[ Here's everything we're expecting for the new iPhone 18 Pro camera. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">695BGLutfreudGq7epEFCM</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/bc3v2xma2LGpb9mYSNpejc-1280-80.png" type="image/png" length="0"></enclosure>
                                                                        <pubDate>Tue, 01 Sep 2026 04:30:00 +0000</pubDate>                                                                                                                                <updated>Tue, 01 Sep 2026 08:27:48 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ scott.younker@futurenet.com (Scott Younker) ]]></author>                    <dc:creator><![CDATA[ Scott Younker ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/RZsUpqcJ6Uj2q83oCUwNhQ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Scott Younker is the West Coast Reporter at Tom’s Guide. He covers all the latest tech news, including phones, computing and more. He’s been involved in tech since 2011 covering everything from cameras and swimming pool equipment to the latest gaming consoles and smart TVs. He is on a seemingly never ending hunt to build the easiest to use home media system. &lt;/p&gt;&lt;p&gt;Before Tom’s Guide, Scott worked for publications like &lt;em&gt;Digital Trends, Outdoor Photographer, Dead Beats Panel&lt;/em&gt;, and in a brief detour, &lt;em&gt;America’s Funniest Home Videos&lt;/em&gt;. Yes, he has seen more pratfalls, silly pets and ridiculous home movie fails than is reasonably healthy. &lt;/p&gt;&lt;p&gt;When not writing about the latest devices or advances in chipsets, be sure to ask about Scott about disc golf and sustainability, or just if you’re being cheeky, ask about his noodle arm. If you truly want to get nerdy, bring up board games and his ongoing losing streak. &lt;/p&gt;&lt;p&gt;Scott joined Tom&#039;s Guide in 2024 as the West Coast Reporter. He graduated from the School of Journalism at the University of Oregon with a degree in magazine journalism and a minor in communications. While there he blogged or wrote for several magazines including the Fluxx, Ethos and the Oregon Commentator. He briefly wrote and managed a moderately successful blog focused on web comics. &lt;br&gt;Send secure tips on Signal: scyo1.55.&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/bc3v2xma2LGpb9mYSNpejc-1280-80.png">
                                                            <media:credit><![CDATA[Macworld]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iphone 18 pro in dark cherry color from macworld]]></media:description>                                                            <media:text><![CDATA[iphone 18 pro in dark cherry color from macworld]]></media:text>
                                <media:title type="plain"><![CDATA[iphone 18 pro in dark cherry color from macworld]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/bc3v2xma2LGpb9mYSNpejc-1280-80.png" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Apple has officially confirmed that its annual iPhone event will kick off on September 9 under the tagline "<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 Sunshine</a>." </p><p>The much-rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra </a>will steal all the headlines, but we're also expecting to see the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-rumors-everything-we-know-so-far">iPhone 18 Pro </a>and Pro Max models as well — the base iPhone 18 and iPhone 18 Plus are reportedly making their <a href="https://www.tomsguide.com/phones/iphone-18-release-just-tipped-for-major-shakeup-heres-when-all-the-new-models-could-launch">debut in spring of 2027</a> alongside the iPhone 18e.</p><p>The iPhone 18 series may be a small upgrade over the iPhone 17 lineup, but we are expecting some updates, including to the cameras. Here's what we expect to see:</p><h2 id="iphone-18-pro-cameras">iPhone 18 Pro cameras</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="XeBMoitt9imyHJpoGeKYzA" name="iPhone 16 Pro Max Camera Control button" alt="Closeup of iPhone 16 Pro Max Camera Control button." src="https://cdn.mos.cms.futurecdn.net/XeBMoitt9imyHJpoGeKYzA.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>From every report we've read so far, the iPhone 18 Pro should feature the same triple 48MP camera setup as the current Pro models. Those three cameras will cover the main, ultrawide, and 4x telephoto lenses. </p><p>Plus, there should be an 18MP Center Stage front camera, the same as the iPhone 17 Pro. </p><p>One big change is a <a href="https://www.tomsguide.com/phones/the-rumors-might-be-wrong-iphone-18s-camera-control-could-evolve-not-end">Camera Control adjustment. </a>Since being introduced with the iPhone 16 Pro, the Camera Control button has proven controversial. There is no shortage of <a href="https://www.reddit.com/r/iphone/comments/1psdcn1/what_do_you_guys_think_of_the_camera_control/" target="_blank">Reddit threads</a> filled with <a href="https://www.reddit.com/r/iphone/comments/1guvdu8/2_months_laterthe_camera_control_button_is_still/" target="_blank">both praise</a> and <a href="https://www.reddit.com/r/iPhone16Pro/comments/1o227ir/i_hate_the_camera_control_button/" target="_blank">criticism of the new button</a>.  </p><p>However, rumors suggest that Apple is refining it for the 18 Pro by removing its capacitive capabilities but retaining its ability to change settings.</p><p>But there is one feature the iPhone 18 Pro might not get.</p><h2 id="only-for-the-iphone-18-pro-max">Only for the iPhone 18 Pro Max</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:800px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oKvNH64TKmxa9BBeNd67Wd" name="Xiaomi 14 Ultra variable aperture gif animation 4.GIF" alt="Xiaomi 14 Ultra variable aperture gif animation." src="https://cdn.mos.cms.futurecdn.net/oKvNH64TKmxa9BBeNd67Wd.gif" mos="" align="middle" fullscreen="" width="800" height="450" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Xiaomi)</span></figcaption></figure><p>The cameras on the Pro Max version of the iPhone 18 could enjoy at least two advantages over the standard Pro models: a longer zoom and a variable-aperture camera. </p><p>Rumors hint at a <a href="https://www.tomsguide.com/phones/iphones/3-big-reasons-to-buy-iphone-18-pro-max-over-the-iphone-18-pro-this-year">6x optical zoom for the iPhone 18 Pro Max</a>, while the Pro model would only feature a 5x zoom.</p><p>The bigger change is the rumor that <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-be-the-first-iphone-to-get-a-variable-aperture-why-that-matters">Apple is going to add a variable aperture camera</a> to at least one model this year. This would give you more manual control over the size of the aperture. What that means in practice is that you get better control over the depth of field in your shots, so you should get sharper close-ups and better performance in low-light situations.</p><p>However, it's not clear if this will come to both Pro models or just the Max. Some rumor mongers have posited that it will be<a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-camera-may-get-this-major-upgrade-but-why-isnt-iphone-18-pro-getting-it-too"> locked to the Pro Max</a>. The speculation is that the thinner iPhone 18 Pro won't be able to fit the mechanics required for a variable lens. </p><p>We'll find out in less than a fortnight. In the meantime, keep Tom's Guide in your tabs, and we'll keep you updated with all the latest Apple news and rumors.</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-ultra-and-18-pro-max-unboxed-ahead-of-apple-event-these-could-be-the-final-designs">iPhone Ultra and 18 Pro Max unboxed ahead of Apple event — these could be the final designs</a></li><li><a href="https://www.tomsguide.com/phones/iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-heres-how-apples-and-samsungs-flagships-could-compare">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra — Here's how Apple's and Samsung's flagships could compare</a></li><li><a href="https://www.tomsguide.com/phones/iphones/last-minute-iphone-ultra-report-shoots-down-apple-pencil-but-this-is-how-it-could-have-worked">iPhone Ultra tested with Apple Pencil but not happening at launch — this is how it could work</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone Ultra and 18 Pro Max unboxed ahead of Apple event — these could be the final designs ]]></title>
                                                                                                <dc:content><![CDATA[ <p>A new video popped up this week that purports to show off potential final designs for the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max</a> and foldable<a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone"> iPhone Ultra</a> just nine days before<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"> Apple's "Surprise and Shine" event</a>.</p><p>The video comes from the tech-focused <a href="https://www.youtube.com/watch?v=LyxJWtoyK0o" target="_blank">Unbox Therapy</a>, a YouTube channel that features unboxing and first looks at both official new products and leaked designs and dummy units.</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/LyxJWtoyK0o" allowfullscreen></iframe></div></div><p>In the video, host Lewis Hilsenteger shows off the high-end Pro Max and the much-rumored foldable iPhone. He also shows off previous dummy units, which include an all-aluminum version and one with faux displays for the Ultra. </p><p>Allegedly, the devices he received came from China. </p><p>Compared to the previous units Hilsenteger has, the Ultra is more "finished" with an Apple logo, buttons, speakers, and usable buttons.  The device doesn't actually turn on, and the folding screen has pronounced creases despite leaks claiming that <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-achieves-a-visually-crease-free-state-according-to-leaker-but-fears-over-the-hinge-could-lead-to-delays">Apple has largely eliminated the crease</a>.</p><p>Otherwise, we can see the passport style, à la the <a href="https://www.tomsguide.com/phones/samsung-phones/ive-been-living-with-the-galaxy-z-fold-8-for-3-weeks-and-i-was-wrong">Galaxy Z Fold 8</a>, a two-lens camera array, and a mix of rounded and sharp corners.</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/rQHEN3kngZo" allowfullscreen></iframe></div></div><h2 id="iphone-18-pro-max-revealed">iPhone 18 Pro Max revealed</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2490px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="Gv7fyY2QJ4jPcPsj7so3fX" name="iPhone 18 Pro Max Macworld" alt="iPhone 18 Pro Max render" src="https://cdn.mos.cms.futurecdn.net/Gv7fyY2QJ4jPcPsj7so3fX.jpg" mos="" align="middle" fullscreen="" width="2490" height="1401" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Macworld/Tom's Guide)</span></figcaption></figure><p>Hilsenteger followed the Ultra with a look at the iPhone 18 Pro Max. The first one he pulled out is in a dark cherry color, which should be the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-leaked-colors-include-a-stunning-new-dark-cherry-option">highlight color this year</a>. He also pulled out a metallic blue hue, as well as a silver and a black version.</p><p>As expected, the 18 series shouldn't be much different design-wise from the iPhone 17 lineup. It's got the same edge-to-edge camera plateau with multiple lenses and the LED light on the right side. </p><p>Similar to the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review">Galaxy S26 Ultra</a> compared to Samsung's foldable, the Pro Max is significantly taller than the folded iPhone Ultra. </p><p>As noted by Hilsenteger, these devices appear to be close to finalized, but he hints that he might get more dummy units ahead of the Apple event that could be even more finalized. So slight changes could happen between these revealed units and the final final design.</p><h2 id="apple-39-s-september-event">Apple's September event</h2><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="WT2eQLr2FVCsKPrzoX8QZ3" name="Apple-Surprise-and-shine-LEDE" alt="Apple Surprise and Shine announcement" src="https://cdn.mos.cms.futurecdn.net/WT2eQLr2FVCsKPrzoX8QZ3.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: Apple)</span></figcaption></figure><p>Apple has <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">officially announced</a> that its next big event will take place on September 9 at 10 a.m. PT/1:00 p.m. ET. This will be the first event hosted by new CEO John Ternus, as former head <a href="https://x.com/tim_cook/status/2094448088199078236" target="_blank">Tim Cook stepped down</a> on August 31.</p><p>Alongside the iPhones, we expect <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">Apple to announce at least eight new products,</a> including new AirPods, the next-generation Apple Watches, and potentially several new Apple smart home devices.</p><p>We also expect an upgraded Siri and AI integration to be a major part of every device discussed next week, since Apple announced <a href="https://www.tomsguide.com/phones/iphones/ive-been-testing-siri-ai-in-ios-27-for-3-weeks-7-things-to-try-first-and-the-feature-that-won-me-over">Siri AI</a> at <a href="https://www.tomsguide.com/news/live/wwdc-2026-live-news-updates">WWDC 2026</a> back in June.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li>Article</li><li>Article</li><li>Article</li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-ultra-and-18-pro-max-unboxed-ahead-of-apple-event-these-could-be-the-final-designs</link>
                                                                            <description>
                            <![CDATA[ A new video appears to reveal final designs for both the iPhone 18 Pro Max and iPhone Ultra thanks to an unboxing. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">cC7ED7HJjD8Zz32pYuvvCo</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/zzWJVAdVMiSAiHb5rnQrPZ-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 31 Aug 2026 20:24:46 +0000</pubDate>                                                                                                                                <updated>Tue, 01 Sep 2026 15:29:55 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ scott.younker@futurenet.com (Scott Younker) ]]></author>                    <dc:creator><![CDATA[ Scott Younker ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/RZsUpqcJ6Uj2q83oCUwNhQ.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Scott Younker is the West Coast Reporter at Tom’s Guide. He covers all the latest tech news, including phones, computing and more. He’s been involved in tech since 2011 covering everything from cameras and swimming pool equipment to the latest gaming consoles and smart TVs. He is on a seemingly never ending hunt to build the easiest to use home media system. &lt;/p&gt;&lt;p&gt;Before Tom’s Guide, Scott worked for publications like &lt;em&gt;Digital Trends, Outdoor Photographer, Dead Beats Panel&lt;/em&gt;, and in a brief detour, &lt;em&gt;America’s Funniest Home Videos&lt;/em&gt;. Yes, he has seen more pratfalls, silly pets and ridiculous home movie fails than is reasonably healthy. &lt;/p&gt;&lt;p&gt;When not writing about the latest devices or advances in chipsets, be sure to ask about Scott about disc golf and sustainability, or just if you’re being cheeky, ask about his noodle arm. If you truly want to get nerdy, bring up board games and his ongoing losing streak. &lt;/p&gt;&lt;p&gt;Scott joined Tom&#039;s Guide in 2024 as the West Coast Reporter. He graduated from the School of Journalism at the University of Oregon with a degree in magazine journalism and a minor in communications. While there he blogged or wrote for several magazines including the Fluxx, Ethos and the Oregon Commentator. He briefly wrote and managed a moderately successful blog focused on web comics. &lt;br&gt;Send secure tips on Signal: scyo1.55.&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/zzWJVAdVMiSAiHb5rnQrPZ-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Ultra and iPhone 18 Pro Max]]></media:description>                                                            <media:text><![CDATA[iPhone Ultra and iPhone 18 Pro Max]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Ultra and iPhone 18 Pro Max]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/zzWJVAdVMiSAiHb5rnQrPZ-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>A new video popped up this week that purports to show off potential final designs for the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max</a> and foldable<a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone"> iPhone Ultra</a> just nine days before<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"> Apple's "Surprise and Shine" event</a>.</p><p>The video comes from the tech-focused <a href="https://www.youtube.com/watch?v=LyxJWtoyK0o" target="_blank">Unbox Therapy</a>, a YouTube channel that features unboxing and first looks at both official new products and leaked designs and dummy units.</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/LyxJWtoyK0o" allowfullscreen></iframe></div></div><p>In the video, host Lewis Hilsenteger shows off the high-end Pro Max and the much-rumored foldable iPhone. He also shows off previous dummy units, which include an all-aluminum version and one with faux displays for the Ultra. </p><p>Allegedly, the devices he received came from China. </p><p>Compared to the previous units Hilsenteger has, the Ultra is more "finished" with an Apple logo, buttons, speakers, and usable buttons.  The device doesn't actually turn on, and the folding screen has pronounced creases despite leaks claiming that <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-achieves-a-visually-crease-free-state-according-to-leaker-but-fears-over-the-hinge-could-lead-to-delays">Apple has largely eliminated the crease</a>.</p><p>Otherwise, we can see the passport style, à la the <a href="https://www.tomsguide.com/phones/samsung-phones/ive-been-living-with-the-galaxy-z-fold-8-for-3-weeks-and-i-was-wrong">Galaxy Z Fold 8</a>, a two-lens camera array, and a mix of rounded and sharp corners.</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/rQHEN3kngZo" allowfullscreen></iframe></div></div><h2 id="iphone-18-pro-max-revealed">iPhone 18 Pro Max revealed</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2490px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="Gv7fyY2QJ4jPcPsj7so3fX" name="iPhone 18 Pro Max Macworld" alt="iPhone 18 Pro Max render" src="https://cdn.mos.cms.futurecdn.net/Gv7fyY2QJ4jPcPsj7so3fX.jpg" mos="" align="middle" fullscreen="" width="2490" height="1401" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Macworld/Tom's Guide)</span></figcaption></figure><p>Hilsenteger followed the Ultra with a look at the iPhone 18 Pro Max. The first one he pulled out is in a dark cherry color, which should be the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-leaked-colors-include-a-stunning-new-dark-cherry-option">highlight color this year</a>. He also pulled out a metallic blue hue, as well as a silver and a black version.</p><p>As expected, the 18 series shouldn't be much different design-wise from the iPhone 17 lineup. It's got the same edge-to-edge camera plateau with multiple lenses and the LED light on the right side. </p><p>Similar to the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review">Galaxy S26 Ultra</a> compared to Samsung's foldable, the Pro Max is significantly taller than the folded iPhone Ultra. </p><p>As noted by Hilsenteger, these devices appear to be close to finalized, but he hints that he might get more dummy units ahead of the Apple event that could be even more finalized. So slight changes could happen between these revealed units and the final final design.</p><h2 id="apple-39-s-september-event">Apple's September event</h2><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="WT2eQLr2FVCsKPrzoX8QZ3" name="Apple-Surprise-and-shine-LEDE" alt="Apple Surprise and Shine announcement" src="https://cdn.mos.cms.futurecdn.net/WT2eQLr2FVCsKPrzoX8QZ3.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: Apple)</span></figcaption></figure><p>Apple has <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">officially announced</a> that its next big event will take place on September 9 at 10 a.m. PT/1:00 p.m. ET. This will be the first event hosted by new CEO John Ternus, as former head <a href="https://x.com/tim_cook/status/2094448088199078236" target="_blank">Tim Cook stepped down</a> on August 31.</p><p>Alongside the iPhones, we expect <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">Apple to announce at least eight new products,</a> including new AirPods, the next-generation Apple Watches, and potentially several new Apple smart home devices.</p><p>We also expect an upgraded Siri and AI integration to be a major part of every device discussed next week, since Apple announced <a href="https://www.tomsguide.com/phones/iphones/ive-been-testing-siri-ai-in-ios-27-for-3-weeks-7-things-to-try-first-and-the-feature-that-won-me-over">Siri AI</a> at <a href="https://www.tomsguide.com/news/live/wwdc-2026-live-news-updates">WWDC 2026</a> back in June.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li>Article</li><li>Article</li><li>Article</li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I've tested every major foldable phone this year, and the iPhone Ultra can beat them all with this one killer feature ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I’ve spent the last few months testing some of the <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phones</a> ever made. From Motorola’s impressive first stab at a notebook-style design in the <a href="https://www.tomsguide.com/phones/motorola-phones/motorola-razr-fold-review">Razr Fold</a> to the thin and light construction of the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> and the <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold’s</a> focus on content creation, they prove just how much innovation and competition exist in the space.</p><p>Yet, despite all their efforts, I always run into the same frustrating wall with these Android-powered devices. I genuinely believe that Apple’s long-rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> has a golden opportunity to instantly sweep the competition — and it won’t need to rely on a triple-lens camera setup or an <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-creaseless-display-could-make-it-a-day-1-purchase-theres-just-one-problem">entirely creaseless display</a> to do it.</p><p>The killer feature that could crown Apple the undisputed leader of the segment is the exact software hurdle Google and Android manufacturers still haven't cleared: seamless app scaling and truly dynamic layouts. Here’s the proof.</p><h2 id="age-of-origins-stretched-out-look">Age of Origins — stretched out look</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="HhYz53Jt5KvTSxcbz8osfF" name="iPhone Fold - fix foldable app layouts" alt="foldable app layouts." src="https://cdn.mos.cms.futurecdn.net/HhYz53Jt5KvTSxcbz8osfF.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" 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 be fair, most core native apps are well-optimized for both the inner and outer displays of the foldable phones I’ve tested. Apps like Gmail, Google Calendar, and YouTube dynamically adapt their layouts and scale seamlessly between screens.</p><p>However, third-party games tell a completely different story. In <a href="https://play.google.com/store/apps/details?id=com.camelgames.aoz&hl=en_US" target="_blank" rel="nofollow">Age of Origins</a>, you can see how poorly the interface scales when transitioning between the displays. The result is an aggressively distorted, stretched-out layout that makes playing nearly impossible — and the only way to fix it is by force-closing and restarting the game entirely.</p><h2 id="tiktok-black-bars-and-a-crop">TikTok — black bars and a crop</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="BYqhjZuLfUu3uKhrktQTcF" name="iPhone Fold - fix foldable app layouts" alt="foldable app layouts." src="https://cdn.mos.cms.futurecdn.net/BYqhjZuLfUu3uKhrktQTcF.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>TikTok is one of the most popular apps around, but my patience is always tested whenever I run it on a foldable. As shown above, the app loads nicely when launched on the outer screen, maintaining the familiar vertical layout of any standard slate phone. But when I unfold the device to view it on the main display, it aggressively adds the video with thick black bars on the left and right — wasting a massive amount of prime screen real estate.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="ZzRxwckLBxWeGwKszH6tcF" name="iPhone Fold - fix foldable app layouts" alt="foldable app layouts." src="https://cdn.mos.cms.futurecdn.net/ZzRxwckLBxWeGwKszH6tcF.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" 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 I take the opposite approach and launch TikTok directly on the main display, the app forces a zoom-crop to fill the entire square aspect ratio. While that eliminates the dead space, it severely cuts off the top and bottom of the video, often hiding essential visual details and on-screen text. Either way, you are left with a compromised experience.</p><h2 id="castlevania-symphony-of-the-night-even-more-retro">Castlevania Symphony of the Night — even more retro</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="hvyXUb63eaZfio82K4TxbF" name="iPhone Fold - fix foldable app layouts" alt="foldable app layouts." src="https://cdn.mos.cms.futurecdn.net/hvyXUb63eaZfio82K4TxbF.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Lately, I’ve been enjoying some retro gaming thanks to a new <a href="https://www.tomsguide.com/phones/iphones/i-tried-this-magsafe-game-controller-and-it-puts-other-bluetooth-gamepads-to-shame-plus-its-usd20-off-right-now">MagSafe gaming pad</a> I’ve been using — and the current title I’m pursuing is <a href="https://play.google.com/store/apps/details?id=jp.konami.epjCastlevania2&hl=en_US" target="_blank" rel="nofollow">Castlevania Symphony of the Night</a>. </p><p>When I unfold the phone, the game doesn't dynamically expand or scale its rendered canvas to take advantage of the extra real estate. Instead, I get massive black bars flanking the gameplay window, with touch controls floating awkwardly across the letterboxed borders.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="XcjUE5A8uJrsgtaDXVFsbF" name="iPhone Fold - fix foldable app layouts" alt="foldable app layouts." src="https://cdn.mos.cms.futurecdn.net/XcjUE5A8uJrsgtaDXVFsbF.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" 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 worse, switching between the outer and inner displays can trigger an aggressive shrink-to-fit behavior, leaving the active game screen stranded in the center surrounded by dead black space on all four sides. For an experience meant to feel expansive, poor aspect ratio scaling makes it feel more cramped than playing on a standard phone.</p><h2 id="apple-s-chance-to-shine">Apple’s chance to shine</h2><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="cLJg47oNbZQTPJwitNVmte" name="iPhone Ultra half open Apple Track 1" alt="iPhone Ultra half folded in hand" src="https://cdn.mos.cms.futurecdn.net/cLJg47oNbZQTPJwitNVmte.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: Apple Track)</span></figcaption></figure><p>This is where Apple can completely alter the foldable landscape. While Android makers have spent years refining hardware hinges and striving for ultra-thin designs, they’ve consistently struggled to get third-party developers to treat foldable aspect ratios as a priority. Apple, by contrast, enforces stringent guidelines that guarantee unified, responsive app layouts across its entire ecosystem.</p><p>By ensuring proper app scaling and dynamic layouts in iOS 27, the iPhone Ultra has the potential to deliver a foldable experience that simply works right out of the box. </p><p>Instead of letterboxed retro games, squashed interfaces, or awkwardly cropped video feeds, Apple can offer seamless layout transformations between phone and tablet states. By solving the software continuity and dynamic scaling issues that have eluded Google and its hardware partners for years, Apple wouldn’t just be releasing another foldable — it would establish the gold standard.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xm828O"></div>                            </div>                            <script src="https://kwizly.com/embed/Xm828O.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/phones/iphones/iphone-ultra-11-things-you-need-to-know-about-the-foldable-iphone-ahead-of-the-apple-event"><strong>iPhone Ultra — 11 things you need to know about the foldable iPhone ahead of the Apple Event</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/entertainment/apple-tv/everything-new-on-apple-tv-in-september-2026-slow-horses-season-6-and-much-more"><strong>Everything new on Apple TV in September 2026: 'Slow Horses' season 6 and much more</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-price-rumors-heres-how-much-more-you-could-pay-this-year"><strong>iPhone 18 Pro and iPhone 18 Pro Max price rumors — here's how much more you could pay this year</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/ive-tested-every-major-foldable-phone-this-year-and-the-iphone-ultra-can-beat-them-all-with-this-one-killer-feature</link>
                                                                            <description>
                            <![CDATA[ While Android foldables have perfected their hardware, the iPhone Ultra could instantly dominate the category simply by solving the messy app scaling mistake. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">hjiKT8tGpFU9C6PmcxVLiQ</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/BXFPFEcaHQrVivQScPBNff-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 31 Aug 2026 08:15:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ john.velasco@futurenet.com (John Velasco) ]]></author>                    <dc:creator><![CDATA[ John Velasco ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/TSj224oX8d5ERXaDs8pDGd.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/BXFPFEcaHQrVivQScPBNff-1280-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone Ultra.]]></media:description>                                                            <media:text><![CDATA[iPhone Ultra.]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone Ultra.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/BXFPFEcaHQrVivQScPBNff-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I’ve spent the last few months testing some of the <a href="https://www.tomsguide.com/best-picks/best-foldable-phones">best foldable phones</a> ever made. From Motorola’s impressive first stab at a notebook-style design in the <a href="https://www.tomsguide.com/phones/motorola-phones/motorola-razr-fold-review">Razr Fold</a> to the thin and light construction of the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-z-fold-8-ultra-review">Galaxy Z Fold 8 Ultra</a> and the <a href="https://www.tomsguide.com/phones/google-pixel-phones/google-pixel-11-pro-fold-review">Pixel 11 Pro Fold’s</a> focus on content creation, they prove just how much innovation and competition exist in the space.</p><p>Yet, despite all their efforts, I always run into the same frustrating wall with these Android-powered devices. I genuinely believe that Apple’s long-rumored <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a> has a golden opportunity to instantly sweep the competition — and it won’t need to rely on a triple-lens camera setup or an <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-creaseless-display-could-make-it-a-day-1-purchase-theres-just-one-problem">entirely creaseless display</a> to do it.</p><p>The killer feature that could crown Apple the undisputed leader of the segment is the exact software hurdle Google and Android manufacturers still haven't cleared: seamless app scaling and truly dynamic layouts. Here’s the proof.</p><h2 id="age-of-origins-stretched-out-look">Age of Origins — stretched out look</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="HhYz53Jt5KvTSxcbz8osfF" name="iPhone Fold - fix foldable app layouts" alt="foldable app layouts." src="https://cdn.mos.cms.futurecdn.net/HhYz53Jt5KvTSxcbz8osfF.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" 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 be fair, most core native apps are well-optimized for both the inner and outer displays of the foldable phones I’ve tested. Apps like Gmail, Google Calendar, and YouTube dynamically adapt their layouts and scale seamlessly between screens.</p><p>However, third-party games tell a completely different story. In <a href="https://play.google.com/store/apps/details?id=com.camelgames.aoz&hl=en_US" target="_blank" rel="nofollow">Age of Origins</a>, you can see how poorly the interface scales when transitioning between the displays. The result is an aggressively distorted, stretched-out layout that makes playing nearly impossible — and the only way to fix it is by force-closing and restarting the game entirely.</p><h2 id="tiktok-black-bars-and-a-crop">TikTok — black bars and a crop</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="BYqhjZuLfUu3uKhrktQTcF" name="iPhone Fold - fix foldable app layouts" alt="foldable app layouts." src="https://cdn.mos.cms.futurecdn.net/BYqhjZuLfUu3uKhrktQTcF.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>TikTok is one of the most popular apps around, but my patience is always tested whenever I run it on a foldable. As shown above, the app loads nicely when launched on the outer screen, maintaining the familiar vertical layout of any standard slate phone. But when I unfold the device to view it on the main display, it aggressively adds the video with thick black bars on the left and right — wasting a massive amount of prime screen real estate.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="ZzRxwckLBxWeGwKszH6tcF" name="iPhone Fold - fix foldable app layouts" alt="foldable app layouts." src="https://cdn.mos.cms.futurecdn.net/ZzRxwckLBxWeGwKszH6tcF.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" 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 I take the opposite approach and launch TikTok directly on the main display, the app forces a zoom-crop to fill the entire square aspect ratio. While that eliminates the dead space, it severely cuts off the top and bottom of the video, often hiding essential visual details and on-screen text. Either way, you are left with a compromised experience.</p><h2 id="castlevania-symphony-of-the-night-even-more-retro">Castlevania Symphony of the Night — even more retro</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="hvyXUb63eaZfio82K4TxbF" name="iPhone Fold - fix foldable app layouts" alt="foldable app layouts." src="https://cdn.mos.cms.futurecdn.net/hvyXUb63eaZfio82K4TxbF.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Lately, I’ve been enjoying some retro gaming thanks to a new <a href="https://www.tomsguide.com/phones/iphones/i-tried-this-magsafe-game-controller-and-it-puts-other-bluetooth-gamepads-to-shame-plus-its-usd20-off-right-now">MagSafe gaming pad</a> I’ve been using — and the current title I’m pursuing is <a href="https://play.google.com/store/apps/details?id=jp.konami.epjCastlevania2&hl=en_US" target="_blank" rel="nofollow">Castlevania Symphony of the Night</a>. </p><p>When I unfold the phone, the game doesn't dynamically expand or scale its rendered canvas to take advantage of the extra real estate. Instead, I get massive black bars flanking the gameplay window, with touch controls floating awkwardly across the letterboxed borders.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1510px;"><p class="vanilla-image-block" style="padding-top:59.60%;"><img id="XcjUE5A8uJrsgtaDXVFsbF" name="iPhone Fold - fix foldable app layouts" alt="foldable app layouts." src="https://cdn.mos.cms.futurecdn.net/XcjUE5A8uJrsgtaDXVFsbF.jpg" mos="" align="middle" fullscreen="" width="1510" height="900" attribution="" endorsement="" 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 worse, switching between the outer and inner displays can trigger an aggressive shrink-to-fit behavior, leaving the active game screen stranded in the center surrounded by dead black space on all four sides. For an experience meant to feel expansive, poor aspect ratio scaling makes it feel more cramped than playing on a standard phone.</p><h2 id="apple-s-chance-to-shine">Apple’s chance to shine</h2><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="cLJg47oNbZQTPJwitNVmte" name="iPhone Ultra half open Apple Track 1" alt="iPhone Ultra half folded in hand" src="https://cdn.mos.cms.futurecdn.net/cLJg47oNbZQTPJwitNVmte.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: Apple Track)</span></figcaption></figure><p>This is where Apple can completely alter the foldable landscape. While Android makers have spent years refining hardware hinges and striving for ultra-thin designs, they’ve consistently struggled to get third-party developers to treat foldable aspect ratios as a priority. Apple, by contrast, enforces stringent guidelines that guarantee unified, responsive app layouts across its entire ecosystem.</p><p>By ensuring proper app scaling and dynamic layouts in iOS 27, the iPhone Ultra has the potential to deliver a foldable experience that simply works right out of the box. </p><p>Instead of letterboxed retro games, squashed interfaces, or awkwardly cropped video feeds, Apple can offer seamless layout transformations between phone and tablet states. By solving the software continuity and dynamic scaling issues that have eluded Google and its hardware partners for years, Apple wouldn’t just be releasing another foldable — it would establish the gold standard.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-Xm828O"></div>                            </div>                            <script src="https://kwizly.com/embed/Xm828O.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/phones/iphones/iphone-ultra-11-things-you-need-to-know-about-the-foldable-iphone-ahead-of-the-apple-event"><strong>iPhone Ultra — 11 things you need to know about the foldable iPhone ahead of the Apple Event</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/entertainment/apple-tv/everything-new-on-apple-tv-in-september-2026-slow-horses-season-6-and-much-more"><strong>Everything new on Apple TV in September 2026: 'Slow Horses' season 6 and much more</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-price-rumors-heres-how-much-more-you-could-pay-this-year"><strong>iPhone 18 Pro and iPhone 18 Pro Max price rumors — here's how much more you could pay this year</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra — Here's how Apple's and Samsung's flagships could compare ]]></title>
                                                                                                <dc:content><![CDATA[ <p>September is just around the corner, and that can only mean one thing: It’s time for Apple to reveal its latest iPhones.</p><p>For the past seven years, the Pro Max has been Apple’s most expensive (and arguably desirable) model, but in 2026 we’re expecting the company’s first foldable to eclipse it in terms of media coverage.</p><p>You can see how the <a href="https://www.tomsguide.com/phones/samsung-phones/3-big-ways-the-iphone-ultra-could-beat-the-galaxy-z-fold-8">iPhone Ultra is lining up against the Samsung Galaxy Z Fold 8 in the battle of the foldables here</a>, but what about the non-folding flagships? Both remain big hitters, so here’s how the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max</a> is set to stack up against the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review">Samsung Galaxy S26 Ultra</a> as we approach Apple’s September launch date.</p><h2 id="iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-specifications">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra: Specifications</h2><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>iPhone 18 Pro Max (rumored)</strong></p></td><td  ><p><strong>Samsung Galaxy S26 Ultra</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Display size</strong></p></td><td  ><p>6.9 inches</p></td><td  ><p>6.9 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Refresh rate</strong></p></td><td  ><p>1-120Hz ProMotion</p></td><td  ><p>1-120Hz adaptive </p></td></tr><tr><td class="firstcol " ><p><strong>CPU</strong></p></td><td  ><p>A20 Pro</p></td><td  ><p>Snapdragon 8 Elite Gen 5 for Galaxy</p></td></tr><tr><td class="firstcol " ><p><strong>Memory</strong></p></td><td  ><p>12GB</p></td><td  ><p>12GB / 16GB </p></td></tr><tr><td class="firstcol " ><p><strong>Storage</strong></p></td><td  ><p>256GB, 512GB, 1TB, 2TB</p></td><td  ><p>256GB, 512GB, 1TB</p></td></tr><tr><td class="firstcol " ><p><strong>Cameras</strong></p></td><td  ><p>48MP main with variable aperture, 48MP ultrawide, 48MP telephoto (4x)</p></td><td  ><p>200MP main, 50MP ultrawide, 10MP telephoto (3x), 50MP telephoto (5x)</p></td></tr><tr><td class="firstcol " ><p><strong>Battery Size</strong></p></td><td  ><p>5,567 mAh (eSim) / 5,491 mAh (SIM tray)</p></td><td  ><p>5,000 mAh</p></td></tr><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$1,299</p></td><td  ><p>$1,299</p></td></tr></tbody></table></div><h2 id="iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-release-date-and-price">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra: Release date and 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:4982px;"><p class="vanilla-image-block" style="padding-top:42.85%;"><img id="atg4cwWLDkkZyksuPLdtTJ" name="Galaxy-S26-Ultra-HERO2" alt="Samsung Galaxy S26 Ultra shown in hand" src="https://cdn.mos.cms.futurecdn.net/atg4cwWLDkkZyksuPLdtTJ.jpg" mos="" align="middle" fullscreen="" width="4982" height="2135" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>For over a decade, Apple has released almost every new numbered iPhone in September (with the exception of the <a href="https://www.tomsguide.com/reviews/iphone-12">iPhone 12</a> because of the coronavirus pandemic), and 2026 will be no different.</p><p>Scratch that, it will be <em>slightly </em>different. While the company has announced its <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 for Wednesday September 9</a>, where it’s set to reveal the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-rumors-everything-we-know-so-far">iPhone 18 Pro</a> family, as well as the new foldable <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a>, the regular <a href="https://www.tomsguide.com/phones/iphones/iphone-18-rumors-everything-we-know-so-far">iPhone 18</a> has <a href="https://www.tomsguide.com/phones/iphones/iphone-18-release-schedule-could-be-changing-but-this-rumor-makes-no-sense">reportedly been pushed back to 2027</a>. </p><p>The iPhone 18 Pro Max <em>will</em> be there, however, but the bad news is that it’s facing a price hike. The mild good news is that it’s <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-price-rumors-heres-how-much-more-you-could-pay-this-year">now expected to be $100</a>, given we were potentially <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-see-absolutely-massive-price-hike-according-to-researchers">bracing for more than double that at one point</a>. </p><p>Going by Apple’s previous pricing, that would see the 256GB model starting at $1,299, rising to $1,499 for the 512GB model, $1,699 for 1TB and $2,099 for 2TB.</p><p>That’s actually pretty similar to Samsung’s Galaxy S26 Ultra — or at least its MSRP when it was new in March 2026. It cost $1,299 for the 256GB model, $1,449 for 512GB and $1,799 for 1TB.</p><h2 id="iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-design-and-screens">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra: Design and screens</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1280px;"><p class="vanilla-image-block" style="padding-top:55.78%;"><img id="WNJZg5wpSg4yem6kzvAjLN" name="iPhone 18 Pro and Max LIST Large" alt="iPhone 18 Pro vs iPhone 18 Pro Max." src="https://cdn.mos.cms.futurecdn.net/WNJZg5wpSg4yem6kzvAjLN.jpg" mos="" align="middle" fullscreen="" width="1280" height="714" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Given the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a> series introduced a couple of new design tweaks — the raised camera section and the two-tone colorways — we’re not expecting major changes this time. At a glance, the iPhone 18 Pro Max may be barely distinguishable from the <a href="http://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">iPhone 17 Pro Max</a>, right down to the 6.9-inch OLED display.</p><p>There will reportedly be a couple of minor changes, mind. To make space for a larger capacity battery, it will apparently be about 0.25mm thicker and seven grams heavier. The Dynamic Island will apparently also be around 35% smaller.</p><p>It would be a big surprise if the screen specs were any different, given the 6.9-inch size. So we’re likely looking at a resolution of 2,868 x 1,320, or around 460 pixels per inch (ppi). ProMotion will offer adaptive refresh rates of up to 120Hz.</p><p>We know the exact screen specifications of the Samsung Galaxy S26 Ultra and they’re pretty similar. It also has a 6.9-inch OLED panel, capable of 120Hz, though the top resolution is higher at 3,120 x 1,440 meaning a sharpness of 505ppi (though it defaults to a lower 2,340 x 1,080 resolution to save battery). </p><p>This year, Samsung introduced a new feature called <a href="https://www.tomsguide.com/phones/samsung-phones/the-galaxy-s26-ultras-privacy-display-is-more-exciting-to-me-than-any-ai-feature">Privacy Display</a>. When enabled, this prevents others from seeing what’s on your phone screen by switching to dedicated narrow pixels that can only be seen head on. This can be automatically enabled on a per-app basis, so you can have it magically enable itself for your banking apps, but not for YouTube, say.</p><p>That innovation aside, there’s little difference between this and the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s25-ultra-review">Samsung Galaxy S25 Ultra</a> — both in terms of screen technology and looks. Though that design does allow for a built-in S Pen for note taking and doodling — a real advantage over the iPhone 18 Pro Max.</p><h2 id="iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-performance">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra: Performance</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3684px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="bFv6s9UZuRZHPMckD5pxaL" name="Galaxy S26 Ultra review-27" alt="Samsung Galaxy S26 Ultra shown in hand" src="https://cdn.mos.cms.futurecdn.net/bFv6s9UZuRZHPMckD5pxaL.jpg" mos="" align="middle" fullscreen="" width="3684" height="2072" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Let’s start with the one we have already benchmarked. Powered by the Qualcomm Snapdragon 8 Elite Gen 5 for Galaxy and backed by either 12 or 16GB RAM depending on the model, the Samsung Galaxy S26 Ultra is a truly impressive performer. It even has a vapor chamber for heat dissipation, which keeps it running cool even when running graphically demanding content.</p><p>Here’s how it benchmarked compared to the iPhone 17 Pro Max:</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Geekbench</strong></p></td><td  ><p><strong>3DMark Solar Bay Unlimited</strong></p></td><td  ><p><strong>Geekbench AI 1.5</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Galaxy S26 Ultra</strong></p></td><td  ><p>3,785 / 11,563</p></td><td  ><p>49.37 / 12,984</p></td><td  ><p>83047 (TensorFlow Lite QNN)</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max</strong></p></td><td  ><p>3,871 / 9,968</p></td><td  ><p>46.6 / 12,260</p></td><td  ><p>48549 (Quantitized Core ML/Neural Engine)</p></td></tr></tbody></table></div><p>A modest lead on multi-core and gaming benchmarks, but a huge one when it comes to AI performance.</p><p>But, of course, this is against last year’s iPhone and its A19 chipset. It stands to reason that Apple will at least close the gap and more than likely go further, especially as the A20 Pro is <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-tipped-for-a20-pro-chip-apples-first-2nm-processor-to-power-new-foldable-phone">rumored to be built using the 2nm manufacturing process</a>, meaning a step change in terms of performance. We’re reportedly looking at 18% speed boost and 30% better power efficiency, which would see it blow past the S26 Ultra (though with the Galaxy S27 Ultra likely to regain the throne in early 2027). </p><p>On the subject of efficiency, Apple is set to gain another big advantage over Samsung with the iPhone 18 Pro Max: stamina. While the iPhone 17 Pro Max lasted an impressive 17 hours and 54 minutes in our tests, the next generation is likely to last even longer. That’s not just thanks to the 2nm chip’s efficiency savings, but because Apple is reportedly including a larger battery. This will reportedly be 5,391 mAh for models with a SIM tray, and 5,567mAh for those without  — a big step up from the 4,823 mAh/ 5,088 mAh cells found in the 17 Pro Max.</p><p>By contrast, the Galaxy S26 Ultra packs a 5,000 mAh battery. It lasted a respectable 16 hours and ten minutes in our review test. </p><h2 id="iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-cameras">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra: Cameras</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="WeRkpqbqkJavKd4hmEBzgh" name="iPhone 18 Pro vs iPhone 17 Pro" alt="iPhone 18 Pro vs iPhone 17 Pro" src="https://cdn.mos.cms.futurecdn.net/WeRkpqbqkJavKd4hmEBzgh.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Samsung Galaxy S26 Ultra currently tops our list of the <a href="https://www.tomsguide.com/us/best-phone-cameras,review-2272.html">best camera phones</a>. A big step up from the previous generation, the 200MP main camera and 50MP 5x telephoto lens have wider apertures, allowing for 47% and 37% brighter images respectively.</p><p>Add in a supplemental 10MP 3x telephoto lens and a 50MP ultra wide camera, and you’ve got an incredibly flexible camera setup that takes great shots whatever the environment. At the time of writing, it can’t be beat.</p><p>On raw specs alone, it doesn’t look like the iPhone 18 Pro Max will be challenging for the title, given leakers point to the same trio of 48MP lenses (regular, ultra wide and 4x optical zoom) again.</p><p>But the iPhone 18 Pro Max does reportedly have an ace up its sleeve: <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-be-the-first-iphone-to-get-a-variable-aperture-why-that-matters">variable aperture</a>. This lets you adjust the amount of light entering the lens, rather than having to rigidly stick to presets decided by Apple. While this is a feature that will only appeal to experienced photographers, in the right hands, it could make a huge difference to photographic composition.</p><h2 id="iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-outlook">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra: Outlook</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UfraPifaz2CpXLbJKJYqDY" name="S Pen S26 Ultra" alt="Samsung Galaxy S26 Ultra S Pen" src="https://cdn.mos.cms.futurecdn.net/UfraPifaz2CpXLbJKJYqDY.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 Samsung Galaxy S26 Ultra is the <a href="https://www.tomsguide.com/us/best-android-phones,review-6051.html">best Android phone</a> you can buy right now. It will probably remain so until the Galaxy S27 Ultra replaces it in early 2027.</p><p>But if you’re open to iOS, then it looks like the iPhone 18 Pro Max will eclipse it in a few key ways. It’s set to be faster, last longer, and while the camera specs will likely be weaker, keen photographers will have a lot of fun with the variable rate aperture.</p><p>Of course, the Samsung Galaxy S26 Ultra has a few key advantages, and not just in its overall camera layout. Privacy Display is a marvelous innovation beautifully implemented, the S Pen is really handy, and as it's been out for nearly six months, it can be had for less than its high $1,299 asking price.</p><p>It’s worth considering, however, that we only have iPhone 18 Pro Max rumors and leaks to go on at the moment. While they’ve been pretty reliable in the past, we won’t know for sure what Apple has up its sleeve until <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">September 9th’s iPhone 18 event</a>. </p><div data-widget-type="merchantlink" data-model-name="Samsung Galaxy S26 Ultra"></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-heres-how-apples-and-samsungs-flagships-could-compare</link>
                                                                            <description>
                            <![CDATA[ Which big-screen smartphone should you buy? ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">PaYSr3WHfuFuVT64zXVYLW</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Gv7fyY2QJ4jPcPsj7so3fX-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 30 Aug 2026 05:45:00 +0000</pubDate>                                                                                                                                <updated>Sun, 30 Aug 2026 12:30:41 +0000</updated>
                                                                                                                                            <category><![CDATA[Phones]]></category>
                                                                                                                    <dc:creator><![CDATA[ Alan Martin ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/xMmhmPSssqZHHFWveDgSs7.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/Gv7fyY2QJ4jPcPsj7so3fX-1280-80.jpg">
                                                            <media:credit><![CDATA[Macworld/Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone 18 Pro Max render]]></media:description>                                                            <media:text><![CDATA[iPhone 18 Pro Max render]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone 18 Pro Max render]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Gv7fyY2QJ4jPcPsj7so3fX-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>September is just around the corner, and that can only mean one thing: It’s time for Apple to reveal its latest iPhones.</p><p>For the past seven years, the Pro Max has been Apple’s most expensive (and arguably desirable) model, but in 2026 we’re expecting the company’s first foldable to eclipse it in terms of media coverage.</p><p>You can see how the <a href="https://www.tomsguide.com/phones/samsung-phones/3-big-ways-the-iphone-ultra-could-beat-the-galaxy-z-fold-8">iPhone Ultra is lining up against the Samsung Galaxy Z Fold 8 in the battle of the foldables here</a>, but what about the non-folding flagships? Both remain big hitters, so here’s how the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max</a> is set to stack up against the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s26-ultra-review">Samsung Galaxy S26 Ultra</a> as we approach Apple’s September launch date.</p><h2 id="iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-specifications">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra: Specifications</h2><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>iPhone 18 Pro Max (rumored)</strong></p></td><td  ><p><strong>Samsung Galaxy S26 Ultra</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Display size</strong></p></td><td  ><p>6.9 inches</p></td><td  ><p>6.9 inches</p></td></tr><tr><td class="firstcol " ><p><strong>Refresh rate</strong></p></td><td  ><p>1-120Hz ProMotion</p></td><td  ><p>1-120Hz adaptive </p></td></tr><tr><td class="firstcol " ><p><strong>CPU</strong></p></td><td  ><p>A20 Pro</p></td><td  ><p>Snapdragon 8 Elite Gen 5 for Galaxy</p></td></tr><tr><td class="firstcol " ><p><strong>Memory</strong></p></td><td  ><p>12GB</p></td><td  ><p>12GB / 16GB </p></td></tr><tr><td class="firstcol " ><p><strong>Storage</strong></p></td><td  ><p>256GB, 512GB, 1TB, 2TB</p></td><td  ><p>256GB, 512GB, 1TB</p></td></tr><tr><td class="firstcol " ><p><strong>Cameras</strong></p></td><td  ><p>48MP main with variable aperture, 48MP ultrawide, 48MP telephoto (4x)</p></td><td  ><p>200MP main, 50MP ultrawide, 10MP telephoto (3x), 50MP telephoto (5x)</p></td></tr><tr><td class="firstcol " ><p><strong>Battery Size</strong></p></td><td  ><p>5,567 mAh (eSim) / 5,491 mAh (SIM tray)</p></td><td  ><p>5,000 mAh</p></td></tr><tr><td class="firstcol " ><p><strong>Starting price</strong></p></td><td  ><p>$1,299</p></td><td  ><p>$1,299</p></td></tr></tbody></table></div><h2 id="iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-release-date-and-price">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra: Release date and 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:4982px;"><p class="vanilla-image-block" style="padding-top:42.85%;"><img id="atg4cwWLDkkZyksuPLdtTJ" name="Galaxy-S26-Ultra-HERO2" alt="Samsung Galaxy S26 Ultra shown in hand" src="https://cdn.mos.cms.futurecdn.net/atg4cwWLDkkZyksuPLdtTJ.jpg" mos="" align="middle" fullscreen="" width="4982" height="2135" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>For over a decade, Apple has released almost every new numbered iPhone in September (with the exception of the <a href="https://www.tomsguide.com/reviews/iphone-12">iPhone 12</a> because of the coronavirus pandemic), and 2026 will be no different.</p><p>Scratch that, it will be <em>slightly </em>different. While the company has announced its <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 for Wednesday September 9</a>, where it’s set to reveal the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-rumors-everything-we-know-so-far">iPhone 18 Pro</a> family, as well as the new foldable <a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-rumors-everything-you-need-to-know-about-the-foldable-iphone">iPhone Ultra</a>, the regular <a href="https://www.tomsguide.com/phones/iphones/iphone-18-rumors-everything-we-know-so-far">iPhone 18</a> has <a href="https://www.tomsguide.com/phones/iphones/iphone-18-release-schedule-could-be-changing-but-this-rumor-makes-no-sense">reportedly been pushed back to 2027</a>. </p><p>The iPhone 18 Pro Max <em>will</em> be there, however, but the bad news is that it’s facing a price hike. The mild good news is that it’s <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-and-iphone-18-pro-max-price-rumors-heres-how-much-more-you-could-pay-this-year">now expected to be $100</a>, given we were potentially <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-see-absolutely-massive-price-hike-according-to-researchers">bracing for more than double that at one point</a>. </p><p>Going by Apple’s previous pricing, that would see the 256GB model starting at $1,299, rising to $1,499 for the 512GB model, $1,699 for 1TB and $2,099 for 2TB.</p><p>That’s actually pretty similar to Samsung’s Galaxy S26 Ultra — or at least its MSRP when it was new in March 2026. It cost $1,299 for the 256GB model, $1,449 for 512GB and $1,799 for 1TB.</p><h2 id="iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-design-and-screens">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra: Design and screens</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1280px;"><p class="vanilla-image-block" style="padding-top:55.78%;"><img id="WNJZg5wpSg4yem6kzvAjLN" name="iPhone 18 Pro and Max LIST Large" alt="iPhone 18 Pro vs iPhone 18 Pro Max." src="https://cdn.mos.cms.futurecdn.net/WNJZg5wpSg4yem6kzvAjLN.jpg" mos="" align="middle" fullscreen="" width="1280" height="714" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: John Velasco / Tom's Guide)</span></figcaption></figure><p>Given the <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17-pro-review">iPhone 17 Pro</a> series introduced a couple of new design tweaks — the raised camera section and the two-tone colorways — we’re not expecting major changes this time. At a glance, the iPhone 18 Pro Max may be barely distinguishable from the <a href="http://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">iPhone 17 Pro Max</a>, right down to the 6.9-inch OLED display.</p><p>There will reportedly be a couple of minor changes, mind. To make space for a larger capacity battery, it will apparently be about 0.25mm thicker and seven grams heavier. The Dynamic Island will apparently also be around 35% smaller.</p><p>It would be a big surprise if the screen specs were any different, given the 6.9-inch size. So we’re likely looking at a resolution of 2,868 x 1,320, or around 460 pixels per inch (ppi). ProMotion will offer adaptive refresh rates of up to 120Hz.</p><p>We know the exact screen specifications of the Samsung Galaxy S26 Ultra and they’re pretty similar. It also has a 6.9-inch OLED panel, capable of 120Hz, though the top resolution is higher at 3,120 x 1,440 meaning a sharpness of 505ppi (though it defaults to a lower 2,340 x 1,080 resolution to save battery). </p><p>This year, Samsung introduced a new feature called <a href="https://www.tomsguide.com/phones/samsung-phones/the-galaxy-s26-ultras-privacy-display-is-more-exciting-to-me-than-any-ai-feature">Privacy Display</a>. When enabled, this prevents others from seeing what’s on your phone screen by switching to dedicated narrow pixels that can only be seen head on. This can be automatically enabled on a per-app basis, so you can have it magically enable itself for your banking apps, but not for YouTube, say.</p><p>That innovation aside, there’s little difference between this and the <a href="https://www.tomsguide.com/phones/samsung-phones/samsung-galaxy-s25-ultra-review">Samsung Galaxy S25 Ultra</a> — both in terms of screen technology and looks. Though that design does allow for a built-in S Pen for note taking and doodling — a real advantage over the iPhone 18 Pro Max.</p><h2 id="iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-performance">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra: Performance</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3684px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="bFv6s9UZuRZHPMckD5pxaL" name="Galaxy S26 Ultra review-27" alt="Samsung Galaxy S26 Ultra shown in hand" src="https://cdn.mos.cms.futurecdn.net/bFv6s9UZuRZHPMckD5pxaL.jpg" mos="" align="middle" fullscreen="" width="3684" height="2072" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Let’s start with the one we have already benchmarked. Powered by the Qualcomm Snapdragon 8 Elite Gen 5 for Galaxy and backed by either 12 or 16GB RAM depending on the model, the Samsung Galaxy S26 Ultra is a truly impressive performer. It even has a vapor chamber for heat dissipation, which keeps it running cool even when running graphically demanding content.</p><p>Here’s how it benchmarked compared to the iPhone 17 Pro Max:</p><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>Geekbench</strong></p></td><td  ><p><strong>3DMark Solar Bay Unlimited</strong></p></td><td  ><p><strong>Geekbench AI 1.5</strong></p></td></tr><tr><td class="firstcol " ><p><strong>Galaxy S26 Ultra</strong></p></td><td  ><p>3,785 / 11,563</p></td><td  ><p>49.37 / 12,984</p></td><td  ><p>83047 (TensorFlow Lite QNN)</p></td></tr><tr><td class="firstcol " ><p><strong>iPhone 17 Pro Max</strong></p></td><td  ><p>3,871 / 9,968</p></td><td  ><p>46.6 / 12,260</p></td><td  ><p>48549 (Quantitized Core ML/Neural Engine)</p></td></tr></tbody></table></div><p>A modest lead on multi-core and gaming benchmarks, but a huge one when it comes to AI performance.</p><p>But, of course, this is against last year’s iPhone and its A19 chipset. It stands to reason that Apple will at least close the gap and more than likely go further, especially as the A20 Pro is <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-tipped-for-a20-pro-chip-apples-first-2nm-processor-to-power-new-foldable-phone">rumored to be built using the 2nm manufacturing process</a>, meaning a step change in terms of performance. We’re reportedly looking at 18% speed boost and 30% better power efficiency, which would see it blow past the S26 Ultra (though with the Galaxy S27 Ultra likely to regain the throne in early 2027). </p><p>On the subject of efficiency, Apple is set to gain another big advantage over Samsung with the iPhone 18 Pro Max: stamina. While the iPhone 17 Pro Max lasted an impressive 17 hours and 54 minutes in our tests, the next generation is likely to last even longer. That’s not just thanks to the 2nm chip’s efficiency savings, but because Apple is reportedly including a larger battery. This will reportedly be 5,391 mAh for models with a SIM tray, and 5,567mAh for those without  — a big step up from the 4,823 mAh/ 5,088 mAh cells found in the 17 Pro Max.</p><p>By contrast, the Galaxy S26 Ultra packs a 5,000 mAh battery. It lasted a respectable 16 hours and ten minutes in our review test. </p><h2 id="iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-cameras">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra: Cameras</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="WeRkpqbqkJavKd4hmEBzgh" name="iPhone 18 Pro vs iPhone 17 Pro" alt="iPhone 18 Pro vs iPhone 17 Pro" src="https://cdn.mos.cms.futurecdn.net/WeRkpqbqkJavKd4hmEBzgh.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Samsung Galaxy S26 Ultra currently tops our list of the <a href="https://www.tomsguide.com/us/best-phone-cameras,review-2272.html">best camera phones</a>. A big step up from the previous generation, the 200MP main camera and 50MP 5x telephoto lens have wider apertures, allowing for 47% and 37% brighter images respectively.</p><p>Add in a supplemental 10MP 3x telephoto lens and a 50MP ultra wide camera, and you’ve got an incredibly flexible camera setup that takes great shots whatever the environment. At the time of writing, it can’t be beat.</p><p>On raw specs alone, it doesn’t look like the iPhone 18 Pro Max will be challenging for the title, given leakers point to the same trio of 48MP lenses (regular, ultra wide and 4x optical zoom) again.</p><p>But the iPhone 18 Pro Max does reportedly have an ace up its sleeve: <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-be-the-first-iphone-to-get-a-variable-aperture-why-that-matters">variable aperture</a>. This lets you adjust the amount of light entering the lens, rather than having to rigidly stick to presets decided by Apple. While this is a feature that will only appeal to experienced photographers, in the right hands, it could make a huge difference to photographic composition.</p><h2 id="iphone-18-pro-max-vs-samsung-galaxy-s26-ultra-outlook">iPhone 18 Pro Max vs. Samsung Galaxy S26 Ultra: Outlook</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="UfraPifaz2CpXLbJKJYqDY" name="S Pen S26 Ultra" alt="Samsung Galaxy S26 Ultra S Pen" src="https://cdn.mos.cms.futurecdn.net/UfraPifaz2CpXLbJKJYqDY.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 Samsung Galaxy S26 Ultra is the <a href="https://www.tomsguide.com/us/best-android-phones,review-6051.html">best Android phone</a> you can buy right now. It will probably remain so until the Galaxy S27 Ultra replaces it in early 2027.</p><p>But if you’re open to iOS, then it looks like the iPhone 18 Pro Max will eclipse it in a few key ways. It’s set to be faster, last longer, and while the camera specs will likely be weaker, keen photographers will have a lot of fun with the variable rate aperture.</p><p>Of course, the Samsung Galaxy S26 Ultra has a few key advantages, and not just in its overall camera layout. Privacy Display is a marvelous innovation beautifully implemented, the S Pen is really handy, and as it's been out for nearly six months, it can be had for less than its high $1,299 asking price.</p><p>It’s worth considering, however, that we only have iPhone 18 Pro Max rumors and leaks to go on at the moment. While they’ve been pretty reliable in the past, we won’t know for sure what Apple has up its sleeve until <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">September 9th’s iPhone 18 event</a>. </p><div data-widget-type="merchantlink" data-model-name="Samsung Galaxy S26 Ultra"></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ iPhone 18 Pro Max vs iPhone 17 Pro Max: 5 biggest rumored upgrades ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max's</a> <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">launch event is coming up fast</a>, and with it should come all the details on what Apple has planned for this new Max-sized phone. The biggest question most people have isn't just what the iPhone 18 Pro Max will have, but rather what it will offer than the iPhone 17 Pro Max does not.</p><p>The <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">iPhone 17 Pro Max</a> is an excellent phone, it's actually our pick for the <a href="https://www.tomsguide.com/best-picks/best-phones">best phone</a> thanks to its design, strong battery life, excellent cameras and some of the best performance in a smartphone. Raising that bar is going to be a challenge, but it seems as though Apple could ensure the success of the iPhone 18 Pro Max compared to its predecessor with these five major upgrades.</p><h3 class="article-body__section" id="section-iphone-18-pro-max-vs-iphone-17-pro-max-rumored-specs"><span>iPhone 18 Pro Max vs iPhone 17 Pro Max: Rumored Specs</span></h3><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>iPhone 18 Pro Max</strong></p></td><td  ><p><strong>iPhone 17 Pro Max</strong></p></td></tr><tr><td class="firstcol " ><p>Display size</p></td><td  ><p>6.9 inches</p></td><td  ><p>6.3 inches</p></td></tr><tr><td class="firstcol " ><p>Refresh rate</p></td><td  ><p>120Hz</p></td><td  ><p>120Hz</p></td></tr><tr><td class="firstcol " ><p>CPU</p></td><td  ><p>A20 Pro</p></td><td  ><p>A19 Pro</p></td></tr><tr><td class="firstcol " ><p>Memory</p></td><td  ><p>12GB</p></td><td  ><p>12GB</p></td></tr><tr><td class="firstcol " ><p>Storage</p></td><td  ><p>256GB, 512GB, 1TB, 2TB</p></td><td  ><p>256GB, 512GB, 1TB, 2TB</p></td></tr><tr><td class="firstcol " ><p>Cameras</p></td><td  ><p>48MP main with variable aperture, 48MP ultrawide, 48MP telephoto with 5x/6x optical zoom</p></td><td  ><p>48MP main with variable aperture, 48MP ultrawide, 48MP telephoto with 5x optical zoom</p></td></tr><tr><td class="firstcol " ><p>Battery Size</p></td><td  ><p>5,567 mAh</p></td><td  ><p>5,088 mAh</p></td></tr><tr><td class="firstcol " ><p>Software</p></td><td  ><p>iOS 27</p></td><td  ><p>iOS 27</p></td></tr><tr><td class="firstcol " ><p>Dimensions</p></td><td  ><p>6.43 x 3.07 x 0.35 inches (163.4 x 78 x 9 mm)</p></td><td  ><p>6.43 x 3.07 x 0.35 in (163.4 x 78 x 8.8 mm)</p></td></tr><tr><td class="firstcol " ><p>Weight</p></td><td  ><p>8.46 ounces (240 grams)</p></td><td  ><p>8.22 ounces (233 grams)</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-variable-aperture"><span>Variable aperture</span></h3><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="FkYnLdfVHjjo8V94zycCVV" name="iPhone 17 Pro Max-16" alt="iPhone 17 Pro Max shown in hand" src="https://cdn.mos.cms.futurecdn.net/FkYnLdfVHjjo8V94zycCVV.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The biggest upgrade rumored to be coming to the iPhone 18 Pro Max is a <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-camera-may-get-this-major-upgrade-but-why-isnt-iphone-18-pro-getting-it-too">variable aperture camera</a>. Multiple other phones have offered adjustable or variable aperture through the years, but it's never actually happened on an iPhone. Essentially this upgrade means that, rather than having a fixed aperture, users would be able to control how much light actually enters the camera. </p><p>While it may not mean much for novice photographers, this could enable a way for the iPhone 18 Pro Max's camera to adapt its light intake based on the surrounding conditions.  It may also allow experienced photographers even more control over what the camera can do — much like they can with standalone camera equipment.</p><p>The cameras themselves are expected to have more or less the same hardware as last year, but the addition of variable aperture could be the thing that helps the 18 Pro Max steal the title of <a href="https://www.tomsguide.com/us/best-phone-cameras,review-2272.html">best camera phone</a> from Samsung.</p><h3 class="article-body__section" id="section-even-bigger-batteries"><span>Even bigger batteries</span></h3><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="oj8hrKE6qoSEzNpYXzxEvi" name="iphone-18-pro-concept2-aptenod" alt="iPhone 18 Pro concept design from Aptenod on YouTube" src="https://cdn.mos.cms.futurecdn.net/oj8hrKE6qoSEzNpYXzxEvi.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: Aptenod / YouTube)</span></figcaption></figure><p>iPhone battery life has made massive improvements over the past several years, but it's still <a href="https://www.tomsguide.com/us/smartphones-best-battery-life,review-2857.html">dwarfed by batteries from the likes of OnePlus, Asus and Motorola</a>. So news that the iPhone 18 Pro Max may have an even bigger battery pack this year is quite exciting, especially when you remember that the iPhone 17 Pro Max was already able to last almost 18 hours in our custom battery test.</p><p>There are conflicting reports on how large the iPhone 18 Pro Max's battery will actually be. We assume that there will be two variants, with larger batteries afforded to devices that don't have a physical SIM card, but it's unclear what the upper limit will be. Still, reports suggest it could be somewhere <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-battery-leak-suggests-big-changes-are-coming-what-we-know">between 5,321 mAh</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-tipped-to-be-heaviest-iphone-ever-heres-3-reasons-why-thats-a-good-thing">5,567 mAh</a>.</p><p>Whichever way you look at it, that's a huge upgrade compared to the iPhone 17 Pro Max, which topped out at 5,088 mAh in eSIM-only models. Combine that larger power pack with Apple's continual push for efficiency, and you have the makings of a massive increase in battery life. </p><h3 class="article-body__section" id="section-under-display-face-id"><span>Under-display Face ID</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="koRnLna2RmU9XgJXnhg3YV" name="iPhone 17 Pro Max-20" alt="iPhone 17 Pro Max" src="https://cdn.mos.cms.futurecdn.net/koRnLna2RmU9XgJXnhg3YV.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The long-awaited under-display selfie camera isn't expected to arrive with iPhone 18 Pro Max; that's reportedly being saved for the 10th anniversary iPhone. However, we could still see Apple finally <a href="https://www.tomsguide.com/phones/iphones/iphone-18-could-borrow-a-feature-from-samsungs-foldable-phones-when-it-launches-next-year">hide the last visible remnants of Face ID below the screen</a> — nine years after the first Face ID-equipped iPhones went on sale. </p><p>It's unclear what this might mean for the Dynamic Island. Apple may opt for a hole-punch camera design, which almost every Android phone has used for several years. However there are reports that the iPhone 18 Pro Max will still<a href="https://www.tomsguide.com/phones/iphones/the-iphone-18-pro-series-dynamic-island-could-be-smaller-than-before-and-i-think-thats-a-better-move-than-the-rumored-under-display-cameras"> feature an obvious Dynamic Island pill </a>— albeit one that's smaller than the one on the iPhone 18 Pro Max. </p><p>Regardless of whether Face ID goes fully under the display, we <a href="https://www.tomsguide.com/us/best-phone-cameras,review-2272.html">may still see a smaller version of the Dynamic Island pill.</a> This means slightly more screen space on your phone, and less of a black void seemingly doing nothing when your phone is idle.</p><h3 class="article-body__section" id="section-2nm-a20-pro-chipset"><span>2nm A20 Pro chipset</span></h3><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="UHNuNim9UYH2mmGNTn3S4V" name="Apple-iPhone 18 Pro-A20-Pro_LIST" alt="Apple iPhone 18 Pro and the A20 Pro chip" src="https://cdn.mos.cms.futurecdn.net/UHNuNim9UYH2mmGNTn3S4V.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/Apple)</span></figcaption></figure><p>Performance has become Apple's bread and butter, and we don't expect that to change with the release of iPhone 18 Pro Max. Qualcomm's Snapdragon chips may have caught up with Apple's A-series, but we can still expect the <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-tipped-for-a20-pro-chip-apples-first-2nm-processor-to-power-new-foldable-phone">new A20 Pro chipset </a>to offer a big leap in performance compared to iPhone 17 Pro Max's A19 Pro.</p><p>The new chips are widely expected to utilize TSMC's 2nm process. The smaller size compared to the current crop of 3nm chips means higher transistor density, which translates into improved performance and better energy efficiency. </p><p>According to <a href="https://www.weibo.com/5821279480/RdwrIjz35" target="_blank">reports</a>, we could see an 18% increase in performance compared to the A19 Pro chipset, and a 30% boost in power efficiency. In other words, we can expect a more powerful iPhone that doesn't need as much energy to run — which can only be a good thing for the battery life.</p><h3 class="article-body__section" id="section-c2-modem"><span>C2 modem</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2272px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="KwwUMqX3DXXqj5wDYpEhRo" name="Screenshot 2026-01-20 at 12.43.51" alt="iPhone 18 Pro leak-based render, showing the rear cameras" src="https://cdn.mos.cms.futurecdn.net/KwwUMqX3DXXqj5wDYpEhRo.jpg" mos="" align="middle" fullscreen="" width="2272" height="1278" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Front Page Tech)</span></figcaption></figure><p>It's not often that you can get excited about a new modem in a phone, but 2026 is full of surprises — and the possible addition of the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-offer-improved-battery-life-thanks-to-apple-designed-modem-heres-what-you-need-to-know">C2 modem</a> could be quite important. The original C1 was the first modem Apple built in-house, and debuted on the<a href="https://www.tomsguide.com/phones/iphones/apple-iphone-16e-review"> iPhone 16e,</a> which was followed by the C1X modem in<a href="https://www.tomsguide.com/phones/iphones/iphone-air-review"> iPhone Air </a>and<a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17e-review"> iPhone 17e.</a> However this could be the first time an Apple modem is utilized in a flagship iPhone model.</p><p>We don't know a lot about the C2 modem, but the fact it's built and designed by Apple means it should be better optimized for the iPhone system and software. Much like we saw with the A- and M-series chips, this should ensure better performance, while reducing the amount of power the modem draws from the battery. </p><p>Or, in other words, it's another thing that could help the iPhone 18 Pro Max increase its battery life even further.</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/expert-predicts-iphone-ultras-usd2-500-price-tag-wont-deter-die-hard-fans-it-could-see-10-million-units-sold-in-the-next-year">Expert predicts iPhone Ultra's $2,500 price tag won't deter die-hard fans — it could see 10 million units sold in the next year</a></li><li><a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">Apple iPhone 18 event — all the new products expected to launch at the 'Surprise and shine' event</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-11-things-you-need-to-know-about-the-foldable-iphone-ahead-of-the-apple-event">iPhone Ultra — 11 things you need to know about the foldable iPhone ahead of the Apple Event</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-vs-iphone-17-pro-max-5-biggest-rumored-upgrades</link>
                                                                            <description>
                            <![CDATA[ The iPhone 18 Pro Max is coming, and there are a bunch of upgrades coming with it. Here are five of the biggest ways it'll beat the iPhone 17 Pro Max. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">EmK7FuDzfzqGsN3wdLEcvS</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/WeRkpqbqkJavKd4hmEBzgh-1280-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 29 Aug 2026 04:30:00 +0000</pubDate>                                                                                                                                <updated>Mon, 07 Sep 2026 13:51:37 +0000</updated>
                                                                                                                                            <category><![CDATA[iPhones]]></category>
                                                    <category><![CDATA[Phones]]></category>
                                                                                                <author><![CDATA[ tom.pritchard@futurenet.com (Tom Pritchard) ]]></author>                    <dc:creator><![CDATA[ Tom Pritchard ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/biCewUkKfSA6QnT2HxVc3f.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <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/WeRkpqbqkJavKd4hmEBzgh-1280-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[iPhone 18 Pro vs iPhone 17 Pro]]></media:description>                                                            <media:text><![CDATA[iPhone 18 Pro vs iPhone 17 Pro]]></media:text>
                                <media:title type="plain"><![CDATA[iPhone 18 Pro vs iPhone 17 Pro]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/WeRkpqbqkJavKd4hmEBzgh-1280-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-rumors-and-leaks-everything-we-know-so-far">iPhone 18 Pro Max's</a> <a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">launch event is coming up fast</a>, and with it should come all the details on what Apple has planned for this new Max-sized phone. The biggest question most people have isn't just what the iPhone 18 Pro Max will have, but rather what it will offer than the iPhone 17 Pro Max does not.</p><p>The <a href="https://www.tomsguide.com/phones/iphones/iphone-17-pro-max-review">iPhone 17 Pro Max</a> is an excellent phone, it's actually our pick for the <a href="https://www.tomsguide.com/best-picks/best-phones">best phone</a> thanks to its design, strong battery life, excellent cameras and some of the best performance in a smartphone. Raising that bar is going to be a challenge, but it seems as though Apple could ensure the success of the iPhone 18 Pro Max compared to its predecessor with these five major upgrades.</p><h3 class="article-body__section" id="section-iphone-18-pro-max-vs-iphone-17-pro-max-rumored-specs"><span>iPhone 18 Pro Max vs iPhone 17 Pro Max: Rumored Specs</span></h3><div ><table><tbody><tr><td class="firstcol empty" ></td><td  ><p><strong>iPhone 18 Pro Max</strong></p></td><td  ><p><strong>iPhone 17 Pro Max</strong></p></td></tr><tr><td class="firstcol " ><p>Display size</p></td><td  ><p>6.9 inches</p></td><td  ><p>6.3 inches</p></td></tr><tr><td class="firstcol " ><p>Refresh rate</p></td><td  ><p>120Hz</p></td><td  ><p>120Hz</p></td></tr><tr><td class="firstcol " ><p>CPU</p></td><td  ><p>A20 Pro</p></td><td  ><p>A19 Pro</p></td></tr><tr><td class="firstcol " ><p>Memory</p></td><td  ><p>12GB</p></td><td  ><p>12GB</p></td></tr><tr><td class="firstcol " ><p>Storage</p></td><td  ><p>256GB, 512GB, 1TB, 2TB</p></td><td  ><p>256GB, 512GB, 1TB, 2TB</p></td></tr><tr><td class="firstcol " ><p>Cameras</p></td><td  ><p>48MP main with variable aperture, 48MP ultrawide, 48MP telephoto with 5x/6x optical zoom</p></td><td  ><p>48MP main with variable aperture, 48MP ultrawide, 48MP telephoto with 5x optical zoom</p></td></tr><tr><td class="firstcol " ><p>Battery Size</p></td><td  ><p>5,567 mAh</p></td><td  ><p>5,088 mAh</p></td></tr><tr><td class="firstcol " ><p>Software</p></td><td  ><p>iOS 27</p></td><td  ><p>iOS 27</p></td></tr><tr><td class="firstcol " ><p>Dimensions</p></td><td  ><p>6.43 x 3.07 x 0.35 inches (163.4 x 78 x 9 mm)</p></td><td  ><p>6.43 x 3.07 x 0.35 in (163.4 x 78 x 8.8 mm)</p></td></tr><tr><td class="firstcol " ><p>Weight</p></td><td  ><p>8.46 ounces (240 grams)</p></td><td  ><p>8.22 ounces (233 grams)</p></td></tr></tbody></table></div><h3 class="article-body__section" id="section-variable-aperture"><span>Variable aperture</span></h3><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="FkYnLdfVHjjo8V94zycCVV" name="iPhone 17 Pro Max-16" alt="iPhone 17 Pro Max shown in hand" src="https://cdn.mos.cms.futurecdn.net/FkYnLdfVHjjo8V94zycCVV.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The biggest upgrade rumored to be coming to the iPhone 18 Pro Max is a <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-camera-may-get-this-major-upgrade-but-why-isnt-iphone-18-pro-getting-it-too">variable aperture camera</a>. Multiple other phones have offered adjustable or variable aperture through the years, but it's never actually happened on an iPhone. Essentially this upgrade means that, rather than having a fixed aperture, users would be able to control how much light actually enters the camera. </p><p>While it may not mean much for novice photographers, this could enable a way for the iPhone 18 Pro Max's camera to adapt its light intake based on the surrounding conditions.  It may also allow experienced photographers even more control over what the camera can do — much like they can with standalone camera equipment.</p><p>The cameras themselves are expected to have more or less the same hardware as last year, but the addition of variable aperture could be the thing that helps the 18 Pro Max steal the title of <a href="https://www.tomsguide.com/us/best-phone-cameras,review-2272.html">best camera phone</a> from Samsung.</p><h3 class="article-body__section" id="section-even-bigger-batteries"><span>Even bigger batteries</span></h3><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="oj8hrKE6qoSEzNpYXzxEvi" name="iphone-18-pro-concept2-aptenod" alt="iPhone 18 Pro concept design from Aptenod on YouTube" src="https://cdn.mos.cms.futurecdn.net/oj8hrKE6qoSEzNpYXzxEvi.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: Aptenod / YouTube)</span></figcaption></figure><p>iPhone battery life has made massive improvements over the past several years, but it's still <a href="https://www.tomsguide.com/us/smartphones-best-battery-life,review-2857.html">dwarfed by batteries from the likes of OnePlus, Asus and Motorola</a>. So news that the iPhone 18 Pro Max may have an even bigger battery pack this year is quite exciting, especially when you remember that the iPhone 17 Pro Max was already able to last almost 18 hours in our custom battery test.</p><p>There are conflicting reports on how large the iPhone 18 Pro Max's battery will actually be. We assume that there will be two variants, with larger batteries afforded to devices that don't have a physical SIM card, but it's unclear what the upper limit will be. Still, reports suggest it could be somewhere <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-battery-leak-suggests-big-changes-are-coming-what-we-know">between 5,321 mAh</a> and <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-max-tipped-to-be-heaviest-iphone-ever-heres-3-reasons-why-thats-a-good-thing">5,567 mAh</a>.</p><p>Whichever way you look at it, that's a huge upgrade compared to the iPhone 17 Pro Max, which topped out at 5,088 mAh in eSIM-only models. Combine that larger power pack with Apple's continual push for efficiency, and you have the makings of a massive increase in battery life. </p><h3 class="article-body__section" id="section-under-display-face-id"><span>Under-display Face ID</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:3840px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="koRnLna2RmU9XgJXnhg3YV" name="iPhone 17 Pro Max-20" alt="iPhone 17 Pro Max" src="https://cdn.mos.cms.futurecdn.net/koRnLna2RmU9XgJXnhg3YV.jpg" mos="" align="middle" fullscreen="" width="3840" height="2160" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The long-awaited under-display selfie camera isn't expected to arrive with iPhone 18 Pro Max; that's reportedly being saved for the 10th anniversary iPhone. However, we could still see Apple finally <a href="https://www.tomsguide.com/phones/iphones/iphone-18-could-borrow-a-feature-from-samsungs-foldable-phones-when-it-launches-next-year">hide the last visible remnants of Face ID below the screen</a> — nine years after the first Face ID-equipped iPhones went on sale. </p><p>It's unclear what this might mean for the Dynamic Island. Apple may opt for a hole-punch camera design, which almost every Android phone has used for several years. However there are reports that the iPhone 18 Pro Max will still<a href="https://www.tomsguide.com/phones/iphones/the-iphone-18-pro-series-dynamic-island-could-be-smaller-than-before-and-i-think-thats-a-better-move-than-the-rumored-under-display-cameras"> feature an obvious Dynamic Island pill </a>— albeit one that's smaller than the one on the iPhone 18 Pro Max. </p><p>Regardless of whether Face ID goes fully under the display, we <a href="https://www.tomsguide.com/us/best-phone-cameras,review-2272.html">may still see a smaller version of the Dynamic Island pill.</a> This means slightly more screen space on your phone, and less of a black void seemingly doing nothing when your phone is idle.</p><h3 class="article-body__section" id="section-2nm-a20-pro-chipset"><span>2nm A20 Pro chipset</span></h3><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="UHNuNim9UYH2mmGNTn3S4V" name="Apple-iPhone 18 Pro-A20-Pro_LIST" alt="Apple iPhone 18 Pro and the A20 Pro chip" src="https://cdn.mos.cms.futurecdn.net/UHNuNim9UYH2mmGNTn3S4V.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/Apple)</span></figcaption></figure><p>Performance has become Apple's bread and butter, and we don't expect that to change with the release of iPhone 18 Pro Max. Qualcomm's Snapdragon chips may have caught up with Apple's A-series, but we can still expect the <a href="https://www.tomsguide.com/phones/iphones/iphone-fold-tipped-for-a20-pro-chip-apples-first-2nm-processor-to-power-new-foldable-phone">new A20 Pro chipset </a>to offer a big leap in performance compared to iPhone 17 Pro Max's A19 Pro.</p><p>The new chips are widely expected to utilize TSMC's 2nm process. The smaller size compared to the current crop of 3nm chips means higher transistor density, which translates into improved performance and better energy efficiency. </p><p>According to <a href="https://www.weibo.com/5821279480/RdwrIjz35" target="_blank">reports</a>, we could see an 18% increase in performance compared to the A19 Pro chipset, and a 30% boost in power efficiency. In other words, we can expect a more powerful iPhone that doesn't need as much energy to run — which can only be a good thing for the battery life.</p><h3 class="article-body__section" id="section-c2-modem"><span>C2 modem</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2272px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="KwwUMqX3DXXqj5wDYpEhRo" name="Screenshot 2026-01-20 at 12.43.51" alt="iPhone 18 Pro leak-based render, showing the rear cameras" src="https://cdn.mos.cms.futurecdn.net/KwwUMqX3DXXqj5wDYpEhRo.jpg" mos="" align="middle" fullscreen="" width="2272" height="1278" attribution="" endorsement="" class="inline"></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Front Page Tech)</span></figcaption></figure><p>It's not often that you can get excited about a new modem in a phone, but 2026 is full of surprises — and the possible addition of the <a href="https://www.tomsguide.com/phones/iphones/iphone-18-pro-could-offer-improved-battery-life-thanks-to-apple-designed-modem-heres-what-you-need-to-know">C2 modem</a> could be quite important. The original C1 was the first modem Apple built in-house, and debuted on the<a href="https://www.tomsguide.com/phones/iphones/apple-iphone-16e-review"> iPhone 16e,</a> which was followed by the C1X modem in<a href="https://www.tomsguide.com/phones/iphones/iphone-air-review"> iPhone Air </a>and<a href="https://www.tomsguide.com/phones/iphones/apple-iphone-17e-review"> iPhone 17e.</a> However this could be the first time an Apple modem is utilized in a flagship iPhone model.</p><p>We don't know a lot about the C2 modem, but the fact it's built and designed by Apple means it should be better optimized for the iPhone system and software. Much like we saw with the A- and M-series chips, this should ensure better performance, while reducing the amount of power the modem draws from the battery. </p><p>Or, in other words, it's another thing that could help the iPhone 18 Pro Max increase its battery life even further.</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/expert-predicts-iphone-ultras-usd2-500-price-tag-wont-deter-die-hard-fans-it-could-see-10-million-units-sold-in-the-next-year">Expert predicts iPhone Ultra's $2,500 price tag won't deter die-hard fans — it could see 10 million units sold in the next year</a></li><li><a href="https://www.tomsguide.com/phones/iphones/apple-iphone-18-event-all-the-new-products-expected-to-launch-in-september">Apple iPhone 18 event — all the new products expected to launch at the 'Surprise and shine' event</a></li><li><a href="https://www.tomsguide.com/phones/iphones/iphone-ultra-11-things-you-need-to-know-about-the-foldable-iphone-ahead-of-the-apple-event">iPhone Ultra — 11 things you need to know about the foldable iPhone ahead of the Apple Event</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
            </channel>
</rss>