How LLC Owners Save on Taxes in 2026

Digital Marketer Find more write-offs — search your profession or a specific deduction
Try:
Others Also Use These Strategies
Digital Marketing IRC §162

Marketing Tools & SaaS Subscriptions

Every SaaS subscription used in your digital marketing business is fully deductible — CRM platforms (HubSpot, Salesforce), SEO tools (SEMrush, Ahrefs, Moz), funnel builders (ClickFunnels, Kajabi), email marketing (ActiveCampaign, Klaviyo, ConvertKit), design tools (Canva Pro, Adobe Creative Cloud), automation (Zapier, Make), and analytics platforms.

Eligibility Requirements
  • Digital marketer using SaaS tools for client work or own business
  • Paying monthly or annual subscriptions to marketing platforms
  • Using tools exclusively or primarily for business
Example Savings Scenario

A digital marketer paying $800/month across HubSpot, SEMrush, ClickFunnels, ActiveCampaign, and Canva Pro deducts $9,600/year — saving $2,400 at a 25% rate.

MERNA Strategy Notes

Annual subscriptions paid upfront are deductible in the year paid. Keep all subscription receipts. Tools used for both personal and business use must be prorated.

Common Mistake: Free trials that convert to paid subscriptions — make sure billing date falls in the correct tax year for the deduction to apply.
IRC: Software subscriptions deductible under IRC §162 as ordinary and necessary business expenses.
Marketing IRC §162

Digital Marketer Advertising Platform & Ad Spend Deduction

Digital marketers who run ads for their own business can deduct 100% of Facebook Ads, Google Ads, LinkedIn Ads, and TikTok Ads spend as a business expense. A digital marketer spending $50,000 on ads to generate leads for their agency deducts the full $50,000. Ad spend for client campaigns is a cost of goods sold (COGS), not a personal deduction.

Eligibility Requirements
  • Must be a self-employed digital marketer or marketing agency owner
  • Ad spend must be for client campaigns or your own business marketing
  • Platform fees (Facebook, Google, TikTok, LinkedIn) are fully deductible
  • Must have documentation of ad spend (platform statements, invoices)
Example Savings Scenario

A digital marketing agency owner spending $120,000/year on client ad campaigns and $18,000 on their own business ads deducts $138,000, saving $51,060 at 37%.

MERNA Strategy Notes

Digital marketers can deduct all advertising platform costs. Facebook/Instagram Ads, Google Ads, TikTok Ads, LinkedIn Ads, Twitter/X Ads, Pinterest Ads, YouTube Ads, and programmatic advertising platforms are all 100% deductible. For agency owners who manage client ad budgets, the pass-through ad spend is deductible as a business expense. Agency management fees, platform management fees, and white-label tool fees are also deductible. Creative production costs (video ads, graphic design, copywriting) are deductible as marketing expenses.

Common Mistake: If you manage client ad budgets, ensure your accounting clearly separates client ad spend from your own business expenses. Commingling client funds with business funds creates accounting and legal problems.
Digital Marketing IRC §162

Course Creation & Content Production Costs

If you create online courses, digital products, or content as part of your marketing business, all production costs are deductible — video equipment, microphones, lighting, green screens, editing software (Final Cut Pro, Adobe Premiere), course platform fees (Teachable, Kajabi, Thinkific), graphic design, and freelance video editors or scriptwriters.

Eligibility Requirements
  • Digital marketer creating online courses or digital products
  • Content creator using video or audio production equipment
  • Paying course platform fees or freelance production costs
Example Savings Scenario

A course creator who spends $5,000 on video equipment, $3,000 on editing software, $2,400 in platform fees, and $4,000 on a video editor deducts $14,400 — saving $3,600 at a 25% rate.

MERNA Strategy Notes

Video equipment may qualify for Section 179 full expensing. Course platform fees are deductible in the year paid. Freelance production costs require 1099 filing if over $600.

Common Mistake: Course creation costs incurred before the course launches may need to be capitalized as startup costs rather than deducted immediately.
IRC: Production costs deductible under IRC §162. Equipment may qualify for Section 179 expensing.
Education IRC §162

