From 2d81b981b1f8f0bfeac59bc4111094232339ccdf Mon Sep 17 00:00:00 2001 From: Jacobie Jackson Date: Sat, 19 Sep 2026 20:07:29 -0500 Subject: [PATCH] Add SoundSpace music player for issue #958 --- MusicPlayer/cobie1818/README.md | 64 +++++++++ MusicPlayer/cobie1818/index.html | 59 ++++++++ MusicPlayer/cobie1818/screenshot.png | Bin 0 -> 58417 bytes MusicPlayer/cobie1818/script.js | 194 ++++++++++++++++++++++++++ MusicPlayer/cobie1818/style.css | 199 +++++++++++++++++++++++++++ 5 files changed, 516 insertions(+) create mode 100644 MusicPlayer/cobie1818/README.md create mode 100644 MusicPlayer/cobie1818/index.html create mode 100644 MusicPlayer/cobie1818/screenshot.png create mode 100644 MusicPlayer/cobie1818/script.js create mode 100644 MusicPlayer/cobie1818/style.css diff --git a/MusicPlayer/cobie1818/README.md b/MusicPlayer/cobie1818/README.md new file mode 100644 index 000000000..60a433aa6 --- /dev/null +++ b/MusicPlayer/cobie1818/README.md @@ -0,0 +1,64 @@ +# SoundSpace Music Player + +A responsive music player built for JavaScript Mini Projects. +Contribution related to issue #958. + +## Technologies + +- HTML5 audio +- CSS with a responsive layout +- Vanilla JavaScript +- No external libraries, API keys, or build tools required + +## Run locally + +Open index.html in a modern browser, or serve this folder using +the VS Code Live Server extension. + +## How to use + +1. Select Add audio files and choose audio files from your device. +2. Use Ctrl or Shift in the file picker to select multiple files. +3. Click Play to begin playback. +4. Use Previous, Next, or a playlist button to select a track. +5. Adjust the track position and volume using the sliders. + +Adding a new selection replaces the playlist. +Files are processed locally and are not uploaded. +The playlist is cleared when the page reloads. + +## Features + +- Play and pause +- Previous and next track navigation with wraparound +- Automatic advancement until the end of the playlist +- Clickable playlist with the selected track highlighted +- Track seeking and elapsed time display +- Volume control +- Responsive layout +- Keyboard-operable buttons and labeled controls +- Visible keyboard focus and playback status messages +- Error feedback for files the browser cannot play + +## Manual testing checklist + +- Add one file and test play, pause, seeking, and volume. +- Add multiple files and test previous, next, and track selection. +- Confirm navigation wraps around at the playlist boundaries. +- Confirm playback advances when a track ends. +- Confirm playback stops after the final track. +- Replace the playlist while music is playing. +- Try an unsupported or damaged audio file. +- Test keyboard navigation using Tab, Enter, Space, and arrow keys. +- Check the layout at phone, tablet, and desktop widths. +- Check the browser console for unexpected errors. + +## Limitations + +Supported audio formats depend on the browser. +Audio files are supplied by the user; no songs are bundled. +No automated test suite is included in this contribution. + +## Screenshot + +![SoundSpace music player with a loaded playlist](screenshot.png) \ No newline at end of file diff --git a/MusicPlayer/cobie1818/index.html b/MusicPlayer/cobie1818/index.html new file mode 100644 index 000000000..8ae7dee2d --- /dev/null +++ b/MusicPlayer/cobie1818/index.html @@ -0,0 +1,59 @@ + + + + + + SoundSpace Music Player + + + + +
+
+

YOUR MUSIC. YOUR SPACE.

+

SoundSpace

+

A simple player for your favorite tracks.

+
+ +
+ +

No track selected

+

Choose audio files to get started.

+ + + +

Files stay on your device. Adding files replaces the playlist.

+ + + +
+ + +
+ 0:00 + 0:00 +
+
+ +
+ + + +
+ +
+ + +
+
+ +
+

Your playlist

+

Your added tracks will appear here.

