How LLC Owners Save on Taxes in 2026

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

Hair Color, Chemicals, Backbar Products & Professional Supplies

Professional hair color (Wella, Redken, Schwarzkopf), developer, bleach, toners, keratin treatments, backbar shampoos and conditioners, and other professional products used on clients are fully deductible as cost of goods sold.

Eligibility Requirements
  • Self-employed hair stylist
  • Products used on clients (not personal use)
  • Professional-grade products purchased for business
Example Savings Scenario

A colorist spending $14,400/year on Wella color, developer, toners, and bleach used on clients deducts the full amount — saving $4,752 at 33%.

MERNA Strategy Notes

Keep separate personal and professional product purchases. Only products used on clients are deductible.

Common Mistake: Personal-use hair products (for your own hair) are not deductible even if you are a hair stylist.
Hair Stylist IRC §162

Professional Hair Tools — Shears, Clippers & Blow Dryers

Professional shears ($200-$1,500/pair), clippers, trimmers, blow dryers, flat irons, curling irons, color mixing bowls, foil, and other professional tools are fully deductible.

Eligibility Requirements
  • Self-employed hair stylist
  • Tools used exclusively for business
  • Professional-grade tools (not consumer-grade)
Example Savings Scenario

A hair stylist purchasing a $900 pair of Mizutani shears, a $400 Dyson blow dryer, and $600 in color equipment deducts $1,900 — saving $627 at 33%.

MERNA Strategy Notes

High-end professional shears ($500-$1,500) are a significant deduction. Keep receipts for all tool purchases.

Common Mistake: Consumer-grade tools used for both personal and professional use require a business-use percentage allocation.
Business Expenses IRC §162

Beauty Supplies, Products & Professional Tools Deduction

All professional beauty supplies and tools used in your business are fully deductible. This includes hair color and developer, shampoos and conditioners, styling products, scissors, clippers, trimmers, blow dryers, flat irons, curling irons, capes, towels, gloves, and any other supplies used on clients. Product purchased for resale to clients is also deductible as cost of goods sold.

Eligibility Requirements
  • Supplies used in your beauty business or on clients
  • Self-employed hair stylist, barber, or beauty professional
  • Tools used in your trade
Example Savings Scenario

A hair stylist spending $4,000/year on color, supplies, and tools deducts the full amount, saving $1,200–$1,600 in taxes.

MERNA Strategy Notes

Keep all receipts from beauty supply stores. A dedicated business credit card makes tracking easy and provides an automatic record for tax purposes.

Common Mistake: Products purchased for personal use are not deductible — only supplies used on clients or in your professional work qualify.
Business Expenses IRC §162

Booth Rental & Chair Rental Deduction

If you rent a booth, chair, or suite in a salon or barbershop, your rental fees are fully deductible as a business expense. This is typically the largest deduction for booth renters — most pay $200–$600/week in booth rent, adding up to $10,400–$31,200/year in fully deductible expenses.

Eligibility Requirements
  • Rent a booth, chair, or suite in a salon or barbershop
  • Self-employed (booth renters are independent contractors, not employees)
  • Weekly or monthly rental fees paid to the salon owner
Example Savings Scenario

A hair stylist paying $350/week in booth rent deducts $18,200/year, saving $5,460–$7,280 in taxes.

MERNA Strategy Notes

Booth renters are self-employed — you also qualify for the QBI deduction (23% of net income), Solo 401(k), health insurance deduction, and all other self-employment deductions on top of booth rent.

Common Mistake: If you are an employee of the salon (W-2), you cannot deduct unreimbursed booth or chair fees — only independent contractors (1099) can deduct these costs.
Software Engineer IRC §280A

Home Office Deduction for Remote Software Engineers

Remote software engineers who work from a dedicated home office space can deduct a proportional share of rent, mortgage interest, utilities, and internet. Self-employed only — W-2 employees cannot claim this deduction under current tax law.

Eligibility Requirements
  • Self-employed (1099/freelance) software engineer
  • Dedicated workspace used exclusively and regularly for business
  • Principal place of business or where clients are met
Example Savings Scenario

A freelance developer with a 180 sq ft office in a 1,400 sq ft apartment ($2,800/month rent) deducts $4,334/year in home office expenses.

MERNA Strategy Notes

Use the actual expense method (not simplified $5/sq ft) for larger deductions. Track all home expenses: rent/mortgage, utilities, internet, renters/homeowners insurance.