Digital Marketer Certification & Education Deduction

Google Ads certifications, Meta Blueprint courses, HubSpot certifications, and digital marketing courses are fully deductible as professional development expenses. Also deduct industry conference attendance (MozCon, Traffic & Conversion Summit), marketing books, and any coaching or mentorship programs related to your digital marketing practice.

Eligibility Requirements
  • Must be a self-employed digital marketer or agency owner
  • Education must maintain or improve skills required in your current marketing work
  • Certifications must be for your existing marketing profession
  • Conferences and courses must have a business purpose
Example Savings Scenario

A digital marketer spending $2,400/year on courses, $1,500 on marketing conferences, $500 on certification exams, and $600 on marketing books deducts $5,000, saving $1,850 at 37%.

MERNA Strategy Notes

Digital marketers can deduct all professional development costs. Google Ads certification prep courses, Facebook Blueprint courses, HubSpot certifications, Coursera/Udemy marketing courses, marketing conferences (MozCon, Content Marketing World, Social Media Marketing World), marketing books and publications, and online marketing communities are all deductible.

Common Mistake: Education that qualifies you for a new career is not deductible. The education must maintain or improve skills in your current marketing profession.
Technology IRC §162

Digital Marketer Software & Marketing Tools Deduction

Digital marketers can deduct all marketing software subscriptions: SEMrush ($1,200/yr), HubSpot ($5,400/yr), ClickFunnels ($1,200/yr), ActiveCampaign ($720/yr), Canva Pro ($120/yr), and any analytics or automation tools. These are fully deductible under IRC §162 as ordinary and necessary business expenses. Track all SaaS subscriptions in a dedicated business account.

Eligibility Requirements
  • Must use software for digital marketing work
  • Tools must be used for business purposes
  • Subscriptions are deducted as current-year expenses
  • Must be a self-employed marketer or agency owner
Example Savings Scenario

A digital marketer paying $3,600/year for SEMrush, $1,200 for Ahrefs, $2,400 for HubSpot, $600 for Canva Pro, and $1,200 for email marketing tools deducts $9,000, saving $3,330 at 37%.

MERNA Strategy Notes

Digital marketers rely on expensive software tools that generate significant deductions. SEO tools (SEMrush $1,200-$4,800/year, Ahrefs $990-$3,960/year), email marketing (Mailchimp, Klaviyo, ActiveCampaign), CRM (HubSpot, Salesforce), social media management (Hootsuite, Buffer, Sprout Social), design tools (Canva Pro $120/year, Adobe Creative Cloud $600/year), landing page builders (ClickFunnels, Unbounce), and analytics tools are all deductible.

Common Mistake: Software used for personal projects or non-business purposes is not deductible. Track business vs. personal use for any mixed-use software.
Business Expenses IRC §162 Uncle Kam Clients Only

Advertising & Marketing Deduction

All costs of advertising and promoting your business are fully deductible. This includes Google Ads, Facebook and Instagram ads, business cards, flyers, brochures, signage, website design and hosting, domain names, email marketing tools (Mailchimp, Klaviyo), and any other promotional expenses.

Eligibility Requirements
  • Advertising directly promotes your business
  • Self-employed, freelancer, or business owner
  • Expenses paid in the tax year
Example Savings Scenario

A real estate agent spending $8,000/year on Facebook ads, business cards, and listing photography deducts the full amount, saving $2,400–$3,200 in taxes.

Unlock the Full Strategy Breakdown — Free

Enter your email for instant access to MERNA strategy notes, IRS red flag warnings, action steps, and implementation guide.

No spam · No obligation · Instant access
Mortgage IRC §162 Uncle Kam Clients Only

Realtor & Builder Relationship Marketing

Expenses incurred to build and maintain referral relationships with real estate agents, builders, and financial planners are fully deductible. This includes meals with referral partners (50% deductible), co-branded marketing materials, client appreciation events, and educational seminars you host for Realtors.

