290290 color : white;
291291 }
292292
293+ .demo-box {
294+ background : # fff9e6 ;
295+ border : 2px solid # ffcd02 ;
296+ border-radius : 8px ;
297+ padding : 16px ;
298+ margin-top : 24px ;
299+ position : relative;
300+ }
301+
302+ .demo-close {
303+ position : absolute;
304+ top : 12px ;
305+ right : 12px ;
306+ background : none;
307+ border : none;
308+ font-size : 24px ;
309+ color : # 4a4a4a ;
310+ cursor : pointer;
311+ width : 32px ;
312+ height : 32px ;
313+ display : flex;
314+ align-items : center;
315+ justify-content : center;
316+ border-radius : 4px ;
317+ transition : all 0.2s ease;
318+ }
319+
320+ .demo-close : hover {
321+ background : rgba (0 , 0 , 0 , 0.1 );
322+ }
323+
324+ .demo-title {
325+ font-size : 14px ;
326+ font-weight : 600 ;
327+ color : # 4a4a4a ;
328+ margin : 0 0 12px 0 ;
329+ text-transform : uppercase;
330+ letter-spacing : 0.05em ;
331+ }
332+
333+ .demo-row {
334+ padding : 10px 12px ;
335+ margin-bottom : 8px ;
336+ background : white;
337+ border : 1px solid # e0e0e0 ;
338+ border-radius : 6px ;
339+ cursor : pointer;
340+ transition : all 0.2s ease;
341+ }
342+
343+ .demo-row : last-child {
344+ margin-bottom : 0 ;
345+ }
346+
347+ .demo-row : hover {
348+ border-color : # ffcd02 ;
349+ background : # fffef8 ;
350+ transform : translateX (4px );
351+ }
352+
353+ .demo-row-top {
354+ display : flex;
355+ justify-content : space-between;
356+ align-items : center;
357+ margin-bottom : 4px ;
358+ }
359+
360+ .demo-income {
361+ font-weight : 600 ;
362+ color : # 1a1a1a ;
363+ font-size : 15px ;
364+ }
365+
366+ .demo-status {
367+ font-weight : 400 ;
368+ color : # 6b6b6b ;
369+ }
370+
371+ .demo-descriptor {
372+ font-weight : 400 ;
373+ color : # 6b6b6b ;
374+ font-size : 15px ;
375+ }
376+
377+ .demo-descriptor sup a {
378+ color : # 6b6b6b ;
379+ text-decoration : none;
380+ font-size : 10px ;
381+ }
382+
383+ .demo-descriptor sup a : hover {
384+ text-decoration : underline;
385+ }
386+
387+ .demo-tax {
388+ color : # 4a4a4a ;
389+ font-size : 15px ;
390+ font-weight : 500 ;
391+ }
392+
293393 /* Mobile styles */
294394 @media (max-width : 640px ) {
295395 body {
356456 < h1 > PFA Tax Calculator</ h1 >
357457 </ div >
358458 < div class ="header-description ">
359- Who really pays the Preschool for All Tax? Input sample figures and see for yourself.
459+ Who's really paying the Preschool for All Tax? See for yourself.
360460 </ div >
361461 </ div >
362462 < div class ="calculator ">
363463 < div class ="inputs-row ">
364464 < div class ="income-container ">
365465 < p > Income:</ p >
366- < input class ="income " type ="text " id ="income " name ="income " value ="40000 " />
466+ < input class ="income " type ="text " id ="income " name ="income " value ="50000 " />
367467
368468 </ div >
369469 < div class ="tax-container ">
@@ -394,7 +494,7 @@ <h1>PFA Tax Calculator</h1>
394494 <!-- when the box is checked, the input field is set to the right value. it's 2,835.00. for single, double that for joint and HoHH-->
395495 </ div >
396496 < div class ="ti-row ">
397- < span class ="bracket-range "> Taxable income:</ span >
497+ < span class ="bracket-range "> Taxable income (TI) :</ span >
398498 < span class ="taxed-value " id ="taxable-income-amount "> </ span >
399499 < span class ="rate "> </ span >
400500 < span class ="amount "> </ span >
@@ -414,6 +514,38 @@ <h1>PFA Tax Calculator</h1>
414514
415515 </ div >
416516 </ div >
517+ < div class ="demo-box " id ="demo-box ">
518+ < button class ="demo-close " id ="demo-close " aria-label ="Close demo "> ×</ button >
519+ < div class ="demo-title "> Try these examples:</ div >
520+ < div class ="demo-row " data-income ="32600 " data-status ="single " data-deductions ="standard ">
521+ < div class ="demo-row-top ">
522+ < span class ="demo-income "> $32,600 < span class ="demo-status "> (Single)</ span > </ span >
523+ < span class ="demo-tax "> Tax: $0</ span >
524+ </ div >
525+ < div class ="demo-descriptor "> Full-time minimum wage worker in Portland< sup > < a href ="https://www.oregon.gov/boli/workers/Pages/minimum-wage.aspx " target ="_blank "> [1]</ a > </ sup > </ div >
526+ </ div >
527+ < div class ="demo-row " data-income ="86247 " data-status ="joint " data-deductions ="standard ">
528+ < div class ="demo-row-top ">
529+ < span class ="demo-income "> $86,247 < span class ="demo-status "> (Joint)</ span > </ span >
530+ < span class ="demo-tax "> Tax: $0</ span >
531+ </ div >
532+ < div class ="demo-descriptor "> Median household income in Multnomah County (2023)< sup > < a href ="https://censusreporter.org/profiles/05000US41051-multnomah-county-or/ " target ="_blank "> [2]</ a > </ sup > </ div >
533+ </ div >
534+ < div class ="demo-row " data-income ="127901.67 " data-status ="single " data-deductions ="standard ">
535+ < div class ="demo-row-top ">
536+ < span class ="demo-income "> $127,901.67 < span class ="demo-status "> (Single)</ span > </ span >
537+ < span class ="demo-tax "> Tax: $1.00</ span >
538+ </ div >
539+ < div class ="demo-descriptor "> Estimated income of the top 10% of earners in Multnomah County < sup > < a href ="https://censusreporter.org/profiles/05000US41051-multnomah-county-or/?utm_source=chatgpt.com " target ="_blank "> [3]</ a > </ sup > </ div >
540+ </ div >
541+ < div class ="demo-row " data-income ="306960 " data-status ="joint " data-deductions ="standard ">
542+ < div class ="demo-row-top ">
543+ < span class ="demo-income "> $306,960 < span class ="demo-status "> (Joint)</ span > </ span >
544+ < span class ="demo-tax "> Tax: $769.35</ span >
545+ </ div >
546+ < div class ="demo-descriptor "> Salary of Andrew Hoan, President of Portland Business Alliance< sup > < a href ="https://projects.propublica.org/nonprofits/organizations/320016048 " target ="_blank "> [4]</ a > </ sup > </ div >
547+ </ div >
548+ </ div >
417549
418550 < div class ="share-buttons ">
419551 < span class ="share-label "> Share:</ span >
@@ -539,7 +671,7 @@ <h1>PFA Tax Calculator</h1>
539671
540672 // If tax is 0, set income to default
541673 if ( targetTax === 0 ) {
542- incomeInput . value = '40 ,000' ;
674+ incomeInput . value = '50 ,000' ;
543675 calculateTI ( false ) ;
544676 return ;
545677 }
@@ -611,32 +743,122 @@ <h1>PFA Tax Calculator</h1>
611743 }
612744
613745 // Initialize on page load
614- // Check for income query parameter
746+ // Check for query parameters
615747 const urlParams = new URLSearchParams ( window . location . search ) ;
616748 const incomeParam = urlParams . get ( 'income' ) ;
749+ const statusParam = urlParams . get ( 'status' ) ;
750+ const deductionsParam = urlParams . get ( 'deductions' ) ;
751+
752+ // Set filing status from query param
753+ if ( statusParam ) {
754+ const validStatuses = [ 'single' , 'joint' , 'head' ] ;
755+ if ( validStatuses . includes ( statusParam . toLowerCase ( ) ) ) {
756+ filingStatus . value = statusParam . toLowerCase ( ) ;
757+ }
758+ }
617759
760+ // Set income from query param
618761 if ( incomeParam ) {
619762 incomeInput . value = incomeParam ;
620763 formatNumberInput ( incomeInput ) ;
764+ } else {
765+ formatNumberInput ( incomeInput ) ;
766+ }
767+
768+ // Set deductions from query param
769+ if ( deductionsParam ) {
770+ if ( deductionsParam . toLowerCase ( ) === 'standard' ) {
771+ standardCheckbox . checked = true ;
772+ const status = filingStatus . value ;
773+ if ( status === 'single' ) {
774+ deductionInput . value = '2,835.00' ;
775+ } else if ( status === 'joint' ) {
776+ deductionInput . value = '5,670.00' ;
777+ } else {
778+ deductionInput . value = '4,560.00' ;
779+ }
780+ } else {
781+ // Try to parse as numeric value
782+ const deductionValue = parseNumberValue ( deductionsParam ) ;
783+ deductionInput . value = deductionValue . toString ( ) ;
784+ formatNumberInput ( deductionInput ) ;
785+ standardCheckbox . checked = false ;
786+ }
787+ } else if ( incomeParam ) {
788+ // If income param is set but no deductions param, set to 0
621789 deductionInput . value = '0' ;
622790 standardCheckbox . checked = false ;
623791 } else {
792+ // Default behavior - use standard deduction
624793 if ( standardCheckbox . checked ) {
625794 deductionInput . value = '2,835.00' ;
626795 }
627- formatNumberInput ( incomeInput ) ;
628796 }
797+
629798 calculateTI ( ) ;
630799 incomeInput . focus ( ) ;
631800
801+ // Demo box functionality
802+ const demoBox = document . getElementById ( 'demo-box' ) ;
803+ const demoClose = document . getElementById ( 'demo-close' ) ;
804+ const demoRows = document . querySelectorAll ( '.demo-row' ) ;
805+
806+ demoClose . addEventListener ( 'click' , function ( ) {
807+ demoBox . style . display = 'none' ;
808+ } ) ;
809+
810+ demoRows . forEach ( row => {
811+ row . addEventListener ( 'click' , function ( ) {
812+ const income = this . getAttribute ( 'data-income' ) ;
813+ const status = this . getAttribute ( 'data-status' ) ;
814+ const deductions = this . getAttribute ( 'data-deductions' ) ;
815+
816+ // Set income
817+ incomeInput . value = income ;
818+ formatNumberInput ( incomeInput ) ;
819+
820+ // Set filing status
821+ if ( status ) {
822+ filingStatus . value = status ;
823+ }
824+
825+ // Set deductions
826+ if ( deductions === 'standard' ) {
827+ standardCheckbox . checked = true ;
828+ if ( status === 'single' ) {
829+ deductionInput . value = '2,835.00' ;
830+ } else if ( status === 'joint' ) {
831+ deductionInput . value = '5,670.00' ;
832+ } else {
833+ deductionInput . value = '4,560.00' ;
834+ }
835+ } else {
836+ standardCheckbox . checked = false ;
837+ deductionInput . value = deductions ;
838+ formatNumberInput ( deductionInput ) ;
839+ }
840+
841+ calculateTI ( ) ;
842+ incomeInput . focus ( { preventScroll : true } ) ;
843+
844+ // Smooth scroll to top
845+ window . scrollTo ( {
846+ top : 0 ,
847+ behavior : 'smooth'
848+ } ) ;
849+ } ) ;
850+ } ) ;
851+
632852 // Share button functionality
633853 const shareBluesky = document . getElementById ( 'share-bluesky' ) ;
634854 const shareTwitter = document . getElementById ( 'share-twitter' ) ;
635855 const shareFacebook = document . getElementById ( 'share-facebook' ) ;
636856
637857 function getShareUrl ( ) {
638858 const income = parseNumberValue ( incomeInput . value ) ;
639- return `https://friendsofpfa.org/pfa-tax-calculator/?income=${ income } ` ;
859+ const status = filingStatus . value ;
860+ const deductions = standardCheckbox . checked ? 'standard' : parseNumberValue ( deductionInput . value ) ;
861+ return `https://friendsofpfa.org/pfa-tax-calculator/?income=${ income } &status=${ status } &deductions=${ deductions } ` ;
640862 }
641863
642864 shareBluesky . addEventListener ( 'click' , function ( e ) {
0 commit comments