Common Mistake: W-2 remote employees cannot claim the home office deduction under TCJA 2017. The space must be used exclusively for business.
Home Health Care Business IRC §162, §132(d) Uncle Kam Clients Only

Caregiver Mileage & Vehicle Reimbursement

Home health care businesses incur significant vehicle costs — caregivers drive to client homes, supervisors conduct home visits, and owners travel to meetings and training. The 2026 IRS standard mileage rate is 70 cents per mile for business use. Agencies can reimburse caregivers for mileage through an accountable plan, making the reimbursement tax-free to the employee and fully deductible to the business. Alternatively, actual vehicle expenses (fuel, insurance, maintenance, depreciation) can be deducted based on business-use percentage.

Eligibility Requirements
  • Business miles driven to client homes
  • Supervisor home visit mileage
  • Training, licensing, and continuing education travel
  • Caregiver mileage reimbursements through accountable plan
  • Owner/operator vehicle used for business
Example Savings Scenario

A home health care agency owner driving 20,000 business miles per year deducts $14,000 at the 2026 rate of 70 cents per mile, saving $5,180 in taxes at 37%.

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
Business Expenses IRC §162 Uncle Kam Clients Only

Office Supplies & Materials Deduction

Any supplies you purchase and use in your business are fully deductible in the year purchased. This includes paper, pens, printer ink and toner, folders, binders, postage, envelopes, labels, staples, tape, and any other consumable materials used in your work.

Eligibility Requirements
  • Self-employed, freelancer, or business owner
  • Supplies used for business purposes
  • Consumed or used up within the tax year
Example Savings Scenario

A small business owner spending $1,200/year on office supplies saves $360–$480 in taxes depending on their bracket.

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
Home Health Care Business IRC §199A Uncle Kam Clients Only

QBI Deduction (20% Pass-Through Deduction) for Home Care Agencies

Home health care businesses structured as sole proprietorships, partnerships, LLCs, or S-Corps may qualify for the Qualified Business Income (QBI) deduction under IRC §199A — a 20% deduction on net business income. For a home care agency generating $200,000 in net profit, this deduction alone saves $14,800 in federal taxes. Home health care is generally NOT classified as a Specified Service Trade or Business (SSTB), which means the income limitation phase-out that applies to doctors and lawyers typically does not apply — making this deduction available at higher income levels.

Eligibility Requirements
  • Home health care agency structured as LLC, S-Corp, or sole proprietor
  • Taxable income below $197,300 (single) or $394,600 (married) — full deduction
  • Income above thresholds: W-2 wage limitation applies
  • Home health care is generally NOT an SSTB — no income cap for most agencies
Example Savings Scenario

A home health care agency owner with $250,000 in net business income takes a $50,000 QBI deduction, saving $18,500 in federal taxes at 37%.

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
Therapist IRC §401(k), §408(k) Uncle Kam Clients Only

Solo 401(k) and SEP-IRA for Therapists

Therapists in private practice can make tax-deductible retirement contributions that dramatically reduce taxable income. A Solo 401(k) allows contributions of up to $70,000/year ($77,500 if age 50+) in 2026 as both employee and employer. A SEP-IRA allows contributions of up to 20% of net self-employment income (max $70,000). Both reduce taxable income dollar-for-dollar and grow tax-deferred until retirement.

Eligibility Requirements
  • Self-employed therapist with net income from private practice
  • Solo 401(k): no full-time employees other than spouse
  • SEP-IRA: available even with part-time employees
  • Must open Solo 401(k) by December 31 to contribute for the current year
Example Savings Scenario

A therapist earning $100,000 net who contributes $30,000 to a Solo 401(k) reduces taxable income to $70,000, saving $8,400 in federal taxes at a 28% effective rate — plus the money grows tax-deferred.

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
Retirement IRC §412 Uncle Kam Clients Only

Defined Benefit Pension Plan

A defined benefit plan allows high-income self-employed individuals and business owners to contribute $200,000–$300,000 per year based on actuarial calculations, far exceeding 401(k) limits.

Eligibility Requirements
  • Self-employed or small business owner
  • High income ($300,000+) for maximum benefit
  • Actuarial calculation required annually
  • Commitment to fund the plan each year
Example Savings Scenario