Eligibility Requirements
    Example Savings Scenario

    A loan officer spending $500/month on Realtor relationship marketing deducts $6,000/year (meals at 50%, materials at 100%).

    Unlock the Full Strategy Breakdown — Free

    Enter your email for instant access to MERNA strategy notes, IRS red flag warnings, action steps, and implementation guide.

    No spam · No obligation · Instant access
    What Most Digital Marketers Don't Know

    Every dollar you spend on Meta Ads, Google Ads, or TikTok ads is 100% deductible as an ordinary business expense under IRC §162 — including testing budgets and failed campaigns.

    Marketing SaaS tools (HubSpot, Klaviyo, ClickFunnels, Canva Pro, etc.) are fully deductible — most digital marketers undercount these and leave $5,000–$15,000/yr on the table.

    If you create courses, podcasts, or video content, your camera gear, microphones, lighting, and editing software are all deductible under Section 179 in the year of purchase.

    Common Questions for Digital Marketers

    Get answers to the most frequently asked tax questions for your profession.

    What tax deductions can a digital marketer claim?
    Digital marketers can deduct ad spend (100%), SaaS tools (HubSpot, SEMrush, ClickFunnels), home office, computer equipment, courses and training, phone and internet, and contractor payments. Most digital marketers miss $10,000\u2013$30,000 in deductions.
    Can a digital marketer deduct advertising spend?
    Yes \u2014 100% of advertising spend (Google Ads, Meta Ads, TikTok Ads) is deductible as a business expense. This includes both client ad spend (if billed to clients) and your own business advertising. Keep detailed records of campaign purposes.
    Should a digital marketing agency form an S-Corp?
    Yes \u2014 agencies earning $60,000+ in net profit save $5,000\u2013$20,000/year with an S-Corp election. You pay yourself a reasonable salary and take remaining profits as distributions, avoiding self-employment tax on the distribution portion.
    Can a digital marketer deduct software subscriptions?
    Yes \u2014 all SaaS tools used for business (HubSpot, SEMrush, Canva, ActiveCampaign, ClickFunnels, Zapier) are 100% deductible. Pay annual subscriptions in December to accelerate the deduction into the current tax year.
    What is the home office deduction for a digital marketer?
    A dedicated workspace used exclusively for business qualifies for the home office deduction. Deduct a proportional share of rent/mortgage, utilities, and internet. A 150 sq ft office in a 1,500 sq ft home = 10% of housing costs deductible.
    0
    0 write-offs saved
    Tap to view your list

    Your Biggest Missed Deduction Is Probably Locked Above

    Uncle Kam clients save an average of $20,000–$90,000/year. The strategies that make that possible are unlocked on a free strategy call.

    Book A Free Strategy Call Free consultation. No obligation.
    ';// ── Open in a new window and print ─────────────────────────────── var win = window.open('', '_blank', 'width=850,height=700,scrollbars=yes,noopener=0'); if (!win) { // Fallback: inject an iframe for printing if popup is blocked var iframe = document.createElement('iframe'); iframe.style.cssText = 'position:fixed;top:-9999px;left:-9999px;width:850px;height:700px;border:0;'; document.body.appendChild(iframe); iframe.contentDocument.open(); iframe.contentDocument.write(html); iframe.contentDocument.close(); setTimeout(function() { iframe.contentWindow.focus(); iframe.contentWindow.print(); setTimeout(function() { document.body.removeChild(iframe); }, 2000); }, 600); return; } win.document.open(); win.document.write(html); win.document.close(); win.focus(); setTimeout(function() { win.print(); }, 600); }// ── Email Unlock: post to GHL silently, expand locked cards ────────────── function ukwfUnlockStrategies(e) { e.preventDefault(); // Support both the main wall form AND per-card gate forms var form = e ? e.target : null; var gateInput = form ? form.querySelector('.ukwf-gate-email-input') : null; var mainInput = document.getElementById('ukwf-unlock-email'); var emailInput = (gateInput && gateInput.value.trim()) ? gateInput : mainInput; var errorEl = document.getElementById('ukwf-unlock-error'); var email = emailInput ? emailInput.value.trim() : ''; // Also check the gate input if main is empty if (!email && gateInput) email = gateInput.value.trim(); // Basic email validation if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { if (errorEl) errorEl.style.display = 'block'; if (gateInput) { gateInput.style.borderColor = '#ff6b6b'; gateInput.focus(); } else if (emailInput) emailInput.focus(); return; } if (errorEl) errorEl.style.display = 'none'; if (gateInput) gateInput.style.borderColor = ''; // Disable all unlock buttons document.querySelectorAll('.ukwf-email-unlock-btn, .ukwf-gate-email-btn').forEach(function(b) { b.disabled = true; b.textContent = 'Unlocking...'; }); // Send lead to GHL via server-side PHP AJAX (bypasses webhook workflow) var professionEl = document.querySelector('.ukwf-profile-name'); var professionName = professionEl ? professionEl.textContent.trim().replace(/\s*Tax Write-Offs\s*&?\s*Deductions\s*$/i, '').trim() : ''; var nameParts = professionName.split('/'); var ghlFirstName = nameParts[0] ? nameParts[0].trim() : professionName; var ghlLastName = nameParts[1] ? nameParts[1].trim() : 'Tax Write-Off Finder'; var ajaxUrl = (typeof ukwfConfig !== 'undefined' && ukwfConfig.ajaxUrl) ? ukwfConfig.ajaxUrl : '/wp-admin/admin-ajax.php'; var nonce = (typeof ukwfConfig !== 'undefined' && ukwfConfig.leadNonce) ? ukwfConfig.leadNonce : ''; var formData = new FormData(); formData.append('action', 'ukwf_ghl_lead'); formData.append('nonce', nonce); formData.append('email', email); formData.append('firstName', ghlFirstName); formData.append('lastName', ghlLastName); formData.append('profession', professionName); formData.append('source', 'ukwf-unlock'); formData.append('page', window.location.pathname); fetch(ajaxUrl, { method: 'POST', body: formData }).catch(function() {}); // fire-and-forget // Expand all locked cards immediately ukwfDoUnlock(); } function ukwfDoUnlock() { // Hide the email wall var wall = document.getElementById('ukwf-email-unlock-wall'); if (wall) { wall.style.transition = 'opacity 0.3s ease'; wall.style.opacity = '0'; setTimeout(function() { wall.style.display = 'none'; }, 300); } // Unlock all locked cards instantly — no stagger (stagger caused 4+ second delay for 70+ cards) var lockedCards = document.querySelectorAll('.ukwf-result-card--locked'); lockedCards.forEach(function(card) { // Remove locked state — keep collapsed so user can open each card individually card.classList.remove('ukwf-result-card--locked'); card.classList.add('ukwf-result-card--open'); // Clear any inline styles that might block the toggle var body = card.querySelector('.ukwf-result-body'); if (body) { body.style.display = ''; body.style.maxHeight = ''; } // Remove lock badge var badge = card.querySelector('.ukwf-result-lock-badge'); if (badge) badge.style.display = 'none'; // Replace the locked gate with an unlocked badge var gate = card.querySelector('.ukwf-locked-strategy-gate'); if (gate) { gate.innerHTML = '
    Unlocked — tap to expand
    '; } }); // Show success banner var banner = document.getElementById('ukwf-unlock-banner'); if (banner) { banner.style.display = 'flex'; } // Persist unlock in localStorage so it survives refresh, tab close, and navigation // Uses the same ukwfSetUnlocked() that the book-call path uses, which sets // localStorage key 'ukwf_unlocked' = '1'. The main script block already checks // ukwfIsUnlocked() on page load and calls ukwfUnlockAll() automatically. if (typeof ukwfSetUnlocked === 'function') { ukwfSetUnlocked(); } else { try { localStorage.setItem('ukwf_unlocked', '1'); } catch(err) {} } // Also run the main unlock function to handle any card variants we might miss if (typeof ukwfUnlockAll === 'function') { ukwfUnlockAll(); } } // NOTE: Auto-unlock on page load is handled by the main script block which // checks ukwfIsUnlocked() and calls ukwfUnlockAll(). No DOMContentLoaded // listener needed here (it was broken anyway because LiteSpeed defers scripts // past DOMContentLoaded)./* ── Sticky Save Bar ───────────────────────────────────────────────── */ (function() { var SAVED_KEY = 'ukwf_saved_v2'; var bar = document.getElementById('ukwf-sticky-save-bar'); var countEl = document.getElementById('ukwf-sticky-save-count'); var badgeEl = document.getElementById('ukwf-sticky-cart-badge'); var savingsWrap = document.getElementById('ukwf-sticky-save-savings'); var savingsRange = document.getElementById('ukwf-sticky-savings-range'); if (!bar || !countEl) return;var _prevCount = 0;/* Parse a savings string like "$1,200–$4,500/year" -> {min, max} */ function parseSavings(str) { if (!str) return null; var nums = str.replace(/[^0-9]/g, ' ').trim().split(/\s+/).filter(Boolean); var vals = nums.map(function(n) { return parseInt(n, 10); }).filter(function(n) { return !isNaN(n) && n > 0; }); if (vals.length === 0) return null; if (vals.length === 1) return { min: vals[0], max: vals[0] }; return { min: Math.min.apply(null, vals), max: Math.max.apply(null, vals) }; }/* Format a number as $XK or $X.XM */ function fmtMoney(n) { if (n >= 1000000) return '$' + (n / 1000000).toFixed(1).replace(/\.0$/, '') + 'M'; if (n >= 1000) return '$' + Math.round(n / 1000) + 'K'; return '$' + n.toLocaleString(); }/* Animated count-up for a single element */ function animateCount(el, from, to, duration) { if (from === to) { el.textContent = to; return; } var start = null; function step(ts) { if (!start) start = ts; var progress = Math.min((ts - start) / duration, 1); var ease = 1 - Math.pow(1 - progress, 3); el.textContent = Math.round(from + (to - from) * ease); if (progress < 1) requestAnimationFrame(step); else el.textContent = to; } requestAnimationFrame(step); }function getSaved() { try { return JSON.parse(localStorage.getItem(SAVED_KEY) || '[]'); } catch(e) { return []; } }function updateBar() { var saved = getSaved(); var n = saved.length;/* Count-up animation when count changes */ if (n !== _prevCount) { animateCount(countEl, _prevCount, n, 600); if (badgeEl) animateCount(badgeEl, _prevCount, n, 600); /* Pop animation on bar when count increases */ if (n > _prevCount) { bar.classList.remove('ukwf-sticky-bar-pop'); void bar.offsetWidth; bar.classList.add('ukwf-sticky-bar-pop'); } _prevCount = n; }if (n > 0) { bar.classList.add('ukwf-sticky-save-bar--visible');/* Calculate total savings range */ var totalMin = 0, totalMax = 0, hasSavings = false; saved.forEach(function(item) { var p = parseSavings(item.savings || ''); if (p) { totalMin += p.min; totalMax += p.max; hasSavings = true; } });if (hasSavings && savingsWrap && savingsRange) { var rangeStr = totalMin === totalMax ? fmtMoney(totalMin) : fmtMoney(totalMin) + '–' + fmtMoney(totalMax); savingsRange.textContent = rangeStr; savingsWrap.style.display = ''; } else if (savingsWrap) { savingsWrap.style.display = 'none'; } } else { bar.classList.remove('ukwf-sticky-save-bar--visible'); if (savingsWrap) savingsWrap.style.display = 'none'; } }/* Update whenever a save/unsave happens */ window.addEventListener('ukwfSavedChanged', updateBar); /* Cross-tab sync */ window.addEventListener('storage', function(e) { if (e.key === SAVED_KEY) updateBar(); }); /* Expose globally */ window.ukwfStickyBarRefresh = updateBar; updateBar(); })();/* ── CART DRAWER ────────────────────────────────────────────────────── */ (function() { var SAVED_KEY = 'ukwf_saved_v2'; var drawer = document.getElementById('ukwf-cart-drawer'); var overlay = document.getElementById('ukwf-cart-overlay'); var itemsList = document.getElementById('ukwf-cart-items'); var emptyEl = document.getElementById('ukwf-cart-empty'); var footerEl = document.getElementById('ukwf-cart-footer'); var savingsStrip = document.getElementById('ukwf-cart-savings-strip'); var savingsAmount = document.getElementById('ukwf-cart-savings-amount'); var headerSub = document.getElementById('ukwf-cart-header-sub'); var footerCount = document.getElementById('ukwf-cart-footer-count'); if (!drawer) return;function getSaved() { try { return JSON.parse(localStorage.getItem(SAVED_KEY) || '[]'); } catch(e) { return []; } } function setSaved(arr) { localStorage.setItem(SAVED_KEY, JSON.stringify(arr)); window.dispatchEvent(new CustomEvent('ukwfSavedChanged')); if (typeof window.ukwfStickyBarRefresh === 'function') window.ukwfStickyBarRefresh(); if (typeof window.ukwfSavedBadgeRefresh === 'function') window.ukwfSavedBadgeRefresh(); } function parseSavings(str) { if (!str) return null; var nums = str.replace(/[^0-9]/g, ' ').trim().split(/\s+/).filter(Boolean); var vals = nums.map(function(n){ return parseInt(n,10); }).filter(function(n){ return !isNaN(n) && n > 0; }); if (!vals.length) return null; if (vals.length === 1) return { min: vals[0], max: vals[0] }; return { min: Math.min.apply(null,vals), max: Math.max.apply(null,vals) }; } function fmtMoney(n) { if (n >= 1000000) return '$' + (n/1000000).toFixed(1).replace(/\.0$/,'') + 'M'; if (n >= 1000) return '$' + Math.round(n/1000) + 'K'; return '$' + n.toLocaleString(); } function getCatIcon(cat) { var icons = { 'vehicle':'', 'home':'', 'travel':'', 'equipment':'', 'health':'', 'retirement':'', 'education':'', 'real estate':'' }; var k = (cat || '').toLowerCase(); for (var key in icons) { if (k.indexOf(key) !== -1) return icons[key]; } return ''; } function renderItems() { var saved = getSaved(); var n = saved.length; /* Update header sub */ if (headerSub) headerSub.textContent = n + ' deduction' + (n !== 1 ? 's' : '') + ' saved'; /* Show/hide empty state */ if (emptyEl) emptyEl.style.display = n === 0 ? '' : 'none'; if (footerEl) footerEl.style.display = n === 0 ? 'none' : ''; /* Savings strip */ var totalMin = 0, totalMax = 0, hasSavings = false; saved.forEach(function(item) { var p = parseSavings(item.savings || ''); if (p) { totalMin += p.min; totalMax += p.max; hasSavings = true; } }); if (hasSavings && savingsStrip) { savingsStrip.style.display = ''; var rangeStr = totalMin === totalMax ? fmtMoney(totalMin) : fmtMoney(totalMin) + ' – ' + fmtMoney(totalMax); if (savingsAmount) savingsAmount.textContent = rangeStr; } else if (savingsStrip) { savingsStrip.style.display = 'none'; } /* Footer count */ if (footerCount) footerCount.textContent = n > 0 ? n + ' write-off' + (n !== 1 ? 's' : '') + ' in your list' : ''; /* Remove existing items (keep empty state) */ var existing = itemsList ? itemsList.querySelectorAll('.ukwf-cart-item') : []; existing.forEach(function(el) { el.parentNode.removeChild(el); }); /* Render each item */ saved.forEach(function(item, idx) { var div = document.createElement('div'); div.className = 'ukwf-cart-item'; div.style.animationDelay = (idx * 0.04) + 's'; div.innerHTML = '
    ' + getCatIcon(item.category) + '
    ' + '
    ' + '
    ' + escHtml(item.name || item.slug) + '
    ' + (item.category ? '
    ' + escHtml(item.category) + '
    ' : '') + (item.savings ? '
    ' + escHtml(item.savings) + '/yr
    ' : '') + '
    ' + ''; /* Remove button handler */ div.querySelector('.ukwf-cart-item-remove').addEventListener('click', function() { var slug = this.getAttribute('data-slug'); var arr = getSaved().filter(function(i){ return i.slug !== slug; }); setSaved(arr); /* Animate out */ div.style.transition = 'opacity 0.18s, transform 0.18s'; div.style.opacity = '0'; div.style.transform = 'translateX(20px)'; setTimeout(function() { renderItems(); }, 180); /* Also update save buttons on page */ document.querySelectorAll('.ukwf-card-save-btn[data-slug="' + slug + '"]').forEach(function(btn) { btn.classList.remove('ukwf-card-save-btn--saved'); btn.setAttribute('aria-pressed','false'); var lbl = btn.querySelector('.ukwf-card-save-label'); if (lbl) lbl.textContent = 'Save'; }); }); if (itemsList) itemsList.appendChild(div); }); } function escHtml(s) { return String(s).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); } function escAttr(s) { return String(s).replace(/"/g,'"').replace(/'/g,'''); } /* Open / close */ window.ukwfCartDrawerOpen = function() { renderItems(); if (drawer) drawer.classList.add('ukwf-cart-drawer--open'); if (overlay) overlay.classList.add('ukwf-cart-overlay--open'); document.body.style.overflow = 'hidden'; }; window.ukwfCartDrawerClose = function() { if (drawer) drawer.classList.remove('ukwf-cart-drawer--open'); if (overlay) overlay.classList.remove('ukwf-cart-overlay--open'); document.body.style.overflow = ''; }; window.ukwfCartClearAll = function() { if (!confirm('Remove all saved write-offs?')) return; setSaved([]); renderItems(); }; /* Keyboard close */ document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && drawer && drawer.classList.contains('ukwf-cart-drawer--open')) { window.ukwfCartDrawerClose(); } }); /* Re-render when saves change */ window.addEventListener('ukwfSavedChanged', function() { if (drawer && drawer.classList.contains('ukwf-cart-drawer--open')) { renderItems(); } }); window.addEventListener('storage', function(e) { if (e.key === SAVED_KEY && drawer && drawer.classList.contains('ukwf-cart-drawer--open')) { renderItems(); } }); })();/* ── CARD SAVE BUTTONS ──────────────────────────────────────────────── */ (function() { var SAVED_KEY = 'ukwf_saved_v2';function getSaved() { try { return JSON.parse(localStorage.getItem(SAVED_KEY) || '[]'); } catch(e) { return []; } } function setSaved(arr) { localStorage.setItem(SAVED_KEY, JSON.stringify(arr)); } function isSaved(slug) { return getSaved().some(function(i) { return i.slug === slug; }); } function updateBtn(btn) { var slug = btn.getAttribute('data-slug'); var saved = isSaved(slug); btn.classList.toggle('ukwf-card-save-btn--saved', saved); btn.setAttribute('aria-pressed', saved ? 'true' : 'false'); var label = btn.querySelector('.ukwf-card-save-label'); if (label) label.textContent = saved ? 'Saved' : 'Save'; } function initAllBtns() { document.querySelectorAll('.ukwf-card-save-btn').forEach(function(btn) { updateBtn(btn); btn.addEventListener('click', function(e) { e.stopPropagation(); var slug = btn.getAttribute('data-slug'); var name = btn.getAttribute('data-name'); var cat = btn.getAttribute('data-category') || ''; var savings = btn.getAttribute('data-savings') || ''; var saved = getSaved(); var idx = saved.findIndex(function(i) { return i.slug === slug; }); if (idx === -1) { saved.push({ slug: slug, name: name, category: cat, savings: savings, savedAt: Date.now() }); } else { saved.splice(idx, 1); } setSaved(saved); updateBtn(btn); /* Sync badge and sticky bar */ window.dispatchEvent(new CustomEvent('ukwfSavedChanged')); if (typeof window.ukwfSavedBadgeRefresh === 'function') window.ukwfSavedBadgeRefresh(); if (typeof window.ukwfStickyBarRefresh === 'function') window.ukwfStickyBarRefresh(); }); }); } /* Init on load and re-sync on saved changes from autocomplete */ if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initAllBtns); } else { initAllBtns(); } window.addEventListener('ukwfSavedChanged', function() { document.querySelectorAll('.ukwf-card-save-btn').forEach(updateBtn); }); })();