+
    +
    +
    + + \ No newline at end of file diff --git a/MusicPlayer/cobie1818/screenshot.png b/MusicPlayer/cobie1818/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..85a37a3efd2585d26b64a49f6482c4bf94ee7da6 GIT binary patch literal 58417 zcmdSBcUV(tw>}(Y6h~18l_J%FQKXAhfe;&@qk@VMYEY0GT109f!A=e1sPv+uAT`oM z4Jss3LlGi1kO&ANKnNi~NcipGyyv{<_nqrp=lk#b_H`-AX7Bwx&nox2*Lv0__L`-| z{=L$BK_JlnOBXNP0D**^K_H>nJ-dN3w)>6013z{I-LN(G6_eV+IMhcEg)>Fp0cT6vtB|3N; zo%a>@R*}*zld^8{`bAOWRz|e8w$E=36v!$JiESj+8W^0u^yN}EiKujXh+AB>>Odb2 zqeU^t>va&zm6O0652Q}s-fG!Bu{1b)Z#W+WiZ+$)H{AgO&DT#(PR>b!WEUbSJ3-Mx zmwy0q;I@et?=U>Lh5{tOJ5;w5)NH!+&>Mug(?r?9;B*7d@6bGT|C z(251HvgYfaCs9X7`5(Cxe2{!JZ-6gPkKAjPLFao&(k)7Go zJekV_)0VhRh%gi$Sir-d51}n>>{y!QKD-Os-8;#Nnp)au+6Pz-)RX$%o4-p0)GW5R zwDxgv^5oOL+q&Y>N|yOi)Yz34tGxbj>I|R^;fy~8BZXP{PDK2rnzVeIGb0HSw&J3L zIBfEc;GW&`70RpJlfaaux2NP~H7Xh*+9Qe^fy6-0eBK!-1>Xwb@8DASLi#!a^BKtI9m2$qAb$4UImmeCz%A1PXe#9!scg^2v#AB2|0}M zBlW12B~z5B$-Ud}C&WR~N-qIzM=SL;@jleLxYZ9@=d7-z8qR)CJ&Cxnd5_b*)|M1X z&_Xfe!#2xuh_oa~NX(2#^Rrj|vn^#rc}b!?=j{*KpeqT;;YVTZxL?ayPe)vdt52!Q z^`X`E2@^e!Uq29t>%z7yEYrUd1t+^1ccm1y**=t0| zx{5aQ2>viIZ?DY>mnO-ig(GxM_Ctl3y?~J!9u%0GAyroMK7DB^@Cs_W!gchKXUl@K zG1U_?Hs-$*Bs}muXQMJ~u0LD8KGgK!2s&^}N{CceIZOIB4fxE%^8!;6o0)-oFeW#2p?ri>DkNMUGLqzkvOjfiUhXWF+6T5S_=l=(>(h5+%(h=l@(d>86 zRzM>A?yG^GK9&>Raul&>dFz>NG#%i{?fDH@Y{d3rrG#tRgGJm#Q^ZU2EtA}mkT>SX zt8&M7g0fFS#@9a^uC5)TrsZc}k0K4%YwHbb33IsmfOZ`OH-9VA-n@qMT~26ICTbJq zlmmB7e5mAFKoV#eW7BNy*|gSJ?Z|i;Hzg3ruy9)>in0wpY1#>n`llz`XjE^joWqca zJC60cK(hKFCd-T3DC&1Zew&qsWx}N6n3N2o;vt7813-($Yrww}ytE*D{KwLnDQI@( zTH8Wa_&$)KI`0mk{wbH!C8oU_*@Gi6;PU3{0*q;HHa4_5g*;NhUbW8A{~ZHfzneI-vN4B zA_p0jAg#T#uEUoFN97pf4s@eU0AzleEP$c9gyqka(wZkq0%MPTPVEIl{P4d5cUhoU z`@=SLjuQj#)!{z|N8vjXHvlM-eJOAekxC&KIi2<}=YajhzzYdEVSjtp?mYPyYMJH? z2;$OI4Nh4z47@}E5OJdCpa2n3Dm%$BG5HA@zd?9qJ>t$d5{{*Q1 zn}R?uy9e)Mq zv*P<|0S$w^VZvW?E2#hlt|0{;h#=~nC$Dm9W1d;=1c71&&n0X=|32;a__-SfJg6bI zL+aw^&z}*UWyET$P>M&`O*cPb5XeGPpl6}kzaC|ljO=!a#7#%Bg8p@-xbg=#RZz?$Dv@48asHZo{$fqa4{9%cP#Y zAk1E8ig3Ni+cy69I4-=D5tWHIcXxWmzSdy5hFUQH9$;vil?PLV)=RhQ0Ml zL{uS8VW())X702Y1pvP{YnktAi4BK4hR%Du?HCIC}D#|)7IM=t<)mbw3zrB z2z;{p1>^OU2S6a>HG`nQFljEQqO9f@P;~B70gUE$j-zgx^l?8c0RhM24X|i=bEBMj zMiemra=|lSCFShn^ooNH$V5d!=tVlfBaa9kc~Sz5el^Pa10?cZo8FP2$cmysAehog_#_z(n^V?Xj0D`GRuix?b*0Srty&r{*9u30kLK^ zSu!J#O^h9Ph}s!%T6PMy@x_An8NXFk-gViPKOEW;Pn5JUZhD57)SmjRkO(zd!Pr$5 zn=qenS{Aj!PMB^ETG=kTY<@!6aAOvUSGADnP3w^3&`L^nl?rz23#C=KT-&04`bQAz zQl|^@?B>X3Lzt$_w5-nG&SvkhP3MaYSX zX|LR0<2?^(pXManRjz(tTiz6H6`JBM=HwVzT$smTJ#(O1N-o%1t==kw*@#}2j!$HA zy?!g(8^hoz5_GMkx(f11G4)M+j+j_)8wz_bA`@Q2K-KF~Wsn22^Jo`9+B)&!D0 zn3G_m(4^dLx0Fm>+P@f^LZAfiDt+$nD60@=&!np3jt{8D?MO z3Z)Ew!zAFnN!aIFg!w#1u0%gKZF#a4LExA=z*xD=Mjg!<$toEe*g+P#N%c)Sjbhfh z)qH{xx~hUs@Y2MT-7KMG&R&gCt{w^`?#OrH$rAYyvhXY+CC4 z7;mXjp%rt;s?;8(vWJL-(Shp7qFlNZh#uPD{1Xdl<^2m zKH|N|0hfbXhHl76xXb58_r)a9NP6d7I@cjhhFKMMOJQ~LKE>q-#h50CIIAl(C*)4u zN4dU8S*&@$tR|rVTZbs|-FzrEHr!&|(Z{mf+-O0tj6(Ee&vMiu5XfgcE|{Z9L1QkBrD<7owtm9gb7slnB4%-{I^|^L zQ(^gG`9oIS=el&V<(U^NPU($>tZoDVCPjIFzUf)isV4T9S>}V+L9_%5{m?3f4n4Oa zZjs{{YN{o)<;^PNu7%D@a#ZmJou z#$z%HLgm&hf~B_RpHe>$F%mLf2ceLYt%;78@Dm9L_hv38jJbwD5IW5F6#*iXmY!Pu zG{l14#_KiZus5a$>7yUnEs+#qP&7{oK+1^|Wi<+;3ydhkFQ!OjU*83u8eqq|Su+4vq!B zb%E^4*lJMj{_?3_Ok+gW(Jj<>3&u@sbg95O-v!UaTQx+jobDox;8k52)MB0hNJZz} zrr?a6afh43(?RRaj;y2W&zVyJR|@^tk<23;-RvDBw#9zm*WWtIL2K5dhLX(Xw88eV2t%v&(TBVnnHV-8p$RN(I)Q5d4O=PS_x1e6|oD{d>gyf z6a0ujFgrP}5#dzRd)JU!JcO6$P=Z3oe*x_#Y~!K+X4HjzQ*xVV;q$SXIGw5Wg__Gs zP1?t^IOqGT7??N~PH>eG2q21N%UiZFV%3NnIT-Hq3 z2QvX5ziRklQPURtMb>3*(*m7}yncl}YN zMb1T+U(d8@&)!?bYXRa?RR#19I#6jXK_E6Q&DvG1JV@1Hy!8NRE#lL!+PC|@rUs9{ zv0EM5lFLCYUQS=sIX(kxIyH!1jawUIb;qfcH0vo+9~~kPU+9o9`%+N4gQ!U>*GZKU zKuw^)Xn}cw4!nO{Hm8%)+L2eO)ch>-aK(6?iGSpx&Pc$?xYN)mRnujHC-Kp$jFRE) z_J%cV&f0U_2cF=5S&%>#(L!F`%a64^i!a@pdK9)GQyN!OW2N(e5*vz-@PWG1VOP^7 z7ajPYRsrS+`jH_}&qQ?iZT0lB?uO~gXR}tsN9_yZkc(S^~vtutOYHP8=^Oo zbrK9ic(V>G;Z~-Yqvq5)W%+OStRsK)g|?`9By%^PbWoEZL7u)N&uijSPX*oX^v(v1 zCb}v3f3I!YkE)ZlV<>yu*}8wJaHw$U@3nX>r$aMV1ti~kUR>Cav48jQ*Sv;}zojDR z0WFy`ncu?9=d-g!TWj$AcXsT2a_g|LjPsu<#Nn%wE#3pnK^$T_!|i?VamCV&o4&A< zRi@+No{>wVp@hPFk-ZkKyuON}k@bbqz^k3LYlEp<5FE6=@gS?1k8@5xhc; zb7*kGOoii(MNMm1l($oO+b(TShdIfzAZ};}YM*0}Kf?`KDjKN*W2SS6LhQ8m7ndOt za4l1{qBx#^ab~SyvJJ6>SG$;J81!+@4!7CJtk=qtw?6(h8|gX|MTwEYI?8wOSA}gB ztDl+X$AHT`XOx%>Y;l}g3P0Gld)(WYwLgW(9p8W>rd5>9g4bidRj?+*CX8JYU!o&| zi}{x0xwD-Hkw;6Nmf_4%74|qG+nL!Mx{#1zinzKtbb>YWrRx2mgxm@e#wcn0@(<~H>Il3v$(>w+VS^ve^j5CU+&89GAIg^0%Fykb zH+O)x)Cz3A{MPqin`+7tg-E)wn+@5?<>2`ooT3EDq=0AMQM$J3SsJqs>rc9^&f~N+ zy5Nk)n^vZ?f7i26-cH9zjK>1UO2uPFs`VE=k)K|;#8Vn0Y*lj)XJXMt$6I+ojvIXG);0i7EKEyzaBww^sua4&ux&Wd4?~VJEE+fnd$QxQvz7 z3rvhj9o^%Ew5xb0E`>>&(Zs3S@)(eo4XsFZ(~$MW7B$!=@NDgjyQ?Se!(Y(rRBfHV zN^jL{nItD36Wn|+q+!MiogZAjS!}WY%5x@j)Bq-4q}fhNtlIh&F$~vCN^%bNYO(|z z79;V~$A7qyqpCu8O+I=~tsKIO;gPL+OmYVQ_d!beDPYV`sX>3%-}Y-qrVx=HNu=)i zSU(y6gxAL;328c{STYRdR*XI>8crkzQEm&Rtuu*I%8=xA)j?YZv z*Zb{O(%&Jhm8QU_yYX+G&B6l#EV81BFXA-)H!UxitR>n757{6b)e!O!Z&=ia@0(#~ zL+Dd6PpQ)#FaU6wRo`UAL?fg8oYn_xTHCuCcMgn-Qc2@T=h5mYErz9(%P(V4Y+P3j zTGjOHo@fhZa|(5A-?&0i6aQh%+Sy|KBu^VXo05Ke<530e6KC+LLcNc7Q@$Pj+V}7V9>&XdUkFWy(&%{-RVw%p~L1pRB+bt9TxYM!(aZCV9sK zSpSNkED8$z&17kaLwr2Ldm6@=Dx&7?cXXS9Et3!BIsb+ZiISssrA6J%UDlT0L~Yum zGPxO8LR8{+=64`AFVi00h5{N}t@S^2e4u6(>=%jRj>ZVf``RQOH!wLoGBOjf;h>Hr zX1H}1QN$EBJE63Zk!7*itVI^%i|yNnm#Cht-%S$7S%IU*PZ~=aCWpE_CoBz($7^OW-$wcDeEcA8*WJu} zcWDxBz{=(!0^DpqTe%)k8qaasoKDr@W`?!?y)02Fx^h5Rxij0v=6&{QzIP%g#Gle< zI9@~>Q9ke?3$h@Wig7)c+o|VDDh<%Jx>?<_s{In1EWc@9T(==g{ltPD(Mqj7F&<(g zb}xXgNBGs6HhOHPhUBr@k}FzGN*q|hE%iZSt{I`6??&0T00eo5H-ShQ*jD4QJ>A-5aztne`)?ZT`=PpT#x3?yw)Lb7wWUR2} zUyPq3to5)%6B+tno_=L2L4o}u&$1}YqsF9J&8o7GP(Ut8EZS_mM+so80 zh}54+so63_yJ^*wgS9aM&>N=1My4XZBLfMk%2~_91cYD26={|Ik?b6zU*gDgX@Z)S zw?QFzsfJ9*FhxRjM&;Snb;>Pk*8?D<9s6kKQ}8MtHl&HML!zVQCNN_bq$QKAjxkH& zc}Myp=|V&67bA^%>&EqOn176-)UJh&A5jo+w_37GfaxzJzQ9F|elp9yv>@Lir)Rzg zQ6v;1ylFT4FKZ>t==W7Qmqi6J^M&=nUyBn=rtFyun}(bb5=JG_^8pH?k6Ci+i(zWd z4lshmSXMr!0qk4f8Y<-e$QdwpYWVT}{c=Y&p674UbMab^91H944Vf7e6Xv0wzFu6u zTvN^Y zan#Vxo6NVgjModl5^K)UJPB`Dc}eAYGH$G>b>>>wN4VxJzt}1~U=%m0;L4Mk(H`&Kq3cpw>|X!GCPTIH6#80t(G-IMuQpC1?y-tc97Gd zmP|xSWDXQtCdPm>nxqwwC*^qVo2?pM?L)s-XvJE&Y>neSh+HLYGB|`nE%l^*%lG_A zgLcR+7Z2qo=@A+Czr;vU>}9*v5wks!(*bw`+bHVasXBKR!zMPn3hgL+gstLIoSExu z@yE1cb(CD&<0T1C2c5(vE#VZk+F3Vp@Y6iyE2q^o8+^lyH%9J_OxiG+Y7(vM{lnr7 z0OAMOjTn(nP0ojrluZvp`Kv2{$#kv*lgUr1*}2T1#0;plLuvx1B0t$P^Q@etSyr(z zGo49l*sZXJeDO_!z%~Xxic;J4LiJTMtWs+~tQF@R8j!V(az&YN9vyQ1^um*v$V zI3dj%xUFJhlo$w?yQuH~+GKr{LrB4{XBisMw`NBcV*$bCbTzdUxRH=Ov`M2_FAeC`B9Pht&mNuU`m6K$H^&XcF#fAWWYQo7XQX8cnY9yh8#r)x>Uinthk6V6H+itxdpUF;^4yId;dieXW$_mG z0cm=ipav2xH2ZO&><2Z8;MXObgz+H>g%aA|F$6g+T)Xm?ck$@bwcNO}e6VP%AGx7I z4dAwR_oK>-$3 zY74widd$_vCkc+U>FdNXaSFdvyd(-H1BKyh^v1*u{K5>45dfV0f$w68x(>8LTiUON zXFT&8S(yzB6~~z~tM0bxAy}zR3#%->)*`LW|}5VSqqS>icT}yDDb_k+&x%yeP0R z_^2VPOZ%&rkcEDY)b0M4UI&tr&CfPfS{M$z9R4-- z$4zu0u%A&!3a)|&tE`xuKAzRh=K$5a^JeehQ4h0gQg2jk)8(yKr;dYHcp}_RozSHjy zj773YZfMht+Vg4$e#mk>4*-k(y6qzSgWSBvzkjRKbKPi&5_xT_nfUl}a%Gv3E%YLwpS8kzSZfMj%jOYX6b1vh7bwxlncG@>Yc^b z#L1~)^iOtm<;8EZAbQRxOBvz|$z%%7&$d%_cYM{je)_8oZDq(&oD>=6Se;K-T=Ctw5Fp0Ve$*& ze^s>E-n6?j-JKy{HZ^Eh<8MD&7wpsd10hVVJs%KnKQc)8^mw1!7@(+B$Z368J)rjn zeSJbPuCnO5_h@ly6K#0e$l47Bt*_OtbVXemx2sf{*4KJ6T^jFLGmj}4cpynkC~%}L zyhP&pxNir^n!Zr~(u8;W$b>=j=1A|(xI_fw)8n#0#$c)ur2a7r7o$PeoG(2L3lH^` zGXUS{MX=XfU<8@gZ_~zuQR(uBhzyKIP4exj&4RLE#y5`lSoyKC5V#zwTh2j@rJMq< z3vp{HzFd!&2h0|3u+Y78W00=_lTYa$w!JxDjUSiLO1hjc$vV*#LKz&bs6Ags?Tbaw zfhpXZ8kLH06l>CS0<61qY;dg(pv|uYJzSvoor#M5YUj#ch6Z$fs(MzO@D5ybTgjC^ z*18@nN~r!OCqq75Qa%4|%qJ9X55}Du^z9UC{4^Tg?>4%ias3M1S-n0O-tyhrJS=2> z5LYF_wk;hJ$lPn!C%Ws<-|B0QoLjz^7f0)kh2$e7NihXeo16%qpJ)hlEF?`P{|e?? z1pG*0sna2u(4-Fk$p#Ji`O{z8aY#BY)e!8ELmCIGa*4WgdkdJVR)hrMZS4Q6<*7U-xB84Zc{Uw7)Am$xZJBq(Vw{NK#O9oBh;q zHyEalzZcv0@UL7%_&Z&@3r+^bICi)fJSX0T44w=giIPe>S@Y z{u@zooPbGOuSg)bmLG#FP3M;-hw^}y$Ddtypc5LflWGLNt2O&AYdo@~SrMZZAya){ zJ^Wgv0^r7fo7~J8zj6>>5Oc|<|6Jj65}aM^U?n6iPctSY{p7>Jnco>RLNuOUB0C= z{6*)eu4S^RZA!OXgk#jm)Z=~ej$#(`da2`$h^y+3A#i%~XEitPbmDN#y4n--_aA^_ zzu|VL14yymGu6DJuA)JYj+Opm7KZW%q4Z8~yu!n#M#6H2fZ{zne4p|)+#TP#&($_UVh&c4P+w!2 zXkRhs2w4nnm^=NUHG8$F(MoM`T$<+5m1J)-C*6bZqyiS4@X@YtE)zp`sRg|&Tra{(Z&bq$$)tmjhqEqEy#nU3BM!? zo$fbQo;g8jyj|nA6C=M zlB!u?F&>JR3e{Pi`TTQ#bM%IMu%gjGP9a4tYaz&);o!U%Y=ya$U$GSh?Dbx|4)l?N z&fI1$+eOV5e;f3iTDY$V1meRs^$L$A3u zvApLRX86XM{o{g&s3dlO)*vN?inHcx%wFg%>7O0*e@m-FW5d5P3TaB znuv&eCzP_HJa35PO8%VGQfeWOQGhI8-1Hi$UL!C1V$ikRQlM!SLNfk*d+}?(XN$9p zze8@93}58^K*)+Efj7J&dHc4E2Pu`uQROU)a3RBD zfgQd=6HUWMbxM76egU@37gF-B#4GRu9l5%)64@&+4pGVD%Nb0^l&zGtmlb(HH>teL zvt3Wkj;5=cSL`KOhCcRsEh2?nDN?m8LU}iALeMC@u%@2o4NIHQR)m$2DJpOg%v^IzddZtuVy+xgCgLGs zF5%lel?T$MLyteV zxnbd`zV@{ULq^slg5l@S?8s%N zH0#9Wz!BDLm4ddcvdL5dvya@UBH_ZOxKg#iI?hr+&aV`+y+yodrMSYg#gR{e#2vB% z*LI3qzq30c8)D@CD!p4m{MGd_M2(3*8@_6Fe>(7`W3}2jID4)2`k0oS!Gk{a-!yk? z3UxKOL_id@>URZ-ZB`E+Dma_OuAH_J&S%&4vHMK=Zlid*FeF&{>iWQ%6_f{Is*%#J zV*v8e{OsIznf+1t#{mA*u(9$E>LY|zf$FKEh6<4z*3qduTMxgoB@V5ZyM>zlNL6); zf7Z7)i#u?xf<7%?I%N0^(?O2li-`q)7_zg1J734-B$2DK)sJ3fDQFV0Wa~<`w|uaw zQwKtt9&2eb<$Z{%fxZ`PvgJPWQn1Mp_{Vk^hV0pGV}voe0f}yy)772Ajyvwyf3ml^ zlef3$6r>oV7W~0(SCYyX*{V-^i_l}q!FZn)YJ}M>$D~6;4L3S`zys_Iau+fFlza)H zz_M~s=iFm>uU3ZDQ0WioqLmwX2xUueQ@t0DP{e?N2Jfz|WntzgXhWVf(B%>Rahr)6 zp1Tr0egrXYOmP~IsJXIsW8ChK=-^jU;m17W?_gF%$S^=Wi4HX#>m|c;kG;c>@2UvLdu$!{T6p(KPXTLG$bCmM4;(4|t4sAl z5i0zz^zIav6}=!Y%LOlsg@a4N2R?d(v60~5zlR%8(ptOl0}+L&sfa>m9EvC#=wbNT$a``EgPyadRzZ0%lVIvvp<+e5amP`;T_}}nS9W-CaaZ;tp^rjr z2+87k;bvZ^UG-ou$XCfE>`3XJF0~s)XLNGVH%WGK-r)7%5n6CbzWAC1!V9MD=%ihu zjMjjavnvTI(>XiI^M>vGDU)m?)VT(}XlV=$18Ir`T4KdH|Z|LE1Ok#W|o-bGq#F$E(-GV%MR96a6o{zJ*g z%*(=DTb%y%z&x}>S;3%7`D)l(_6u5QiE>e3$zVSmQW3tnTw$3MgktTVVgqZJ+V1y{ z-l4zHl243>ab(P>Q01h=_OB<@bm(zkH}#6Xs7H8+zgD_=FPRoa-2?<{80G(`} zZkW|We6r5DVPlyW{o(qgwEG#m~mJ=!qGqJCNbSbA%iGu^wZ=zt|X_#ORS_}kB$8{Q42?3=uH_Dx!q z>XRbooVV$EfmM7E>aw8GxcSv~Pm#!bgt95vqdNz>8#C2*>f+V=E_)AKPeA27XF4$U z*X(UwF$JHhq*O!?_Xqbk6w(1?sh|(s_b}Z$A=DvH_byRuXR?@egU@%p_2w&?ey(ab z*NeA!3_oq@1}=yyyWYjS$ht@`$gp9+HrsbGD`SaX*0<82Z>K-Hiksve4g4zbrk8euyu#ji`qU0L@mC(axnJ|bzhZ5! z4X2}-$m;CUa6PUKy`VIwE8iEoQpCwG%l3s7vG0hNwi>RRq`xflZkVepVQ;@|GUU1C z5bOs`VYi_B8FcGR7PC(>?|a$xG-;Kd4pklcQ5}Jv_0`Vh?m5ajQ@%%PM7%T{zfpC> z%bcTQ#f^LdAIDl_zP%6h!{%Q(R}@{ThxGxgXanDHXCz(-U_d>vYa_Tz$;C>4%kmy| zNXsby2QXgq89|>oNaPhQXXC}%K$@rRj@!AP^xC6O+T2O@ym2za;rk9ZojqfhAHz*y z!8bXVi8j}U79dW$|90;vbg4s`!cK2hX8R1UvpWEJ_oqYUG6z}hWb0#ZO6d8_8`m64 z^5>wX`O?^hl-=rtB7s1b$Ej=fq^Ps9$WcV=9|EyU{S^DX;mjFgnUztg$XS8aJ?CgrnJz{?+`w1}I zcEYjcb$F{UqO~%6vns4@uwObq6+P7S?Y%trdV&kviaV5!*2}R}79eV>k(=$D2q1>& zZ9Erw1%%b_s_%=0IuHLQ@vF;T^?t|9P`$Q$BMT}#)@<&@~KWrH5Wo3hKD$pCIA zGyv8`4}aUD&#-{Y14!&j2HM}N4o8As`$nVWe6 zVd0zw@(KJ#l8fvBuMeSg!VmhzL;Q^mUj0Kc;qtB=?*?7Q=El_j!khI?a|+Ro*{*!E zj(n?)DXIyeV4>|T@srU6Fm2ZCw>06%bwo(hU&o>g4hCHTyy0T_tJG2%8$1vF1TJPb zxWfax4kecSFWfh{3!iQ!A)C)82DbEP^Aqkm2|VcWwg-U{k%ayt5O&WsYxz{0Yv#HS zT2;e}AK-gcomeOvS9?y8xmIb4aDq*AI=e{u+g^Frt4h5sD#sV>%<@?+0-z&pAhJEg z3?G4(rnjwDI9S=tx7#;w^=zjyyL*_l?7wYX zr_XxWK0EU4?}j-w^lJPslNjln(5ckR+*w$gsYUpLgM-oI;8@Rn{xUlLc046hNW3uKgVFTCQS+ ziS^Co2p zVVQk1){72+^5GY@^n#6-^a8+1-|dKJ&Y^&a>{L~ot-D2tDCYr`>(+;#<6T#~RlKwQ z6j|+g!<^x+a+Or|;S}+-?U1VjDi$J|e;6v=<7X3?$4ZRrd6qpnoC-a12SDf%y7#Uo zGud=#rv&s0z0D;)#TQ(Hh+9u##3#;`DYUNHY*prztV3CC4``Kqp9pX8)RX`n)VI;$ z?9HiQ_g(HUzXD)u+m?nY8ZAGfTg`pPTn5%z_@QfOhiij8%S$+ED44}8?8v8`VD%9i z(s_mK@3g#iUDZp-;(S>=91KLRs%#i{C>1@1b+9@OBS#puMkgW)c?B~9T6yay9KJEX z2Cy}iwxS20sPB$kl=uis+Dk5W8Gs-e7m|KzPuG6{vK-g5+7O2th#VF#U5{uFai*(i zo?HgR)v0E!L?`Pd`GUdUSX=YNPo#NU{-FGNuRT7*=2~(9^sJ}E zQGLQsrHQ?$R=ZQNx3|zm!p@fVGQWt~SIMHM2q=pl*2u7g{IWD<`q=>%fUk9f)@(Jh zbt1V?s+3TapEh{NW_-lSN_*>#d+?~VmU93u6KJRX`KBJ|zR zYXVY#fM3=V)gKXmJ;a_nQ_wg9)xP1Yq|d-zu_um#z?{hAX<<#ZiO1-x-iQ~All{ln9Jtol{L_N1m+jYV zK_~xuQt_(1_|<%2rn=fGR$R}iQ=LN1Uv_r>cYbE_KloXGvz{@g9GwoW&h~*gvar+7 zcM-jL11o(I?H%uUKwKIE295r>-M%GtG0Wqar%~zM4v!wYUD59KFX&T1To6;w^9Voc z$SESg|7SGt*vK+*{By90Po@6V0gOmfeZ+&q5$v`YmskK`NKI8F1gx3 zhBu`Ec;7!n;OvW?_!B}6<|plM+J*p(_GPLdb3Fvk4j-P;aq7p}Y`uT@ zCWp78j3CzqGno+SxGiqz_`#gU>GRBrvHBvwIhT1Sj@vH$XH>NADoTeL`E%e69`v?6 zq5t&BSEYN~PjTQkJ(7304&|2qquc+dKi-f}6QnT*R67JP`b)MO@(I10AxebuHwbI- zm(h^qt^8JIEu60|zc!v+?pK>#=u(^Q(_q^gsFxIx?hU>^mD|NW%+hkO1>#&EI|A~# z%E{`qpe6C)PxpzAbEM_{*=cL$A-;C33-neXOcm7Mg2VTHjcE|mUq~aebUgD+p(a>WB z_ITgSH=n8wNELzf=+H#+0U&JZ%4oHRRZ8a@JtGwj0hk)h^EJ(~G~s`9V`@>x4sOx$ zTO7Mp<9KTBBLATs#{fU#A`;tOEueOxHpOpnDDHrPnsUWaokj`7(t|lc!ar z=jSJD9imR+Q2f*zJEjHtaOikskjW~`qCeWr8dmLK_2R4-HvBuiZJJ`LX*|dsZX>9S zydxFVY6at6n|(9y3ih-AHS(XeF5(UP+1DK!Y{k>u>rbd%>PPJTrG7&)_I8?@2XA>o zJ4-95(=}7^`W0TC>bVN0MPVT0f^x{>s5k|;p1h`TdF!NUSnp!X9E2ADyq<8CXA_NC z5+PT**c=^xe^H|p`u%km`|Y~HVE=HA54uC{674I`f#&|Q=07KKR8{Rb(iWF@^n=ME zXYo?TpPh@OvgrVsNn*tH%;TIVH)wLkZeuRk*ewo6D}KwfZG?*EZSj#N_ehQI zGeSp;oJu%KiskH^0xB&3MdGLW<39Ur)n#7-$~0O%vRc>#Albe3>SxHmA!nz*vsrOR zaZuwj&VDlDx9mxWse&oQi}e6ESQpA0_W84zsPE8012pwH^UFigykBK+O|jpkLWB5I zrqlFG>t0B3mg1j&3DykK2~yxyg)>M{EG9l zJshlVhI<8pTQ}pA2N3Xv${a3BgnSc_Qkh`oX)1xgy{tWc}>W?#r~TH7t}kg0S6_LfqU41jeI%^t($PTKD98N^Cskj ztR{H2j8YtaTiooaVph9C>+#)urs`y@@?qXa%psyz&E*JsZL1`KQa?Rx82S-T zJMtW@f;l~%s(PYi@cG6&pr$eKvgy*lBDzWCPxkyXqFat(^~Qlh2xZ7=?^vq!hFGW%{rB^n^2BQGVrFy!1*`hJc>>^p^?6ij|Go z#hThCz-u&;KD5xUC3o@oJGvtkGUW&4T^$LqpiM@E1eM1#Puw_kDtJ$%1c zgif}6QB&Ndc1}>I0CHD_;NR@8{-Kb6@u9@I0T=^yJx5?fB3+rnCM)lQW z5+dHT>t)bYrd=wFF^;r%bh%7VoIY8=5B@dG;WL1$Ld?9fQayIuy6&2`{88~kr%>y{ zM7fcFqJe{;c3YPdp8lX~d9T^l;rDqJ_5xK^X+7`I#oinHQc7<4Gl)MBSw4Z=Ytn&9 z+)JL@7>X!o4ZIwtC02c^l7@^(0-E|)+?~4bdR@$6`c-(e!?9%dq*Hr|-hJyFu# z#39i->;1!4Rh&B449H7YI;Q)J6m=J&St>h8K7t(QWq>U?!1nJvW+6R~*$&ZLeK()- zCrXBPlWR>)ovn7gvYHGiM`n74N+TN~6u%qVhoM<5m(_ zLQpA9eb6PS7Cr280Jf)^u4vM4Rl}^r>^#T;P@FAoir%)9BycVQ8^|Mlp(3NwSPOUG z;p*wl5#rEHzrVm3fh{v&NRd~kh(!+?6>&v>cdK8UKX4P+j;bu=ir2b?%euoH8n3S^ zlzh_5u>#6hQ!ff!PNV8j@;ds{*MZJyLmNCmh9(SLtn@5-4h)O>^2*_yQ(jkh_~@g8 zz-%}=@(~Ya?7AWw)8Oy+F4>S;2&w39)=8m4)E)D4=sn+^-D@WMi21#$P z4&V23@Sc-ogx{g7q`R}e5C92s)D8gkAN(r3I$QVFAhrxBnE9qmzvL9HDmhw}DY!%a zZGd1PWV}pMu~XltQuOM>^)`EX(fmIL%FTdkp{R*9=>Jgn9$-yw>$)fw)QOd;6p`Wt z6{U!Dr0P^a1wqBoi-I&mm0p7#X_*#!iGqL-Aco$9N>QrR&;vw>5Q-s$5JHkOesr$0 z&f5E)yY_vabMM`G9u-6K|KlHHeC_?d@qQ^tlbJ-=HFNGri@xOFy9a2!fw2=6=}I%? zHt9c)kn=W!)1skjNAI#fhJr1Dcxmx=dAaW_2eT&ur&7{qe;`(8C4l`(^mKjZbwpUDN+46>FC0Kpn}_Vc*t&zQA3ZKM14 zY;~}wc|?2Hw50!}hEK1}t~;K#FpW%L30bm&VUIw-*nzGO@7WAoMDrAY8>x&M2wzFU zM}lAk{=89T^-W-fnb(LG0zB3}&tJ#|cSQG|)z(@Mu@gT zt9c#J2(>J4AFD)-D1zP3%$bzZ%l-pcTg`{cl>m*`wyCd z=i75D%+#eQXQNeDO7b!k0ig1fij%Th=L*|MCVc*(mqROBEw%qnzJPKRFyvC?fy z#C{>cxZe$}bpRU(46n2`0NIgYhS@E^AR-r81uX_F@VI~DSg*ELE1-_d9xggHh~C=x zSz4;?{<3$}Hw^Dde));}h$m#1`1IJIi;c}zo^fJqCax?s)&gq-GH5s_^0VdRHaeC7 zJ8ScIwWEgjhu>jZ&g)l=S>RS{gBKw0=IPHfFI@S%#oH!MtNR^y4$@4Mg0=AjW25=Q zaEpt!5#`3t$1so}{g8hizbU1vAbiAQTBMndbGKBcBz4C52#jW(GRv4TilpXQ2qvEk zemboPJci*FFmHb&Sg&8<`L@`JtnJNhP}qOE*W0w)@&uyayXIrrcY(1kO6x3>sa+j-lS1_O#O7!B($>|u+nehBdq_Qb zNQn_rDRMScWIHg~XHNcH+>`rnqFWf_ryttKrkuX<6v9ttNU*~_QoS=@3_@0PmfO?`o0N{?&T;6QZDe?w3m*hC9IQ26-OB_Z`GH|bq;2lI5Y@Qf|GoO; zTV*aNgzap#s~z1t9z3(~j$e+3#dV8gQM!xx{C95LIY6m6VE`<5D%X(JO6jGwSu3am zw8EF5Mfve?|0@<czRA0U<{ zkY3U~V{V$C;5^*5r(;|Fbr1zpT2~$0)Gv3e#}ft4!}&M-TPNOkHN5v}$I4H>wUc`I zHCPLj_^78xk~qV)YdRR4!=6EOKFSL!LeW-f2}a2b!bByeajYl_ZAFoE8+vjeQG;_P zBfRIWLYG^i{lc|gFTXyWS@bUE-HT6i0I0BBiGGfnw6uNm zUFT0-7xYKvSn4-#Vk?`u*l4GH)<`|*3csPA;t%0CwaHV)&q(bl2dM(A#I=QJgdD&1 zMu_)^r45oA^|9QugBk06!8)0vPfIgaA^4cwI`C2{j(p3vkq1Ap5zUfCTHW{Xu3Dz% zIYX#1*Uzxwo%k9YcGKy+E8m7L&&C`N{*Y$QYpk=b%Q!|D=R(NeC2N%vN`2+(-1rg{ z0SGzRX)Yc2aTs0ut?9fn#?;Z3@74hIq}1gS+Rbi9%!E%2fchR|KIMN0umNm$g-Vu>~g-(Gw>yHbTCPGQnIK z2?eZ{T!PzwCVcy0lPTO!>K-&msdY%fBw+ptj9bZq31@GsfCLRDmZ#h4yC166Ob|RL56PQvsOuYiTR(Qx-+Mg+Xu6DHJ+`<*v57NC#-5%e;Qj z{b0n6&XhuQr59YZJO7x+f^&*~P`#z`xE#t@dID6I-134*M-tdN5btIAI(lQSyTV(l z|BG^$AFBOd3M_XLdT{G*{K7e0n0JPS4{NW-X`~CXbxprm!p!}nCf@U&aoTd5;_px^ zb6Ms{A8|itN`TT(M{gV>jVY%>b%dShT%sMewF?|b=xL*yF7pB}NXjHJCe>(5; zKhFS6$r;j6drR385k~Z?B7ZGT&HW6?mbbk_oO)2J^bT@*p&~jL%k`=*C;d}vhWd^N z%)<`{EWgj9_@zJi;H%9YtFiMd^3&%2%m5y}e(piBK)eB2+v~4Q(kTRV76_y-ZnR(D znLS(iF3FJL;4OSAaQ>~;>P&o+YucoqqpOzfn4FlL4fcwXNrbs}mXe5oXYQ4+eYF|4 zmB9{+B`1jT`E(=<8H_$pTC;pb8<1V~MorvEm zCfv7YI&w0o-xtjab19Z|gHOuMc{9%+j3{wdgNt96(k$maQ}nekzEv~fac98L`a`4e zp*lUa`QG4;e^)Tv-0rVC?V|2+^HD;}_31#6gX(zf{E*5VK<(K!2LMq)hJ40V2ke_@B(?RK}ouiem9v?y7O|#`I zie;3NeE~7HBJ^jXaP`FTWj0$e%%O*X#}`8KxJ;7K?l0G=gymV zg zD`O#y^?7hTR&(&aufP(}Y6e~+&1mo)IkezbJb0GEuH1}kW1Cj$XUgf^rXnbO@Hz7~ z-?!{G8i+M??4M}d( zf(p{-W$S!oc%ft}!a-|#dkXo~H`X##nf5oN?4q{+H2P?9pagdi>{I^lB}H$cA+w4p zH{P4W9_jglV#wAWabvd~`SMem)u0H*wRV8j;{|f=L2oBiI&gIvGAG^Z__qM%{GZBK z^{V2CKD21R(oxy3<@1Fx7L%4c1JV`LWFE9g4I12ch>sp1I$pN-OEY_sLkvxmGL~WA z^pz&{gD?U8peNG?fJY~g9kkMI?QXWG&J}I#n=3nOn_^a%F;IVpX%gEzhu1=_YU-IA z57p0i54QN0SBIylLKFC_c4c+r4*fHL!loS=PsJMwmT^u1C|DQYz18H5xml$OC}e$6 zs%=DkOCF#`NqugA&~)uX)DM;`(NI4A^!cS7o@4sPD+e7wmH1k?;wm0(n;F!cToiXTQeo zxdGs-*oJ#{8Ivh`a?ETl74)vF)K(0^ylV@{Csc>ygO@4!;T;X7w#JNM^vANabKo8J zQ2o9{V)nU>7MEO79vz7GCF@N&yg zbpw376rv6C<^tpc?D^>f04`pQ{E4DnGSmop^tXZsUv7R#zSmtXUUF?Ex=(KZfi|M% zt@ekXq+CUeE<1osMO~%szlz{R3GO$H;2up-f0i$E6%)&H1!4};%tIUc*2WHqVzv#l zw=P3$=_Yid;f%}AsKAB3A7Q?;FunRg@xJZR{*X{A>G5v>l<;psR5v~E=x=TOI?enn za^pP@D3d7a-!M5kT$i!@-qtwlPgRt@iY)-@Qnq%iZuG9jl5<%nyUfU^a*`J=u!M%H zdq8Po)NPPdC0z?Y-O)NZ6~9eD-$FWd1wO8DT!!*BA{LP@&CfcOn;qjRP6sO6?+AfRAp z@!oR!j}mHn-)YFB@ybwhcuaA|UF{}#y_lx7;{otXuKw&J3$35C)*q zHV~U{O__mlCk7oz?mz=?JVdJwBnG0!On+F!_JVCJ|F42tF2~S(0uJBN7i0A48*c>x zi2irA+chhd0^{FqC7@KmWxono97uZbq52~zo1BSHq{(rTS#atC2LNa;{*9zje**$He1e?yA^5Jx^)i5?Gh#QXns+9$D`@E8c z(H7zDhD{0qx7qZ#6D)Zs|MUEz78p+NsO2i=;76&?hEH|ho9|2?+u}4Pw>J^_a_g53 zWo3AQM!JQ5wI7TY_!dI#)F!)=ZCLLKD)j>RQI^k^`PW9@}^$46bpbo;^zf~ zA~{<^xDz_UX@S$Bt&08k@`FkTOl(0t8Y8eUylEX^dNTxbt6}1&4^|14d4#f4rm=A5YUHK!cW!>Lhw%z&NkR2NMLeC= zc05MC?-#;Pf%=dn3!IX*L)u-@tecNaTNt5pc)f;{4r!Yrp}NY5UU^7njDbMAMWtF>%pESb3b!z zauhj}GXwi*G4r4h*EUyPqH%xu_(3~s zhE6`DtKD~`1Wh}JS?_ozpT_<2)Y*b6+fu0sF7JAQX&VT++iJg}1S=6%OoNX6~fs;79zzxvr z%G-K_wJai_J4k*7!i6Zu=>Aauv&jQs9_s0VknZG^tv{p`dWPl+LF((**^ZB)#5TLg zBSqnM8!Ig}DSXN4nSYiPHMVc-{=BtS%G*tt|AW1Vum8>@P)TO3ZNzhoitm%Dmb%y$ zu#BItp1#eJ8CX@zvwMM&TuSW9EfcdLKg+cH_TetvCI}R^&Na|lbcRJa1Upb6L`B2% zVst%7DtHQkV-noND@Y-#Kd3PzDfY;{hBT5nKQ^9*q|M14D@A zu-`OMFa#Vr6hs&i5}T#F6T4_x?i^8R&YG5YTW%2&#SSzRxtZ|WZQe-!=Z>wX+8W<` zn{%fEi(Ras#Qk)A8M%}rc)1p7Ide>IyEi%P zot;TUik)f)S};dAcaI0z>NgVAvr}Rkr^B2rTALzl;6VA9-S0Z%RdpGFI+;s9#sQ_d zc-XAm7=YdmbOV!|CS-VJVVKaq-Jfu4x|;7D!8sKsF4h4Vb|X!5A?CYp-0VK<5x%q` z3TUVx@wy#llOlC(z`S0`nRc^2Cr2-)6^J?In?2>7I1B zSj7MhO8tm%etcP*Z`Fxn)-!2>qHJASRm0>r01d_=5I^dd-@UBgK;yXg{_~N|bpo*X zpbf}BQEJYWqnO$M*QZ6FVtxY`R3z0Zf#R0vsXj%NSc^zN=&A?5o6>`h>OYkbxB+bf zJgpj}O8v7$k?Kg%`-aSo@qw3Ra8Ul9zWkoYl57gAX$fb$gmN-G8?{n#`~hJ^11wpe z{cz7d#6MU#ejZ!fWQ#w#%Vx4cWASoJOP;f~PPpTGOyD|b5}pnHOC+(#;f%t#=~QZ{0}(Zv z10L1j_v<%h;5gd$yP<^zRhl8rw+pK4IGEIxAdh;M1ok9?m~Tw0oH4f+h11KQ3WOaS zaJIYP8q2JC@?3b(yNxwYVyT^L)gsfW0DDvW3v$F8Zj(#7?P6d8WnF(>1Wa=xF}5qq zYCeBb7wQcG5nX@4U*SOoW4`Cp2DHbD=VJlK?Vyky;0$CIZoBL9;jH&eyN^AaZy{i{ zWv&vior&kvZTz;z3<@f+3HJXcMt9x49RqH1&=^`;Vg5xMlShBf;&-afM@3S+XM+6J zU@-9d{W2LAd^POk=R0BWsq z_{dBK$$@mA+*kR&g~WG#zC}7mw=s+m^=36hYoQHK$+dT93>DzQZ+Bh6chhrN%J@)3 zzpRzLa}4sVr|_HMG7=&8UQF!`zegA(FK3@Et=8Udspb@u@GSCj?h1!~2=EqcHrBXx z#+sHFNSLQ|_<-lK2of+Ma-X_+r5~wL(b%DCEkdZ3OIb3Tyej=8#mm1vIYA`ukI*9> z#mWJVkB0(zO^6>?7vK_rKQxFo4#vup#owGiQX_rB*y`F&PlvkZ`#-sO+g;zLgU=o+ z82f?52033e46#-2Iuy6K0Z7#H6;|NkIYfufp1PgQ^zn)^-p@J#J!_GJLiBOGTLq3N zp!eIMkVVE?Qi<;)FTd^m;ckSUaQJrSvY)21QR)F+th5TD$3}M~#Pi1cVKTg^EC8ZC z%wjNB`_`CBfa7qv$sA>tZ&dR-q^p{}&(^e}YO13Nk%XO?tNySH4$elXz52PiCQAV* zF(%@8^wpTZ@?+Uqd`cl`m~gviB{F~c^i*lG?zMq^Yfn`87EE+Ui<3WWldF>PFLw6ON5?gkIMeEccJ`Cbs0*sqi7hdNTj2e*hJyA94{OPG? zTXKWa51E{f3ae?p@7oWLZYT>IlPYlAIk}s-L5k_xTI^e^?BN!gV?yK$L7yI9DXgqm zpKqfP=!I)eS>0?T&gawBCQ&-ib_w*g1tE>8QajEinJBaayFGPk{N2b(b)hFOzrGv7 zYySRZJwgPhz(4jiSo$tHqxbx<=*lBQhT=#kvy=t#$NDu9GL za&EOIwWLdldsbrP_mN&_8`EHav*=Y-b|y~lLSI3qTHaRHUW5%I%$9=Jy{0kQ80b;L z*wurdC>pGlzyZ05BL4%uvD{W3E=WT-CA?xv}LUG%I_8En7ysG4@^z7D)M&uuggd9X8%?x#hk z9X&ivoefr5F!%HU`1wyTJ>paA*9V8BX1bIY>SO0JO;XOAe~XWwrd}V}V&@GXpvXI) zU!w1?JhaQPVxllyIpgx#sOAz^3G{@_0#(_vLR!0`=;oNfsX!TzTq|>5R$DYFLVM%d zStpUW&QqQOHf8{#Ygv_bYf;JdW&L)rS-Lp_+|m`%=IVJFj;O!8t(dN(sUWp)TN%U``$wN|k{O^O;kcCXBvJTAJl zlnWFmTodU}&C#%D(RP>QH?9xhnlP+)f(6Z$uXiO&?ffBRQ#{gUifbKNFstniwwhKvjrG@cLRt+b;D%8_#ti47lAe+-3Xt!)Bm(SuIwIYVP_2d=yZ6S$Bvk90 zY0I|#Es+%@cO7D-{8BwG4ijgb>ztiKmPtwp^9PjS17*F=BR1F5JdkPYzJ$0SLM-yE z0hPR3$?{*XmZocI)f@&f!m~{vd!G(?5_Trf zypr!>?i~O6V4lA)I|N@_9PBi0>lng&U7PHG_4;g5{yt`XbGU^_bf-IE4kA!12^$OU z8sSSupAL7lIBzjhHJOs6lXJlPoA*n0vs|`URdz@hpyr(>-EqKwn7P!0zq{nT6qm!n z5N$(D5FOScROcB4VR%XZqP3`8QhB0t%OVCa60W;>rlKt9qy8S1IidWrkd@5+FHm(o zEpdb|M()n#>-uXf_s8CSmA~i)nI1xure7sOKH}o!)-M&<1^XKgBCC)mW2>m0YZHQ= zTRQIl7s#vhpBJlp;yk|a?6kDN4(AVy*GRI-f!%;c=})q05Ab;O6(KOq>n7OL0%+2k z@tPS>v}j%_d_Lj&3w|J0o4EmxxC=_;MyqvZ8)(77Z1-J1Yqw;R2=(tq-!c~W@c7=OvQ z>7(qOt*zO+9ljL%E%Z7lX`P505rPYxj(KdrIhG)6A!uM$KB7bmfKqUS0g$83b=S(j zanbvrLohQ`CT==NcYe7^OIlArZmH;~`^}8gwi&Sg)5s>rriG0>UZRuDaK5mOaGO~d zGEZK424l;6!KZ}0Id~c5bRLiYTb?mdJUUI`kaR0u2;aec)n84sn%#Jil#~vVEEC^1 z=@4Ek1dOi;R)pxgxn{(^;iEb%H^Zav4#HKN7xSq0E{lMcsckVyT|zfG+M&6x(3>6^ z|1R2rvGD~<8P3dK9gcnJF#dJayu$5r!I%&>gjiO{(;tuZog5w%s&OEe8DydZ{YLvD ztposf8XnLI5$y*atg;@2*vTcUYfTY%gZIm<09jfEIQcdD#{4?1>L)px;qz#(%7SXv zT3nLm=^Egzap^1nnhN+tBII^ThE^O`#rO4JTNtlMS(wsD9^Y^Af%%AWqsB-!w&qp$d}f8$#V%S^=)EEX znt$v0@yZ-?0w}zM&jHV<;rga8?4<

    GhlJ8GqwSRH>sn+*QXd4h;U@>o7hV*`%1$ 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 Vey7HnyU-4O@q(E?_T2S5{}1WAR)zoo literal 0 HcmV?d00001 diff --git a/MusicPlayer/cobie1818/script.js b/MusicPlayer/cobie1818/script.js new file mode 100644 index 000000000..407de7814 --- /dev/null +++ b/MusicPlayer/cobie1818/script.js @@ -0,0 +1,194 @@ +"use strict"; + +const audio = document.getElementById("audio"); +const filesInput = document.getElementById("files"); +const title = document.getElementById("now-playing"); +const status = document.getElementById("status"); +const playButton = document.getElementById("play"); +const previousButton = document.getElementById("previous"); +const nextButton = document.getElementById("next"); +const seek = document.getElementById("seek"); +const volume = document.getElementById("volume"); +const elapsed = document.getElementById("elapsed"); +const duration = document.getElementById("duration"); +const playlist = document.getElementById("playlist"); +const empty = document.getElementById("empty"); + +let tracks = []; +let currentIndex = -1; +let playbackRequest = 0; + +audio.volume = Number(volume.value); + +function formatTime(seconds) { + if (!Number.isFinite(seconds) || seconds < 0) { + return "0:00"; + } + + const minutes = Math.floor(seconds / 60); + const remainder = Math.floor(seconds % 60); + return `${minutes}:${String(remainder).padStart(2, "0")}`; +} + +function updateTimeline() { + const hasDuration = Number.isFinite(audio.duration) + && audio.duration > 0; + + seek.disabled = !hasDuration; + seek.max = hasDuration ? audio.duration : 100; + seek.value = hasDuration ? audio.currentTime : 0; + elapsed.textContent = formatTime(audio.currentTime); + duration.textContent = formatTime(audio.duration); + seek.setAttribute( + "aria-valuetext", + `${formatTime(audio.currentTime)} of ${formatTime(audio.duration)}` + ); +} + +function highlightTrack() { + const buttons = playlist.querySelectorAll("button"); + + buttons.forEach((button, index) => { + if (index === currentIndex) { + button.setAttribute("aria-current", "true"); + } else { + button.removeAttribute("aria-current"); + } + }); +} + +async function startPlayback() { + if (currentIndex < 0) return; + + const request = ++playbackRequest; + + try { + await audio.play(); + } catch (error) { + // Ignore a request interrupted by changing or pausing a track. + if (request !== playbackRequest || error.name === "AbortError") { + return; + } + + status.textContent = + "Unable to play this file. Try another audio file."; + } +} + +function selectTrack(index, autoplay = false) { + if (!tracks.length) return; + + playbackRequest++; + audio.pause(); + + // Wrap around when moving beyond either end of the playlist. + currentIndex = (index + tracks.length) % tracks.length; + audio.src = tracks[currentIndex].url; + audio.load(); + + title.textContent = tracks[currentIndex].name; + status.textContent = "Ready to play."; + playButton.textContent = "Play"; + playButton.disabled = false; + previousButton.disabled = tracks.length < 2; + nextButton.disabled = tracks.length < 2; + + updateTimeline(); + highlightTrack(); + + if (autoplay) startPlayback(); +} + +filesInput.addEventListener("change", () => { + const selectedFiles = Array.from(filesInput.files); + if (!selectedFiles.length) return; + + playbackRequest++; + audio.pause(); + audio.removeAttribute("src"); + audio.load(); + + // Release the old file references before replacing the playlist. + tracks.forEach((track) => URL.revokeObjectURL(track.url)); + + tracks = selectedFiles.map((file) => ({ + name: file.name, + url: URL.createObjectURL(file) + })); + + playlist.replaceChildren(); + empty.hidden = true; + + tracks.forEach((track, index) => { + const item = document.createElement("li"); + const button = document.createElement("button"); + + button.type = "button"; + button.textContent = track.name; + button.addEventListener("click", () => selectTrack(index, true)); + + item.appendChild(button); + playlist.appendChild(item); + }); + + selectTrack(0); + filesInput.value = ""; +}); + +playButton.addEventListener("click", () => { + if (audio.paused) { + startPlayback(); + } else { + playbackRequest++; + audio.pause(); + } +}); + +previousButton.addEventListener("click", () => { + selectTrack(currentIndex - 1, true); +}); + +nextButton.addEventListener("click", () => { + selectTrack(currentIndex + 1, true); +}); + +audio.addEventListener("play", () => { + playButton.textContent = "Pause"; + status.textContent = "Playing."; +}); + +audio.addEventListener("pause", () => { + playButton.textContent = "Play"; + if (currentIndex >= 0) status.textContent = "Paused."; +}); + +audio.addEventListener("ended", () => { + if (currentIndex < tracks.length - 1) { + selectTrack(currentIndex + 1, true); + } else { + status.textContent = "Playlist finished."; + } +}); + +audio.addEventListener("error", () => { + if (!audio.getAttribute("src")) return; + + playButton.textContent = "Play"; + status.textContent = + "This file could not be loaded. Choose another track or file."; +}); + +audio.addEventListener("loadedmetadata", updateTimeline); +audio.addEventListener("durationchange", updateTimeline); +audio.addEventListener("timeupdate", updateTimeline); + +seek.addEventListener("input", () => { + if (Number.isFinite(audio.duration) && audio.duration > 0) { + audio.currentTime = Number(seek.value); + updateTimeline(); + } +}); + +volume.addEventListener("input", () => { + audio.volume = Number(volume.value); +}); \ No newline at end of file diff --git a/MusicPlayer/cobie1818/style.css b/MusicPlayer/cobie1818/style.css new file mode 100644 index 000000000..1972946a4 --- /dev/null +++ b/MusicPlayer/cobie1818/style.css @@ -0,0 +1,199 @@ +* { + box-sizing: border-box; +} + +body { + margin: 0; + min-height: 100vh; + padding: 32px 16px; + background: #101521; + color: #f3f5fa; + font-family: Arial, sans-serif; + line-height: 1.5; +} + +.player { + width: 100%; + max-width: 580px; + margin: auto; + padding: 32px; + background: #1b2333; + border: 1px solid #39465d; + border-radius: 24px; + box-shadow: 0 20px 50px #0005; +} + +header { + text-align: center; +} + +h1 { + margin: 8px 0; + font-size: 2.4rem; +} + +h2 { + font-size: 1.2rem; + overflow-wrap: anywhere; +} + +p { + color: #c4ccdc; +} + +.eyebrow { + color: #99e6d4; + font-size: 0.75rem; + letter-spacing: 2px; +} + +.artwork { + display: grid; + place-items: center; + width: 160px; + height: 160px; + margin: 28px auto; + border-radius: 32px; + background: linear-gradient(135deg, #8de1cc, #9bafff); + color: #142137; + font-size: 5rem; +} + +#now-playing, +#status { + text-align: center; +} + +label { + display: block; + margin-bottom: 8px; + font-weight: bold; +} + +input[type="file"] { + width: 100%; + min-width: 0; + font: inherit; +} + +input::file-selector-button { + padding: 10px; + margin-right: 8px; + border: 0; + border-radius: 8px; + cursor: pointer; +} + +.hint { + font-size: 0.85rem; +} + +.timeline, +.volume-control { + margin-top: 24px; +} + +input[type="range"] { + width: 100%; + min-height: 28px; + margin: 0; + accent-color: #99e6d4; +} + +.times { + display: flex; + justify-content: space-between; + color: #c4ccdc; + font-size: 0.9rem; +} + +.controls { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin-top: 20px; +} + +button { + min-height: 44px; + padding: 10px 14px; + border: 1px solid #667895; + border-radius: 10px; + background: #28364d; + color: #fff; + font: inherit; + cursor: pointer; +} + +.controls button { + flex: 1; +} + +button.primary { + background: #99e6d4; + color: #10241f; + border-color: #99e6d4; + font-weight: bold; +} + +button:hover:not(:disabled) { + filter: brightness(1.15); +} + +button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +:focus-visible { + outline: 3px solid #ffdb85; + outline-offset: 4px; +} + +.playlist-section { + margin-top: 28px; + border-top: 1px solid #39465d; + padding-top: 16px; +} + +#playlist { + padding-left: 24px; +} + +#playlist li { + margin-bottom: 10px; +} + +#playlist button { + width: 100%; + text-align: left; + overflow-wrap: anywhere; +} + +#playlist button[aria-current="true"] { + border: 2px solid #99e6d4; + background: #304b4b; +} + +@media (max-width: 400px) { + body { + padding: 12px; + } + + .player { + padding: 20px 16px; + } + + h1 { + font-size: 2rem; + } + + .controls { + gap: 6px; + } + + .controls button { + padding: 10px 8px; + font-size: 0.9rem; + } +} \ No newline at end of file