A physician earning $500,000 contributes $265,000 to a defined benefit plan, saving $98,050 in taxes at a 37% rate — far exceeding the $69,000 Solo 401(k) limit.

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
Musician IRC §1362, §3121 Uncle Kam Clients Only

S-Corp Election for Musicians

Musicians earning $80,000+ in net self-employment income can elect S-Corp status to reduce self-employment (SE) tax. As an S-Corp owner, you pay SE tax only on your salary — not on distributions. This can save $10,000–$20,000/year at higher income levels.

Eligibility Requirements
  • Net self-employment income of $80,000+
  • Willing to pay yourself a reasonable salary
  • File Form 2553 to elect S-Corp status (deadline: March 15)
Example Savings Scenario

A musician with $150,000 net income pays $21,240 in SE tax as a sole proprietor. With an S-Corp and $70,000 salary, SE tax drops to $9,912 — saving $11,328/year.

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
Musician IRC §401(k), §408(k) Uncle Kam Clients Only

Solo 401(k) and SEP-IRA for Musicians

Self-employed musicians can make tax-deductible retirement contributions that dramatically reduce taxable income. A Solo 401(k) allows contributions of up to $70,000/year ($77,500 if age 50+) as both employee and employer. A SEP-IRA allows contributions of up to 20% of net self-employment income (max $70,000).

Eligibility Requirements
  • Self-employed musician with net income from music
  • Solo 401(k): no full-time employees other than spouse
  • SEP-IRA: available even with part-time employees
  • Must open Solo 401(k) by December 31 to contribute for the current year
Example Savings Scenario

A musician earning $80,000 net who contributes $20,000 to a Solo 401(k) reduces taxable income to $60,000, saving $7,000 in federal taxes at a 35% effective rate.

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
Musician IRC §162, §167 Uncle Kam Clients Only

Sync Licensing, Royalty Income & Music Publishing Deductions

Musicians who earn income from sync licensing (TV, film, commercials), streaming royalties (Spotify, Apple Music, YouTube), and music publishing can deduct all direct costs of generating that income. This includes music attorney fees for licensing negotiations, copyright registration fees ($65 per work), music distribution platform fees (DistroKid, TuneCore, CD Baby), PRO membership fees (ASCAP, BMI, SESAC), and any costs related to pitching music for sync placements.

Eligibility Requirements
  • Self-employed musician earning royalty or licensing income
  • Expenses directly related to generating the licensing/royalty income
  • Music attorney fees for licensing agreements
  • Distribution and PRO membership fees
Example Savings Scenario

A musician earning $30,000 in sync licensing who pays $3,000 in music attorney fees, $500 in copyright registrations, and $200 in distribution fees deducts $3,700, saving $1,295 at 35%.

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 Hair Stylists Don't Know

Every tool, supply, and product you purchase for client services is a fully deductible business expense.

Continuing education, licensing renewal, and professional development courses are 100% deductible.

If you drive to client locations, every mile is deductible — the 2026 standard mileage rate is 70 cents per mile.

Who Uses This Strategy

This write-off is commonly used by the following taxpayer profiles. Click to see all strategies for your situation.

Common Questions for Hair Stylists

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

What tax deductions can a hair stylist claim?
Hair stylists can deduct scissors, clippers, styling tools, hair products, booth rental fees, continuing education, cosmetology license renewal, uniforms, and professional liability insurance. Most stylists miss $5,000\u2013$15,000 in deductions.
Can a hair stylist deduct booth rental fees?
Yes \u2014 booth rental fees paid to a salon are fully deductible as a business expense. If you rent a booth, you are self-employed and can deduct all ordinary business expenses including supplies, equipment, and continuing education.
Should a hair stylist form an LLC or S-Corp?
An LLC provides liability protection. An S-Corp election saves stylists earning $50,000+ approximately $3,000\u2013$10,000/year in self-employment taxes. This is especially valuable for stylists who own their own salon.
Can a hair stylist deduct hair products and supplies?
Yes \u2014 shampoo, conditioner, hair color, styling products, and other supplies used exclusively for client services are fully deductible as business expenses. Keep receipts and separate business purchases from personal use.
Can a hair stylist deduct continuing education and cosmetology courses?
Yes \u2014 all continuing education, advanced styling courses, and license renewal fees are fully deductible as business expenses. This includes travel to attend hair shows and industry events.
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 $6,000–$35,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); }); })();