RSU Tax Calculator 2025/2026 —
Free Equity Compensation Optimizer
See your exact federal, state & FICA tax on every RSU vest — and close the withholding gap before it blindsides you at filing.
Presets for Meta, Google, Amazon, Apple, NVIDIA & Microsoft.
⚡ TL;DR — What Does This Tool Do?
This free RSU Tax Calculator instantly computes how much of your restricted stock unit vesting
income goes to federal taxes (10–37%), state taxes (0–13.3%), Social Security (6.2% up to $184,500
wage base), and Medicare (1.45% + 0.9% above $200K) — then shows your exact withholding gap.
Results update in seconds for all 50 states, with company-specific vesting schedule presets
for Meta, Google, Amazon, Apple, NVIDIA, and Microsoft. Educational purposes only — discuss results with your CPA.
RSU & Equity Compensation Optimizer
Tax Year 2025/2026 · IRS-Cited Formulas · All calculations run locally in your browser.
📊 Your RSU Tax Breakdown
Federal & FICA Taxes on RSU Income
Withholding Analysis
Tax Breakdown
📅 Full Vest Schedule Calendar
Update FMV for each vest date for precision
| Vest Date | Year | Shares | Gross Income | Net After Tax | Eff. Rate |
|---|
Vest Schedule — Gross vs. Net
Unlock Deeper Analysis
Available with Premium ($29/month). Cancel anytime. 30-day money-back.
- 🔒Sell vs. Hold Analyzer — Model LTCG tax treatment vs. selling at vest.
- 🔒Mega Backdoor Roth Optimizer — Maximize §415(c) after-tax Roth contributions.
- 🔒Multi-Grant Consolidator — Stack up to 10 RSU grants, see combined tax exposure.
- 🔒Quarterly Estimated Tax Calculator — Exact Form 1040-ES amounts per quarter.
30-day money-back · Cancel anytime
💾 Saved Scenarios
Simple, Transparent Pricing
- ✓ Federal + state + FICA tax breakdown
- ✓ Withholding gap calculation
- ✓ Vest schedule calendar
- ✓ Company presets (Meta, Google, Amazon, Apple, NVIDIA, MSFT)
- ✓ Tax charts + PDF report
- ✓ No login required
- ✓ Everything in Free
- ✓ Sell vs. Hold Analyzer
- ✓ Mega Backdoor Roth Optimizer
- ✓ Multi-Grant Consolidator
- ✓ Quarterly Estimated Tax Calculator
- ✓ 4-Year Projection Chart
- ✓ Unlimited scenario saves
No commitment · Cancel anytime
'use strict';
const TAX_2026={brackets:{single:[{min:0,max:12400,rate:0.10},{min:12400,max:50400,rate:0.12},{min:50400,max:105700,rate:0.22},{min:105700,max:201775,rate:0.24},{min:201775,max:256225,rate:0.32},{min:256225,max:640600,rate:0.35},{min:640600,max:Infinity,rate:0.37},],mfj:[{min:0,max:24800,rate:0.10},{min:24800,max:100800,rate:0.12},{min:100800,max:211400,rate:0.22},{min:211400,max:410300,rate:0.24},{min:410300,max:521100,rate:0.32},{min:521100,max:781700,rate:0.35},{min:781700,max:Infinity,rate:0.37},],hoh:[{min:0,max:18750,rate:0.10},{min:18750,max:79200,rate:0.12},{min:79200,max:105700,rate:0.22},{min:105700,max:201775,rate:0.24},{min:201775,max:256225,rate:0.32},{min:256225,max:640600,rate:0.35},{min:640600,max:Infinity,rate:0.37},],mfs:[{min:0,max:12400,rate:0.10},{min:12400,max:50400,rate:0.12},{min:50400,max:105700,rate:0.22},{min:105700,max:197300,rate:0.24},{min:197300,max:250525,rate:0.32},{min:250525,max:375800,rate:0.35},{min:375800,max:Infinity,rate:0.37},],},
stdDeduction:{single:16100,mfj:32200,hoh:24150,mfs:8050},
ltcg:{single:[{min:0,max:50000,rate:0.00},{min:50000,max:554150,rate:0.15},{min:554150,max:Infinity,rate:0.20},],mfj:[{min:0,max:100000,rate:0.00},{min:100000,max:623050,rate:0.15},{min:623050,max:Infinity,rate:0.20},],hoh:[{min:0,max:67000,rate:0.00},{min:67000,max:554150,rate:0.15},{min:554150,max:Infinity,rate:0.20},],mfs:[{min:0,max:50000,rate:0.00},{min:50000,max:311525,rate:0.15},{min:311525,max:Infinity,rate:0.20},],},
fica:{ssRate:0.062,ssWageBase:184500,medicareRate:0.0145,addlMedicareRate:0.009,addlMedicareThreshold:{single:200000,mfj:250000,hoh:200000,mfs:125000},},
niit:{rate:0.038,threshold:{single:200000,mfj:250000,hoh:200000,mfs:125000},},
suppWithholding:{below1M:0.22,above1M:0.37,},
retirement:{k401Employee:23500,k401CatchUp:31000,k401Total415c:70000,hsaIndividual:4300,hsaFamily:8550,},};
const STATE_RATES={'AL':{name:'Alabama',rate:0.050},'AK':{name:'Alaska',rate:0.000},'AZ':{name:'Arizona',rate:0.025},'AR':{name:'Arkansas',rate:0.047},'CA':{name:'California',rate:0.093,note:'+1% Mental Health (>$1M), SDI ~1%'},'CO':{name:'Colorado',rate:0.044},'CT':{name:'Connecticut',rate:0.0699},'DE':{name:'Delaware',rate:0.066},'FL':{name:'Florida',rate:0.000},'GA':{name:'Georgia',rate:0.0549},'HI':{name:'Hawaii',rate:0.110},'ID':{name:'Idaho',rate:0.058},'IL':{name:'Illinois',rate:0.0495},'IN':{name:'Indiana',rate:0.0305},'IA':{name:'Iowa',rate:0.060},'KS':{name:'Kansas',rate:0.057},'KY':{name:'Kentucky',rate:0.040},'LA':{name:'Louisiana',rate:0.0425},'ME':{name:'Maine',rate:0.0715},'MD':{name:'Maryland',rate:0.0575},'MA':{name:'Massachusetts',rate:0.050,note:'+4% surtax on income >$1M'},'MI':{name:'Michigan',rate:0.0425},'MN':{name:'Minnesota',rate:0.0985},'MS':{name:'Mississippi',rate:0.047},'MO':{name:'Missouri',rate:0.048},'MT':{name:'Montana',rate:0.059},'NE':{name:'Nebraska',rate:0.0584},'NV':{name:'Nevada',rate:0.000},'NH':{name:'New Hampshire',rate:0.000},'NJ':{name:'New Jersey',rate:0.1075},'NM':{name:'New Mexico',rate:0.059},'NY':{name:'New York',rate:0.109,note:'+NYC surcharge ~3.9% if NYC resident'},'NC':{name:'North Carolina',rate:0.045},'ND':{name:'North Dakota',rate:0.025},'OH':{name:'Ohio',rate:0.035},'OK':{name:'Oklahoma',rate:0.0475},'OR':{name:'Oregon',rate:0.099},'PA':{name:'Pennsylvania',rate:0.0307},'RI':{name:'Rhode Island',rate:0.0599},'SC':{name:'South Carolina',rate:0.064},'SD':{name:'South Dakota',rate:0.000},'TN':{name:'Tennessee',rate:0.000},'TX':{name:'Texas',rate:0.000},'UT':{name:'Utah',rate:0.0465},'VT':{name:'Vermont',rate:0.0875},'VA':{name:'Virginia',rate:0.0575},'WA':{name:'Washington',rate:0.000,note:'7% capital gains tax on gains >$262K (WA law, not income tax)'},'WV':{name:'West Virginia',rate:0.065},'WI':{name:'Wisconsin',rate:0.0765},'WY':{name:'Wyoming',rate:0.000},'DC':{name:'Washington D.C.',rate:0.1075},'OTHER':{name:'Other / No State',rate:0.000},};
const COMPANY_PRESETS={meta:{name:'Meta (META)',ticker:'META',color:'#0866FF',suggestedPrice:525,vestType:'quarterly_after_cliff',cliffMonths:12,vestYears:4,annualPcts:[25,25,25,25],vestMonths:[3,6,9,12],description:'4-year quarterly vesting | 25% cliff at 12 months | then 1/16th per quarter',note:'RSU Income Tax (Ordinary). Refresher grants common at L5+.',typicalGrants:{'L4 (New Grad)':150000,'L5 (Mid)':300000,'L6 (Senior)':600000},},google:{name:'Google / Alphabet (GOOGL)',ticker:'GOOGL',color:'#EA4335',suggestedPrice:165,vestType:'quarterly_after_cliff',cliffMonths:12,vestYears:4,annualPcts:[25,25,25,25],vestMonths:[3,6,9,12],description:'4-year quarterly vesting | 25% cliff at 12 months | then 1/16th per quarter',note:'Perf bonus RSUs added annually for strong performers.',typicalGrants:{'L4':150000,'L5':300000,'L6':500000},},amazon:{name:'Amazon (AMZN)',ticker:'AMZN',color:'#FF9900',suggestedPrice:192,vestType:'amazon_backloaded',cliffMonths:0,vestYears:4,annualPcts:[5,15,40,40],vestMonths:[3,6,9,12],description:'Back-loaded 5-15-40-40 vesting | Quarterly: May, Aug, Nov, Feb | No cliff',note:'Signing bonus often offsets Y1/Y2 lower equity. RSU-to-cash option available for eligible employees.',typicalGrants:{'SDE I':100000,'SDE II':175000,'SDE III':350000},},apple:{name:'Apple (AAPL)',ticker:'AAPL',color:'#555555',suggestedPrice:198,vestType:'semiannual',cliffMonths:0,vestYears:4,annualPcts:[25,25,25,25],vestMonths:[6,12],description:'4-year semi-annual vesting | 12.5% every 6 months | Typical vest months: March & September',note:'Performance RSUs (PRSUs) may supplement base grants for top performers.',typicalGrants:{'ICT2':80000,'ICT3':180000,'ICT4':380000},},nvidia:{name:'NVIDIA (NVDA)',ticker:'NVDA',color:'#76B900',suggestedPrice:110,vestType:'quarterly_after_cliff',cliffMonths:12,vestYears:4,annualPcts:[25,25,25,25],vestMonths:[3,6,9,12],description:'4-year quarterly vesting | 25% at 12 months | then 1/16th per quarter',note:'Annual refresher grants typical at all levels. NVDA growth creates significant tax complexity.',typicalGrants:{'L4':200000,'L5':450000,'L6':900000},},microsoft:{name:'Microsoft (MSFT)',ticker:'MSFT',color:'#00A4EF',suggestedPrice:430,vestType:'quarterly_after_cliff',cliffMonths:12,vestYears:4,annualPcts:[25,25,25,25],vestMonths:[3,6,9,12],description:'4-year quarterly vesting | 25% at 12 months | Vest dates: Apr, Jul, Oct, Jan',note:'Stock awards reviewed annually. ESPP also available (15% discount, 6-month offering periods).',typicalGrants:{'SDE II':120000,'SDE III':260000,'Principal SDE':520000},},};
function fmt$(n,decimals=0){if(isNaN(n)||n===null)return'$0';return new Intl.NumberFormat('en-US',{style:'currency',currency:'USD',minimumFractionDigits:decimals,maximumFractionDigits:decimals,}).format(n)}
function fmtPct(n,decimals=1){return(n*100).toFixed(decimals)+'%'}
function fmtNum(n,decimals=0){return new Intl.NumberFormat('en-US',{minimumFractionDigits:decimals,maximumFractionDigits:decimals,}).format(n)}
function calcFederalTax(taxableIncome,filingStatus){if(taxableIncome<=0)return 0;const brackets=TAX_2026.brackets[filingStatus]||TAX_2026.brackets.single;let tax=0;for(const b of brackets){if(taxableIncome<=b.min)break;const taxableInBracket=Math.min(taxableIncome,b.max)-b.min;tax+=taxableInBracket*b.rate} return tax} function calcMarginalRate(existingTaxableIncome,rsuIncome,filingStatus){const brackets=TAX_2026.brackets[filingStatus]||TAX_2026.brackets.single;const totalIncome=existingTaxableIncome+rsuIncome;for(let i=brackets.length-1;i>=0;i--){if(totalIncome>brackets[i].min)return brackets[i].rate} return brackets[0].rate}
function calcFICA(rsuWages,otherWages,filingStatus){const{ssRate,ssWageBase,medicareRate,addlMedicareRate,addlMedicareThreshold}=TAX_2026.fica;const threshold=addlMedicareThreshold[filingStatus]||addlMedicareThreshold.single;
const totalWages=rsuWages+otherWages;
const ssOnOther=Math.min(otherWages,ssWageBase)*ssRate;const ssOnRSU=Math.max(0,Math.min(totalWages,ssWageBase)-otherWages)*ssRate;const ssAlreadyMet=otherWages>=ssWageBase;
const medicareOnRSU=rsuWages*medicareRate;
const addlMedicareWages=Math.max(0,totalWages-threshold);const addlMedicareOnOther=Math.max(0,Math.min(otherWages,addlMedicareWages))*addlMedicareRate;const addlMedicareOnRSU=Math.max(0,addlMedicareWages-Math.max(0,otherWages-threshold))*addlMedicareRate;
return{ss:ssOnRSU,medicare:medicareOnRSU,addlMedicare:addlMedicareOnRSU,total:ssOnRSU+medicareOnRSU+addlMedicareOnRSU,ssAlreadyMet,}}
function calcStateTax(rsuIncome,stateCode,totalIncome=0){const state=STATE_RATES[stateCode];if(!state||state.rate===0)return 0;let stateTax=rsuIncome*state.rate;if(stateCode==='CA'&&totalIncome>1000000){stateTax+=Math.min(rsuIncome,totalIncome-1000000)*0.01} return stateTax}
function calcNIIT(capitalGainAmount,totalAGI,filingStatus){const threshold=TAX_2026.niit.threshold[filingStatus]||TAX_2026.niit.threshold.single;const niitBase=Math.max(0,Math.min(capitalGainAmount,totalAGI-threshold));return niitBase*TAX_2026.niit.rate}
function calcLTCG(capitalGain,ordinaryIncome,filingStatus){if(capitalGain<=0)return{ltcgTax:0,niit:0,effectiveRate:0};const brackets=TAX_2026.ltcg[filingStatus]||TAX_2026.ltcg.single;const totalForLTCG=ordinaryIncome+capitalGain;let ltcgTax=0;for(const b of brackets){const taxableInBracket=Math.max(0,Math.min(totalForLTCG,b.max)-Math.max(ordinaryIncome,b.min));ltcgTax+=taxableInBracket*b.rate} const niit=calcNIIT(capitalGain,ordinaryIncome+capitalGain,filingStatus);const effectiveRate=capitalGain>0?(ltcgTax+niit)/capitalGain:0;return{ltcgTax,niit,effectiveRate}}
function calcRSU(inputs){const{shares,fmvAtVest,otherW2Income,filingStatus,stateCode,k401Contribution,hsaContribution,otherDeductions,}=inputs;
const rsuGross=shares*fmvAtVest;
const totalGross=rsuGross+otherW2Income;
const stdDed=TAX_2026.stdDeduction[filingStatus]||TAX_2026.stdDeduction.single;const deductions=stdDed+(k401Contribution||0)+(hsaContribution||0)+(otherDeductions||0);
const taxableOther=Math.max(0,otherW2Income-deductions);const taxableTotal=Math.max(0,totalGross-deductions);const taxableRSU=taxableTotal-taxableOther;
const federalTaxTotal=calcFederalTax(taxableTotal,filingStatus);const federalTaxOther=calcFederalTax(taxableOther,filingStatus);const federalTaxOnRSU=federalTaxTotal-federalTaxOther;
const marginalRate=calcMarginalRate(taxableOther,taxableRSU,filingStatus);
const fica=calcFICA(rsuGross,otherW2Income,filingStatus);
const stateTax=calcStateTax(rsuGross,stateCode,totalGross);
const suppRate=rsuGross<=TAX_2026.suppWithholding.below1M?TAX_2026.suppWithholding.below1M:TAX_2026.suppWithholding.above1M;const federalWithheld=rsuGross*suppRate;const ssWithheld=fica.ss;const medicareWithheld=fica.medicare;const totalTaxOnRSU=federalTaxOnRSU+fica.total+stateTax;const netProceeds=rsuGross-totalTaxOnRSU;const totalWithheld=federalWithheld+ssWithheld+medicareWithheld;const withholdingGap=totalTaxOnRSU-totalWithheld;const effectiveRate=rsuGross>0?totalTaxOnRSU/rsuGross:0;
return{rsuGross,totalGross,stdDeduction:stdDed,taxableRSU,federalTaxOnRSU,marginalRate,fica,stateTax,totalTaxOnRSU,netProceeds,federalWithheld,ssWithheld,medicareWithheld,totalWithheld,withholdingGap,effectiveRate,suppRate,}}
function generateVestSchedule(inputs,preset){const{shares,fmvAtVest,grantDateStr,otherW2Income,filingStatus,stateCode}=inputs;const schedule=[];const startDate=grantDateStr?new Date(grantDateStr):new Date;
if(preset==='amazon'){const annual=[0.05,0.15,0.40,0.40];const qtrDates=[5,8,11,2];let event=0;for(let yr=0;yr<4;yr++){for(let q=0;q<4;q++){const pct=annual[yr]/4;const vestShares=Math.round(shares*pct);const vestDate=new Date(startDate);vestDate.setFullYear(startDate.getFullYear+yr+(q>=3?1:0));vestDate.setMonth(qtrDates[q]-1);const vestGross=vestShares*fmvAtVest;const tax=calcRSU({.inputs,shares:vestShares});schedule.push({event:++event,date:vestDate.toLocaleDateString('en-US',{year:'numeric',month:'short',day:'numeric'}),pct:pct*100,shares:vestShares,gross:vestGross,netAfterTax:tax.netProceeds,effectiveRate:tax.effectiveRate,year:yr+1,})}}}else if(preset==='semiannual'){const totalVests=8;const pct=1/totalVests;for(let i=0;i
const employeePreTax=Math.min(k401Contribution||0,isCatchUp?k401CatchUp:k401Employee);const employerMatchAmount=(employerMatch||0)*otherW2Income;const maxAfterTax=Math.max(0,k401Total415c-employeePreTax-employerMatchAmount);
const annualReturn=0.07;const years=30;const growthFactor=Math.pow(1+annualReturn,years);
return{employeePreTax,employerMatchAmount,maxAfterTaxContribution:maxAfterTax,totalWithMegaBackdoor:employeePreTax+maxAfterTax,projectedRothValue:maxAfterTax*growthFactor,projectedTaxSavings:maxAfterTax*growthFactor*0.30,breakEven:'Immediately if marginal rate today ≤ expected rate at retirement',}}
let charts={};
function destroyChart(id){if(charts[id]){charts[id].destroy;delete charts[id]}}
function renderTaxDonutChart(result){destroyChart('donut');const ctx=document.getElementById('taxDonutChart');if(!ctx)return;const data={federal:result.federalTaxOnRSU,state:result.stateTax,ss:result.fica.ss,medicare:result.fica.medicare+result.fica.addlMedicare,};charts.donut=new Chart(ctx,{type:'doughnut',data:{labels:['Federal Income Tax','State Income Tax','Social Security','Medicare/NIIT','Net Proceeds'],datasets:[{data:[data.federal,data.state,data.ss,data.medicare,result.netProceeds],backgroundColor:['#EF4444','#F97316','#FBBF24','#60A5FA','#22C55E'],borderWidth:2,borderColor:'#1e293b',}],},options:{responsive:!0,plugins:{legend:{position:'bottom',labels:{color:'#94a3b8',font:{size:12}}},tooltip:{callbacks:{label:(ctx)=>` ${ctx.label}: ${fmt$(ctx.raw)} (${fmtPct(ctx.raw / result.rsuGross)})`,},},},},})}
function renderVestBarChart(schedule){destroyChart('vestbar');const ctx=document.getElementById('vestBarChart');if(!ctx)return;const labels=schedule.map(v=>v.date);charts.vestbar=new Chart(ctx,{type:'bar',data:{labels,datasets:[{label:'Net Proceeds',data:schedule.map(v=>v.netAfterTax),backgroundColor:'#22C55E',borderRadius:4,},{label:'Taxes',data:schedule.map(v=>v.gross-v.netAfterTax),backgroundColor:'#EF4444',borderRadius:4,},],},options:{responsive:!0,scales:{x:{stacked:!0,ticks:{color:'#94a3b8',maxRotation:45},grid:{color:'#1e293b'}},y:{stacked:!0,ticks:{color:'#94a3b8',callback:v=>fmt$(v)},grid:{color:'#334155'}},},plugins:{legend:{position:'bottom',labels:{color:'#94a3b8'}},tooltip:{callbacks:{label:(ctx)=>` ${ctx.dataset.label}: ${fmt$(ctx.raw)}`},},},},})}
function renderSellVsHoldChart(svh){destroyChart('svh');const ctx=document.getElementById('svhChart');if(!ctx)return;charts.svh=new Chart(ctx,{type:'bar',data:{labels:['Sell at Vest','Hold 12+ Months'],datasets:[{label:'Net Proceeds',data:[svh.sellImmediately.net,svh.holdForLTCG.net],backgroundColor:['#22C55E','#3B82F6'],borderRadius:6},{label:'Total Tax',data:[svh.sellImmediately.tax,svh.holdForLTCG.tax],backgroundColor:['#EF444488','#F97316AA'],borderRadius:6},],},options:{responsive:!0,scales:{x:{ticks:{color:'#94a3b8'},grid:{color:'#1e293b'}},y:{ticks:{color:'#94a3b8',callback:v=>fmt$(v)},grid:{color:'#334155'}},},plugins:{legend:{position:'bottom',labels:{color:'#94a3b8'}},tooltip:{callbacks:{label:(ctx)=>` ${ctx.dataset.label}: ${fmt$(ctx.raw)}`}},},},})}
let isPremium=!1;
function checkPremium{try{isPremium=sessionStorage.getItem('bsf_premium')==='true'}catch(_){isPremium=!1} return isPremium}
function showPremiumModal(featureName){const modal=document.getElementById('premiumModal');const featureEl=document.getElementById('premiumFeatureName');if(featureEl)featureEl.textContent=featureName;if(modal)modal.classList.remove('hidden');}
function closePremiumModal{const modal=document.getElementById('premiumModal');if(modal)modal.classList.add('hidden');}
const STORAGE_KEY='bsf_rsu_scenarios';
function saveScenario(inputs,result){try{const name=prompt('Name this scenario (e.g, "Q3 2026 Vest"):');if(!name)return;const scenarios=JSON.parse(localStorage.getItem(STORAGE_KEY)||'[]');scenarios.push({name,date:new Date.toLocaleDateString,inputs,result:{netProceeds:result.netProceeds,effectiveRate:result.effectiveRate,rsuGross:result.rsuGross}});if(scenarios.length>10)scenarios.shift;localStorage.setItem(STORAGE_KEY,JSON.stringify(scenarios));renderSavedScenarios;showToast('Scenario saved!')}catch(_){showToast('Could not save — storage unavailable.')}}
function renderSavedScenarios{try{const el=document.getElementById('savedScenariosList');if(!el)return;const scenarios=JSON.parse(localStorage.getItem(STORAGE_KEY)||'[]');if(scenarios.length===0){el.innerHTML='
No saved scenarios yet.
';return} el.innerHTML=scenarios.map((s,i)=>`
`).join('')}catch(_){}}
function generatePDF(result,inputs){document.title=`RSU Tax Analysis — ${new Date.toLocaleDateString} — BusinessSkillForge.com`;window.print}
function showToast(msg,type='success'){const toast=document.createElement('div');toast.className=`toast fixed bottom-6 right-6 px-4 py-3 rounded-lg text-white text-sm z-50 ${type === 'error' ? 'bg-red-600': 'bg-emerald-600'}`;toast.textContent=msg;document.body.appendChild(toast);setTimeout(=>toast.remove,3000)}
function showSpinner(show){const el=document.getElementById('calcSpinner');if(el)el.classList.toggle('hidden',!show);}
function setResultVisibility(show){const el=document.getElementById('resultsSection');if(el)el.classList.toggle('hidden',!show);}
function renderWithholdingGapWarning(gap){const el=document.getElementById('withholdingGapWarning');if(!el)return;if(gap>0){el.innerHTML=`
Your employer is withholding only ${fmtPct(TAX_2026.suppWithholding.below1M)} (federal supplemental rate) but your estimated marginal rate is higher. You may owe ${fmt$(gap)} at tax filing time. Consider making quarterly estimated tax payments or adjusting your W-4 to avoid an underpayment penalty. IRS Estimated Tax Guide →
`;el.classList.remove('hidden')}else{el.classList.add('hidden')}}
let lastResult=null;let lastInputs=null;
function renderResults(result,inputs,schedule){lastResult=result;lastInputs=inputs;
const set=(id,val)=>{const el=document.getElementById(id);if(el)el.textContent=val};set('res-gross',fmt$(result.rsuGross));set('res-federal',fmt$(result.federalTaxOnRSU));set('res-marginal',fmtPct(result.marginalRate));set('res-state',fmt$(result.stateTax));set('res-ss',fmt$(result.fica.ss));set('res-medicare',fmt$(result.fica.medicare));set('res-addlMedicare',fmt$(result.fica.addlMedicare));set('res-totalTax',fmt$(result.totalTaxOnRSU));set('res-effectiveRate',fmtPct(result.effectiveRate));set('res-withheld',fmt$(result.federalWithheld));set('res-gap',fmt$(result.withholdingGap));set('res-net',fmt$(result.netProceeds));set('res-suppRate',fmtPct(result.suppRate));
const gapEl=document.getElementById('res-gap');if(gapEl)gapEl.className=result.withholdingGap>0?'value text-amber-400 font-bold text-xl':'value text-emerald-400 font-bold text-xl';
renderTaxDonutChart(result);renderVestBarChart(schedule);
renderWithholdingGapWarning(result.withholdingGap);
const ssNotice=document.getElementById('ssWageBaseNotice');if(ssNotice){ssNotice.textContent=result.fica.ssAlreadyMet?`✓ Social Security wage base ($${fmtNum(TAX_2026.fica.ssWageBase)}) already met — no additional SS tax on RSU income.`:`Social Security applies up to $${fmtNum(TAX_2026.fica.ssWageBase)} wage base.`;ssNotice.className=result.fica.ssAlreadyMet?'text-xs text-emerald-400 mt-1':'text-xs text-slate-400 mt-1'}
renderVestScheduleTable(schedule);
setResultVisibility(!0);document.getElementById('resultsSection')?.scrollIntoView({behavior:'smooth',block:'start'})}
function renderVestScheduleTable(schedule){const tbody=document.querySelector('#vestScheduleTable tbody');if(!tbody)return;tbody.innerHTML=schedule.map(v=>`
`).join('')}
function readInputs{const get=(id)=>document.getElementById(id)?.value||'';const getNum=(id,def=0)=>parseFloat(get(id).replace(/,/g,''))||def;
const inputs={company:get('inp-company'),grantName:get('inp-grantName')||'RSU Grant',shares:getNum('inp-shares'),fmvAtVest:getNum('inp-fmvVest'),fmvAtGrant:getNum('inp-fmvGrant'),targetPrice:getNum('inp-targetPrice'),grantDateStr:get('inp-grantDate'),otherW2Income:getNum('inp-otherIncome'),filingStatus:get('inp-filingStatus')||'single',stateCode:get('inp-state')||'CA',k401Contribution:getNum('inp-401k'),hsaContribution:getNum('inp-hsa'),otherDeductions:getNum('inp-otherDeductions'),employerMatch:getNum('inp-employerMatch',0.04),age:getNum('inp-age',35),};
return inputs}
function validateInputs(inputs){const errors=[];if(!inputs.shares||inputs.shares<=0)errors.push('Number of shares must be greater than 0.');if(!inputs.fmvAtVest||inputs.fmvAtVest<=0)errors.push('FMV at vest must be greater than 0.');if(inputs.otherW2Income<0)errors.push('Other income cannot be negative.');return errors} function showErrors(errors){const el=document.getElementById('formErrors');if(!el)return;if(errors.length===0){el.classList.add('hidden');return} el.innerHTML=`
- ${errors.map(e => `
- ${e}
`).join('')}
`;el.classList.remove('hidden');el.scrollIntoView({behavior:'smooth',block:'start'})}
function applyCompanyPreset(companyKey){const preset=COMPANY_PRESETS[companyKey];if(!preset)return;
const priceField=document.getElementById('inp-fmvVest');const grantPriceField=document.getElementById('inp-fmvGrant');if(priceField)priceField.value=preset.suggestedPrice;if(grantPriceField)grantPriceField.value=preset.suggestedPrice;
const infoBox=document.getElementById('presetInfoBox');if(infoBox){infoBox.innerHTML=`
`}
document.querySelectorAll('.preset-btn').forEach(btn=>{btn.classList.toggle('active',btn.dataset.company===companyKey)})}
function applyTypicalGrant(totalValue){const priceField=document.getElementById('inp-fmvVest');const sharesField=document.getElementById('inp-shares');const price=parseFloat(priceField?.value)||100;if(sharesField)sharesField.value=Math.round(totalValue/price);}
function handleCalculate(e){e?.preventDefault;const inputs=readInputs;const errors=validateInputs(inputs);showErrors(errors);if(errors.length>0)return;
showSpinner(!0);setTimeout(=>{const result=calcRSU(inputs);const presetKey=inputs.company;const preset=COMPANY_PRESETS[presetKey];const vestType=preset?(presetKey==='amazon'?'amazon':(presetKey==='apple'?'semiannual':'cliff')):'cliff';const schedule=generateVestSchedule(inputs,vestType);renderResults(result,inputs,schedule);showSpinner(!1)},200)}
function handleReset{document.getElementById('rsuForm')?.reset;setResultVisibility(!1);destroyChart('donut');destroyChart('vestbar');destroyChart('svh');document.getElementById('formErrors')?.classList.add('hidden');document.getElementById('withholdingGapWarning')?.classList.add('hidden');document.getElementById('presetInfoBox').innerHTML='';document.querySelectorAll('.preset-btn').forEach(btn=>btn.classList.remove('active'));showToast('Form reset.','success')}
function handleSaveScenario{if(!lastResult){showToast('Calculate first before saving.','error');return} saveScenario(lastInputs,lastResult)}
function handlePremiumFeatureClick(featureName){if(checkPremium)return!0;showPremiumModal(featureName);return!1}
function handleSellVsHold{if(!handlePremiumFeatureClick('Sell vs. Hold Analyzer'))return;if(!lastResult||!lastInputs){showToast('Calculate first.','error');return} const svh=calcSellVsHold(lastInputs,lastResult);if(!svh){showToast('Enter a target price above vest price.','error');return} renderSellVsHoldChart(svh);document.getElementById('svhSection')?.classList.remove('hidden')}
function handleMegaBackdoor{if(!handlePremiumFeatureClick('Mega Backdoor Roth Optimizer'))return;if(!lastInputs){showToast('Calculate first.','error');return} const mbr=calcMegaBackdoorRoth(lastInputs);const el=document.getElementById('mbrResults');if(el){el.innerHTML=`
`;el.classList.remove('hidden')}}
function initStickyCTA{const cta=document.getElementById('stickyCTA');if(!cta)return;window.addEventListener('scroll',=>{cta.classList.toggle('visible',window.scrollY>400)},{passive:!0})}
function initExitIntent{let shown=!1;document.addEventListener('mouseleave',(e)=>{if(e.clientY<0&&!shown&&!sessionStorage.getItem('bsf_exit_shown')){shown=!0;sessionStorage.setItem('bsf_exit_shown','1');const modal=document.getElementById('exitModal');if(modal)modal.classList.remove('hidden');}})} function populateStates{const select=document.getElementById('inp-state');if(!select)return;const sorted=Object.entries(STATE_RATES).sort((a,b)=>a[1].name.localeCompare(b[1].name));select.innerHTML=sorted.map(([code,st])=>``).join('')}
function init{populateStates;renderSavedScenarios;checkPremium;initStickyCTA;initExitIntent;
document.getElementById('rsuForm')?.addEventListener('submit',handleCalculate);
document.getElementById('btnReset')?.addEventListener('click',handleReset);
document.getElementById('btnSave')?.addEventListener('click',handleSaveScenario);
document.getElementById('btnPDF')?.addEventListener('click',=>generatePDF(lastResult,lastInputs));
document.getElementById('btnClosePremium')?.addEventListener('click',closePremiumModal);document.getElementById('btnClosePremiumX')?.addEventListener('click',closePremiumModal);
document.getElementById('btnCloseExit')?.addEventListener('click',=>document.getElementById('exitModal')?.classList.add('hidden'));
document.querySelectorAll('.preset-btn').forEach(btn=>{btn.addEventListener('click',=>applyCompanyPreset(btn.dataset.company))});
document.getElementById('btnSellVsHold')?.addEventListener('click',handleSellVsHold);document.getElementById('btnMegaBackdoor')?.addEventListener('click',handleMegaBackdoor);
document.getElementById('btnUpgrade')?.addEventListener('click',=>{window.open('https://buy.stripe.com/PLACEHOLDER_RSU_PREMIUM_29_MONTHLY','_blank')});
document.getElementById('inp-fmvVest')?.addEventListener('input',(e)=>{const shares=parseFloat(document.getElementById('inp-shares')?.value)||0;const price=parseFloat(e.target.value)||0;const preview=document.getElementById('grantValuePreview');if(preview&&shares&&price)preview.textContent=`Grant value at current price: ${fmt$(shares * price)}`});document.getElementById('inp-shares')?.addEventListener('input',(e)=>{const shares=parseFloat(e.target.value)||0;const price=parseFloat(document.getElementById('inp-fmvVest')?.value)||0;const preview=document.getElementById('grantValuePreview');if(preview&&shares&&price)preview.textContent=`Grant value at current price: ${fmt$(shares * price)}`});
document.querySelectorAll('.faq-question').forEach(btn=>{btn.addEventListener('click',=>{const item=btn.closest('.faq-item');const answer=item?.querySelector('.faq-answer');const isOpen=!answer?.classList.contains('hidden');document.querySelectorAll('.faq-answer').forEach(a=>a.classList.add('hidden'));document.querySelectorAll('.faq-question.faq-icon').forEach(ic=>ic.textContent='+');if(!isOpen){answer?.classList.remove('hidden');btn.querySelector('.faq-icon').textContent='−'}})});
console.log('BSF RSU Optimizer initialized. Tax Year 2025/2026. businessskillforge.com')}
if(document.readyState==='loading'){document.addEventListener('DOMContentLiteSpeedLoaded',init)}else{init}
document.getElementById('btnUpgradeModal')?.addEventListener('click',=>{window.open('https://buy.stripe.com/PLACEHOLDER_RSU_PREMIUM_29_MONTHLY','_blank')});document.getElementById('res-stateLabel');document.getElementById('inp-state')?.addEventListener('change',function{const label=document.getElementById('res-stateLabel');if(label)label.textContent=this.options[this.selectedIndex]?.text||'—'})
Keep exploring
