From ca2d8e7188ddad84cb1a24ae85c9fffde315d595 Mon Sep 17 00:00:00 2001 From: igerber Date: Sun, 18 Oct 2026 12:44:43 -0400 Subject: [PATCH] marketing: bad-controls launch carousel (Junction palette) + claims-sync guard LinkedIn launch deck for the v3.12 DMLDiD bad-control lane (Caetano, Callaway, Payne & Sant'Anna 2026): carousel/generate_bad_controls_carousel.py + committed carousel/diff-diff-bad-controls-carousel.pdf (11 slides, poster mode, ink/stone structure with a single amber accent for the bad control and the fork motif's third road). tests/test_bad_controls_carousel_claims.py (29 checks): every simulated estimate located on the committed tutorial-33 notebook surface, the NLSY79 application numbers and the paper's own wording located in the paper review, the cover's release label pinned to the CHANGELOG section that shipped the lane, validation anchors pinned to the REGISTRY block, arithmetic behind the half-the-effect / SE claims, slide-local qualifiers, a banned-absolutes list, and a valid-Python check on the code slide. --- carousel/diff-diff-bad-controls-carousel.pdf | Bin 0 -> 135392 bytes carousel/generate_bad_controls_carousel.py | 1300 ++++++++++++++++++ tests/test_bad_controls_carousel_claims.py | 532 +++++++ 3 files changed, 1832 insertions(+) create mode 100644 carousel/diff-diff-bad-controls-carousel.pdf create mode 100644 carousel/generate_bad_controls_carousel.py create mode 100644 tests/test_bad_controls_carousel_claims.py diff --git a/carousel/diff-diff-bad-controls-carousel.pdf b/carousel/diff-diff-bad-controls-carousel.pdf new file mode 100644 index 0000000000000000000000000000000000000000..263763f7593c97d8eda4e626240b1e13e3498301 GIT binary patch literal 135392 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
M9XxIEW61qV!Ke+>?gusozz2~nw zzw4uk6*o2KdZ#u_gssyh0&-31IC)QG4%QPJ;)0ew1dzF%*Xp3vLLR{Ld9MaJn^^;B zvzF4hlr2>>_hkSg96hr47CUFAMWa*YN>eoIP3`0C$swE1F9bsleHKmZog#SS{vZeU zrc1_@$);R3`BqVLXoAtRwBS_K*sMW@*VgaQxiKK0hakJOcWdY@#3ylCQRR^PzW0H< zChli{xJ<_3kXlmuOqB{}`cp&A;vW3Ee3t9My&gsa3d8A}s|fVSsQ~4n?5C*?QFS$s z;H>?DcC9CTGI`G1VfDnlmD*~Dcg}}U(?Y6FC*`v8St{*|w4mkUc#I2K;Uv~LX~5rO zp>UI5CQogIHTb+A^vcfOE2NY%hLn#&kabECEtTph{+Xsz;21WVfXQr4;JXPurS8 z=!oYLV`wE%aERcVe*({NiCOp~g*@U=@*M;={;+>jpC>}+^GgTK-BIT_+)t`bH}fha ztptN*C93A_oaK*&?6%42C^euqjFN!B+-;^^-CV)Dmp4{$)jN|&+2EkwDXdH5%7{lZ z(`3F@#KDMI|C{P9jeBA+;+di?r`o>!AH-&%cVw_tPQ>g$&8Y`844esyA`&As&Ohr1 z;f)p@Zw;BisG0YIJ_t`Vt8LcEdUt7CF`Hdes!xK)6)j)vjhnEB-Y5D zcSp2*kH5M`OsvV!VYcK;Jxz;+WD_S$*6@Yh^E{rBOo(i9vJepg{a$%W?TVaJqjbAk zOy?TCLA_tIC=OzcFO5QE${eGJn;X3#wj1EH;@OYTE*jnkF#a6_{@P#+suv%3Agx-A zEl$_Vr83C9T+6Ys%>BxF^z$)#OTqSvG{GDCxzw(7VUB=}UspiSOri(%&y)xczLdb3 zZ=Pj`O@#Z0n$}wO-U2(R9aiLje6;>8DQmKi{c>$`J`=-jK1+Zb^lyZw zmkz2{FcuAm#j<0COg|$Ut}ywMK>(%Z%)-I)`8o+txTq=|mDJb~h0j?;pV*7Eo!3TM z{!*_pN>*SlGDcT4m&2-Y$liRr$}NSF1;#HREEpR!pY|R$9Z9-!#{;LBHM9wrmQ(_` z@Kd9{s!(lxNDl9Ar8E0BRSozQ)WEZ30M+9%43@41v;oR|i5dmk2 zxr~pBTDgDGBk7|luHJfKNc#QW^-J!BUzp!EEL27@m*4wL{JDXrkmgxA_%)LW(_=#u zE&ZEX?QeKC`0n|BFZp&$i}@Y>C3#Kpc2!ILZHgg(E4^d__$dpp1f2mR#oPVzBQO=wYRO2*&Ej91cZq8T(`&KTss((*xd(go&oAQq0ZM@bNa-^{J<9DctZ4z7jS8!x-~jBw`k z-}nu|)YX~g*d-#?ZUZYRteaz&Q!U}S>DKlpT~=BO)d<^144T*1?rQ2*y3$mj4%EDd zJ7CYvblfU2eBUS=`J#-s3O46{d`rL1=yt>~urlNu1n7(E^vdgKx_YsK{XFmqSwld( zIg_8ILzyo_V{>^&$>wxg&a5lt@@?#Ze^TwhzOOVo9x@pF>xR~J+niKTRJGv}7X4sh z_e7*^>4F?{BY%Y{2-o9vY4k}wSuf||1l&K1ADa<7?4RD8zw4EG!*GttC1u$6yV+gy zU%L!az`LZ9#I7zc?h6ao{w%l)e9ci|m6{;G4hYOF>%Bp5P{(!%8|0lLeQ+sz0U~P8 z?=OPFU^YLlt(qJv>VOh>OrZmWr)|%grw8MS!7xcK>^gG-QtkF!=fI>v8~(wX5#E_NfD*o^VdMQ3Y^&9Ju80fC9Z5*yCe> zGaiv^432BvZMMI@0o5gTt-2W-?ciVg!xe;MQ9rEe9;*-P3`_(Ji?18tq+J&w_a!F> z==?HaE@Mdj#l*m%wGyCKY$v_g$u0wDhcS=5w7JNA9$; zOO$8nzxDwQO7At4CqKwbN~Lr1q&*=~58a3A*4;k^6k4k1NgW3~41902Hau$sWHWL1re0 z&T(dEuTgZ3l*Dza!)m-XdtcV1g|KR-4LoA%t{HA!ar?5p0gEU|?XMuqT*gU1DIrXb zkL_HFX`U0HuurJ|m=ASnF$zP*WGopTf+2($S1Qu;|Z)sk<%0^S5;c=(rySk{j zjK_2J+6oNceeULr1dIEda%{pacCztB124(D6U{Ppn7EAPb&mN0`=n=vLAf1^On|2N zR!N$xon1nm`{untc72T*b0&3VZnAzZ3IPSGCm zR8XAeFF)@y^jJ*9vuVA5_O z6bKqlpT6=C^(hlGAL{f~?{pa$UlqfpkXiYyt727XX2p)ok}dGaxL%;k&a<5|Y)wy< zPZ=e)Kw@=LQ^EMls93#jn9Tq~NKKTD`L0ue^mkR4gTfQgWdLF>q^#fR;Z-{4KE@|e zZp`-n_~B(Va|_?D#x=Jo6B`YL?qF=duPB-@MLWm5(WV(s7$&>Rk}`I$)0V4{uP*geF#j3`4ycF;)C^meP#3?~ z{xC~yLG95x>%f?J(Z`mRv#3EW#qKYTE$`wn3liwK$CFb4rHCX`sE?$>?QYlmY8gQj zBwEvRVskW&RwYwyfKFak6YJ$x90~9B{j4FS(`oxrM`FFmBhh0Jhpoy_-T zUw$49dU{wNnX!?H;O$I*>}Yp{eF7BlwZ=0q_5mAnJcBFSXT1UXg&5nuX>6kx3Z%=DX*gW(r&eWd{R=_|2s?_@lJ-xxI@6f}NlG?#Lzng5`l) z4P@th9+FG9dq9EH6gHgSYH_gl9-Xc=co$KSM8w-yZOSvqI>_FuU(GV`y;E&Ki+p;+ zy~t-qy@C-XWm8|2u8TPxyN_v(*dNun{3xE&Mm0B2HHj~7Zy&k>WE~T*>=hp+2WWwn z!eS5B8p3%pD8Iz($;UUvt&iSWvkaOam-)@<#?@wmS0K|)w}?zd$*1i4OM5%4otA3Y ztnzOa`c+bJqpJf%ugZFH;VJ+FP%!9z`&|Y$1`5ksjr9Aft7^Z$7_rI+GES?|R`v5% zG=FTsoFGvHYdY^P_dl*qEX38Xl0nM@R^^yqLk0gruzRW5J>i`MePZY*eU>OZP%+_J zvILx3@#g9H^N9`<2GJyxXV%db+WM;nCd{I?w4q9k3q7?b5;*bMNBwDEiToz$(KfJM zn~I@FZ=j!cF9&9g%?u@;=tt+g4Y%1%g`X79tWk!wngTuy`XKAC^u<=fML4r8-vkN- z?f(AQ6V&~CWF8wCecKKdOo`^}{cBdwt8~V`iPCL+sF#g_tCb}eJ$YihK^rJM%& zPwy`?Fa6ul5pc>RclOG|)VenQYA7Fei?C$5L(3VSV+-fRjlFM{owDc;yCK|trL(Sy z4k6S6`^M99x5C_^en_9NvGxTXY>E%!8B1laml6WJ6>?LTSbAql7S4{l%D!OtNBlOf zLm-1+8Kbw!-+TN0T#I=}FH}-#MA(%Ku9#@TwTk&abx3g=hnR-B@&X6kvRrTTAzJB6 z7veg}2FkJRVz} zG=p;k|Bf?y=~QemAzDe@-7GnCRC5&y9Hv6xE1c-%UKg3xePk|E>0iB7qxrF^f^X%B z!7;Mss?Xe~eZ}8?o9TD0^BY%#VM9Z+cGiO{$cp+vZCkn&hXq^$EOaR;H2!tYi7BXT zRU8D^<4r~rJz5g@vM-7!?GC?Zz=rDSC&|*}t~J%dN8XFeLYPlO@D)Wr_NAi7AJcM* z&2e4p4LCMz*iP@EOi|94Uv%SsMOmjHt49-a_vy@vXd>Ow8zzJ2C&_Sz)AJS~D^B})uG*(_c!Tnq(zsrE(c#URNBHdum2}l@DoQE- zCg+6aK^FvNkbv<@GH-Ff;!$1VxW<|d>Qu*k|A9Gq%g9{kSFm^Tv~g$VS8%fMw0UY{;puK;;e6dUeQVaoSH}Q?JVThcyrvAC! zwEpuK0R_!Jf4-r=^dBaQe)964p9$Qr{u3)DkRuBLyy1VYZWe)m{v;6pAJWXBt^fIX z>Hk&Yw|}-Wvk0%5oz9$J#+ zM;BlDR1N6ojF&7~795wfet2i^z;7-z>~o}~*YA~S=g@qf8L^kYej(1^P$u4>0n4FJa{V@Y{xhkNo#(crFlBvhyy8}?6AYXgIXgfTlIKL!YG z%Vz@ZM2yp^T6}5Yu4AWXe#Jiy8jf;X$bq=p#q|bq^~PRX5sB#bJ4RU_X%G<*fV#Nk zBrm-?jZRIpVDj9YqdXSk`1^N)>6FbA@xDxS{JRyUdiXf&nZoK|_CK`j6kpDJ71^%?BdduJ^TQKu(?Qgg66>ZW zl?QVyb+mKJy@(SM zV^e>FQ~u%I>r|Hrk<)(jUxFHdNo}a*{SV7BBPeKmhlhnGx2$*pVh*)UwT;!rx1^&! zv;K#b*TP#{jn&heEtu>E_O@ZLS73j2<$mV>y3ZY%1;*pD&y-0LorP>{H>bq^(}bMQ zWug;F_mkqFFc@?r{m#F3K+Bs}Ia^{46MR=j*a6--g!I2&@}KrOcw0aE_J8)^8)^!g zwO4~*s}D0*`4BsKHUHXK^H+dorf35tKqLRl8%umFoEKXn_X_+lqXr}H+7Y?sR9&v4 zfB%2RaLy{>9S-K3^|jSWu5fA$Kf*Wrq-5NIN;0L{GBk*?8usm^#L7q@cwoBQpt4v- zk5@)eJWBG}%fHuzU?>CF06j(ahvR{~{noKFD&1Z$clVP&xR44u59dqm-2Sh@{f~4w z3U~={m!Rj~!)>*bqYz;@8H|MIj@L^8`#Jymk4Ii@kpF%+n33j)^*>_i&Cb;uU;anF zWJ_KmT>Kv?v=-Ug>ia*ks_DLf0OS9suf7RP%uKw)z`#I7YwucFDLB&m>({S_h8JBb zd4^>Zftdp7%BrdnAe>Q!&^K3CxsZQ#_)TDRVq%m3crQQns8pq6uVe1CxwzJ0c*e}W z)`nvear(2}EYL|&RpZwv#H%#{hcCP^RV#+Ti zaWiOgf6p)TS|8IYk_uS)Qd6b-$udN^1RfrAEP4-rmqyC};JeYX%H2tfv-9k<@bM_! zeD%K=Nmk+IJc-dGM=m0Q0`<(>+=@|mIWsH7t8Hy;ZCB4~q!*JyLOLw%_bpV{a}J?@})JyR-p=69dBW&b3@19l_C9D%vQza~x)SvF@> zHZkeuMoW98Iy3uAW^ytO6O*g)OZ4(%0G`sWBk)=dWRGHZHY(xT1RF~t@;BuD{r#Um z|FW0WsP8W+ur}IkFv*v}{)MjDzU^aQ5?=>2IB02?#g&+dbOT(n0ew0wT44&_coCP9 z0{b3p>c&RSB(v-Azl=^pTU%S#I(NhyIn8RQYTD3xXwa3IkYIz5l8`V$PXe3`&stbq zq~_Lg~jHl|4VYBnUd(AXx;iks$oQzM`A z$a|ETw9K9G<;gtNOOE>P1XKU(zy;U?pfM zkmSaJw2Yvjpm{CU#L9J?%b?12tt;fmsEVdH3Lkugzwmp zP|TsRa4uaF*^Q4xq=^HXRxhKYqnW{R%_Ce1{Kk2fe(PCvPIK`|IR$;$$CNZ{0f7Kd z0DGr6i0uQ5z;~mvkt`PugXS9iXw-CA$Le4PTEX=V^50t|Y9}P5SdYWF$+Gcb9Vm)+ zn@fP^&ZDOiPa;Boh-N_VV7I0lN8b@+oUiz}AY5jPKNM#>6}?f6V)PF@@T7eNx@ICi)uFXxIU3Y>T&6P$BkFcHn`0~8mn8Gvwep@Ep|x<+_B&ekBpqFaeIe5+#G3r z+5Y|O2(81l8+;~W{N7VwcztmwCO(a zhL>=u-r@dMoFeO5E*d#F&TWv(4tD?GzP~bXjhwtbfinZqLbI->`UHz z4jFMc#xah~_j#`Ob$zZr@6Y!S_+!g+=j-G< zAMylM`QXR$NU@j9)AwTJ+d7sRYkF`je&?gRQ(H7^$5H-~klaPm`Mm3GUSUjUx2+ID z9=SdHJ&O4M@-biLRTIF+n8B;%t{Ab8v`p`BJ6gF~E5$@aM8%1=!ImeCr)1@7y^0!z z^Ao^M$>UmCY1-eOlzAx;$iO&R7hr;K1l_cE2`mBJEy00c2!0AAC(OxuWwkf6dOJa%^Ut%meqD{i%4XHPXe&Z|PjX{F^Yp>*Z7bKna@{SN#)GA+ z*yKvMLjIW$-ej?PH~B`F72|Q5xShWzJEuuKO}HOJ_Hh;(96VFJ1VJ6A%IKKXMWJSv zM@oDP#9G=e{{{xsN?S5k+SukLpri+Lsx2Cfv(G=$#`+L#7dM?qP6x%Iwce z=r!K|pGj_G^J{>e@;JONusB%OGa)Xag z|9atxrd$MkXKjjs8xkB``3scE$?*WFueBEcIr4pt?Js0cT!TdriE13sh7Ba3T3hy3 zCmyzaSGW}(vWCNXlSH=7U0=rhUSdYagzQ>H+PoY`YO$T*OapjxeVJ5{;91IVyG2N4 z3e*klA^#m`gSS#HWro7~ez5<190bSvSxLk#tx%r_3JsEJnA`X|+tTt(P*G6{VeIZ+ zj^Gi#^9Yah9r$h)T4C3FiJPG}ec`{GN!jv9X}DuFZCi{-6WlI1_>)S`1q2l+1sikV zY$Zi9@W*j!^Nh4SxDT2gg2_e!;;Iu$!{V^xYr;!QkCP?MDke|z*$@61>8`VJ;y%+a zD`O9K)}TwH=Kh!pRX%=cYRXk?-E9|fkA2~?@}5v$R3|v;B681ZK!~*7B*7y z`SWLR>^0IQbDRoJl_>!LMNP$PR1}6NvY%Db*49S%_t<*8SU={MJ7p4wZiS%<26&B+P%}DjKi7c@3@#En;jQ4P?3$=#qR8GSNr%RR<2yRqK7;` zT5nS!K2uqst7qfpR)#34q##$0xlYdw50Udlw@THxa&taRR9LAYLnVDdQf~b>+%kbj z%;yxgL>EK*Sfi7Dt~2r+c-fa&j~Nqgxy~^$&WYFgzAsk>>mcQ^zcs+A8Rxx+&T%%W zIRyFQ;+7;LQw$jyhGN^?GUGrmPb0C2ur-z>EYMC^{4k&);pw7|Mu`;32xx6BVtX)` z9rX)8fM!V3bXpd0#D9p!y6aKUem`c&B!(W` zGW4?%@HOhCp_T_z1;)kt^MlXVT8%8Hzp&?-$)6)Hot;S%b;%B>EzddAn<_Kw#7{y1 zM!z9|AlTO8(?lJ1jB(SpxPTUZvh3ToAxrbV;O*NApha)Cy*l`j@nyAydZgHlo1a3x zO}>eVaWT-pyrP0LnvL`LSYg~jzwp*dYlx~w!>bFFSHWz9lQSf!k8-!^O_5#kQzm`n z?+ANJ%6ltpSKNxBu*Ua1<<*I5mjc6*C~=kWPp;9dBIsv=_e93Y$dY3@H7XApol8^; zPop9OvBX$#>Hur-^Dgpa8=MFZj@GSe@FZ9zXt0>IlCwwB;rg2J#t;DZ?xlbCt`_4RcJ^YUCInb$P~-}CK#2<$VVU@x zaWfjlR*x8Hghy^?UGlM^2EDv$B-gD`r zV@>AGo1Nx|Th{4)vPaoqSFbg1de81K`Gc-lZXuMXDdoSYrJ@pHvN?DwCdAg(7D3dr zr~UpGP7hr{8$rg1u`!#@2(HVQe*!kc_G2v%v<5W5ykPJS*h&I)%G(Uoy@~}cDfi{S z_R%A$%%jD(|>}$`cb2F6OS&!E!K!JHC**fAoIV1wS2!6y*mN{|@=V&G&Hl(C0vm zmFqDE+r0V%t7_c@P(An;#h|6B_GXq#c?e@DR5&w9q`*EzHXg) zeNitmbEMR46Kx1yR9p3cxa0Obe`$GLrNM7LqNZ(|GWfLCAHV;JJb=S+6}syN59JQF zXxFF=M(NEjJ`2(WwUkNE9&DB!Vr?3bEG}ezy~6mhCqChRsq5r zprU{s0)h(IB?vd9D+AQa&80AK;Ek%R>Z~tfk$r`?>3RPCaIL53Dg7wZ?mKmE>~TZ+ zOq(WP!NCT~|9-BB<3_W?wXNQji8>c}T3R4s<~2AK-AVTYCO`HA`jR9B8wMc4dv!GM z_^>X4-@*?z4x|8+8mBbjr;UR92)eFxS>Ic{s*fL!mIX}AJ)wn{zusI(mGR)<=I)yC z&~<}mN^l8ow1&?ni#mN2gGQH!WGP28%6Uh*`xulO`+^d`RVmCHvP8%D=j+$bQ`KHT zujo|c0NfXp226vuqOx+sgrfB~ct47{Zsxwdc{8T*zR6n0f!j;|O`tDhv(^i1 zSet#WC8r*p$l_O}eGmsafyYr+%9ejk@5`VDkArFlsx1r@>)q5bkf(V-+{^S&)S2sAAz@pJ2eyr`irK@e%mHX zkL~8*y;!hy3%EcN_Sh*g>m~BBvnz_^qlx(Vk-kJ3RY;xB&ogCevk$@ZGRKX;XMgRt zkYD8=&w|ycGVrV9RR&GDRwsHc@4u}rc2{a`x=2IAaG)JMcj)Wkh-6uGVse&s@&!79 zU1-0ylG69=^RuYU9M5JK@Rjp#<<60Jz7~TGs}aPx+Xk%4MjcEW&qcGypd0P2haP}t z-w&#JZSANj=bj{=22L8_Dm%_qfIsupQ$NK$5t{F4G#TX=lB8|$*CzdEk50^m)9R_Z%ZE_Z<3M5T35y-qoR5nBBLk=flFHq8tk`+pE+T0XQowK&C#dT6%g`8shOEg&njkAY%wc zkC>gEgmjAMa-UV0rEKHeh4oUSSS7v|Ys7Kb(g0wlBQyNfXc=fZZSRz}z*tO)UQVR0 zZ&kLdZkd7a(v%}!hE{-<6#XTtqNEkT4bgeO$nbEt``=_5pb#DdrLOQoKYusQ&}VtkP=d|8?AN;1yy8%0+~B=BS6>8BwwQ}40|lIdT*3dofY$h;_H9V&oQ!~B zxsNu0L(iug2{5XZ05cgGnWKr_qPvk3w$=@Ioel2zuE!ZBO;=+s<6((cEPWx z9(pi5wq@Iw@^iHyUB)pN0r2N)xJ?4TnGU>a?{f}9$yX8L@$;*1Ss?(Xumkay2Y{N0 zUHBhK5kPy>a2S#2t5E=8Wcd+Y@fQ~Nj-W!h>PKF<4*;N_rMkAIy{sP%J&hI<$k!=r zjIVOCQ8Ct61>?Cx%|-Q>0Kp0_WRn9SsdDeL&5vn$(3o|p@t@9ZDpN9#&mHY#!`zN1 zjoLIe7#Yt}tTDuV-sl7pLYkcG>eszZ$?6joeC9U;i*eWL+2^46FfH7`hIPCM4t77g zzq8D}I!>XU99Hw=as%4OnR^9`X_%SxUYW$L`qqdHtx*=~JN7t0^h7!fphZBYrMhdb z2gz#u)VOLW3idqYExH1YGyrS$`uDYJ1N;AzaY&(Fb5Z0zsB)6@30&H0^|lFV@!mJY zcSFr(R1h4=P^#6*T!vflvy-Qg}>^ z0TpQ~&QZN*y#xdrTXpPIqkUFI@}bjIHN-R@f?@^WOh;F@(4gRs`IUvfbdT#+pio(H zI*t_S_YlV_{+RzG65eT(Wy;+7BvH!FJCuJyA{kzG2I&8SfPKuE-(@hjvicNXf-kn& zw5^V;-W*}cJ~!JIt-YOVDu7nDxND#a)Rts0r>}fBo zqu8?P!H!sT_`Oo8_;5}Gi8XT>Y5`zm%)Wj2cj;pTe_!H2rO{X#W@c=RK-3z=?wIYc zF*9!-?gyjD1y{3I(gHdh~q?HZF@fQ#Y0MUaG=RW+kj)2Ae;2?8mi3csJ;sEN@c!_ zYwZT?3t%9$bC|FuHYX5ChtXqeW9~T*i92_^e^hVIq z(n3%`eehqOZm#fS*to(N1qK5dUJChTWi)?bUT+GIZFVj+tajfMgt!7xYODP+nx$V% z;K$4ooO@;q0C`^hG+8f|qRHC8rpVr8VTXK#fo(~BXjD&Cp@B#0ci8rFxQG-Ke+kAc z$4u5xs)cfhVfvf^i@^0c-fgMO&(nvvS~EDqgZ> z_M_76c3aZt&jMw?h{YzvR{;3lqQ82uKP(`YMg%_7U&Up%-Ne*SKMmFmJ+h3#=Qv=2~4pk!A@B`35zXgse276G_n0GWW)v)Pg1>z1&&rnia1#7wbD^&l$9v#aV2E?ETwfaEF2jxuq`_%<=`|Cj zJIpVg>{l6THL0+-@gpXl805 zIV;Cj<&wk2ZB|}uEw85+Hwppt5S`5lz9&U#sM9I{DCx_%vC^{cZnd_)V8D9^2?G!I z3X7e79{M6!mxfE`hh|URz9q1Z(ZTg{CfGfw*hyInC}d;LBrO<#L(~gsx(1OfN)Sz0@0Zla~ae?+loD~ z*AkRj}1kx{^Md=EMh2pHL#>X%%XODnk(_zOEp z(nJ@BI%6pp_h`%Xmym;_ed2rUbF3n>h*j+cisJJ*oQ9MLni*?cl?R#$8}19*r4>WL2n+H3~V0&4z5 z`gJzW47_5mT&PTSI^K{czLT!A!0#RQtxDTJ>sZTv`7hY^`kfE|Mw#{84z?^=JTS#1 zvK`2`m!$~e0=wDjj%7|j-=C=kZiyCLhMJ153$!BPA`1gZB1i=sH`evCPUGv(QN>S+ zw_{o?f%(KrxiY#mQVhPvq;J*CDmZeg6wv2l#ApV<0Ec_-f!fAQ(BHhm%66Q+3q$S!Kp2(be! z36qoevik90AGgi6SkCTmGtm@`dY-2Q)p3Pz)~SaW;E`;t920hqFYO)SX%~$iikylv zg2C4s^c+^tdAu@brxQy1Izwm9Sofc9)~Qr7{?FeTvNZ;!BZ>h0&=Ubdut;(bT^C&2 zOanL`FQgqiCrL23$~jhvswv>Q$VZCj!=;ddNwmz^83WSpTByT zqf3Em2H{$pLayz8a$jojI#Q}yY5)1H@&636+Nb~F&>2(kokTK=Z4OmRib||tod8xq zDasHoVw$g$#1DJZK+MjBc^SH*Wg473D+7Sc3)GZ`hJcvTs$zBqh)=s$6sNkkcb~^4 zC2`5p)d7Fy+O-etxxhsY(*>&0IxEiCRKPV&eDCFqBCwDfCg7EVBd<4rag3TqILt?I z#6H3E%E({{oM)AMRRH*f*w-`H9@=%cv;T02B=g7h2 zUvAKm2_3fG;p;fE%MShmX0o*tkg`a)_e?-A({O1a!B0H!@Z%Dkz9%Vy*033G;5LyS zh`+7R#4ey^o-W{0Bz^+y7B)HWK}^XbWBN`LQCE)PBICM;c=hf-B9AVshr`3e!)KVk z5K@ST$5ODeS)wY_Y{ESVnozhyA8CV~ltACM&uDo- zAel5$Fk<&LXoF6FxmGjSyB&+C*@;KhBV|s2>VfHD;7*mvH==xZeWG)|3lE=BxOm+J z9BygxY}WrC5HdW5A4>v`Gcm?BTo$>5F9YRR{-D-SSEswkXWn=NyZ#L5>Igw#^9Qa@ zY1Xfjo*zJy$<2ecR_4`-WV_%mdmeVE5+>xx4N=kW<^ZZ}dQo&>79u6iQ)b5)eqKSf zoIVPrp(+EMg5$<0T)_1M z>&JUO$4PZzS20bFrHz0)Ms{}4a{9b@EF=D3;4>&$#Jb*rsw4>6+#4b1fax^XZ)|7Y zULM}d-5ddZ<~)-i>9plo1oDIP{qCJIBG6x2;GOKTffKwlfo^SR)yUFPFcD#(4b7=^ z&mpV##!2rc1b4denQ*mKH*&{6AtO@+tM7riI7G`)V%B7wtM{a=2rzq=W+yS=%;$Km zOcs#J-#IJGj2DgbO_B6kjf)emLzk4}R`pK12e5)s!WHf`X}C<*uId{^3-iUL%LSEy z7=v+iwKYH`yTF!CU0DMIOmQ{@E^HeNlGtNwBbG{+F6oP|P+0on_Ok2}`HvWc1g!~D{AH*}A2sH@%tA)?*7<8~nUx#}T-*gTsdGCJ&ZUjtEz6qe ziIl!bd3AZXq+{DszeG!8|E@Jy`UsmY_Z40LJHU*gNI4R0QH&)A+Z3lf{6jP~qfVy;;6{sEG5`$#TDM)5O7kV$LGYJCgVH4MwkxL*U|xCc{>Z#OHb4zf zhkJ^&)QDTZkp#c?`}Z^HDd)(?#>UbE_QRJ4?vRs5fYnDUOG-J4AoSA&eLr|oU%PhA zObY5=wi0Ep3l}{3gYqh&)IzoN`ursszpWp|B~FvZcaecd#z*yDl_}+ZYs2~x9+-KO zGg7|?h$;kr@z)bpqs&V0^qQX8zeac$jPS9BdIkTaqdiCL+$&&~{;;{a@(&|`P1HC; z_#e=`=YQY|q~tudgUbDkx@Ff4K`eKeV{JM(SJkI zYO=MzY2SVWDyZ;?m&tsmy&xUrG2N&l% z(}9L}>^q?ekmDsWJ-%rmr9T5Q3{%3mU0=#gnS+rMa|pz|&fmyb0x)KVBU;9*?q|vW zP6M?pd{oONY4{005qdo7?|(YnYXQCQ(VrGb?-ii&AXhLIPmk)sDP5f`I|5JJmo683 zjA-evE;i9GHe4NjwX;Us1t5KX4jzyngkTOk2M3}v&Y)G$#$-gdr@LD^XcbR%HW724 ze6cjw0m3uUK@e}Fp`Tcp1{thHgI(XPxHI$l;J?p;ej44EprNWtxAQPDbGfO#x3?L# z5G^Q{qd8RFdCjw_*jCX}1QblI zq>UH=fg51MaW!?G%5gMQkerQ(N}aloW?ShrZKs>Nfe1#hl`lyarfJ{4M*iF8e;w>o zaR7Wj`mO9!r;bU#hkW!O!u{asJJ5qPrcHn|4+1F+fBiz#zpmBYJ0Qi8z5o6T!CLvE zpU$aMNX37{FjueW7ghmJk%cT|xY+nA>2CvnbG+_K1MaQYcUArIbInre@e&W3#jGw3)THTNcxt`(Nfi$ptDCJ6Rna4?NVC*SxUKdrT0; zt=mYonLXc@_lQL4{D^({^f%jO_x_3D`PcNIgoM8;Dk^%FX3)HWzp>jkF$Y>QqG=RF zsldN^{hMzy-F9fre$_Yyuyn5ycs1BI|NK$U#9X0wy40#7ke$%zD5xv@F73bh#+I19 z9+kW9ik9zm7s*1vRx9v+2GGJenR{0q{;p2drBMR$Peye!`rO-=!oGUnIz-L>B`fyC?J%LjuWF2f&HqUwo3ee(T>H z<>ANgBs*Q`WFa1^Uns)M3)$;y^!xya&*xwa>U+8-1qB7s0|QkfFcASQj@Y)@6ozq4 zPx%~%igHkNOBV+d_TH`ja7-o$hP%(S% zmSceZ3g!z0tlX8p%f-9l^L_zrJY&2E_CYJHooI3uKGHp7xWwq_KdH&eo@X61iq&%W z+KlkSMva+Uvrd25P0I9RrT*yM#Y3`pKhIMjZok0IDDpC&`8~;c_z?se?#yWex`fJs z=iZ)3Hj7}UYmuK5x$hd>8L z*Ip{ZCsoD*i8Fkv(YxQc>UoLNr=xr>RMixNkxbjN5-SWoLT_R*7azbq{{D>=4e!#@j)9Inp71;;SpMO| zhro2knCS+V1~xq!OHF9a+6PFwH?ZvIsDoZ{N?LsGlJig}UGGvCocgZ$92LO}B)&T7 zZZ$u5EFlX4l2DEvDRY-Vn<@vQq!xIXU(1K0x& z%M0SjxGRNZiK>#K;+SiZt1Ac~aj_UQvT2vHVq_*>1GY44#Q>PP!nT=@z2&<4LTT!D z241h=3M%Dj8}RE|7?9fP#1VfHm|@_FKzeAJ{ICtMk!OPQhlB&N`F1u5|K}Uo;p*6+ zKK*GBWf)SS=eCktvsP-j@RvfJCjT~A-dw};_$+y|KV3nk%h1EB@Oap@)Bm-96+3_# zl`82gC?#c5;Jd$t1IIPT26&@Td@)GUAzpzPA}2Lh6I(y%PBI@)icQ3FXt@m}Ey0KH ztYIo->P3Nvak%Gk`wbPZMQ$7;qiO96^YISgx;Fv3wN2A0mx7^O04I+r#sO?o(4HL| zoSVvr{!%~Xww7?CaFms{Onu8X#+p^uUx4R%I{>!$QlP|Vf-T;R|Q#KROc$D8RB(U1_9xUr@461g9o;|9&AW7 zKk|zf0cU1rj4=J+9tiQUQ|CqaKkAJyHVXnH#sVMzC*M9kNgFvI-;A4BYlHg!I&hhW6!ND;Wil0bn zMp55FKgdY(DeQy)ID1Hz&vI#P-lR$_tV@ZK29OBXLZ0R`9UD0QNS#W7p832*}|S5h{BiyIu$p+m50 z%6N5qpv^mhNa$Lc3~LZ#`pR>h8euVry=lJ8ynst(%c(w4MUS;+0vE{;-#UgNdOQ;gG8pf_9m?X^n#BaRO=XRX8S*l$LPqkd z3oyITEe}j@gZM0}zRIz@ygb_)SEX+b{KJXOc(Zq)8SSbZg3UjGVPL18=Bi z{BzY)KkR7OswFQK1(L{R)6$#c8Exn7;Qib~QMAcsVZ5KUwKX=d@Xc~%OPPrM;QHRC z-Hf4MF&sJdIe1y!eT({kKMp>>_DPAvrQa`k{Pj4|kq2BC7y4)!uA%0S*VorcXA?fg zs=Y#^+#vyn6>i zm36)6ubTjb9H}Y(!?D=3YrqXt&#sLbuNvf@J-N=f=>EyM@hT(Z443;=l8BjRawYS@ z?^h?(Oyi2cWr+$a9M?kg6fpumGeE6G%@%*VflV9uo<7oh0IG#=?%~>GUA){Er{&9H zGrokR4DFoYl*^7u%|!%jxKw4xLqT(WvA>BFXamaHN>rQ9|i@K8ivhYlN&vFB@UfApiNK2J@Au%R-MsoGp2wL%E*Za1OVtuOUj4rx_x8m<;*|mBNhEsJb*ba?RyA3 zfD%(~53QBg1_^$OG^~>hF$$o{LTmt+z1((%O+ItR$TGu}ZpM&g=oF=h2b%s zE%(nb|1`2wa`A+j?_I?h1?7{SteYpFT;zi;q+5vnJhW1+ekQN4+}UQlg$>rsi%;l& z+K!ZFwUGAHJSnQ>tRuz}=kyK}>wKMXml;Gfq~_&c%pc-xK@Qr z9t@?ZVx!{sTCT_rmIo}u98hFK+bUz2=NgB8;2z4Z*Uubis}Q#iD@DE1S|6?=C7>X1 z_99GiFLgOJRhGYf{R)Bs`rB5(p380kS3l+r$=ee&b@2>{=dG9tt+0Gpq8Ok1b>>kz=@)isQW&9s}Qqr%u zhg+&&=rVa7bx6~(G1mIhpkd#(xiQ&MF1K~z$%xooS;>L=5Bz*}TFk5CInSs2LF2I!c$fJ$ti^yM+ z6geEk>BsXG{fe&ru%OK9KO)a9K0cz`^Tk!OhQP%k-FqeabsrG1Fz6ar>}4r%DX9zS4UdlG_mm6idvaie z=`Tm7F%IVOe!y_B1)47CWWCg{0Nlw%EIm5>TI*hkDvQek5>X}yTCyLj~6$H7{nT8UsbfYD}7*wxMIdi+CM2ponXmbcn&qkIb{#5I z>AGDjVy-{ZKe#vzJ5%RIg}q+$T|d3yujp8ay0s$2b|z$$?6&lx&lek z3fIpR%OdwFwhn{D-IO_e1VZzK5J>|wIV}6?z}@-yZDGi*pELM$h8ZYR=pF6Fk4R;g z#a##G(y((>bLX;7;#05Y3|ya!Jh*xLc;9L$uhjb}-~VfSdXd1K#g$%u_d?B@q{x;V zxL@>n%+yD!yN7<-$@PunLt+jdBX+7uZ=!ag2Nq_fcvyi+)+GjZIhW0!fIFD+yT#w# z{{;-<%B>SfLtl=J-dz((piPuE0kV4?TrQg3ciQIK@S1CFeN;1?1-G)HwKq7&%y?JI z=U|u@_hM%i3($P67-+Ym&ZE7WD?AJRc_tvrNUv2dbeyv;0w`E!%^YQxB zZNu!-18Er>W$$CW($A8=RJz7rBFD7PKv3VZ@-k^_ILe+p;Clk=q(1y)>Lcf8y`UUB=@%7$g}#hPwiW!k6wba}me+x%_q+g>s_qtRDC( zlS=mgfVwl1z6gzB?d|uu_zd17{>8*GCf<^nqdZ0Zg8O7E}fQ3ei zI7!hpE$s`$WF8&Cc2c&1YbRD>F$Dt3B~k?zHN8MlFg^UPJ(XjQ6LL?jB9RaoLqnS> zSD2Zc$-}mm2W7U~K#f&VpOSMRwLE!<2_H0PxX|VO0XUHC8F*wRHOv!6(cZi|+NVE;h+IIz?Ly)zpBkEomYfX?l=j z$R@cYH}I{u4m*aQOR(3}kT@tzs26z$!dRt%_E;~28!s!G;C?TVahK5r)*wedSfrl= z)a%Z4fa4QB%xp=}->Mih&C}1QP4Wer&Kh2;7X)4sj_NDH4alnf3}2u$=>ZW7+fXIt zKjs2#KOlefqeDbf;|tdmA2L4@dxDzV|qDK$HbUarXh!0VcZLUb#iO9Mmu7kutap z5Xr!|3mlnF35cZj+mcTA%C$%#&^ka|&-s9$+zG#ASm6hRwrHmNhajLu1mDY{r|{gj zSrL%l8k$$7W{Tb*9S>=`R^vn**8TDl=!*ZjUfj-ho*`Z(zU0+$9BZIFB$2qA?YYN8 z*yxn*y}3d-Z{J6-W60+!)^}`uwQn_Ff%>p!XCsZIufj3EUFnE(FP~jsC>p(lOF^|v z;|4Dnll#>b=Misb;nynI)jgcC<~YH_ZuHiVJd_~!y{RWl=aJ1pEuFg9?)YxTuE^xI- zhgVB9zwPANsdM1w&$;3JU%R$NbcRCQ+@%%`r=|bhwvR`qQhCi3dHgJR^v%0xuUipm zE;mqJBN(X0&rx?hF&KH0P~XbG;9z&(1~f)J{3a@iKgIbLIXQog{{rD`%H`P<&RF&@ z#@q1X{D6{V=xE68obB)ggD1I#Neb#@&~$C2$Q%On>db#0m{IZTo+4;K zb9NrYR#lp3igNFQ`UX2L^{)26r(;e^uz$qkaK}j0_{Rg;h0#kj@e`HrPP(nyk=dcC zUe!-z&ypjjFtEX(qk&5kFh%Fxq?S|bYIEb>GZUQ8=1#o4*;wr~t@@&x*9h0u&R<5$ z&i3^t4ChTw<*jj=>vv}<%Lje%Ts(AZ)8vT1vK(9Dy6$uayGkDok{fzrk^Hn;wCT%cdjsI zoVq5-25Aq<5JHwz?9WX|Wv7ci5tByFd)f{<+o#X4j5_JCo>g5=FMYl;cGi4lk(Wp> zcsNzAI~UpBdxiRdHe8+X^Bxq+X>R=f1;JoGEJv=PXx{sY`O;sWK#&iSX9jTho}|Xo zeWgusfs%gfdhpjpAjBfXtk;hNNbBAv6?xB0GW3V`2@dc0wIpW}b9+T#Z&;MU1US(iN>+Zm zuj61y_NmFF{Y9<)imqRkBdlsq-g|mPB7$;E=Dp64UA>_YG?@rGw?d=gc0q-D3T9c( zcFHm)?`Z@L)KN1P^XCd-*NQbNE%nOnfUx~SmZlWvPyR_yl+qb3J5*o+?%xM+@SODT z@0lfSA7MT3)AD;ol5Y3Mh*#IB%y(^Up2>JXy3^m5cMFOeEX%MvyLg%LaC;5z%)4eL ze~}dCj{5q8`}t1~$H=2l(AMp?^&{u|e;~t>#Tx?NDS@I*ci>;WMP^@ikMO$U_UxE7 zWg4#wkN5U76^TL=-irIaz#rF+gYHyZ*dG|U2Fcpl>Wc`>2vGSoC_W@a_es>d`Y62R z)VcN_Y|v}(#lSEp_nRuz%dJ>d#KKLdzRcPmvif$e{z2-u_5lE`Y=qEm+0oq6*}F!$ z9~()N|B>t)N}W~n?#-h~{VD^g1H+2>zRfM2nirQDukvqvKMp|BZJj-Rs+pA3{(H?z zGoB#FPr&mrBm-)uR^B<=4>el>a3FR|q9n{yf@k~ZX**>OfD53Z8bRJh;}F2uO2n>$ zn33_1^jl({gS#Oi`8{Tk(61>>2PemmEMLB|UW}2N-;|eZEyT!40LNint-fP(p6!rdGu%WaWcCQdjb`Pit_k5IL@8^zHMH8R<}NQdUVNor-ONK1M}Xw z5aJoOI2Gtt{lt5N8^>|^A~SeyH|6iD4FSzXIqcj+=C&es$jNaG>dSq0X%9zJJ58u2 z%pZ-?N7Fp1N!mJg2geBL{S{N2+295x(D|Kqd?!FY-GlSish1c2#-)~5U1ZK}_5TQh z^Y~L9jhyklkk2lpSbu?5wx&9=_^Yj6tP4DW`BAp4B+tqwZmSbfI>|9L#@mz}TFh=X zH9cILJEEEM{)yW957U}$9s!>%Wm`*?uouI{?mBwVIiIq9p|&%B9T*Do84r2)0A%uj zxvJRtz%gKM2X*AwZovIX@ERQ)MtR{^l$r%(524 zUx$QW9d9{388DCv@~O+2h`sm0PGur#qd!#+1KwTt_MhcI-f61)bHgfFjYDcL$MZbL zUxn*+PoPOXTtcLGHWB2L*L}URF>j&+ZvU#02d&|Ix(Q=lb!ueg1AFjOorufUYT$>! zH%I)sGm)k>kaOe!b{;#q%`!MPhnY^9?>=S7>*3cM{(()>8cJjQ23_;xNfI(&QZZA!D2#N9X#jmfJeENf?iP7Gdm7*^J|hsDmz^`mh6rUK85SD zwxssZCB~M!{!6nO?}@vAZuKm72vNpYbszYfuPi0!X-bQ+`SAqRA7l#x{JTsQr0I~_ zeUs4X(D48nc!Re$0+vGazvp{Sm;1SXq+KlC{?2 zD^UN4%2>eGj72q@t9XU>o0pS{YTIJk7!pdgR~K`*s-M{*Tz2l5#oZBjsl7YcmU?Rz z<%LTo%vZDaigrZ!-o-pBZCF6cN+_sm?Ry$45>P+NT%WVGj}2ff(v#rJ)xBw1mjq{~ zcsV*w4Ah(JAjYK;a!rH0;Km<_)c#dp)>WIUU(pM0oTxD5nL2IwSUq4(C^3Buepiwm z0+Y`Cb88z2VoVg}wstaUS~~cjd*$@?_^{N9iCnovJ@Cp6*o!&2;-t5SG&rix^OTlX zn~81rkl zp$8|&NTKvz;>uL%*;d3$GU8+KOB{vifm&m z@{%P3BZ)gzpM#D+xdEhvrv7^fdGBoB@}-S`@Q3AX^>8=YX_((lC%4aRo9*KZlM&{y z4bqw<-0P^Ro=CU2QdJf!9t!HZi1+FiZWT#|F84)OZKFe`d7hU&%YD3@wL{q+>H^-F zspLmaelek>zi>W4KQM|EMMcgzaz96xrXq&RSx8-T8_?24sr#z>#!Fe>+}b#l*RHJt zp0$VpZ^TR?NlYu=6KEh#?|F%MyHpu}vmJ{2&gz1pHN9) zjb5OzxH7@s$zcK(kx5r>RXU~ZEj7o&kNUE=JM(HPWr@@I{)?o;m~Cg7Vcm651YS-9 z-q;n`F{1y&oGqQp>{W-qud;DEtDCm*$^KyXVT$+Mo9LPAl~Z@_%*%iFAd zsfK#^>*rNSrTYvET41-oN1t*bRK+x0U(n>c-$WfdJdx&H;*gnjVk?ro;oRE+_3rq! zKE;$Sv<4=bS;{`8Wi1@Fhzysxo9=}6(|!2o){VkIk@=jzCi-vH`lZE26`k;2Q^1=; zRrEF$djHQzq{=d2T=NqtJq2ax?NXo-Gr@cS9&p=in~gLo7izly6sOA;XWOAxHUi4Q z$?kZYSuYz@8g_Myv*Xid-D|5d5h+zaxiU~~FGcbi*%R!3MX2xJxw68OONr~tv?5Xs zkA@87HOL_m0ZgUdTUTJax5Yc?BXw6--$#EWZmAu6UOaWG@*nN`@Iz^Fh7oT(XRJ!3 zuDf?+CPU#w1d1fZVmmm&O3bi$37VVs&8B4S9P{+vbkbLUn{3xud(+G-LP}Em;JPrj z^LE>wtDs&?IETQ?6EK5P%=YGtq80VEk5gZ`C2k$T0YAbIkI}+)SJz@SzNOHo)9tiw z15@@M8|s5g=yBoq>t8{^!1!6ZM{o9(%}F)1&a_uqI7FRp{Hszt>}#>aZEX8hHTHG# zbv=vlxg0>)Kf+M-@t8N*ZAC#8IQc88)))A_uD5f{pbA$GG<%Gyox8h-W*3T5k?wZu zgvk4)w4T>r{b$36a6d1jPzuw%aE-8*+sc6G1UfUCleLYNm2+he7lp7Yi{$_QtKL7C zRD<@<{roesOL(=^^E4mOEqV&vm|$AciKeSSPo24`Q}z*kn|?5%BuvqH|9jbomQ%-V z6mqLq3vMcBuO)#6`fSWYERR|+0J?Y0vw{G75BnN$p`kMwbamt-XM75i`=HxoklHkA z+b%Ns@j;Z7p!sa?@d+N|>!Ux^BzAa`wuAFcUw}*uNSYKE%S3w(OI9kI6goSv_&9`m zNQPHba^1+d8+J=D=2g_I8#glkc=hs+KO)*QKDA3LFrK;jF1VY}G=W)-jU{N5Lq8n! zE_f6dGT0V34ZG&KnYjhj?UdkFRy&XLiu#xW?CptYwKMQv_J$&!(p1A2QoK!$(TsLcY z5X8n(aYvZ?LI8vYf0jHuoxT=x4sqgm5OY}C8V{Gq+su3|LwjOw(4g()w{=2q) z`{pe9PrmV$IT>r$u9Sg$j&5rT7ya--+rcYG{Druw)l`MjQt!|rL~c!k>v912&eK)% z+90#4U_x$N^px1VrctCHTgu5?$R&xEL7Bp9mbw}jPYvGdAqyc4{2Ga)f5goA zjIASJ4!7WF#NF>llWeN3V1zHmPw zE>cizHFfLYneog?oC9@leX5?D8sYujlkb$mYF(47S5(|-^bYP;OPcVyLS5A?-}z7M zcN@e8u^OwpLi@~RKi!XYp<9&9)*!YMkMqG>C9RC(&b3R+H}wnq2F<>-F9SsP46IKnT(2>a;aZ3fX}XH@Q!Om<@EEaf^TVVa;0m~qVW^9 zSSOP->72VB)&T~TM=NWx28kYR8HLQ!H(Rr9T%f^UkCqVuwL!ea#2rd8dCSjDQ|u_C ziCARY($wnl+&vpq+tPLuVzH$=bh$y%j-Pqhbl}XXs>k5kv!VRcoIbt4@<5Zh;4hz` za+C|#x6ybs`h+m`-FNStCXGKKy^mw5$=P6=ty?nMawkCb7Tf&ju<-6LpuTdh~W+k_RPZxYbfhV59 zn>C~%?-dm1b}hs-%GDFcW~eA7kGg^rX%gt>*@K`WO_-zULznGcRtP6-uU*|t<8dy& z^<-qvWXc6=fBI!owy&iYWG-0V$jG;WGxQv->^?rOO@v`P(#XJKZ_* zQ}5!9H_jW|f9a13M?Tp&<+!Gb5D97Luw^Qalp7-=(UG2>7ET`pd{2xhK#2 zz;~$5eqKv=?yF57*=i1*J5TwTj@P&0;=I4$tZPhr>FWGl=96Qe%GP+uhlp!wlYJf~*y>}b=#!j*G#C8^p|3Er$nmR41? z94C*mR3a*>ZFrZe99wrpWxP#SL^#RusfVG~6I1r158;21h8Wav5k6=8t0aIIEMT`p zDlKgA%N`~gERW^R(j5!_!?7vzi|HPqYC=qY9(#H5rPknjvI;q`2imoR<11(<_dz0W z0FUbC zkJP}91W&=_xZ!y5WUn?;w(8Dl=4w3Uh}p3`3zBJAgH&|yK{S4-xD)4#68&BT)*KD2 zje%MfexiOTL4bcqIqJ~-Akknw1SPT_y>MSKptD=+Jo5ZC)z_QW>)-UPxd6HX+lwX> zI{r|V4_&PvaSZxHhxbZ?0k7>;WkamorJ^UkPqe?R4k^nexi1#mQFlAk1npxEau4@f z9D`)U*TV7hw~xJl85&QvvvYNt6HSMhCB#b||5SZ&N5`gt?9}tuXUX3VE!REy;-pDr zv*`Lf^Wj5-6!D^xMru{si=r2+Ug95B~slj0D;!#4-t{f z8|gdYg)`ju{vYn%JD$on{vTJ01}Q2l)Y~euG9%<&kzHBYq)2u$k7HIUD`aG6Z<4)^ zE!o5|&#|(Oy*bV~-|JS?yU*|Ydwl-fHA=Ue{|rU$5)BY!Kv^uPj&iXZ#!SOw!^UK(w0^YsKrMh@l%t*ov-;<&Q#2>r|Ef;n%KbImHg?3~Rrl($5s_S`4%M9u*%_^Fs=@fLja_DY+D^gL>mH<@r9-PP`^C5t{7tD*ukm2amHys?F&MqR?AzFP zBp*I(9rw*iB>5g}tr02NsM`J`Om8SR$khcy@jqu($;1K%*(&i-AtPUzjh3d5J=ic- zLE1&~E|{E_8HycUf{0*`WUYK?mxyM^n1lZXGyiBDtB_o=e>82hNrACVCvCVp4N-NGmTO7>F6gV4hr4MBbUlWZ z0?X13_2nUT(Av*`UduYP?gHlM56@EqGfr%j_~`OQxp#kHToxNmqQ}YTepFT0j+*Jeh>~1{%_bJ`$M406 zsJckkNkW1>_4w5nF1?NW^IrNaX6hF4=rO&NDVaS|f<}t~Ro-^>us_82F8LnjQ(K50d~X-3~MZt z6U^_rR8J_)N1E7T4x{!Mk`Mpozbw;ObH`Qmu$|B^_K}YSD|pyTx=B)^1XV0G(ic1U%3fhw6;O4fxDf^e& zs8hZ}EGM^nq(S2W@vN*!Xe^V8cu7eK&=8W6Jjp?n{KA=ubrp5055}-V9XcmAa|W+Zl#;~8v1VIT9jCjg!okDUr1jkl zILF;172HqX(&n9CS8C}U528Vl#D!H7QAue6T{8U&moo zj7h-w4&=67W`BCq?4HZx_6-SY>0;zjE9W9ydPjlu zrgF_Q)K;w3(_hjPxw?AK-bno{@QOK}dy?dnu$FwZnX?=9XJWsspr=JSKb4wZShpL~Ktgny z$wTT0TdN~ylx@?Bpc<)ftdQh|B~-dHeMuDX)*kp!3B-kb)%woa3kU|>df`pK!$gUo z;B~k`F&a7ZF;I$=lQTo~qVVFwL2fUv>x21=;_!_@8QWFQY&dD&YlH~D&S$Lq@{b=s z{K}6)lsLaP3J@-gqo-pOXmVdO>y)2yg~!WqvEYj81&F@x!@ zBG`g|@s$X)XkamcpJwI>t#|<)K^WYKo67O6DsEZj4mUdwVk{6IomE^M(Z0e?MdPxu z+0K1qXuc%Ecwu1kl`oEzx#S8o>JwnpoPh`@!{B*4sb+LuYKavc(M9s(WdEEblfYt0 z>7d0zR`TSVqS!{A8QXLJ)`Bd-MKx$NZ-H?1)D7x3yc~?gCLbc| zx)(u8^5n@6(o>8|m1@|qmArt-*Tg}3MOSUqlq_8@xHT&S&n2zqI9&(bS*HFkpS!0b z9LwZ0A3hgID6wK7x;P9R+4rH4gGU(^cPQ&NP&bMdNL+ zr4IMrIF`+uU*_zjIGb9{7p%YuV_K#*9@QQ#Uc}zM{*TjNfHTzHL))QVCam=OdYy&q!#iMseJ$Ry=11UJaL;e_7>>hLBUKsORI+Vn=J^R`4+l#!# zJKB<`v}(E0r4}+pDOkdwFkYOD@d(LYbl5y~g#0P%bBP!f=;qP-BpzIBkQj38u-EJB z_L&AN-#<$3&MXE<&g{Os?@<+}1g7wG8zRk1m$O6{qXj?~a8$;OX|`j2Ek{>Pko|6c zMmC{SMVwR+u6705LG^Q3OGktN4Z2=pyH07N`W4 zs$&JxCIMOEm0ee1!yu*=-pnE3qK^xpbDcng)a_7z+e&bf`_Pj%k^~%wZF^@V8*A*s*@@wPd9#TdS+x`4D z^G-$N6TmlvLq%Ymmhog{y;BOX8B=35esVcx!7WBQS-NN9D4uoJ_YBa{p2l7 z;PO}wVB6+!YnUxsfaoUOyNkRcKQf!srH_W`V`~q2$viP;Oy8jV)$vbB*=;=;3BEay zwL7P2R9lWKiLQ2uEn>FX@FCB>IeLcNO+pl(tg-F(3xy-&HVREAPufa^) zM5bnG`KQ=cVUbmFe2}PcK>Q#B>`kO7A(pKVBP71#c9J5~Y+>*y(Ou;;ZZ#J>xyyHx zW8kkBP+x>U%F`j7IavUQpB)3NCl0K}Gtc?9jNwB-eM=cwW7_f7yRuUn@5q%zwmtQC zcd}`}OrE2r)~L8`&_M%<5El?3_4xAq$5S0v^`%JGN#)G0A>k85?+gDqMn+k<*w=&m zcxXz`Ef;MK6=1^~mDC}V4CV{k zM~Lp4bRHq`=<4cnvZ}I63a-HygmGjP)`b zb)UysH%jYTTH&@JDB}KBb@9VTr>7kqd>VQVW<7l)`CoFjgqyQ@w>bC!F~ zpMZO;_DHDdGSN+{H>|wJxb&B+;coD`?>Rbpg4d4?;E6weKL1k_#qW{V$y637BR@9` z?9uDG8!@GT?*%}Vez?TRX`D?7yFlTpE66J{I&spnWL`3sp3ikNrb6+atTQ+P@8&FI z>o{Ivk@FXx>(&}|UP7`OKV66ffcBk;e|V2&p>s=C$J=AzD7zllfsqDnS3!fN)T}{! zfhV$QcOinc?GY?2Y|2XW1K;R|U$jKnoHTOA_U-c93`(Ss1GsKDOCD@w_81!*1FMA_ zLpnqQ0qS8RMWVL4lXEy;L9#;*$z3Fn0I=jJ{sn4!F?GbE#k`Guyf9xwh9(hFggpNd zl278a*qC|j&>anzoM*-zzG?+7(4wxqg3%sa)mvkeWYu>*f3@qPY5J zQXW#%wE?|C4#&AbH3m^v5Ts3W0aNBb4YiJt z>LH>!sb53kfZ8WYJnbPh3#o$iy;CON|4Vm{W{qCppWkEod4$`Q#QPrAHtaFfDn7Ft zT>!Etdhp8I8I*0j|MwReKw}5a#ophbB@kgWKx9pSzUn{UA6Bwi^~vaS)`N$tFGfa2 zqhT8+Pnfu_aQV5of=NJ6pqZ+{`+rX{H9^QYcA<9hDN@W_d5spkHKfbEjsNUP8cRdj#&5h5b;~>8Wd(5f z81Z8*xegO`NP0IFAgs{yPuQeKb#d6#Ywz`pUh`B@gMqoC+Cx@|&HKcmj_ZC&qhvWP znh)l~c|Se{iH5>xKlpB7)!vuxUz2PN-n(V;x;*IUpf*+&OHRzsR|z;%9o`5FFsv^sqyRa-Rdi*c}pp3l&<_q!XMsvX=dd%Kt&L!Bnf_)y#Jx8l^v5XA&RCRQ6 z)Hnd2LC@(DM`Ev*mRr$GZX21lIoB8JR%d(u(S(1O|Ki2JgJoiP*o-~C!6C zp4oD-m-^f;+V*{=MmXcw-{!brlJ(8epT*MYRsznwBwfqlaRd=P`sl<0n%r1Y^(6VEl5Smv@=C2KrSDekz4(VWE!)gqa0K z_KU4#wy$o(?57hS8=q>_c((asmgncqK^L`v3f#p1=)8Dt3vWSCOUp7lmhI4Zww&2K(~J-k=r(>+Pbya;=76He`HQqMm6FA#3n)?KBfLmxH! zfxKlpj-j*A#gC28|74Yp$G}L{Or24L+1V#$^YW%foVd|hVbxLKXv&~`TCTyv%e$6p zLb-a9Rym9xRJ(@)*T=l5doYJGZfLk1hzMsZPMt0()4~JcrP6gX^ zDb_>DFK6_rlAhxmNvq{|1Ec}rTh6?BwJNprx#}B%Lya*Ey4|FQ@tU>Yvf=v2@HZ}& zIM95rlMmQaZ_x5rQ!7~Y zu9?Wrdy)D^(fPWRZ-&3-a>$HZdKET>>iJ~VlNx6cCbj5REWtOK6F_mi^4e_DH>UDb z>H|gw=UI(MWq2hJc6W_JN^2;X%=?Oy9w0v(9hK5}q`>mz##*}!kzY7(1_)%Ph)DvR zlK40oMO|KumNEG{o7y9$^cTd^`+f@qLbl^L*?IM?T*1qZDbrjAXXB{1F!0;p{Mjug*v8UIsh!tpz!N5 zuZzzCyYeWH=rVx%JH2hGOcc~A1U+>F6EXOKqV%ZM|b-K zO{ISrFbe>v#`>YDsb^YtiKEBwd%{Woqs(KIF42bUr@$4L$4k(SNt--QcDT|1Tsan%uAv_(=71m5Ez58lP-X$T)<1eh zdTU_x-TZ<-4gznuOsh>~kC55Z8A`cy$Oa z0ng0|@P&liw^txZ>(smp>pEg~r`12nqzx9_O>XSiH`=^}gD@I^mI4e9r-`iw{Fc zn>UlwwXb9YLz`c-hiUn^zMnYolXN_)C(`(-=8*`5QG=YD>rY(#+7}A`Fl%ZiK&`hrOu*mMV z%CTaq_LJI4hAPRebi#(u;?DsWSocBt!5RYBM;NWOvhGu<%g3I2h1W6lR?!H?s8RWC zL88E~YXvVp=OZDx^%}7UAw-^6B_}JiK-0S5zF{mu25;@)Eg+eIO*Hwqiq}otXarug z_Lqu{C|l#7{c$NHdTpt;jlihj zIPAdc&kaPMd7=A!oy$fwMCeaujOVPRzJPOETP~H;EjU7Qy~IfhNjs&(Afsk_%K%!3 zpWLi;9g{aQEy=@!c%T7bWg8otj`de6Jn#PM6-3HGpx4~o)Cb6A_Go<-18bnlJJv&N zbN(LSl)kf(^%}xfLpmv2>#$eSV)n68Zs5%QJ-|>V0=LLc>@^GZz4sQ{$&QucJ0?Gg zq|4F&VfH!_kncyP3D_c>Mp8DFQe_;-1_|>l&aGyjES2_)KKs{vdb0;`Nfz&A$X_Q(8{B>o^zUgua(fnl3JjNf}^Gj~)(%B<^2q8R#R< zdyGLMN*uPJT`QwB-D&nUSe%56QOJHE=)te&Xm)otH{C|R`*75gytM~}+66HX zh={1VOS3%wc#Y+;F(cg#^EqJxj$O^j>vq}f4ih<@=p^s}wocsDIN%;5gVQ@p2?g__ z_L8gUN=-qbt(r9IVZ8okYs8nh#Kgqo9I_PqFC))-NX6ymPWK=u@c@m2<3F6tU?bHR zC+q+nS!Riw{Dn6|Q+cD)4GOy}u&36T1XkW*EVDN5-w__#WlGQwA6ipOI=$~2n!T>N zxQ72mLFig|+l{bS>*SGVe=( z?}gQ_dX3?$ymw#klR(hK;GVjAp}}Yu2o9IR+KT&_-v+VoyDF_zH0J%K<4ugjZ53Ou z)2(4=9)`;Y=`z{Y0(1T=7iu zfi+-LI$X^JvyAPdtV_Rj`A>V~w(BFw;MTRRW()SQS>qCv*R&9ZwhHno;s*_Kf0;x-R16I?8Pz8(=C z`V=U_z3D@YZSXB$v(djGb9@eDWtD{&!iya1oB62~BXJv^Nf{1vDC%tv?6of_-4gqT zAqSA7gKAq$TER)St*?Q1cZT~wD+ANO1*Jr593&i<-d=LZ$LOZnEnJ@+U)N^V{4s8) z9ZR?MsE3s@OA#wUEUgITCWAn+$*+;%h`oU4ER~R=0rO{qN*V^fs<9yob2nHi=d)#Y zD$7=a8_)+RgWxTLdw2)M!lCdc+ZtvpOl+M=+;n5;4kz%TP;s5zAOT2a&*d`ZMZ&{J zm=8JUaL!*Im+R9V*vGVx_&np?;Z9lXWpl>**i$9TJ6@&I7oKP0NW=H z1jebRiJC=gj6y?~kN}*~7~YwX^77sAQ2dK=|D{|g%*e|NP@fylV;-;0zEykm687mW zl)$}*sxE{C;@bApSG5ZYyWGL#(!QMcesTi@iM5MUiw6@&RmG*IregVtl?VfBz?0YG zn)kKMcHQZ(uCK2Tr0#%MZH`w)}7WC zoo3osbt2%-vxnEt95_QiGdX&j(Xl;@=Tyznl`~b2s!AH>B_<6~) z3dML<{QIp&IpWIg`N6yZ)z$0nubtr4uu)oEbtbbQxpslEk;q&y`QU8XHwc+(UR^P} zQLPVf5fSt8Ufp%wBv4Sd#|41^4JifzuOZn|5m(owOxxl8_&#fptx+$_% ziI6z2Mn0H>$yhr=;yM!r6z+DvEZxt+PPYF85WA^u9>Y?EFvWw z>t1SBf0c=Gtu$=T!aI&bH44E)gy||gb25lG8m47!oln7MvQNRiavU6=ZDsosH?@BZ ziB_=~tk{gJ+FJ_ury#s^!NpsV$`I@%d{g5UBa4n|M8lTJL0|lwVq|0}XA`@5uSO*& zW}0mzI~{)XbwY^~z>Ro($vFxEtW&gx3pnZX4kKvTP(#1H8Q9ExJ<-5|lByJP)-R*~uCd zVyJvwaxonwnFUW^(p#wU+Zev5HTnHk?B}D49Dm5?a68WRcN!w8;0?x1O^VO80$9Md zC?cY`raDR*9pGI8%EuRlvAU@}0v$X-?#3+(f|%=Mz|7QD9X;&GC{G)iwEZk!eC5d} zPp0zcuZa|w>uws-7cFFqPFD29z7F7+1@W$|sVQ6|?dzWq4b!5Fh{z71m5K2#J{^rq zv#{=oU9?1Q(aFg-FU)nYizLJfjAspyZeG}V;25Egeg%{nwGK?fyRvN47yzLFsH`Cx zk3PqQbO?EOpjtpMmUM;RGl6iMp5IdLT9|JnuVDFOked$ta7NL(g6;2zm276?|kwqV`T~?7}(8)gX@+ zAkm2d?hFNqzIDF?W<7mE>&9k{?}$78lNMUxeMs~wnu5nU!{3`)?ZI-j4F6=M3U&m9 z%*Une7p|x4WvKqMZ?YkDA*aQWnT(8b9;E+@Q!J)zs8XO5-wt^sG7BBGRSN=yMO<@2 zirf0Pcg!X&5!7nr05UnHyz21eLaJ$B*QVqtZ;SrG`#G#DD<^Br^gn({+^8m&Rw9>{ z*qEDk&Uyg0WJ1rL3(K-LE1da=^1T8^^6BH3M=wYObtmH_l~$pGn`A?%o~I#yQKB3? zl^H|b%S=}M5JbfVsuksHy{UU7K*iH9z?|C1V5uLiZ)^?WkW}ZQ@C6xqF%q0Bhe`Y+ zHUfkxCA%E3*>E+|tD2Q;yKkz@R%acP?-lI$h10byE$?IrlEW-eW#`U27acnJ+a#iZ z8;r)cEQpi30zpKcJ;zcS<7&SI`R|#PCi=zzR`E32AuT(lTVyKJr>3rs-&hfJknG}d zX_t~BUsQUywLl6m4+^cZbh!!u3&vlu?VS;%3eI|zz zFUNs|&4QKLa*U4~?*2^3UCv<;aV*|2!;q03X37~9HTa%iCc2hIcW!8N+PyQ_c=4Oa z>86TG&25^0MKj9Q!@*5%eAZx)jfK&2az8a6o9nS&7Z4{3klP3^_F72Q(v!b z|2R|Yi{T8G2?3lE3W@%Fn3b`nrXSxe;)513C&;?Isvu$lPWzSf{Qu8}Hdi_?{xEJXc*Hv#)Pofdv8+>;ddE*e8b>qDgxW)5wC#Bon zU86A{D6P-S#wTJU>$3hwe8$P!S7EXU(90J?Z>OSNCZB+;JSPuNj_Kog%qwbriJ2C8 zDle)q7H;3P#Qz`wPo6v>;4AbQ9mbsWMb_g%fPHr|s3?q^uzQ7?jk{!Yl5kgt@vpEL z6<&1N@!LIb85oP3TA7maQH|DUgouCo?-&qRz1@uf3jjh;NNPpys%1!Si4@N|xILr) zt0~BT0B;SImrvw;Yid22T{;)RRCizPcZ>?G^$2;x+t6U`fU1$FN|x3=O(uHh|7r%R z3K^Mp>zNg7(k}qs`A9lHVLtM&_s+T$Nvk@Nd4O`am$P7;!|opR~1kZh2XR5oa7qh=ci!!dLtat5LEgKFVrq< zo1>>d1@v!Z2Y_fGFwh?mzt4C4ZZfU_j;wpd7xLkE#18`OF9;KoTIov1Z<=AOK!fgt zG65SpO6bWzrqr#* z7jDKkfBL5&L4Z}2f*%CwR7Xi}Lq!_k`EL^W&*U=DNT6zL7+m7rZ5Ihb@Gp;gWE2Z6 zcMdWKeZ&yb39J-uZbK*~8eR`2tPAC8lNBNbEo;8t=Dd8_w=7ZhASzuZA+f3~n7~lO z%N{A+Q!!Y&=WSVyZ1j(%G?O*Gxj&poWMr?&+(v;>%@N{CrK2$)tmNO?fpU2IvNO=m zE%5At5XNn;Umj^ewLiR1r^7*cQSVtAmLcm^wood=MRFtlLAhDr=%(0?hT5=faB>ig; zQZw+XWnj{q^}dPL5N}63+$xLh)EKwJIh-+L`wCA-lqy zDA@df9sPI)`)|?p^^mIRwGe|U4ufS+W|xezi`g%{EeQXuivdd?PfAKs(Radu5~y>P zBqa~ZK;`* zTe{wb7>T(w4<02~i_yYp82$CtL|Ut1q|?oc0gyZTStAW~5@>eLqZ;2*+fEkaC{u>& zDLg}^-`;Gs)r8$LT{Vj+NiMX(EHn)HS3xfW178pa#qgJlC*)0ZE*P?6`6&qNZ!Zq=}1Z4ubs@XGU!-nG6XiuujDt{AmvdVnkD8bUkR!o?}yyi(djCg`nr_sT9s-V zYdPdP@f7u`Rz}^W7{VB8vVmW2F+$18di2$uf+CBujn^kDK*E;U>cD-{x@XVNGO`aT<$OK#Djx!MU*nZ%@D{zxg_p`sy! zyXqvJCm~TQ<0z17_nQaWR@-gEdnw3YH|A|(I)E_{68He`GXUz(&d-k^Jp|%2*vMya zHCknD%I!SMAJ^pMn0BZ513?Y@(AM$&x&UsltKtU6%0&#IdlGtO5<%$_{kdGbYgMoe z$t=^p2_$|QNmvAt4v1rek~p=tJ74Ge{$R>9+kLt3Vu$@cW_Ux6wE_w_onvD`4ax`EORj%-ArO$KbPNV6A#y<$ z@$T&LwF@f`tRE28;*J-PabDr702?DCP_`X+y-zV&fSL#1?K%zW+t*U|*BX%Mg6NCl z2PbRY({)1zI-`d2@}8l%I~+m9&MBo?8RZCF>{s?3UvlXUdOpDcI^z~N`|ef^h_M4( zuIvXookvL2UU^6C#l91EK%s_4v)cGtKOoDBg$j$#* zWdZDEfP=(^{P4*f6_BCjKLjG*}kHFiIFc1lR%qJ(y3)tOcemjZKZDf8cT_GSw z(+`;c{yAQU&Ud-)e%cN)g7YSNKko&*N!BIAE24gnCI;CaMX;Rr^7e%b(rovA39MM# z`mC4Wb)5-ruc~Uhe`&|c&lN#|(4yN51MA0< z_TT6W0_J+Hba?YXjx_LUh0|aRZ?>b+C^oQ#_5dLRd4&I26@;6SqVi=EX8!^=wp3V*Dhxq+~% zzMd6q!uSl+-!gSCLT8Mxe{H&a`EqH_s=GlAB+k1pe?vzA34W)>6utFBp2L_3if=($ z<@#=8bN04WlE|e_*mi*=nHGzn%U07Q@9~GY1fv$`5~sxs)^?LPB(%hO-PQJ0?-50HStjI(?1S6GwW@+s|b=V@f}E>syiKPW=W$ z8S~YI;$jw;-h1trctXO$G#G+GDL{@g+3|)O{Em-UF!oHm65+W3(s*lihs9PMR4zi# zUP2Dkf1mX705#NVbLs!1=qHl)Wh~=e0JL!BeAiZ27c$>98+8ZJrRDCsGX86|$Eh-e zU2D?!!w+tNTc8j(=n@a35%UO;-&+gyj4r#TB!+!gheWL61~YJ%Z`OiBKk?lO+tK5A zfB}P&p{rmE2=|r#VmpmR!{FNNx>&P_$9-GK1yBV|KR27fLOrwOSwaV8jj`{R|hN0mBr;d4f+%EfaD^_S8rm-uRVj?{` zF^LqYt?KNq4NOWZI7(8_%IfCiV!g*`XHa(zQU;(}#k#iyc|?X#W^bZ83w9donSpj9d;E?76aWMZvmHh7&Cy!@ zsO?eqNQ}$j2P+;@TfPZkV-dT$@7gK+pXDS`Hf=q?rEerVuh8dXR?c`|KIV z$;alO{x7gz>&}Y*0_;u7@P5ZLCe4Ry0frzT_RIJzw6CQ9Hx)X6xlgj=ypB#gnfs||uOprcJrUPVy-?&W|VYs?`RNiuD)XI~GZD2Kl?Qe(pWg&$m zV-&tU1`Bevz#Ja`;*maIE^pb=+U)bEr~SXEUI~}`BfG0%aIXwx6qEusZ-Cth9LYzE zhBjiEa&*yG*Avh0L*r&KRTr)29#)qvW;w4Hl-N%3pbEqiXgOuM_DPS7@;F3(ko5WA zR2uyG4)EeY8gsF-D7|}J+-<8H4S{*>AUXx5iA^B4R@`>pOfBtq1qc~gXwDWCm_7$I z6^yIbP@_9Y*?~F;sG1#PN-cPm>om>YHXEQP_UcAJNe8s&f`fzz00J1`>n?pdHOvT) z*SN;@m*4yXK>jr6b{iKL`tzN%FJ$Cv?avevta`g564PoPH(LiyP0b7P`Nn_zcv>Q0 z8W+OUz~{z!5O{&`M_+V&4D9%@Z+UCK_NQ3UYoIP1Apt<9O$++lL3{|R5u!Kk$PRl^ zAYJJ8t54hsu@%^*;EbzljRY)3#~=~s2B+ek&zGFvDPmvY|;9F z+Ap*U(#6o1>IT-IbEgLhiwMi&1gja%D8YNRWvIp9X8P`Pj? zP^znVFBu;F&(7VG7K09RC6-O7)D`!G79Sa$7IDZP(Llhjwvatj%@a-6*(dCH9u19x zqx~eQwkQMvLeXP z(45sN4*#pQI3r{w*ulEfv;Ox&Y%qzeQ7o2?zoxf>gL(Y@^I>skii*(&ZM1E-#g{3r zZ+|V*>8FFsGte?Jp&Vq2^t|4^^ZA0jZ?rGN<9X+36k^wP?zygFCB1!UU6#i6cZa9e8dwfRG#7djXz3Cdq}h z;|D%m_2ZEI6=!`dHa|-8_}~>Pnh9uM9`w+%^L~YP;X%(eP#FRHB|eWqWVX5gwTOq* z!Y^Fpy-mRhvKPk%2UaRiD|F`b4)jg_1 zI5iT29;whJ2_<}k?T-WeaA^HsgT2rHJGnob3d^b*A>jM2UbV~B_zz`=tjDtq)4VF^ z==Udy1bPdk^^DltEz$6&$jVyw_Na{1)UOX@JjUe10xn2aSRkw8a;Q?!l`cP?C2RdE z7=CZ#2WnsKSLUX#v`h9{ju5wEZzq{f8LCWi@mwwaQ0)(LIH6h235_F76ou1NgBnW+ z-5uqqlBFNrChf?)lLy_qANB%Ced{o{?G6)uvG5-m!V*KJZgXpJbEmxS4vVr=#)%1W z(Y@l*8a?+P>S=DObHNViO@5iTuZVE3xEW$^5}B2680|+>m`FPYl+}cQ7vo+PuNZiI?S9z?xjOL)veNYnGz%+P ziv$jpT9H-z>e?(+Md8S2dt&{;;)?kAYeO#z5?_qw6?FP}X^9J_=VxA>_b*(O*fQ{` zyuW)o-{o_vNOoH%l}Tu}3y>k^8K!ozeb&)2KI~nTZ~R#G)txYW-^#ERF5qM7Wz*H@;-nl?uG?zB~KI6_lCqH51b;QoE+OVD=rWCFZ@p*OU+_`hKw9-*Z z@J8>|E#lacHflm7ex1@|nO`r}l!reSc715`Qz$Mw^uuck63GkKU7efTaAliJ;Z8o6gF^GLOzDq*A7x7899M8hTeblvWM!2Vx7X&61m&`T5YR1#Y_aVcEA=*M0P~ z!b(@($eyf;uz>YA4v$X`OTWbWN0eIw7Elx=_wzgPs5w^bRDUVv=DN0o#=Y?T3*t8F zzeZ{N1eCfsOr7AC=3j5tuu{-@Y)y{#?#WMR9H@lxRgZkOjhW^Z+1&<=2qTXa zwQiZ?#<5HE#ajskd26i?RuJwAYG-peIwrOf{gSSaAw?e5Z@aBz_~$b82BS(>CayQ5 zqNlCIa-}O&RaNU+CnbkU2`fGHV53Ze=oHUc>1H0%Bq!t&qSM-|MtYD! z`3oJZNCa%xLq>~?mJi?Zv53EK>toT$c-oC~W+*V^nikehU9V>Y_velt0Yd-930s-i z)1ah%Rt;v_YM1SJtmN0#-ga!-9@R7aCfWsyXFdQM%x=lW$qCz97V50|YPj9OjwpAW zd8a@=^60*efD~fl$9fuPKukGrX8&y3eZl$Zd9+63K&!vP<~}BC&&pEnrQ-{$T0Xo#lgXtUX;PzO*N0_ZK4h4O?+@*)_1?9PWA*n<1%{xp=xgid!7*QZ?AcU~Di2%Gf? zGS`N0)}Yy@Pja7EQ=89Xz{WoVC#+?e@?cOyXXY#IkRE3R8`~W(Wp3O92Mo@${&vaa z46GZeE2)%lu{X{U{IH&$Cn5D@jftsn6RxNPOT4taxI2QRrEM5BN{LU~t>?+gNFP{w zyPA-66qt`^1I;0vtO5Cqrwe(_M!%(}gJf^v0-tDRZxW#{VuMoNV2@Tm{Uw47;IhW3@dY=E}s$~ec7CZ{SwAK?=)Z$@g*IU@}dn#lf9X& zsEV$nUf}YIN((d}%43g6UKDrHT25;ItgRg7TGpeIP?JSbH0w4w@0sW~C-!2uH49er zKvVPM!_l?=)#?R9v0)M=xpG`*Xf&3|Oqe%w>1pI4wO1#4_9J!3adepu)<2bk4`38K zQ#6B*#c>Y_SdRG?D{5rx_?^GiHe&GFH9#v) z?mN2@l3^xn9=SaPDlBeD0&ckOqi%t!%*o8$EfteM>=t|)pL&%P|4$Pg$!E_KWg84J zh{vsUALXSLw0LcLyXrZ68AM$EnHeLUIdDusv?3=jzla~e-8Vk{!OaoP@L6&Z6+BV4 z(YZpRsBPcWkh=1^YL9*QME&$bQ2F>mTuNuA*Vf<>uG^$d`cuu8>@wyO)o(86|dOucecmfXU2IUM!v%cHyzLBNY z%PTzMw?FMh#X_Y)6KE|WECxewLr3K%g!?;`3xKIfqfdonoi-x&ZRP601-kl4``8_3J zUdQDm4GFs`;YYTf>4&|NxyoJ!1jGt3XWaTme9)$kM|DRa735pUc6-)UjX>ujfuLXj z*H8bz^;i7;-lqQqS&a7DBXcclLc6Q5V_)%hJ69S9?=hFvGQ=_A`Mwh2|HKV|OMruI zg&Ts8&Jj`;b{irJtZqj>I6_i^4LBye&U8bRKH=Mb7UvqoREbw?Ytjgt@QGEMu#<_$ z$n;!hfSz$9psD(4)KCZG0Bet*+Ejk2LWnNg3>f?X;P>Zij>R*!`glDd=@8)qe+g(` zu|@o*^{m@!D1!~u^{YGeqsbKTmFB-2L~RDP18J$R4;vFoItKApts-FyFZP8mz5Kuj z1iE5qYqb593PB?$w9dl0U9m{*91W-f=N?+?R7MB;-T$$lKKm6%E}TrkQ!rg;EV^=M zFVGuJ<{4V`GWX@M+7EAvGmnsjh6Idv^Z#yl(0ydvA_u>+Q;sz}V5oAI@iW}U4^(ug!gv6w+92bcuTz3H}>j8<7q)UIy5qJS#JI7;- zaj45ATXSKRgIUP9dU=i89@T{mWmA$x6TnB<0xasErEWd?DD?G*-)mEN*sJQbpA{Sg zpT0Hjn9u;%ofr!-dlPVD*)4-TApvFwNZ6dD^)wVg+jV*7xURB;^hxuq!5^Y+X>b~( zK4S$px3QI*%};43idTN*5T35&mq-~r8iubZrI<&<=Dr%X zw??n;3rj&^9*9Hd2J-`0f{=|%1aF4 zu_>kbt}DuFA@;42Eippd|4K>e`p<&9KfQL==6VW@x*j}u@O=3EyAvm4BgHaQA}6n$ z;^L?!SsN~aYuk~8CK(%1xNHa24~yleDPiZeZ#ZptCD9d7fML9EoaN@dr~*2=sZ;XY zsfM39gP)J#Lz{)RIeJGu+RtKR?aCDr+x6L=?`4aqf&|;h^F256Qx&2`vNJRD7b5-U z`U=<6lq}4?JKEg8Pp-rX+PtavQ>6(U0cMkNs7S+aGI>w{zS~NU!5EkWGAW4%eFul? zz+rp={Dk!hXV9 zom3szzcScVJ~4nZ-eDGEO3MpOjiLqVHOrjUoLhg^Z2oiDYlxZG-MQ#VcciRIEb03E zdT%7XQuGZQP^3CF)h@g9YUdIzCL09bsJ`=D;jm%Nm9rkz3%X+I1DJlB1PAj$x(mbA z#8`c&?Ig>2ZT2i7`-u)wGocqNTgw|<5iG-IRo%*2jy6q|;$@y2;38%x0|H7zU-PMOWrZyW$%C1 z#GoapSUP8|roj(Zzr-?vynK1b?5&^|F}lJQ+;;G=UMyRi9IQoLAUFpHU^U-!_?Ta_ zwcVqb?dCWAp-7LuD++Y<(kEXE^X)F`M`ce3=iZj^C-(^OhKunxal>IR6t$e@BPKXW z>vT;6D~yR{!(#MA+>{EG>7gZF1RG4DRukmw>tzvz`aNWJhNJa~wrHR8EzNUP;9gf+ z2POimPmK2F>}&)mH&CyLdWeuO3zc1*UmXj&^EL!#KXcEdl~Ka+;%DQsNkz|Yz2IO{ z&~lajFVc6ShQ)%Fs;wMx1?l!Ps85QIaGkeEpIEB`iLE7F_pw0ew_5@?-}DH{RC`6V zz?uHf7VEXUbx+a^6F0t?-^XFK=Vl5&hTmh$zEDHeT=6Rhz_>|-PtlFqQ=(W+GkyiZ0y+;Mv z^V;Y16!7zSa{)0+)gab?)URTj|NTaNqAf>nyKCaO(d)Iv;S`y$YBO7>GXsm5zB3E7 zoiO^LeslLJ(BXTx{SJpxM`fqtGIq4!1`Qu%WgV`&uHBV>Enq)^hBxD9ETiS{5u}OK zG&(R7ZrAw;wP7)~l8+C%x{_zcRoMJ1?pa44WBJmmSNS3>y&}DPYt4lH1Dp08TF^yY z=RP-_aYLxyROQw$Rqf%nHC9k8m48=8qlRu+$Bab`m%%jh1?Q_Sp1tt>``htsu~k%p zEf#2Tb+?v}&o+hzO)_Y2sHy>-@nd5zUwmc{G`uNJx3s1rn-U|R9^)A+36t*9Ewu8} zUo1)nO0z5F1iq>6CTZ{21&uT0WMVZ}bJ$7Lbv7=D9SD z(M5yfgoxa4ub}O)Yh1F_z6Zk^4az9D^!j6VT~2Bf--Phy7?{K+5e)dY}ZCeus`BM403a_qQI3~21#KGJL@%WNoRa|`h zqqPpHw`KVj8+B2%Du8R8Cf8=h8~w9&zs!OqqRc3;>YVsGddseRF7Osk0k{h~ zW~*Baw(}t|M57$sH)I0(CAx^-7o+eqw}O>Ksn4BPFKEt8YiAo~ovCyFKkU7ASd`z_ zH;PgU2&j~_C?%kd#|-VYpu^(n?tM0tx7Dzp(sx(mR+z&o!Aq$VLI}3>OAGXrO zCkxu1*(udX631Q`a2xh0R(0C9F#VX!d$lp2lG1Df#8sTo_#3~6WPgV*Hu>9ekNJx8 zl0LJ!mOyY8h-I!uZ0QnERZo?-N2}G83=x6lB)NZXkQPXYxIraUN2vyjVvwcC$Gy zCSfi0qX&41xeE6EqkYNET}^HKAFXsL^|-?~`yUrwg?Y$~7!X+lB3wRML=^LuIt`gQ z_-6_)I1W58CeP&2oSs;yBFC3-?{nH=sKX>%k$v%?8DzAvUR*=a`a-qeKu5Kb()hBn zB?SQ;h-v?BXQht-4bGN=G}0Jg z(BCg*)Y#_^izC!=yW<~wd{$=CvfnJeQr?w7SL^h=X#aOs!~+J$jb7fh+h`I50?|$y z$^Lq8Xoi2wLw1kH*u*y&pv=EXhX=PcuN|LV6{J(dg6JQifsCa zu)#wqDl5}ynOEv<7yuEJCT%ShUx+9_9ZnA}8UhPp)aO+tuEER=70frV`XL@WRsO-Y zKjS}cR0Fc&?|6^+4O<7Bni@0>W!2QG^d_RV$;O`!uT2+qElEUw;ndji6j9Q<)1eSQ zZsB433Sa`&t;4Jc1)3l!^%D0$nrN0b3P@DUJv>5u>N<-gnNVhcm9P{1lDdZ&RFn(c zva}9_Xq8DuYs5gbt1H0+%OWe@5rnEPU1+L)d8k&~8%@=>L@1e0mCglc$K-iH ztga@j4pye?E!2w4#QUGe@j6pw+a7g9Rz~ra=GyFT#attVIDVr1ZMZO_vxi9kEyL8Y z-dM}r0+WJ}yjX#uEOVvPcVPZ^rs{HNdicSOg$4h?c(gL4GT_jh(x-J59zV`JK{HfW zd;5M}%{mv37Hy@e>I~iw0A?$3B%~RGMg1URwlRIYCB87}@$_w2wS~ zLIvvLGFLm6wc{}$4D2RgY0E6+i+P_PgJ5#*xdAfFUkj}N(S+Gd%CGUE922*f2zl5C z%rB55N}8)w)Z{lEU)+%Pf;(q-hL~&QPpJRAX^lYsh^G?Du`&Zx;_3c=8o)tELuN+j z!xb)$J8n}3iH`(NPWqkMg@0AQu=%M?G{3Up~H0cGDeY5dk4E{ z7OiSotNPvf7IvDNz`($Vgv|9$doRbmt6Y}e^|yopZpwgBUP{V5@CpbqFo0E)kT7+# zv!C27Ysi(-BIdtO$f8NdME?s?g1F1+yPF)_V)X^~O^p+!*iG*4Npf3*_Jy zdH+PW*@c7YSS!`#_s`PfZ3*&-`ONn|eV15fQL6(X$^HF+@rsLi29nP*aXRrfC!=fQ zjKYs?pV8nxHt^wDo7AWzujY&%B(w zgVkI z6tpk_0p1E3EUaorGmV*r8-(N*aScKldj~0}XEgDjyPYgrVvaOa@~8MM&gR9`ueV~n zSE3uD90=tgz0kqm_bj*G$uScUj9mGlps}NY8B}K0;WXaNBbA@a7fi zIwNO9jAPN89|w!me2PT$cHL)brf2n}HAg2|B}_G;SQUbk+1F#Xg#8=T7+5qz+wXi# z9uS4KJ!4>iZ;f#{Uwr%FNcB$LD@NoJQUIAbBNx26ULm+1@9`tTJSD3lx?dINa5CPj zwkY?XybI|p(gmOij(&4i1nuX0tFgx&t+09#%p><3EE<-x&%?^?wrOX-&5buzvMRHM z78wC8%BjoA}ha5!KDmgRT z1n?UJvr&aIZoZnDnQ3*B|f|LNr&7^Z&JiCk4P9iGmGxioU<#(g~P3efN zyEAAu5EUuPMH~Y{`Gb+?!7-19HzzG$61$6fiuCV80tLNWyLp@z_0`+LKQ(^5kk!^s z7~{K7UB?xEbTgc!n0>&JW~|1O8e?&Gc3evej6-7Xq3 z-}JtbOv6Oi+^I&7Cx((bh41$Q>`jL)oy`}H33bMHe}7%M9<-1(Gb;qa;B_tyrQ_YV zvA1p`+f0EK9_O%>NB0!zmFQJ*r(nLB^N+Rnu%zQW_+oT*j>eY^t}Z+x9h{Pb>`-0tdu$+h>uOuTY=s0RfqzPVH}2wAgq?~ zt7wp_npj~`zIMIT%V5Gb<=onXA37W?#hz_dB}@1ZYO2$c55F zkiCCBY#sbBH%7qgS9xbXwucJK_1~&(dLAn@#mL-Ch)di1?W${!2f@>1%$5R;;%vr! zyu1KV$XsZoT-}@Z0Xu#bF^1lxC36Vw>ZqY6w}=o(%nfqH+CL&6CgpOsjzTLjxQwC$ zLBI<;^B5p?13-$E+Yp=4W8=IRv1&;oonYI86p_!vLn&TtDQm(cwiOJJ5TRx%=;?=O zd)O-sc7inCNIK|;%wyg^DtGjNNRpVZx*mrNad+ZUAOXtxQ>0ye6x?np*(OB_r@kQx z9sLlRZgt`#n>Cv}8j$o^ECm{4L;})VBH?=`XovWw5om|YTB)jd0aDjg6=7l#clL1j78&IA#oN9wg&vW4Ih zJvSENmbwNP0ugfQ+(Nshvv243>k@*WYckQVfwahA=Rv1V&IfNWiz6UFvHl$7?hPH? z6A_m{GOFC?XXSQ3zCbJk+Y!`+%jhya9v^>)*#P9~%2(6u`>5|AG#R=0c>8?x@V!KC zA;!M#@HB=Q)e?`+Uu-K692pr{pn3=SoC1md{azsZ3htY=Bmx9h3xO2d8X;}vOh@hr zMU0d**8xsY8J{W8$Nfq$^#+?rAg9M~O~#JsfxyYzja#lbtxnsl&-T}Z=3}QB$_Vu@v50mzUnl;o|2n#SMS4zjBtj3$G|L(IJXHi&MqsmRK4h2o5;a|b|W8>o-l9Q6m zOK8`*neMpMI?cUwr{G20kKO17q*MM+g8L^iVKar;Ox%Aq69xOtm+bz2>94K<3L~i? zsqIYA2=T7b>YuTYbKCE~2JxA7N+u(K-PROnH_ojP8=4aR#=-n}u?t|CJuXqMW_@lw z&W%51<9!3`+Hn9{1Cg3e6Ls8DibMGsbPU9mt3b<71V9M}vf&|6^MRge6`%$XgLJ2$ zLcG6-bptKKWPnA|f5L`%v)9I*g7oG+(2N$q&M?D(01P%)%akOJksIqK47#ZU0@KF} z1)%M1PK$wGH2C7#9rZioMc^bi@cQxhra20h-6rzSfb}9H zBLQ+x;MbJ|7)Fte_KpeKk$0V!`-bZY;woW3|4fRWRdNz!Y5zk+Yly|b;oc7(ksf9; zuRIa5K$06Z{pQcqXjV8JWrO&gO3Bl@!6X1Xb7o%3dXaCOC*A0?IN^`STDpx z{a^%_P#v>Gub%sVEc(q= zDF2TPus;L4`OyD;de_aa`u}f$g!F%A!2Q3OqWtG*XdsjUcB=ir$k3O51{H}Wd3EKe zaL#`T3wnsWYUgn7%nLw1GSK=gG@7ylEJoR;pv~Z-51=JQj$?qX*_-^k4|Jh~wb=h$S>LeZI|vFV=~0@EI0jW;{#BN}rLvUe3rZU~j9C`(@8 zgu0yEbD;Y(o6^l)+4?~XKQ&*+?T?4RDgk1iYwacEFSqBOrXV_6TG|Jw34FWa-1T03 zjGgs@M05e?8asRLfNlHNphG^xJqBIxz!`tKzd1*Cw^LF;M6Kqkc7ZHJ2`DMWo{yYf zg3026CYR?>Q1H5}14fnCaP?uLs{EXgj{~1 z$&^OfT2XFot!=~Ix#|u8Ixr}}c^QaT?=C+5KAHib5yz_1*oUMO*d)1!}r|hh=%WwSH1$5SB zH$e1tN4##3AG1ys@syDftY1Yzg`C$zTeakJKyP3pA5_asG>Xr?yu$}451IPv0I|wX zVm0P*na^#!`SQo#9TSa7voGcFh!{1F-mG`%r88rga_(?a)ol|19BHNtp4d9J9~&!W zuPst+9P6J1uNpx6as0N-F}hIat#kl=yR-rHt-VYF(ARo>%U1)A<6t>#f0EX@7jg2> zNCiD%I+Af^hXtOn*%${!Ik~Zgf*b}*z!@p>(s=L(M(qL&DQmT7S@Bf8`bA*HQw(Ap zIGLceM?VIEz>TAkG}j5xeaFxjI@WIu`cms1uUfm@9s3rhIW!JW0HFi{MmA4g`@#sB z325{F5^8V0M7jIg*U@mjOgVa>L}YJ(I$l3KEHIzcRw`S=RQ_at zHCk+`+m}Xc-)Go-*fx$Wsg?2^!Du?1{aoRY;jZ~FDFA%Acz<8Wk@SJ|u;ZH0^R?nz zgqVS;9B5}DapA$bs)sk*@Z)C|@WIA;{EZZr6WV+kgqsdr>&&K*I^PIR(Ef*jNja{S z=wJD8CP%a(EZaJg#Jh_{%H|4i6PU~fcW_2=7at!y7T25@>@lTaEMh*|?5M*RK7;@D zt0>a(JTpHAdIu$N!I1VkBA*qI|Fdo2`$DXDz`n^}38Pm^Lj?{VW4#?u%l6*~+Sg9K zgLNBdKMjXX3O;kW6_1AroBX+eiw7t|F`Uz{+i>{b!Q?J84;yv6d9H#p>3kdsd%97x14yMbyDH8#=&1rYIP)eDd`C z&vye-o<^mVZp%EmG1sDUc>nc>TJ$~7F;A6Wm7 zq_YQ4d!3xxkcsbFIwB$61A4RlmY~e-VBi05KX#)u{w^lc-wB>YH2+7uD*rZdMauun zr}=35|MVl7=_Q6eAld$cE}B^@e@z)FQ*TZuEeSL;9D%DMeT)NU=L@&XW^<^=)%o~W z)E*X)o0d4S1w?vz$B~pRg}x9H&icrdW!NjRlo-?D`ujD;?S6Yh6w`q1GBC|W7m?8= zbw2q;30T@b!-Y|si{>mqk@C(v5@>WobVQCH?TjuMgj-$BgHnl%o;W7v`mb9d^+%UF zQ-C`z@?CJFD#jv>*Gs1#@QDn25*R=Wg`FaOtM)>*FKf-3;sg=v5r;9_1>jp0?&bidng?Risd`{D~yXyU%~U>oeRT>5Sg9H zvWj}K7!v6?egW6%l-Z!m!)Tnzt5eJC0rc%4X@lMA^E!&_^qHhSunsxi;cjOoGr8-C z=@s$-O|1Z_e2e!8dzvBJIao#08|JC$7!BIQ%1oUGkJh2#kVK~}DQ~$B?&xZBv9_P6 zp(5>r<}Gijo_NCIoC8y@r%K?$O73;XXRV`T(A|M+spp006sGvfH3!?!(21w4v*Sm% zy+`*`6R)qDe+?W7OfLe~&V*HcLxaQAXS|G}ZDemSv4$Dlbqkm?Roe<~2TX~UWBFnR zi61;gT2Y}E^#|TMDl3l1pim*V9zFK8xrYYy+?S>Z9lQPu*CChb%-1o>`+ z>}T;(LGzJPw5JHMuUc#)WnBpd(jq!I^`SXUB3ehgjMMmg#jGVo3!mMZf>K#(n{*tn zJ54sv+}L-eqanxH%tGmtva(oEa-`!Qukq@(C6C&JA@4mP?%5Pk-*~9`imoqDOs6;J^u&D z-lLX>BYSrO16eLduCM5=sh(U=EjGBVmiWh>;nZJ6zsZq-gsEwiZ(X!!G!VnTy3gu4 zLia-o+UkE>7&Ur|j5p+=q7u$)7wKFs%M`P>zoF)2y`%lMFYzN{g_{Y7D9A0eXBMQW zj&am>Z7;ED0A1;-jG%U=e&)6=>gwbq_zNMRJfo1R-}>3-&P|k^%TQy zyM0kgL#KfEhqb|fw&E~{16nb>RX^yR(~}!fNbd=pAeK6V&LvO`9wwQTu-tpM$uBX# z!RB;?O(C#`SUbfGQ1x~6qI-~75wg3So;Py}EAXBPfBXa-%6ru@_oPiG;cOySSSzHk z@}wV8zLmKFXlCc&IR&9}{iAowfJTyt$}^j;*7%A8&V|eE@9$@sI{&$P7d#`hX7=>M zN;m#%{HEBx0`)qJ-rk}H*Fs}oX7_dLQYG>8ilgt=3O~sZqSMzrxy-~@%--Gl1kCBx z7;a5gaj^|N;WBR=?pJp(gejqupAoK{bqfuR;$(CRhrj=QcWp~i20Qont_iz>l8Eo` z2?T3to@feeTvA-V+(dy7Tz=N6fU$UNUG4hLT8ahS0yJZ%1z#aTG&zd1#pn_;BK>t% z5=BQO;e23YI22MFXZO;f=gR>6flvc1qt`0kV=XYJsly#TP($ zDPlAcGQ~Bszpe7bJ6Z=629n|ISA!`GqdS&LVip6ZBQT|UAjARGxQWYE%{H}UB#`gR zP*f^FdLb>^1;f>^dPudDpKi?zTYA6==R$y*ItLR*ay4136`VonA3??HCmHvGFZ6iat6CcI~V+}PqLO7FIt*Xmd&fhXm^3^64Va; zuqbpbfXxljQk)*DC@@x#Go=pI+a|8|XI5ij_4EBk8zMsrV?gYtK>%!leHl!gn3*i) zm^^bDzy|2+b0QD)I0rqVoWOP=$ue#98LQE6(B~QDy%5}D^h6nK2VN93|M#@FcB*zV zfJkJQsO)01IbLBtBK_P*>7Bwg9XjJ+86aMb##}cu9A9(%reFos$b`hR3S69~Cf3tB zf-@K8;u|SwfidH`hp0-hct~ohx|4xrfV7KDb=4h92c%6$_Ll_oA&$oz?=M$SMyIKQ@E< zFMK2lCd@!o7Lb@#4CMx9(@2<Yn zU6`W+ni#|Zahr8y+J>o?U6^n6ruE!|))BtjZ2&^|Ddz-bsY;Z^!1(tgv&Yg>GOo%> zY^+8=P!*Yu->53x)n0-9%94(=UF%<3uhk+X!1o>UQXs6@0YuHzB2=Nay8LVx3O^JX zv0cr~n3-nTq ztmZhl>*))s;6};Zulw)b(T@sqG{Yob006s2CV!Ma^zH#xd!0}s5=L2D~wnP z;j5pIVDuPQRQwlCv3LXXePxj|C*9C=BE#JfGUfBGooiA7ZtMNrjr#oTn9-@49mp=f z#}bLqRU5p4L=d&76Yg;l3(DmT&SPg|IV}S}SJ)hx`s1er@zc?7TYOcQ$|(1)Pa$Pq zi+>Ru((mt}Xc`nS*W^7xuCD8M0{4;!e|t>)&1YIj01 z!z~2RX&f%?8s_GPXM_eB6;cBXM1>qSM&7-Xcc*pl|H`A=B{RKuG|FNmG?pSU*s`uN zl411NM_n+vNMWT%I{qB!GC|`f*Jt0M6Xkl2n<3z4DX6aRuj9JD)v>xQf`Z|dv62;e zQk!wTZU|->|CX9kSL1A-P(@(279-=k+(OIiWCXF9K4E6&;;Kh{W^qH1^^V7_*s^uv zb3t4cFDPh_upscAgqR4$KIIHdXvh?v zmfbb5VhhCAOP1uprnD!lq!t*06Hh_JuCdGn9j)Q?GBMQzf%_+1fChn{!>@zl&F>20 zLpO&DL`$Z1tCn;ciuG2eE8R^Ioow6~ot)9B&peEJMNi%;B6Qk(jLATe%H(7(y3kb% zq|`b>?5CJa_O^I!LNyN7)#a6rZw-1|Wb1a(`<+)dKlyZME>FziG_6bs`KWd^zwKRG z1IWi%*!+`cXC$%n<;AEzqoeHVdE@e-Nhc=x9za-?#+TD5$*Y?(< z2(1hLB~>vw1d2e7-I(g4WQ^GDuYmp+8<+u#)yfFrJ-pXIkk>Ud-RQ@k0|VB(LvBXA z{UGl9Dr|O(Nf6RpBxBc=8|zw_Bsk0EC;S5bYR){oJM)H%ykA)9J^VBV)@>G zCr9VHyXRq#3>dJQZ6b~~Pai5BaLz+qwT@N=*vsQ*afaa@heAcEF5oOl^n%u;W*S~t z4#VEm69saoAEKk3d5JYZ%ba0geGVd`II3}LSyAiyx2ryysq`Qd|v2FVuf0 z%99~-W0o41V_&0idv?{=0~m4sf}3eYma5q?$SIFAr6H`qw)e4jT%Z5CrcriEQEST# zpY^FQ`Xw`GlnDMA6}N~`B*_I`nTDTYnb`B&cjoicXa@-%a z-&t6mDX4o$``Xv)Cm)ypc;Q~&uC_KT9aKKJEzMjxEWw`0lm<`Kae9hmz6m53I#JCT z&9M1Z94Ytt{wB%AD~8&yY;J*cjM@7I^5b3^+yPzSq>`voX?Ik#zSmG$8h*Z#Y_wGI zYonsL%H91UnysI0D@;!Cky;T{G|K=bi?qZE&Jolhtc* zi*cHhcIm$ZjtWlO`8*SB4&+>_2GF=d6T)XNlb07R`9OVC%=|VNKy;U2yHOnD*D^g- z&Xj`4#^%%V^Rc-|wVGF-o5ForeynOF!Z!HJUzUDbF|7Z#7&}<@Xb1p?8P|iYx#1u1 z$5jNjGs)Mdmk<3ldJ?GvaBJPc;d4v3wklLi#~v7=XW+jb_=a_ z%Mf)pc!75*`0dy=QxN`y!`bgKynD(D#GWGN&4L-mi}yJ2rF2P- zebhs7A-TyU>lJNua$zJHYpju_Ud0WQA3bcmXbFU}v zDKYxEY{gft&B};x5>`L#q_t>p1U{WH)>ZXFXnMEMLCX#(Iifay9Mgs~{qTWhht5DF zWwpovA`Dk41&}yGeHHLItK2Nt#ybFso^i6i)vDjO6ykAOefu7>Z^Cu=)qM8jvI zY9GbPcbi~&F6J93veuWr+Py{8v(aa#J+6M#2f|bCOANoDZEV!RSz8ZjWyB0$?4hao zd%}RNZpxts;iURi&^3vr|A**`(F__s(GTw5W}t)Tzi#=D`$Wym^MrXzm5wv8-SEnS z_%{sVtsb93maT-G+eUKMsbdat1efb-P0W>+A~^~&>JZxX7-&}mNN=vvNVdT!!kN;I zZzhpyj^VTw8C16;Oft16A$nb5yVjc~6JX+r&``u(#_7s!o+7)FqElsNDht1&2LY!H zG(eY0;C<-&{GFX^aHZ?HW~UKEb|C*JHJ5j>*(pPxci;Zh0?pM@e-5ip-TBT6N^11s z@V7AI#*ZO{hnqtH;F|cx*+ij}@6Q)9 zsP9R5amB5ENv9uJNn53>mXexebc;ttgIP|33T{nRbKq&qAL0+zf=aaf35b;a1`jK- z;m*~Q7ei)B{olp~-4>nLo0=I|K@g{r1$tm~0{IHPSR};x6xz&uyYGJ%4fk^#(Hcf4 z4>j;%s;BweM9gsb-o$n=`CUPK-^lBo(5~$DmXtQl^K<7Y9O!yyp8#%3?5yunD-P5G zxcmM!;6yI53RQ7|6_WFNHKPpp>x`^`#2%C$;5E}cOUTAZD|4BK@)NTYbTIYW2N1&0 zN;(5joo3&r(k_8OXZPD!5Do4t{Sb}7bA4Tx5mC*S6eEJHZ)-M;jDtsa_R(pdy6uA6 z%8~c=TO?Yfw#S=QR>y27mI3}vrDFK}d!qPkg{)zPw@d(ikoX?#@}v%rzLo4 zoOq+!1i`*cZMa=jkVZ0H1(ohU7t8}*Om>8w7sm_R?iw9_9FMAe%_?F6ZA0J{HzBzm zllxsh3_DSw)TDeyhln&i&t4B~g}zcBm^Xf_XX4sf9^Xg#(6a3-JFB0z&|G5d?4S?y zqZe28s5=P=j?A-`fHT+ybC85RPOc~TFn8#_L9tajaTeO5kToOJ=AJ7qI%e z=e!^gXu+*^il=57Z_QuV>y~uShgtCw9#9?E4DvLy*b*|1blRY<}skp8*UWXnKz zcPdI>NJMviDuG?e3d>XLEW)-xTEC%{j$a7UKewl+A!;8c?()r>h{O>jgoM(Uhu%AK!Xr#Ccia|i zUs7x+Ho-tE(5BWvOZ8;n1d<>8n>@$EZkjTUr7ciw9^7yCp>s$nR&Mum2e zY>`RZ?74Yv`th}(AXjBBdpGS>n*OMT$Z}+UZ)cWDuVwzGVEEv{gOhFB6K4AmEGS-> z3RQ{7gQMH}(WuDqlJxQ}SJY4VjOCUC^%BtgE64GR%6+v``^rHM@e$};QZsqm(H#jt zw2Gd?J5>aopi8+^aWX-{!JRQRKi)n&VyQ1qCWm(>e(}2HnpjS4UKN%HZ%V;!ua7db6d^4FSq{srfH8&VHaE zdv_jwfN997`M`@+(}VmzDV(s8zT zZ@vKo-i`t0zUD6MVMNso2ucQ0!r@3&j>jaE1SgRcV zz;93Sr0-hVnyOgHIl}7}jwv%Hnx>*l$&1rFNwdq?-rsGbtj1zWH`hbFHW-;D&7<>F z#p1p^OD!0u_e+2@;;e4gr?pTlF>uMoor~W^LyKO!3u~-YM&$H&KOn)7kY-8q@1jK) zeA-jH-X3kk)?4#dBl})2pOzRr zH;IJJtopp`92CL?jAIY+-qkfOCqRTnmrg5RiAfXT4cW+Rvxcec6Ne(V?m}K_X|r?( zj;eNdzJxVi=5EQ?0IbV$S>f>0fiu$fwl<0D()!V^-^Bb5MgLiIYpZk0OBBN%-+(*p zb`5TiETdn~7vpcNrkRnCUHRAc{Jz}J_y!S9y%ox|?4ACYz5o+VnS%sJ_YEs$K(x3+ z;ao(4>=oG)2nS>1%B&^R%l%WdxYakuait!r=nblfm?Y6tYWSTu(YqR6wAmi4+ z4*dF_PI(9Sh^|}O{Gjr6vJFJR8)Ycss@|ugQ^0!f#nMJ|#uFkUo%AIy&!6gu+JnaE zTPVm#A8jjXh(@Uy7D3N6T?KrxYreEcRd2SUs9vrvv1(&U>tv&?y<$aj81T9!y0FwE zrS1@kbE=Zf;DM7n(Lwp7eBw%LopfK?tFkg$6G<&VmQ{c8X>2`2w$SN=wcX{LRQmR3 z9I*jLuii+q`x)@ivk>79nU>-5cpTW43!Gzr7n0LP>P!urZr6)0CGGN;zEJ?>5}fA6 z=TXvj=-2586w%rdBdJl0jGrp%%r#(2ijNtdLwQF%XV~NeZANzRnQ-(7B zLB@9U%;hh~h&ub}Cj2-*vkEab{fiPxvExrOs9Xw#g=0>)BfLD#wq!XO2q~@uW_W32 zbRc1JvX`7x>f+Zi`#XFNWVj6q0wi(WJ;Y^@-9uyc=&im~S{M3Sk4s*lxv(wMl-f;1 z^3co`JdCRp6eb2gcA^fh+_s!38le<9`frv!$P&j`O}KzPm;GO((aKDfUyo2YP(O^BOH>oxsn&ONnaye>GE9GoAmjry0I zz}XC0OcF>As5mte^i$Ul_j0*ocr^C);}SwGc;jg|*-^dwmrTd(lsP(n<47l9OJBR* z8e2*yR~`%54S-n95Ary8NS7J%6SIQW9Wl=hpI@u|E}S@o>(@FTd}h$GO&R!bv%kfM zFPxv*F2!^KA0Q~H)m<$JCn@39HJXX+o)TTuBVT)t7&Hu&EQqBX7` z_M{-uP2m|jjcL)~?jT#sZ5Q5M0b)**0JqhSp$$zWfi?+RYTsWbu-Ty;6hUHg>$cek z#1(JLZAI}d(qC0w;LQrW!ZR7PFzzi7@IB2kuZ|_F#-6>sVSdDli)Aqt@*CI&++B9} zYc~up&+nb3vaGCX|9wr$T{}xWOkxXv7cFGqhp$ci9*to|L54WKVRa%p@{>9%^i>VN zeVxDtRXcKf=G@<$U@0qZx8}ffq_k3L%M4vaT zmp_f(|6YtoV120UrJ?l9Ro+xTE69^A=Ru!#nWK zovX!~@6#?!n=~1a{?I#oXIC7i_gmyGfJ!3ZB$0t=vw|22PMc<_9n*Ea`-;a^{2SM5 zsuusRjE;@hX+6|@tcA2v9S7v$F-Ph-zFCDEbBA`bjDudc!skNul?)c5;?bh5PTvu2 z5QrR2@H;=qBaFZhHxI1~;zkt^9QEN4Xwa^+QD;ip^PF;NYpJtK#&Q@?m;l+x4>@Xh z{rVj_)9I;iWo`Rsh`@+wSO%WK8r|{`^xN4^B(GaYjXatJSj?K$R6UfkM7%b|+WKeZ zir-xG2Qurd&!X<2WxY64&Ym9Cm38VsO~hVCMNV-|oGXV{4|eTpT-2Dc3Tzdeeh&KP zw0W|&>&Lgk{HZ&p=F^IQv*s6og6{laPaAUW1uC+?LmNOu#@eA9L@wDNAbxRafOv4 zD8&1(DkTUa=F$pzgU{fG)-D_0ZjG2zL;mJ$`MYTMVkyPaEkw75DFrS05E4uLX@yzU z<7D+$r%DqLnIF*WsiK0OkA1n$qhB2Q>BbxW$g`v+8MhsOhA`PclJvJD5~1HN47GzU zTC9cTW2zy}u#cbd%Hu_Urt+8cEPpl=pC=8zu*0_tzK-W+1E#@+dAHABVL4l2d(09= zY!@f9!n#wsdWXy6&8CpkSM0mqP8WE+cv!bh*ykp*o`2H9S`!Z( zy%*~!%lE^>4j5c-->XzwVu9?{Te@s^e93JoX{J?~0Dz}qhPS!dhnXKfALOhIldj|K z*d655@`+n0D~zR;iBHW*PnKy<+rK0J#Q!IX04)(+K=va%5|q3;$pbG>r7{HJ{38qU z9Y73Ru~K7AVzC`#F4!?(TsrdgVj6MqyoEyc8jTG zoNH_255*&N`7rbBSatyg?Y1!GpSgOLDLG_XsR1U;Io zR}t(`{gJo8Nie_wd)DjuLxcSQbvBWNF6U!@8Zm95g_G1)DZ^_50t~cmL#Ej&6)MHd zaal6Mp88idagDsy)7-hwB4>}|-%dY#lMEmUTKLu%2!!UxB}bx5;-^20rfcbbe#|8E zD~svdT6kDk<9q*?EbwXw#Jr@46g)N6esLtp2|Pn46+hxfOtR=iLd>~d0>A&2fY@{I zhqlWsodIR(5Me#P>8ka}S?|wMvpnt#y+sqkh8rbjExgO;^ghNVUPJz>3`F0s25+%^ z*5-&vT0uc(^ZYE;qm}LqYs~&n%mI9?GUC!D+Xk71ha@D1xZmrV#(#Hl3j?G<3&hkG zE;31ppPoW16U#!dZ0a#xvE3_XOO`eZ_JTkcrQubvSV;Wh*h48;V}kzemyCCmpgB2D zbm|;leVggSG=8zPHE!!Sy$|(ullQu1O@F99)e5|lu*k!LDu8=^1j07Bs4}nDhrU=j z%>qn$nTu*UT^p{#6&lYiLAJ8g>6CAU0em?2Oi77%E$!YH;DE#6CtRijKP6MofH{7r z-1DU-_QtwxXI5-alQcCj>Xh|WO6$8EQP6jv0jDfi3Lz32Q)am>^sw2f8b`Os2q;Dn zwTkaEeNX?MB=(`*H+K63k&fi(pM$YXuQOHi`hXG{Rfzx-jT+(3{YzxP?)P#0Ip!4^ zq&Kv9@tFt?2jTBq?jc^Dz+WN$M8>OrGKq@J7HymiffWA-Dn86A+-baje_P1UW_^-` z>&c0xK|?(W51Lv$dDVu#B4wk+QW|2kS6H^?uH;}@G$E<0Q2N(sv z{$-|%P-t4UmMgYejYn)JXDVv2hTWVx2R4{5)AX>7f?}$d1y@g|=>30BwVwkQ!*n`* zMM#Mlk4~As#&XRIivATdbEasb5g69B?)CVSv!f0C9IheD{_y#g_6@Ni(MV3y?FYoR zuTiQo&&{ZiF*bYU}MKAEtcDH0V5xgUlsGav}QCWe@&Zt?N4FU)3!b`t(%I!|o&H0W} z(O9Zm<4!wYrvt3hD={bBUerB>F4vIMp-)i@l59gklE1cbczBIQQA~V&-YKTXzN|>M zfed)QY8%*LuHnlcSp5lkPlLjul`8#-!kLDmD+Z56;Z;1D7L698z^2hj8pBkfaSd#? zAevI(MH~}W8M?PEM_@LgQS-s%2l*$9uPZHGnE8OZL~?r$B=_b;(8#C7uJY&)jU0Ht zhn|o>Z%i)9uX5qlA7pT!~N&iNJyHufF(z~tO6Z(rcnotsLBaTO=c!0TK@bR z7<(#2)Casi4m7tlRFgPg4{xIpMyvDP=GIZh zZ&h51>y8PZo9Z9%$ywl4{`0NBf5ZOU|Nr|3Aij|Q_6fefgZ=l{qmOUc)&KqQ6dg4#zy8_wQ3G0+A()bO#)c!juZEeeoEOIPmRn(P?7U#k~K3 z7;U{72!PDq7YuiH<^a!B3!(~<$gu&F&>lHP-m~x4i}lEDe(gd(j(DJZHXUDaksv{< zk$4u9LAwrW^|%gOJndy2k3kG*nt4R!mO%JWWP`z_GGc6pxP)nWLrHlRo$p_d1=zpl ziDuLR5A-qAuhKqx;v$yIvQ~>U^dY%*tYHOwTgZ&)0K1J*r^?g17_{8Oe}2g@kbCmp?%C5p^n@~ zzy>90=6AR_tjH>M&B;8>qjTV_6oTpM$|Jd92(uQF-a*qw@$$^@gzWy>FT0CoIa4nM zd^hVl&@%6ZUzO3Cy0dVl$In$=l@zliKV=X|8xkExAYc#)X+Z`XB-Cob;B{#IPkJm0 zfuV^Hr*{C50O6J0k(LB^U-pIOmb%|SmH8>uN(O(u4!Lw}6AX9FZ|Lyg6~DDhKg$D~ z1vXE6@Dcve=yg5~MGCt@mYI%eQqGp=_0lx1o2}T*q^f-x4k?OR`M!xJ>Z2toJnd%eVtp&^&bBHt7yRya5#%XeHf6Y zUhj;%Aaa;1_5BTULQ)lp^UR;&Hqy;$VMOQNhBewy60!0RZS;0Xb?o9}paD)c;mA1% zQ9Ng1pB6&p**}wuOMJ0N5FT5xmPKd__HF)8y*3%w^g#+(UZ(s}D}7k}tNzPl!W+44 zR0o@J*ZvmlKo!lv#W1c63cR z%wRRN`2NO3``W(7MhMQ$5_E*^10Q#13aUEb7G~PZrLp&d7?o z=*961!-SCnodKz2md3GzDEataAAVQzR6^$&&nJp?TQ!G-E$v^^3Nx*EfRn%#QQ!kM zG6#qWdU-l}LT2xRU4V-vh?ErR3@k0m&}e+o9Uw4w74*0mW!$3fox-GubzAeZ8O$!==3Z+N=|gP-06$7)wtpYKPKe0@fUr&^&D8{&>IRW3Zg zXLH3u6ByO2qsGbId!p$`R5>!$eDjfq%}=;EIi=ZbKxFL`?e7CZ7Lw={-N960%bO9#Hn<^wLTMQT??rX7_C{ihTi3g$*bxvcv#FNhy&ELLK2BI>ENx-Ns zo*MD}%hRV%b7v~!rIW4ucM`|hAtCYHfhy0O6j}Y8@7L%aV7urgCrGGBy}DO7*auZ9 zn0QI}!D@c&AX(9qUHL>MTjB$D_RMFOx}tk$v(!1F4C`Z-pH6&QgbQRgI zBZ1QZMO?Vw`lo~=s^aBdkx=q{Vds)uvFG$ey@iy|WJ@52!YhvcAdq94F5D&l8WB$s z0ms=OR7NKNaUaE4SpdPy#*2$4=T(B&5>`Fu8ZrlniMHCpkUs~p>99(mfU=VZtFdYY z{4*DE=B;rp*r?u2*W1tQOB30a$4c#^MILvtnGNDixP}`b#F%Zq;jjv93O+~qbe2Vc zdxI={fq|4ss28@TLP4e+E!mL;n-ptX3*_L|OQvg`5g~-KH`FhIR1q?3rwQh03cKG= z*4WW)O-mtQc)#4fk+J#&?9DdGZ>PRJGcKs<7Wmd1`3A-NrT5cHbO(-SiWx-35_lJN zEG7p>kr&nfS94z-7FD;luM#RLl2QV`AU!k83?U_{2B z6Na%INmfql)?Bh;fU*@i=cRWb*mHU0_K}*wMa_pKfnE{9q45A=dpmkpf+u?39K^-e zB}wggouh0dtv!6X6AA0VT~`XDQb6Q0Unpcblwpfev{!PBmA z3fzAU<^$5Ia!|OVQEiMc?wQ3LyO!Xrn9Gcb{uWcnxHE-1s_%*qb2<~mD0(yep7%(7 zk3$W;kW*};k`Uk6S6)$kYpUP?R0AJyjo;Q~JfbGb`zRk*%<7c&&PJ*7)z&43^N#Fg zvymtBS~fIRNregoX(_k0>CdwTF9;ndJeJIOzLW*v-&WC}#F`hggRipCFN@QRWFk*_ zMa0pyeLbzZBzS0MR5bEE8o+uBCm5Tu&}+Io8H;@Lm8?pflo0hy;2CaJQvzF6aQ~v& ze&UP8^aM~H-R$lPuy_6LGQfl_IzJKnBp*w-FJ#P^B!C-e_O!MmwS6o0<1=S*P8v$N zDzco5)@Hmn)F{`dffm@ys4`^j~l2j^|XEWOI!IU z(2wwm63_Y|FWMH#hR}=IMfaI=()1P*>gx0nT{vP-vuuTmOjW#M{GS8?v)6O`0YEBeJoaV3t-IDXXwe>Dlr}AFxW?n+Ur;83zC5#~G?79fVg&b#4!7 ziOUJtyyqoZ-{HP}PhDJ|Q^TH{L?iEg?}pQoA>c736s0rg(#6^@GO+XxKMTb!kt-P~ z$M{%c3Ir~|mjj`IA^|?jBVL2$jo2uvXtDcVuP;`P=dM?~AE&e6g&(U2k5=r$`GAkE zVJ{9G2pNN<@F0a0Dx!){!yWHrQcs6R4S_9=nq5<_!EL*!9U#ATl}x%RYJf4!jlU%5 zx-SCxBkRoBvsB!<83-NDa}v&HE6UF_rQME+1an8F$E8<`n2^$w;IaBOzk%uE1fk8i zHsZ3IDw}}KRd*NjTp9(N9TkrrcFis+A-vd?AMHK@tkcBABsstg(#!Mg!Oj)R!=N6| z&!sK)Ad$;nez?jsSHGz{xgJw4K1t?IaqW1gkl9T8y~|21*orvUfTKimmp-%OY+m2p za;mq(6qo_o4Dq9s%;DY#G5Lp&7J+L{;c+F*7|{98C@)>vzhKG?Im}|dG1DPYnx@a# zX*qFTHkBQZphL^{(e6#q<0_M4q5zWErRuFlEcI7|7X;^I^s^Rg*ISNejer2FU!|Ce zs8uoE@*{VY*)VwFHj7fO4^1z_q$hn4cRg?kH6^%9mvXL-vIRmdmqhH2%@idQ?tZ53 zk;|9Sgi#*Y7OZ64%YXVxUG8-?K;3D@E5y{B{8G~gpU&~zas-%i=J68({jwUxp!cJM zKsKT3&0OR4DOm7kiN`F!BkTbjs+`4qk5TuPtWw*9cPM+z`QC$vHn9)va9u^0{Fph;9Jqm(Q5iZ{GF0jmiD^IN z*W|4Zptn)6_&)4I63|3*Xs32oWqG-n%6qaRn1iM!u(< zUmImpuI%gl6=$i7R9~(b!BST8McN*MP;<-y7KUEfkt(7F=q)n6EZ*jXaG%NFy&y?OrTtTln@{kpDM-^VB#;&0@IJm=`H|i1sZLIW@!c5mxsvj$Ue2 z9O%T5Q(CA&J+>CkLMYYjv-YJmzr?9c5%Kx(UeuI>~IDBz7!-ZbNmE$W3 zhe=_>;B!u$1p(C%nzcbcVAm7P*ukpaH}9VE*|Ta&1D5u%>w@R1zu8Gfk^B1q%_Xy4 z4BwWewn+qWv_t-k-p=Rf=xDSJY6p;f4d=EK)z9D?@Q_u0E;9`290{i_x~4f?BeXxx z;mIg(dyph{P>pj0@#Up8pUE6O*eW_p4*b~{ix9IS`eB#1qpXR>iK1DnS~6Yoog@+;0PnHY**1J{9PDCiP&>2>yVz0e`v{3Q zb~v*&PRusL&-EVUlq*M>ck38=Ll{coI0d+dR{|vgklU4I%mdhU0b`g7iT0-h+9bdDm0x2AxM`HvIK*@V%5*qsKw_2_W6@U8H8orI)>7p${Pi#? zS!K0i%CwZ0hq~x7&G1a8pgXCp=G!$qONzByG@ZWcqPz+2UPV>az(*UpUjag~NcBuN zg%?TmHPuD}PkAiOpElb>N;SRgY&|obRw-BLeyqyU3m>? zL80vUCuwCp*2F!Rl0%Dz88E`B>}M_;T8XIogPts}ZvfPb*FrB{!GNINmT5;KiRlxNdsR;x2Be2)9=L9!dMr}Z&_$vQnOp5q?T(+WF2o;rscSWJ~d zas<;;&h6~$4XG4_y}F2pu$>r=xy8PDB4dpO(?AZO{a3AbOu)|TaYcIoS}BFoURU)3 z8(m6moOpc9#X0C+JgbOF$08_Ab*MO>! z#wvmk)?-1X5HH}xa;2l%y~odDNj+7eD#Gxzml02IR5NwxQDfFFz1%5fW%o)9HAfKV z9$s4ggI%TQVKU}!o3k{*u|lc>4-a7-7flIgX8hK?y+44nM|Q(9UTmWC>{_w1An^Hf zG{M$MeQW!sh#Bx4S#BR+gO-E(Gs6YG z_AMOeh#HhX)_cbZ>8ge}BdpGolY2h2z?_-o(@%I=)0X2z!SBg#U7;jy+Ing`OyrA- ztQWads|uvI^Zn8K^S&y%@`!=I53@;^o|<$L%)C?rv2@VvfpO1w##l$Jj@DmR#%kHh zZ%gN)Tg^P_@waUn2m}0AI@18ZRFo#j<)YI({RTB6aKHIwsKzaTSoEV}`?OLnF@iYd zi|=t$X0CE7^_>p+Mw{;I1CfoL^IYJ4eT!8TUJ;qq6F#A`l8(=sImwc|a@le}sgq0Y)q@t|+d z446ZVxP~Z*8WOsgbg$0sY3_#;)-rxpF6*4Lt>wC5o458LjpPMgg?jRtritadJYMQh ze#>k>rO{#f>NaBi8d>Q~vwZCs%qxZT^RYvh%ldnBj12;}QbnV5s?D5xZeIdY3!Mt1 zCmGp=r5q-1S2w_h6J9=JnW>)JLubJK1_54!$`vfv#3VAse~mo2ju;CAkg4m-TE*FD z5BLofDMbw}S5&Q9kD1;&M+6?r0iQq@rFoq4B3Lsv#bD%8IzoB8+FDNp@rc!g4JLhT z@a3Ajm|yRBmwdG=?C@cBbQ9;vCScitpOxmQxFefZ`6eK^fdftj-lUZaP&^lbdyfj* z86G1Cj{@Jc=WfwGvQg+2PfL+_>tZlG)yNuf(q6Uwaqc7a%TE55XZRx9x`}A{m${F- zDW46OX89GUO4A9t)J;W$8QAn;4(#Ps({vX6xUPy_s_(dzqfAZA@#!lLmpR_y@%hBf zDk<17$F!OV@!4yB08#FjAbj!^cC8iaEd&sC4i5`{yuvL$@mgE{Re-4F{PSM?CB!}& z6X~Aat1?l71>?Zy&j_1?#=`5!_$YQ81Rzq789 z%!Q)kNao7>YyEQ2tdI(|_l56iFiiGaL6&?a}e^7`4YnQYo_t>j5c~*A-uk^Ue?ptz5`UX;2D0|3YRa9>CHScXj$3bMjb&^uSa79oD;3NN4$0#q+Eu z2Fc^8iO$f{OV0$|(+V>fKI>E4{q;3ut19a_=eYjFI~))_Q@H6Mzf)e?Bp`|r3Al!b zlM*MenfUoe(lrh(WpeW2B4|31IBU!+hYY|RKbZS{}?egoG0|M1~5T@2u_83}x z$WQg*C6vK}Mcq#X(!fr;mT_9flfD_x&4UHSO3i)LX9juZ;6)A>9J|@{k_l3gzUt6( zwjzK_NJip zkKgEE#ghn?p&E1x$PnPPsAfP7oNCYkP*@ko{0AG_0A&QfHwzs^t>+quyX5HiSrwQ^ zVy`z%#kQ;(vvm$CKITy#e(3XYXGz=%_~_m{3>l1TIR*V>UsML!&&M@|GVv+3QQYa93P zT&<^YrnQfo(@@xd=h9Uitlq0GWwHwplI8)VXy9vzdAB}=^JD62k%h;{i|BPQS>(SJ-=%Y0CYi0${V)9k(ZH1DNlSk z2K1oa^(tZQBnN4p!~ONIX2}Q^l%$e}i(K8O<3;YY_dl9YCno~3DefsS#ch)lZR)PO zv8|{;)9|O~9NhQh<0YCbR~xMdu~8{jPcYr^ zvUZub2{I+`YA!B#-S?C858$R8-28E&LDx3;xj(XSj0%ksHJW-CkH=s5lT`igJx!=K z`S}tK2n5ELloX)rI6e$t6+)S_;|9toyyFx*i+G?{&WVeoUzbpP9WVD;2NG}y)FY_=jF*n}y>wL)d>u}p91xTgsAz!8k7SpQy-X-4`Vj#V z;iMS_kt1Y1oWomyu+{A`vDl?ctD@+E3*n=t=1-Sq3-8ypD>BnyNoLX~wQ09*So3Tl zF`hvBuIu=Snn_(7q-YQ>ZoYfuzdjB~CG%Y#o{W4v9DRG%=Irb*QI@dusi@XHZf8)jrYEr^HHCk&VD zTfAwuuOB{jQ0^_$gRFadykn0fxH%)L0VHE}Rg(t@F;&&5u2c-(5kO1>RU@AT1)+l88SUcX>|8;I zp&ejbobPNglhgS5>rNg)+EaQ>eyeAYXj&Za9XjTt0|290dHbfI*Vasen7*#!0gr3> zq6+FzOZ}v2X(JFHVpaBdpGVv=OoTv+>DCr>)>m+?;7pM7DXZv;tPs9>ywY&E(+UEP zRf~hqpV)6^fWMyC0SeHQ(@)@d()aV&oxFroNz4_NZIm|8vj8aG^`d@# zy%<2DFFDw8arXK_{N++bEHo!$13G3}FtPVEC&b+fU@m6K0Eb`GN^TMfWxN;1IzBs! zceuTyTjI)*^cd~1^2O4T9mG1_bDyiTt`eLBenpjm*j~G!X?%Pz#b+_Er@Z?kn+9bR ze0GPU=+`dVl9H!V%YZ1XOWk85K)J7D|I>#`5owR>P=`jEu&}V?F90#bH$|J1dJQeG zxhz-z(Oidg7T9QL6D9VN(0(56s0mHub10k$p*YCh1M1oOkWkh`_o>dF3!9;^2-}m{ zM2Bgex?fT?tYhM|AllE>B44@H1JZ{z*;6eIW7dDHh=)S}P_Mpw{HC&H>-E4d@mO1X zwdvAZa&~I>@h7jvC*E_TtZ%a^0{lhHYi?(%;TW6vcb#wYdtY&`kbUd3c>7`4%5rQo zh}yjRz$@esK|6B|=$BU47B^npSFmP-(3)W_W5xv!ryMP$VPa}Cpw(ui05=231UnLU zuUe7Cb4i5ccF=_ujW6_645O1V7+;Um4|&>r8re~|pXgQe_4P;_qrRI=dx} zcZG{a@kw>`xGQ+9lj%UeP*r{3>S*4A?Q6yTAN|?2=ifx|LmiP0@q5k~qxTX>Qe{|GmIYSrXt-o^nG1=-q@2hb%lROyHdZXkS~cU{Z$ zftm)8tjU%;0ck2d((a0{DlQNjTxdE`P)MLb7tVdusgo@B5|OED2|v>5?To8tb7A&L z0C@*DeDHy^m>&4^w1)cKmDn%(yY1d=0n0)S%@ug6M)vlRCW%dfXQ0O=G~gpeMtD$<=+*#=F_<)LnBNIJv7%ls z#vGA|cpel-myVv7#~u}Dk4~O19%13WXWnU=w-&N~Te$g8_6xV=1AW5?R7%DF)H>Wyi|*82t4;hSx~yCpft0 zJUbR)^;2cX_xUKToZsGH+_9TwhG_@a(|>qKLA`zrP|90Vgme~&ExaN7ODu7m)H92c z1z=fBJYfe=aCj?|+j)%RaPP&aLWEts&G}y@$W;Kd#fg``)?)QV-%o%#AI^-39z+&9*11svh_$lIDE%v0R75NN?xAM@^9h{K@jSamd|7R z;J%0w@O@u|CTo5cBCNqk7;}o_Du4t>J@T50$E);Gq)>{AMD_HtqLQ!+6c>*X z?HH}6f@bHvVc^r0p%ZHT8Xax51JnafEg}URg)Wq$TA=Zff;~JJDM`W+OlL!NY+y2>>mnzU|d9|CGMbhe5AM z_qLp=CHHO}`+03xO#z=Y@3_pAF)0#V;(lx>mWXt3bEP{nRoF+R$_^}_hA>wGVD;{` zQNzYF69uO z0ezKqe#^W^*D6gXv6G8)3D(%wo4w5-80=21I(1qya-EG%_aQT+W%1*AqJ``mCi0)u znUU+fEJ+Qj@-@7Sii*zy-Uag5ttWkIN7mFnSWr?U(^*eR zfJ4VTlC3>?Et3IiB5BIA&g8BBVmv^;fXtIZzO$FkYF{W6*iOsA=2mS0t_>6UpvwWc zKh}RF`ZomSbP-V9u_nOZ2ym2faN})j27A{Uh$oV|O6yatJ3i~~7iUny&AHkc4C>NCjN%PrT=EUQnQLfG{@*kxSfvr351MZ@9_Lav1&g@-_X&x}f99mX?Y? za?ebWevcxKO6e7bQfmFgQA805Q1!?Q)VmLd@ID;umDza8Qvp>ikXJiJf-Dw4oY=dc z?VB2L@}A$?%-8@=Mlilb_ZXWLQZH~f39D5YBpW^=8frZXq?LLuqNKPzaYJZC=POq5 z?%PKQv>g?k1{XZ#kU=|o`-RgOIvw_{1>sSXsnmS53Lt19cwYd5yoAJ(Yl?59k`TI2 zB)4z!%m@xzZ&2o6#i7_eZ`o@BW9Av@diw zMk82ycjs$}j}syB6HTw!Jze3a_m6VzCBxC&G{Z5E-}Ijrf$+^n18GsIW=A^u>S)!4 zKEQUj?1JN%a-CDfhFq-*+CXNor(0Bm*~tCilR(0?xn(_|IhNesor3Vz1=_%xLx8#-lXSD>_xA>Re2$|@)AwD1y? zoT4LPtWC@84n|doy2V+u#PxttC~__r&4H=8Asjmoc>-JUrqRk-^?_)F;L3 zR79hQ`xU^Mug(COK=4p{K&55m$9u-Upa%*;uj4p{XO<23_k-v|QU=+`zpHz{<37z1 zNo1n?B)L$ZtsC2_UJ6v#fGP_ejR6uc8AOOCHDKv#fF1?p!t7iWaU0I#*mAA8J-q{T z_d~D#(HTk>@_xW; z2B%VQ*V|W9St=<;yadioz+PPLZ5u9!DRf?#@g~g^f6Qy3pr5MX{uI654zhIlEw?|O?>vJKymSDs-?IQ-KFzRo#=1CQ z_gTzn_W4wSo2aWQg z0~yXYfKYRf>hKY>`={VfL^Xb*ixT1hVF4k=toJ-HG@`lEW3+_$r@WZc*OfkR3_e^; z;37H#ZeYpf>NfBs0NdG@IpMYsfY>E>19-?PJqH5yS$z{}y>u3NK-oAxWG%2&RxS-? zT8P9lETx3)bHSkQhc_3+)JS8sN_$@_T)0rTl3jwn8e~E$%KFv1y<&m_02wXIGK0$1 z*nAk0?BjaB6fW)weodR3jRKWvKd1WKu{ zxbK>Fw9q%#%df`|xSz%2p=W9t85zEI&fISlwKUrV(8LxQc$lS>`Mi;S<89y1lI$S> zyWX4!;9-p;dH0Kd!9-h(#nMv{RgV-kP846w7Tm+{Yu3cWZ<3|&HD~q%=$NLYnDd)Kb-#Vr4W46QUh_X zFgFbbtABrN?gBr2eBB2V8us||(b+j`{GcuvR%P72A|Aie@`p#8m3>@`a0!|z7}l*jBDP8cDo< zhxq%J*WmG;qdejB3FN_Q9Gs}4@fzB=&$24I7QSd}KWmLY5_)(VXL(;N`{W7zKSZWT zwtEjq#dtc*IND+^_bo9m-yH6G#2uJ3o(Pi3IdrgD8WV*0-x`Gd$tB6}XD61m_J|$) z4}A3h${WG{X&@!+mBVMryh=js`)fg_$eX|NPELFY2QB{g@nih+wm?6TCF1uo1jj+9 z>-8MI|5XHw*Z=hSeqTQn{d&N^n5^-`6@Wwe9Uu97nIFSnxA<4t%HNv#XUTsqZ{)8k zzJ34y+>{gRcaGjLtPq&mnK-*RnHt(+f7u&Z5%38zL7A{WL_`Q6l7`Nvvi5c^OpxoQ zHg2Xamd1uWlJ+(x1P~cJV|x=zJ98$8mZhD9owMa%1q2XvS0fis2U8}<4e&3F;M*4y z1bZ0*F|of@BlOR!`S)vpL;raVJSZa@OGj7J|3FQ!e^`^0y{nU@sndVp`h5TF`v0K; zfx~~OkBJXEW@=yzAu3Mx#_FanOu7&iX<0DPrXFC5$k`g2 zn@axqE%oQOoE`y08)al=YV5)UE+_{si2U;^f1eC+#DA;qAL_tX``5hwkKW%8b@2Z` zs6*gitOE=goax&l_`eU?54ZHAIrwjN+mE*3pVjg2+|p085X@z4H)1>H@3)Hh(O~?y zn(;$*KU$6dr8)!?9DDS?GmwZMjmST%4z%$9w!VM3rGM3i{4kKu}fd!gYxmipfEugKO6yv-sJdU%sre;%?O}O2qXdYZyzRpBodBf zGGqE%84TDC?1#zjZ)Gq6Fk5~p;}Zb)|4SJH_S7$4~MpO1sV-~wP|e>xY&CnWIOxo{W^7^$1rYqdv=0UcUHZ$ofilp6Kc5TA1o(fc7nBM9+6SOa==XEsQ2t-W z4F-q9gnnrsDC7GFW$=GchWH0%{7_(Ee!O3BJ%N8vCJ6t%EkcN2<|GV`fFgex4^RgC z2W5Oe&T$tfLrWXrF=1U#bxSW(?7D=g+1tA?eX|b)5IH+DdnN>StpkrlPMS$q1OXM0 z5R`;T!v$qzq=f{bP#IY`Tox`ZEhED(Ed`Sn``?ey!`cI97egnPZ`J@b6b|PnU}cp- H$rAhz>CY|y literal 0 HcmV?d00001 diff --git a/carousel/generate_bad_controls_carousel.py b/carousel/generate_bad_controls_carousel.py new file mode 100644 index 000000000..03df8b3f3 --- /dev/null +++ b/carousel/generate_bad_controls_carousel.py @@ -0,0 +1,1300 @@ +#!/usr/bin/env python3 +"""Generate LinkedIn carousel PDF for the bad-controls launch (v3.12). + +Mirrors the POSTER-MODE architecture of ``generate_dml_carousel.py`` +(magazine sidebar with progress tick, light gradient background, split-color +logo, footer wordmark, dark slides, soft card shadows; poster type floors: +body >= 16pt, captions >= 13pt, headlines 32-54pt, code >= 15pt; one idea + +one visual + roughly 25 words per slide). + +Palette: "Junction" - ink/stone structure with a single AMBER accent reserved +for the bad control itself and for the third road out of the fork (the +deck's visual thesis: include-or-drop is a false choice; condition on the +covariate's UNTREATED path instead). The two wrong roads (include at t, drop) +are always warm gray, matching the DML deck's misspecified-fit convention. +Two dark slides: the "drop it" twist (slide 4) and the code slide (slide 9). + +Narrative spine (practitioner-dilemma hook - user decision 2026-10-18: lead +with the include-or-drop choice every practitioner faces, name the covariate +explicitly on the cover, then show both roads miss): + +1. Cover -- "Include the covariate, or drop it? Both can be wrong." + ("can", not "are": the paper's bias terms vanish when + Condition 1 or 2 fails - user feedback 2026-10-18). + Fork motif (illustrative): one road splits into two + gray roads that bend away from the true effect and + one amber road that reaches it. Subtitle names the + 3.12 release that shipped the lane (FEATURE_RELEASE, + pinned to the CHANGELOG by the claims test; the + FOOTER version is derived from pyproject, never + hardcoded) and the paper. +2. The dilemma -- a covariate treatment can change (occupation, hours, + insurance, firm size). The paper's Definition 1: a + bad control matters for the untreated outcome trend + (Condition 1) AND treatment affects it (Condition 2). +3. The receipt -- tutorial 33's naive within-TWFE with the bad control + at t: 0.4886 (SE 0.0142) against a true 1.00 on the + paper's own DGP 1 made staggered (truth known by + construction, said on-slide); the half of the effect + that runs through the covariate is netted out; the + paper's Table S2 reports the same -0.501 bias. +4. Twist (DARK) -- dropping it is still wrong: the covariate's untreated + path carries trend information (Section 3.2). NO + number on this slide on purpose: tutorial 33 states + the result and deliberately does not run a drop-X + arm, and the deck never shows a number the committed + notebook does not (the earlier on-slide "no number" + caption was cut on user feedback 2026-10-18). +5. The paper -- Caetano, Callaway, Payne & Sant'Anna (2026), arXiv + preprint (status on-slide; the paper is first NAMED on + slide 2 so slides 3-4 may say "the paper's"; the + Hugo-not-Pedro disambiguation stays off-slide): two + ways out - + condition on the pre-treatment value (Approach 1) or + model the covariate's untreated path (Approach 2). + ATTRIBUTED PARAPHRASE ONLY, no double-quoted pull + quote (the review is pinned to arXiv v2 of an + unpublished preprint). +6. Route 1 -- already in the box: CallawaySantAnna reads covariates + at the base period on panel data; 1.0540 (SE 0.0235) + with [x, z], 0.9754 (SE 0.0274) with [x, z, w]. Which + conditioning set is right is an identification call, + stated on-slide. +7. Route 2 -- the DMLDiD bad-control lane: the paper's + Neyman-orthogonal doubly-robust score, four + cross-fitted nuisances, two nested; 0.9766 (SE + 0.0260). Payoff chart: three committed estimates + against the truth line - TWFE gray, BOTH routes amber + (both are valid; user feedback 2026-10-18). Body says + what Route 2 buys: W enters only the covariate's path + model, never parallel trends (Remark 2), plus the DR / + ML score and the pre-test. +8. The pre-test -- bad_control_summary(): the six ATT_X(g,t) rows. Pre + rows (t < g) pre-test the path assumptions and sit + near zero; post rows check that treatment moved the + covariate and sit near the true 0.50. Both caveats + on-slide: a nonzero pre row is NOT evidence of a bad + control; a zero post row does not prove the converse. +9. Code (DARK) -- the tutorial's own lane fit (seed=0, W = ["w"]) plus + the Route 1 one-liner, >= 15pt. +10. In the wild -- the paper's NLSY79 job-displacement application (THE + AUTHORS' estimates, labeled as such, not reproduced + here), told wrong-then-right: the intro states that + displacement moved the covariate (ATT_X -0.0261, SE + 0.0092: occupations paying about 2.6% less); the gray + card is naive TWFE ("almost -10%", the paper's words, + with or without the occupation score); the amber card + is the paper's bad-control estimator (ATT -0.0672, SE + 0.0242, about -7%); the line below says naive TWFE is + roughly 40% larger in magnitude and WHY the right one + is right (parallel trends conditional on the + occupation a worker would have had without + displacement). Plus the + restrictions + validation strip (panel only, cluster + yes / survey no, CS simple weighting for the headline + ATT, numpy oracle at 1e-12, black-box goldens vs the + authors' R package). +11. CTA -- pip install; tutorial 33 mentioned ONCE, here. + +Claim discipline (verified against the committed executed notebook +``docs/tutorials/33_bad_controls.ipynb``, the paper review +``docs/methodology/papers/caetano-2026-review.md`` and +``docs/methodology/REGISTRY.md``): + +- EVERY simulated estimate on the deck is a committed, seed-locked + tutorial-33 value from the paper's DGP 1 made staggered, truth known by + construction - labeled on-slide wherever a truth value appears. notebook + <-> deck sync is pinned by ``tests/test_bad_controls_carousel_claims.py`` + (parses this module's constants via ``ast`` and locates each on the + committed notebook surface). +- The application numbers on slide 10 are the PAPER'S estimates (Section 7, + Figures 6-8 as transcribed in the paper review), labeled "the authors' + estimates" on-slide; the library has not reproduced them and the deck + never says it has. The "roughly 40% larger" line is the paper's own text + statement as recorded in the review. +- The drop-X slide carries no number: the tutorial does not run that arm + and the deck never shows a number the committed notebook does not. +- The pre-test slide carries both Remark 6 caveats ON the slide: pre rows + flag a possible assumption violation, not a bad control; a zero post row + does not establish that treatment left the covariate alone. +- The Route 1 slide says which conditioning set is right is an + identification call (the tutorial's own caveat: on this DGP conditioning + on W alone already recovers the truth, so the deck does not claim "you + need the lane"). +- The headline ATT keeps the Callaway-Sant'Anna simple weighting (not the + paper's Remark 4 overall) - said on the production strip. Panel-only / + cluster-only / anticipation=0 / varying base period - said there too. +- The cover motif is stylized art, labeled "illustrative" on-slide; it + plots no tutorial data. +- No "only"/"first"/"unbiased"/"detects bad controls" absolutes anywhere + (claims test bans them). No external competitor is named; the authors' + R package is named once, as the black-box parity oracle it is. +- CallawaySantAnna is named honestly as the Route 1 host (Approach 1 needs + no new code) - the lane is an addition, not a replacement. +- Tutorial 33 is referenced ONCE, on the CTA slide (house precedent). + +Run with:: + + python carousel/generate_bad_controls_carousel.py + +Produces ``carousel/diff-diff-bad-controls-carousel.pdf``. Generation +requires ``fpdf2``, ``Pillow``, and ``matplotlib`` (carousel-only +dependencies, not part of the library's install extras). +""" + +import os +import re +import tempfile +from pathlib import Path + +import matplotlib + +matplotlib.use("Agg") +import matplotlib.pyplot as plt # noqa: E402 +import numpy as np # noqa: E402 +from fpdf import FPDF # noqa: E402 +from PIL import Image as PILImage # noqa: E402 + +# Page dimensions (4:5 portrait -- same as the other decks) +WIDTH = 270 # mm +HEIGHT = 337.5 # mm + +# Version label derived from pyproject.toml (regex, not tomllib: py>=3.9). +_PYPROJECT = Path(__file__).parent.parent / "pyproject.toml" +_m = re.search(r'^version\s*=\s*"([^"]+)"', _PYPROJECT.read_text(encoding="utf-8"), re.MULTILINE) +if _m is None: + raise RuntimeError(f"could not parse project version from {_PYPROJECT}") +VERSION_LABEL = "v" + _m.group(1) + +# The release that SHIPPED the bad-control lane (CHANGELOG 3.12.0 section). +# Deliberately not derived from pyproject: the deck may be built from a later +# version, and the cover's "New in" claim is about the shipping release. +# Pinned to the CHANGELOG by tests/test_bad_controls_carousel_claims.py. +FEATURE_RELEASE = "3.12" + +TOTAL_SLIDES = 11 + +# ------------------------------------------------------------------------- +# "Junction" palette -- ink/stone structure, AMBER = the bad control / the +# third road. The two wrong roads are always warm gray. +# ------------------------------------------------------------------------- +INK = (28, 25, 23) # #1c1917 primary structure / code panel +STONE = (68, 64, 60) # #44403c secondary structure +AMBER = (217, 119, 6) # #d97706 THE BAD CONTROL / THE THIRD ROAD +AMBER_BRIGHT = (251, 191, 36) # #fbbf24 amber on the dark slides +AMBER_TINT = (255, 251, 235) # #fffbeb gradient start +CREAM = (254, 243, 199) # #fef3c7 light fills / dark-slide text pop +WRONG_GRAY = (120, 113, 108) # #78716c the two wrong roads (warm gray) +SHADOW = (214, 211, 209) # #d6d3d1 soft card shadow + +# Text + structural (shared with the other decks for legibility) +NAVY = (15, 23, 42) # #0f172a primary text; dark-slide gradient start +GRAY = (100, 116, 139) # #64748b +LIGHT_GRAY = (148, 163, 184) # #94a3b8 +WHITE = (255, 255, 255) +DEEP_AMBER = (46, 30, 10) # #2e1e0a dark-slide gradient end +PANEL_INK = (28, 25, 23) # #1c1917 code panel fill +AMBER_CODE = (251, 191, 36) # #fbbf24 code string/number literals +SLATE_CODE = (168, 162, 158) # #a8a29e code comments + +INK_HEX = "#1c1917" +STONE_HEX = "#44403c" +AMBER_HEX = "#d97706" +AMBER_BRIGHT_HEX = "#fbbf24" +WRONG_GRAY_HEX = "#78716c" +NAVY_HEX = "#0f172a" +GRAY_HEX = "#64748b" +LIGHT_GRAY_HEX = "#94a3b8" + +# ------------------------------------------------------------------------- +# Seed-locked numbers from the committed executed tutorial +# (docs/tutorials/33_bad_controls.ipynb, seed 5). Every constant below is +# located on the committed notebook surface by +# tests/test_bad_controls_carousel_claims.py - never edit one without +# re-running it. The example is SIMULATED (the paper's DGP 1 made +# staggered) with truth known by construction: ATT = 1.00 and ATT_X = 0.50 +# in every post-treatment cell, 0 before. +# ------------------------------------------------------------------------- + +TRUTH = 1.00 # lambda + delta +TRUTH_X = 0.50 # lambda - the effect of treatment on the bad control +TWFE_INCLUDE = (0.4886, 0.0142) # within-TWFE with the bad control at t: ATT, SE +CS_A1 = (1.0540, 0.0235) # CallawaySantAnna, covariates=["x", "z"] +CS_A1_W = (0.9754, 0.0274) # CallawaySantAnna, covariates=["x", "z", "w"] +LANE_W = (0.9766, 0.0260) # DMLDiD bad-control lane, W = ["w"] +PAPER_S2_BIAS = -0.501 # the paper's Table S2, TWFE Include BC, n = 2000 + +ATT_X_ROWS = ( # (g, t, att_x, se_x) - results.bad_control_summary() + (3, 2, 0.0019, 0.0166), + (3, 3, 0.5137, 0.0156), + (3, 4, 0.5055, 0.0299), + (4, 2, 0.0120, 0.0169), + (4, 3, 0.0061, 0.0190), + (4, 4, 0.4764, 0.0263), +) + +N_UNITS, N_PERIODS = 2000, 4 +N_NEVER = 974 # never-treated units in the simulated panel +COHORT_SIZES = ((3, 531), (4, 495)) + +# Tutorial fit config rendered on the code slide (claims test pins these +# against the notebook's code cells) +CODE_SEED = 0 +CODE_BAD_CONTROL = "x" +CODE_W = "w" +CODE_Z = "z" +CODE_CONTROL_GROUP = "not_yet_treated" + +# The paper's NLSY79 application (Section 7; the AUTHORS' estimates as +# transcribed in docs/methodology/papers/caetano-2026-review.md - the +# library has not reproduced them and the deck says so on-slide). +NLSY_ATT_X = (-0.0261, 0.0092) # overall ATT_X: occupation score +NLSY_ATT = (-0.0672, 0.0242) # overall ATT: log earnings (baseline imputation) +NLSY_N_DISPLACED, NLSY_N_NOT = 748, 2483 +NLSY_TWFE_TEXT = "almost -10%" # the paper's own words for the naive TWFE arms + +# Validation anchors (REGISTRY DMLDiD bad-control block / CHANGELOG) +ORACLE_TOL = "1e-12" +R_PACKAGE = "badcontrols" + + +class BadControlsCarouselPDF(FPDF): + def __init__(self): + super().__init__(orientation="P", unit="mm", format=(WIDTH, HEIGHT)) + self.set_auto_page_break(False) + self._temp_files = [] + + def cleanup(self): + for f in self._temp_files: + try: + os.unlink(f) + except OSError: + pass + + # ----------------------------------------------------------------- + # Magazine vertical sidebar -- INK bar, AMBER progress tick. + # ----------------------------------------------------------------- + def _draw_vertical_sidebar(self, slide_number, total=TOTAL_SLIDES, dark=False): + bar_x = 14 + bar_y_top = 45 + bar_y_bottom = 275 + self.set_draw_color(*(LIGHT_GRAY if dark else INK)) + self.set_line_width(0.6) + self.line(bar_x, bar_y_top, bar_x, bar_y_bottom) + + ratio = (slide_number - 1) / (total - 1) if total > 1 else 0.0 + tick_y = bar_y_top + ratio * (bar_y_bottom - bar_y_top) + self.set_draw_color(*(AMBER_BRIGHT if dark else AMBER)) + self.set_line_width(1.2) + self.line(bar_x - 4, tick_y, bar_x + 7, tick_y) + + # ----------------------------------------------------------------- + # Backgrounds + footer + # ----------------------------------------------------------------- + def light_gradient_background(self): + """Amber tint #fffbeb fading to white.""" + steps = 50 + r0, g0, b0 = AMBER_TINT + for i in range(steps): + ratio = i / steps + self.set_fill_color( + int(r0 + (255 - r0) * ratio), + int(g0 + (255 - g0) * ratio), + int(b0 + (255 - b0) * ratio), + ) + y = i * HEIGHT / steps + self.rect(0, y, WIDTH, HEIGHT / steps + 1, "F") + + def dark_gradient_background(self): + """Near-black navy #0f172a fading to deep amber #2e1e0a.""" + steps = 50 + r0, g0, b0 = NAVY + r1, g1, b1 = DEEP_AMBER + for i in range(steps): + ratio = i / steps + self.set_fill_color( + int(r0 + (r1 - r0) * ratio), + int(g0 + (g1 - g0) * ratio), + int(b0 + (b1 - b0) * ratio), + ) + y = i * HEIGHT / steps + self.rect(0, y, WIDTH, HEIGHT / steps + 1, "F") + + def add_footer(self, dark=False): + """Centered split-color ``diff-diff vX.Y.Z`` wordmark.""" + self.set_font("Helvetica", "B", 12) + dd_text = "diff-diff " + v_text = VERSION_LABEL + dd_w = self.get_string_width(dd_text) + v_w = self.get_string_width(v_text) + start_x = (WIDTH - dd_w - v_w) / 2 + + self.set_xy(start_x, HEIGHT - 18) + self.set_text_color(*(LIGHT_GRAY if dark else GRAY)) + self.cell(dd_w, 10, dd_text) + self.set_text_color(*(AMBER_BRIGHT if dark else AMBER)) + self.cell(v_w, 10, v_text) + + # ----------------------------------------------------------------- + # Text helpers + # ----------------------------------------------------------------- + def centered_text(self, y, text, size=28, bold=True, color=NAVY, italic=False): + self.set_xy(0, y) + style = ("B" if bold else "") + ("I" if italic else "") + self.set_font("Helvetica", style, size) + self.set_text_color(*color) + self.cell(WIDTH, size * 0.5, text, align="C") + + def _kicker(self, y, text, color=AMBER): + """Editorial section label: letter-spaced caps with flanking rules.""" + spaced = " ".join(text.upper()) + self.set_font("Helvetica", "B", 14) + tw = self.get_string_width(spaced) + mid_y = y + 3 + rule = 20 + gap = 8 + self.set_draw_color(*color) + self.set_line_width(0.7) + self.line(WIDTH / 2 - tw / 2 - gap - rule, mid_y, WIDTH / 2 - tw / 2 - gap, mid_y) + self.line(WIDTH / 2 + tw / 2 + gap, mid_y, WIDTH / 2 + tw / 2 + gap + rule, mid_y) + self.set_xy(0, y) + self.set_text_color(*color) + self.cell(WIDTH, 6, spaced, align="C") + + def draw_split_logo(self, y, size=18): + """Split-color diff-diff logo with AMBER middle dash.""" + self.set_xy(0, y) + self.set_font("Helvetica", "B", size) + self.set_text_color(*NAVY) + self.cell(WIDTH / 2 - 5, 10, "diff", align="R") + self.set_text_color(*AMBER) + self.cell(10, 10, "-", align="C") + self.set_text_color(*NAVY) + self.cell(WIDTH / 2 - 5, 10, "diff", align="L") + + # ----------------------------------------------------------------- + # Shadowed card helper (poster mode: used sparingly, big type inside) + # ----------------------------------------------------------------- + def _shadow_rect(self, x, y, w, h): + self.set_fill_color(*SHADOW) + self.rect(x + 1.4, y + 1.4, w, h, "F") + + def _stat_card(self, x, y, w, h, headline, sub_lines, accent, headline_size=40): + """One shadowed stat card: big number + caption lines (>= 14pt).""" + self._shadow_rect(x, y, w, h) + self.set_fill_color(*WHITE) + self.set_draw_color(220, 220, 220) + self.set_line_width(0.5) + self.rect(x, y, w, h, "DF") + self.set_fill_color(*accent) + self.rect(x, y, w, 3.2, "F") + + self.set_xy(x, y + 13) + self.set_font("Helvetica", "B", headline_size) + self.set_text_color(*accent) + self.cell(w, 16, headline, align="C") + + ly = y + 36 + for line, emphasize in sub_lines: + self.set_xy(x + 6, ly) + self.set_font("Helvetica", "B" if emphasize else "", 14) + self.set_text_color(*(NAVY if emphasize else GRAY)) + self.cell(w - 12, 8, line, align="C") + ly += 10.5 + + # ----------------------------------------------------------------- + # Figure helpers (matplotlib -> PNG -> fpdf image) + # ----------------------------------------------------------------- + def _save_fig(self, fig, dpi=200, transparent=False, facecolor="white"): + fd, path = tempfile.mkstemp(suffix=".png") + os.close(fd) + self._temp_files.append(path) + try: + fig.savefig( + path, + dpi=dpi, + bbox_inches="tight", + pad_inches=0.1, + transparent=transparent, + facecolor=None if transparent else facecolor, + ) + finally: + plt.close(fig) + with PILImage.open(path) as img: + pw, ph = img.size + return path, pw, ph + + # ----------------------------------------------------------------- + # Cover motif -- the fork. One road arrives from the left and splits: + # two warm-gray roads ("include X at t", "drop X") bend away from the + # true effect, one amber road ("condition on its untreated path") + # reaches it. Stylized art, not a data claim (it plots no tutorial + # data) - labeled "illustrative" on-slide. + # ----------------------------------------------------------------- + def _render_cover_motif(self): + fig, ax = plt.subplots(figsize=(10, 4.0)) + fig.patch.set_alpha(0) + ax.set_facecolor("none") + + # Shared trunk + xt = np.linspace(-3.0, 0.0, 40) + ax.plot(xt, np.zeros_like(xt), color=INK_HEX, linewidth=5.0, solid_capstyle="round") + ax.plot([0.0], [0.0], "o", color=INK_HEX, markersize=11, zorder=6) + + # Branches + xb = np.linspace(0.0, 4.0, 160) + bend = 1.35 * np.tanh(xb / 1.5) ** 1.6 + ax.plot(xb, bend, color=WRONG_GRAY_HEX, linewidth=4.0, linestyle=(0, (6, 3))) + ax.plot(xb, -bend, color=WRONG_GRAY_HEX, linewidth=4.0, linestyle=(0, (6, 3))) + ax.plot(xb, np.zeros_like(xb), color=AMBER_HEX, linewidth=5.0, zorder=5) + + # The true effect: a target ring at the end of the amber road + ax.plot([4.0], [0.0], "o", color="white", markersize=22, zorder=7) + ax.plot( + [4.0], + [0.0], + "o", + color=AMBER_HEX, + markersize=22, + zorder=7, + fillstyle="none", + markeredgewidth=3.0, + ) + ax.plot([4.0], [0.0], "o", color=AMBER_HEX, markersize=9, zorder=8) + + # Labels + ax.text( + 4.22, + float(bend[-1]), + "include it at t", + fontsize=15, + color=WRONG_GRAY_HEX, + fontweight="bold", + va="center", + ) + ax.text( + 4.22, + float(-bend[-1]), + "drop it", + fontsize=15, + color=WRONG_GRAY_HEX, + fontweight="bold", + va="center", + ) + ax.text( + 4.42, + 0.0, + "the true effect", + fontsize=15, + color=AMBER_HEX, + fontweight="bold", + va="center", + ) + ax.text( + 2.0, + -0.26, + "condition on its untreated path", + fontsize=13.5, + color=AMBER_HEX, + ha="center", + va="top", + style="italic", + ) + ax.text( + -1.5, + 0.22, + "your covariate", + fontsize=13.5, + color=INK_HEX, + ha="center", + va="bottom", + style="italic", + ) + ax.text( + -3.1, + -1.55, + "illustrative", + fontsize=15, + color=LIGHT_GRAY_HEX, + style="italic", + ha="left", + ) + + ax.set_xlim(-3.2, 6.6) + ax.set_ylim(-1.7, 1.7) + ax.set_xticks([]) + ax.set_yticks([]) + for spine in ax.spines.values(): + spine.set_visible(False) + fig.tight_layout(pad=0.2) + return self._save_fig(fig, transparent=True) + + # ----------------------------------------------------------------- + # Payoff chart -- the four committed estimates vs the truth line. + # ONLY committed tutorial values (point estimates + 1.96*SE whiskers). + # ----------------------------------------------------------------- + def _render_payoff_chart(self): + fig, ax = plt.subplots(figsize=(10.2, 4.3)) + + arms = [ + ("TWFE\ninclude X at t", TWFE_INCLUDE, WRONG_GRAY_HEX), + ("Route 1: CallawaySantAnna\ncovariates=[x, z, w]", CS_A1_W, AMBER_HEX), + ("Route 2: DMLDiD\nbad_control=x, W=[w]", LANE_W, AMBER_HEX), + ] + xs = np.arange(len(arms)) + ax.axhline(TRUTH, color=INK_HEX, linewidth=2.2, linestyle=(0, (5, 3))) + ax.text( + 2.62, + TRUTH + 0.02, + f"true effect {TRUTH:.2f}\n(simulated - known\nby construction)", + fontsize=13.5, + color=INK_HEX, + fontweight="bold", + va="bottom", + ) + + for i, (_name, (att, se), color) in enumerate(arms): + ax.errorbar( + [i], + [att], + yerr=[1.96 * se], + fmt="o", + color=color, + markersize=14, + capsize=7, + linewidth=2.8, + capthick=2.4, + ) + ax.annotate( + f"{att:.4f}", + xy=(i, att), + xytext=(i + 0.1, att + 0.03), + fontsize=15, + fontweight="bold", + color=color, + ) + + ax.set_xticks(xs) + ax.set_xticklabels([n for n, _, _ in arms], fontsize=12.5, color=NAVY_HEX) + ax.set_ylabel("estimated overall ATT", fontsize=14, color=NAVY_HEX) + ax.tick_params(axis="y", labelsize=13, colors=GRAY_HEX) + ax.set_xlim(-0.6, 3.9) + ax.set_ylim(0.38, 1.2) + for s in ("top", "right"): + ax.spines[s].set_visible(False) + for s in ("bottom", "left"): + ax.spines[s].set_color(LIGHT_GRAY_HEX) + fig.tight_layout(pad=0.3) + return self._save_fig(fig, facecolor="white") + + # ----------------------------------------------------------------- + # Pre-test table (fpdf cells, big type) -- the six ATT_X(g,t) rows. + # ----------------------------------------------------------------- + def _draw_att_x_table(self, x, y, w): + cols = (("cohort g", 0.19), ("period t", 0.19), ("ATT_X(g,t)", 0.31), ("SE", 0.31)) + row_h = 13.5 + # Header + self.set_fill_color(*INK) + self.rect(x, y, w, row_h, "F") + cx = x + self.set_font("Helvetica", "B", 15) + self.set_text_color(*WHITE) + for label, frac in cols: + self.set_xy(cx, y + 2.5) + self.cell(w * frac, 8.5, label, align="C") + cx += w * frac + ry = y + row_h + for g, t, att_x, se_x in ATT_X_ROWS: + post = t >= g + self.set_fill_color(*(CREAM if post else WHITE)) + self.set_draw_color(225, 222, 218) + self.set_line_width(0.3) + self.rect(x, ry, w, row_h, "DF") + self.set_fill_color(*(AMBER if post else LIGHT_GRAY)) + self.rect(x, ry, 3.0, row_h, "F") + cx = x + vals = (str(g), str(t), f"{att_x:.4f}", f"{se_x:.4f}") + for (label, frac), val in zip(cols, vals): + self.set_xy(cx, ry + 2.5) + bold = label.startswith("ATT_X") + self.set_font("Helvetica", "B" if bold else "", 16) + self.set_text_color(*((AMBER if post else GRAY) if bold else NAVY)) + self.cell(w * frac, 8.5, val, align="C") + cx += w * frac + ry += row_h + return ry - y + + # ----------------------------------------------------------------- + # Code-block helper (dark panel with token-colored lines) + # ----------------------------------------------------------------- + def _add_code_block(self, x, y, w, token_lines, font_size=15, line_height=12.5, fill=PANEL_INK): + n_lines = len(token_lines) + total_h = n_lines * line_height + 26 + + self.set_fill_color(*fill) + self.rect(x, y, w, total_h, "F") + + self.set_font("Courier", "", font_size) + char_w = self.get_string_width("M") + + pad_x = 14 + pad_y = 13 + for i, tokens in enumerate(token_lines): + cx = x + pad_x + cy = y + pad_y + i * line_height + for text, color in tokens: + if not text: + continue + self.set_xy(cx, cy) + self.set_text_color(*color) + self.cell(char_w * len(text), 10, text) + cx += char_w * len(text) + return total_h + + # ----------------------------------------------------------------- + # Slides + # ----------------------------------------------------------------- + def slide_01_cover(self): + self.add_page() + self.light_gradient_background() + self._draw_vertical_sidebar(1) + + self.draw_split_logo(22, size=34) + + self.centered_text(50, "Include the covariate,", size=46) + self.centered_text(74, "or drop it?", size=46) + self.centered_text(98, "Both can be wrong.", size=46, color=AMBER) + + motif_path, _pw, _ph = self._render_cover_motif() + motif_w = 244 + self.image(motif_path, (WIDTH - motif_w) / 2, 122, motif_w) + + self.centered_text( + 230, + f"New in diff-diff {FEATURE_RELEASE}: DiD with bad controls.", + size=22, + color=INK, + ) + self.centered_text( + 248, + "Caetano, Callaway, Payne & Sant'Anna (2026).", + size=19, + bold=False, + ) + self.add_footer() + + def slide_02_dilemma(self): + self.add_page() + self.light_gradient_background() + self._draw_vertical_sidebar(2) + + self._kicker(40, "The Dilemma") + + self.centered_text(72, "A covariate that", size=44) + self.centered_text(98, "treatment can change.", size=44, color=AMBER) + + self.set_xy(28, 130) + self.set_font("Helvetica", "", 20) + self.set_text_color(*NAVY) + self.multi_cell( + WIDTH - 56, + 11, + "Occupation. Hours worked. Health insurance. Firm size. Anything " + "measured after treatment starts that treatment plausibly moves.", + align="C", + ) + + self.set_draw_color(*AMBER) + self.set_line_width(1.4) + self.line(WIDTH / 2 - 30, 172, WIDTH / 2 + 30, 172) + + self.set_xy(28, 186) + self.set_font("Helvetica", "B", 21) + self.set_text_color(*INK) + self.multi_cell( + WIDTH - 56, + 11.5, + "Caetano, Callaway, Payne & Sant'Anna (2026) call it a bad control " + "when it matters for the untreated outcome trend (Condition 1) and " + "treatment affects it (Condition 2).", + align="C", + ) + + self.set_xy(28, 232) + self.set_font("Helvetica", "", 17) + self.set_text_color(*GRAY) + self.multi_cell( + WIDTH - 56, + 9, + "Condition on it at t and you compare units at different values of " + "its untreated version. Drop it and you throw away what its path " + "says about the trend.", + align="C", + ) + self.add_footer() + + def slide_03_receipt(self): + self.add_page() + self.light_gradient_background() + self._draw_vertical_sidebar(3) + + self._kicker(36, "The Receipt") + + self.centered_text(62, "Include it at t.", size=48) + + card_w, card_h = 108, 78 + gap = 14 + left_x = (WIDTH - 2 * card_w - gap) / 2 + y0 = 100 + self._stat_card( + left_x, + y0, + card_w, + card_h, + f"{TWFE_INCLUDE[0]:.4f}", + [ + (f"reported SE {TWFE_INCLUDE[1]:.4f}", True), + ("TWFE with the bad control at t -", False), + ("unit-clustered", False), + ], + WRONG_GRAY, + ) + self._stat_card( + left_x + card_w + gap, + y0, + card_w, + card_h, + f"{TRUTH:.2f}", + [ + ("the true effect", True), + ("simulated staggered panel -", False), + ("truth known by construction", False), + ], + AMBER, + ) + + self.centered_text(198, "Half the effect, netted out.", size=30, color=INK) + + self.set_xy(30, 222) + self.set_font("Helvetica", "", 17.5) + self.set_text_color(*GRAY) + self.multi_cell( + WIDTH - 60, + 9.5, + f"A simulated staggered panel built from the paper's first Monte Carlo design: " + f"{N_UNITS:,} units, {N_PERIODS} periods, cohorts treated at t = " + f"{COHORT_SIZES[0][0]} and {COHORT_SIZES[1][0]}, {N_NEVER} never treated. " + f"Treatment moves the covariate by {TRUTH_X:.2f}, and that half of the effect " + f"is exactly what the regression removes - the paper's own simulation reports " + f"the same bias ({PAPER_S2_BIAS:.3f}).", + align="C", + ) + self.add_footer() + + def slide_04_twist(self): + self.add_page() + self.dark_gradient_background() + self._draw_vertical_sidebar(4, dark=True) + + self._kicker(40, "It Gets Worse", color=AMBER_BRIGHT) + + self.centered_text(84, "Drop it? Still wrong.", size=48, color=WHITE) + + self.set_xy(30, 128) + self.set_font("Helvetica", "", 21) + self.set_text_color(*LIGHT_GRAY) + self.multi_cell( + WIDTH - 60, + 11.5, + "The covariate's untreated path carries information about the " + "outcome trend. Discard the covariate and that information leaves " + "with it.", + align="C", + ) + + self.set_xy(30, 188) + self.set_font("Helvetica", "B", 24) + self.set_text_color(*CREAM) + self.multi_cell( + WIDTH - 60, + 13, + "In the paper's simulations, dropping the covariate\nis inconsistent in every design.", + align="C", + ) + + self.add_footer(dark=True) + + def slide_05_paper(self): + self.add_page() + self.light_gradient_background() + self._draw_vertical_sidebar(5) + + self._kicker(36, "The Paper") + + self.centered_text(62, "Caetano, Callaway, Payne", size=36) + self.centered_text(84, "& Sant'Anna (2026):", size=36) + self.centered_text(106, "two ways out.", size=36, color=AMBER) + + y0 = 138 + for num, head, body in [ + ( + "1", + "Condition on the pre-treatment value", + "under simple covariate unconfoundedness, the target reduces to " + "Callaway-Sant'Anna with the covariate read at the base period - " + "existing tools apply", + ), + ( + "2", + "Model the covariate's untreated path", + "covariate unconfoundedness given its pre-treatment value, observed " + "confounders W and Z. W explains the covariate's path only - never " + "parallel trends - and a doubly-robust, ML-ready score does the rest", + ), + ]: + self.set_xy(34, y0) + self.set_font("Helvetica", "B", 26) + self.set_text_color(*AMBER) + self.cell(14, 12, num) + self.set_xy(52, y0) + self.set_font("Helvetica", "B", 22) + self.set_text_color(*NAVY) + self.cell(WIDTH - 86, 12, head) + self.set_xy(52, y0 + 14) + self.set_font("Helvetica", "", 16.5) + self.set_text_color(*GRAY) + self.multi_cell(WIDTH - 92, 8.8, body, align="L") + y0 += 50 + + self.set_xy(30, 246) + self.set_font("Helvetica", "I", 14) + self.set_text_color(*GRAY) + self.multi_cell( + WIDTH - 60, + 7.5, + "Difference-in-differences with 'bad controls' - arXiv:2608.03881, an " + "unpublished preprint (v2, September 2026).", + align="C", + ) + self.add_footer() + + def slide_06_route1(self): + self.add_page() + self.light_gradient_background() + self._draw_vertical_sidebar(6) + + self._kicker(34, "Route 1") + + self.centered_text(58, "Already in the box.", size=40) + self.centered_text(82, "Read it at the base period.", size=30, color=AMBER) + + self.set_xy(28, 104) + self.set_font("Helvetica", "", 17.5) + self.set_text_color(*NAVY) + self.multi_cell( + WIDTH - 56, + 9.5, + "On panel data, CallawaySantAnna reads every covariate at the cell's " + "base period, never at t. Put the bad control in covariates and you " + "have the paper's Approach 1 - no new code.", + align="C", + ) + + card_w, card_h = 108, 78 + gap = 14 + left_x = (WIDTH - 2 * card_w - gap) / 2 + y0 = 140 + self._stat_card( + left_x, + y0, + card_w, + card_h, + f"{CS_A1[0]:.4f}", + [ + (f"SE {CS_A1[1]:.4f}", True), + ('covariates=["x", "z"] - W left out', False), + ("misses the true 1.00 by two SE", False), + ], + STONE, + ) + self._stat_card( + left_x + card_w + gap, + y0, + card_w, + card_h, + f"{CS_A1_W[0]:.4f}", + [ + (f"SE {CS_A1_W[1]:.4f}", True), + ('covariates=["x", "z", "w"] - W in', False), + ("within one SE of the true 1.00", False), + ], + AMBER, + ) + + self.set_xy(28, 232) + self.set_font("Helvetica", "", 15.5) + self.set_text_color(*GRAY) + self.multi_cell( + WIDTH - 56, + 8.5, + "This design has an observed confounder W of the covariate's path. Leave " + "it out and Route 1 misses; put it in and Route 1 works - but which " + "conditioning set is right is an identification call, not a fit statistic. " + "Simulated example, truth known by construction.", + align="C", + ) + self.add_footer() + + def slide_07_route2(self): + self.add_page() + self.light_gradient_background() + self._draw_vertical_sidebar(7) + + self._kicker(34, "Route 2") + + self.centered_text(58, "The bad-control lane.", size=40) + self.centered_text(82, "What Route 2 buys you.", size=30, color=AMBER) + + chart_path, _pw, _ph = self._render_payoff_chart() + chart_w = 226 + self.image(chart_path, (WIDTH - chart_w) / 2, 100, chart_w) + + self.set_xy(28, 206) + self.set_font("Helvetica", "", 16.5) + self.set_text_color(*NAVY) + self.multi_cell( + WIDTH - 56, + 9, + "Both routes are valid. Route 1 puts W into parallel trends. Route 2 " + "uses W only to explain the covariate's untreated path - so the lagged " + "outcome can be W without becoming a parallel-trends variable (the " + "paper's Remark 2) - plus a doubly-robust, ML-ready score and the " + f"pre-test on the next slide. Here: {LANE_W[0]:.4f} (SE {LANE_W[1]:.4f}).", + align="C", + ) + self.set_xy(28, 252) + self.set_font("Helvetica", "I", 13) + self.set_text_color(*GRAY) + self.multi_cell( + WIDTH - 56, + 7, + "Seed-locked simulated example; whiskers are 1.96 analytical SE. On this " + "draw both routes land within one SE of the truth - Route 2 is a different " + "set of assumptions, not a bigger number.", + align="C", + ) + self.add_footer() + + def slide_08_pretest(self): + self.add_page() + self.light_gradient_background() + self._draw_vertical_sidebar(8) + + self._kicker(34, "The Pre-Test") + + self.centered_text(56, "Did treatment move the covariate?", size=34) + + self.set_xy(28, 80) + self.set_font("Helvetica", "", 16.5) + self.set_text_color(*NAVY) + self.multi_cell( + WIDTH - 56, + 9, + "Every cell also reports ATT_X(g,t): the effect of treatment on the " + "bad control itself, with its own analytical SE - " + "results.bad_control_summary().", + align="C", + ) + + table_w = 190 + self._draw_att_x_table((WIDTH - table_w) / 2, 108, table_w) + + y0 = 208 + for head, body, color in [ + ( + "Pre rows (t < g)", + "pre-test the path assumptions. They should be zero - and are, within SE.", + GRAY, + ), + ( + "Post rows (t >= g)", + f"check that treatment moves the covariate - near the true {TRUTH_X:.2f}.", + AMBER, + ), + ]: + self.set_xy(30, y0) + self.set_font("Helvetica", "B", 16.5) + self.set_text_color(*color) + self.cell(WIDTH - 60, 9, head) + self.set_xy(30, y0 + 9.5) + self.set_font("Helvetica", "", 16) + self.set_text_color(*NAVY) + self.multi_cell(WIDTH - 60, 8.5, body, align="L") + y0 += 22 + + self.set_xy(28, 254) + self.set_font("Helvetica", "I", 13.5) + self.set_text_color(*GRAY) + self.multi_cell( + WIDTH - 56, + 7, + "A nonzero pre row flags a possible assumption violation - it is not " + "evidence of a bad control. A zero post row does not prove treatment " + "left the covariate alone. Simulated; truth known by construction.", + align="C", + ) + self.add_footer() + + def slide_09_code(self): + self.add_page() + self.dark_gradient_background() + self._draw_vertical_sidebar(9, dark=True) + + self._kicker(34, "The Code", color=AMBER_BRIGHT) + + self.centered_text(58, "Name it. Name its confounders.", size=38, color=WHITE) + + W_ = WHITE + A_ = AMBER_CODE + S_ = SLATE_CODE + code = [ + [ + ("res = DMLDiD(control_group=", W_), + (f'"{CODE_CONTROL_GROUP}"', A_), + (", seed=", W_), + (str(CODE_SEED), A_), + (").fit(", W_), + ], + [ + (" df, outcome=", W_), + ('"y"', A_), + (", unit=", W_), + ('"unit"', A_), + (", time=", W_), + ('"time"', A_), + (",", W_), + ], + [(" first_treat=", W_), ('"first_treat"', A_), (",", W_)], + [ + (" covariates=[", W_), + (f'"{CODE_Z}"', A_), + ("],", W_), + (" # Z: clean covariates", S_), + ], + [ + (" bad_control=", W_), + (f'"{CODE_BAD_CONTROL}"', A_), + (",", W_), + (" # the one treatment moves", S_), + ], + [ + (" bad_control_covariates=[", W_), + (f'"{CODE_W}"', A_), + ("],", W_), + (" # W: confounders of its path", S_), + ], + [(")", W_)], + [("res.bad_control_summary()", W_), (" # ATT_X(g,t) per cell", S_)], + [("res.aggregate(", W_), ('"event_study"', A_), (")", W_)], + [("", W_)], + [("# Route 1 instead - read it at the base period:", S_)], + [ + ("CallawaySantAnna(control_group=", W_), + (f'"{CODE_CONTROL_GROUP}"', A_), + (").fit(", W_), + ], + [ + (" df, ..., covariates=[", W_), + (f'"{CODE_BAD_CONTROL}"', A_), + (", ", W_), + (f'"{CODE_Z}"', A_), + (", ", W_), + (f'"{CODE_W}"', A_), + ("])", W_), + ], + ] + block_w = 232 + self._add_code_block( + (WIDTH - block_w) / 2, 82, block_w, code, font_size=15, line_height=11.0 + ) + + self.set_xy(30, 258) + self.set_font("Helvetica", "", 15.5) + self.set_text_color(*LIGHT_GRAY) + self.multi_cell( + WIDTH - 60, + 8.5, + "Pass the bad control through bad_control=, never also through covariates= " + "(the fit rejects a column in both). seed= pins the folds.", + align="C", + ) + self.add_footer(dark=True) + + def slide_10_wild(self): + self.add_page() + self.light_gradient_background() + self._draw_vertical_sidebar(10) + + self._kicker(34, "In The Wild") + + self.centered_text(56, "Job displacement, NLSY79.", size=36) + + self.set_xy(28, 76) + self.set_font("Helvetica", "", 15.5) + self.set_text_color(*NAVY) + self.multi_cell( + WIDTH - 56, + 8.4, + f"The paper's application: {NLSY_N_DISPLACED:,} displaced workers, " + f"{NLSY_N_NOT:,} not. The bad control is the occupation score - displacement " + f"moves workers into occupations paying about {-NLSY_ATT_X[0] * 100:.1f}% less " + f"(ATT_X {NLSY_ATT_X[0]:.4f}, SE {NLSY_ATT_X[1]:.4f}). The authors' estimates, " + "not reproduced here:", + align="C", + ) + + card_w, card_h = 108, 74 + gap = 14 + left_x = (WIDTH - 2 * card_w - gap) / 2 + y0 = 120 + self._stat_card( + left_x, + y0, + card_w, + card_h, + f"{NLSY_TWFE_TEXT}", + [ + ("naive TWFE on log earnings", True), + ("with or without the", False), + ("occupation score", False), + ], + WRONG_GRAY, + headline_size=38, + ) + self._stat_card( + left_x + card_w + gap, + y0, + card_w, + card_h, + "about -7%", + [ + (f"ATT {NLSY_ATT[0]:.4f}, SE {NLSY_ATT[1]:.4f}", True), + ("the paper's bad-control", False), + ("estimator on log earnings", False), + ], + AMBER, + headline_size=38, + ) + + self.set_xy(28, 202) + self.set_font("Helvetica", "", 15.5) + self.set_text_color(*INK) + self.multi_cell( + WIDTH - 56, + 8.4, + "Naive TWFE reads roughly 40% larger in magnitude. The bad-control " + "estimator holds parallel trends conditional on the occupation a worker " + "would have had without displacement - the covariate's untreated path.", + align="C", + ) + + strip_y = 232 + self.set_fill_color(*INK) + self.rect(28, strip_y, WIDTH - 56, 46, "F") + self.set_xy(34, strip_y + 4) + self.set_font("Helvetica", "B", 14.5) + self.set_text_color(*AMBER_BRIGHT) + self.multi_cell( + WIDTH - 68, + 7.5, + f"Validated: numpy oracle of the paper's algorithm at {ORACLE_TOL}; " + f"tolerance goldens vs the authors' R {R_PACKAGE} package, run black-box.", + align="C", + ) + self.set_xy(34, strip_y + 23) + self.set_font("Helvetica", "", 13) + self.set_text_color(*LIGHT_GRAY) + self.multi_cell( + WIDTH - 68, + 7, + "Lane scope: panel data only; cluster= yes, survey_design= no; no anticipation; " + "varying base period. The headline ATT keeps the Callaway-Sant'Anna simple " + "weighting, not the paper's Remark 4 overall.", + align="C", + ) + self.add_footer() + + def slide_11_cta(self): + self.add_page() + self.light_gradient_background() + self._draw_vertical_sidebar(11) + + self.draw_split_logo(38, size=34) + + self.centered_text(80, "Your covariate moved.", size=38) + self.centered_text(106, "Your DiD can handle it now.", size=38, color=AMBER) + + chip_w = 150 + chip_x = (WIDTH - chip_w) / 2 + self.set_fill_color(*PANEL_INK) + self.rect(chip_x, 142, chip_w, 22, "F") + self.set_xy(chip_x, 148) + self.set_font("Courier", "B", 19) + self.set_text_color(*AMBER_CODE) + self.cell(chip_w, 10, "pip install diff-diff", align="C") + + self.set_xy(30, 184) + self.set_font("Helvetica", "", 17) + self.set_text_color(*NAVY) + self.multi_cell( + WIDTH - 60, + 9, + "Tutorial 33 reproduces every simulated number on this deck - both " + "routes, the pre-test table, the event study and a ridge refit:", + align="C", + ) + self.centered_text( + 218, + "diff-diff.readthedocs.io/en/latest/tutorials/33_bad_controls.html", + size=14, + color=STONE, + ) + + self.centered_text(242, "github.com/igerber/diff-diff", size=17) + + self.set_xy(0, 264) + self.set_font("Helvetica", "I", 13) + self.set_text_color(*GRAY) + self.cell( + WIDTH, + 6, + "Caetano, Callaway, Payne & Sant'Anna (2026), arXiv:2608.03881 (preprint).", + align="C", + ) + self.add_footer() + + +def main(): + pdf = BadControlsCarouselPDF() + try: + pdf.slide_01_cover() + pdf.slide_02_dilemma() + pdf.slide_03_receipt() + pdf.slide_04_twist() + pdf.slide_05_paper() + pdf.slide_06_route1() + pdf.slide_07_route2() + pdf.slide_08_pretest() + pdf.slide_09_code() + pdf.slide_10_wild() + pdf.slide_11_cta() + + output_path = Path(__file__).parent / "diff-diff-bad-controls-carousel.pdf" + pdf.output(str(output_path)) + print(f"PDF saved to: {output_path}") + finally: + pdf.cleanup() + + +if __name__ == "__main__": + main() diff --git a/tests/test_bad_controls_carousel_claims.py b/tests/test_bad_controls_carousel_claims.py new file mode 100644 index 000000000..c9c5b7acd --- /dev/null +++ b/tests/test_bad_controls_carousel_claims.py @@ -0,0 +1,532 @@ +"""Claim-sync guard for the bad-controls launch carousel. + +The deck (``carousel/generate_bad_controls_carousel.py``) hardcodes +committed, seed-locked numbers from the executed tutorial-33 notebook, the +paper's application numbers as transcribed in the paper review, and two +validation anchors from the REGISTRY / CHANGELOG as module constants. The +synchronization chain is: + +- library <-> notebook: tutorial 33 is numbers-locked and executed against + the committed library (``tests/test_t33_bad_controls_drift.py`` re-derives + the estimates and hash-pins the code cells); +- notebook <-> carousel: THIS file parses the deck's constants (via ``ast`` + - the generator imports ``fpdf2``, a carousel-only dependency deliberately + absent from CI) and locates each on the COMMITTED NOTEBOOK SURFACE, not + restated here. If the tutorial is ever retuned and the carousel is + forgotten, the notebook surface changes and this file fails; +- paper review <-> carousel: the NLSY79 application numbers on slide 10 are + the authors' estimates as the review transcribes them (never reproduced + by the library; the slide says so); +- CHANGELOG / REGISTRY <-> carousel: the cover's "New in 3.12" names the + release whose CHANGELOG section ships the lane; the validation strip's + oracle tolerance and the R package name come from the REGISTRY block. + +Skips cleanly when ``carousel/`` or ``docs/`` is absent (the +isolated-install CI jobs copy only ``tests/``). +""" + +from __future__ import annotations + +import ast +import json +import re +from pathlib import Path + +import pytest + +from tests._tutorial_drift import notebook_markdown, notebook_output_text + +ROOT = Path(__file__).resolve().parents[1] +GENERATOR = ROOT / "carousel" / "generate_bad_controls_carousel.py" +REGISTRY = ROOT / "docs" / "methodology" / "REGISTRY.md" +REVIEW = ROOT / "docs" / "methodology" / "papers" / "caetano-2026-review.md" +CHANGELOG = ROOT / "CHANGELOG.md" +NB = "docs/tutorials/33_bad_controls.ipynb" + +TOTAL_SLIDES = 11 + +# Constant values the code slide renders via f-strings / str() - resolved +# here so the snippet reconstruction stays a pure-AST operation. +DECK_LITERALS = { + "CODE_SEED": 0, + "CODE_BAD_CONTROL": "x", + "CODE_W": "w", + "CODE_Z": "z", + "CODE_CONTROL_GROUP": "not_yet_treated", +} + + +def _skip_unless(path: Path): + if not path.exists(): + pytest.skip(f"{path} not available in this CI environment.") + + +@pytest.fixture(scope="module") +def deck_constants(): + _skip_unless(GENERATOR) + tree = ast.parse(GENERATOR.read_text(encoding="utf-8")) + consts = {} + for node in tree.body: + if isinstance(node, ast.Assign) and len(node.targets) == 1: + target = node.targets[0] + if isinstance(target, ast.Name): + try: + consts[target.id] = ast.literal_eval(node.value) + except (ValueError, TypeError): + pass + elif isinstance(target, ast.Tuple) and all( + isinstance(el, ast.Name) for el in target.elts + ): + try: + values = ast.literal_eval(node.value) + except (ValueError, TypeError): + continue + if isinstance(values, tuple) and len(values) == len(target.elts): + for el, val in zip(target.elts, values): + consts[el.id] = val + return consts + + +@pytest.fixture(scope="module") +def visible_strings(): + """Slide copy: every string literal in the generator EXCEPT docstrings. + + f-strings contribute their constant fragments (``ast.Constant`` nodes + inside ``ast.JoinedStr``), so phrase pins must not span a ``{...}`` + substitution. + """ + _skip_unless(GENERATOR) + tree = ast.parse(GENERATOR.read_text(encoding="utf-8")) + docstring_nodes = set() + for node in ast.walk(tree): + if isinstance(node, (ast.Module, ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)): + body = node.body + if ( + body + and isinstance(body[0], ast.Expr) + and isinstance(body[0].value, ast.Constant) + and isinstance(body[0].value.value, str) + ): + docstring_nodes.add(id(body[0].value)) + return " ".join( + node.value + for node in ast.walk(tree) + if isinstance(node, ast.Constant) + and isinstance(node.value, str) + and id(node) not in docstring_nodes + ) + + +# Chart / table helpers attributed to the slide that places them. +_SLIDE_HELPERS = { + "slide_01_cover": ("_render_cover_motif",), + "slide_07_route2": ("_render_payoff_chart",), + "slide_08_pretest": ("_draw_att_x_table",), +} + + +def _per_slide(collect): + _skip_unless(GENERATOR) + tree = ast.parse(GENERATOR.read_text(encoding="utf-8")) + per_func = {} + for node in ast.walk(tree): + if isinstance(node, ast.FunctionDef): + per_func[node.name] = collect(node) + slides = {} + for name, value in per_func.items(): + if name.startswith("slide_"): + for helper in _SLIDE_HELPERS.get(name, ()): + value = value + per_func.get(helper, type(value)()) + slides[name] = value + assert ( + len(slides) == TOTAL_SLIDES + ), f"expected {TOTAL_SLIDES} slide_* methods, found {sorted(slides)}" + return slides + + +@pytest.fixture(scope="module") +def slide_strings(): + """Per-slide visible strings (a qualifier must live ON the slide that + makes the claim, not merely somewhere in the module).""" + + def collect(node): + return " ".join( + n.value + for n in ast.walk(node) + if isinstance(n, ast.Constant) and isinstance(n.value, str) + ) + + return _per_slide(collect) + + +@pytest.fixture(scope="module") +def slide_constant_refs(): + """Per-slide referenced module-level names (each pinned statistical + constant must actually be RENDERED by its intended slide - a hardcoded + literal bypassing the constant would otherwise pass).""" + + def collect(node): + return [n.id for n in ast.walk(node) if isinstance(n, ast.Name)] + + return _per_slide(collect) + + +@pytest.fixture(scope="module") +def nb_output(): + return notebook_output_text(NB) + + +@pytest.fixture(scope="module") +def nb_markdown(): + return notebook_markdown(NB) + + +@pytest.fixture(scope="module") +def review_text(): + _skip_unless(REVIEW) + return REVIEW.read_text(encoding="utf-8") + + +def _notebook_code(rel_path: str) -> str: + nb_path = ROOT / rel_path + if not nb_path.exists(): + pytest.skip(f"Notebook not found at {nb_path}.") + return "\n".join( + "".join(c["source"]) if isinstance(c["source"], list) else c["source"] + for c in json.loads(nb_path.read_text())["cells"] + if c["cell_type"] == "code" + ) + + +class TestEstimatesMatchNotebook: + """Every simulated estimate on the deck is on the committed tutorial-33 + surface (prose AND rendered outputs).""" + + @pytest.mark.parametrize("name", ["TWFE_INCLUDE", "CS_A1", "CS_A1_W", "LANE_W"]) + def test_headline_estimates(self, deck_constants, nb_markdown, nb_output, name): + att, se = deck_constants[name] + # The tutorial quotes each as "**att ± se**" in prose ... + assert f"**{att:.4f} ± {se:.4f}**" in nb_markdown, f"{name} not quoted in tutorial prose" + # ... and renders both in the running results table. + assert f"{att:.4f}" in nb_output and f"{se:.4f}" in nb_output + + def test_att_x_rows(self, deck_constants, nb_output, nb_markdown): + rows = deck_constants["ATT_X_ROWS"] + assert len(rows) == 6 + for g, t, att_x, se_x in rows: + # bad_control_summary() prints one row per (g, t) with both columns + # columns: group, time, post, att_x, se_x, ... + pattern = ( + rf"\b{g}\s+{t}\s+(?:True|False)\s+" + rf"{re.escape(f'{att_x:.4f}')}\s+{re.escape(f'{se_x:.4f}')}" + ) + assert re.search(pattern, nb_output), f"ATT_X row ({g},{t}) not in the summary output" + pre = [r for r in rows if r[1] < r[0]] + post = [r for r in rows if r[1] >= r[0]] + assert len(pre) == 3 and len(post) == 3 + for _g, _t, att_x, _se in pre + post: + assert f"**{att_x:.4f}**" in nb_markdown, f"{att_x:.4f} not quoted in tutorial prose" + + def test_truth_values(self, deck_constants, nb_markdown): + assert deck_constants["TRUTH"] == 1.0 and deck_constants["TRUTH_X"] == 0.5 + assert r"\mathbf{1.00}" in nb_markdown and r"\mathbf{0.50}" in nb_markdown + + def test_dgp_shape_values(self, deck_constants, nb_markdown): + c = deck_constants + code = _notebook_code(NB) + assert f"n, T = {c['N_UNITS']}, {c['N_PERIODS']}" in code + assert f"**{c['N_NEVER']}**" in nb_markdown + for g, size in c["COHORT_SIZES"]: + assert f"**{size}** ($g = {g}$)" in nb_markdown + + def test_paper_s2_bias_is_in_tutorial_and_review( + self, deck_constants, nb_markdown, review_text + ): + bias = deck_constants["PAPER_S2_BIAS"] + assert f"Table S2 bias of ${bias:.3f}$" in nb_markdown + # The review's Table S2 row: TWFE Include BC at n = 2000 + assert re.search( + rf"\| TWFE Include BC \| 2000 \| {re.escape(f'{bias:.3f}')} \|", review_text + ) + + +class TestApplicationNumbersMatchReview: + """Slide 10 shows the AUTHORS' NLSY79 estimates as the review records them.""" + + def test_att_x_and_att(self, deck_constants, review_text): + ax, sx = deck_constants["NLSY_ATT_X"] + a, s = deck_constants["NLSY_ATT"] + assert f"`ATT_X = {ax:.4f} (SE {sx:.4f})`" in review_text + assert f"`ATT = {a:.4f} (SE {s:.4f})`" in review_text + + def test_sample_sizes(self, deck_constants, review_text): + assert f"displaced `N = {deck_constants['NLSY_N_DISPLACED']}`" in review_text + assert f"non-displaced `N = {deck_constants['NLSY_N_NOT']:,}`" in review_text + + def test_percent_readings_are_the_papers(self, deck_constants, review_text, slide_strings): + ax = deck_constants["NLSY_ATT_X"][0] + assert f"{ax * 100:+.1f}%" == "-2.6%" + assert "2.6% lower wages" in review_text + assert "about 7%" in review_text + assert deck_constants["NLSY_TWFE_TEXT"] == "almost -10%" + assert '"almost 10%"' in review_text # the paper's words for the naive arms + assert "roughly 40% larger in magnitude" in review_text + assert "roughly 40% larger in magnitude" in slide_strings["slide_10_wild"] + + +class TestAnchors: + def test_feature_release_is_the_changelog_section_that_shipped_the_lane(self, deck_constants): + _skip_unless(CHANGELOG) + text = CHANGELOG.read_text(encoding="utf-8") + release = deck_constants["FEATURE_RELEASE"] + m = re.search( + rf"^## \[{re.escape(release)}\.\d+\].*?(?=^## \[)", text, re.MULTILINE | re.DOTALL + ) + assert m is not None, f"no CHANGELOG section for {release}.x" + assert "bad-control lane" in m.group(0) + + def test_release_label_appears_only_as_the_pinned_constant( + self, visible_strings, deck_constants + ): + # The footer derives from pyproject; the cover's "New in" renders + # FEATURE_RELEASE. No other copy may carry a release number. + hits = re.findall(r"\b3\.1\d(?:\.\d+)?\b", visible_strings) + assert hits == [deck_constants["FEATURE_RELEASE"]], hits + + def test_validation_anchors_match_registry(self, deck_constants): + _skip_unless(REGISTRY) + text = REGISTRY.read_text(encoding="utf-8") + start = text.find("**Bad-control extension (CCPS 2026): `fit(") + assert start > 0, "REGISTRY lost the DMLDiD bad-control block" + block = text[start : start + 30000] + assert f"rtol={deck_constants['ORACLE_TOL']}" in block + assert ( + f"`{deck_constants['R_PACKAGE']}` is used ONLY as an executed black-box oracle" in block + ) + assert 'CS "simple" post-treatment average' in block and "Remark 4 overall" in block + + +class TestArithmeticBehindTheCopy: + def test_half_the_effect(self, deck_constants): + c = deck_constants + gap = c["TRUTH"] - c["TWFE_INCLUDE"][0] + assert abs(gap - c["TRUTH_X"]) < 0.02, "'half the effect' no longer describes the gap" + + def test_route1_se_distances(self, deck_constants): + c = deck_constants + att, se = c["CS_A1"] + assert 2.0 <= (att - c["TRUTH"]) / se < 3.0, "'two SE above' is stale" + att, se = c["CS_A1_W"] + assert abs(att - c["TRUTH"]) < se, "'within one SE' is stale (Approach 1 + W)" + att, se = c["LANE_W"] + assert abs(att - c["TRUTH"]) < se, "'within one SE' is stale (lane)" + + def test_pre_rows_near_zero_post_rows_near_truth(self, deck_constants): + c = deck_constants + for g, t, att_x, se_x in c["ATT_X_ROWS"]: + target = 0.0 if t < g else c["TRUTH_X"] + assert abs(att_x - target) < 2 * se_x, f"ATT_X({g},{t}) is no longer 'near' {target}" + + +class TestClaimDiscipline: + def test_qualifiers_are_slide_local(self, slide_strings): + expectations = { + # the cover motif is stylized art, labeled on-slide + "slide_01_cover": ("illustrative",), + # the receipt states simulation + known truth WITH the numbers + "slide_03_receipt": ("truth known by construction", "simulated", "reported SE "), + # the paper slide states preprint status and the author disambiguation + "slide_05_paper": ("unpublished preprint",), + # Route 1: which conditioning set is right is an identification call + "slide_06_route1": ("identification call", "known by construction"), + # Route 2: simulation + no "bigger number" overclaim + "slide_07_route2": ( + "Seed-locked simulated example", + "known\nby construction", + "Both routes are valid", + ), + # the pre-test slide carries BOTH Remark 6 caveats + "slide_08_pretest": ("not evidence of a bad control", "does not prove"), + # the code slide states the exclusivity rule + "slide_09_code": ("never also through covariates=",), + # the application numbers are the authors', the oracle is black-box, + # the lane scope and the aggregation weighting are stated + "slide_10_wild": ( + "The authors' estimates, not reproduced here", + "black-box", + "simple weighting", + "panel data only", + ), + } + for slide, phrases in expectations.items(): + for phrase in phrases: + assert phrase in slide_strings[slide], ( + f"qualifier {phrase!r} is not on {slide} - it must ride " + "with the claim it scopes" + ) + + def test_paper_is_introduced_before_it_is_referenced(self, slide_strings): + assert "Caetano, Callaway, Payne & Sant'Anna (2026)" in slide_strings["slide_02_dilemma"] + for later in ("slide_03_receipt", "slide_04_twist"): + assert "the paper's" in slide_strings[later] + + def test_statistical_constants_reach_their_slides(self, slide_constant_refs): + expectations = { + "slide_01_cover": ("FEATURE_RELEASE",), + "slide_03_receipt": ( + "TWFE_INCLUDE", + "TRUTH", + "TRUTH_X", + "N_UNITS", + "N_PERIODS", + "N_NEVER", + "COHORT_SIZES", + "PAPER_S2_BIAS", + ), + "slide_06_route1": ("CS_A1", "CS_A1_W"), + "slide_07_route2": ("TWFE_INCLUDE", "CS_A1_W", "LANE_W", "TRUTH"), + "slide_08_pretest": ("ATT_X_ROWS", "TRUTH_X"), + "slide_09_code": ( + "CODE_SEED", + "CODE_BAD_CONTROL", + "CODE_W", + "CODE_Z", + "CODE_CONTROL_GROUP", + ), + "slide_10_wild": ( + "NLSY_ATT_X", + "NLSY_ATT", + "NLSY_N_DISPLACED", + "NLSY_N_NOT", + "NLSY_TWFE_TEXT", + "ORACLE_TOL", + "R_PACKAGE", + ), + } + for slide, names in expectations.items(): + for name in names: + assert name in slide_constant_refs[slide], ( + f"constant {name} is not rendered by {slide} - a " + "hardcoded literal may have replaced the synced value" + ) + + def test_no_absolutes_or_competitor_claims(self, visible_strings): + lowered = visible_strings.lower() + for banned in ( + "the only ", + "first and only", + "no other estimator", + "nothing else", + "better than", + "state of the art", + "state-of-the-art", + "game changer", + "revolutionary", + "econml", + "csdid", + "ptetools", + "unbiased", # the deck shows recovery, never claims unbiasedness + "valid coverage", + "guarantees", + "detects bad control", # ATT_X is not a bad-control detector + "detect a bad control", + "pedro", # author disambiguation: Hugo Sant'Anna + "reproduced the paper", + ): + assert banned not in lowered, f"banned absolute/competitive claim: {banned!r}" + + def test_no_double_quoted_pull_quote_on_paper_slide(self, slide_strings): + # Preprint, arXiv-v2 pinned: the paper slide carries an attributed + # paraphrase, never a double-quoted pull quote (the title's own + # single-quoted 'bad controls' is the paper's typography). + paper = slide_strings["slide_05_paper"] + for ch in ('"', "“", "”"): + assert ch not in paper, "the paper slide must not carry a quoted pull quote" + + def test_r_package_named_once_as_oracle(self, visible_strings, deck_constants): + # The authors' GPL-3 package is a black-box parity oracle, named once. + # (the constant's own literal is the single occurrence; the slide + # renders it through the constant - see slide_constant_refs) + assert visible_strings.count(deck_constants["R_PACKAGE"]) == 1 + assert visible_strings.count("authors' R ") == 1 + + def test_cs_and_dml_are_real_exported_estimators(self): + init = ROOT / "diff_diff" / "__init__.py" + _skip_unless(init) + text = init.read_text(encoding="utf-8") + assert "CallawaySantAnna" in text and "DMLDiD" in text + + def test_bad_control_summary_is_a_real_method(self): + results = ROOT / "diff_diff" / "dml_did_results.py" + if not results.exists(): + results = next((ROOT / "diff_diff").glob("*dml*results*.py"), None) or results + _skip_unless(results) + assert "def bad_control_summary" in results.read_text(encoding="utf-8") + + def test_code_slide_fragments_match_notebook_invocation(self, deck_constants): + code = _notebook_code(NB) + c = deck_constants + for fragment in ( + f'control_group="{c["CODE_CONTROL_GROUP"]}"', + f"seed={c['CODE_SEED']}", + f'covariates=["{c["CODE_Z"]}"]', + f'bad_control="{c["CODE_BAD_CONTROL"]}"', + f'bad_control_covariates=["{c["CODE_W"]}"]', + "bad_control_summary()", + 'aggregate("event_study")', + f'covariates=["{c["CODE_BAD_CONTROL"]}", "{c["CODE_Z"]}", "{c["CODE_W"]}"]', + ): + assert fragment in code, f"tutorial 33 lost the displayed invocation: {fragment!r}" + + def test_code_slide_snippet_is_valid_python(self): + _skip_unless(GENERATOR) + tree = ast.parse(GENERATOR.read_text(encoding="utf-8")) + code_list = None + for node in ast.walk(tree): + if isinstance(node, ast.FunctionDef) and node.name == "slide_09_code": + for stmt in ast.walk(node): + if ( + isinstance(stmt, ast.Assign) + and isinstance(stmt.targets[0], ast.Name) + and stmt.targets[0].id == "code" + ): + code_list = stmt.value + assert code_list is not None, "slide_09_code lost its `code` token-line list" + + def _frag(nodeval): + if isinstance(nodeval, ast.Constant): + return str(nodeval.value) + if isinstance(nodeval, ast.JoinedStr): + out = [] + for v in nodeval.values: + if isinstance(v, ast.Constant): + out.append(str(v.value)) + elif isinstance(v, ast.FormattedValue) and isinstance(v.value, ast.Name): + out.append(str(DECK_LITERALS[v.value.id])) + return "".join(out) + if isinstance(nodeval, ast.Call): # str(CONST) + arg = nodeval.args[0] + if isinstance(arg, ast.Name): + return str(DECK_LITERALS[arg.id]) + raise AssertionError(f"unrecognized token node: {ast.dump(nodeval)[:80]}") + + lines = [] + for line in code_list.elts: + assert isinstance(line, ast.List) + lines.append("".join(_frag(tok.elts[0]) for tok in line.elts)) + snippet = "\n".join(lines) + ast.parse(snippet) # must be syntactically valid Python + assert 'bad_control="x"' in snippet and 'bad_control_covariates=["w"]' in snippet + assert 'unit="unit"' in snippet and 'first_treat="first_treat"' in snippet + + def test_tutorial_referenced_once_on_cta(self, visible_strings, slide_strings): + assert visible_strings.count("Tutorial 33") == 1 + assert "Tutorial 33" in slide_strings["slide_11_cta"] + assert "tutorials/33_bad_controls.html" in visible_strings + assert (ROOT / NB).exists(), "CTA points to a tutorial that does not exist" + + def test_module_docstring_records_the_discipline(self): + _skip_unless(GENERATOR) + doc = ast.get_docstring(ast.parse(GENERATOR.read_text(encoding="utf-8"))) or "" + for phrase in ("Hugo", "AUTHORS' estimates", "no number", "illustrative"): + assert phrase.lower() in doc.lower(), f"docstring lost the {phrase!r} discipline note"