From 078a5b2675620bd0b9809e8bbb0580403e60403d Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:44:21 -0400 Subject: [PATCH 01/30] chore: drop Storybook scaffolding Unused default Storybook install (config, sample stories, assets). Nothing imported it and it was not wired into any script. Co-Authored-By: Claude Opus 5 (1M context) --- .storybook/main.ts | 17 -- .storybook/preview.ts | 21 -- src/stories/Button.stories.svelte | 31 -- src/stories/Button.svelte | 30 -- src/stories/Configure.mdx | 388 ------------------------ src/stories/Header.stories.svelte | 26 -- src/stories/Header.svelte | 45 --- src/stories/Page.stories.svelte | 30 -- src/stories/Page.svelte | 70 ----- src/stories/assets/accessibility.png | Bin 42336 -> 0 bytes src/stories/assets/accessibility.svg | 1 - src/stories/assets/addon-library.png | Bin 467366 -> 0 bytes src/stories/assets/assets.png | Bin 3899 -> 0 bytes src/stories/assets/avif-test-image.avif | Bin 829 -> 0 bytes src/stories/assets/context.png | Bin 6119 -> 0 bytes src/stories/assets/discord.svg | 1 - src/stories/assets/docs.png | Bin 27875 -> 0 bytes src/stories/assets/figma-plugin.png | Bin 44246 -> 0 bytes src/stories/assets/github.svg | 1 - src/stories/assets/share.png | Bin 40767 -> 0 bytes src/stories/assets/styling.png | Bin 7237 -> 0 bytes src/stories/assets/testing.png | Bin 49313 -> 0 bytes src/stories/assets/theming.png | Bin 44374 -> 0 bytes src/stories/assets/tutorials.svg | 1 - src/stories/assets/youtube.svg | 1 - src/stories/button.css | 30 -- src/stories/header.css | 32 -- src/stories/page.css | 68 ----- 28 files changed, 793 deletions(-) delete mode 100644 .storybook/main.ts delete mode 100644 .storybook/preview.ts delete mode 100644 src/stories/Button.stories.svelte delete mode 100644 src/stories/Button.svelte delete mode 100644 src/stories/Configure.mdx delete mode 100644 src/stories/Header.stories.svelte delete mode 100644 src/stories/Header.svelte delete mode 100644 src/stories/Page.stories.svelte delete mode 100644 src/stories/Page.svelte delete mode 100644 src/stories/assets/accessibility.png delete mode 100644 src/stories/assets/accessibility.svg delete mode 100644 src/stories/assets/addon-library.png delete mode 100644 src/stories/assets/assets.png delete mode 100644 src/stories/assets/avif-test-image.avif delete mode 100644 src/stories/assets/context.png delete mode 100644 src/stories/assets/discord.svg delete mode 100644 src/stories/assets/docs.png delete mode 100644 src/stories/assets/figma-plugin.png delete mode 100644 src/stories/assets/github.svg delete mode 100644 src/stories/assets/share.png delete mode 100644 src/stories/assets/styling.png delete mode 100644 src/stories/assets/testing.png delete mode 100644 src/stories/assets/theming.png delete mode 100644 src/stories/assets/tutorials.svg delete mode 100644 src/stories/assets/youtube.svg delete mode 100644 src/stories/button.css delete mode 100644 src/stories/header.css delete mode 100644 src/stories/page.css diff --git a/.storybook/main.ts b/.storybook/main.ts deleted file mode 100644 index 8c68b2d..0000000 --- a/.storybook/main.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { StorybookConfig } from '@storybook/sveltekit'; - -const config: StorybookConfig = { - "stories": [ - "../src/**/*.mdx", - "../src/**/*.stories.@(js|ts|svelte)" - ], - "addons": [ - "@storybook/addon-svelte-csf", - "@chromatic-com/storybook", - "@storybook/addon-vitest", - "@storybook/addon-a11y", - "@storybook/addon-docs" - ], - "framework": "@storybook/sveltekit" -}; -export default config; \ No newline at end of file diff --git a/.storybook/preview.ts b/.storybook/preview.ts deleted file mode 100644 index 8678238..0000000 --- a/.storybook/preview.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { Preview } from '@storybook/sveltekit' - -const preview: Preview = { - parameters: { - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/i, - }, - }, - - a11y: { - // 'todo' - show a11y violations in the test UI only - // 'error' - fail CI on a11y violations - // 'off' - skip a11y checks entirely - test: 'todo' - } - }, -}; - -export default preview; \ No newline at end of file diff --git a/src/stories/Button.stories.svelte b/src/stories/Button.stories.svelte deleted file mode 100644 index 7187089..0000000 --- a/src/stories/Button.stories.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - diff --git a/src/stories/Button.svelte b/src/stories/Button.svelte deleted file mode 100644 index c34befe..0000000 --- a/src/stories/Button.svelte +++ /dev/null @@ -1,30 +0,0 @@ - - - diff --git a/src/stories/Configure.mdx b/src/stories/Configure.mdx deleted file mode 100644 index cd2ed52..0000000 --- a/src/stories/Configure.mdx +++ /dev/null @@ -1,388 +0,0 @@ -import { Meta } from "@storybook/addon-docs/blocks"; - -import Github from "./assets/github.svg"; -import Discord from "./assets/discord.svg"; -import Youtube from "./assets/youtube.svg"; -import Tutorials from "./assets/tutorials.svg"; -import Styling from "./assets/styling.png"; -import Context from "./assets/context.png"; -import Assets from "./assets/assets.png"; -import Docs from "./assets/docs.png"; -import Share from "./assets/share.png"; -import FigmaPlugin from "./assets/figma-plugin.png"; -import Testing from "./assets/testing.png"; -import Accessibility from "./assets/accessibility.png"; -import Theming from "./assets/theming.png"; -import AddonLibrary from "./assets/addon-library.png"; - -export const RightArrow = () => - - - - - -
-
- # Configure your project - - Because Storybook works separately from your app, you'll need to configure it for your specific stack and setup. Below, explore guides for configuring Storybook with popular frameworks and tools. If you get stuck, learn how you can ask for help from our community. -
-
-
- A wall of logos representing different styling technologies -

Add styling and CSS

-

Like with web applications, there are many ways to include CSS within Storybook. Learn more about setting up styling within Storybook.

- Learn more -
-
- An abstraction representing the composition of data for a component -

Provide context and mocking

-

Often when a story doesn't render, it's because your component is expecting a specific environment or context (like a theme provider) to be available.

- Learn more -
-
- A representation of typography and image assets -
-

Load assets and resources

-

To link static files (like fonts) to your projects and stories, use the - `staticDirs` configuration option to specify folders to load when - starting Storybook.

- Learn more -
-
-
-
-
-
- # Do more with Storybook - - Now that you know the basics, let's explore other parts of Storybook that will improve your experience. This list is just to get you started. You can customise Storybook in many ways to fit your needs. -
- -
-
-
- A screenshot showing the autodocs tag being set, pointing a docs page being generated -

Autodocs

-

Auto-generate living, - interactive reference documentation from your components and stories.

- Learn more -
-
- A browser window showing a Storybook being published to a chromatic.com URL -

Publish to Chromatic

-

Publish your Storybook to review and collaborate with your entire team.

- Learn more -
-
- Windows showing the Storybook plugin in Figma -

Figma Plugin

-

Embed your stories into Figma to cross-reference the design and live - implementation in one place.

- Learn more -
-
- Screenshot of tests passing and failing -

Testing

-

Use stories to test a component in all its variations, no matter how - complex.

- Learn more -
-
- Screenshot of accessibility tests passing and failing -

Accessibility

-

Automatically test your components for a11y issues as you develop.

- Learn more -
-
- Screenshot of Storybook in light and dark mode -

Theming

-

Theme Storybook's UI to personalize it to your project.

- Learn more -
-
-
-
-
-
-

Addons

-

Integrate your tools with Storybook to connect workflows.

- Discover all addons -
-
- Integrate your tools with Storybook to connect workflows. -
-
- -
-
- Github logo - Join our contributors building the future of UI development. - - Star on GitHub -
-
- Discord logo -
- Get support and chat with frontend developers. - - Join Discord server -
-
-
- Youtube logo -
- Watch tutorials, feature previews and interviews. - - Watch on YouTube -
-
-
- A book -

Follow guided walkthroughs on for key workflows.

- - Discover tutorials -
-
- - diff --git a/src/stories/Header.stories.svelte b/src/stories/Header.stories.svelte deleted file mode 100644 index 23175a8..0000000 --- a/src/stories/Header.stories.svelte +++ /dev/null @@ -1,26 +0,0 @@ - - - - - diff --git a/src/stories/Header.svelte b/src/stories/Header.svelte deleted file mode 100644 index d6b7b21..0000000 --- a/src/stories/Header.svelte +++ /dev/null @@ -1,45 +0,0 @@ - - -
-
-
- - - - - - - -

Acme

-
-
- {#if user} - - Welcome, {user.name}! - -
-
-
diff --git a/src/stories/Page.stories.svelte b/src/stories/Page.stories.svelte deleted file mode 100644 index 8f2ff22..0000000 --- a/src/stories/Page.stories.svelte +++ /dev/null @@ -1,30 +0,0 @@ - - - { - const canvas = within(canvasElement); - const loginButton = canvas.getByRole('button', { name: /Log in/i }); - await expect(loginButton).toBeInTheDocument(); - await userEvent.click(loginButton); - await waitFor(() => expect(loginButton).not.toBeInTheDocument()); - - const logoutButton = canvas.getByRole('button', { name: /Log out/i }); - await expect(logoutButton).toBeInTheDocument(); - }} -/> - - diff --git a/src/stories/Page.svelte b/src/stories/Page.svelte deleted file mode 100644 index c4c069a..0000000 --- a/src/stories/Page.svelte +++ /dev/null @@ -1,70 +0,0 @@ - - -
-
(user = { name: 'Jane Doe' })} - onLogout={() => (user = undefined)} - onCreateAccount={() => (user = { name: 'Jane Doe' })} - /> - -
-

Pages in Storybook

-

- We recommend building UIs with a - - component-driven - - process starting with atomic components and ending with pages. -

-

- Render pages with mock data. This makes it easy to build and review page states without - needing to navigate to them in your app. Here are some handy patterns for managing page data - in Storybook: -

-
    -
  • - Use a higher-level connected component. Storybook helps you compose such data from the - "args" of child component stories -
  • -
  • - Assemble data in the page component from your services. You can mock these services out - using Storybook. -
  • -
-

- Get a guided tutorial on component-driven development at - - Storybook tutorials - - . Read more in the - docs - . -

-
- Tip - Adjust the width of the canvas with the - - - - - - Viewports addon in the toolbar -
-
-
diff --git a/src/stories/assets/accessibility.png b/src/stories/assets/accessibility.png deleted file mode 100644 index 6ffe6feabdc17f715771b69fd7f33ec2c57e7c30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42336 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

V}AC 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 diff --git a/src/stories/assets/accessibility.svg b/src/stories/assets/accessibility.svg deleted file mode 100644 index 107e93f..0000000 --- a/src/stories/assets/accessibility.svg +++ /dev/null @@ -1 +0,0 @@ -Accessibility \ No newline at end of file diff --git a/src/stories/assets/addon-library.png b/src/stories/assets/addon-library.png deleted file mode 100644 index 95deb38a88de416671e20ebc28dcd397d6910331..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 467366 zcmY(pWmp?s)HMtgDJ}^PEgqy$oZ#*dBv8CiifeEvP~4?JC>q?oSkYp^OL2<3Lvbip z;NyOt_p|vk*U33ES$mze_MYralqN(GABPGD1qB6PSxHVC1%(8Lf`UEw^2PHf)^0V7 zC@3#bG}UzEpNErsw;Q#}zkk#YE&j33oH^|^Lk{&lH4%PQ3E|}vx9E_dW8&V(%VcAh zni!trNf;+20xph?pJd2@zAXQq+knq5-F5T56V8ko&mNSJG5*<3P`N#3S3X_%^n5(u zAH<=%bo97)^FTpCfnIh%&%iKW^K{v+{8)`bM$O3_`t;N(#`(&ZgM;Hue48Al^7Wj~ zPa$yNTs}Zh@=4HP%p&7y3^iRwLsV3BIN?b*T~Td&Z}V7EY3XGkDGpM+j`s{dV0K@;FN>bu025@kbl~*-ww1qejk0yBOozi z`gcU@K^pUEdgCdrwS4aDG6whK1UC}ptwZ1A=½zy!j8k^D_+Xmby+9Nl|wWphp z$Bl3OLrp_7YqzhxG6c^|-@wH7 zf2jS2D*sL6<7)I*9qN5r`(i%)Gtb~D%Su9TXi$2v>-yq?-|E3(c?Q?oAaNbv!;j zX?pyedKjL4EJ2!=KG{0jEN(Bx>GQMGNqUS?-`&ytmw z-GU!7k;l`J`X@rTdg7^B^s(BP{OM0tQCWFR!(w27U)L*I$Bd_TnR0k$;YP@pQm2~M z2*z9o+yqyST4jr3`S^_Pr?_9Aoj4W0amo2@Zpxa3RTqU^RG%frMU@Z|h^yNA)IU{> z?4$;DYr{uYV92i~Y5x+oT6}}XI%n-&rYl1D=R>NTJSsVCB^}I#rRYbU74P)Qg!Q3TrKBLGmadh@tMy`|u!Vkq|97g|mE+tWMk`W>cujxp zJZto|yEX)h^6*Ic`0#N3_@Muo@Hp{KZz1MgO5zHh2Ei=GO{e@@4qNoXcgDVs&pT5|* zshT}3ZkRNa(0Jc}G~1!}@R@|>q&dp7gOv61LS5zdZ$a1W(PqDVVj)|K%ymwV`mX%@ zsDX^NHr8Dk!9LZEOy{u*PTLql5tlrEFWah-cY4%@t1z7PJ3$Uo0r?)RtmbcpWiGk~ zj%{(LVnestm!VEe3%BoTaLGGv-?_K?x&GD*AKo<9|2Tha9i{ zZwZ~0Ge0Yjz7$$!VP@asP2DUZPikXvh7z)$GAt#lGNd_I0QnQ$)1Vmd8R9R`-szjB zE;vr!g+pw93-zee$`EZcRS#~jkMBNK@lCnthOCJh5IY?Z1=~=@WZF48>N+IDISeUw zGO?Y`ONSCuzu)wWDD2J7Y`fWC4DR1=_U{j=XK8n77(o4nKNtIUCdOO)D-(#F1x~>; zMVN!ensyyI(9{>d#Q30URBp1zT@F>@1)%2&Hgv25!mk{^Gk%bR7+a3_c^&od-RBMH zzjzQ+ZpH?=ZVYb}YxYTu3?TEfHk8 z%GzG0hxW21|%B zfv}&gS4l(vN49`KkQnQ~(X46ue3IC@eJ5>`kg%#LY-Z}qJ@i`^?h=RAx0eK-9aSVF zGRhv^si@#VWn(&Ad9bkc0*2^+o@wdO@&=63ft&(k>RD`K4TuEFKLgjd{?5BDuLg>1 zX#daTiZOhjVQ@>AeCGEAr0e47*G4L^hbGCS78I~C)qVL#%j{wFNK$3j+GEcVw$#h9 zui8DrYU$>Ge;qc>nB|3XsZ5?v@6VQd@#~ajxa^R44kR4)vKDVKkh)0{Q@a?~{eN{{ za9WJY$(}&MH9U|>=y*6>bX;^s$12w@9YOax7sz)^MTGv%p?iGuKhr7Ft?ON42vHQE z%2{c)i58pD#hm>iPjGdJ)~A1->hn_#BjUVZeHoi^B@_mOZ+6$18oW$Ay6O^Y(VN*Xhv1sse9Pqie`Aq1 z+h_c9<4>sJ+V*juxS>*ndNr9i<;i;A6zlk*mfGeW?f;9WJffRIRY`qL=)K&7#83Es zLoNWcp$?9MXFLCBaqHL;-1vOS36_pw`-fa1J^YUULJN%wr!-u9_E%C78=d>!8fRt@ z%8G#Hn9vq=>lH^GaBn)m!7$86M0}F0s9#LvS_LkWR1z+rgY)(zUiTuO7|juoz;_g7 z)x+P6v0s*oT|ztXCKib;&RrX>seM+=+p+IQ0rGwQ_9AZSQr*%Hk$t7k;)Di{fSOiJ zf^`o8nrd3uiI9N#8ou(;zfCgNO<8$z{n&o+LbDsHoiso8J~GR>$^1)uM65GA+~rez ziR@W1lL^Jq?E;N$iN+?nKVZ_~n#^A$aVm;1@FV4-$ne_s=Z1lK)O z$(1gwdWP@c6z=-kca_SeQAsSS&l0=A9js<-s$e7!Ho8Aj|8)qc^*fhf{z{(XEkoT{ zxu~P;Fq*i)^an(ybtnxbsCE4)d85p50bm(sZJwohy+B(+_F6e*jnFwm$?x6f%L;p0 zv}wfT&BVEpT15U-fu0f4eNQ;-<^c1|HOYkGf)nGn3qi>%JqY$YP;q9vl~P%N+WHp0 zz*y#yv*odKj%PT!pR3BZJF1@+z_)etDdyKk(f6GR(IaBgKP1D}| ze}?uT&BobqrUrJo@tL;!*E#s`Gg;+~m;)z!rJk(#6VCo>snJW8mSQaekd!i2$-(pi zi+ss6^ENrwZQ-VG{X^BrgQGPoPaL!{t~Xa5lxDX7YFC0xp!;A^votUM{oYNW?jnFO1xNPZS%T0483WDCTYW|mQI4Xt=tvlS=w$F72Xi_5zyPK{e?^b#Xq4Hv8w9-aFFw^a4{)T*9lTpK6?almje z_M8r2Oa3E_AY)H{ueaWNizF3u{@(eurPDylBwgA=0M72;C~hAHz=I@@J{Zm0y)3T} zY~>9(IH)95qRymW(>l-2c*>ZZk$`Z)tbBW2kWvol29V^8d-r_DyCg!kI6POxMJ6jt zo1A0vf9yKvt5OSF3Xk|YA=tYNEsvzDa zSqDk`OR4H+b7uP~IqZo!mcu4t$4Pld> zSTteE#BRyg>Z!yBHUC_sX z;!*L0(H~tS#Miq;ilZKRvzlvIMKu5VLi>+sQ?xu%x^0Q;R1sWn3hWX)(Z1tB>Jv;h z8nAIw#$%Zz#XRE$pQx4iI(y4L=W7gWgE?7=!*uS{&s7l)0UT}t^?3hLc3`GytVx_~ zl6Pr`1L~HcZPQyFfg7iFv5DHHk_uq^1*-v|+Ree;EdxBNPhiY(%+ZD^dYAIH(J8sX zTUu;0Kvr-CWyEMA+qC>2Y~G0e_G_L1@JE6ro*Z~ceVXds<}lPb;OMI*%rN*53Fsc< zbjcL8P52ug#3#{Y!`ZB)eg8Z-)VGiv&;V3W;#R7yH4quFo#Xz5 zX>CbMu)s3nD#sSB3J*SbVw@KX0kj6rS@gLDoydlPVEnl4f4}$Lr11ZvkeKhU5CB}( zg_TO|5ojna|L^C7ww#U$OguksNfqYYn28DiTPm)cs1L(6<;Pq_Sz*EAJGqx%o<5u` zxGZ7@@1b#_v7)0gD{Zo4B+7(QHKF2tv)*P`AI-Jj0@|V#p5yz)EHRwYZ$vJL;jcRN z5*DU6?u5|`->-vEYyToMg^~qWGtM$taAvAR%+oClnoIo-sLSj!PqAMY7j`GH5uA95 zRrY<|+BOfBC{66@Y*h7TgmdeHek8;w{4gIU zx>=la{{xqmb=TB=EYB#6$!2G|*762pOMZ?hMVI*mc6n7LH)6cH#A{4jF6=QAB+=p; z24E>*6epzh(3JByNsG#nCMKOrPLxo?AMywHuocfAlh<@J-`-?3b_!{-t~oSo(;P-= z|5Xxpb3#N5BSj|~xzXJQ>1n<|CW~W(qunlTSh24aoD>+3RVJ)`8<1FTIQ=l5Sg?k!-iQxhr}Q8r0!ov-n&fvu&^ZuImU?q9fANw|*qJ9P z`|ND?PP=eIQ-R4tDv3QwrHF!8nEASyU1qSV_p4G?C?GWXCF{1fn*aK5mr9zz7t7;( z2V~~q-^Vz0XU_cJj|N#!m&u;_`sTp-T)qLs`_($efFWTYOLwNL1Si2prt8Uzf@5Dg zUkmP5B?-9}2O&gESBH&P#R{rN5Ur#(DQXOqA|ty~oR&F6yN7>2Oe1JskCoP={CaBA z!51_O1&}P%e#~?^d|-QG;eU0#I9O)nVUe3WWcp%W20_vv7+`Km98Ay2uOk*DqN1gO zNCXWrt1(5rQ_;bQkCE3`yfnh1T(_d~=i1<4*J6iqilQ$DVXU z{dTK+ahfRcGh|(IE)Ah3mF1G%Hu8UVLc8TjLe?EM&dlchcRQ3GEV*e=J!OLJ3?Rh( zUh;{lv^X{EbC$?hDF+-@-c`$wt-xj-)@zL4ReuNFe7NM=attGm`;^s+BZi--D$6`Y zZzC$GVGd%FHsvA42w=S=;8M`hr$JSTTFT@Vb{~1)9n1cTgaA6&4%Z;V(tTgxMEU!J zNPGAgO?!rj#PbmKAUE9MSRc;^Wz->27I(9KkWG@S^aE`f%TTlah32OlkJ*A{ic?s0 z=6{e!{|7SB^f!rgh){}s-TE27eZgUp#+^jIqJBiwX{-qKOFMmd8n*Qt%whcgaH|y3 z`QtA<-y{G0j7 z?v;41rgu=h`HPDMP6Qc)&3eE6&6~1KzOk(yPDBH70}Q^QH7++`KUDe?@v+8n1Km?O zPjkt}{P6bpZAYL>>(+zMl#t8$Rn_>_QGJ0@k8Nf5-+dRs^0^7Y`v+K)*d|$V7dD9R zr5(y514XJ7uP|pk ze9~vx)xwRylz}TxnRI$e8}8A18;=ycL6&Wj4;ynrdl8P3oOro^GvAmt0>@prOqP>0`LxG)e?JNEbGSAl1~1!MfQf~Kn~y$x5t zutB1lZum8iq-ImA-$ir}&PU$Gr}3^)JzlKTqI~L=ml&%2Fvf^36`~L;gH@L2@RzSU z1rA#`PK6~ADE}#7QYKR-p>KhlgDK{na|>Yd?|_X+j;1pjjnMnRr~Ha_t6D#BAYiClpRwN(}KBLzKeR*>Ot#^*5>3n|NsU zEcy_&VSXwB=o zt2ZBkki*>20bj+a>h(rCQ~kpi)fm)JVVjK+ew?@~#k#0fR7NIlgA?Bh(PDoozC4pw zky;YgBmYpYz0l@=%fzqc8OoBYqmniv(`5!V-ehAix^}3i5ys&8|6RGg0 zt-hen{rkfs>)ZM$xh-SF=|@tcl7hyyPuyJFZA=fTgR1Sc2Z=;5hF7di>2g9qXjGcW zU=B@HVR$)Gaex7x*?VTs(xV`RVPZ?#1`O}Z!>C(-M^=QOAP@pepu+Rs zd&neUC_x?{mr#3XKNZ1_M!zYYB~;RW|wd@FXI2i&d%=ine7GVf4*{u94h%zgLl+)I-XH z^TfOGJg{h+u~P;*VL*hmGG%seJhOr(P@BUrQuAw)qHz&f9GOyKNK#=p+f$<8Gzuv8 z1)UrlMKpSjjHHa%1j$!A<9rS-Ke~a}#UJZQA}R6nbzxC1SP%k)0xK5e9cl7ql-ybr zsarvWUQv^W9xGVGXNny<5e#dvoxDKEUf(D$P`~p;gqcRzxKE_lM8ohob{o#(8 z7Cf)3Nup;_e$I*=Cueht@>l%K?4kWs=**nRB@k16t@khEI+WoiiES$xQ_HxS+V-+w zY)xF_&1pP}d~=>;nvU^)4{qiD4{r6HdVhlFuZhznKvc4`D$k`Xw0%4->dDpA;Hd{a zCg+GE7T_k3u~4?)l91*7MPL89Edo%z>zakGv@*t5b&-^Rxtc9BE|~{AG+@eSP)Lg2 zU`Cg4#q|_nb@>9)^W>zOSmSt6X3WHXnCF6C=y^00ft$ zVcFb4p<3o04K-0KMh#Jxlg1HpM+6`&NWs_tiGP@ptXR#50!qgE$wO_O#}|rfbP(+c z&NI82ji1;rCyIfBbstZRr2hl9t}D{S>G8`a6b&D{L%UWKF{&!9tdq#L`!PR0okYn3 zzHt_b`HOMqYf;m@3#Qir0SMK858&1gB@p*+qnun5OrlU8VSEjoa?l?Jej@41<`!V- zJDlpa{5dh0wap^t1r~-;HPL_#bTzduHjh%%>gNkw_oZi1OCG5oT zFC7hnD+|Nw%1_zj#@G3CyQ5av)PF3kTj)zGTc|UXhqBm_7HF4i(?!~9jQJSK?9349 zwd*&0sAPdLbTG*BGOoWHrqihXlY znXJYcakjd>)5EM(?-5As-H4D1Y%BzX+6&x*_jvEQ&WnS%l*IQsmuL#YgQStw*If_M zLQ+VRM3F^ph-Ts;|ir=vuny{RP*%7X@lSt-rPluGdG6G*P zRURZiSmEld#K$yp8cX(rr%XPEM`HMv&>H9^OYRUw-o7yQi+IF7YC~ z#{X>CK9%$Wl=;6xlj3R~Iw!O1`gQyAH<$4l;|niv->K!LV|{mgYxT^&B4sZdg8k{b z>i@*IN>t>%=iVhHQq5tmk!$w9%FZX<5sai{E5w zx-@pIn$%c5X;ti-$YzIoi9gfJ_CL;cZ%_aSe?-fyrP_=SB?trJ>v@5-png#$>Z!a@ zvRMMRDI)*JLs%Kmkx>zW2tdxwuaOf1P#ca4TKb1`xwuF;xJ0Jw2RO#Xe|P^^RPc~Q zdXag#3=PDX#rTs?>+2|47F+(F%~q*07IJ{|H^u;B3c^pD@)M#gawH~}EL>V0B3IQ@ zA;fsN2(r|sw!=&V=hpOre4O( zy0M{Wt68_ulUA0C)pn1JQjH#fVR|9t`PH&b48;s#6~f6Ub%J zfam`=DSise0cE}?LyvzHRsirdBt?f;h$46+4EkvgRJ21Rm0!?B)xcZ#3S-$sFMYCoEmwp4A8=s5k=i*v>p zT5|I+EC`E$=i2nQVxjse0q4>wc}g4=!{i?Y1mBb+Vup-XwY>y!REAGzk#9pIsd*I8 zFXgE4uX3#4l27q`w$D}wP&ElG$^qGIRfo?wKYTL(3FxFL z?&ia;Qhp6}nzwnq$Kf&a$%_v_`Wk1d6K`qV zT>(dh!6H~o-#S70{*Gbqmdr_Qq+-oB4_6V}v| z$L47b(H&^_vs=IpBTo0~&%{Z=7!CEA2tla&&?y9PiU$-`w`Pqd3z%HDv^{57_5V$3 zG|JK=v~w5rTZ$AhE}0V~###lyhDEttEzsZ2K~G|JN7xqRd^cc8Wj$@*!C&X6Ly$v?^5JsXEakuT5mHtS3UsgH zaK>g8j7_(ZUQ1!>rZ!P{%0$dP{8FM)^1;1y46d*ey9y#JOGzN+$IolbesV$vXrPVW zbvA4BB%__Oaf~Sa*v2I+f%26NTE$3)!CG^kIlU{a>vA}YJ?Z4*DPo__TPHP zC}56F?c+mG!7UYo33lgBpgK`OO5hY<|g~oH{YWGA+Sy_sqF@XuAT8PMe+=E^W{=cA= zqs;24WRT~K5r9HW+wS#V0uV8ZF}pKwD%7WVRLmv%x9*L9z0y4fg54(*^M|92Rwqu@ zCrk&(x>D9L+6B)yKl~$hCseR-`CtOO4GX;*qcTCcoeEMZ;w4auFxbYC7jncK?Wxn8 zymxL$DXE=0tk)B?TB^~HT|vCTjjsD;N7rg+(-|n!W=v~eOmZJ6R^%!=9U`Q%UkC=Y z7Md~Cf4b z0}uJyImC3YZ#DdV3BF=>I@n%x%bzkH6&M^i8dO>1rKHiw7WW5dzd z@&eagMZR&w4y24n35B~LpzNfJy|Np(MzCjbe5{yZa($Mv0mj-^IfHCcCU0zpvv#S zzMkcIyc~T%c_-i%(BdWi2;pR*pkN+0lI;Z0l$T|j6sq;|=fuC*mklV0H{xnd`Li_{ zpMIktmj0JurtKgR7S7mYyRU5F1$Q?qRRtj-ZHi6VV#SXvho9{Fhb!H{c}ou%A%K1J zB0mS4kiHyP;i%;iHjJbhyP-^LM<)c)jtVKr>tg`{)g4@0LK66wo{dky`_NUtw&ErU0~F~+K7nSXv^<5f`HjCM4wsvWk&Y#GsqT$ockF-RwFWD|8>3pGQRDg; zS`Ujh9)#u}Hq2eghT1aR!OW%~6)y$muMA$mT#c$zJv67_mNMzA>IFpWCrgvTb)A4b8~A^DOp%mQTU`P69X*eE-8uA3 zQ8F*vNPtLDE`_N7*qfx0yB942U=uwUDOck?A3erK zPL-3KH<31e_8y;rD-s!5L+j`bb&HMQ&u4lApcvK03lng5RmCwJ{8h-*4XplJ?Q!4O zK}oVUqKVn%eEZsQDGm~pY3Q3}EU_o%@9nK>a%5?@?rQrbe%k-L1ZuQOjimEMr63xJ zh{=@+wQjALG?+rk(ynXdPrZs~B;TA&GPQ6BJR_6&_ZCcLyMMz zJf@ZWCJLki+l*GrxlC-zhla3p%^)n*MNrjbU3eh$oXt~h@pT1m*N{KPnhu93KBPDZ zFvY-6WG$VD9G=(or#!q0O=9-&DdvJR_l{>;Rv~S@Qm0_pnNnHNW6F0qlp0plgK2F; zV~ieHa9#1ZxV^HuUQ@<`x1G+L1k=|@s1OXH z+DG2b7tF4%GwZ;%vifWk&;~nRY?nQ2&nO)`FXP793_(-pkNdNSi3^!89Z%lZM}lz$ zWl;=y(fYJ%G61iSyUEIHa^B(iGUp-HQg0E0%0k_CLWW+X^dH2RxP|H8z9(pt;m82T zz+ajf@Q}7OWS~N1vGxbP4?GvI+nyN8mBjAds~+u&spZImU=dp(7QXjg|>~ez;51Xp+5y}Vv>(Ad@AVe{TO2wLT-1FbMR+%;~d9q&6Td!?r zf|3XTJ);k@MkDmqqwVF+vjMAN8P%h%(__9N-ke$KyCsKJV4KCQtxV+p-%i_zCJh{% zrF3w`j zpLVWgum+QnGNfZ1PI1Abh%w{m9l^5}_t+S32_z=$82Q#L)ls%xZf4Yu9s){+p@wUL zYdCDZYZ6;_fi4H6owHt*$15l@ENpt&&dYWfzHnh(uo?6- zEvmaYs<5uJ>jD&Bo-3?n+Fgh)UUuG2cEM7#(k_-xDtnHjxnb3^ghzY{KrYZ$R zJevuPeEpxPYLX5A2Ug)Y_9%;=x278OlW*xtXsnHiniQ^M2zJbD*41w+F-^s%Ap8$>X-G2(q~LO8FtlRThCH<2N54!IGR(d<`t|37{x>zH< z$JPEgrF9^Ho*Z(lE`?BK-a!E2l&27w!YXocI@|eI}Tk z9%jP&bHa_VYFI>WZ*D6%JnAC+#RV>?%)Of3d5v#hX3mwh~XA_&uR(oEOshzE|%?< zkC=+RntlcK^2{xGKl)6IE_Gv-P&5Y(+gH;-wx0n?}RfT@R zI=L)jr*g*bvpnta^pprfu%yO%2^F%FAncxo4?*Z)i{lkg;N~4Wud3Nhom_lYJos1B z;I_bX$a<1-&wCu&u2q^}`Ly3Nj-o<4 z0%rn+^1e>y7kFSqz^QLDNyOQb2cAPt;$s_WxVm|q3Gg_bf`R?Ki14K}PQL%)7H{mb ztrt0};qnaxwD@UK?CS$%smKU_WZ{1ONM%x}ukFL5`Yf!D(K`Rk> z4gV~I&^*S977yYLQx+bkgLFXzMV|Mof!;)TlL(d%6Rx^{`8Bps!(Cw_?XOXx(_PDv z7yo$)o9o>SfGJX+%rYV=1eSWsn|1L}h+&iz?sfoE&X~^ol7ci-L5&w_MREHkIIF2< zq{X}nyh&gkx{-?R`zQ)rpr}*60|I?jvwYjj^mk6lz&^@zOTU$2EF0=Z$n;lVYN$vD z7D@TVTh0hw13U!C!Qz*ygRjA~5|uvcS)0NLo#E4kj|ayDO0(k3|B+FSzIHJ`-Z^Fj_jH%SWhucy z9@wEn9`6_rq~Q4ytW)Sm(vn|uFyNIw8d=3v_+^W+*$5YGFpt6zxdRIk;R_ClO{(dL zX?4l5OisP29HkwLKdvrb=}Z z;XcV^8Oc5{Ju5(Js@;6Z{(xq5{nC}YRI-?Wiz88RDSg+diT&vQ?a?i&8`OsqD(62+ z{BBlft-+HQ5X2%6NJdIDO#h=>NDj{KJkE4n)ovmd7uf>B7*vqC*r)P8Ep70qwxYP4E75Z@oKoju4_);t#j97`ZfVAUU8UGncQuJhT?{|DIEI8nN zbu>m`kQs&g+5N7K?!R6SN~yePOb0AY)oQ0DDk~yo+${>V8AXyh--<%ye&cT7``xzL zWefz7pq|<$9GNEg%l&n4S>SPwUsGdIt=NAq>5QeqK@3~sHDQ8l{a?x}zgJ++O-_Z9 z+ZZ^6eb=jdpO!D(_@ab?pk$+vCHXr`VDUCd&jF+ltn8mS%*G~d8=>9M%>;38{)$wV zpPqS6r(U@e_>I{A83rfxQeE+{UR-7_$Z)Hnes6hprlO^*%q#VYQD z27(d=+mx;$wzXcf@E6gRKNz zhp4Jj1dWKa6@wgt*jNeBmBVN9SW0YKQ^L^p{@1w9_(pVk7*)EmZfKT%)Sk+JDQ=(eI1+0j$e82SJ)#5!S@2+szznL z5d?GcN4;zLDHs8zH^}NLQ&^LW>bWY5j@D)FPAs@tc2inra+z}WP&(j0N{0)dRh(Z| zzO>xY%+FNU`ZH5b48}ka>_L@_LiVvzmSb9lu=R5bz-Y0(zXe+;#SAsHvV{Q-nrTd4 zizfXt#skLyzMJqCR-Njcq#?YYmRNmsrf492x%e~?6&SdWH1Au%Zvu?> z8KoEK$;$r1>E6wW#_RRp|GEMrClPSy7rRTBDoq{GlEmfHfZCFn>7JtNtx+1`Bf1k$+foKShAH z2PFp|wCxyR?3p}EDr<7|4)W+ggu9E9a~|w*|TTpJzxULqoKT! z(2*1(Uh*6kTMF8{q;H}H$TBzf=zMNnV3y$!Zdkolt13Z>0k_c+kH;6xPs<)Vx4%s~ zJ=J{RW>B2NRFSt-3YHvi5L@?{)qpHtvJg*(f;vi$fWo)ft}?u!7D6EYUXM+-U&=v3UQyi&+KyA}7ijkUFvFOEvRUV}e8?fp zE|?4(fk1XA5%PVhAcNMAKCy51xsQrAm)tC5@)>SJOZ1o{0=kO zNH!GIyNEHEHq4LdRvJi^2zmo5BPELiNv3fG|5V;!dlL*_a-(z9M0Ly}&bV~{@bVZF z+AM?xa}~>VDt=*b-TGW-Mf-do0V39u;46Xdtz>D$9yU zb?pcF;qyV$<#ixA0>2E(hCKXIcF#S27|u7=blloF3!OYKrgdiA(19pyOxvtorv7mA z`bzb(0Q~$T@e%(lEO#*2Ebm)xVbfWVAv;<0$!L$ADD`^J5s>Y4;9D+?=P+2`A^L1dkGV4u?En8x4-{TPU98vgSx z=7E)8O?s7PF2Mu)@{N0^v{;1Nu~3?TgfS{Ro38!2$}%)`$Y)drTV3mDEOxf4DSm)S z7L~`HpW+?QmLF9%vMlN6eu9+h9&26hP=`EVZ%9xR+En|UL^ZRn$Y)4(VT<)*LH}K4 z#b(ECWNqQ`1T%>^L$w%G({ zD=2ho?^PNWjbuA>+vBcR+D@5$zx+_}RsCyS4p?@SVTgpAf|ILAl#YX3ntg$@8d}Lw zg^wVRvw*22^+~!R2QUzy9SqmDNH19Q5!D~tICFsBnPeI1X$OmWu#5GyRa+ElA7PC z7xB-i9=P|1)(UQU3G7D@j;@FPI)RnvBi<~de;^rQd)>tO!K+Rc&58Yeupnvgkl(v@ z)FsbpN=PRI^1i0bx2ndRc<5OLxw9y{2i#^mcM1bJa5e&rcut>seQRj@Xvt zbR-4(X*cw4q2BMjqQJ`WUr8!dT+~pzpI<_SAF+9aixws27P)`;Q%Q&*c#~9$9s{s9 z?%MYm{p6|Hkp$}8m(ZW`XmEhDM93WUeHL~jwE8+^pa1~+PHlHM&e?=nof3d9Ih^=(CVak9t~E6LX3;ERzR&!|ak79>%{#bJ z9E%STcKyGY`s%+X|2JGp8U#jnkM0-)QIL?>LxZ58gp>lKB$SeFrC|>!IYvnePEe#9 zVF-f628gssDxjWyzUTaK{(vi4N9oPN7R})0Os=0xl;qtTiry87Uf_1-oZ31}>O==rnJan+FxTPSOL#3-B3J!1O6V>L$;QWJmL&-$ve1^PA$l z4G0U#F|Q9J6P^Lj?r3$NEroc7)?8Q1h)#1edPHyB-%))xJF~c)Zr!XJ0{ishcqDMZ= ziN5t$@TKY;G8)&VMh^&)LK}IeY=Z|~16KcTRn#@q%*7Vj&icX}- zd}S>3YFRLoKer0fyO$8;u6kq9El2I`&M;wpmV^vEzXCk+pBB(D{1TtJN-cH`y9M#y zQixZg;{K}uh3mIzyr5RLs0&vR3(gX1N~a><<#W-@ZWL)^qea&ZKI5t1SMu-C_m}IH z8Xnu#@1J%Yfc_pZIc*ZK>mi$7=-#@)f(lB-RY&785yUa?&5>IZD56SYGsZWmldL4? zZIb>!AZqRDXlYA1Ge%i#w(UR@}~9{S|>~N57W(zGZYT zH}?@r-R@sE1~U%j6Mv-S?de~n+xzY_+%JU&#yr;)0lihG!??a7bT0@8jYWm3-I^G1 z2GFev(6>@D86Gp+8yy{TIayd$rL__5GH4&sfb|%ejLL4MF~oOV@=!t#VTzY5P3D00 zdeD7mmLd|Gb;*vbv4+*C^qG8uN*M)IWNB4J3Ln%Vc&#t*_K+W(4BIzi=(k3H@r?>t z>W3k^x1y@+pJ9>F*`k_tnz`i9zeohDN@A|K@?#kjq*8&p}-P zqd~PayuX7(O^~t&;xW@0&EgixE>S3X4V^mGY=ilL$1)T2(AaRYYRtP!vt719qE4uG znFMr|6PDwe;YJ`kXG1MXv=#BeZ{HxUUeagNuL#kNksc;NS4Tsj@?MygzgckYF@dGN zPbR{G$TDtc06TB=wj_|$I4NvJEO?i@ha|V5(s<#Gis8Ju7(LS!mN_yci$lG58Xs0F}Mdt9Lj=GFa6kR8~o=#@c}2u z?0qDehXa+_e9_0@N57wV?IAwA`=A;2PNI!?lYj$>;|_*9j1%I@UF9$$GdDNNCiK~Y zNFApI2-DTFyJ`Lzs(D6HlWfTF!(+VH(pxdX7byN~5 z-P>VesQ&ZY&nmvkUJ%LM#ww8QaOalC88PldO1Wa8^mN36&G0TM^rC>eB~ZUOjS(Gi zeaZt3!Ahz*QFh;+8Z2Q=R9JZS9rM0->j6t?Nym?1)9$Si9ZDcFKl?x(1Fr+?H9@yD z90mB-Q?MITNrEPcflLVt^k7~Y8fiF|??7nEOV!rEeTAEAV+SP0+wdS5*8_+95UH($ z1%+ryb&dI}I}aUt4&1z0dx`@tb6y+{TPNZQ;fzqDk}_$Gay2x%2=3hCQk=GW=Chpj zM$F)D|EcPhT`F%hv;RU?2qgo^J-}J4!Bb#c_z>CtA{F-e{ZGkWjETknQiuz?t`dJL zWRLAAH_i8OPzqBN@q3*v&~kQU#`FxPf!?~-n_PdBM2bGZa{ILi-^T#jK#LTUFISzV zE$IR3fUIit=30$4>#ZcC=OQvoko?bz&I70e52ku($t&j~RL1G~7LGmgJkd ztr4*%85T|gt^UJ_rXf0Sr?lHWWPnrXI;jOk#iwd(tM*qr7IyTX!z_!h=cXivPLe2r z-Yn3g5#9lDl|Jc<{@CTqQ&ri$ca6$1iuUUi(3yl-bv7%@I4he($Uj`)77`o0Wl5qM z+~eMlW$PyfNX(_6hspG7_9yMwWZZ06#1*pt;lW^B_#5~1`c;81e@x_9Y|aMI=$T+i zT4V|>%tA>W+d7vUQ!$@)IfZz7CH-`FkgYM7F0jYZ%So0&J^78+`!jl|v*jw~rPd?< zvZv5S&?V%jSQV=*C&*gAXmb7zmGW5{gMTz@sXMI5!6)QVe+A5dT5NahI1N&O(P1QD zCx(zHW;=cIINR(y7b%EM^)HIH`tIHIN{$mR8p`Z&dBuO_<&NY2hYPO<-d7(S4qeY} zr|V=l@C=<}gf@z+Z07oz>>!nbFi2RTtUwc6uzP1TBGh3i%OB#IeFMmY`B>Xu|A*7# z;*RXagMS}x^Z&MON+J*$a^r4IUI1q^i%1Ddy?4Ulv^x1a(|4sIPMY0)>I6xLUD6L zEW}d7(OaE)rOzz^_hOyYvvR*nvWndZ?}l7$hGT=I&ifiIhx0kD6oJ5Bot8lg;siTc zJTbjmzH~f;3*(QU79Zx+M}Dn{L;6T3Srx(pNT7X05ygCBBIeau+U;kgK%djoYkbtD z!@tcqvXrFab3&`%cG2{DKDps=z=%F)N7FYFR~au6{qFv_Y2RN%{vz3_3S^NqNsXNZnDL(FrVHbg%~Rw6Z#du zrN_%kM6b8eQuF%{UQ(DHfa6c+mQFLL1d?p+XBDp`B{bYF-B&mE7DT6H!5KIw-VKTy zO{Js!nS;GH=6u(6-D4H2!rS{@GE!K1j1oF)d|$qZ`0jU?BmT+ZjWlNg;M=>w^fFvG zq4ic-jHoTd!RBl8EfU2{4etuA$m0pGRlA1XzZb z6v6kZd6MsONYvkT)yowDJ8F+4|CCS`60Db2Tcub~2h9Sf%KzRl>>!)P#UFY#BU1Ct zO+s+Tk2|}8N_*rbKa3|_nsyP!JRvlZ8?SNAYuZk9oTios3NXxwU zGP3JkMN_``K{Nr$c%+t{KlU>Of#HX&{SZ+;|jiXFAM%+K;;Y;i_%#;xSCbithlRmkXJso$^{H3E^g*=<5?ldfRv`p z)SIPj&sT$NT=mp-haqQE(|ZUfGXX;*$6ED$v!KBzqG0Q_~UD10~6<8asK7LQ}I(*A1~q(`iv+*jvn+X z`cWMF>e`c|t!n$F4~5+EPe+IEuiBPeIBpkB4*>GZLFoE!npa69L$_9iU0)ebAqvv_ zDW$883n14@-J4fKp;hL!6oB<(%Euz`@C?g&7SdHE@D7>evAM-}OUB4Jh);bY-TM79 z8wFT)zF0LGq355B8(iB!@u{U9OyxnbF#s!_xg;crMQ-k^-_JO zO^y%hANiM6X^wf_a0Xf<0e!T5zO-6Ytvp84;DLwnBZwjFV-v;onKDnLsjR%YTSqL6 z87jP6K@fSQWN0Qbo19=UcOdh4nzq}^thr&e2)j>$_PB`a^j=Z(vtL{%3hrEqj|+Rr zkp?MIn@+m7+RLZ_69!}o6-?4eIDYR_`Xb@0&*+2T4&Ea1%GZ`ZASN}t0a)gDy+)@u zoeH0!Qrv$gR6VfnP*oQC=(U`9^2R;Sd1XNtZRH`oowcrio)0Gno%W6>foJND{xI-X zJ2@Ya8V>QX_P`tj2yqn1((X9 zZ|41pRwY$_aiegIhk#HMUVK0PF%M_ooBbAkYXW$aA z74-NycSZ_aU|sZsP7$h4T~Y4*Le`mExKbgtE5>i)0G1kUrG8e8+VMHh$C82X{c5_m z-nI(rpeBv4XD9a4y#6ZGO#@#bN3W#t!DQ9DC5i39%{5bkjv?#EJri)^7h>`g24G}U z4f-OgjSaxBuOVFo*De+=cvJ~-vDT#dGB(Wv;-dwR!uZr0l$)WlJ;TCK7r>T(zbZom zGvW_AW{0KZ5gL?Sp| zPcpvltYGXgFwz;(L&FqCn(T(Y=sl;L+oNF%jvVPf^Jujk^ED(L{d5l`6XUnj63X3} zui8d#Z}JBR`cy<=q`QX?#3g%7?%IYl#v$x#!oiY!s$-&q_jZaLZTW&6Ep}Ap84a-z z2ZLWSH*tW1;&$N~xPfo|FW-LT8&B2SS&M{~Prt-CGNNzf;{^15qfNCLp>eUUbqd!I zDNZpJrVrV(2r4W8{XnB){!G_ujOO*zso2?n?-_PzNr9dlt?(`y`^QgWaLYwQTkDT1 zr2oi5`ktLi@PAttvP}cS6CpECqamSI?_#o>`FOEoL4s3ZQB(3*8bi}Mj?))?#ZP0U z$F^3VICKqspnk%<=78zNkf`35p@v%);`~}~&I&JJ7}E?eQOZ~@!9dNb>1PvDF3%G* z3vWJv9atUE=SJfQZt1}=wryIZZgh5tQ859b0E-U;8)^feY3{vZEB-HPI%06mEXignB92-&>_yvWW*~l!dkdx?@T>KW7hJ4afXze0?GfT$1 zsAtTYBHnCI;I3IwZ}J<=yL%2`z+8&vccjv68Bss@)4GD%Pl);fCl05yI*nxX=iboj z2m6ykP0XZ@s+jfQISzkDLPyT}^4D^HC)_3o(0pGeP^j|ZDVAr#@f33z(UNkpIDQTI zuT`F?XLFH-o)>Rg2UX#s;NTd~VG44)q<8pss&F;tsL$!U`oiA}wL0`9 zHIl`(Hv4O9T+N5ZGVD;a)wM+2ql$-l6Ib5HQT&{jV1FRgfdHQ*T9JqArHU=jMB*tV zjr2|3I|^jqQ7`JX1!-N`aGovq(?gR;ytkqWgu8Qu{S=Kt9X4*h;?PgPt<3W2+@l^p zs0uU|hgCh8gjDIcg$f4f*0AVZ24; z-yX;Xh%0F&6v2C(QZicqocY|oS#6r?9*Y(I&D(K2ONI`o0Ys8o)m2%7FmC2g44Wjb z5_}F96BFd`@Z$SAF(=*0OIk^aF1=SJUOal*c{{JxXz}=GLDqY{qXP-;YRxj_RR`|^ z$n0;6c%uMXEydt*p_EU^8(e~1%wuj}lQ^N7Oalio0rU|@!S|80mW-(ER)u6`uA-rq zTxT;)jSLGW>5R-8JaQrX5)(`gBvY&JQX|Rygz*(ySaQj?t;v|n7~F=zRgkuy9xP$Z zs}GHatTPW*42n&0?Iw!93;Nx+mHxJE>o|E7zUyBu!2kWk;yShN&-A^=urPOxVla#j zgJ617hY}z>Y37%JffaZpOOYY$gb|8)xaLox8hmx21Uq}W((c^Y5$a191KJFG*{_zt ze_Xhd11G1|JX=Lo@c}fUyZHYY!~Xg(&g{6`3sVHM{ma zz9~-qk|2S+`&oEQacJ$olng9jv6<^ltA-omSZR68#S?Nh(9@KOL(ZW*Ky%~zQ|4|- zUX2(A=bkjXoaE6$YIwf1Ydgne^4l5>Vl(ON&4q-Q{4Mn*fl|Pjk<)3nsN`R98MFeJMf$Fld6O6P@vm z2g7cM`%CM^VLaoG0K1}4?=WxO+?K#!@j`;z%J0A0y+)fgF|hxop9}BuZ$x3a-&D92 zs6q+=gDf1MBMv(?;dtvwLQbZ&{TtC2Ic?YUb5?WW6K}I6M&@HF*J+VOqC2GEslvUF zjh#Juw4GZthUz*LDFv&Zi!?ra{QLO4k1Io4G)a(a3RH1NHU2x>d;p2mGZ{>k(A|Ck zADzUn-=4zC${Mhv$=6I9D5Un8y_@+IGiuwEKNsnWyS z6l8hR$0JgMYN>$0embxSk6li)5v^?LGCYGCg-1=o8FR=WZ5Mi{G6+F?jU(7=@hs?KW1-5CqjXt|{1wXm?u)$m^e@4o1qFiTBrqoQY$kv4O=O@^iv1|2BD zHz5qLh?Qe-`!lkNnl!a6*escw*O1N0k5l6A4w-G601 z{P8B{zOTQ&R;~ffE$Sx@x3q3un(@ndf+Xk~0)J-b-lZ}~}>^oX3m zhYvscDh6YVuxFaH4${BBf6c0eDK3_iKq1=1=-d(3T8XwQVAE);pg^)&=`0!jaQO<+ z&%WKc!H5~{+YzD9UIQ!1vvkL z8;YWdt_)>HtAD$w89Y*0KhUzj%o#>ThC&c&H(om(%*N$P%^K&gCxIksdVvtn9PEun zR-U$LP5RLpqnlQftm#N&N>Gi%gC3R+)tq}u$^(E!}hV?&P7YLNUd3#ln(m6KXqQ-98*L0P;`gF1G<>qDULr90Ws{7Ej1};a+OG z*NYoK9|T*fL7CM)5-2b!@S`V%#q>}&DBGs2(#~i`mv7F+k&k4o9EHf|;Ug6ULmscS zN!5%A4Jfw}4f?jJGTRF?eltt5Qqf7u4KKW2Dd$lbic|Fo3X93!r0=-~4tV{lE@?2D zLU>o*uBFWB%Mf3HEWJ{8Riq6xPO}>{TFptzP4Z!$bO6H>ta>b>?^QD*94$?)7GC*! z2MjxeN5!F*FR>;8W`WaIqbJ)p7PwA@b3Vr?I!gh!p#fBY-<1q0E+nl(ffil&RtCvq zYGu+Zd{XXi&kOaJ6g9!yuPHS=89`c$*9BBFVdP*^^-z^?pm|p4+?0I3ws=-_W1XX| z=X7D8N$!SZFvJ0LDD;A~cC`cs>1%*9sjY&c*+gr1Ew}$|FOB8@_|lfq^TU0Ymg#I)#?yJ1Mn))XX7YJc0=t6_ zM7Kr&N!!BTbgGXJnzF+OH9kQeobS|1)AAxt2fj0+dE30#5p1M@aZx)J)kOyN%_T}d zGT$D0>gePKWV)~THP7ce$@@*}QgBLtY&!Ri2;sfx7kN;z;PnT@C*r@N6v&@biF_KT zSu6O}IQ6TXc)AUUYx|VZ+8J1XM*ywS*2tgvkO&b15- z?0JELcY72d)0*|R{JJyaAq2+OkGdoS?n|(=Ouhd6QCRO=Umho2A=*`Xaa8GeHI0XC zPpYYRnD%Rdf3~?1bar-6d-}ak0?zmFd_?+)9-58_azT8k+W(UgJF8~$=l2_xw*#UH zSI^D6_+3js{(`Gj59}~fp4@I_+R|mmQ``{0l77JmDy>y1a1Wwb?aLa)iI#1A7IrC? zLZM#!Vs{)hMb?sgK6-6SS>0b zk_=rInr+yf9Gh`lDV*>-&A;Pbl|xYGKi1cesx!)obLyX6+io!X8$7OvrI(ufaAN`M z!BPJt$aCD=YY&SU5^?YNJX46(0$eWKe0#E8%&_U>unn4vgt=5Y>#cT1>3mffnAj~T zBh~8_r3ZE_?6YI(n0Za<3vP#41+9mU-RxB!F64Klt04oA^~7;Un_ujLsy-n`P{K_I z2+dYThhi8LsZ8ru=5Q3x9SZSmrIE1U-TwS6xFkETUcyV0#20BU!q?n+VqdJXzT`g* zPj^~NmCKC%ue1*5?-88oc*B z@>R`pT-f8qK5X;Dr?>bxKF6Q#SIrM0u?zlFpI-^?z4a-ddFf{YG0830AQh2&_YMy$ z3?V68G~Q>2zK*dn$i#)+nW^6oW&hj{mhqW3(w8sj&6WgnchEpg(5l&k5HWjUgE zX>EcQmfX2H`H7c>_4{Z&Ec8kgjN+VBmdsPo6>3~niU49k^mnBv!!bZKcld=l6a!bs zs#v97uu)&1wpw9XWPQlR791w=_biH{xbcWJa!ZsZgkNCpQOTgU%NsbkjVkd(06o<1 znUy1+Rc3+_i50Qrd!bIs`QQLXSVm*t(h&X59Zqz>Q=zMY&ojHXE*d3%Q-dV;smEcQ zQR_N~d|}Kg9hn|O70L2TWW8b0XT&F&BX}8s`UnfV$KrErB+yYNbOg^Q72*Px8Qk|= zw9)+M*A9yfB3WVs^i?03*1Vm}kICNc81eK!WP!!&ABfN9@S3{gE0%{A3D(hB&`G{| zL3BCvN2qEwE0RUvPnGD!%jtzy(IlSEd3kUrdhgy!J1FA}uXv zj8@pwfKGyh0U~ol%1M>6*Gsv4m=~zuCP&-C+Yh^GNP&u-<`0q@GhRxW*^hsy()e`A z>>MdY{Rd8B_tv{c1)^Htu&euXlm3aD@jA?O@%b0YFPQ}|hG7gpMhimsiL)TeM5}P6 z8<@IzL_l7)DQYG&1Dx=wL$u@&^j;8f7|atqHeD&|y(~g%uG8l+>_NRd4~5LUQf@jb zj0SAx)t?<`N*<QyW0;;p#Juu{}1-tR&b5N@;^gw zzrT=1I$*SsSky#4oY?q79$t!UJ6#Ofuq5{IT{5Gx;C-;%6S}a1*h_Li|4`g78gjF+ zHHP29)>d$FRXI@LnEFolGp?E+b&5Q_((=)`J}!XMIok63Z(E#>q1mB&e}$hjLP^*%XrLZf@ysr7rv%lR4>J`!zd8BIZy+9a zIjuRB{|qka#(d34ws>c<=vCn^^Wb|*a7oT&FwWwfVrHR~*Y9agIPPu5KAK3Y72I2* zER6+m!bmkGmxJd2+}{e}x#Lb+RMLTw~%3C?> zdJ(I4VF)pY*NZ6r-K1qZKum!;^+bQKb`w>|f6fdNP z0vhk1akIxJ)q%>1&5z9gTzXXj*;+uZFY*M3d>HXC;@43UOsEE|VgjD^OO|kYqbja& zMs0QB$brjs4TD=X@fVvLcl|Gg%Xk_$<`TP@eI34<0Ha-(_gzP za4nLyKl(DWr>kOrkO++c?kyV?v8`zyN0KRw;8ue?DS$e=(TjMkF`f6MXqT{Tv+gZr z$bFa2zBdwczx>9&X{wl<0)&O#f*zQ&Sx4hJ8jtEVD&Ax4yj3k8@&s~>jzbaO0Ld)V ze>kJn1S2<}S6Nt{y;`fOZJ`3UGYZ@ls?RR|;1-BatExW(7boZ44=QmuI&U%Cad!p? zT$&s?l1G^FzRt$SO7LAp&uBP+8;sCV-M8iRq(H4sTQsDDrIJ<0)GY@v_$00h(+7Vs z5DZ38uP&O(6mQYZ;cpzM`_#Xd&c}IPRdI~GIX<(hQWUDYW*_&d6A9B_$o?nE!E0@V zmSYwXPy7B#^yDt~Nx1`-LOp`BJ@1FCIyTH$r(CTL@KV;Ulpp5WJKg*gxgyjsAe)Ay z0P<_Dg1%LOwZ!GMdylUGczs_g6Eu(rbkisT-!66eHv}i6tv+@RL-BfI?v#F+G2~Na zWR^+-8oAGMXO;ufG3*hcj3s09% zNunQ=)B&0dSdF`?Tegkh(l*v%>#+<>o6uq5wiXS*JAY zR{s+U@K*ll`G3TUBt@5nWvh1&k3DpQLa3yNca2Ln1q(Hr)YP>9hPt};DxjDPxUfVQ z`w$7^%CPgegA#n}dZKf7hwq@b~S+^mQlWvZFnb zFR_-{=BzI>osq)k`W^@3hcKgeI?zkR9mU7ostJO?qq=Fk=>9FydW?un0!?`K6mBL4 zVhX%Su&b``=cvr@!4Jm1v0L61OY-t#U_|%fkAoY!CEL^_la4d6#&VWqSF)|94MKRJ zogAl+Et0Z%kXTMw?bGh9vLXi`e8m-5)4*ZX=fF1=opm;!$8y9rw%^(irhXTC zz!dQFjW45yYzGUq^E@v4r=U|#|AQv%`=Dj(<(bo&pmEb+52v%BIcvN0r9g$X$+NEW zo)QAZ#xX8>GB`{LoV~Muu6Zb9w;%uIAmwkwogmi3Y}x~+u%r|l`qUKCf%~NR7qR`4 zck$LP`Mq07FRZpMtB&snJLg}25b{`!AO6t`YrI64`(EunOLkhzW?OY+ck(ADw?Tzw z`Ikbd4adp~KLpR6*lyI9wK%T0qM?=JLU#n}tCd7}3Rf?=I(NO3NmUH1p|UUI#~Ce26P6?APQB>ybAT`XxtRRvC9= zc>S{G4n0S=m($NB_JV|Gf9mqe^E&NbOY_L}+$xXgM`aBlAI>1`Fw&nma{8^cGQzAJ zZsPkW`F98O2jmUyEx5IA=1@Ht+vr4|!W3WW^8BrO=z<)1o*hY^3F&Lkc&9lPDI-a( zrAT>jcHiFJZ6G*3{_mPE^ws@3tbhLGV6ruG zv`@_LOlvo-ka$1*`frN?>?2+!7*=@x=D}3x!)@O;2~+L)bTE4@od*xMQ?4Hw8+l(L zJMHegc2Q?eJnp0t;GF^Q$3R}Vv%9m&E_^^%;=s=ii1ht?Eu|OfseN1bA3s)KqPiYX zk4ELq=u~9V;XZ`%9##33!O74C1$1ua>|}Bw!ExD4AREu_$Cyw^80g8(+PgAilZwM2 zo@XyK+VWi#eOfQVmhYY_W_fa4PY+9jQiC^8^yF6!qetTneKrY~%JIc%V%q^%XUaW} zu6|8meXt!2!<=fG`21i7EOn`NMX9#50+qiRNGz#{4}Ze3F{x-MMv(^wkONdxOx|hw zf1`0truB-*@belGB$mN;{aT-q!yR_~I`T)afB-J=)t_?B9D?EbR-zjAI6bVO=@A1?;C0I8u^-Yp00M$yqeJ z&e`<7<=-U1U=WXBuu1a|?X1Z#2&o$wt|(mg{d0YK+-AFq5&F6lQveI54Ygv3fvgpN z2_5xA?t7;`*Mq6fkM}8>_n~C?q0C|Raq2!&6G5_?-s=_DfZMehBoMCGO#YF=l(Ho^ z!fgA>#QC`+h2p&C^~}Ql{eJaZ?cra-<=aS(i9X9DBVJ(I^1N$LwTGs{sGaG%D2jlb zcCE;D>=QkKtByN7@>RkT!~C^HqjxAdkf_u)(7iQbqmFO=Hn%c^%RG8RZ0V0$Q?3s| zuF_tCr6;P#lY_gQ!~0KHOD07^gg!l?b_?$MwA8oo@qW8jAf;K1CdeE6=3-pu(XY&} zOc1e3+4fo{oOnd^M=$f8Suy)cAf`mnd;9$(2CDaR5M;P+^v1BuE!AM=6-G#lH2FXR z6&+~2fFknxU8M7JPE6&*ScACH^MGr7CHDCl>2>s6xoT+&3lU4{Hrsd4wxoh5WIXEy zyOTq$_+lVDPb&Hm?pBU8I$7qTDNo9h@d)xT@XM;`->OOM!c2uzSen%vivXCDunOeu zz2sLe9S{DgDab`SClfBB2zsK9ip5{P@t~AMf zEUj=QN}?&YH(Azc_wUHU1S7go;`VQH;9)Qo@WhUa9Ka())L~77$*(vcHvC`IC}3@< zVHm3*vU#1GVK(GiK>lwU^+oZOS4HouZ*MV#C%7!w7TRnhrM@9`SG9i(+$y9+RrD9uv^!b2_hrtS-t(75SeM7gN&~O-8h;ES zW2`K_(E;!utJLV&&J7pY5}&FrG1@^5lN8c2#w#}^$A?HP46$rT?#R;jnBHMU>P|>u zmOpz0J(OZ5|kp3v9rrSIr6PlsISAg&W4;# zJ67D)$nAt0gxAe$hZ7RWtGb8cTwfPLznYLhF_qZ~3;l%S+_NnBZ7>e{;=7T6{_Pn+ zb&{%%^BxTpjaqrZgWT5pI3j@D9-3JoLw~g+Qc&%u@Cq|fCQAnBFO+-G{i6z7)o~_4 z|8~D4QbS(rS}cCLk6{eWD8xc;Q6K77Adffd zqC(z(M6SBFV_@L|W0>=wHY#q?lvXhsNE>eTi%9=E^O^_D*JKsMA75ku5hszM{eME`xdW7D{J&qMB|Nqugs4|FO?REpBI)}EYdZb z{OTDA)K#Lkr+aw9zN34B7qlo-9{j{?n3~;1N3%@z6oH1PYvVep#{{N zb!38_VRLoK;`N69D{As-sLo!R!Y>;=k4R(`j_YzlV3L_ucYc^$&0qe#(EibAweV1E zv%4_uWV>Q?`5}? z8byiIfWGsy3FQxE?mm89T}}-(qzz}>u)q5WX%*n}{xq8(Kr%WZAA3wg9W#7mg%W9nlse3>cCyaV(45UAy z)`K`QF&^24kN^)AsV!SmJ2T@;&apSQ^2BLX+?fo&GPmPCF`~UZVaYJd7d~DLOLcA4 z#0%N8#b3xAb_oXJ$Shyeo;#=N81Ig;dQrZ0e__42OYtT(O!ga%;CD;o-dImCp-H;UkUD*s0vKPiyHCh>1Z75;&blxLmy=}c-m^}^{DPQu7WXs;qCifw{ zX7)T;PK;FfXNMD;fx)nTi;hEb@W3MY3a}+8`knEcdOA@c7LZqfkP_Sd|41i9f_|Cp zFUg5t7w3#JRSOmg$R$_=7}{#y{GJ|Vmg#z;K;U&SDyB-zo@&19%idrHy^XnNQ@n4( zLAUYaq#Z`wJ0ezbZ)fkY&7FTE1v2G@i>V&8Z@coaLyeHr--TX2<>vOCb@P1~4 z+2`LEId@qVAOn~Z?pz`Y)g?zSY@u5snGiFMC@Uuflo48rKsiQOM;ySI-JVgy>`8bW z?;p+eDT8^+MHQ2W>^@#YMqBn@b#{@u50<8HPBH`E=U1w0t$co=OsV6)ZKcJ+>+vyH zRG1@r=hh1dGig1!hWME=_gOaBo+HsK{`&{ ze&=iZQ%f=-M$I2C!oe@XZFNT3@aj3PpzV^is&|HlKSTzTe+aCnnQSAI`7A;O)%*~h z75i!BLxppmy)UA(r2{Na#WhlThXdVVx<&Urrr!k#tKDrNzs@yf7W(K>H_+wbk%-e} zZO|e^e}3eSh{5gE0^MG&tbfHdgRviUx`!19B!B%^`yq&jgoDGd(b3uQuVIn_a~Z!U zbvsjQuWgqPSqRu)yR+F>n7UmHZ%m^g+gr59 zcdn;ex!#_&zLSU>w`IsNaA3Q*c(W;-^V0vC!+q6Y`M(9~R1pc$#H>28R-xj(PH~A0 zMVkJL+}z#yk{Nr8qE%Gs!pdf#@p|Cm^ZQUY*l>xd$@YK_XvwYHi5ch~=5LhMq*!zr zMfRkQ{s4fCnT9v~aiZ(huLqM4djc1O5I<@v{j(Qds`Hes>lyuXRp4rm<$vf2yDoL& z6>o0YE|Zj;=SH5OD_J<*^_V7tHW6p}Cak_1G7}dk&bv-)yn{5lrx@60M)<8uZaCll z4UES5{*QM{kKAQrtl)wJ!+#KGgKkLOqxaJP)o~90)p11VL_GP2Xs>!*j-t0Js7DLQ~38tfV1Sp2UD{tm93sGR0?wIwNSKnQ+l3KjcR za{5Hl%GJSAU2c`aq3>L_Mjc6ZyX-)0Kh>vphAnsHXQg@oZo2I~KQxUM7A#wiK!rUD z-SC_KdgKH<$x}=%>2ji6{Ykg?pU01< zPHPft3JuRWbuP)Z5dBONo6+G-Dz}C!(M(7>hd4KgR_pDcH63Bkxj3|i99GXAcvj^2D-xvSc@0>3#oKU`gx)icJKURlle5t+i zT^44-w^kTgw=q?9>&05dp}J1HV`8=uy_tN)FtWzZEwtveg%so`8-LZi*+!&qw!`b3 zZ*NG1{rx|*@5t0_?u1|c4$`?#`on!ESFUz^shL&qQM^~Y5g1){7&9qKGbSF z24eTJG%4falQ3RyC;@n^t#$%M;*W^{tmU)|) z9in9&M$Mj6L&ucS(NA@y!j^Yy4@e!(G$5Ue=QetgM0-V=0(4IiM*rG{*1Wqi!s+mC zol4#R$tyqKK#u&G94!8Jf zaWeB-d-DFr?jCtziw#!R-wV2sx2}MvWrtFN$OV(hIw9owg+3edoF&>*j~zNCPKxG@ zxLZke2#Z$f#sJ@fT&Vyse>_7#yZUvaYc_Kbf-Y@{qY`JE(UsiNSG?Rrj{ej#Q@Tf) z@GvPm6tw;;UQ)CF7`wDj&`rRW!{MMe6IaRhhB7HA0}EgNNtw)_Q&+{vp%;EjTw=qs zjD;MEXaBQJgREilf7a`jBu_lx5Dx|9#Z;*P{#jwf?qV-)ISX#~9;PD{3TEJ}#Xk%h zT_OfKTIiui28Sr6<-XPHo4R6;VLxHsN?2}bWZ6O!&h*NjT`CC_2F{NCjf5LH%2TOJ zKF=l*)j#sj~nL4cK$H{$Di@$kM*vARsTbzs0NBuA_chdt>oI)k8EI| z+maBzBGX@L?|(e`>A80idMrg;*eU=E#)D=S4Fw2&Wt$T94VW>6R<#xJ64T>6IOuvj zSY@1`Ml}7@hgT{x`~%2AH(Y)27_vrRf9dehIBUr~p2(KAaHrdhA5jvLcM!z_0tlt7 ztkJKpnUGQ&$ZbciBK^yP~&-q(y)ViN(aac38(`eOD(ofeBf((RBF}x9;CO zMJRc@jrViNci#AB6p6#GtH=B!@%XmLL<;2{V8ea(n5pM2B>=`9I~)GG&Eqb~xDO9+ z(q+%sC*tnVF6s>>i-0%s^g^XA5N?4zJh+jBGrUXLBGMfCNDANjzu>V_zt$4j?e)Er z66O=B;vEZVrNLLE_}BFO-`LrVl;(d|!jnyDD9d-Msbf@;e?c>%i#ppg642{?nEHd6 zfzj;s-2^M=L|i$dQoGISbLEp3$Z~}U&~Y`k=k_m%Tw zH_fxe;j49c|7PCd{53bqFF8omqUhMxmsRog`0P!~#SmWZiT0$XyS_<({o$aw_6CiA zfHKHFn_y>aHmAmjZhx9RbF$GDUh`2h9su;RA5DAN4Q{yE&5?;Q1NRYvCXBhgW#h<$JwhxqBAr{a~jz*!_QXX z2hcirqE!&P@#!0R)0crNfrR_s$K5obgHuo8jv= zQV;aQ@$vC~Asc?Y-q;oD6h_O$9xqmZS9JO7a6$t zc6*Gm)2Q^iGJXaESR?BTd$$Gxe1gjVb`Lif(Ue_xCK^3~4W-rnUc%f8eVDOsj4&fK z1~}XA`g8iZ)@sT3Y)6!~bZ>UdoDxmc>=r@bp5Y`JvPitMXSHxctCYZ*8hH6K1GFocq z{|_X<4Z;iH&8fWuru+O2C`)XY`o!1Oe&;EYqxV0?2l6|@cGbF#{@rM}N*s1~kit|f zQz5fv*JntSAZymSM8Qp3piQ4xo++mV>EnWthzl$7&&^b&g5oqGk`K09}~ovpENRS zf(jt{5XRQ0A>RA|3QN8QRDEp}CpsaTxU9>nH1#I=`kbe z59;=U)7Gw2w+{D$3ZXgOlB#z<)5G>ayUpNNrT+F{h;!OmIDd_}Y?^n37IPqjA6h3f%Eh z0=HSYO1!Ux*yOIX+gA#g|78Y*9&U@PI!Sifq$IIUf08B#O9XQQCM`oKNu(58y|xeT zKk=XJDjgtHnBQI%{kQX46B+I;#^uD-rGO-RMYu{3p}PezP0)B_4j#I6}~00DbaVq#~){qnnp_wUjfUr{qo4p;p7)tvqG+0E8!_VzF+SwTjGj}!?EZ8+&a@FbPR1Ns)mF45UXlA}J{#pu|u?YNID1 zWuwpi{+|Et-{*DiIp=fEJAiH8Ja!ZBCGT4J2IuRM{r3=DN4ztC^zxMi^lE>1EhLTj zD~OpbkZ;coB1B81tY!zRaivtp(J zvDz;e7b-{%mG_`O0d1t)JqOfoS%^Dk-rYV{@)Kt3_{=G~MY;G_8z>9Y)0^;jE`bV0 z87}y`qjL7Am5*^nsO}3BjqGt9+#Mg0Z`F4{{{9l|^uBC|RaXA%7Nzu~W%!sGGqs+;8jQ@~nG% z{J8-@AJD6%7xsu`*uHhoTgFNm_=Th5;7%T$re9K|7A@#Xt$uWbfA@Ll`q9S~f3LMy zQ!&(^7Z`dBvRW?V(c_t061HbERw?d(Qlqu}@nD?nso{5@po>S2-29NNAq#3dSa&-r zq;WBHgw}fIebbMx&lNDz%GYpuRM_Ebzy#x6`*yIO^-)2!`4jVQ)i+4ftOP<=CXFe& zZe?@ICfpW!(Z-^zz`IVV+Ynd!HK3Lc;3&5+VPdoKS4gPOZewcYl9Vl*C)& zkX0V8cwZWILjO#Baz{GOe2*k3XB1(dd1VO9$li{?JI( z%ljE!WRn`8eH1(Ghr^j$G{6eF^s1J6-FcoehqQ?IcXq$%n90Ib=jxfx9o}x$5p8dw)mDD#>qSP``Yf^mmc)>+rgMLuJrU!!M08QZg;6&#fm1~ zOtWvVcFJlq3QpB_i|t9iqfHDj$KSonLY1bhGuF zBfe&vU#mf}0=(qAAMJl95IG0hd6iQS(AyI947Yi%YBJu!@Kd%aFV5gYClTCI@xYV~ z$Qxg*ny6EI9n>yjSZat$k$*J_}7|!devnkBnDd-EBahLUC)e_ze z)0WnQ{<-h)gN;rc%TrEDfzfc?jZ#*7!_R#*n+Fe1g*Hl+aLbnA-)x*O)(Lw7Z3uhk zCsIU!xEq&a=6E`!z$EG-#!H^6I}rZlHGPu`MXJISXB@mO8fZ*-N`_5BpZQZ@%H^id z{F9^s?zLRKTFI0DYT83Rhu=5ev7Cr~;6Yx?qlaCNul?*(wtC~rTUMA58;`YSczA`c z1)3)`pUz?G(Oar-L=@V4gn~2ACkR%CUm4Y>(7z+kA1M#L{gg1HXauC!)2QZ_P<+uD zy(|6r$Ga$n=+m9aqJl|v^EKn$g2`$1<35D~mNI<%`|lAvZSKE@13s9d6)$7gKD)19 zsL6p=z-zO#i;Ew}1;h*H_LC!YZypgU-sGrZ_%8y7rr2b_YQAAkr&#;V{Mzky>qSkZ zC=a3IJ{KThup_v%JH10;EhfieA9i;3JwUU}LT4Q1Gn*Qsgu+5XY6J_bWkCdo@`&%q z5)Ib!lQrF~qB=qVcj%K}RSu4|%S|u;V7VjJ&FwvwGVcmFjUlEgETmDMRqua?fO{Vr% zA0@oYxMwZsY%W#Fu@q2yF1NpTN}++aPtOh8Hna8?iryiHKpfJ@Ei=dRan7IsfdGlwJV}&LIy{tDTkL{1 z9IlNSJv^sq0_tK9>=)$KFl_af^>IZA^ox15@FIgX*U5Oe>g**|Vy>t8>PZp~cLK*` z^>%^pE)DvX+!Q}G$|66>j#}(JxMOtWrBy9UR1?2;!|wl687ivE}fWV@T+U%`@2_EY8n5SI}MCKc^5R!1;DNe^u$@)NBO*p zgNRANo?YXyv~*UdydT-tQ(I8Z)GXj4;FSzPlxssZu{`oHj3DpGn@Whd>MWn7pTZxL z7Exb#Cf~Dea%_wzO3e9$e#7Hu!k-c$pt}{ei2mYI^8c}8D)&=MC{cgBnCyKm43vhk zx8!?pknGmaZ##3fxw?R@Y)Nq?_0Y1R{=6yDFi-(=;8pAYgbn8_E7k}fxt*pWu?*fP z9m~dzPce^fAtZRs+F|TW&<_D)K8oq^!0d%9D)?H@?ta|he(tr*>H|OG9r?Oi_0$u4 zzM`{QUTWY0KeQ`i!H_u#6)MxJjB-c_yt0h*rB(-^R9X;a9^7K}?b zCBR->-|}Q!!?achm zZw?o$l+wV$jDSDl`hMXwMSAX3*v`_*qmP>6)jfgkYRE?+v^<^a@0mE>LwY(K)J8Mw zJ%4z*FWGF7@jQ?l#^W4|ZSn$_8pvRxb7vQkn$WA*$lz!Ppq>miMzT!uaV7+aDA zYA|m|`HZISGko}3dHq@i1Jd}1NJetx$d5#ooVzQ}C+2<({$zmiXe5kKuRXk7R%z6A z?s-Z|+^@8)BR*ov&|`NAPrT{;kBtjxSa)USmd8d}f1nK%N`P|`a_e6QeW?sjpJ#j2 z;bsq~_T0*g^pLzDoDLd-DR{sOd|a`)vTXh3TV;kUO+ejG)@2;CDm?ZIFNG+olk0y8 zxZk0fsiGtYLAY&LU7OI=F$OW+O@k?NdgiMOZ#OGt|0&qT(q@?9@1x8xA~L)`&COzG z4R31d5LLx)`@Fd&-8^W3+i(G133Bf;+iVnxiG1A^LZx8x>2{d0>b4BUJp@tEa{e!1Q&;cIeM3g4W$ zae-Syc#k~%`4?5soak2x`Mz#1;e$ni15uEl00B8{jam+U&^FigDTuut_w;7N$Z{py z%T>9Cgl5`OX*#5XA1GOp!9QvqL~t@+J*R;(Y2Qt8q6V(kR}32K7G(|3igiAS1b=B8 zzFghgaMQ!wNW;SiSNPVBe=TxBFkn({ozC>_U!GQx0cMWpH*fkruX-2764GGt`tgXw zr^h!flu$#F*HdAsW4`HvtkU-9Vt>Y*tPG*{_y5$v2ncSO5=af%R=GO|6VmMyZY|>+ zagU>%2I`6Ug%lW+sGXa=EUT=sl54`6Pw;$qhWGQ>AC}6n}tZ4cdTv11I&l zuHCPygc8x#d=%OWvhyfDiBuF)ooq ztu{e((;WmiR5=2n>iltzGu-~u^wN44N?ZcrP(YQPE@UL3O>4JT3-Qvnb9CdYDm z1Un{~b&Hm*3_r^8{k(io>Hrl479F0iDtz{k!l87_brB5l6g#s2&-7iNP056 zbV{Ix%iWRrkNI3g)i+!sf>9Z{w~(a=J8X{U7FAHw0Y!D5d$7k?e z*Ic6sUTA@^^Sxt-b>5L#l#4?LOzOx=13`-r$=LQE;a3Ye5Rvl6;SdIZBLEpp2}34A z&MG<4X#GSqmy?or6V`uLfpb(TK9agW8j#1_pO|jGW=9s1^Ni_5W%S>t62w3LQ zqH=9W!sV5(gDN>DXU4?PxtgTjI1NjS(Y0fPE0TTfnA@hZVY_1R} z8Nkl{<~UO`S@sId(g00WvX%J2iWx~rLC8)ADWLAQBz${xy}7!w!_`@kzpEA7oO33qDE$`pP3oj9-^w8nuydz4?3?NIdtl1m*E6MrBHtW2XAzP zzRxQqm;KR1umZl^P+;HW=C1Fmhhvu4FZ@-9S}a@ ziZVP#X$B4!wqi239z*Uy#sr@V5E1`?YUxO4RQRdv&`zQ|ml%h!dT%Q6*#!Rl zx7~sAm8_1Hy82$GO`BJS5GHJ&d0K0U!B>(3Q2wd4um>XV%N4(1(iDgG?sr*o&~{!m z6pr-i-Kn=mxSC6L?2C)%f9WLW>l}7AK2+h3WFO-a)NmU4o*_Dw9Ugo zee<>SypRp+fn7DE$$dm*$=b}Nz?O^HayJcM%u_0rvht%x?jx(@0As*70i97ZZvZPe zUNPg`7=2l})rxnTNpX&{EM8#3a&gUE{mN=J?5PD5BO2nxoODrPzsgk%nP0rJf?*V+ zYsLe~H;txb(2!EA7QzWA3Yqfr*YB4lCfnNI75d{FR9QlEQf>V_{q*@><PJ!Kp@l z2W(IRhet6~{b#jW3;}g@Hc85hQDsKX68T?JdMm8Dthqzq^!BbkJJqe_xo%Bh_ii?N zFFJ|v`}O&A*zwvbV`$jJ-Ypg1iH1?%hkyQvk^tJKxy*o_H&GgOA1P#%_hEB%c~CR6 zNjge_%AdKC6uOX57GJbcP5+`wR!{uvSzHan!;5mYMfL9LBd#HH4;nWW+{H+zI-TmF z_gIlgqHm=`;6kMW-c-J#xFegJ-^Iv4jE#Nxr{aN`mZ|gW`(^L^47i;%5X5l}-GO-c z&xrAOxMtZ+8UMHA%)xSyLyzXm=Dzb^`+}|f-@Wn_25D==#p+XkFieRJ(}sC@jPsSBu&DI(jwh zl_p=jEs`Zi5X41*8)WfASIB^a>jcMyJ-Z0ZkEU00u{Ycm9>7{(OdUKN{zORz)sf~7 z9KM=MDQMzHvrz|oS9wT(*KYc?-e5Z^RZ&Mgr>Y)A`n*5!uB=HZTzXg$NG(!)& zux+;*13NJvLQ?CCBGSYM!QHGhG5KEzJ)aZ}e6s>IW;g^0TMP)dmt;*snRb8YjkxfM z{^skU!XU5m>qI7n3Z8@TunHG$L%j7F?$3|+IhBmQBTZ>(r-28S2n+%J4rWamu+ z$BTlBZayJjkjB?eUPXZCCkyXpEZv3&E#~d(UIvWUmbvOroxfTSch7`WSqzaBA9?@K zYjhH>m)_Iv7nhZE>6>On7~o8=<|kR|`D*U*Qj}3MKN1f)DG#M!A97{pudF%&FOJcy zZ}e%}!nqM_dK8{IRQ0Ea(?vvYR8Esw*spO@wLELdB@gBY$K&6lw|nbiHWK%$>w3KN ztz#d<(Q)V*@llbwd)7Z`pdYz*Twdyy)8W$Mty;NRxsP@b1e=?$xjItwZi%`9!Es{8 z*bHpgPfm9r8us3D z%l}4&ANDh_&(}X~`S<6ViZ5QCp_+WlxR2Yx2}3cZ&vYcg4;R*l$ob5qTeX3Wc1r!Y zbPYM~z0HH17>A>1&vphT>^pjo0FW=xS@)%1oj!cw5jk}B>W;}LeR5H5q*k*N+5I@p+??W0+!-dpC*c|6W9HpEmoXkpzA3+F2Rk}dm!^Z|78AJ{?{V8Eu& z-TKe(3oGTegIzhR?7Q+UMfca9RD4R8zqwtdTa-(6t#12GqxX}msw1^$x|5Epv_)_w zg2%3TIunM$OjrsURUt8f5Q>67Zs*ki&aVks2R~DbQT4jNQ(KUdEG&zWBm`gaB+ECY zLAq_7Z&oev9PGYIMctA)#*G!lVMfk~1P9 zS!(XwoG?_ZW1$FNrGtUnqYu=Xlz=F-=J$H6_xmB{;C15*a;)LN1@z;j6&dtaKu2P^ z&y(=EGj>(xe^2GuxiNH*f%N0~)_y9!vienz6tom3;@r9ZW?$OtE?YA#bobO^nBq9! zgI7C%Y!o7T8{w7$F~Kps^B@#2QK~vu2WxFWN0YoAs8Z0BFdft)&RH&!`wk1DC(Jbt z4H7IroS#eT7Il#EEh|dr(?8_qqqNK>trj=`tyWm8a=?^=3Zc8r*w^wRlB}A_UYLt8 zcQbqb`6A3=B}Xl{e=!rIjbUTtG!<=;@8%G;4SMit4P3iPu_^m-IqoZ^deVcU)Z)nWd31v!*tj-bYQFrU)+r?2tdj(Oa@-THM@1gnX%pTU%6~QY*&Rw6nVq;(_Nnk-KXSMxnzI_VR|JlV_&ZEg_(O(VtC`>^=F{h z3%t0mHWl>qaImHiC=~Bbl_EX^1@BLOTWGPo0EgZ<=LT;F_Y1Rl_SEX0cC_3?*3gdZ zh_9~N*|SU)=YY(;t1YY!EJM&w#cKmSNK@xtq~K*+aCh;%Kvt>m94`=wH(vMncu%dp zu1Zj#Tbx__&9zss$@#j1TY^xj>k6bOo`9Cm%0lW3Q;~V zlU;-1qRKp`j_25>|5TmgM<&gm-v>e}-0uk&P40&qVY9hqy`VZl;dl%vFiRQoaS@cw zFWF!V6`SO`eP?iz6qXvOlmp9CfCY32`pCv)|7HR`X`=t`dk?e&&mb_QJ(oa;%8Oc7 zd}4i_J}hs`LyjX`t|-3NIwo?H56I)12}ZpChBb@6(52`<@GP z5}$BSP~A?sOXx`aK#pIe&Q-n=x|AGAHB}xF7dCwtl`aj+o~Jr#w|z6JQf*$@BL@a9 zC}$99b*ocKBvC)(&=biCf=%7R8;RFM=)H$&%`yC+V-9@2d)P*2;o3B_U;*>R$XlTZ zEpOP;Ium1xzS1CGPv6JO6oBGzHrAkTA%=5O19fXhWOnihX_Wv3mD+&YO@r+6?B=|BqQ*brIv5kmAh8QgwL-w?Nu*h9Fo;$e-G5kR!Liuy$uT}A4Lac_*WFS8qcX&pDa8T0t^e45BZA^ zvh;z^1F3l}Q@IU@XKF9qGEY?E1C`1u11IcoX*;10KTuWKHVQnTQv#7!+7$~1U2dV= zn@F|f5nuYJoB3O-Uq8BLi=9RqD-`GStW}1A`hbyA8*DF~E+?I3!8otyXW-edMSIX-?YQ3jWJD5R|{yS zqqK4Jlc&p3(XX8oooocohZ3cNn?5UtSmIU zJC}+)GrQ?9ddbv1DEpkM_2#>GM^pCONojpCB7xQ7u+6A6_80R@n>k!1GOi96GaT}Y z8kj##DKcR))Ce-9jyqQM+bm*Mz|AVcS$w^Ww+iOk)01K6Oej=+ z89qr0m{G$TIaXWLkddL3nBiybf2AS$q3ep^KkyvY)bzE5ITX0kuWgiaDuTIWjlgXXY&Uk zQs_FZO6vRFD06^$9Tk2!)tlSonX@xB;{W>l%Wt{E3=*hYnPrb$1;cqSM#RtLF3=3( z7rlfi6O<49jw=U)D_Z>76|5*TqudmN+wzV|^I$3|1kJ8%#DLi&(^V{mt)P`|2WVA4 zn_kIvhbpTwX5RjMv;7*4TwG$}zn9it!Q+y3YRTFno211a2L91%s}Z^4n5AfFC~QJ} z3&ThX6}^^jFdBILAqRHzaxKjj#O@Vo9OmfStl4083;WjZFk#`Bv~j{bX-1Kdl)Y%A zr2K(tsjHBx{KK~G_dkEd^wKQSU;;l_z*A0`lu%S!Jp&elldGGd3~P!?hdOdT&qRzj zOe|H5s9ZkX?sxs^ByH~X*rdWJMH!W3NqHT1_;79~(lcS9+!I#YhoJ6X4xXPUf!<o0F&8BCR6*JU!r>2s5lH8hvijse$NGBOEwC zY0v7a&0*TwKL!)khM?L)+CTJ+0hl-Qec2-wUWpH}Q=84(pZqVN6QG9HkrIkTE6b(! zOCt7wJg~5#0S}hfb65Z%pmNC7BgOv2>Vt@7$(1#F1yJj{S|!PM`N{CaR0~eqs}(&n z@Vq2)kr7DW0Znd(_20o4WhfEyUQgUx63@J-)iDj0pBZ8sIKPw&0iSz6N9Ytgd`wsEwhb-@x#7%?5WS(sgJtqWk75fRn$2D+f5nYDY&BPh5m@gS}d_Isj+2%odeLE)r>zd6QbW+sCp6$>XC32fKek!Cl*Spxb*UvW%3xho7gb=52TW=IeH79JTqI7nOjov$E?M^Mer|t*~aRs1X?hraM)lY;!*OP&(R5=F= zLY@K=CJ0534|ieOu(7h~4yL+)32ry+Z*Q z`?E#_{-|?=-FChll(4atrAGLz{;JWridBn%!(+35ch)HS|N5oyFDfyu=d7fn>BeAf z#w0E1HwKt>np~>~RIge;a%4}B1{i4><%;pvh0}k?KX@4Z>ylv8PCRbZ7T~>iB^6#u z6-Mo{Mfp?3*~0;2_gb~Bnlc!MibH4zwWwa+!{vI_lLv6$P(;>1-gpqFKYssAF}Sar zn)C8=u|M(pa&2`JNyy1(rx%cot==lwOomFpq?!iJBRyn=_yH4SBw^*0jiQVr#ZoIP zN1+z4gImP*B*awW7NZjo$Klc4pa9`joRWw_R7^aY{e8pISw5&Yk83=+h)OfR#i2mx z=)GLnnVbyVLA0@A13p)r6mbfRkEF^9ej9bETk?j{8VynTP&)I99kKE>A>o>!d>d!L z_C+XF>|6DFp}OXL@7}61`RP81-_))erGD^tP@>g7_ie5F4WkGY88l|glN9*Z8g^4I zFc-;b>r*iDm$JlQzm0kbq*rhvmeM)$jl%SUxhyGIdIQf1RoKVWIu0Kagz~0!^!Hwl zv(l~=?qvH*B=M#}hc2usssssrXEQ$zilEKMW+12H$(FJFai5kv5LvLjc^2*R4;cZT zt(K~eIR~f!gXr505_j3HEp53sJW_6JEKc&{NAt&0`RtuaRl-KOj_E4WG^$3ye7?ARamX=6sLy(6&SjC1Aq=3+TRv75JXt zkf^-h!@(rhKl&QS^ElJD^pB|yjFI`tSG1o2a&zoK&2`Qv4$;SUekWO3-1d**hYxB& z#a?Bm-C%PH`o{p{3cNnURmozs&a+u!>AiM;A1gn13t zxXwz@`|gGCoZ|x>fH$D>ey*fhV_vWu?)VkN{_yWDFC=Tq0==pMESl|g4hifV-7teF2s?h_ZO%rV~+Mxx|7b%Zd-<%|0L zn8dV*;)|TujaM#Qi@<@eowiKQSX?oVk_AZ9+VIul+_g;^aDC!LZR^J(5v|iX} z-3Ya07FeN>Ef2~LoDvn0&={oRS~fsc?sCY~*1s6>^(s=kE{d@bb!^)>cuQO(HBnog zAJj-+SWMGgFSKYH+z)hFGTp_1;>`}vh^f|jWB?K@SqN}1(F_-Cc_z%L|q=`CaXQVO#L3Kv)eIxOaN1nd_#yLgM&-Z-3 zh-3qD07I^CAm*kUI@y0$c!g~Vv-VJM)Hf(Sbd#Qi3o~tl+WV}4InVP!-br&NhCfkT zT}jBNa+M!T4oQT2Am5H}h&UNrip@er51gT6C}JE@O-a&SexP^iwY5XGa+bC2i>NsG zHyW(wdRRN`;^UwMG$4PJkejU12=ZoN(aqXuA#>9?c`4#satw%V#LOBC;Lod>I@Rc( z4Wqsm>{ssGIp&Er)i6qK8jeTL;X7)k_P>wLvvswo(js!kJ!}t*5ir{OZCu4oqwlI^ z?pCtDaA)xk(ji#CW`M>zu2%uR&lFwn7_@F&biLP`G|w)h6~enRj_)voP zN&j^QsGncWd@=!$}=F60?#O*kT)jZ zsuZa)X571OqO@n2i4YYF{1G;1y02aJju)1cOaZk`$9>?2ZC4p?x4`TJhyQ3jl)CsY zU&k8${Js1w*Ux5I{bC@Y!q-@`uDpqY2^tcNj@+DXntG=`?Hs(a)08kJeHAo0tqm>1 zCo^D^oPqa$pCU?bX=*shV{jF<>+3kv@#A}31J{BW#D1?F20YlFtkn!_-sU4z-t7Eb z^)8m-ZDoEPKF)Xg?aw8Tl#xkA$Wmnr%r}Dpn=kb(%HNB{t@9A5Is=qYyI=1{?QP@{ zmCHaVUwL3s9D0)<^?Qol2W`~T1^mu;c>7wB^Lyl4M^qD3TY{GP`k1e4SQIV3PK9$ z_B)3cnbx$1@PYlaQ+#eBHkFO1C@kM~TWBGYYINIS+)@@U`*^{d5!@CMWqy(i*M!L>eZo_a;@_v52H@=NX_-ouEws~dCE^0Cp7nD3(D z^Ev$kfB#`fTrxD*J!i=LJNBW63 zGO|Y`Zq_cJH5#{(VMDB|pT(N5I%n55$&9Z^57_)pyL;UtaD#0!9;U=?dI7uPpT?~9 zm(wT`4&!=Q#zA$-sg=3ds`Tv5S)U-oEgNl)6wS_ZFKKZKf7;@!gq4ip7+Ai zRyw9!XibO!2X2N!^+t9MEp<9vujp^!;SK~}c~jeHHdlGlcm65K$rg{Xtt7F-`Nsp2 zJcid=KS7;P+;@)I(Xw&?*Lh7UY-3b?vylyP8Y{j=IB(5ViC(<8R^u0&twJoLjx(NW zsFC7@u>`o~>XlP6u>cleX?f?y0_0zPf*}4EWd)eM5atS(Y|atiJt0oyE!ulIRdq=u zrJ*Sc3q_E_AyrcFNRM<2gER60e}!8xm1B?B&{R9+Aa_I1n49KS%FD(DKESpf%-x&@ z%$}~~$^r_+u2IH2f#mMR*j=w<+RGerC^QBA>p)ro#`{-{@8%`uN50V1JW>vHD5|#e zWjl8i*3T`kjhRg!cN1FlW2_kQsUa&~maD7x5C$&DfDJ=m`t4<&bdVd*{}M}gE0#ST zUFN`0PU>!4JS3*yK}GE#$&bw!-UBfkD~TPt7=|vxe*uAEEn763J$4#>EncXYytBmdUd*3BC`8Ku3 z*JN|Wk7!|;0z7DDgFgEF6qiIt3Qg(a1)e2i6y4Deh>VZ!U1z}J@tVHB7U7g<(>v~oTS(dOe^3vaMrW(ViukkYR(d+Z*tkHI7VTqsly z(=rD4J-&~Q1 z=l+T9m;>g33Mw2__eo$Y(_ydRwt_GA>R>9xgM>3hSuF622Kvs3=#hmWJRGjMlwZwF zWHjX7&wYpYNWSr0`FX-$w-mT;#?7z7NsiV@F^oR@7Ah)31PYJs8B?h!bH}|agi4)G zZZ%BQtH+@=6!VG5Ve<~hV)dZ;VzXb3C((~vdV=3~d0j;=E};jE(>>*o`o+hfDo|zr zkK?{>mzI^m$xM|=Z*N~ul%WCTh|87}_w6jlIe*y96@e$#;jdJVI;*R(n{$GJVhJ&~ z&69K}ib@^pzaZ$~vRgep4<&rjqc>Zbmj8m)>v-ThNEWV7KviZBNP;88r`zBC`Pm*4tHKQ$B zn51TcuCjF2yNcO$b86ox4xt9<^g(kxf)4&BJxLfp*kej7NEY0?r|F9QQZQFWULf=V?bIQ#CFiS6G#QzBHFY_=G# zx}N7$rD)%tw;Y-8Q{H{5y7LLis~79JRsg*7dye1IdX#A-S2vPcRwH}7N)#_Le%HaY zZg`r8>ijRN$}E+tMTKh7i>vyeo7!^Fd42)CW&<4}_)MkND=1Y0_*BdUou?Q#sUR&J zpkroEuDEJ;yUp8KQHf!3<)iI@>TJ!T@ypmOwWQ>fzCdAigVXuBYaTi6%F8dBnGnmE z^up)lH&W$2U~^W<$~~V5m5<>Wm<^;*${gbW$-Qi@Qlt;;<9FokuE@MmJjEI7H@^z! z{Xx5&IZA0jj_DBP4d>P!57Cnggi_BzxTncCY5_n34nMuyjgvL`okEf%7w1$&(d2+`n}M{*WxXM z;}PgC_x=aO&r$taFJ^LAt^HFLE*4si*x24RP>)LNt`Ze95~mi-_uI=oR=3}RGw@RA zHD`IS;+ChWrGOLKH`alrfP@?RLP+|IX95J z-kh_JOZ7*dZ;@66$M!2i4%&mpuZ=JH3+|TLKFaB-^a-SDY$+y$ ztu?`enw7mb9}G^tB$#P^l%iQH0J{wVj}+Ip_rXd)^by!|r2h$)UY$QrEMSPYTZlGq z)o7@)=nWaX%+~G$*6szyzUwDhF6m-A1x$EvvirK3B^qCqy{*PCnFs3-kKXh6r$9oL zhLjb!fGDy*mFB7tXzl`1rK3J%!ru~?Aw6Y=-vP3_=PH#GI(BNju|>NoBek^;XU zazSwZd3cHqy)yhew=jtR=9vvCP$Z_3L#fUsk6}2cqppC`x__!avb_SmwDQRilkw7@ zZyA{+?1FH7RoxLr4}HFSe_a_yz^v;x9uWUE;f55dfT&|an{ycMDXP)L>W0I1s#koq z0zn>#>dzoj%7#>zw0*y~4GB(2x*?{D8`it+;o_M!6;5b*`v`$Y0zPn)K#w>x`+ zSx%M8usEaJ7~&D)v`b>tH_);;P-)ouX7A#DpycYks&%&CE%y-1P5;Hxs)d)O>c-ov z)Sk^XA*UuwQp9s};^Tlk9$5FGRo7^+8VU3baJe~oeJ$)Ay(aszqMvAogzrPVhdd2i zK$YE4X`I=M|9n;%roV&W;@!SfKe~R{TiuH@zW<6Um_Z+9m!R?s z=w0l;^;a_Uy06OEO=$}(-Od00{`{`mDbVtm9n~V~`Q4hiqiEL4CL(K0aMKvhukv1RTR3<1*l6oS$&+TpU-TB`=Vx@X*VdchHH}jr#m3< zWJuPlzPU{gqE`5E|Mx=4x4yQI;TkC_qr#j!Oyp3nduFSz>{{+^R32+#p;t-!2S2yh zjO_; zf-u=e$a|}57CpX#<}7ymZuPim>zM9u?8Ol(ca3uQ_Y>Q=;;kXI6C>N#1PXD~qpbFp z>NHhM-z_TDc^z_}lxppmn-haYFdaH=<5>8?$fKd!#PuLJFszLFhWpx~gmSX#2D*jiFC7|%f$KQqLEt^mYNgHnH6 zN}0*LA*5&MIS&IV=j5mT6UobQ#P4tC`07GK3hU5_s7=eOVem0|Odpj!W&$rlT_AD> z{{Zg5p0vn6WA}X~xq6ydCLi+_(^nccCLLNh;(ji1EcizM4O9z)c6{)Lk&cGMOY0 zrvRNGpqzkCQpr1{?!HSJyXS&Kl>U+HgFr6cNtNgD$ z=Po{Pend%Si@`aRisl@%z( z5a19Qr>3TWSpM`0_H{gE3E%OZjH%-zQ2`VMuTw+Je`4&6w|#YMaMEG>O>f_cV1`lb zbO!aHgcHYKv9u$vZyrXK!>RF*1c_PbH*-d_WC#fyw+W7MZi*U|>F7)qyg{~b7=fY! zedh)iK&X%13LYhepIQWvx{jiK7}%2|31|qyFZ^g(W$THzGOtWAIrb0AiUJWS;I?|6 zp#~yv_83(*wrpu&T&t$fTU_=)_Wm|Me#^p=S~RV;?oKlLLkWgvpQVmi**=R$Sd9w| zFL)XKryL6VG4LaTlGCI!%fRrM0(yADmkoEnc<`!_MEa>T2hGwpec-cdKW|vX+W4`; zWa{TVA2XT-&M*;h>;=MXP;#bG>C(4@qa|LiSMw&}5DHVsExm7PJ)ue{T1g`R08AmO zG#>rpBm&|8H)C--FcS6J{`2l^b+Kro@>2XlRN8G9nH03Bzi&iqo>q{XvyU||Z2urx zs95kQ@q3qmMHKPcyJ<5y>*mnzHWJ--~L zuetL*nsQF>9}{qh4-Mwjg%Pwxvrji`K~o@yDi>;gvCRjeZ^kp|5xTgrZ==UIs2|w0 z&o+bQz;sm=GdS7n2L-(S5NhX6){g|X{@VKnx2=}Y^P|x*O}ZZ8r0ghi63hh79WQIW z_)K}Y_DC-+hR_?K|IoEW^m3&q%=u(cB7G!v6*!Dzk5|BRCc1ayhYP|4|BZT0zzlfCi~b$&vwz7NY?m9B!!+h ztK;Zk9ZpTynkYJ75qEed`9tw4RRa8fp{6jYWD&2h`hde%m9p42v)SO5*49V(_qP%l zF!R@|-+7hlW<%IK5|594%FJg3JB+JRx&*?$OfX=q!uvr{PjH?-nDyNc2s>mXN2KXJ zpLDu2&IA=RGN^cpiD0{w{n;UADW)J${;`4q+Cy(DuZn(6-~$w_C9j5XphQmPD{Klx zrx@?PsA@s-Aky0U0t}#|ai*QTg6L62Uw)`6<*<2sJDYXVos@dxe<}N)hTk*7whe>) zT;8zN+-MFO^fg{ptsIc*h@ML2u1V&XZog=h+#1QR-&c>Z-in?AKm z;#6elE!*8cQ$D4gy@v0vKBDXOesY{4sR_?dTnH{}c#u}$G4uFdYFr_K4U57C5YJ;X z>pWrl>u%cW))v^AGJQZCe5nk!KKHUTgC*~0QvQ000UKYI?skFZ=wu!Q&tLKqe*Jrz zS{8y^f*D~lQq+TA*dF+>82y^p?|AJ^?UBUl@~1-E8u5E(j;1sLbYJ!!@H-zl3(hfO zWbgCx8pWXf!y^}Y0c&_Zms)f{Mv}wY=g*EVN1EMs$PK+fF?rhkTYEPU1U*DX%k>%W zKAD@FdNM+mypq7+_(-5b zc(w}BOSaC695rA4V+L(n7wB6?>L(*LMI*I4RkL;<{*R{f{-^r?|G&MRaO`Yxtn6_R z+1oLWm5{v>$2e9t;h5R$kbRJq6+$>DD|?2H%~4WBDfNB6KJUx-A9((7zuceq$9>+e z#l8NMM8F~Gx+F111_G;HnYgTa>Ie)9BbWEy{u5f(3XfX6Jb(UJdowz!nH@l-hzrTk zu^qQ^@S$zI_|SMS!{4fHI|7mJ1cvzUNGNAgHRY7>sW=Ibw`~#H5m9XAWzucKSMt~4 z_Luq6JXGO>`hC9NIktvG70xTU_$NBcLW;64YBfh&nH3C9Ob-6G8@3=4juNs0${VxSNh%eLMNS zM1%f`WDQiesRJU=p5p}7p@#BB-hmh?vU|PPm{a!SxA5Sqoa`MVe0>ReHc!e6)w{)( z6!$nXdioJ36EP@lJ`yP?9splWE{Sq~eJ+5mzz1%)X zKvak;FHVN6$ZiBZy2YHivdM^GY7_urTIFab8HrwKy<0YsHDZI6y{77_st~-8N_yb^ z{#d0TKxqSV_XFsi9DCqACu~9BCaNTWZel@4Otr=pedM*1(#z;jUl6*iGVJv{Hs{Sd zeO*|}%Jc7}u*&7&+^LTKmWHF?mAo1+>-m!4;MZLBO1=4aJ5aH3A1edx%?9A!zl+0d zg8tFxo_%{3+4ZNu-LrP=0xOuWIXV93U7sOmNeYx5#eOl&%JU|B=*b9Ytt~V_pL1oZ z$cqg$s)W9{yGGIHIlyH{t>iXC`)Fm**a*G+FS7jx^$a@qAy_9?u|NGM!mHsvo0?Cz zkxObXs06$#2MR78N&q9)f0);;J#Er;&`AHdZ5@moNq!s}n{(B}Mp!EB*XzH-76d}; z#g#Na%%xXkdSs>`IarVBM~%uH1I}L7t~=4+@zu7?WQqWk+awKwczq&&Jnw>b6-qE_ zIBTLdFs3lgUcPx$o$LGM@SW%!i6J;X{LBrIXx{`xk0F)l~#SpXu0# z7Q{r(>aq|dvwxF$pvdWCZUc^ITuUGXG2ItCx%!x!L$|Z|y117fy9d{8Sp=7mr&iSg zYCeF`UsM*-iV80*tD(TP%ZhVo1+GK)&7O{@HdM+ zVD!GWHCIPr-D$I>KW8Z{b6^Do=jPu2U zpIo)XvJ^>KY>r3r89H}w(CElref|2vzVGKKM1q;9f5}WvY!*10961n^2rk1llSSVG_HlR!%Kj!Ck(1$TLNFW~CxH@6+Z zTwr?HlvfKRd7DmZbaMu+*|UNh?4L4C0g|VM3TI^*pET)NQ11M;#T*S}=5a*hQo}Ll z5?So9n8FTbb893`zn7$Bu($W!w=q@mFMz4rakSFEa;4oQR7Tp0yzvgN=%q>%`x!MF z0thkRE(U9&F9n04DxOQlDROt8Jc~6p94@tepi)^taZ6W1;tg@K(DROrnj z>5T7b99!w2XPU?&`mPj**T>k-Ey3bzLa|uug zb1)B4Vj3{y>`oc88_e^R$IqCWl@8$&kOzCcuT_7m{CxWIi2$s7Y3PWgmyrW#p&!3b z^D$fbLA0rcVgvtm+t9?m?vpK+ZS49gFq^-Bun`M(2>dTBG%xKeM&p7OPG%JmZAYQ! z;m#^1oZP1lW(vE94Zy>jIOTKU)9}Wh%Rvs9k_Wu7h~FYB9#{1N9`s!>n6p+eO47E{ z_{-k=4U}(MZ1$ge)k64&sy#x0P+PP8nhh3f^~T=d$dm59qc7i{>sl%3>KjA294DDn zIk`b;?iEm@Jh&AbE$O&;k|BrWAFH=U_nDh8KwHa#H!}%69bT|g|0tX&zcp~eGE=YoIJmW73TEsZ7r0f^OllQv~83{uvaAu5{vPD$|6H2bIy&0 zbkIp;@`DZ< z8gwCaDEiJ~g>JFM*Lrd8IEMFizl5Sy$r>6){YJt6TwZ z+!6$d@^u_eaH)Hz<@mhzlXSzH0I2HzyDvrH3I;p z-goAs97-i#c<3nQCgEVmXl*7ze~*=#OhF}CL(RrSL+FAb%fOocmS8BOU)iFj1XCr6 zfshJmHb*sM?mQQI?Q7c1!0)NoU;EDam1RmGZ)Cn^7KM0(ul)cvjNIM!(Ek!d>nWhy zJ>h}0=sxm87k`m>1-TQTYLC6-_EX0D540&Aru1sQwVP&z9%~2ClmxBuqX`0R;(>JB zhQKD-nlqg4Lm<(_ zg`HsquiNM#4F{7G=$&iD3Ho>Z_?SY$tDi#hAw@YEAPkd4fz>$!=9$}%urNy^%uo0s zJM?(u*e-MdDbdb;8NVU%$fT>H0kv=*qu*XvS0apHU(HGVJOBZLE!C}%WQ4ig`~8mj z6w0-!CDo*b?oMt!s~n%>uU>(%(sBI^UlXi0vLf%%akKrzr%yFu^#?{0KGPXxXDI5( zAzYK^CyuAUublY7MGZ%0#B@i#=gA;;{k`Qf|bUkbp?GDvdIz zB{0%}(;M%5^Y`T1vs9ymN(udauuDEMk$>c)nH`C4Do3|zb38LKM)ngZ)0s*vnG+T? zAQyt7W0KI|Hngt9sBg>6x#JSnLNWX5+k-^_)9Nk5%B&OFDuj)wdCmpxa3g~Z^+8;p zfEO3ns<2K&6BMN*TM3oD^>;8{9r^i(u0MPB+}snf+qwD<;&;Uk_+cSS=lQyT?MA6_ zjQDFs8??pkrCHJDaNxNzTzUI3>>~8jOjQA4j=Q;;!tZRQr9D|wDYJ^YQ}t)`Fu$kF zn7k-VT7gZx5&_1X6XqdkHviOJjw7T{)#>r#9DNAYAsy~c)m&lAd9|lZ0SLkiQ-gW= z3Ua9J&TA=`LXDmI8!@_a0+HtoXZp8_|1%)V%HrLy1|PIgpmu4~PWtkzS;W)ay$G@WSFUrsP#Xhi3LA%#*W3SYTu(r zvz=s`NS_Fd)BbZ8z3o4|u-B^;=)85ufCzoI*IO4t^(k5jvUe;J^f^j-(uLKxtcqW$S?LniGcN^;Y0Gp@+yXV97)=IR~iVQlrKJc`kEx zI-xXq6+|Xtr@h@`F|z3e{%`9&P?htvVdBDr@&!R+aZ+j51eN+I$e1~lMCC$?*1WSg z92|IxphAIp7+!J36J&j%z(TX)(Ob7O8PtazZGmPM_z^ZQG5RfXgJd8`xMXxZ9UNw2 zKQ|ob@8`{3Jo`FBw`g8ixui$O^r;Im`3@B+c<)7TG zpNt3I7fxuTkZxM^oHI^qi+4wfU6%nz5~Df5SCz^Xw*A+v+oH_;kX|a)sEaSY3N_Dt2Me)@kf~@ilwuXG)k4!a0)>61My0v}0bb zHIELozK>wYWfYnc9uy+OKp8(wqQ6xeZ}-0lzkOc1&3H_eH_1j|Fyb@LA^$=Ci?OtK z6j@DfU_wrqq~lUv?SDocovDBG$lRC{NZ+~iAsT6QWv?Es*EBLA0a}FOZfdo_?YHJT zcLpi1JzmAILKQ!~*@!mO#GdnGvWT8*mE>m{Vy*9z!V(H)Gr*D~%ZN`BaX)q*)+Zo2H~;#sk@Yq(v$yr;%^B1vyXZ7 z$K8aOk7Xrl@f=wT!+7}2nFui~-2B%DA>?b82D(8W+P~ul=Lh-@`*@#^wG4r1Z&NdC z;-sA6IGK(!aAc1wqplLgM~48LU#r^2NE9L#8U2 zT%#*X9|XU{knti61oY1Tt>>;EdFoxz_2tPyRs}&Hxps`+jnEo&7 zq?HWq@L%NoBSg@<%Tb#;%XDsUaS_jfmsg8gGiGfbLg5c@hHE zX6Ni~y55+L_Y4NNiv??OcCbV5f;}r}_@`V9Viuf6P#SRySUxql4`Rn$feiNU#&om4 zboSZer`03v^V`b(Bv5sZmXW6s_ds8s6(}FLZts6JOUq@J8hyFUgB>rwTZ_~~syda$ zVVkZ`a)4un_Pg1nibdA50_L(zEaG45P!meRbydHt{6K_D_%#{Zb>>nyBmC21NkGn6Xgm|;{& zIH0b+-LcZ+3Ck$CYL#~4!qUHGF<@$!eZJJBB*!sWPgKg(^DEySIuz1z-1eDJ8@j*Z z{xlY>^6dp-&JHJob0ATirn5o(vsXOCkfK$J0#)WQ##jg;te*5Kx~Ur6QJ9GwniQL< zs$%?Rn~<1OpLAEn!ZFGJ^JX&K6~SJxRO+k9gUMwKbgXM`tvJ(w3Di(73*M`SJzrR7 zhJ76?2_*;-h96g076Lqx`%e`+y&r`BT6#l$!mG>P^l6~8*Jsorj|g)|8BYWavu@~s z_D@dG7q52!(YDAovd>=cRwRp}_2Q2kX}Lh)LSJgazg*thJg7dY|I7x-w`o$(Qa%eQq#;_PdmO-H;=wN8{&xKfLb?h&S4rnb zz}G5}R;WqoH(U(O&sSTqi|P%mp#@SU>sWG?lBJ!X`}`21Vp|cwg{7x#mTOMO6^p&8 z&;eP@vOv&v-mGJWGHn|-1w#c?Ay1zG(B`HVrp3T7q%dZk>YpWhOX={}zZp^z*gjAv zCHo5x3a?*jmI*D!On0o1bvz?V(<+t^b^Ix{dj0(qgr5gq906vg)Kibwt%tX{d zdyo<_)%=S9wiS;TgRO`h8h8FtKP{+F`bhd?B*c_c1n&)uDtM@8&ZL5I7tBjv=H|Iv zGZ7l#uSO@;c7IQ#X0Lf3+x;wm0>V6(975kQJ|;60eU2g#r*|LjK6Rtot6Bb7Gehd( zsNLLRwHDM4BL0Q(?S_a^UO(Y;%5=9 z;CLy0(VFBBMyq3#8C;mj=n*c=-R$WDSEbgew{U-japel*)g}~-7NPBhYpc2ag&{s5 z7}^xt9QUM7cC(ok`h(?5F$=Dm4uhwGeR_J_O8^rNZ~IccGqn9e`S`tr8IlNQXNoyY zc7e3HCq{p{W5t@n3Q*fSIAs+>i!Zp?w~Xxdyq}W2epPb&J=^jY3bCz63?CW_*2}(LU(E zTIY&U7Q5Bv$Ojw^aCha7;#^-j0W2@3Kxn_ZcQID@-~B-}0Y(oyr=Iw|*C}k!YZX8b z>VM+E-Qhb65);;|tH<(+QH2gW3nJE`pw3tAEI*$9ds=?Uhf8pCWpZFP7W4bSVX%|S zNYciiGM>|;rec8a1`$?8>asz>jr(WzrRGMR#)yD#zc(KetAFv4O?MKh0Bp)9&6618~^8z0*s4H zbDsv{9fF8qQK$x51UvLz6Rpc0cpho_pd>WUB>~(LxT3bj-TS*Zd>(__bji_qwTKOqTtIt0>2m>jcd5Zl@ufh7{AzfnFk}_J}Z-b6O?sig+ z&pIH9Qj>Le;kfjB%mPajDQs^y>n>{3M5l zjns-J_j<`}j;HkU-$WI;vMv00kBCDhu~A=JjO5FXFz#!hftw1ChaYS|Dm~K`_O~t_ zs|n(LFkHe3o8vmHwP0YMMg4Pf49s2>(#6Ss|Lz_6ild1}lni!BT`G!`H4@NdVnYXW zhc$bz-wJqpPh~?~-6P7XMKX>=09#Tb<>MK2jKbsUe3f0Me(o zY%e7Efj>K{0^nzqrUJt7HrtEOu;cdHf7@}T@pASh`-B*?$Fbm8#%YOM=HR`r3HVXP zjid+~iOj!y-#1G&+pB#QeUe=ILjj@&pM$2Yte%626qGZa-b%=(HWvvvFpB`dRU33%!mx&#`l91zFN@U6mit4C4K;kv_*jnQCsd#?H zewMWq;(957G>{D4r~4*lv_2w!p%ZgnYX#iN87|<1*}^}2Sp5rx{P@FQc?)<$HIhl~ zU-n_BUZ@fMc*XaUaLYS!!T3akuBy2Nf3qYi+n0=`w1=V@R_{dBvTQ~Fi@Y$?gR~Gt z?x~P|Ba;_gt^WBcm~iQn_KRP`d+}#uyT4gL!0K?RlTJ1>d%3nS2!a;86r9WbhKhu< znlxds3&-o{H_NdNub^v+^wx{}Y4N>Ut9Q_@gi#`%Vz%HVQOQY@fKW zp@?>FI+?1!hwIpK##M)h3f8!Kahuqp!`FNIE-l`^ZD&!g?Il9*NIhEDy8wNM)T;-yE#gc9T9XxR2=NW?Z>C7f7IHl|x*6{f(AG4hlozVz8y# z=q;)sxqb35o2&_T^q)YinVG`h_h-PFzDS9tZqd*dCHi`Te8_Fj!U41x(j52FT@7ih zX}CJ_1{DmQb0k62*faFAP$wKOFirlvbK@#MQHHw66O0SFp#lnxM{rO-*W9J5KrJ2(nfbdnN2W{r>;JV$V#Wen~RmKwK+5V z!)r3w;=b*-4tWj7z-{87qtTe#)n|x(iSrgCwZK#9XdASw902Fm zd8npQjHN83sAA0zP&(RGX-vd6wM$KdAoog}r9Sz+BppQ`Kxg-MwCv0*N|~-+UYls+1+;^Yx8sq{_<1fgE5G-gW-cv{FZf6T#^E`EI{m9utek&xC0G;oQV+;;4sYIRnh8*cDu{CJ27>Rx# zO&un#zX8X?t)*OhXe~PFP}> zw9o^<4Vl)o2lYuPo;{%0h6$U*Em3Za%eE~G@ESt}Z$_MM6~RPVJV21lwq8Bk#GG`L z&)++jf`*s$(3K8hE{=EZFJLQ$Utcd(+VZ3>#8>{;;5ArUR6$rSa>_tU)NqXX-=XQ< z%^(nDwb)l8lB{%~7&LQ8Pl)+B6{n!u34-9bNWu0$x{JMtVXiw)LJ5lOv7`0;Bja6+ z+oO-yZ`2jY)HE3{&a@7=R6ma-ctZVW)5T25?agjaW=lTv3N0MwcNt;-tiw+Cpq+V1 z|6!ywTH1kY0?1X*i|-3XKVLYJ@=qzsd6beAPmSsj@=k&g zU56&<=rrTFR)G&8-!|OmNFIH6bp6(_cKx z_KRm_ARoE7_>QcAoLzKs=~*o=*GY%0i*up*PV{q=BgU6i93hKPZ05r0dPi3v%hy}~hps#HoS!TWh|7>jGk?5|9s}_Cq z&DeqHfDC36kF9FFy<`kC0X{N~XiI#Xh}Dg9ESn83(j!{2Xfd2NNFs?izA3tR+DV1Z$ywOd+>_AUdTtoi|R(HWPv zIBbLo*(=`N>^0=nlO1+_q)!ZUglK2MA7Aur6Tp~*l@u;}UJ#(=sWyJ*7A$HPFT}!M zxF7hU!~WD?&X5s6MEfY7K8aImvIh^SK$DlurE@)LZLPyYkB8f!kCL3fGu&~noHm)_ z$FI&*cX?Zy7wCITI5IbvVQJ17VC@w&MljgU#f1F~`BFvj2gXHxlRHp@uHo`(k3smG z=@7RnxeYo^$eQf~lYznG!}8oq!#$|Kiv7}{K48=iz^J!%wDQ=|s-MZLtW=_&Covtr zD4nw-lTRy0$KF;=b#92a=OR%_bq3rB^b9mj$hF@wLKJXSb97K$G25I`iKk^ z-Sd~W)zA2yshFxVG~voTBAk2P@jd%j>*88&cmtJrt#G(O>D=-(qk>st&SxniI?|_L z>b(g*1J|N9$9(($#e_I#D{RlU#aQjQrCGrz(fzu*s*QRyB}|S4W+;#aW@t>flhDnGxPY^oM&cGECrbL75S}Te$H4Zt%h6&O5{g}tpC&E z%o-#s)m%V@or7}!0WoQl@POb2eg`q3Q~<5iXXm+VP+!`acy#tJ2kpFiM;#Ug!q8}C zGv70w?@BppBS&}nTMG%e;zw!)kNw9>B@owuPfHw9j^ytwi8YpRGqLw8)`tk$O zYxZyP_ZoHfMez|X*vw{4m*%>cU+9b0SnoN?dk@a>?7;~i3KQo)Z=>*SCWa3r(@kxIt*}*2H$&Fr1|Tu+2qIVMal_0 z<`~D%vh;gZdnXbR_yCU{CC}M!J0}GKK69DwUt(gRnuRTB*tw8g?%zJb4EfGwT z6EdU`;W6N!G_zDLd|i-=IkvIz*9mw6Mf&!kq*>N3qqLvwv&;1PYlbgnpmd${B7?q3 z`74|bMX4`Q*l`?~NJ1lLmaHy|j0_=O`<)k4(Jy@c^vhzrg1&h7=X8ekgb_jTA>-?* zMX!>a8TA6Ow#3`=5AeXfd}Fomt3v8NpXUpsH;zVwH zxRov6SJj?AJ8|%Swp6b=IPT>)-$NZVO_^r1!tw8OxGogXC6*H*wurPzTMhp~N&8PC z3GT#k?(8E@WRact4chPOuEk@mP2R_80WVXVP!>X-pzx#D4<2P%pm4T}TNqod zwpet+Z5_VQmEh);?F$UYrDffu_Gr{Ekttj>0Wk0M5!-W4w`MFukrBBcmo3 zQmvi}&FB>g|7=I(YTlflW*mWPiX9yyvkzrc3oa-KZN)>#}W?AWiPNs4=0KdK#@-%qLgymNBL%)Q)h+z3#3(5UxP&!{VE>%IV6qQnOSq=_IMPj z9`oV$9>QOH74gn~OGbPrhrKRTP&XEm1*VDP^8Xw)f0k69f>VNV zM{CAk+g_?=krY?Oy-A83|6wACNU?~6K1nl)%fC1}dx!lSOpgmv-r73;shz0MQhn+j z{$Azv_;Hw`d8|R8z+D(E8SJw|+eg=M=bgaTRHN#Ab(rqmeacX(u?N*7ejZC4#pUqo z%h*VD-8Zi?3gx6aooy3So759?OquEUQ@r_DiCyCb*%HdJkd&F@l@;f8Mo|SnBFo|P z!^Ft6SpA`kgh52_E_3)LZ>ZsmO~=23$5E!S&EZAp<;(b20I7Ga-D7Zk{`L|9hW)G- zMGi|+ww&PH*?VYq6<|~0O@uCNX`LK@;GEL+?}97{Aw z@ZOO}IHOhGca$#WrbdNR5C7Uso!!Az;~w$SA%E1CjkI*(JUFEMb%q=n*`BD^t5b*H0e|9!}Cw&xP2`on!J>JjwN&#}sfcf+u@0TlREK>8ga zsK#%~=5{E$)pqO?35`GtZ)~{iB;xzh@^s@#vL}6_qhA082(l)eS+A+cx%glHZ;t0z z*f3)_Y^Wy|4A7r4EjDLIHj+ZOO+(89>H$shDNzmOQGI5$+qcln#M+kp5L~T45k~vuf(_9oaDT4imM8&? zo1Dor0LY>8j#^3$kVikeuPqjrh@cNP$duPLmL2aSj=xNnl$5Lt*nHX%w$?5qX9!#u z>spq08y;=k2!Y zT%1kCm#Bc&a28y5oR+)itv+oKuoF6aEUS!upDT-DS^g5QV77#27mk`Ce0~ilL^GZ< znPDhj37oz!|{c8&uYtFLp=YRwZ@kNg`-bv65;&F52ZA(v2b+kg|B+`pT^Zb|1|RWOZt75j9!kh zAuJcC?x5EWFKl+a_m*#Dda5xww12BE7Cdr&L~A`7w($E#2y<{w4IqQBLgMkS4g>b< z|Jw{%e-&DCA&XJYvPW?CGXRp|c>%${%1XYN82U>l!bH!1EsNFO7UuC-n?kXI*8nNd z4|*PUrtbo$sS&ocF=&ud4)gnLTX@pnZIk<(@F=btLdag$Eu&k&A;v<~dPV;!#4D++ z*5nULxm0-UIA?2Y{x9G^cG7|>Oyfd%p4d)2iDIWKk1zj}uzOo|b>w6sNN4h4<Z_0o^t z?-Ec^qyJ1U7K!5JcVk3uA?7vEf5rrZ(#n(iwYw-VoRKHr48oeXOX0;eFG# zfpiOjE`8&j(4lFP$TY#{xiZ9|Iq)#@_=T4<%WSZ)pucP$(4lgmtxzIKC~`4-ttN_j zId%B3z3^{Jcb)ItFksDJNdATNEarO$VlNEH(2X&uxQxW&?s5IsGBxEGbxlBx)|Cih z835%SL`A?hZ~iV3zj1c>u2?vqf%nRU%Uam(;3B0jT$ppG^0~e~ zE`mN9`)N&!9z&|?pi|h^OFiSpp2zz^dA}kaua9mdJ^-cSGEz`~Y^TB>g~u%LW&W}h z!MP3_YjSps>Fg}ahQd8)q=fOSoUqE1Qv`!*b;FACm*6)T%%FK=-Vc8-(agkLon|kc*ND0gv8EYS!XY|s-9}G zX<*fD1|2w-6Y_m#)rnnTL<&qbl5p>Lq&+DDh#M5wP-V6GLK{Mi2No`*9#n{Q!o&>I6k#fjvf_iq`p?5yvK@XgA8} zVc$NpuVs{ngZUv3lb}@Fw%(KHEa-SGOpu_!q4K3L*neG*#yFWQWT7~wTyoV{x$N#A zBFwnzO0o8-_-8dya)c5}k4DfTn(&vN$0w4}6-fFQtiZ+<;o1(qR1g(feTYgANVTyEGs z#^q_mZuWbe&_Ld_+HR7o!OkE-FD zGgG40sPP7*XaJiS4?Cp0Ic_vpIB*QO4xM>xVE?Y$fYSlEb9WD|5`=!!K-yImYG#HKpZZY`bIkch!Mn4D97WcD_m!m@9H9j3w8Fga4s#(;~ zF{r_k&+AxMNmvCs!?F|*zHs8iFk$YlD$+}4JxYDxo8rXssofGFoxY-M?NHLB6(5?K zJ(DG^5lnb_Jx_s_JaoT&t2t^_|M8PhqxioSz5Ai{D<^krPLFgg$zfF1=F6VglD?mR zj0w2prYJo`It*Kis?H^wbrevCRNW}v+hc_y{-G9Z2KeN*7>4ouLi5zg{lO*#Pgbof z%aaz7R4k>GF|2F>kwZ`q`R%6cxiAr!Yq7s2m}bJtcW51(-J2I>Vc8@*W{F*4pz&Q0hN-F;uROU;Xgsz97PP97r*z@H`1lj zMcw2Fh*yl|o+g2xr@lG8AJA2_SgzZVVr)KNDeJ4a__=4s2(vYLYE6 zb$pfYi4r05?aoP6SmQ(Y2|}KxfW^yQI@|IV!#H5> zrsp$V@4>qrPnZu;*qtD_PG{ihzM}^+F{g^f(N{y!UVVpTV-H9#J{&%jiD71HaM{%g z*Dh57;nOnQe=oEJmG=O(zxAO8`LO#A_QM|O)Sj3Xrsctkj0e=IsP{1*!T!BOVBt<0 ziijRl6V(~JAi~Qcpr~KX{AN4N$O&dqrgMI_wD$PU1jD9QPI=S5UPY;`xx)D@B1ujP z6j0D&_?y>CKtf5Sr|@>RD-Y~;ftdc51Q@G(Gso;_QwD2RN7F>!6ISfpAb&f*EQ4-- zY;6B_s38_!eErnbzYSzW0+`F4pUl5U}l=P<1fx`d$i1-th#bS8Hm7TQCvk-=Di;+zWWpvpQhv;Gj zy1Dh8zTic{g5|+^6Pw1n4iH)couRVen)|xex2T1xbZ*o3KQ)>R1Oq2cbr41-Eb>Eu zC-`?6EFA=yk^x3MkofU&XG5iFK=3IR{3~oxM4o+V`1KD-NF&cX9({=I(L&bWBSF0| zI&w)b7B^ctcoKMNbUZO`kaI7aK&a9(H()Qgm1Tr{XnUZom)=Xm2OLmR);G@Ft-n*U zZo?rVH;4kyZDMB!&to+zsy|fUuQb3{XH~L8YmWbj_)oYY!i9@t4sicJ)t9m_2UZOP zC}^!G@EuZIYF=nzMPWlgP;z@Iqcq}4Sf6nX4egaO+NZ;P30o3J2l>GB_BeO3C%mEX zP5lRi!317w(3rHdAQIU-5iuY~P2Gu@?V&wWW&|(shAW;O`^O7mZa9RWW`*JN=eH2n7>C%HX(3ziJ z6Vhky%L@+zXI$N*aFT}!6i3T92E9}os+VsI1Mbq`z?Ygcjl0mcP&@zg3}8Sf zy-`O>EL%3G^a4t(VUL&p9E}&R^dm+2F*`4h4+NEet?$HX_}D;OBR~*7@x+yxsI5Cx z*b+6g#f^))`#5)bFjUwLi8I#zF}GFMAg-xsj|2onoI0i~y^YX?V0u9+I6TDt&^VAB z?ZbpTtqdZsnyp%{j>mS6AR6j4+poNP%>n4D^h2}=fIMs{Ay@oyZPqRPW`$4IE=h9A z;i8cLQuG%VZKI|fA!^jQp6qM;LrXz8l;+9)x1V3l0Nf9G&5$t7uk)=)z&FnO?-n%{B z5`^Kd3b@`7Juv$!H~%Aj2Qf^N^xz*KQxNoKX6skG61|og$LRfM z+7NyUpXLr;3IbH0tgEE1Vv9t3&2CAqQ-ZY-pPT5^Tb2 zfqK56H%>DHNdVZfWu4-veiS!dW@-Oy-rL+^bcZcgF?OL8MqHzn_;J+?p>zMM7;N6-ym6)J$}yB;TovaDshi&?bR&pycR#lw}j4tTJgKSuD^h=&U?_!eA#wh{?q-9js86^pC&j4*HN3lk)C^ zgQTOxIT_Nc0|W{B@Cd$gck2b{i*^{e*2?2IiH~bk=bOdpqX}%e(xxzG>`&A~>KYav z*dp!!B}3b(HsyADd3;-1o59)yXqu6F5u6rLgn0yv=$s&noxVy9%^cl$NN=uo1vhacLle;o;KG>Bz-Nc1MSl!+jr z$G;aTThwE~WBxlECQ(9_a5F^G{&H*Z$!n3H_~l#q{SoVD?i$B6YxQ(_`i1Vjf(wmTsh;`b};DbW^4& z>O^V&ZZCZ^^>T#t?%Bskfh&<51YFLg=^Fc$66XcN*8c^;X#}MnZ&v81I@T5oE>} z$@)4W5!|3;dkUE!vBwAWJ{&s;@^}218in}wsb@F(z?L320um&BTVDT-wN=Qa5WFqe zupfVr;j3}W&r0_$xyD@F%Nc~TB*~&ytgbcV`?-bEn$`z8D{dNbi(o}?qb(KO$Ej? zKlHK^DuM^L_Ycz73Sl*&9!ma0F(owgFsdi!$PZT>fAtZRoeMzGE^pBO^p+$%_N_hy z7971G^Bd(ZRc7^@bp^f}k^zu)KC0=b4k`8_U}YfIfizjGcUydcW-&5mAKl_PAgCJTZ(AVQ!o7I63{Ql{a&<6bEb z^7ZGe5#fc~bt>|5+Qp$ct}k8-ck6%ScjAS2mwsYvTbtT26h+ck75@b#Zn>c0Y? z@RD2@tbWFMaa`2k#vO?Q3Mqg5MAF))gol#%k7caf9~lFBi*{Dlkw8$1Sy&eogmG{V zJQ&py6!teIc*OooBEh9l+}$k{PY6&76bhuJ zIK?eU3&klA+=>?Z<-PaLe1BvnlVmc_?mn`=-E*FkWwl=I7LJyWVuFwca2g&(nVetf zh=%L3FPIr|(*&S_wWiA{ASeBIrCk#ZyB*WKbqn(K|6WVv!D`c4?*=|#E%`UjG5(mL z(bq0r+;F_cSs4RT;jnUJgW`dOIm};Xx7NxU*NL>4oQyEuK-*dwKw|>+2gQ%CYyOKU zRreTGf7{?s1?W3(beHG(iQ8Zkn<%808t5wK@m~SH2!{~_oMW+eadBCe3bi+Tw2%mb z3r??miRoRRcoEaP@}_^XlJT*~``~5`j`9%1hjgT)k1)!qJP$S1{M(hs39ipm!`hS) zN$*vitX?R5E90ysKJ9{-I|B~-;)uR`vvh_}#_2oP>@-tP`P?s@C1tn=Z`@EQJZY@d zp!~@>PE*nE2IA#PaPtVJ6Io{`?tu>M%RN`@CYX&x9(dSa%(O0Sm{$K0B0Ea1hBT`5 zxOv84jKZ1sMIUTja^6T4BZ8|@hllQ~t7p{nY zey@2N;L#?b9Mn)R5_q9C;-4M#Qxu?QBDu2B4&CEjX^4&aEWm5}LQ@irKzxt2y?I*6 z%8-L@-FQe>{97tEWV$C$&c7IgcSEm9Hcd03!qPe?Y#J%A!2bnDKUTUk=C| z2XT+a#t}hGSunr?Xz}c&B-KCopy&TgG*;|6w3|)mG>nX4?A%Vo-cAh-#t$*-bKl98 ze-~+XC4{_O(n~ z@;@bLI_wn8i6#IVn*hw=rI$Qo>-u7c#uf{+$O8-Z576|bCK)vG_5J#H!~NZ6 zaZ=a|GYd3ci)MZt8)a#*x2`>54|-W*A&f}+pc9&!lbxLYmO*yo^C%0*5odID4{L~j zTyj>mY&yy(-mru9h1Q~LgII8}>CZIlNqU;@nbDS$F{BiJc*Ph)F5U->iVf!#l%&?w zV;8zk!S9MIs^!k0co;D7{oI3&zhxA1#*sf6jbIdpnZloLF&!n2a4p45VwV=m)vOlf zjdTj4`OA?EpkT$a@|v6or53DCuY&B-b)Rh8CZ5(kUbIX!&s)SG9&BNQTJNd_u{Vk; z#(_XtVIuNNyj~}V?!;Ied+Ia ztR!S48MacmAe~pzAcA$#cfM>#HTfw3~Ew(u9t1K%e!sO!JR*?v&mwG%OjzYVBhBMIY+!avB)F{D>(V^dZ-4X4W9qj2T6SX<(L~CgV zjX$WiFF%UHRz1Rkrx;fTsI^_(F8xh8hIKRL>#;%1sU)jdH?bR7GL$_eUOmjhsk2Wt z=m*#BOIntl;u)?q_&4|XJ6hN$Mo>{k?wITTtw{P1qJ4B)J&;SxNszH={7ZJW|Bu}u z8Z{On3S@{v-aBe1quWLrzojYu{E4ZU-$uL8&6a+kA@%;jDROQjK%?eN4niy3@K(ql zRZU;&JM9)WJIH^iV{^*a4k1;f{;O`mXFYc`A<_~6#Let(5MK2~#ACwR^cj6d^*|z6 zrgI|})bAAYE@r+37?ws+t?MLN$125=!PEN#fV{J|N+Hcx6?>n(}N_$t2jH$_Q}Dr~8_)<|Pr+i{BL+q@g2|9WTR~EkO_J;=k!o>(6oGXI!r~&767CMj#eKeJ-w0+*J#5F%Ffl%a&W&Xnj)s zQ;4)WRW#r?yOvvY#Spg5sE-31H3G5i&8d(l1xB2m?4!%5vA->UeF_57=+={TO3FR# zmgAdYQ?mGC4j(7J!mw^`!?8y{&k{11Ecg9yYk4oh*i$ou#r!!T>j@lC`BS|_(E*N4 z*QNk1kwG;R62IuxbSXDOeI57aQk9cm>r!RGz_?nX@|>A;^>t(nmCh_Q zTdvqb5nmcBTYzU=ksA{*%+c_m%5q7k$}lvOv!vyuK1 zuYuEo;NKCMfQ?I@uf0hDb3G-byt*dDJxQ*~Y#TRujPZIj0dS?5hY(|iX}Ti0mEdBn zAh_S;ZfN*>?I(2ICYssPk>3gUbQ*IBerflVyc~$V{WaxyF8QIKKN2f%-ZQChaG7sC zm!`?bzhe%4xG8Qiw?Xvxu7fJSe!4EJ-!168{NFz*wZc=?f0YCv?E~=L#Om$+IQf9R z0?xmo!HmQw)^6N{KQ+|?5Hb~6eCpAl%F66=Q)3PeouuemP=%3>y1Is8A~~lzx+UTHSy&k=A3+EyoczE#&78;`AK*zDx*`hLC#WnD=0gzl zRsI208@u|o-R&X%*zEV||BSWNVR9@g5}u=Y5!3X6DboCfIV?WEJcLIlXF5a!&$-IM zzS?vDgPJ24IOtwDpxnqgS6(iR4Y0F&CtLVP47nnkH4=$L9?R>B0#(+gCO%*fp66nK zEA58AgR0f3%lcP3pg@j@knCDSwtOS5r#DHd571t>y>=_gFvrR@cEGKTFr&#GpR=rC zkujb1&6$42A=r0xU(N!wsJz~~Z?S|kB%uP@RzJWeLLI&jP0JrCSwd@seGc@kLO`wO zl4N=}OoO&<_BZpQkcU?uN>0Yzq`xpb23n8Mctn8NLb&9lV;TV8ysE@Den$T#NdyNX z&yW{JB!6RF4l{m2LZ?OH8MQ%BO|Vn;3X)}5EYbP|HwbR8R^0CdD(<(Ge^Q8$+T(r^ z)oOMks3!#g@BaY>SnRxAB!+|?p`~PWJYo=!7_iNYqM;?5Ik&aWSk8Vb0+Jx{YzU#; zI=d*FeDQLLJNb+LJ0-SkpC%#(&{kE{82pDhT~jL;H)t!LJ)77-P_rT!2A#=~vs78J zv)BK*!EN+B(7yrFn9u`XqV~#OBk95bi>uOzgx35jTJ%ZWrv@kUfV64m;csRJPGigs zEv7e2BODWuE%VRUsYQ9SIRfN{@d`DAvj2!0L+nBM%hf;_V2YF)n4*{`jer4!*ZS2 zO8Por#}K!%;Z}G5j%n-Ce>G^LXJpaV5>k#6Vqy?!a#4wx()bX_i^h#c_VbetPur*u zJ{KIs588^pzR#$&R3`IQ%xda~M~$Hx&kKi?5lw8N5U8AKgp1w0AHqmInYdogQ}8jp zm)`~WU}U$$3tGsJrrq?vV0g3=(tEdkL>-hh~ipsVA&wq((L)qtjufCkoA76C+u@=2bT3Q-fhu!FpgiOsN}#3j z_17AYs@}@F5<1O##sGZa;03hVi_JqtiY6c}*rc_eKOw%oF&zsa<3J#`A(g5Lb2ruG zoTC1nAbUojDMLXqlT+g@H9VdOWxj$|IVB*eQE+yBjL09<5i^C*jn{#~*f=<&RF!OB z%({&+GPRODat~DXOm1QqD0r*3LT*|vfsrQFpKV$Ett_~(AmZTca$RR1-$-Peiq$>= z*uBGKWpM>pJ=_4@uOMK3yN98BQonzH;rS+yebzsxvb#clVXUOJbkSj@Z*EvUBLP78 z_itP_Dzsaz4zX}m{RP{f_JA4AE&Z#ghKTd7&^4VuUrWvXclWC^zK;!)!g%<Cgz>&3q%d~@ar%DIess%M5n)I z+)SD=;6vn)@A!X$uqc2{VsO9eN*dpW>;w*FKZBlP{CIg#u^}2_KRQefIjztSzDV#(Mz%14}<81S2Z|Sh*RQWDDxMB_Ye8EFsR|r*PjXa#v`)_S`c1`pvA{E@3;9p^Pezp z)`xogtahj5jAd75=W4PMBk)pYfDvyKY>Vgux{OzhHEDX{Gx}w&t??KOFv8!U#uS#6 zF{?nGY_vv;rp4ZcO7VsTuaDqpa3DrxfNswJR``Bp%a4nm69W*q;PM*t@+FQg$mpQ!Iu+HZ3SNk!4H&qZDrcm#^wQxGIZ(Ais({O?4PJ8br-bw)R0Sh~-W%w0pp%~``}fH&&C8)F zQ!M@#yxGAR2CT6>O~Ato`oCuG`eZ1vfJ#G9bsaH`{DQE(j|-f<*i>Z}kaGGzGf**z zn%ii;BFi?3h(tp((n6@(L|9@>?nwblMU{lVIG^eN684i+Ium!V2{T=MWEqKzpE>|1 zqlbSaI@wzJ7h0CKu1Y*A?BQ6<Q z{w{ctFJIR4-7(cuA7Lj2A#E0apnf)F=?R(459$N2Z0L%9L?YqTm${n8Ni2X0gzrad zoGnj$Y79TeJIJlp;HSlEeUUQi*k_X;H*uv=)!09hGxi9(+0Y)l&SvaX#DdVpfX;2{ z+>=5HkeTE^9fh`I4|tpTMFlzwbU<*I7tiTdV{9(g-x^zpp7oK!-faVg^4D_F5y902 zpE@W@N?qlB3Z4hNayLwO!Qw$98l|jDUXvS+10-`0fjVDgVOj>#dco z+C#o6FGx*2k9ZF+etrdYf-A1$v{LT+Gk)%cKo9k=Ip3htKhD-Id#{eG$6Y+^ryqio z&GA6$nz5>km^=1&pQ*2AX=-f!GyFhC)CZ;7@ifFll`Qa)gwSM*4i9YcPL{ zxJeLgCZn`dTr{SRg+Itg-GE(oMCq5%$K&TR@uCDok@A9jIJvXGNL2gp(TeOs!zJS2 z^R}R&O@9HS)j7d+oD37>1FH7?Eu-}ujdpB&O#8r}g-lM8fpNNx&koikIs<~|0sqJn zkXJ(1C;xEt>awjV!dko^Ot(is@nzH()kX)TCS?syr5W`FqYR*b<}T_*)pMh$P*O5Z&xp2@LmidKutQ<=fPCTy1uQA%6iGc} zrqont!Q#B>2~yz+(1(Qhsq+eBJnnlaRjnhaqfru=M}+I0?Tqyo6BQ+)P4=?(xz~Zl$@%iapBLna@G~(towHGzZuJMNmNb{xpebVfg6%EL! zI^q6O5ODqzS2X|X0J>-L7Wti6a%8RC7Uh>)B71VhhJgczcw}YuPIK^Vy5*Z3Bj|hz zicN|}T&c*}SI=tG=&Fc$d3CgK{uJ#sLrww9*@CbGd2sd!!SKjT%Acy4z1xd``q0NP zNvnTY8ODA3EiytTALP(!SUMZ1o<6;tw^=u(v%?8i zzo#Vnu@`QP?ME(f%gKhUJK%Lr?A$$a=we^{roSHR&vRr>M^3MNz~A9G@EIQ}NzMr; zmlNBzo_HnfoR=VCUPl!#96p7<%2wDm@&!sQ^sB)9Yev4H8{X~DZkR;%qAuCB{}7|6 zLwO(<87^Gec6QJ9p#LvfrUo0*V>@k8_9>Q1+u*AMG;yk|&z*m>*$W7v{Vu&IG^`!9 zPUF}j$TU4Il6iTdKvHlhT3dYx*jBL-Y(4Du-6n?Bwjj30P%RUG|Ljd5;hPt9M?IRh%4+AWsT${(_BOgYLt zXhO2DCk2c82#2tjEvCENWUn+{>0RyflBLlOjNBiU`mcBEB#cS1>#a{mmsWq_eLi9a zago%2>6-B0U;uU^!UAX3{kdkSh%HEfc_nMzf9$=psm-2001Zj2J9+y*-L<9 zXxhjaDXyOhQpuE8aWh3It%H&fUe!NBZ(3k+yOGG_B_3$1Jh^9C;1t<%c42;BE7%G| z@qI-NRf-Ajf*Fm8>*d??q2??={Z+C^i0vVzOPCmgmIk+w_c29#mQn4R3%svS=$C>w z1UG?75hNI{vvNT3P%yDLj|`I#P+aGhZf)(=KE*SW(bU(NX6xZ1h6|vm{Vu z11i$oKZ`YYu8^;V400w^`~=v(n`XVsp4gb<`B-$MLh4%)^XTxx?ii+_ zL_sG%?r}u&4B$+rb{W-g5vN6BRl#`2yO)%t&IotKY)mg!j<9Od!mOz>D4Y^nnFVj!| zf#S1swpN~uIM<#lz z^O#`9k`dHZv+$}EHsHCP_wah|KNTf*@RGtpD&$+ZNWtPrcL^jtU#%{YyN@1=$pr)F zbW4p-7|xkR9<)_|roS}K1zR#Ag}JZzh7L@^Boa*a+~rnw>krqHgia4QOyQ@jhu zN`qt46U%%bXq8|AS@J`S6K-UgHR;U#D@@!IjZJ2l2IHdjF?6#8e5`;;Z!aZG;WD9G zrGAdg4bR_M<`NhMh|-9eQ7T)f;uLM40Ao^hnwKdv zF34LwS$5PiQ}Lc{q+=0-b)8^kOEDOVMN!on5v@`x+^K_pt+&tu*d<&p1jBS}%>SC~ z>(yf3KYOK=E=9-#2%w&(kT2{`8kA#a*^Yi5LD~iUZtvx{Uv2H{fzLLdSeGOFGs;}Pk2bc3 zoKGa#$%U4GH79MjK{MEyKg(F>17k@Z%QmXGvH>kZ5%PsgP5e6?24Zf(8R%ZQzY{K` z-WZ43JS#MXV;^CZJz_y8nY{KNM`a=A#`1VT%ezzDqtN!Wt!-O+&$<9G_!l)DFb_lQ zLnBznn-t)`=S=5C-ygd%286WkYZ<`DlJOzW+zks7<4r#+g{Dnccq!Y+SpVqpq|g(S zp}NM$+40It6yOD8b;?dAduaJf#6h`s0?5nMMAt(rQorf#>=URyrv0?>15WgB3&%!|=;(30(=;floI=W5Pw2}g zn3xxLd*^KYSUJafd zwQG(XZHZ4ZM9H-Q(3=}aBGEwlj6j|!+}xdXi1r}db<4=N6Vmuip>?$jy}^v$KmJ(L zfX1{#C-y&C32-KP)ZA7hc$p{?d?Pa|{|xsPSvD#Pd*7@<}I@v#% zqOE2f>>G_#<;vW0>BIEn_#m!E{!2~aN*`Ce{BBH>?Ky?WM!ILYe>Fl1YnY2z<88ilAbX^3JPuim zEM4uceL=Nr`NEc(CW{*jxv*KiOpX~qYHuZ62gBKZYO5>4Ngl5O(?xvdO28bgX2`{5$>hBay5kubbsV&Mm6^FRf+Yw%qMBt1V7dKp zGM-+DddZ#P{~zbJC@8pi#mqAcb3{#nTaj7KM-)HP!pP%KO&TwiG2P&XseJbFgwn6J zX}K!BE73jEHJlRnE7NA^&(ctaFF{@3(dpOiNDE!jx=4$xbW-Sd$_jv z2}4P;7FHw25=Gc7`x(O*j!n=Y)I+asf#(@tn7uuvvGG9|<{@Ro6Xj6Z@K%Jm@WR`L z3X_kOzx@z*`&q6gBBMQS5cI1-fD_Ik2#f`-!+tmD;pjt_&@z&g3=}Fpk~6fZAL(No z)yks+LC51zgOm5l4$n}Fuf;y)tW5lDy+2Ms9s0nX1|WAGzN9d-c@Qor?;S&Fel!Sw zt*dYV9dS&$xGQh2BWbT`&1l}QyDJN8`+p|^o_(in^aMb@b!`fd^4tVzj^rV_5904z|@-`sEJR?A%n|CzU0gx6CDBv-iVLs zxO@Wmve^aVqUx`P7|l4{f){l_oW@q1m6-(KIlko5ktET&7U8MwLjj9SOaZ{^<9e_~IL6lmY)W&28y9OQDv94NmO3t?E92`voVJV42CeSZKjhtk3O4 zoD#AS;ric4E9vs#p>x>&CHE&mZ00fr<`^&~njW|X4*;`nkC$IB_jNnXb0%(lzxw6! z!x>_uADxP|1nYB|{U|F(Qr_#{HTWZZ%(iKf+I zN_06h_oYO}Qnl5_(N8XzwS+E{@~YnugSHKcu~Uqne5n%D#k{Hciw+k2!F35^x&{zo zK}c3dEZ&K*B&!?ELF`JIC61|;g_!AuS;cv8Xkw+P4$UscnEu$tcIEt0x`JX@spn&c zqNlQ_^EKJp$*Rlrb|nTVTp-fqqYj8M#(sZ?3s1JpmV=P$6i2wxe$RMLRAl~&?3N8K z@y&SG=!%V*6c*h5Fi+F9won0zLQ*Fn8NOKrQDU_OMM`5SRLG2OQrp45ptt875uYF2 zWUNv=BCC^L=;^ohriy}QllgwgqZlGO8B+nZ$-k{{by!S*B#ZVq8Pojb9VmK-K2OH% z*7$X5(CGv6uDWhB`7Ei^#9&@@dDUzHsn2B9=oNH>IzGM!U0>S;IhniCE#)QHoOn&& zFO${J>oe)V1RhmZGqHew>bAL;aZN``a6s6H{d@(l5`89jCCw?+ejGQy>pG8YI|L&X ze67SyJ-C=bXYUUFK71w(AcFAHnZhDIdNFSqle`zix#=;Y1sH6P3B1yv%*PPz|Gqn1(4TPlQ&N|@^2jsv{MOer6%>s5ljP6+XDK%O@ z0gX8UJqXB-LPw{>39Y;pTzf-&V(f-~p!WeOaGfRL-+nMOX9K+?n| z(Kw`$3=%V+Vr)e5nH4r{mXp~p)dO{VWv@g$jon5(Q}oXBw$l3j3Zx%yU1LInmaNyp zgoK*;W^YJih0LVA-e*tpk>&$6v>okICZy3t*cJN&Wpf#$#SeCmW7%NaRFH*;B zB3C<|A&~x4>NF3r5#x!aeB-#Rys3y#~Iq~O|tUhjj-#wb#9}rnI0^f|= zEuiv{NvpmM|A7BZR^}OTB`-23P-vJZ>3VREZUtN1GHHSdI%i^a8Re8G1jF~RC^_F( znk0Xcq){Pqp%C?Xj%YTR&G+1cBI^6yF!Z0vpNz-qs@1qA((_LRdG&Qx@4Dr_1ZiDW z7jc>ozC1GD`Xfl`ykr;c%omW~ZJvtU>f1ou%m2UjVrjsc@_wXXrnXqp8D(?6Tw494 z{k@}DF{Qq}xF61+V8WAtl-1n^BjoC())sX!G zo>-WNm*3N4F47f^+0({62u>oFM7Ab|^4VXOQcXws+`bpY_t>_5>Fym#5}nc`Ol

    eh;b=yo@siZX=z?XCR;YkTUI^yZ6su)v*d#lcGAwu`rA-oyh8$fNpKhP~`3A z!$Q^2w>2!FRMmF12A+C`U81M&^q#bZ{S5f6ZI(ivPRCADvfI0A%(ogefhTfucGxBFBQ)4FA|q&e^sxA?R#Yb~N=Bu88$} zFZzj#FY5;Bm3fIxkhBjy-R4u!6%NP`&7AZX$~$$EQH_{aC~XMtmg4$;y_^!@8g0uB zn20jvrE_3?_pwnaroS*~qW8@(DR+ zZx|*e<*oYmy_jPdE=TuBf2#0%i8$1;{h00k?6POUScbEt_^&Rr$2+BFOfsP-@-4tj zV3c~@OT+wj5msZa6c@F+J_-h_?}Hqk)T>wrGgMS_-gMf)jVHj7qRh*^ei0^dKf$?% z1u3yt`Wc%c?)Lk>0kbcC%`x`@tUdsP&+{yT){5nG=7=MYcX>Y|e@35fUtNq1=!AU> zcTg!LOCl*0dLr@{d+AkVl@|MrY@~b*hpSA3y!Fei^uTAXZ;rtM=)c8zP zKxcPaqQ<>7C5VM16j_MjdXv@Ry;|rU92-(it?B^a zb+7v(K9_Ft_Yor}c3YRY(&PZni$w5hN(HY_MxW8 zQCLqEy3>V^oLkgApK|27dQ{-|!C}lGmx3?!qOXG(UjWdOI9#0Ih_`=*#W*)4ZA>=& z5mKFO=F|14z_b8w6QIT;esE~nkI0c|(U>TEX&%CaTFzOPeGaqbq>+dBj_>E7$M5!7 zS95qS`5(R3?e?yZ)PxYtEYuVs^{0yNd$dY<-38AIo ziq!mpuHGMC8+Bynp(FY11Tb6j>rPp{bYj*mEVemjcDZy#SB`5n%4Dh2mo4p;f3|x- z0z=_m&*3pj)WtCKKarOeU7KFyW6&>%vs8Iet?qx+6!V=0#{qw>r5-iHX=#H6{PG;8 zOpTB};&1bQV5Icvzh~D)+8~!HpY1f%DLb)nnK9*)m+@ZkF~s zoJoDd)Dms`xKl*NuQfz(@q^H(_-hQJeyLmNRTLP;#`|CkL`tvCcTL&#D=fzeT3W`ERiQK&iIxnvaybswpUI2gM@yM zHh=tmG=@80Qsd~4rcQ>1b_ME5w(%egrlEy$YLL$6TxTD_fPr$t{_jU=PV+redv7;Uc?t7CRbz)dwZ9mP$s7I8t}$RV_sTk0p1GBo`! zMc0cMfM8nssTZ&0HGY-de+zJ&)rXq2a7oF$x2Aj1-tDAkgWvS*WsJ8~Ah{J^j0% z&#YxJR8AocG>4CRu2|uWMHY}`%lXgjt*KIZwZOO9m)X`vzf9k<{x(ikz(08rO=-t7 zlu|44_PrQBwkETq-bx`wKr*~v%sce+xp*&ul$Gm6kw~zQa07$QN;7Wy$1hf25^E)v zNuXdX3GD^2`Cs$K6!7>M1=|h*06$A7}k7t8@VVBDcx@dY^Xl zQGG725P|n>zXy~>_0_Q42$|{Z94e8i5F>;Xp zlYQjAAV_B{kj6HzoZvtSm5}$S^jYc+Xv-RWqybHizqL+E zgk4FP6 zQXFZm>#s4LC`1_Hf}BOle_@`f3z}*-RemfMBN3>j0uOwm{)4fNU#0W7HfBOJsF2u) z^8WgdEz0EByXx2*J^acZw|m(DGYVQ$qrb}`a_psbZ)(;#c|a*XWjG+`PgJ!~HbCv+ z97rOBFT*7|L7v!5n>m&Cwu0bdG^g6~Xf3K|#G^5Ky5~FlGmt*Hm=EEoYaNI~bIRklPGWR@L&y?n9mx>8N7Ttjm5V&f7a&)D$tzugY$ReMm9*^57&f4F?^ zhE{)W14(dDg3Ri~FMf=aS^9pIU8mt=5vmY zlSL%9_g(!Esy^L&;~9m-`H+*S%0~k+?tZ30RG1D}XXP;$`Yd~+t^4=NTJmPDf%xAO zJ`iavj*Pr^s=QFY+x65)CD4f*I6)1ga?_3kM-G;&hK(|^4CDhDruhv&zW7tlozIZ? z;xkV0s_i&ECFLv_gQb~ORX6`vHLnHvC`e7wM*|H$OKsrL>u>SC(D_Ud_Oww)_j80- z%6(v%NxptB>dc}iAam-DE9^bVm*tzrrzO!yJs+%$L~ZxF%S@*EnYrh+Khh?pWWlYg z0(Yg?7U1H;;Pi2DGS^aTN1z3`4t>u17|5>+TbKOlBjJ|Vk-gvemtyK;%7@j$8`jbp{Z;cS0opW>efBb;s}Q+9m!SHX z{d0ccM!6icLl zXom>crXgA<|CFOC5xVq`~cqz~iDd(gsv3VNf^6&}yJnh`eEKo|T7xw*;;#f~Vwah0x zMd^;kujPqHU(6D`sI~7BEk+dAAE&|Ko(Fk0ygiLI11jXfyzK10w&z*d>HsGfq8_znCJ;=8qhDKcs39GXoa}iK8;e+4J3sc$Gc6FQ@B-CY z>w+B`nW`aS)qH<${lzH51mIq6aay%GUceA#@lB0nNqv^$T!Lr3rP1>aSf=N@yT6oT z2kcF=*5dKBYu{)G5J4%#cc3y(ohk==@u0q9*0*CK9x$5WV)w3R7PGOmP*vknOIEr5 zq*FK7ziQ>*a}6yLkiXql^j7J#|=$NaYu_0@M3a3U? z(G)lRqY(L!VvWeeL-~E*D?X6;km%g=J|GETad2GWqR)_5a)=-xC1=0zEbvoLrdo7y zRbJRo|Nhh3*E`~K+_;z_(SK!JpEtT}WG^<5Ga3uj`83~@U4L+dNL$8I?K{hV6|kRw zd-R$(DkU48E-65@B}b?0JwoAJ9sLW!-6JR3-9rcUZ;@j>Ge50S{p3UGyS2oy6}slH zl@LRVd+YOuBjf!2Sj5jE{mAqKY|7tSk+9ejhbN-fsK*@{fnzna>2!K8#m3aY00ut1+ukp?{)a3@-cO44kNTILZz&JJ&Ot}P*+ zFisuCROc4s2c^#2kS0k&BZ@9c@|s29G-(`g#q&FPQuU{Cjc~5+DJ49Lj>59`Ag7=u zdepZS5&%kHq~Ohfc>t_zUg<_XbG&TTMigJ89gGFKxCl%SLnnM)%a?84POY!*musFD zL?ZvncE)X8?$Y*YU{o3JAmi>JU-MVoRB#}dUxiX@sZ7QV)#+Mqsd)mOzc|z~AMXzH z=S%Pp;WZ_w#wdDMMZL~scgZTe75Ctc%lz0%KS6bL^=XUt?06%vo84&c>Eh{0fr(qF zOV|ahEiIvf90rJ%nU^_-tbI?|Fl2_s1|vn8V~1*6RVqrFYkSB<3E!Xsj%8-IkkBxa zOV?mzYd5ZX(54s!v}+h_a^&rH-L7k?^cDU}hD`A+D07P3W zUbEmeWNM%z;l@1Sg*?hsc0pvds=v~Wz-G;PzRjD}4gJ?mvw3NH3Pmx6pkDeP`L&*G z4f>2G$s}#H4k~$)SaF$?N;c$en7=OAtJYy_Odj@jpR#@xZvqjdUp2kAUi!~p$h?=5 zfdM&aIEw1&1InMm6||uQ_~>+d3cdQeVJbrtiNr`%r9-OXf`ddWH4CGJU38KQUo#XM z#FvAEP1GR7XvJR1D2wk{HwkjD8dK6TEb#1(mSMEU87Cy*=FqQwuU|y&BsLtwSz%O;lQ2@n^ zexZ(63S;kzCBWr3b*eiZ9RsDemE$~SsTe64rSadFXo>)0orBDRlF|uNSgiWcm>8!f zZg}jhB!b~JqDXs}{;Y)1CsZfc#KipJ95LP|qI_w}wc3srb=uT7Bwc)i`xx`21NB|c zk^QHZG6`valgiNTUGWYX#mVy7SLLQp9ccHMge|R6TFs&7`Kq+*(|1p%CzVYYG+6Yi z;+{1|d8%3)oPZ~<*t-O-mDG|U>^7hZ-e+~c#9A44+%7`&UeK0X?uFYwJzjIgcGll_ zbN;N^EI#*_xlDoBU zt%ozI8zX9N3ir$Ur%e^RinBzvqcM9pmbg-N{YVLPSUaIBJ-s$FxF7kdHT&mt5)DJH z;RJ<$n4G0Q>s!^pVsSCgc#rJH_T`HdIfLg)WUvh_#A;YX{l(+wM-N*^MP2Q;goE13 zqx)RHc^68BnuKQ_4|yg^L$aLnv!zp?s@XuswQ-5R)BmXu$#JYlF|YroFPyh)9Wrrw z2X8(2uyRz%vdyhz^q1gsl;9uMA0`_;mp4?%>8U<4R9Sot+rExe>f3cU%Gs}T<#!bh z=Lo4~GG51$%YP3ZpRI0m*KZEi2Ho>>cOG*HIt}i^L`zomzHo)d?Zx6%hAzo+lHBHo zOAZ^lCXlo?74g*kKla`-s;zHpAEme#Z;Q0J7l#Cw0wq8KB)GM>6bWt>+}$C;B}k#T zL-FFpTb$s*3)E;S|MdLMIq$t=+;Q(1@8`Qe>}2ebz1E!bnX7d_$sYm=GH@%>fIQRZu(TRRF|Zvv5-H55BsR1 zl|-Ul^bYQg7*#MNH;B;Y7>FKypStm3vWQeiM-+cl)^nA4C8K$lw;edj(5RSk26fc) z4~j8t(8{V1`OvmrkeWKIdw<2FJ7t&XQc!vTL)lM>#B4q2IrEBSik~>yp-UD=y4m)S zY%P=*#SVIq2gF?}Tj2yo=9xTyU}%s!T$)*mU1@x8mx}ZZ0G3(0_q<;Sc+;2$8)QFJrw@Nu7zpvz3S zHuye`EoXs7T)yN>A6p?Fo;E>@z6B?CHRK>%HH$-iOEgqyo$(#7Cf}0|-ia*4Mgm@u z92-)o*n=D8fSDcJ#;cClru+fS|9P|#GMt0Vx666iJu@0ZPgiU$$|KnzP9}zUCG?%C3d8o%Hx7+6{k*DQ0_9ti-0%>js zICYami&1&&LzxB{4f>b?2{4YwPISk;(NnR`T@NGDSCuT`9Q zRo2Hu0C}vXuKFDSv9I#mzs7d{}%A%0raEl+2?K&gZmF5$%EpX`iCRy-Wmw*fFIwaVt!-* zbEm$yE}yykdRFPU1(v=l*}=yKg@1E`{zC};@BF46{eo4AT0o4jOhTG?eL|5NZF~Ed z*td{yuTY_goC7+J;;w`C5{zo+4ufYIBW$snGeOhh{yjkEgOBQI4PdWlw%e5&XpNHQ z?L1R7k-?!IW9%^)HgU3x9d};*nY=>k*^T!4oA1ADo{et%e_XYMd>sYLUm{4Xh-%W^ zc(*Dx!e<9A{rBZe9biCl24EXwyHnfyGTlJJNj~N078IUoXYOCuH;(@qPjPviBsEzR z#;~oouju^a$BKCCKMJ(6viZ@4GPEkM6`hCIt1-#FZ5uLYwJl=);T$n#Og{=9*aw_^ zVd&B{jO~ilFWw7xn+>B1GFmn)o8nU+O+U`WP3uU?Oc!BpxVKa8#OQ7eXqbGs>NRqB zjZS%WtN%JDX?NrO_m5k@qVk7+?eq~wNlfi>HdhvZ^=&Mo8=&DhfjoTpVGkn{=s?{f zmNH)<#dWt_;M2;ILB1f`JMYY$UJr9~GUf)kHU7i~ke^|0wPG228U)Ofx10O1_cQGG z_>r%}pNrb6qv58tl(4yPyUEh`Nui1}G#hx_Y_Or6UTHGZImgNRhOaFGw2$ab6J9e| z!8HbI*hX+7$hA7_E#=YpLnhN4F`-!<4PbSfd$l%-?G{ASD5cHKdbJ_xA`-C zs^;(cEnn#2XmP7+v=NBi@2Zrp%r#WeMo+s`jze;`c8pn{ z;i|vyyjtZkbMAA9!9s0oSyyy&7sA6k^~JQ%Bkqia;3o8;W`YKntC3NanKn1qJ3f{t zMoS@NpQcZ03N~_EPC8Da$V!hoT6%7;0(sxRzWu{qFn%xY`={!|hr@RlS3Co5F&AxT znd2=zQFt*BM8SsTJzZ2IFgTH3bhYqwzH*4;s}ro?vv=Ei$5Zs~?6-=}la4Yh4$$v6 zC(hkH#!F7!Jyj4F{(P%524Owl4# z?#q3k=BB|<7!m1(=j1Zgu+c>Gx2x(~ONK&dYO(&y$hPa_a`34ySR}8DgPZ2@!v@5Sb#81i~ zsI#G4qv-magkOX6Kd)C3wt(Qdpt}JYbHGI0qCz)zk~Geb)d9O4mvSG|M5sV*rtVTa zic2n1egc&~<6{kSKR^MzWkxJ?VRX!zrCmG%hn)%37~QzP|d>x#TWkNauhnYkZ@+hQ zeyVj@wcky}lh@=T6IvpNDYclhskZE~`15jLdj|4~2(xo<<^uijK4%TJE+EGz%$1$< z=B>$3Mi)k_M$$p5eyMI4spq{qFt($2lM9k;>0WayuOj1`l$U#F>LQoPmqT;d$`AEz ziugDMplkJx>}vW zsQ70*{ZbUv7e_&#%kQWhGJFzRveiAUl5=!1^V_meS>!5e0pqRhn2p2;n$1~^{OF3P z1LN7g)e2o5w1Bq?M`zlN#_4PSoKP@6*e2P%b(aEI$qA zaKZaF*gPqf5;h~hV9BH75Uc5D-t~g-xy9@O_X~?IZGd#(X(e$R-kJpAtq&-4^Bd=*j<$pH?gBk{pWOhA6M%TzkJxKIanK7P zPRrG750S6li0%*^dZfg4dBBsEN1V53p#PZSOS3%h}KH!O*A*^W725K-H(Yu;Mc ztm*tt+eY_vY&*J4*d@B-``%ps*N)NyX4-Z5V!}~QmZijAV2h1?*QPn(*)8uHk+D~; zSqUN;e#ni~kQS|F>aBe%yp0Yy5ia|S`jak@{Rl}X#x@dJi1^Q`*swuPuVr+J=hNId z&&aUh-b5)e>t&Bxd`BLZrTn-$dH4DhWSZdc9tUfY^`lISrE1K*GY) zg4lN?47P&Kjj~U>p024bQhX^lJ74W%SLBN<&d=0z;B4*Y4=a;Em^DP9I0AH0#c>QBsbSXB5TKT3iEkjRf#N_UfxpyI-5 zYkTxv-Ik7XSGZ@IQ*=(yi^J|ecOViXW?dd{SE&EqoO|M}0kq&o z9>lo%(BiMFl(#Fbg)i3NJ_>%e2HC_ruU@&MAptoDizUFaP2XATg+W|}y1&oc21=+g zvj5yu2Qs4I9s!=TJ`=ekZSx&U z%$9`*5EOU7D2I-#?>~;?Png0AKgA>dxx2|dP`MwY-cRxXHG0RLZO**VP36e&PE6+^ z7J~oFRHU#5k*c6t>TZ#Hhq=DE-RpEO7?1Wkm}5pYH zC+D37p$gn@ir$~U@jYVMcQz9GGIlpt^m}QhM4F_xIMo()8 zIOc{M!NT(m;o^(@?B1~C;e0xa_7)KiO~ph<(W*}gvGKcB_3xL<9?OhO`8XkStNZE9 zRcxt96h1D+4w84f zbB^^B;b=t?f6cyTSYJc>w;y3GAMU;%K9;! z5os^^eljafl>`KE8+27r*)_PSAGL5ZxFQ`lZRdt#2q9Ac{#qI1Wqly7JcWPj!dZu3 z;*`nJv>01@+&bXZI}3Tbrog%tl1%c>8|2VdcF$JF|LLG*xV&;##zl@R%rqpY|1OKq z3RRpG1iS)8d&l;ZR8%lYry(4m5j3)_f7Jx)I(Su_T50hIz)3fi^1v~)M29Y#NVf+2 z@#!XBrM+HkbQ9!|_dBkcK~5O++oCyl0~NoezrQ)q;MrSv=If zx5To@Y_0dE@_yB}l7-|(9_~XM@d#2BV+2f#2}KqhWw#3wvEVz}iewt8KM_p8h(nKYDW z9%8P@C+{k4j6!!{(LpUjcR-(XZ_2DI67hU!bcz{kLX`gvdUqO@r88w z2RfGCuHt!Y{3(*F~V`2yyGko3vhwgc|9l_=&2_( z`^4(eaZM4ang2t7E9%~xA7ep~7IxdGN!?KhgWBC#^U2#F&nMcH3-T@czy*FJuSdgO z9T`M0?yb}R*!DxFv0Noquz%_M*Vrp4wHfNWJOO<|vV&CPq>7v{>K!dzKbD_U&sQOf z_$)jNHLNE5lJe2pT$V{N8D^8{E*IxI9$^qDi=|wJQSuh#!(7pbVS2p*MeCoSucp!t z-_GgsipShDA~-4!U;67uTo7;aRz8nnn>H+>ECa5Z$lT7ilh8mQntpC%%kZIt14rs( zYa2Gd@_vFirD(nVy|Q+ddjzIsztd%s?6rimin)BE15GOA`AM)HXH4lOOXAadhf5 z<*F^1hjBRUa@P;tpSAN%_f_VOrvlZ8c=(Z3@>qL|-Hi}S%eMG8xY~o@NJ@y;)>JSh zZ=AxD?sNpGTA3{~gWxXJ0E&^iO;Eaj})u z9-(>2$;3Dk^C=~#>NCvXq}xX3Yn7$ZES*Z*s^7E3s5Hg}NlFtP2adA(Xe@8rP98#V zV6MI}x1&{-jn@6iL)!=Wu>=eAqhei?xgGoJW5C%Vb;s~tE5=)RIb5?!qW?aNcHqpC z>y%nnX`xHieO$NAN1m9vX8x6-04oD+{rwfVNo1=NlhF9NIv3nqSUfKZRKXLF_f`Jv#O z`3CkZO6B0AdC0*vMI2vdV#bW9U4W`zzQo0k$TJ5vq6TuE51uXqpEgS2V;6A7KcUlt z`Z*a1>C1w7W?&5kfWf>$i0$JVEYqt}q^|{*BA2z>5Zif4vT(Cq{s}I=UAXrsCM)~- z2uYbY zK0_%m7%H~oV&vfO2Whh2zdm$}%dt%~S7UKF$!+!*yshx`l?Sy`OdJ!qnvA6eyGbwN zACoh9Gb|PQ7j$HZ6GgpHUJ>W=afA}h?FgrIf_WwURB;vtiE)o*vdoHGE3A7R4>+zH6jCmyx5BY0XW3<#wo-6NR6S;X@ycv1UPs9~5ZEhqT?A2Tn!MQavQiGczE5kQ@OEu%%lQp6qvO zWHIIzxwAUg@^GDRf7KSP{}8m#-CxNVZhh{_?a$fSD=q!5JkeIJ#g)g6t8s);RL9{6 zQWcRsPSQ-A9Kb@Qi6)n%$t@_crObr9&V0ECIx;~jZe7N#evT;&JpF9;{8R_>ZIDY$ zfov2zD*=$KtPbnr%4kknRGE^Yl56fA%<8fnzy#Rrw51;rF<0nxVO@Sw=)HVDaz;c{ zdt*k#3w-m26=|WOxZ${NfoAX37NAm2o+Yx?g zQDi@Cl^W)ECTzDA9ziQI;7+GW9D2OQO--G$v!Ht8(`(=O^racYmwXxMLr2g=k#$1| zOiP;c_Dxy@jGp(~KdvSik*1AYj(i)uEP*%M-W=f80C!G<2fi1GqcETInOT*u3zgk2 zA8Uk++LK^~!o_ey{>nC_jm($LI!Vcnx~H^`FTQ)gxYxxtyZw&Z??X06si|DjMn7(; z&Q2Bw(s0UVB`a$!JSa|(FLg`ctWMfGvPqgl!TrsB)wq#C0VF|Cqv9JYk#6xkcxnWU z<*#4~bbp`CRDqIY)c0Iz?#Z-DeFTTY5VdGE`GMB=Zk6R=+<4zA<-;o}PNi^|Bo%s| z8~cx{$)*u16ZevSnTzkK9I~SM$(1T;;<{AJ%<2o4WiFladi#$P-4kdjg$#uZABtx) zCJg;ASntADV=vv^IvkEZ7he^tPQuxFhoY;3-q}2`C9b_k>Vq z2FFdwV9=p%Y9;;!@!Pi4RZ*MDZ*3E8oMw9^aW_I3v`$xno-N~I1R~1!A_c{APSmcCM*t~6C(bB>8KQnqxORdH0;RImj^y%>@ZA`pszi_^+ z{-upHZsI$wr;gzwL7j12mK}^Rnznx30e38cmAEh18Q)Jbe0fzgR8A`J-aClpR24^U zU1VludIKBZCgCc^T7O}?jrJ-U{d2vql7f^lud8g%FA7g>A5FII%!P2Jbw28puRqI<*cN?^xal8Y>#t=0ZGRT;fgmmxk;{#Y z6}RP34y|y~;8fL7p4Lo9;^?tEQ*M&6qQ_WX2~p{VGr`H+aQq8?e%@ePqOi38@cYr1 z!1b>EFO;XRZ!V?ix1zkQqvl+hA-{6qh&OTO%s_ibVR5XvlA!&uD#7Cvsn` z47P&i@z34E{|ieYv(5`QD1tUM&HCT45O*n9qtP)w`btc1qPmxB*ivEh{%whqi&rXu-Q;&P1V}p8gsk zws|xyxaF%{?sb@cvdTA%aA{3zW%Rsvd!}DHDwt_|cr=ZD^{uQx6m5s5eYlwFog#a^ zT)3#yi!x?{_v>N_d2TFs2zl58T!oHxj@SZa_3nrkoWQFxB}o4z<1a3AeRalRg+~L1P>YL{P`hTjEtp_Uj|}(ATh$NSNhd9; zdB6QU=i47bTP|rc9(km-_QQH^&MFcwj|EFeX$74yLn?ip&Z{xY$WPe>n^oAMxXg!een!m#2=5lEGY*%(J>(RR2a1-LupYMQcrenp1+|2OY$qA zd<~7lO4`S9s5CV?)64hAIubXrsnRLBN5hpfVjyqt$|+FWgGtnuLa(;%70E8z_k=ug z{;O&^b4yXOz8Jysfku?cG1Rsxo@k?QI$HNv*m(3J7#F0_o!a%Mb!2f(;w5?95Tez= zK^T2}e1ZVPp~~t8oP6K-0#5)5mC!cFSkJRBpLYA6)pfmGPah10)s*(>vjbT^D!VNs zs|Wr`E1}7VsuV2Vx@M+t5tj}jIvD@bNn&`#cNjp&ZljiEbgq&vs(kp_A zUSN)vII*=bLn2h30jck{yf@dyiPDdTn8?uCK&s|SB9~P ziw)Z`89q66O9~ei)da0^beWWMhBFh{D_nrA!;Q4V+GKoAUeMXj%c+8(Gik5yly~AD zZ6M8{icufG34Lm`+TQq_Gr-q2zzjJtbdIGlFU@ZXc(kmK=cRcw5)6CmSw@csCmmjI zdhRK@uVb?(@Sa_EYOy#J^O4E6 zC|i_DCT+&E7evMS6lACIL-5DGSI~1&ME>Mj9s*wgLDqSr@Ii)G7aZDS+A&zFEsVpP zce%cZ-z`(jkUo|@xN|EMmcGgEYKeFUka;nk5~XuQ4jke)GVQ}dF$sq@0O-LGLgeA1 z|H~iV1htQj74H*ijBzf#lG0RwKJDyW9PoKoLyj~ zp}*zmTZf-|Fs<1(zUN22?^=y+Qni}|cND^~WO-h|2*2!s$^}iZUT9pClk4mI-nx@g zsPfht@qd{zUf*1(A6R#r&(D=!KIRDP#^XN06HLfzPrPmW2l zh%_>&EZUV_4|wU+Fz#hDvzDQcV|l)CdlcJ_$avUc9B8>W$7Q>{d!1=QGxG*b>Q?0hB15nJn}-h?JXP^+4T8ak z1YEe8nJ7WgWapEh^k8@Vx>{?=?@&;K**85}*a~h#EpMuE* z?pZO6SpT5@2`+E8IHbzmE}u?GtLF3q<_wI|(Y86}nM)7d_~8L+beOuEq#wXz4QiW0 z2_Yc{WVat2dMZW4FRYPW{Di(BnLg<{@ zQX9v~(fq+!k-}2Dn=zn6MCK^#MM%S!6-yQfK~pip+vgQG4yEYvQ|wFn7TID}>Qc!} zpaQ!YGlL4gl(gN=C)P`XI{7=2G|fPheD9QcuYnerMz zL~qx6!AA?~UP9RLs~^iS9O=aj6U>qr-y0X-^j5QSt*TY#mEti{uEB+DmLHPhNK5O? z3X(jfv3SsTs!Hrdd*>kjN3mgcDy#z{EIh*2^*8xxSF}FEP@is1JD&)Vl^d^LJ@XPHp@5hIXt+XU)Fm3^?iC zbjM!66jqrb=)a-Y40V@Lkd~JI<=b)%?ACX1aCnyp)9E1WdoElL)XBw52Y4@^fnZ`6Tgy3d%ty-<~NJ{#@iTd!# z2ZxP^CsS9B?q5Bo&lJ0MHncysetdcCvlzJ9^s~89^9wtV5r`0}k|Iz84}rDqA`XRj zydQ_m?I=SKron&Ro$#-_J7e9QRU zjPnN$gikE5y#53HRPgI^U-p@AORJ8K;`cy+otoKg)yjNX9%%iyCgC!_9CG)`?D-*l z)+H)$UF4FyPrNC;(lO;p3RxO|W(cl5$T%mOA%{v_(-7?-${`AHS2ZG_8-OkpMTg`c zr^#>~gC#58xYvk9!Th77k)}0G9xMe4Vy!7e8%PkLkWFuAic zQB8OL9VP@2;r`V;h|^(zpvTvbhqWAV#xp?wf%mU|32XR1!*AJqg>&0x@Cz@O*}Aq&gqO>Q1BTQeYN8(6c^+aJNzOL z57IGDjXKW_SNOxe9R6I6tUo855A=CXBq{!!hOd)GddO3YBy6s;#lp&EOn4&B-+*0P zi}IbBd7dko z;zmI-p;rEzCjm}?xp#IUUR~;!1@iP`5}hpC@2*hyykGqCDsP!D0fRj()gkJAPH=#9 z7#vv7#Kg1CW>8J?jJ7Ptp2Niw&`%q|74x%gn$305K3Ix4j%Os8It51*;b&aHNjuF- zsxVA`5lv5FR5iIiA3i$zpCFr6_rbOA-)K6_#&$nzM*wXr-mg`RS5EdiUD}|Uwtm%4 z8KmAp>F#I>Xm8Tpbsvkt=H-k2RsDkBuMPc9uxy2uLM+!xkafjM+Skw~89mmRKnQ_g zSVvQ#n4eZXPguKSE3)VC8yz!&^iiUy|i{K&aZJy03ymhbb*9NHtFTl(S;6 zM#Q($tVa*=jfg8(xzDjp?4Ah+T1_TI=+ZHBkY--<4$MDkUVj2C^DZh|Dc*?v!vCa5 z8mZde&Bwp>pBxuKDK!0svbG${=eG7iCCxCdG%^JihwaIv`~i`;jylTtr>JOP*?B`R zz!54C068$j(9O;H9u^}yc{nz~GqCdPgWf!+Q6dybqFLmbo;&WZbwBup@)Mwf1?1Vd z(ZsyR6b5J5Zf@4Ea%OI{1U0;l&JHBV?W&BeX2Zzn%*yu6gmBN4KYb#~EHlBaeC^D5 zVM6k=o#94(ZSt^a)!P)hw70Th}v~@fv?_N5~z0?8=ho`M{N9 zyWf6n`=={M+a>(b$1V;EBKnGcSD!xg&IUa*B+n39u)b?TvoQJT6*J_6r3sc!r=%5R zaVQ9vdG^hvqa_Df3?=Oyy{9&HK@I%*Ms96p;1Cz?Im>K3!?i`1p*tQj_r9(2>jTAB2cKt_pc7i zLYv-u@cK9IUrr`!qhgV}Y;b2L_pxXg4&?UJZ%BNHDzccySrU#5Fet)&u*`F&0V=0o zD1lf;ymOu$`4g{(qew(mex?;@ewzbz5x=1|`qSD?N!GS)eAaGy~9?0#%K*j*3?~9S4hI4#s;5>NK z`;W*sr6_v01oB?Y{k*03SW0Ct0XI4B!~<&K|cN>20YY^M6L0h z-aCjI1)tyfd->KAP10gs{cn=2XnH7#n+gM$ba*r%2XF5j5F^D>VQks2O;m?!s$7&b zoVW+l|L8h~F5Um_0jyWkR_C5_hPh8wr7uV~OcGX?(oUB;EP|~i?ecXi!+KW*vV)DN z&67o#uLi{>jC%upEtT%GusO9!FzZ*1PV!^XTDRy!&%1K@Xe{+xtbyTtMp3k@paebn z7^DmdQm8Asdphp0Wr1L`$>fpYTfUpl@2;O@v5HXwn^XQ#Y+HiqLz(2mjT{K7)uD0e z!gnA2d8P3X3!pHZQ9fSa)0yQfEP$im!dg-94D~2^G}FFD|DqU3oZp;Em?d4ue{pE` zh88tjIiw(C4ULiR4y&TyheIE|vyrWLh~yL}l|>XAy$$mz&+vPu?jC zs}`2k5&GU05L_>}Vl5K`%zWqd)&EgVmp`5`F}5@ugI(DmdVB;?FgTFlC#ew4RVEC> zyatYaBR4oyif}zlov(-i`cMPq-CxSCnQrfc)JS`sN~TIH_!fGi2KhWQ-FqwZy7)LC zcYv{ElM6jPWkc+19Xq{ zJ!%4Xv2cw)+=zaXr?gBMRxqZ5G+tXOigqnp=9bwq4~iOCDwKlLueBGkIMX>ZO$;V4 zM>E`Aq3+-o%v$;pZD(~rpQLdv@Jq@7!~JEBi9yNbGt>xM?MOUg$9RFr&;h;?BX~+- zmQpFrr{{0rZ`=>~pOxDuq?W}58%!M|AZNF z#sGL*w(-_DV{d4GRkF3xO)Gegw^ps2kzSH>%1vAvIkFXgZ9!7B{q=bFlDbVtC*&P z#3-StN{nUS>v@n_$V7-oG&NFnkwEPcN6YhgA%>$`7lXf4r?LbAvj%I}>@t zYV!S~pAJ^P%QxTW)|dp}-RwRytd)_<`ZXT)CrFcJA;WP#?L(zkFQ$L(v%p%7y_p3L z1mT@+is%u}gT&2mUs-(;#`-B4(8A@hyJpPX5Dt=5;*sn?ImYEwYPae9OZB89R%iBF zwK&UHv5YjFBzSj4%7Ia|hOC#yw@1TZ?|Eg-XpgH5%rBJfmtB@;wt);oNGE34 z7aTly(n?deRBubeev2fnK6KN}`h4UBTJOO>J{mwGq&tRaDsZc74Fx&ZM9;EzpXH<$ zVpEMWUleVE%v9A8Bm6KZwTHwYZ3LT9tof{dSef2tHt>9$s)|GI(!-s_|3O#%lxGg@ z;+gBamo|h=IE%QbMvuobr==aII6N*|`VCqZ!~#@BG%J{1^_I|sa>0oW?+C#DB>)pD z8j>^LUhBzH`h8r4<5)|-&z%t^lH|V$pPhM8ssPO(MNGt}R30SD*zk(^se@Vu*3o@-l6Tc$e2wg`q`+o8Ea@>RC5rWKpBki~u?rlkJudsH zO0v!G)-gw(JqlJ-IqF+u%jlj~wII6bJ&w2nJH8Z#uP_x7eDa`4|UsDOHh^%IjuHB zMjWU2;83+6YDqDGyx-w6y zV}kxZOqDBPtenh|m|pU%ziaS;56#Ez$YO9pCbxC_+mz0waferiRTx@sa_SFbo-om+ zsb#`uEU7uVQ2iwD+ab17cBcRk*-=yK*}cYL^W(YV_blJrk7&-<`cr6q7$eH<4r;$X zE3g3BfeYtP7XyyYb9T;sw_MjkL2LxY`z zdGGKBAhjt`0!NgCK(+OgoxV&N`rjjk;f?#eG%EN#CXwa4fr~6(n7AL0#Dx23%4FKxH%Z8R)(z}*n+>q(l&ynZAiZQ{*lk8 zs*0VxEVS+epIYE19MnGCTx#t@3hYjjU%=3!aFDTI(a*wQxzkP?jbNXYMmb!FP9|ZI z=G9TkLUmk*W6VT;+p8li@#xZLC!V#@XCke_*_N&z+S5b#qx@`{Q|&1Q3DaFMs@R7r zUzjUJ_=al4iAAIGOAFu=23>vrHQ7%lhyfWEs4_#+Emu|c7oPonWmmegW}RiHAJ$3g zXW+mb!AAw!kx7rTg1r4Zo?#hh|6MW{G?@;6gkd&1}u`Wus+(nYGlXyFLl-OZj+c(`^zIK9MsQ&AMY8{S~2(ygO!!? zK3G))?{1Izpo~fw70ZMQ`ZO50v*Rbxwu$v&fCq)DSzeSp7l1FgKM|DL>g5YMk11k> zW+J#^J>($L`!p=hqLBJ^_@|eYJYVkLT=aXZ;t9{_O_UmcrM9IkD(UdLO7A$P$b5-e z5HzY6yu++Uo*nN9ej4^s4;gE&z>l}bo$JRGG8f}JC;vy3W&hR&@dsXT(3Dg~M#*zq zy9qyRN{#h-I5=nlVElmXi}dtbJd2d%P=6fc!-5NWWS#VtP1*t*wiV*vGfj_+&(=+l z><$5V$l3u!RUN><)iV@maktlrFKW#@8vzkYlj+Kl_c6mmsyDVl7mnSr4+%@;>NE?* z%#dWBfMm-D4XTad-6ZSb_pQ!_nM8Fhx*=yy1n-Hq@q^E>`W`S)>0Cv&8Vr; zG5;o@JglHJpc+(;q9mnsYZc-I2@zp%Z z+C#dI#tgiOO7k;1f%CVre+YD!ntl+K_Fyw|0MmcX0-1UY*}Vg?yeu!HMKJ>H4$DL( z0vtU^_cDchowS{OWv06YV9j$8!>exzA(zMHN5TY@Ii)*lNSG1J=DbVKVI<`Oi`1q5 z7u39RS}-=hdjiX@Fncc3wozwmo!_s&(tB~eDNv{*blG>htoieet6=__gANZtK9&Nx z*fRDN_tUh+f&DTM3k<7t9;qKt9*3?nxP4Q#p`0C&j{wodqDRZaay@<{2g99bN|@F( z1TK9;_Mf(m$6pEwQT zTgn6-eynD>xA$!YJy_(uxTcCXyG-RDEY&gDKJJ7u4^S=E9(Akg@PXolr_`Lq! z9m4;>3FkQTB#i&177L{O3;0ot{aryxaU1_{39%C}-wh@yzPJKom3v;|gKv$I(S3?# zfy4Lgry-#Pv4LtVknVO05WM*O*&$y2h32-tEV8T9ISSTJ-=0AZ8J>|S27xjfkG9xj z5KUV$I3P*4k>lF&k6Zc-n>+IEreYpdA+YkM63Q6mZWsTO=WYSG$W8Fn_qn2^_uDU} ztAva-dT>#1mJuCV;_N1IbC_nNf#jxym~@2O{Huitvxoxdr{Z9Kv?w$Uvap~?FJAPC zs8xiXmQ~%BC$-2ikhQ?O2eszDJ~l4VUZ^AS9l;E?eY!!W@BF0&G;Qf=o=`0R8S3zW zRyUI7t?im>3n1d9K1|t=i&-}wr^r}Y*}II{sI9i)BKU=jWyF``GcW>@O{ZR|r`OI5 zi6p;4b&{~iBY*O+~T!>_ItD*1TxXRKYNX@|#XQM%C#a5^+x1O2bpK}Msi|P=2Yq!2W&e~V_A%rcQx9*pnI#U75y`;2-&#b`U)eqU z>yo?hAxRwpZHVcttK%2a)uFwWORLP0=))C6ZiFn-IvBsDZ@iR|igcMaj>2by!d`_a z&3GvcP6l?659YEk>|(x(^>ml}Fqh~fUHSOn%9}an17DAE;=G}!I5j6v`d!dKkW7%< z708sIRr5#u=S0HU(Sto85KK4#8ghOtsD8LlPgjZIL}2;n(%2I|j@3P`se;}W#oL}2 zm!dW#0b0m5SM)?&9&MG$=~Pv-K>k=X4^+;_A`iR46hejGa#lLFBn7^mgj)U0wuoRJ zMn=yrR4rYvlbS#5eoyotvxr-_gkp*4M$v>@^;VZ13C?G4#f~)*77ct7j8%fs*H} zb{VbjrUvm@mqE@K4WdCrM#Fr*;yUGs0FAsRVb2ON98?AxY~?R|twVp?DM>n89xjzY zm&KAyJGL$lpmcY4_Ah?!_7ex21t1iV)5j1h)X`kei}sMYEH}$j?sQAf8XSYWzyxhb zHTJg*r|@gAk4Dj;uh?$|47BwVfGhkXCXIVp3wl1vX!v$e_S`Vih&r{KNLS$GSDwhr z-%i!@4?A1aK!qlevh^!e$e zz<`utK4XpbJE*5R1> zlW)P&p_L*|Eq2il>ApKP&wS{jKjqu1gBHcVqe@b&+n$Iz*wng!E{vjgcum?Cu;h=Z zCtA=G_{C`z3uM=D2bxqb=z&r1;7*kW6UI2>CEF99s~&|O?z2akzS?XmVX95;s5wyF z88}zQeLSIS z$jFA|A0J5fr-dYPG^fR)PGSc09i_gy8sjk9zcsW;%C!Drv}D#bFzO#%PR)b>k8W{F zM~FNHKY@@gh~tmkaI&Y1Mue!fB^oPDraOTQ7I{Kw$+h`P{Zswe@i<;y}TzXg9svf8ZJ;KD_iU{9=B1W7jKy# zA>w-dHqXbt1nC*cG|Id?p5O7@js7mu+_gd$PO$5z%i@Im5m_-5dH<1|b1>ER-3 zzJ0E)`pqZEoU=4HYA#3LNxWJnok$vKT~#cj8?6r}Efw0jm`>)d`uLEW8qSU=07*QR zv>42G)~Z+Us>>)Y@Z~0&A0m(*tOqW=BXUXARvS>;haWyDNx9Z{WKE0}zK+%dywbM2 zuP37)vIDkm$ggr{oE|)y&S;VCi}x2;+aLMWGPhkPVV&fNS@(CU>=E)w!?q4C**VF+_6oKx{Ctl5GtHhlIbHGnJ#2 z@F?0~l4V>Ey#!<5o+WaKy(|m*evGNg(~;V0jfiHA3j7M_JE8tf_49@`V+4M#P?C@d zlCH`}GAS_N1wW41T}Y)?m%QicLB8js$|xDX|HIN(_%+>sZ<7)d!swD7AzdS-dm~0j zDIl%D=o0B}M(;yNjZq4MgmfrF3>Y8{LmEX=5mBGr-{12GjMun!oqV6`9M|SNBMWQ_ zHNR>>Pm@diL!KL6HCdr0^}27T*uScc`86BUq3`?s5DuN|>4Gp*0kF#*gi650o7bZT zIgginB{DmG50eE9=m%d1gj{nF{C$zx2EW7m0FPsAYtM-UIZ|JT!?)5EULFE*iWPa^ zEyzKmp0naT7l-3@RHm&Cnauf*8yYCmy&J~c@?KSnL!uIuKW544w*GSoAL2Cb+Xb6B zouK~91wn|i(gDoi4(!2{F?mDB(EjvYxCHHI_rS9E$op}Ue3p`1I&|O{NXqP5mIk3Z z`Zud&{)`T;_G6_%t_F4y)#14;&Z&*e52wVUkV7CI@EzET=2F*{4ETZY?HONO+Pk#; z*Zf)UsJ;n7vyOlZX!M1jVz z{o{nB*L#jLC5KXuZ&p3<@(tmTkkva*gpA&907S@nA95dz2PXm6yWLy)qg2&y@&a~{ zNRA#{Iw^V?Pwi7~Fc)$9S|NS<6A`!+Sn^C+sHkTvy(G=th{z6`SYv8{v4-I)4NFB_$71`cALE|@5GVq_36OfUF9NCK$7iBh zWwS%;Zb9K@HkN6I?0)kv?}OJ&G)-EClf2db>=<*mLPLDd6?xnv)Q4>D5{~)NiJgt$ zYw62^saGZ*x`Du$Weu3lbvm7}+oUO_E|JB(7lOY}(_t+iiKxm-bk_}~-hjsL-L#Q4 z+UJH1E~v(QHk^cHR^A+*9CT5vkYUN!ju-3_9Fttor3I4o5aJnCTGFoz_0nJ7dev#j zcY~B)i-v3OHZRKwbw+sN*#@s;fGroEPSSa|k8n|NcL%iy6)s);)pq68 za=+dIkB|Tx*dq>hf&~hoCytwgAjqKiU(NkSFpkOi=*LczZ!jW*4&t{B@nnL5_M;P` z(iC?guRHE3gnVY?RT{xonA=K>V2k}$*;q&R^QL<;^GUBn0_D0}7^=$>k^bv$Z7CB} z*M*u}1*U5Soq2EuH6WM#Sp>%xo{aq*s^*u%gq&H7a>rkOC|6be`&r?N=h1R%s`t)u z<@op@>p%AEU5}c$o}NFy*wxw0B(sp`P)a~?B_vr1?hg^ZS&Lw7_A(+>Whj-WgHd-= zJ|gM^NkVBoT7q`*4wcwZ?_`Kbh`zc#aMRnx*MLsP{-&#PeFaUpRA$s zkJ@I?rCxL=PVxNJOxdRp%fzrBJu>u>6B-)k%G{Hm9n*X;=Qzz4H=8|7;N7|p9CH1g zO|9d00k>$cguW>_Q#kc3EQ229`a74(NZ2|iI5Exz&K30VZ(GKO+G^>PS5yz&ZQ=vFRt%DgNN}69nVbbZ|oQ)@N$8i%4A@ zuFe;rK6~96NDTh8=;g2}Wa;Ycb092C_ZOm~to$ulr7{+_dw#yPx3{60W>=+_h?9ex z7n93LDPX<@AiZ9(t;RmrL$c{{KFzugt@8eSwL{Hh<$qtY}=H(SpMiNsl;?`<2r22b-C%5Gc19>ug}8 z;aS5IjI`N{?}vmjuFon^gK_TJH!k2mbH9!B+p>1{RtiqBMPeym*ZNr=f}vtUKl4@I z9;fbm0}Q+Y&gC*rmP~x`TifsSy$ZgH`o|09PW>puzoKm#I~71!eNE6}k|NqeQlEQB znHh}RFyE~^+NTgGR*I{eBIw%|MyYy5m0Q;@++m#~82uAUaL_T=RDSt0!na^B_)(?O zd2;*M&X+@j$iJwg>Vu28i-l9%(=Hng$WWCi2fbNS)LvL6O)Dy@Z~kv!*YvMVq~PVI zeDpj45uDjw_GpU`7-m$-u|W)f?j=qU0lMs_tiW3f05AL}b+yfY#_!8%Z49 z=$hrFl_~NF7n^ZR_Gn&9Z{t@pBE_?hs6pyKA>hqXhi;xj->Gh6^{ywbL z?6y1JN`WA@^cRt~CNTnl0SB^;*JM9UsR+cWU2Nlld32<=gfFOO2SP^zawmJS+%xCy zBGI6o%^8By^VS$n-*ml`cz4T{V??RzzygLSIlD-fc)oyf_HY;DzxDW6l(ZOn znRD2|y-J~N;@26g;w#zGzl?Jauy+h11kwIHnSY1{P|0tRZ&d!YK9g~_t#F{Xn#=DU zdxG0_xL>yLp|{@8Q5`7i7ylA6_@dPYGAF`>KldNvCSNym!r9<*`o@%!2qh%xU2v3f zxg^;og1GgciJWRdF+wart9;b|J(fWR0tU87QLLJgcv@c31UFsBO{ z`JA#*PLLQCUOsC`^rqV2EqsSuIr%Z|a|m9(#Q!R_mWH8ay~m zsogHM>|Xs{8!yf0&qT?6Il^i!vx|NX&7_Bzn-^XnjO}4RhhG)TYJBXj_v2!Q!Qox4 zQKCbODFpw@p~nyWcpytkuQr<1E$UV?(sY+q_bNtZLGqP3-Ha%U{jyz^<;}VqX6OQ+Lt||So~?q)Z)=C0 zuHr%n#w-NfIED&{q2)->D`E#?dJva&d76JAUyA%H2N4c8Yr-YsWX06CS`qOjr3z)> zpmc5qgGpVizy&M+Z;Ma^j@$w7A{2Wx@*dwZSi5^LwP*Brb)ht(jD1g1{KpKZ$+Y`F zh4d=Kfu4E}ZwZrSLKZSuBel9C_2B`>v%!43Np;G2-bp!;p?*_YTOH-LQeD%jaUj<7 zPtD%TWQyHTW(kbRq|(K!zK*tv6XlSHdwBT^e0wot>w0-vBQs1PT?g`KGh9f=!dD3@`Xir{g1Hi=n3Glr5r<8FycxTtI{ZV(6T1_9D zC@QPJlG9?eFb{YbE>3D`xSpl{G26iN#k(&H>6&kt)$2YiB;{DGktx1Z2;k63!r5Xb zP`8x-3*AY4z#4)kKN0%LbhBjEc7;PtbS)W1GW%(qzii#tBek6oCVqckX1$L${elp} zN4_ZB{&~Yx zJZ7R@T}D2Z_=?)>$qEvLkx@;D?sh7m;9=;#y@=3A9&#&3&#D3}i3l*(GbF^I7X3YX5yB}oAt3=P?IW^~I__}NA6_C3a&u~RbOWM< z5VG)Le$4w?jj*1^ayXP?NgYnn*jW`gNsbs;;WR`V&dg@p*Q2!g}; z`Tl10JwnDS<-AEonC@4^FVtsWxW;SA>g@29%g5%r+U+)k=oQ2xv^NUa16d)zj@R4U z6G8tj0J!^dq!t;hkPrCLCz#5r?9T7MStMFb*o4UMbn7~iJ1U*q{~ID4Ub2{b2lecTZr&&RCoz)Y$cXB1?(EzX z=x83JokdRU1I96W)*>WRDcU_QJ6vZZksG<;u~3;}3D|A&x5nSh*n4oR zSFcL>jEy0G_N|Fx6r~d5|M<07kitX-3pN9!IszD%$&$ugg43r-;wQnbD&^uV^M(J1 zNyV-tB7Y21mWT^odxER5rFnPUcnkJsK$JWWZhtC#?BwGfLT(P}&t+e%S#{0KqFhaD z^HA~lyZ!L%1li9Mf9k24TK@w%D1SbaWz3gxuEO9%$0ptJ9|F(Yye5QG^!`%4ctj%E zK<0X%tu}GunA?&EnVl47Bh!%_Bagb3^Bm zKlBy~H6B|rGs95WE$DsA=ARlr|0(&u>{f$=^8Mk8~3Xa#%~n!bW*E0 zKzoju)>ayVxu9uIc*El0yaA2E_>SV|(a5Gf@$?~rq8s@Y#mE~sf%Tv(RC4#?e`Um`_RPcCnwJfUyfjgi37Y+GUq95lH;6WeY{xjQ(5O9iY&nuQOhz~@A%rl zCKFz{lbiQO!38#gvX73Q>1&y*Z?wrUC7qP=L3xg0Yjr-qM!S1=PUW{{=K{UfxOf*VEOpvMSHg+HCprxS}^yX z85Sg;fH=?uN8D|zPRlrOrP0@o?4mXTO8VC@jNb$S`|oTO8(N+u^54P^=aa@Id=7{p zA!h=$#x&05mqfJd6I*CUC#Q-3aHnpwzq`IA2-9MOb)G@Rzbol)Fp=SdrNrWY%IU#s z*?-pYp9+he8P^aeg3hUYco^hKx<1rtqXuMqtddqVaBfuVj~rH>Wmi}j22v<73eUpQ zd(j?WcrU_^&0-v%Y}YxxdXiix|B>u+XO>g(?Wj>~u|>|OxDIWB%&f;WV4+bCQJ)4O z#x!vd6xr!6YjWpt((RNDE(vl=Oimk&5zQC+3-meUl1qCHZYo{I4W`Viw23G*V&^Y_dN!(6%}`zQBT zpWs|(+2Y`o1mC4>a(1`Kxc#)gn)%6B8%A1QV645H*+*0)2igg%cxE z^YgrnFB`ACR;cbxNa+yq;RN34DmAM)4^$4&=k$SY!5P{QlQpCMG5tk!}l zB5;D4@Im9x$0l`%GL7}bH{OI2xrQMT*R@EfHcZnd(qbF}n#qPJekdy->Xi>T|y&Nu}Y8gxSa?I0j^;9by7KCuSv+Q8(DS< zVHT*rP&4G5I zg7fznp{>C;9^dNm_tE?p$A&8Al@VVi$Nq#c%H%ySX){qVl$s9E|LFF$%J4^o5vFrJ z^?7xweSWx9P)xZ2f0BR1Jsy}RC-Wrg2XC(ML*Rq#L@U93OnG2kHPk1+I(tUEvv1sj zm3NvB7&Tk+2L{FjGRDv+fvy?pn-G>?O8?ZsMVAaAuki|>d!abLnL^Cqcx{!Ut!4eG=Gw&um{6UG#eaL8hkURWjGj#sVnZk2f*s$&XJM)4Y@A$w|1z+g2bO<61fosmF)~}X z7wQR#y!7uD$l+!!;mu2+h%xmEYSCYH6SSikb@UxA{raw1*0AcTDU#=Cv+0dilAo_2$;nf0ji`i9TTji|vJq3@~ZK4S}iAh?yiWj*J<7*n2Qw!vL|)Ub;ph z0_$Ua*>gup6zD`lahw zf)ean8_o_C8DDDg=Br%J^9+&Y{@bRZG_0i&bFYQ?=u}S zpAOiG)gK;MLqt_U?(H6M0qv)fkjL8T95Cs^AVpLWh*HjZ*0zbL@y_e#X+|8|A;Pu~ zb37cnB%2)$gq0BXAOHM&^)#+rTL|#@ia!su66N|LZwq;Ep^BgVC7uyb&Fw~8J`(l8 z#POv3F{=J6_JABFAqe>C61!xMVd4mgXk5SUoLj!yb#*&Q+Y@4dRc`*F{k)Z8sn$G` zay?!tpR9U!pGE783LQv-o||)Q`uJ`V^?`fR5U9AJ4^dxhO7SOI{_(YtV>)zXUs{ZI zaAN=bd`+_E^iUlw z0BhNeZ?ONLDou8*b5366dAQuTgPv9<7?HUfh32;HY#a+CjF<|j-ZMTVxL}E@`qr+J zcE5OyctkrL^a^fnR^t=zN-|ZFwwVe4LWSNe!hbT@Z9>Xv>FJK(^zpghyWbERRrw5|8hvRDo6niqUBD->FSGq?_DOD&W}1SS5W*p=dCBe z1e*Y=fM!L*cJRXivhC5_5)N{&DYAHQJQ>|y)X}S#v7Pa;2WRBn?%6$Vw4YoDM5q#+ zW9#uCmRa8|_xU^};@mce>R=A>J7Bkaf6y#K~2h&qx@2*kSyy)y|>s6dR! z_7w=>{zgcCz!1TOUKxeo>#jfYHcteRhd9^k`7U3S(`q(RfmixXi1U!+9otZ@?jlZF zejqaiU(G9-{Q+ZbXo?QxqA6dgg;nA9_Y@-tv>M?<&~9|Fp_f1JP@_Lh zV|X6bFvCu=f?KmCe<`JEYPyR9&PCU!=tZX4&Kv~wPI@ofA|qP(uiq+1Ter|MLPtsY ziO7i2Z2mT(XGD_5kX7nV0=bPorbKU&pv{QdYtoHRHX1Zt(%|Naxcghfs^Tx>w^2S) z4UZJ?!E8|4MQguHq}j~}E!%ntlxX>`mygLb=rGi(i1i>NZq?Q0Ow zKBv!&O=tgM9j~jmbx5tUAhl**iV+(6WW;5*B6uM9yWFnn7ZG$+sWDH<_j_jB?c4q5 zcg#n;lX+lFv({;+AMjvTBmo)(0UBEaae(W+yw?^!v0e08Rb~p(8_Aya6&STZ2X%`l)e9ks5{9z}!_KPr6G26I_sjb0 z{5q1PV3s7`QBr<@PQaXW_v|ua0J9U{s|bRwRDl)v6Ex?4hEp-1X*LP$GYgm#U;LlOt+E#91 zhVfJfII0nW|IB|l=LTziB{Qj^93_8Klx6XN^HA{nI3g1=0xRR87KY8UuLv8^q1ve6 zrpF!vjpuZqJjiPi2etzK9FJ%^;aCK}Y9v<`BhgiO?VdRya>`iP5Yr5!(PKWp5A#b0;l*Dq<-k zkppr&$0g$14VbvEFaWFZ-ppR?XB?o~>T7H@N`xCrE# z$Y82^TTmfN^o2AP+Ab3EzN(7u4FZ#P5pJx??5^bYuVs`%Hmi_cH$HoP{+9fOz6dP_V zifT7LXcs@2{q*$sffASl2C=YEVvYl8qYrAKRWE$QrT^Ch5eEs;uUieq;fzs)ct33w z(0ikC9=<(*X|?z-j7h7WZ{fb3AmR}ultsD_V#e-Yw2TJC9JEuIgM`GU&2q*p&|{>a zDc1~V8AK??uU4Wn>BSVovAvDwT&%-Evv!(@G4Cc-i2;w0TVc11P>{%J=44t`XbSY; zcg7ca*BI^CZ#14a43g4C)%9S8galAHS4l4-Ru`jbwCaer%Jz!KmU6?=IU)V0lZ3qR zKSISnkYxkg+7^c^U#wV%P^YIH7`3_)caaTEUDm&1fZa7nBF2-YuSS4J_8T>hQtZ>I zzZ`y`ls_X>TIm$9&2v#lMn+*uuw-q9O#UO1Oaq%)8RM)omN^B0;JTlvkbqx2$PQLn z|L1n+L&p3pxejFbGWJ_x=}^0qY)<2CsV&VJJfRpOto59BHbGd7zLivkn>Wy@f5F#!zNZEY z-lb8Kr{mE#K7W+jQ4uj~xh3*$O~4@kLmqE>;nd7$A9Z4rUp~!Hj`OL(L ziD^95_FYo^2J4!2KmhZBc9SD(Jm>S9Fw*QUiPR9pKG}y6Ows4nWJP)3vri*{EEX7#8GO9+O)yhA<_EB;mR>x z9?yC`R?~ue{slnz9zAHM3MQNNm`%U6ifY9$BO>p*>vONwgzw2utEn_qTJFsDKVaQ( z%QI^=@_ikb82bHAT&r@a#KC|Pl>(d(R)VPgNK#zc(Kp3S3hmpr-eH(-#U^$ZYCW+V7@AI*64pUPD%*W~F3T5Enxiq+(RWHBJ z=>3Sc!%>PC1jP66s2~`LfSX)7ko{z$wLds{K~4e|6N$5T{LF!>GK}7I%v!|SUZ<)r z2r;h*4ALNB9^)H>qATMOx3Sx7Y!a1GS@j^DfYQ3P`CSq-;#x zRV-SY@bZS5-L&%C(A8gMiUnPH_nr5OLs0cpz>NpJJVRLC1U0ebphH32! zg<=SONJt?CBn!}C^yMgtp(Fx6sY-J`AKfSQRH$~I;ipNt)B6g;Qdg{!DO)U~1j@nH zx3z(~YfQ(a zV2_xrF7MfD5k^@Su|1@L>BCm;{I}jg6NM|=ssrgBLdfZ>4x?L zoeONq(FXC1XZ6OU=y~B=GBwS^-eoN4w=*a8?L^>mZE!INJ%N8R|X&Lb07Yxj1$r z*e?jcu^cB)|49b8IW^}*C0tDbVnFlxm-$Z-?%r#7_A9U3u$wN%6uNhpHFq) zK>Odn8D!NNi_^;0A_6yYMryfouiUaAjKE8A-k&GfUnP;AJf>Vr1Km?ulI8a9YsqGhNd!0TH^r z>**prW&}xQThUFKoi!$D&mbP(04BSw(s$;gR0jEFv-f1H(p=0lJ;`4#IvenaifLup zoY$aycz(akNRet=+IS%~qVqaAOWFHlIO^&qEB}OX*hZQF^ZcRZ=suHn2bbWjAN9=> z7*-{zPC{xCF^4EiAyyt&0fdWfmA+3|VFUl#aL|ABfy_N{8L)>)MS&uM+7(4NF?csN zWUH_Wjqgq-N{k#}i7z00yzK*qD;9Yd-P%0pAQ$7}pFh5jx%eESUrr7yVqVnjdzq#o zQ@z&m>J{VmY#|4v-;}_z{(B@R@Lf0FuZ{r*6e?7 z|8TGAG5eDfo5lkou;t#$TzJatY@v+VG=doX>O>W|E_}97NF^(!Rq&OXk|C$TopdwN zzAWn6FTw{Rp%2>bM$J*)Ev!n0cU0$LRhE^9Ev9O|=C@KC>Hbv`fF1EhORv|TT+lyI zelm`AdO96c5_HtDmRlt?BCR%-pum)xek*)x)t`?>DtzYmp0{_u4`f`Rx|}yI@}qj0 z5hwSAwd0kO4`EC+Fc1<#9-HkbHIJ`#2(?Yf95GXvKh$d3Bdi4S)N(me`S+!a*hDhP zk2?jvH69m?Rsl5DV^pW?3Q1tt9&c5!^IO1DHcJ@~Ji`=8Y^a>F0O&&T&8gywv? z4QeJPp7QQY3v86)mv>isB+woth3t?#i{dw%R^8GNp^yLZ?(|PrL|^b}2l|Y|DBFMJoD5i~nH19AAj|fzu7OpNl!R-S!oN_5R zJM(*qAHH`%YGB_DLb3)FY1}uH9Cue=Ys4vTqm7BtrtBdn_jc2GpS6>sFM-|}LZ-12 zLi%1An?$g43?H5F7!$XIAePP#c@ z>AVk)xW#W>l;7Kq>{?w}8^h1eZxD22bn?&kj6=R=olBQBgtgIuAN=xv7_s?Yx0Oud zR&|TVKi1FAVtyim;z(lHR|?|Olz~tAI&Y>}TnJQJn!0_I9Mkv(}d< zULJY2U0MzIheYX9kTfvcu+D(KQKM1OG&lzm{&U#5_S>5&d@u_WOWo&z{vRmS@7ITC zX5YCSHMkvb_@C`o|NcGrJw`R0{(b`eR%A>}#Qw~92J7JU3#>U>FzUegYF+U2pPg5VLRPCTqqxdUqiNv6R2Fj$phX+;_R6-{BmB|#^j z?B}wiXyUM*w%)P*H+P2iKOT^Rr$p1_4nlDy`8@mNPt|S2)~rZ3X0KXU-E!C0f>%R6 zM{jd3th~?g{bfzE5lr$(#9DVso3||C?pG5cuwA^>D3;nWL4FmI-bW|G*_Lbgdq41P zs#x^f22vO!3%IDnKeNY3PJS|+0BnZ!t-d|qY`>R~Ny#c@Pk}#4I*}}Pd2Ksk5Sa(A z^j{5+>mP2q-87Wp&Qt`)AcM8!UYK3fG|e@pjf%2>)LFyjX`_$|$|0M=chJ^Uv2YCq z;MKN*k01g9J?iK!go`P22UPyjiU~DdWhYS4Z{T9QI3+UXn6>FR=6vW+mr}*{_aDD` zL`YPusUYg|5gUm``6TF2UG_>}QF*cN-{+^SjnO(>R;@zgr4{C9HHE6;@S7F zXzMumGhY@K1keWS&x;pUftrU2`&O3B}~;WLe2<=oEYF0lHuE11Y=RJx3A6=lb{GPra{OY*_7`SCK$O~*XHwlH! zT%0StAEm#g4Y!#uFSGxNFhP|az|JG=X)`EHhhAWWm0y2_dbNOZo)^KJ$c98IQgE70 zlfInq@M8^(tHSZXW&r30x^#5kRAkCYY5gpaBuPUZq1v1_sQ-5gV@ybX|I1?u&j%lu zOpg4$y~E#A0+LDk+XO$ToF3fk@Yi8{pQ{6##sQmHD!kOp6nG5`y+FVTdyX0s;mn5+ zC+zvg5z3Ya5<)^1^2TY|q<|_c;^X`0+A2;?vG7QO1N`oK5T4>vOf}}mZVf^BM2QIm zxG%W!#7rYjkFV*_dhi=74x?0k?v+hY-P?-4vsd*1t5KsG2=D^ZqadRI#5!_VcO7%U zv_(^w^rg!_F@P^h>XLiYe=_H>9ZC(wE-ahk#%)K_61H~?)4wn{9+xOR)A18HPr7$| z8yXI%l_oT|5_mRWa_-prL-^c)5dV^O4vdL`(+2!3v%m2kqPoK}w8bw>o&Lx1kH$AL zkoP{2a`Gf)leKz+CH=lpfW2PrV%upHBSv@C69b>LWH&mPEc7?dZM>|P)>}%^kn(I2 zd`-f^JRS-GVvXhVv`po{=BD8i6rWu@Dtp*8Hk8H)!-RzKP3=>^X+GBj#OMj*a|rFI zvb#4VdY=Hsw#-p*0$TQzOb`9jF(>8iuwM_6n^1y!D|iZ}i~d$-nu|5SmsI2J|6atz zF^Qz2?mcI8UAg`2UBat~l~<`qABeZ*BP%(s6Q_%3e&@t#(shUwq>0)~gBLwSozc^qCktIrz*NXh_Y0$~9yq#8*)c)U!wOK{iI_ZV3$w`gu%e+=;?u zB&TZg=C4tZ1qevWOLJP>(n8Fkc&WO>#Db=zF5d5!xAr(GbT$6AT8=&pxZTFPmvdIm znTc2`M}AC5VW|z0w+K#zGY(;>QgDUwO8vHT_{6u~GLe^AvcXs9pOwDt*?wr{g1vjz zXQBSu*1E?!4mDQX_oY+c2_`|%j=M3GkwRK*iR`BdWlCCKZQ{Dapw=JFNH{SnbA12h z=7;EVB|5Nz5GU6Mp?9T(jlGgy@US=>0rk1PBF-Av}Ma*cFEH)MCvI?U)p_2hq->6VlLQjH7!h_ z#JVLt2VqPMQOL)id;E}2AS|Vk`0#}+B=YQ=65aWaQ4Ut@M#m(=o_d@1VE<-R+t9v5 z4~oP9If2m|+V^0=pd#)ih~b&n*Sb$ONh=q|o!*-mU-n;cBD4If+hHu=?p!2Z7kATB zdxbJ%L%6A&dU;le2KbSRNOy-lc+g<|sh(WovhMKnG9BPiY9TZ@{kXtLpi=pLy~F4x zyDi2BM-cm4zv4~;m9h8*mX#4N-2~{~Yu*y>)C=#f_m5^)@NxgmNQdTOhv^?T+&^LF zb#SEnRrQHTmYh>;zL^H>WNTD@ijou`rP2XKw}p{gmcu^d$^HyKBh#PpzP~44S{hyz z?kM}oXx%6MU?OnLii0>*Ze~5nBUWC!W_|^>e)9I^W7CHr<9McY z1W7xEyi20T`D9ul3BqR#U!eYXfAN40tOkSbPc9OgF-8SSV0R@wBJ{`4xz$*GDgtIV zA=Yl1uZg3O({9AVV3QVm8o=1yuj8Aw_+Tw8I)i?Qsu(#06&b~NVQ5M7->0IDAB1iT zSt>4EA1D1*irUUs`EyW@!q@tzvBR+l68e4C_V`gF>yQ<6(h78|O64mT`k6e~J)AEE z`FHvy9p;p9XW6G3_U|uz>FVR_q=e`ZI=#TimAcMbRlvM&)Z5J_|0wEENnkuF zLnf}=SQJ(!U^^Kr4SYqXq?87%r%?Da6?d_Q=N=dcjRjFF1M=|$ zLK$VV$;21I#;@{1e)sJhI7Q!Y^+0>h@kibzXN}y$sK{C`BRRF|7`kV2IJwofh)O13}mN zbbW%5Xr>tvdy?X>j-X~Q5Z+%z(FN}oBE_gSW;K&>i{hE)aSR7f%_C-?ihJpfPjvxYftpX`L@Nx*_a5*j0NKK-qnq@_>=&ScsOWBSOE`93Z+&a z675rP@($`XH{w>tn~(rU8f^H2#{sK%6(mltR$me7eQYeKtd!wER*4Ul5FMC<%O^rB zGvxaFQ{x&}DUmqJzD|+yP$TX+pAJ4rwkPLx$h$iMkkt!0;D%o^5*7mA?X7$D1ZJ~+ zjnHJ#+WKl~>!!r~kL#20-BAo$L3*nSLNlmxk>4voL@}#7WGRXLqRU$DOlA+)XEf6a zK|t&@1H&eg$+Y*+zWYwXVTVRlo{ckE2$PcAe1i`o{;^9 zBZSYy7hTuODDf2BjEKMHaXsb6`I34JJdg*SvV+46Dh;kk+<>@yLhzeU#A0#K?C_2A zsEV2bLUaoqMpXWbW0l%ST%iFAfJcqYDh5W4@Vb|o>A3th zaPd|EV`z^@mZqy2jkBXJ1SmNu(+K`yav)egi=2SHZ5EOdfGnCGovwJ(edAMHN?mbXLVp2^zvC7!$vPZ!j$}&BHunkx9}< z%%2yvdzlfkWy(EFoXiT#lVV=bh*D?+=Ojq4bu={&8nQaKkB5y)wPnqof#sSF9I^RA5dN8w~esp-=_77 zmSTi3_w7HPtD)MQ<=H5RNGF3Ws`gB;I5!c&M0g-sOQ&mB7dO|&)`C@{GY<=orhjr++=spW>`}E_-4~=MwF=aeq+dEkGcJ+JamY=h70Hq7#r@YTp z@ot2@tO5M0R1v?I?HV8c%;ZFo)jNAZOvux+LTp-NZtg<%l{Wlm1Uwv66r06oX;W}| z=Gk-N8RF=upDX29$#U@XOf#RHUbYiYC<&xL>=i8?T16f9)x0YZB9U`?)%lc<19GwD z-x%Ci@ws)L2&^Qh#sSHym}r^bU8I#_fh564kx%{qaFF|-iXTkgujRf48p2GKL1d<| z=@}dKJyugo--!^7x$Hc)j>VRIPNE8Z--fUl%rYdce)LZBszftXhGX8+;xofW@L=fC zwDI}gO`e+zsK!!2(o83F((eAY@#~IQkex9li9p|`2LvB5g4Z>O1(_PlMX|kpBXKbh+1}+$JKu6XA0v5~CQw_%>2HFzQR< zZiAKRE}UB#kmlHb)I0#NZH#?$)sM~PY+>Ssl?6$B^>`7JMkx5F06$)#E1x81Oa@`APgHF1gwy!R~HBO?;z|`_^p-KCJ${M#UhK@dFX+5 zsn0=8!y>Bp$q~I*LwKuAy=KYnpYzY{6bGrAkiTtmZ|Jr4 zr#|cFB)qRB=NY%O9M?7MBJIrF{c0eS;! zH4~lLk1fD5cX;kz%UNQ-GZC47g&8Dl)Tb})(;<9@40QvXIFf?*>gb5jE*=Uish=Jz zmis~J6v|=aSz=i)E*`|K9l3>`AGwMj^pX>7uOzkmk-W0q*RCwC=gx%oU3d5`ju3#6 z6h^A1YlC2RG}z+I`{E`G1mnap;$zZRI|qMUdg9T>VG0S~M>v@1&?ev4n;LQOL@Cix zqYkQ*l%#%9gM+n_G!KXoFY~B7Ap$Uf4}E&;A4F7e9gj+ejHe_l-b??EaD{!fxU75A z`xFa?ouB-H_P+J6a()3KFzX~uq#=Rc{q4k^Dw_m20WS$UG-(cQbg`P;|3An~B3A7O zZ_xs4@k-XJ6(1iFc!i@cMH3!hoZe^cEZ_Q`pht?X3@rFB2@nfMb}DIQI%W|5a1K|4 zTZ`!qKmhBi@80lt!m7V0BDBZ(h0I#LM-eHacP(;*YeEz85;NXf$Dv(1J) z&D+3r9*KpuL;{margP*gAAdlP#UejZ!D=eXNW0T-)^O$EBrZhW5JB*PBun=^3ndX* zdW*_&W^BmG{{UKURN1Uh9EKKOOgj^a86+^t0dM#f^<_`P>A-FoVN0 z%eFY9@1g36V$?ur;i1=OyhGp;N)dVLs@#Reg!$1|Xit5yd^}`C7yWWJk3ENeO&}k& z*BS&oO}?qj1uLQf^SmIoEVze+iP3N&;ayR6%L-#@Uk*)81cgE>Jt`L~-5{7cYv)4E z_DflySs|eBRtj={K=wBxj$^TkK4qHk#zoQ-J6S;1u4pS$MFkQFtnA|2q;}kN_(cz! zUXNnQfwiAv^|%8$;f7&RYQmPi6nK3KRhf`~EpD zK7X=UD#Xx<6!_#%7X#|o&Uko0=>Jr=Luk_%Y|V=QC7J8RAzMqM+7I1SOR~=8;gf!W z2ZeRck0&t`vB)Y=NtQfbHBf7YI|npGb&u@72P>%ICh;qwX4v_cqW%zlRjt+k$I`b4 zGW~!5yUV@Y36(f_7HAmdsj=b@@l2E zwYKMl)4Rd@+4K0?@8jco;doQ8_7dqA3o4IFB2G7uYKTzfvC@+ zc4_ZDt?m8lQ`B3KH;R7(zOO@vNzjckQOfY%JMDv4phRsmKP$E*jf5$R8KL@kiUAx1 zjWWAmdYY!#c+E}>1~4_F)zY>0q>qN`(PIsBTag)iSC5)&8J7P$E32xrHZSz)~uw}bH=66;2o?wo?02ZNd(Gh6;P%+J1e z?-Flcg38XpYfjj0-*MHaJjO=|r~eo=*G%yO9wG^dva9OsF?fxx&m%!8jx`qAD!_Ck zi56!2TR~}(ij^#8+s&X_l++IZ;N$@+^n&QN^5@f;x_^tWMw4w?F%*dTb5ZXwaKgfh zj$rBmUl6a9sUB9({GadS4!vtw<^egiC2b-o6~tKoaa01AqEU+wPH*==dry2t&|>%Fg^L^uEbC) zZRzQZb}KP#>T=lX{@v}6575xP2QyJCVv|>-f}j)>C#vxzE@+;bH+sga1Ax{sBxGUq zXCt+!$xomkOsFI9r%~d@Jw&Gd=l(7Qmpm7iA~}B!7yUQ8-qU6*Qs{)Od}~y+1j+5J2OqhO9!~*c!;ta z>I&Wx{$&G+<0Wk`@)j&;NupTSUh|(KSd8b!Gs0~ZN%BvRJ12S`>>Q4c1tgL%r_xzQ zdUGp>w0#av5i|-)7$A*b4tg-Pe8i@dtVjnCx(SEB8DZ>yW{;;G+l+42J9SP+I_2rDU`cNMliWLk9+F<9yfGX z&gja=Q<>kGuH-WU;y0rC(qioID@>bALkUzE9|M#eJX0_KbSfxm89wm@F(02WpR12+ zjMjo~I38$rAPcX0aU%K7R0&AoJSEQ1scHO8ZD5>zam%;{3&+HDvyH9Lk}nn}X{Ac+ zaT5O9QBCxq$;V7sQLcUAJM9~LSmaB}Fqc$D2#<77=TBIS1Ia^P_Jh`Hg~5HE_7iAd zI>NFJs1~ZvhbK=sgrMiJj^>31xREpPW~}0JRzsnVymBG_Y%5z%k?GZ+y&^?;_}OoS&W$A=Nem(k^iZ>R8GKu`l=ejzWY|d1dQd>VX>%w{|yltty@ogJzu0p;PFGff?Z^qKxq^dyt zqtSBjUZ-D3EHwIK`#?kI%M#x8c!iUYvFLRfhHd!S0Y)rd#FYgD0eMjEB;kddr9wh{ zKfGWoJDJJU%C@^D@xA3pJ9VB8So6DQGLg+N53fDqXU3Kkk$Q$loVQ6Ro_=ZQJz1qk z4=?A|Mc*Cnd<;wtfoU&?3I|(>qsUsjIx+lI|5?bD&s5U`86}%gl%n0d%(o|daFUjV zpk6y8BFv;#=lwv|)#z8kXiVupDApI{T>W!dKBZB~q=J$%PKNKBN685_1VM}AlMkEHPy2yoLkB2$<1NeEX?ekXIQ34#6hqMQoP)mHr|*A5j246c9>*nHsS`54B>gwY%ce&2mRfkcaZ zjTeExTQAD1Z>h5ro{G_0cqZ2)fLTrJmJemZS~JqPy|#w6r6SO@Pd~4RlbauBB-q}i z1RP8^Lv!Ta{tF#!lQ!mH(&XKR92qVwZ#uEKS~^Czy|Fn8;*j<*I0?Y8yx9EZ@lQRA z;X8N>jEP7N$Y4*wx(TaG369zWpU5dxPSsVU>9Vx8-Yrjfwc=+Qkie=9MIo8bE5e1-lceQzkcNhs4Os91lrB5*T? zTt1@l&qBkQzVu;yGF}Y{;ygLAK>tlf@UVbm`PNm9046xkHfc7xyGwk_RGo0;{A9rq z%FP$y6-FNZO`r#=nSf%UNcfaoTWoM#1j-f5?w94V5KgvItL>zP=(4?m{rGY<=e~p& zTtEuDOlMi(x_!PU>g7czAnT1dM4%z4R!KK|#BtwGUFgv5m=fi27nCQeU(#I+F1#=L zwB-HxoJOGWnbQX5JPLR&rGDhk(>2fgmJeJlDtkfdNf}<#2z`?G_!n*c+~t?3qYoKwbbxI?RupxB zqw%dwf2qzEjUl@!auG7=2twYSIimk*d|c)NAE*M|DwG|wWB-{$&DI_s?Hr{Wv)Qdz zztvz}#25Er+6eJ2wIskBq-@4^bh zUhIxZy@Yu;$hISk@gD` z$xa^?mN*jru-}y`Flv%^e^mo@QsD8AoX~F;iyt4(OwH$v_VqQ-9I0;f{nxTS6uN(L z=GUKqh06zJ8rXJYj{pmE3(FE~q{O-stFL4W+g7J+^lBl~!gzq`)VQ*JEcx)>(zx8_ zw^ho|iTf@kj9AYa60u$c4A)V zbUptX0GUDhCWj->TW-*e?{t6BP9u-aX49Dm{vBdv`OE)WJlaltGO`6J_<0x3KsW*F z@iV~h9ov~H>+o_+=CvrzbZ%wDS(y5W$9XN9K8tcqS^$3!Ofqu z&rD@lJ@1?=PzT+mUW)1pgT*R@VJ?9HHOYQ?+^3VUYev5^G|ULYn`%w+;(V}=b?)%Y zyCLg6)p^x{QsMDNd)3RId{Q~=qqk2Meal5JI}xd*4r1c{k+JMSxmyo{l*7>e>L75g zY--o6$K2Ub$Ojz&-E2R%zyn^~UPKKXfzfCtfNlKg#SzD`*X$sm$UxX$?!Fo5hk1-o z&^jj(Pb;Pa4zJ65wa-W=BCT`#pA0jCG|u%Z^Dqf zSv(!?V-E(+ovBrrr{c4-u5Kr6r_%vrW&v(Fki)|D3|x!wV;g70+0tDYHSCsl>Zsg}rO}Tj#C2|vrS?FLs zG0134`|@6Qb)_;W^+X6wQ^_oX5GVWVNa6-#eP0e%t4T3n|4{ zEd<&^Qb-`&Ajx!E?jPE}&qUsd5Nq?jeDS4o&jq{u6<)&3uGaY~P}8gkZ#-i^(zGF?{NNK{?OGS{9CP zg}B}g_Me-6a7S)X!H05hHu&e60Z&vkWF1{fS1T%SIs$3A{pXU~ zE{!0-`XM@l%_PV+U33KHr!nMy4NwxBHN>h9JopWdG4EW#&puXVAgB|`r^X}OdL(A% zD~hCgknB@??LpZTl(m_?1_BarS}I+_va^C0cn?&?IWCRYU-V-MJ<}lc1%O?)O;;O{ zpad+U4Q3VZ5u+yz?DZ7htLdTc5EwUh@En$c6-5=? zt;8)(LjLYT2hq$&oU0w0_*FBd=aJ+~Tw9?erO5>Yze=&OyA$Wz;EID!iEkGjRtblb z4<+l_yd-a>))tyAC%Zq|Km~6wCBHQ{iXO-mmIx=?Q250G`fxr<_l8{kT%TI!Tg9bD zy|5&RaGd@~^qu96F!YRoX4RTRwoLf&!^*~~OLtMu;^BNR^V)kEHyo3^~j z*0!)?*#{=2d#MPjF$3;8=TJxRR+#LB^&wkY+W86f6zWw2=YfzpY~JIq0x!@PdtXu` zz2cvWWLI2?CP%*c*_o)pkFDZ^Df(1FzszY{w#QdZcd(W1ytV3?OW&0oBCVmS?mKrV zPh_}3M|@?~XCe;TR4I4%?~GZ`EuaJFTOulc~i7b?Mwgj z!}r<+Rv%AKJ)dz|D zlITWHfj`m*UnbiJ!km^6kI zjMbs`yXCc00zTfoxHzS#11=?YVUWD-XuM&hJ(cq{FhS-&v3&W zBu5-im8NKFOnz9_x7`kGtw5?h^h*6Yd=TEz+Y&c`aeWI_sZ?E56}?0<6|n`)P{ z`JRn>r-x%tn%`;kLKFJd-o_?;mx&Vd@S~#0Q zEfg+X0-LG6$~0Bujs}VO71#AoFR2<6b4)k<+~Ets1;$k0s>tYx>U{V7)esYB@bgSZ z(&{AFd%Dv;P!!8*7-SvsxKFxK7kytH|JIml2&zcHZSmBaTuAkT6^hfEuXAN7^ZnW0 z$Nx)YES48+A_Z}0xIk~|T+d5b$$Da$km<4PW289OuI^MpvC2u`RDW7uokm6d|1ue9 zhQTa4G>*M;8uh}m$l1L6y!f-QG#LfOwvyYsrH@+8^_aB0+{yc$xCV@-1l&P!S!^Vr zEe^kk`avwst~zL7fZ@2OciFXbDG#LCde3L9qc7m%^65*@i? z7v56+45uQsX`F=jcDrK_1N*wX&D2lSHDF`N&mzTBYznMXG_a1Z7JM0$(7TGQlaj2FsZI+ebG}CfYi;1M?cWzKSqADz^5qbEqp#xCRcZl8=ZacPg7)>d>Ew9 zy}{cCJl@FWVHd8cLpSgB`cfCC;#!Het+e!)46w?xgq5*0*RA;rb03XuVl?`5e&gJy zrcHw1S2&Nw%6#@jV5sZ|dvj*{oZ4f#ixLw{(ysTNUw?Qgq?6xY`KDW zAHTa+rtII_%D(XO=DESwNX_18nFsTMI$YvR5Bkyl16Z}r0G9?tECfSio}5_6k8|bP z&EkL}2Cm5rcU5I)0SDa_45wgW)s$I*r?q_WoR+fn3+RYfL)`CbqU7^GvoHrdr<{t|^7zwZ zj;h6Iio;#^4PQ@eeu*P$uU^`o-+p5Kwh9j;TE8?`-kdm|RO?>SZ1iLYZN$YtNLVIa z$g1#T@LKp?b31<7@2Duua`ZY_6MrTk8n5O+A9zot2Uv>zV=DD#`uohVI)w(stm~{j z56Ye{vu6+8QTm?-9XXmg+DG0x z<`(DbTy;!C!Lg1+zn#Md_GxN0kQbD9~8qO~WfJCnC`Hb;M-MSyvCh^no` zXTv{jH->*|yvbq!C8Yn$;sOWfY#?SDHz-k%7YqSbpRy^g{pdg!!=0R>TKINubO-=Lq|Fx}o6-DU2-LU?TOZLOARs@W!xf+}-^Z9?2au z_vxMet~{=mb-m14@w#;&ql`2LmQN$CX#C1LpW*s5l&RO8Be#SgkK?mzeyf7V!O z6@0i=_BtE3(WDNIX7Ailo0%93y}Ng$+S8iz1gd%;?kzm$mtB0*#*7nU3>$sJ4T&_Z zg@F`zz}*pAWmZ=RU8| z0mAW0za^EZ8&{I;RA%|@GDM%yT6@$<7?|AE(Uv6p6)1lm8WE$+pP3!L@vE%3R71T< zzLiE*fR40KP^Yg9q#OTx^ZM77vFtuOH7+{VP(056aWlM5V#jFriT4ph!`=^r zmj!uWmfdGV`J ztAU&tH4mK4$k#^@H)wGu#6YZC)ui%ydYu3LX!5PLFf4q{TQml}^B+bGVCZv$CV}V_ z6hroq58Ef`JKj&Gx_^x8T()_Ro9OqZ8(@Olo1Ab@$8D4ZY0a+GDcy+Xql*N zcO0ga6Sjafy#vp=0-N(ggr60m)YQdw$6*}IzUaIa;aC~*K!DPja*OJ|jD7CF+{03+ z$v3CLIQ89hIa#+`-j{aww2xcURlBF?lHIt|Qk*gx3nJz?dqq0SiYP&M^I#_q=j? zp!}wZ1;n&qvd_zWV-Z5{W!+GB+3>g{?%?@lU@_=hT`42LtWH`<6P*sExU1_Vs;_Je zPBIs$)TbLFhA=n#JI^+@Z?ckUdfx&NN4NAir_OR}3c;J1iEL+dN@gQAst%$e0Kb&%$>0+nq~JA=15EkgOd=cYzmrf$Lm9 zD|oSvYNWXRBHrEhA2}o~R`BIK8TD zv-0EH`J%EsgaD=BQ>v$Hs42Y>$3+|C=j6L_iL|W;mZP^QHCEb`ni3QFFtTxDINv^N z)OJWc^1b}7_#i6}zLQ->j@dqyG|Qhv@K@B#PTD+k2G1=X-0Qyl@eBNcCGTWSoxB9$ zJGG+#wiv$&C)U>7jOS~%5|?{`ebm~MdQzp5ZPb|?cHb2LnJS%eN(W#zdctQWf^zyp zK57pooP;?!UxtbL$tDV>54&O>|TRK9Rc<$=5=w)`&$2(B(w$=@N_n_clnk?0(2(u)ZmQ0am^sOx1J`=sIo;r+UIwo1sA z`^5;l><4aAx-ef)Ic)sp#DmQ)`H_ILdW9QG3qCHvX;0UPQkeK*|I+0X;8`=@?9_VY zri)o$DA-g^!qNq9!rk7|0)0S1lx?`v_7Re`ql5GAWZ0jHspny2od@FrF?@>9mR7q} zwb5^F?~;z?n(Oxzy@zjQAli)GX5P2L>PS#uhs_Eq7vf~=<39QJp5Mx@Cu_b!XSKxr z30$?!*jJ8SVYBJXvv&zh!t~VSF}7ZHx&}{~6DZT&8dz8eNC` zY_4Eh7=gm2<9jxQlZ3gshc|e@=~pjuI^xQ(T~X|H=CS%;N2j=tIs+r9c?)O1YW}*4lSEIp`!g87| zag1{5j~>RPt3jG~W#Ba8HRbJ;DAE zS{EC-F>LFFg(`<&VL4lF8}dB1;MQ)mSBOh4hwRUN#+Gh>q^=@JM(deKDYe_s$veQ!C&XNJ6G|i$Ha{ z6bU&NM`u&;UhWp ziH4QzX1m4s?IQ)tV4F#FxbQRy|HWs>(X8KR7Q1TOJ++yAq4C=$M@sFDS?q5PwfW&S zU!6VKdEpI{C*ymTTw!D=aq2dR8h6-$vQH&Xe(ZAdA{Q9!a~|UxTxtJalo6D0V!&1{ z1YIg)fMXhLe?V|v0RteM*UXGaVAB35fIfHIQq56RyDj@N>f?5H7CZRGjuTvep%(D; zwg3Y>$C-=5M4=bB4qA``$X~y!<;H!yML=)&O^66SydOmjbz}rx*!7nw?4Cg>+8&j; z<|007*kAx@{~}o~2aLQJzgvC_mP3tPJMjXaI8Rsn$vUrpEB5?HRTYSj9_3%Osr^vn zWDL3^`*}C=pb(y}{j!~2w$3Sr6Sn#D-kyq~_ z9m?*fD0asU%U+!SRntZJuxcICMwG@w1N1s?R{KF}jZHLp)Sz&j_CL!AVz)kXZFD-` z?4{U*8aUq$BU^-DwPhsyG`3htmx{%Q0|`7n%>$zUa9n1mgA1JeoowBpqSSZfg674BlB5WM?FO6)Z9)>GDq=>qmT!v#cTn z9EJ_sE7CpR;*b;iRBx->-qQXdtrdAynrq%tI6fgja7bDn7`2J!YoCj}i+smr)>M`- ze?1|3Qt4*NkZun)J~`D7{ub{n|AFrXABWp(!`^Q)v!BgyaN^n3D?uDJoe)E;8*`@( zWf#L2v8l7r4^8sqRokR}p5QtC7vK)PyGjvI+l=XS@9^4M$kY4S35jt2vH?Nq=-wdfUHF}y$ZxNU3j@5!^ z>45#r`A&K-h06)YFpFO=J5Y-zud?Gei|#NGZj>?ub;g;F#5o1EAZHPZ(E;d8bsBqB z1Q_x=asv0fX$is_Hgt-wqaAKL(u3=Z%JiGkz%hD%bOfTZ7Q$m#E(m{Axx17f<&H

    wyQuQbqeDC?b4FVon9>0iW}N&#hIJCuHi ze_tG`$fgtZ=mG0UAoo2g$j- zE~TmI*Ympu$~P=G%a`}|eyX0UI5nB3Oe{<|tt!({SI~%@hT{*5v=|8jKImTq_iReD z8mi|K6`4RA<{X);PB&hO5zTLFABv2BO^>$mUwGC_^feZDIUU9~5|Fti103@;4YN>o z&OE+5Ac+)+aupYTe#m9JTpV#iG+;JR?HT3l^PBzfwmU5BYH|scNUpy0f&5v0YCNs6>1lPq=6TRc6tQV#Y>U+sMoA(LN#%$$9rw4%A1> zNIk)CQdjcq#R)sBbi44>h{0PU+^{mk6Hf=!V)(2_9y&Idi6^|#p8UZFOP?vwx^Shg zCGIFQ2ilvUCX59~)MEdI#dy#!G{2it#4dm%@BXV62`miYSpYIV-g+VoeR$b}!awtb zG&(n&@b_sgEBsLnu@vgzcl#R8T&p#!>)_abxH4)AN(|7fu3_;)*anq+BabPRaCXqv zji=?|Xp+}*H0hn^a;hvYn+Ys7CI{=Rm>~jnUJjZ!pQG#jNHJ;YmhiN;691ehBS_d| zBQwyV{iI%_hO$?*MC z%eZ0uDcq9v zkK5R12hXJlT@Nb-XJiJ#8tOvE+$(Dg>40MqAitPx?fiQ<4l0Yv=>dUQbV$WS?r~8> zJw0SK+fF^1aPoJn<-nUZb!q7e^E2f)feD>fecXJWDQ!6A_qi(%uKAhu z%uqehN*R}7^cJa9jaI7kSD-OwZ_De$b`Egy$JzcxyXnGp4L;F}@6T^VGXTl*=9lXe z0oC&ha4^7Os=zV{qKiH_`$h@Y5+{HyITVBaVV*BjdOG2FCWbHalbQVnkYCe9ZghE! z$`eC<6NEp4gL1|94gWw)(EOvAf9X90bUW_0lzE!3XRJ14sn9Vwtf97;DxjU0Rj5X~ zay<3BmKP?5Ix#-4d?khxyOrSEJ{9?1zCUOE!LLzqxF)$MN#dWeWZ3MoSwOL+dwLJQ zwe^edpAi2c3c|bFq9`aaHmpMNqxHO(jIa`#-i{B;ev`jbvh9?7o%PD`!*Nb9xWSTB zIxVYHkoNa4Xg+1a-NCTY*dB6D&?fHFNjrvQR_Ix z?E_M|shdKpIluQ!L*z2YIJ&6Pu_xk5x+*bzT3GCd2A3)zbD7W`h^fr0HWySytpiq5+mAsACAQ^2UbtIhccb1G&xdTF7j{>=v zopz3kBQ?H9(zmERWUjoTgcW2s!pB~vr98wsmR1u@3sd1z<7BHj-$-M}+ zw!S+toI-VXdvTH@%urwJrBKK5yE8|FIaDKLZrW$(567|`ufJS}YVC{x#!ipk%GG|l z28aT})XbbhjYP5)FdX~pfO6LOQ-U%MuU4>CE9K#)Uv3AwB#~hXH51;gzDXvszsa!7ZwYQJv>$~a^_!%)D2tVg9iMH4-S%&5=`?B+~?s=EQmG@V}Lk5iQ z23tA4g8@#Ezqu2Ts4lCDE;IWN67YjN@U?4PCuVJir~!%%zo=iR!}4?#{%(s5Cg9$W zOvw&f;@!D_X8{7LT`7^dCHt<2UN-c9y+fZaoFoj?wh;BacyI7oQ90rRzB26dMg=&T zbw|~4!!<=_cWCdDpX_|E^1HKdOb^52`L_FT0%AT&^nki|dKdR;f!KIhiOIkfbcnSG z)EyJQR%lx?I{Ex#L1M<}`_T+8Hn@D<$^J2oTlCuyY(Fq{@rvfdA3r(DaF>w>9x!PQ zU4)sN|2CIEsDrPb1W8Q0AE6f4&Hqb{jJ`1*;NS!-UV5xfsm8tnTWdyi!CS`rVXG$I zRopP9Az%78WhCUC?e5=tFQA91;2vTa?j)N^Q_QV4(O1>3xVqmYT=g?RUktEm*CYrL zzA}%0c4)G9gl@Q9ior{%9=<)g0n3jmH_pc&{a6mTyp|CF&v{k&udQ>km1yITGd@dk zo8B=$?`;lU?6_Ew7aUGbyyjLeE-+`aefM9~v>!Y(s`gAP^K0!^`$(F?ySc!gfLnM! zt)AKkA!v?p^zCy1$rTb`%((d22P#q9Q4Tg5{%0kpFAtvM1h_>bUtKm3mrH=TWc}FB zgYHex86Era!TvI*Yus1FT3_|*UARK;pf&yJ8@Ua<_zqftsXy9lI0>72tg?G%-pD*n zOKfcO^7N{zgHQ`H1HtBlNCN^I@2Z)ZE(_Msu%kcaRsz(_7H+YCeXhxMoi!tO;a{`9 zaB8GDtV5*F6I@*~4>J&Tvin6EP|h27l#?q(N!cOX_MzSgk-u#1dCErq;I5!wc7u1V z1iU;i517b4lmw?I6-zIN;q9aGT5$b`D~I}*M^4wRCzi0!&Tn9=n&gSakBKYRqw*&p z@8jWAWPnA0&z68X%LE7mW6?NDVK9g>vDQBRzo3&U z7Kx*$;EDO{evHyHGy&Vg#%N}+=Ef(Nly^cB{@V?O=CW-)P1j@i5;(C{9c*uyO7c2X z2FyDd=U2~V_?ap*ka&bbmz5k5__ei_%up3>m^!VTRQN~gzl&^3r8qdIIyFM;qc~u6 zK_q8r3{ZI$$&a?RfyboFV@{3cXuTPvW5+0kuL7?yM<9aA8u(QAqqzKm) z2Ns6m-kzth@rqgThfqwoXjkH0-wT}~hpaYg2D(IOjhu5NQ*Zh45>{TyZ?+51rX9A7 zZTPTbJykRhyIpSy5~S5bpbG6lS@31us)iR+t!$=|cRsSfp7rboqQlaS9Xw8CJ$8Uj zpyw2qB!!sHSG~2UE-qQ;hlJtiVdArq>1?GhOxAtjnV0-ejiol^D(x@e&H*LA#QyjR z+Uv?@^l;BdbG$Mom4y4koP@ujEqBmzR0AxgT$z;#<(Wcy?NO+lNaG z;IbcH_?{haJ8X-w7Gl9}^#UDRcbQo7K zR|u&8jYnv#gz+hm1H3`6`w#hT?Wh3Gm7YMKD|7GzD+wt?2br4E1gWSVj~flc=jO2E zA388$*G_D5#^%3nV7?(*aPb9a;$zGx|L3@vo;z^YFhn(XvGb$%&C4&fdgoM{I0^nW zk<776vJbB4hyXYGKJaM@`RRc7E_7=N=gN-FV>h)^#%l@%dvELV2koS{qa5QeHTO$O z-Fq1#t&_<(+D6?mt!_Xh#>)*nthIM^rGuT1A)7R2J3)jGM2Wo1;oFqgB#c3W@ju+V z-YT!vhq=xTe>=Sf6MTjIJ*4m3D5PDfMNc5uodCONS#>!;?~2MZx*lnTRh`yjG7_^k`N z#bv+P9Ib!ljUYou4O-=ofNyM?8)4AOdg^f~jFgg;p_*0v0f~I3` zk~&@U1~rRKErfEF8D2*cOVxP{3dFeL_Y8YbFUm91xU$r^W!bO@rwasior&X1W+&2& z^w{u-d1)u-RqmkKK?6AvK(uw~1~V8t{W9g2aQ&&Gvk(aC8S~;h9-UN-CBs%f%lF-7 zJ4d-m+?N#@V{|p$OL-udkVc9tud~)(pt2WMQ7G@bXGe-rt(d!$ za41y{bgQ`?M}G4k?|rA{XXwD(@8q(i3D2!43+) z9m?6-y#7=x&4W4Nj$wj^W7didwl(S7SHB3p?QVaaOr4tIh)bIt=xt3VU|Ix_knSO| zEtErq`P4(%ZP;z59;9ZbI+LfBDeN53lSrZ(*@_P%z1D*)&=O3yW^b365U!M&MQh0f z(Vk1{`NEN}5$M2-rq{my?{#l*_?x+0r4Jxhvq7Avuxvz>yUIg_^3mT z=z<%Dc2|+6W#hApJBrt&1@hSv*S?dL3|DzP-5PhX@CA?PmPbzh%~Ki*cVg2lmn zlkPi)Hu(R%zixc1EZL|Kv9fqruJyHu+xc8q&&weyCJ!b~YFI;+GXPvsaA#3jb_FfH zIP5qbrC>YF<;yKOx-ZNQv-f1{V~O{=r0teP_3juphiD32i2g?`Mr7*jLN!^%?2iih3*`bl>mT?rOW76w(3rr=4lJ_DZV zJf^k;>FQpI=bM!Nisgq#s1|23ZMq_-Vr>luJhid4$33vz-)yo-8C$C>^GbG&c9;%$ z@O>oKdHI&&NugDgO&EN3<>|}C38ir z?$l+|MFtoZTSYZjwX532&0?3cte`^X3yhSn&X3d_ibU*XtdQb@e0EeMW!kDVA>> zUiemV^+v$s!JAQ!E)DEI$FeiQ(|fSvI`Oute?nsLDFkUk;)okJVNFU>ko8h+<8UoI zJG}hpy%5yc;`r-5GXfoywl~X@ny&c}_`>CqPxP}R@8;g$%;WPSaGKY0tgom+cJ4BE zD|0#^D~$ZibJ;tM9%y-Vb6T7_9755s+bhC+tJCOb1vK(8FC|pPs6@vGue@%yneO)J-fUd#rc(GCC7S^_ei=4nVp`>T98TA%dEYus_9_$+}ciV`YRET z3M78szL5F%U_Nc~piX^$v5h-0`#?; zP|Da6YNKs2v6KO{oYC{Z;71&lEL4HCmA95HH!7>XOu0WqJdLAzW+ODJPGXF#@nZAO z7}twL9+MpyfEPZ>k_9&`t>N#f=VyNJSd+ui-=>X(R_VhcSO9nCi+Q1|F20J1CGMy7 z>_Bf@3aUxCFsPpnSeg42Gua{EGLg`=BEt_g!xe;h0O|2H&Ejj($YAsqUkpCeLPGD= zIja^mtMM@-6+T}S=UTP!d8WN^M9&H|7mMSZsR4@iy=U|k@i$`7hcBe#vu~zSrJr7~ z_U$aufSnh5Mq=we`HJ~|vLUcjYOTE(|5!Nhcr2$yH)paM+Hcg)c_LMq6lx7qauub>kHj{DUxtw-J(puSd7#D9FBK4Btam)ylpb~>^;<{;`GQ+{ zxJu^jPTF;XY5M4e+F)n^>^gr9uVn2==c6DbA_38Gmu2OzQe;z-1srMWt!xS8U(nOs zrWi2fryk$*kd!GhZubj7@P%5_x*g@uzeF(+?x^^}-yZcBjNOTW>5hM;?Oez0s^AvI zB1vrX?V7R@#y`#crJb%kZ`DbY(V0Ed&WqDvoWqJc-&TY3GkOR*sy|U)8=Ex@zK3TM zc@ync7SF>40q&ce1gpF$?UI#dR~x5~vG;$?z87GJDE!!QlOXa+rx@V3V+_80xFrT? zHM2#aSFoM}+*rpy?v>1d=99Y5IH<+5I+PlY`dPI7W5ecoBc-#(@W@-Ar(tg><@s0I zT#7xV;0kEmo>iRVFL8q7($c}OJOfblVYP$Vj9o@c@A!uHX}HcBYRApgsug)6#ao=9 zJH}J;^(@-*xy!SH>}ADcl9kP4sX2oMSOF|WB%HWl|p`A?6b)w`2XbCcz$k|ci#281TxyMDW<@F+g%JhTtRV+@&3d;=iK&Lurmm!nb_?*-e z1m?ya-a9znTLw7^e|kiP!EsK49pszer-vB`zyG`OJ`3@;l}*2OI_+oClbI{e$-6QH zhW{Cn#Y;`};2gj|*gq(Ho$p=`u625NyA;g?s!S<3qJLacJFJVk0TvfG;vg0oX0}Q@ zofWvEjrBVX%GPATzDCNNI&U{Z8J4EZch1gFN3Z9M49<-5jD`9yquE0&oDpHXs&gw#z(%qq3tF%s6US_1=k9`<1>(kzgGLrLLz z%&qW{ysI{8q4d`n_^Yw&-`^ibIWV3{KOiSNFKZ;wYJ>3NH*N(>X4TzezI3)*{8-p8Y?fzQQlc?+KUgPU&W8q?c5X zhFuzIC8T5N7LZPrhFw6ZWkDn)q;x3>5tOCNrG%xF5CsA6>-Tr>=l%!p%$b=p@0{m( z#?|YISA#9uD^~oZI_^#oR>G69*GrsY7;70|P-f_}$MB{a0zuIsljIlgRHjb*{Gs)I zA2O1|3Q<~C-W-k3t?gVVvC%3%1$ffUf zFS3n)`($r^AEp)0TM*m^kBHqu^Af;)r=QQ1@|m(Edq!kuyGyDiP_^{b(ADv=1JI6^9AG)7xbKV z2-RKqpig>c>~3>e_Wj)f?99KS2&j)99JZrTN8iIc9HJ!?|VMaz^16*bGXF zFGh-}9mmQWHK$}*wV1wA{9>7YLvajwl}z2>g~oM_7NsOJ6wq{5KBR)S%~b@pT& z)-8PKuI(Eq`*55Yl>E>v=(cMj49s=7sHo%)C+HI3$fuywv&oz&43-bv;^WW9a}0Y- zfbe{wGYpo&y>@~=9<9JCiN*-;&N8R);;Yv4!ln?=2 zCa+9z8i~LyeemX8JLkvMH!Vvl2s_~7?v4gPci0|vdrFvAKx0h=CfVkz6&20<$KCJj zrxNvH4B0~kTbcwpGh;f1o+eT>wA@1=D~s^jc+A-R%(YyF*lO{|%C_G7GXM+4z8`f&jM%BdLA0hEJUIyL}G_rb8c!4TsZ#fI=2PlZaY^WE4 z$G;XB`3$I9iyRrJ1-;hO7L7X#&Ny~M;7I`pQ-?a8x6iK+9vVQBm z)5Esr-l|j9qC8fSGk$O6WAZk|@%O45DiE>D!V7AFXCJ^}reccZ{zHTaPZ<}^)z=C? z%)BC!5)Eh$AbP4M&bEfBN-b5~v1tl65{iz)@7?of@PRiy@$fGN+gpH)!3=|jz~DW6 zD4=iE!KW<535`HNo&Hw}HSv%~KoV>H_J1%72+Yt9DGm3I?M~hYF|l!f3*V2Vdquvn zMXH>wixztQwkAEXPrr5G5CVvzy&*e{diFtI%VX18(-xj-A7z6e|rQ84&P z(<*oRyEsavkJia*g~-(P_!~ZQhd+S5`~Hsy{X1)H-$U?0-aCkM?ozAIn8AgfA)3%a zwa}-p3?1R?f{_~?^Sd2d#^)K7xMa~lRCzqTsK{BKjHKh64?^UDfX0c$v)pH(&0twV zm0qU&Oy9b;J_D7#aB%2?3v?*^$=%?}9h~ z^w)i$ZECn3ZxIgMznU?f1xdtwKo4%zyE$9I%w5Wy2>ZcQ9MPhFto&{UDxOCKu@ikZ z#ghi!5&XBZ4?9XWzJgpOqN8%h9uO#h5#t&U8@8Ez`_k>%t>THPaw>;QdneSN%1=zl zP0WsIp&VZ-wJjG43HcwIFfQ{W2OW%VukH{kP_O?~eC6PfgV{T)!?w0xTA zK|;a=p(-XW+^N92KzvdwdlJU32h9$rltVT=I)vPdz>wcUJi&+R$RQLv?u!EgQQrdX za#;Q35O&FU2$;v zmIheLXPQPhoSthT-M=5AOL`1ZRJ=OCLmE9b>8L%@^}qd_-*pgG_vg&qA|Wq>@_nun z1@~5~5Tsa}5Y%t#skI#9q{*XBXlmsJ>EvJQevbBHh{P0`*zbR=YZYVr_mPY7f=e4L zrL$ywhPmugY*5Q#+f>FsGbL4QKavb&hXX$gSr-{;1C#O3i;MEFh3}ONt-CP{{Vk6? z&ynmBFjtegYjFI6My4p*U)d&fp9t!5gI|{>m&W0C1ZJFb8>X6`bACo*Ht|r0)m)%@ z%$Qiryl1K_xD3xUYB)qcPYq3H=SP}ncrVXrkF%}L=CzVSq)@xgV~oN7JjexIZeRwO z@~2?GrVbjUHIS(VCV>CO!|l`e=5|;m0vMLuA~4%xGEg6*VCJpxQ+xA~VI{33LoMX< z-=%jAmbR+dnNtXqY`G@WsqcuRaY;UVC&B%34Sb4f!oCnl=381#XVQY3854d>D^86%>9R>So`Q zL7?6g|5-DaHRnBUrRTlu#xTewu2p25WuA>IgpJ>c?_26|+N~;zr5RO&eE}a>=_f#` zu~zTO(FIH7EnC!@?x;9uz)~pSa(H=fFm$yvjMo`LutK*QW6{8FoXk94Wz+Wua z*4sRvVsv}m;Xt!OggqMp%G{F+|0&(j{l**mfYuw~s^~#i4g_>L{FD&!0)p`PRluQH z_N}Be%_sL>p@K5|w()7Ar5omI;l~?%gjAUg#L?*sCvkXYCN;A1^-DDF&iUkyLXK?K zrj?D_g;JJ_fO3RGQa4@D8L6FXT3@8)vxm^yy}$si(Z(nnPfaq<33cpn<|jV&v$=8p zGjrc*I_-vt&}`>)l&cinQ|d%w$lH|C-}IsWtbE20-C_=$iyvcDP+ z>M57~z>Fk7%nCGhq9>^V6MIhZ^J->R8S%Q&xY{({VjyUU{O_|KU8J{zY;+zwf&@)| zn71Yvs>*^pQ>9!lrfKX^2e7=M!~H` zU%2-~9@*J(o@sbrAp0fSX{o31bidz!7_fID#_VUtN&y=`gxSGY)-C%+(uqTTvIkLS zz=KX~6`&9ToXY*mu6-~rpgSre;3#m2BjmAkkQ_;oPM=ud~V580Ft3 zy1x)c>E0(oYu~GfvBK4aWg*u*@t6lzc8GH3>9dC^E$iAT^Ne7}k6Vyk^ekQjoeI8a zms2fAYQ31HUxGy>3rH4WszbgVZY^vMMw8o{$nuUYxv|JpvLXRFIDaECa8J*5ZK6BO zTtaB4-#Km<@@>}@R zW|mjf=-SQb-qssHD`xKya`)9NiV0v5HLU$#Z~f0%xRd+Tu2ss2&T?cRiHP>0paDqdB1 z99Jv3vvTD0qsr0gw}frX>!YexJk=EU0#m?*RPzq`1cwf>h>Xx|usakSK4fVci!+zSETWImzSlh$&? zX8USBtj~y0Vb6Z+5+bA=DRz2@9|rC@F~>3X8pzvbVG4?5nX%#f`2>h~WBv3zGO?`) z`ZB7|wQ*U4=`t6T!Hlg7KVAXUbyBF+hm<>`XoENHV0yNjYt?olC@K9o)tpA4X`0iP zSd{JUG3pkZCaqaEa6xD>|$K!z0+QIPdhRj_X1CKk7vZPf@7GeqxCY^k#J@;bruL!3r z*Y)OhjsUK3-LM@0>s2n6_$~A2ue3*A(KaVBj~iSvoSN?QWS&=NinEfn@7(AwzRfW7 zAAB)vs$MvAtxT_QDZxR-Oz;CxiG}`~;C>PuOn<+YB}U&1={-~*TK7d&JF!KFXG z4Z`0M3#o@IfieQ4oR8oAOSu=2xl5a=69Iyi$dWT{kU&`2b;%F%U`*Xvp*6@NlmyBQ zxCk!XC)2P1;~(@PM=;&m&M;BY|LQHZS~s&<7MQz9fNXs&xL zk!W!XJytl{??$KECghrb04zh~URA8E7ODFrC@WQUjAvcPB{@&&Gxo_r_=CuLZNKsN z?lb?NN^IU4k-0bWuW=7zg(&0AY4gv07V_>QdsOhk3E$g(46sC6h~~h9Q!r9EqlGN2 zl%PEB(Oy_+mJF|j&}H2YO-V@&m*i6Yx}7WZATXOq7sH!MTle&10x zHl?i-S;kr#VP``1MeYkJio9SL7!Q#(eEGS36!mdX+`KQrf}E)?vrp9i0jIC7#s0&C zGfD!)D2%^yEFzQZ)x0MaYU!7>FqnHo~ekc=cO-A2z%VjoJIC=YNaraY5QWnz0%CD z_e-~bm8nTvvHMB?pd&AurBGz)T)Rb12JN8s^v{)X@43Dd)3LcjvDtXvj{#MLwH%&F zih$_m>j6X@uzO^f@*hI#%@}N>DcVdY%HQk1U?co5*g$6bUnTK?iWL*6yb75$83x&+ z|8tsW9%mPUa?NHfJC0Oaw#*C`;2|!y))s1bDO@4w0B`NYm+dHJ>Ihca(rbG6q zC|2*!4Jn4H!0e}HR_A_zG9ORBZyUI*f$f$KtPMd1;M#s`w%3r4gDb+eqMbE|jrehw zYy$cI<{lr9s`VrD+%p&rUQ^2=e3N6 z`@%%2kBT8#IT!lpx#!nrN|r9`k?=I-aR%4B{R= z(swtLWeFLVFs#mJ8#Az;X7fF{Fy@aU7DpZQx>ARHU1L=XW6?{n56e?*lO)?as0_!A zeemJ<_^JzY&dlblIM1u1HvCuqL2BMtWDbpPAa#o#M`!h+eQI3Vn5N3ahY-aLM;+sJ z(6*aJgy%LdLz&2gnyXT8iLKj)Qv!8BC!kb?<9 zV$hqtj*!u*%eG-RJ}^S6yKsToUx|K!$XP2(mbm#FF0#llKq)A9L@recDuX)zk>Y8x zACa;8eeV`>W!s_!!p%8ZAKJ!3gQQ9{n~TdQ%=jE8EmjAC%}WpLo!3icy@u3pYJCqCFX|U<`Wp8@`$p2Sh|jv*T* z&Spz{Y@00KHSV1aol=2I@Lr>F4P88A$QV+AezCgGlIrO<7(3bCnN-8+%!b>MFsD&* zrQlq;Q@>$H8q{8v-Nawrx_fFL8(?RhB@d=%9mmz2Aw&zO6Rp^TTh$K>n+Bg%Q=BqQ zYZSu+>zcz*0^6ew#uA=Y6RQJ#@+*saB0}|_9JF2aD{gtPd%s=BZOtsF|7nICdTBGp ziNO;o%d38Bd{cY(x?d`^p(ojVkp4x+1XAmX-6sjOC=*s5K)E(Xii_P3kdpitaQ*+~ zXa@6KxM~K$XKB_$h)j@JzEtR$xfJpFstTr|p#1CB&%{N9C2kDzE>WuIbFD>UeDYZclTQ`e^@ zf2BhA=3DMDa0cppH2k&eMzjBIi6dF<{gd5lwCJA5@x|JiTp-2uQgCRN>*~@YL3RC% zwH+S-g?}ch|BMs0BsH<9)amgF4%`EB;b5;{edZA8ufqSr3>J?8TGtHbh43C`;ukmT zd~F6ZcP{JV`*Af0ihUqK=L78?=Ux4_551n>O#Lhn;65G#wq1V6C`*U|o}^bacY9~( zkinf1`cpQ`&)F%RT~90S1cCqGQ|tc zvj|TvU}L_n70h=9IVPf+c}wEFe17ER^gmIN%%pu%J2U6Dj4_z}{o-1iq~AEqWfn07 zYmL(ieqgS2c8OiZzXZ?ckpg)G7uI<^`q9CzXK+f77m>1P-Kd`rpx%{!x_#*f$ z-AVm(=nE9byVDMEqmR&yRSALo zO*43tbe$Bl=?gUK#V{&-hYjmEz@1lc8tf@+p z91*#5CB5}l=vtW91r;bScxgX*BQzFL+w^iP$$R>(*wZCjaW#>4y*CK~G^|+)H^t z?X*Jrzitj69~nl7Fn$@^xhaCTYIq6PzHmWg2&Itz1afzO!4r6@@Tt0EC%I>jybgZv zL^G}}?OsRaRt+9|%V-N3O@XQkdC@0e&{wAbi{W(1kU8bpj?DIFfc`LTH{E^B&v$Vr z8^co!Jq<7=|BPWBD+hNzvgxw7WFlnv$6?Y;)$m<@sg?F3m?mq{+6Qx~DCW+|Ki?pa zC&ofbyX1m*++)TQJ*wlp#bB-|XOh zNLUbEUG*oN@pL{E?!e&@CVpv##56SQ*}3@ae`%hsnO&xCv|Ie`%C;GGIJ*>Hmntih<^=V8n46pJw4!H>jpr>K?gEQ^$lto5c=wVjli5l5 zu(TxAeBbs;C=}`)F<@B>4fkn)tF^rj{_V8h>jmgWeCV;aU4TOqKU&ft4K?tQcf_%7 zCx=~;&pFoWdV0OUyHj#fwk~h)Pc;@m!3c--sHhoImgG8&6}X=KToAr122&vJs5LV_ z`c;rmJn}p%JBy}CM#Zj%6x#XV>~ ziVhIViWH*(L((azl7DqB(yTpssB^$|sjX-^rIj0!Xos`%eZwe9L;X#5$yH@*fXGmp zDdV_xP*KN9n&H{805G1lEaH=o5zo1nKQa5|M;n2WRY5$N+Cf2}oo@Bx>y~5U*fTR? zgz=hsCl7~49j!mZhWsrWlG9=E_1p5h8tR?aQH%C_3!8y1qK<9e_~Gm{JPyR&u5k(6 zYGhzc-3PR)VFBGn!&0%sC+$=ZIQzR|G%jq81*!dUt6bOjx6duaI5FZ|tlsKcjKki> zhD(B%g+V+9*dnb<{s|(Y3eTI!wH_t}WkJ9ZyD#o*(BvrZFb56f`j)ME;tZ35VJCKe6yau z3G|puV~CSzgEhk_(A*Rzbm8`YAL}VCBClh1F3Ar^b<{DC!@8!7&n}DW44~(+} zHpc?3bfR0_ro!jkntDWU_6qvf+kOUS_0%P_zEQg9hXXLIYWQ2kG`1G-2ntw!XirIn zxU#YQMcixPg?aJyd${Za)15EDJ~ah+NKbWkH|AOOEC=S1C}kfX&My1W`kq&9@o3!n zuM(;HKk5k{q7O0|NkET%Q1O^AYG~X*4Qb|~ilwL&uwU%MvGHD$TA9iTRrp%HXQ~?*02I($Q@+GoB|hC)wlyV}UI z2G!bpwO;A0(4?E3bup$oLVW$vjI(JxDTCfIlvf{;NujCalF*A~_~&)&juS#KbMd-c zb|PpjDC($iBv@GL(z9^KsJ|_9lRLq*-5>YLz}!+ATkjpKmtSlcL%I8G-Xe&dPPnXT|8UpP zqivjL;EFOXueAy*(jja_9nfiVWbXam5SKq^)USKnn56xXRQMCD)meuCX*FW%2JyWU z67Ta$Gw-plHa$9HpZDE%@5sbLmdH25V;4GM5%(AI{AKcrW#jH*Be^PbGur`y8+NC= zhwnRD3t7=9a4O?4X~p~U&nqGI0sss^h$jJaAJ~6&@p~nOnkU4!0cROI3z2~i{v0~_ z*3~}kb5}c}&5~&#yF7i?1a_k`+o&=?TRpTiWj%ASyLG zSy#0NqvlQO$q>w~AJ|)*kGtDG2fdL3Xz7ta zOMoOLENWiz?TaTvKTf=b60V4$@YSJj!qe}}UMnK|KE1NM4ct#6xx%l7DPGNsO))XF z7()q*pKM;s)X1dfKS%IPM!s}36)OOjQCW?R7&6_n?O&AG@AiE!NM_IosUVA%&6@f1 zT}s9zEZ=+B*jyM+vqZ~}kh*Z>`@`U|{+D*fU^3ImJbcu=o$Z7uxxZqDgXg03&2Hcp zFV}R!8G<9Q$%OhB9=&}HEqnWTa>+B8$YjkISG6nhCYF0za)tbZqG6ELWws9iR|RBB zePthmRCwb5C8(-0IQF`W;~@r)B;DjI7)0fEqEU9{O3#a?4t1nm5Gnwt^d0W)gYQGL zcg*7Rq=7r%iEsi!r1a?3u0kmNZIrNj>6Rt@%rXEapwx?(Xi?4rVwnNF6|{ktPI8c# zdeRMusY^iXfv+th)nM~@GxfdW_`DrcPV}X=>i{6C z9>DO!?TxK1Bb?E_$(FSE4$u~@U-xTN4~WSptAXRm^j&B?*x<~t@m}={ny+-jtuNQk zmW)5l7SG%AgKDPr_y#XTgAPSJ7%iZrxR@(6gB!S|mgeOku-m3kZO}k_rynOd2&M7v z4!u-vHpl^7Wp0~*@z^i-d8Bc1vGUIA_ltmJuycUQ5f9J2>-c-yIR40!6+2w$(_&cR z^rQOy`I%1xf}!`k3iJ4oFMl94#aSikVEjsIN{JROnHIW~d+v;b9|;lNf#5M1rnUFw zYi+dG+(z3QmOEJQ#(RM@ibw})sD?Y(i}qc)?VG#~y$(TWw*Fo)`zi9&1N7)N-0w%8 zFJu*$dK5TVdL|%c(xu?^EqZYv(Bv|uyQ3REvs_KSd6+6&c#%fgd3=_fR~|D8+lUQ> z*3#z))Fb*zk{sal6BJ}aH2cp8k;UYLjO{Bgj_BlIU%znq(-dF^$)wP;zquX-f&F4{ z={@eQX;ZQScs3vqDJf|M{7LQkV%ER-0b%*=n1M|w8cKIu5MhKXApsfiz3ZsHcktNw zJf45?^NY-X9CA-nf3W1pY{*>I-Wt@+p5=YdZ#%>%lL%ohQEx>1G$@_gLvxh@AL*rq z8IFjYl_drjkb$q+AA3GPDk{}x#7SipRJsC3lG`!7ZFfKs<7Y^3bowdI{&ttOCahwlr^b8^fp zWE-CwsUBm{EhY<_8o#Aa(ch!2Kin3sBz($X?}kwJI4H^3|Dsgx5T-~uX32kKrSdGg zFBc35aZTYMq1D>Ve}lRK#lj*Qq-~I;GD7TvOp0!t0DRqb)MfoGujyZ5c`~Rvq(tt^ za2Qru^tFZz_Mbxx<1tl_8w=iWlc}&Pm${{=)_YwPtBh$hE!&G=^P|ihWAGyIS&+rV zp^xyPtl2h_Ru3b9wk97Ong@rUbSfX379~@JgFm@}S6{g&4SOL7rKlJGV!LZ^bMdLy zc#-Dt@_|`*kzN?Pr&f!ms$DbsffreRkp8bJjju4HFvd5SL28Q+8oQD+>q!qhrjzPn zT7#8YbUwQap33A#vWQ%=Lw=Bf z%j6o~C)o&+7CPpZ;P=uMkrQrxtAag1s6_T1Oinyj?J=W^jM?FWK_l5~KBRno_}T1F z)t6fHNQ=IB#>_p6r&MvRw~&{nqffe@C16maZ~|iJj#EG*ZO1nSrGkK9yM3w!i6-8Q zqIJRMWHOM~bCAEI>OWlZg`giK(EFqFNUh=2!`4NdkEFn}+QmQp2G+YyApgDlahq?C z43Jp{l?WnruO}9nQNo|~_N0@BGXtubnF)|%M}a7xNwgm4*%0L3MgiUKh>)KD3M26W z=g6%`YNdP>ye7Ruer5UJ$C%yGbi;4^a)aA4`@x7PV7b!WuZ5S=kE9PFfH)`@)U4!$ z!J*p63ma0s-$k>P_dd>_RaL_?+BX2;#&s8xeP`}oa5Ut;>MCo@OrzG*2G`VGPb$9p zW5*p(&k7TBGjmMo_nQ1OzWh=O08X+*TD(Au8UYFuvjHv2k3<31Z~1x>*{2WlMC=0_ z)iYxfP-%&2FB3yvE35!$O?4Hg&73w~o;f@k>K@qCVM04{42fMXc`fa?&-J&m^O!D5 z)Loin+a@-J5s#$YWr5g)u4hDfbqGhuJ3udQRWFbg*k-ge{U-Y)jfMI^52sC4#mI`M zb6faGuQ8BW+UTdRdSTt&cnjU?@Bs2?MhWq!)^sdR$}m7zcNgYe*)8O~HuHnsJ!PH; z9NB8Ms-OT?fAce>K2=Ufy2q&g@=oWQ(C0%bNPm5$%J22+h8-Mg_Lbfwh{-!PkN-0q znu#enVfi<^4^u^XKXi(~#AEiSC*JM3=@u(m2`pDbXRMcoPP*;yykfxR zUnX!aT1*%{638o8O?FKQa$;z$ITv;|>d;wDkp(FOYYzUZQsLgSL8+?$-f-6G(=jVM zJDBGPR^>?uux?c=7usd<>+S}zuEy~(bFni)e60rC@IZ=F7G07m6X-`#X+a4RbKdTk3TEzyi~S8& zwdeShBtyS$S+Ylh$dTmQ3~_h%wh{oV$DmbeoI?0X0PVM-G)q93qL7wo@gOmx6p|IU>n4$AR)Cj08h% zy$R%B3#e&J_zvOJjcM>m)qW^`ati3lB~wSezf&}(reF~cNNWRvn?a-ZVb3e8E*8zz z1rUJZ!fH4dt$ai+4pREHdTA|;WtMpq&JP=(>nZse?8nxBW|;t(J6T~HWwttCW_*W| z7%EXm$p!Y?z79V_3Gbpg>lI*8tD;s-Q;p^~kH95)2B}$6nxSojl^tC6I!cR8QeK8} z7P>^rwxYRS$HK=CbN(cO7kQmTPD+cHV0l`#GJZ??j}5{%U{O`!r_MjQP0EhJ%I{SH zzG9XtIMSikjan;TBs{|a;%)0UT^)~V8|_<7>H44}{A~zMLA-%eO9{}cDNt|y=&!~! zG+sWW^DZ%_5ylDaTaK@&%pD|EL_R&Q1*DMysaE4iN-6Vv4$0XN9Y+9*@~3_?fm`Fx z{8z!!4shQd3$VSRbv8@_%3DV~V~K5x$--t>qXKlaiE{C3R%9NNCO@m%h0;DndgKil=&nI`SYA*4Sryqfz z`sUk;0~<->z-Aso@Zq<0Qiu(7UJ!fMZqaJZ&UxgT!pH}`ReI1GioKUN1PfFV;_xH#UAuLLbwT?R!H@82!VPnI*vQtThSwB z&6i{5QSJWFV11Vj+P79^EGW-f{Gg&*EAsyvJc1ptdYoyY4j`|I!55l{*IYzOq5)B4 zfntS9I@tVsha4ETbpcxInORye{idZ&8fGf_li8gjYM3_xKq#qu&4+`~gPH4_cC72h zxuC#q@0I6rw~9@}UZN*L zy(oILsE?WBJ!_24zik{cY|toS70$`vTi*u!gDZLVT)i1Lsw*HkgFK<|+P=QN=T}$X z=V^vAe??sG|2f_Hn)l#p0o^?7{Zr|3L@D=yuMy~dZr%&fp}sxzNu|c(mXzh@F9AS3 zOvQ=-R7XWU(&GqlWea%-J*ymS;_nT~I9f zzk~G-9Kf9IMg5GP0UjbHIXEA?2YR2qxs}M6uuhE+t(gC1YdkNwGQ)`td2R8U1XvqN z3a)VjFP1PWj3rR61V)$y4~#6$Sld7L8*jcE{Sd11;VrQ`ZY1Z-+-beYwn$Ns#35(y z+37J6zkvp01TeCTJzNjVb@pp}{S349yYSl>tlK;=g;BK~-_uyplc%9N(UY-=s2pEA z@V(XBiSZS4mI-Z`vh-l)Z6zA<0d#tDD}!)xWUszniN6FH)9lNCM%!~Mwv}&6t6A@C ze<=&-qW~HZpbIGwdf%U1<(p~INDW>8cP&AGMuGdvk6z*bNBl`4 z{SP+rktFr61A;vkb|i73HMk)^fDL+o6z1|q#c$BP zjhuPO!V_5KIrj9(ob+Dnx7us6&;g2{ox>iW$T|(vsi@yGe~mKzDZtYYL}(cx1-tg(`?Xy4*|dM-`%RSBV7b&{N5&XmiehD40eO@bH7w`2Lz2 z5qGcYP%&FkfgD`W16jTFmKzig2Pfn-U%hqV)V~MF7Jw|4P4jNS+gt?=mGk5!jt!&? zliS;@?*xSUI~hb;JSZBoRRd&?>|$RUZw`l;zhHg!c{0||u;!#T@4V)MMnrsYj0Ont z^UT3;`9srzd)3L4QA!jxpGfH0W%qrJDBGG`vj$UOw~h_-k6q5eYeb64&KaQ3hOy%N zKj>D>soDmDz(1qHgM_6TcWjJzPQAOe|JQTco^UyURl0a#DvOPYG+P#uH!Cr`P|;po zU?&WyVHO4{d9Ug@vfnwewoh3%loB8xb=D_xTstgq|J+*0AQ&9PgH}#egi8lB3N0-y z`SJUDv%tFV^9S15%LJV84tj0aZVa&mT{OfR?K#$rwqHtnngV-X)Ghd)1`F z7OIm=>Q|6Unb(3mHHNXv5&kZbxmAV6jm>bX_77>~&pFGL2FFrA!-6t6$r8&(6qL;- zxx-UDMBJR_3x@%zyvl!*FpCt`4;@Up(rpTiKoC)A-R0#Hu;Anc5M^f^tn`X}>kLWCeai^QD)@w9GTLGiDEx_&!+qMIl#NK>Y! zr1=g`U-e6!3X41B!>xui!G=M>JtD#;IE3?62* zp9iw>lk-__syp86vu(8y=#&6PYjLX2`uF((2KBZBgM7zUwF?lh?u73x7u|uO>aeu^bc?PGu~AaX9zI4-F#DCy&O_6+8tx_UwQlMXPHHBi>^H`C*Lj;&}>uMIbV zyn}4FoV_+*?oE(24|cU{Yn%OJDjvFAcBK{-e{p1jEN zvjy41Bi%iXHWX3W4<*QB8Hwxh!VZx=H*4X{@x!gx6)R(<4fc9#W$PaFTGM{qCJiZh z3g8?E0cQ(_R(wWVMHKjH@5x%7&NF>ywhcp9XBIyCUl`cUNdgDC1Ux(*)tT4H?uf|u$s zo+1XzxS5LO;Atw@%UG)OT1Ik0q+5F4aV-I2&eDo@8xIk-uoconUM==)=zfw-v!s^?+w^AP zOL74ww{MM_f-<0XCE~J)Bez3|YV=gSiMLav{YsWnIu|(yWMa&X&OmSv!I3WEH?~mC z4vl*3S>79)RguUQf)>iYu3&Z!$arYP1wtp}_PRjbV4!N=-))J&cgt9)>I21HYF|iv6VGuwY{SEuuPhK zpn?DuQ`#B=gt=9Fs|z7CodL870m@H9J@+^vSV0=8dj5Ceqi~iM0rL5SBJ#0?ss|AX z2mH(`Zo;6+I{UVxd95iXS++#kbGM>%j7;AJoJFdZoEvEib5ZZHrsddc) zgIvQgwN+<+rHMt3%lNeTgmE#P;Y`?Z>{EpYH3-?CjwuMFs=uuJ@5n^#U|*(h_Ah1w z>h~oQEc)*J?&wA>LzS?168~piB_Y({|611wSVsg__*B-XTB$l;`mmnBz@KM<;$6)h z-V%EHq8y3sz68NULoE~Q#xZB1%*Ac)O!=`5?LHVw{(JIoA+y;mYF-3x-W7U!gfF9_ zCO}^0j_Eq8PhSgY+V=Z^BO?rG_jdI_?C~uPk z{Pe(xJPa!8E;Ba2zP^B&2WI#T{9k#D1WsBD6~-5-uUajm|q5u7Sojp&kYg%(_QVI!l5vM1H9hhZE?vh*A02 z)qH=@;CPs4;N4qq@cK_>w_n-*q|f8pI3I(u4N_(KbUce`GlqI7qTlh)nWoC^C^9{C z-#=-YsHDfdQL(7oAC&3~kb8uKvFCz^Tj2h+|F3G0IkcTQ3$2~Kgc{Cz8yH+AXm6f=-A$BVb zlbD!38oTF?5A|uRPi-ZDenQ6GR(8CcA+q|-4)wSqz*1;AzAymCOvt&(XmeF7ow`7C z6c-)c(j`NBUhPNC1TZWH#^~>05)i_{Y1*G%9tv}aET1pf;%c8t_T(x&(F?m*{W}Nr zgHZvY6@Xd>wtu|0CoFiL|AK~v*NZSdNx-XXCtd24x4eahnt0TH3U{h}6{9vZP-D4q zqlFdw3+qu!!0-;?&UON|>!bdeHHZ=kf_<6Wje@=v^}t%rBcBu_j<^~~@8d&J^>(&_ z1jwYc{}pn3ppX+IZkD!~*4AdUO$XB}u@w63kxo2AJ%~+`^~lrhL!EVD< zz?8CM;h~EVMge`v={7R&1G~;m{|(*Ov%mMYmV1=_HX43=?MQA>(Xw*&8IP)*Z7SE$ zNF<8HR8vXZ4Vn4uY|WrloXr_@%-B+QhfmIY+Tc*}IW$E3QP7hz&>6k6a&^ROok57I zXAAOQVq$!zoj@w|&OiG}&F zs%zGTT?!GRI@RbGXZ!MDhcAoq7tL}-1;XHS^e%k{Cxn~{C}l_&f)6e_bjXGjF-1Li5AB_7U&C^wO`fRX7)P` zC1@VT5YYRwh-b#edr1;Cl4u`D`VDDOMz>hc7}ERoJ{Ok0dv7RFA0%$%(+%#0G|nGL`^;Ueg+XP4osfNsXj4~`JS!m`Cwyk#z_kt+eqUxDJ&~0+TgmM+> z#>6>OCd$!V>>rg?>eR^!^*d^DVbg7cj`&hsU#lOKiX7G-&Y9AR_x)jOWI@vZk_Qh>4!^%pQxQH zDIu;YC1CjZFDhhRK?&kqx)9l%4@@zE4X0e#N+g9>{l!j4PkSGW-y!v!5Gk}>Ot9f0 z*78addi-0M6#6=w6k4VFtF!3ywQ7|tlPv1ARauux{bv~-tODMkHq^` z=1j8WqapbnXlIzjbL$b61bxb_XKv+DLGn0M@@`#|1eNHG*#m)~d$-t5+vK93F~;%z zOfWd$@nED6&WXUMK^Au6hzehnu)h>7*zm7>iMD%IT$Lr-e2wDP-q0vEN>tAvB9vlXD_W*-4 z1a}GU?(Xhx!69hmOz!7?*Lr?@>sx2Nzt8-r8hUkAUv+Kirf1jQfB1}PJp^0(M;jG> z1jkUY6qY^Ytc&~U>9RXO?V&=dE*b$qPkAtKqgny2ENF|Ls;(9^e*&1Z0>Q6l$q5DF z;>o_(LuDqy`dNf;!Ec%bt7yxpHIrcd7*SQ)Yuu8)z*E7shs4<5m;Q~~R=f5n)Jd{= z!4#f`-Udm!&qyYZCflTgOV$`=1=f+OuPJiYZLcE3+0v$y`4t%3IP#VANmX%aZoBxg z=d@+Srn{lP5AzU%5ek@~%+hIAB#d|QkL$YM^R`2!h-dAkYX_O&VtGPkU(kFJs)fIf z$F7EG*Ju!UJP4d@>B2I+m5eW_`i3JHFIX@Y53aj35Qc)fCOK)M01j(#?p&%WT2Jwl zB^UQM?Z*6tIu>KBRDbC-ykeagOAoA&u6HRVTaw^E4CB8k znS&~L(Tw}uo%n4&swe*huq5C|gEL3U z5^QPBI}feO(PZsAMZfrdh5(>NeFgZSJpc9E3z$x`xM93M zPLG@3x(XB6d$;k7{Oj=$b`~JyAL2)medfmwd&+d6PTO&Zm*oAbLz$7!JQI{T;d-Q7 z*w8s5;X7b#uRu8;mo>OZSunrlR~%L<^SFO$>IzTHilCw7`6!vgluSsg!3gsoHW1r4 z_3@rUjECH^J)#ISLvBA*M_yEz?2qaQNT#8hD#JWninI*CH*s?Ycy+?I7l!)Ydb#`~ z(D%SYkfFo*;+TJR(@p#+0}YmgyVxd0`WgM%@<)HV_ZUw7pfQ#BMeAv zn<@Zta5al0OeOf2-Ucjz<{OjwgwQ>ASS}?#sy?5I&(`OnpOk6l(UTYkdgbmX=MYRX z*egs!$NZJEomqFW_PE>JVT>a2oN18sLeo$pEv{l|gNdU-3hT-6YCP~>7U#ooV&z2U zD#QN1C5oi(;qw}*e-N^VUgtHx6@4E4S3PoiWPhO8ob68AKc3zN1OpH`D9a} zE@GmqfCd73Ce4TOWc(O30vz{@9`-0oJvP(3IcnugF~De_fQ*Do#DY)XIHj+f8r6v+ z9w%Gc(7!yOhz#E6#+gmqgJdQYoB~@|)rkM7y7-DnjuC0FAc`&>QKCYm zOe7;U&Zk6A0c_W|i4^Jj5s5+Y8|Vr|n|v#QL^T+sHLwl+B>8jxA>y$ zGytG0G6jP|_)GK1d1Tt&^XXv{eB2Gr-0C!rS-Q_a0(5Fx&VSkA&4iG2>3WFX@EgOG zVD;Jrmn?n;aeUn}WGuq=rz*#U%8k@bXaAN;DXZ=Szrb(CI z_gi(e?za!w{&$xb3HSzqBwERuj$j`OlkXX$l;f25q+Jgz37 z`}EP_83(9D%16b?jw5X6gJ`75HfZ?N;Xd?kmV+v~U`&4+97aXXoV0LR@yTN>TaUw_3PK!K^KO;pcney3eh$W=>ENyVL#`5RD?gF0$ zva{geE*^$T%SkNv7t!Vv4Fc?58@A-tdwRjRtHsF#$V+k-jo=R@{hk0CK|cYZ_a7=c zPq$FW03meb%b$&!^Q@^<;g5=xLP<`nw7p8OVna6*;;fyu)vi!;k{@e`q*=amuVd48 z7{-~Dfs^V6RSJc~Xs4`k{J(-x6k&Iy@`I81P^>lRR};pxIDaic>c&_nnlF+`S8K^} z7)xu=9l7KOcNcgpu>ZkHV>EI6F*K%N=FoLL6bbM>5hCW|34~_Q!|Fx0-4gG5`8nu) zp_;=SS4u}4FXK`M55^p3UJScuRaQ_}%OpMNyCuQ26up&mR|(uQ@F7vr&)-g?csCxs z@v?@3f$o8R66#kCNUOplq4E9Z@Jc@zW4Hg)b-^(gg}#Li_Y$x@UEL)zInq`iP2Xsv zS$@}uJfFz}@h*8sjZq>9kqV80CyRA*#%uF+$inI!42;}a;3&d= z5GGwA2BgS*>W4AWxbWTk?$$-3SkxV^k&|l>5t7R5ZkQUQ@!*n;)2#2|GCYx9L$f>t z%}qxf$@`$YG~?p*Jd?XYG?%giko<$Og&cjDBQC%IWU%8?tq8s*K}FjIzJ%kA7$ z88+byeP=zKEIY7^7XgfP;>roZW{;Ojo3_WL5v-DO;cgv`+`)qiR@nv)gIc3C49_aw zF;ci1g@p=wP2Sf*! zLi_azlrkiJdMs#3qogNiBR~;Hk`|DL;f^=QcdAGeN{zCOJ2{|Ms;4@}L>U3>PNx4C zQElLVAtGiM`V}MaeW;zx)sXRj$Z{8)ZS)@N5x+WeK}R0b4>~$~>t4ubK|YtBsU_RX zC+BvT^&t$wL8AHtg7KIG=ho&@g zld}G4I!c@i$Yf!PB>K;0Mr`Vk~c7YZ_anRzhjXEz&tM8r7UGuA%TFw;xUyunq(&O`cmkqGB%SH0FPp zKvx&)FS8oMfrjJtGt0E-_4FbU%IA$AHz8v~ELR{ikl(>;y!*y&NC4_!D7A7c8j5du zC*G+rEaVD|GUsvmDB8-EV;u?q5baC41* z3gtkmzyvXnYACAuspD!`f@(>>{u~FLqi4h>sLKUZ%$GKt=tOx-Z%FVUj9HImLlau2 z)kO+I_MA|#*^gW~`vx^mZd>i8;7W)$ME%2$?&TMYy^f0i2UqMFaw-Lbi9Z)!=8kSA zGzz%}2^Tl^8m%>N5@b2$s!@YsMybg-t(DEA)1Q7?@$@mohpo4r&KSdl?D-W2|vZwnw*eW`z(@Gn6R zyoVj{4Ee9?ZF)}|P_+-^&gz0^T!pB(t{K|D^xcrT0{?oBG7}}*Db?)VLX+tBZ7VVs z4P(W6f<#+|sim?uBpAhecJ%LalCB~O(MNfib?NFn*fQ)%(l#<6mRaPXNHK1tD|cnmupL-Uxj!sDCuyzH?u2b^m_r}xQ_$hfJ3APdp>ef59@@EZAJR1+yDnibqj3b;$M=v99;Udo2x9>}p9RM^2 z*B4=*a9-lj@c*vmWMJ&VEnzk8ivImVvtWx@C;wcl`bo=!s*oRK{iewS_+ChX|}{E@p$RjRiqo)$Ek~VuP;Py?v{(5JzJ7mvB+7Mdn>-K?1Q-74#)k+$kD4y?myR z*?Bm_m2$6qhMIilKFzBJi#x}Ku8w?sxDfXIZfkY@xDlKzqWLK!XYH0wd9_`S7wuX4%G5)FA9!gY z{InJc8sepCatuE2;t6z+J<%D7MZWEZ&Y@%^ITlm2G2)Pnf;ly#l@bsc#k-AB=zLbw zd;PPlLw%yc0(DuE&@m9jH!#>fRQ04&vB@ISubTu_N)ov+Z0nJmrAOPZfCuzHb~t<^ z8&o(A$yKVoKq_gc3}ba7jJvMJ1Ki;Q3V*Sq2x$z+0`~H!*p6E-C{T%!OWI510^MHd zk4`Ka<^@hO6ZjhkhSNi6AgRGL5SM&nX!WkCVucj*WOTH|k6#AM8k07VVoypx(*ceR z7>8WiQ>e3&(3o+D<40~BXtoz_zNPEo>u*Z`YaeK-u?Q*>u@GK>inJM2)Lw+4(6MoXd6_4?pnB208~7}bHdE~=F_a$v5+_!5}rgH_cf zCmI*>xEcY|q|?kAVIk=ia~MX;Pq#Q~=knH$F=kF!@_mSv zpLS6OjOYTOb+f|_c5rx*y8-XO>>F$mwl6X1ao)ua$dUR?eKyRImY%FEgB0!sKk8JY z#dh)#4<{R?LT%~UbjX-BBTAHG9EI_ zLi}TfH$93IIcaGBhy7ce8O`_n#0zPO)7RQMoiTN9o=q?1O^)tSH#bOe+RJF$ zH#v+Kb`p=x^YDe^q-7!T#}y#?tor~QCdg6QJwd>f#^X~uRS0<3E39dSB9z>wLy>*s zHzAAfYyf+iPrLd(&!wHIaK}>?0x@slzg@Ox#E!JmFxX}`g>7;X z#OB3jf^26+u$}1uK-mPv;=)vr=++!Pyk6sL`j$Fby>`czsc44zJ z_P?Q4UoISWXz1dUKm^Xt0LD|KAneaR7pe`Yw=^A2{BRzZz=E*$QC!{DboRdxEkKUf)RiSGKv+4(d2e%g~ypomxhNNGvtUB zau(M{D$(hYs=)+2PW`a~B~A|dgFi40xT6I<4Fv){00;sO9GUb{m`kMBMk||P2y)_= z93g$^kJ4T=B~JZB@)Or6`Gko(P2VWpsIZbqEn>7K+y7O>Kpwau-ClZ`R2F@(fOu`b zG4qizGVLmSkogDi?7ehHSwe3)4FzQ|D zhE2eS6d1VdRF~zBhA*AL*d#$<@e|Lo?ksuC6X7il@y;B_w%YTI6+8adlkw%tKlI7y zk7=9Ua&vI4ks~Y=*;&17xLnsfLn|$3iln6=+sJ3@l$9*2eeb;t4sa9I;tk1KcKG&7 zQP?%=HxBV;7E&=(0WI#I&}cR=G@4Cj*OJ6IGP=8kcmUxGl>^B@C-ixz`NVKxwj%;4 zgeiVED{S036TA05`|sn<$bwA5@c4*N6c7)fyWrHec@;btsa5>p^b}&a=^8Uo_F?o| z0a88mx~UyGVDr8S$SsOfl1bm6C`f&Nnyl=CH1obXv~M%btPj~xmI*m(dD({Jvp84C zd5zS$kw&LK^7H|z3j(@|-=FS3-3Qq*!2rO|8R?P(6dH56-wj#xw4GiZ=U_Vm1qoD5->>i-)CmyhUM?@RHpWIUkUy3)7ndfU2o& zL6=`QW3iJb6enbMK)r7YbZ-|6YS{$leD3~=-+t^NQV%#jbx{ph3wU!qE-nX%~EMfyglIrBJG z8Cr8-fz9)kO)sjs9VX$QKMysHCs9GDU)#x$Ix!(JKn;L^7s^p<3|I42WSE-f%0f6v z4_uI35g_LS!<&3NHHEsBWEVc1vp*)KhS%qx)i0zrI|rCiN+&48C2v&b0zzY6(3Z2n*?blVk%FbtPv-=IUYRR6l&eS!>TH3^uH?%L9DGAz!p7y&%QB6$dPIEpQQ6c*NI@)` z+~I-eGG1OxR$uj^o-5z*@q)2i!HWTPAk~<#!IN@H_Jtw`&%cuUAhX*bx0{R#%92cv z!6(`&s)ra}xQ-XKc@v)9Y8rPEp7jYXcB&H&l^un(!K+QzbK=tE0>a&T)>c(D%t;u& zAq*-_Xq5IJGi6F(sJhn4sjmN{zJpr^(%0 zI#*_xOj=E6`7hXSjeb6~`xjdF7bapZsTkYo@u{Bb%bhfH#%cDHnTi7$k%bZVhTg~y z@ES3qUMSIU#R;x1)Ltnj{&x6Kk0bnQ=tgoE6zrm%JT#&C;>D$Z*0kh+cc5upOL)e# zj~6x{f>MI#v_|n@%FaGC9>kt>^soN)Fk3)$%o1P$rVwcCvl4MhCOpK=fg_Ptk`hEi z6)ieC=e<%D3T6P0RJ?ztseHc+KSWg)kuBQQAeEwRVxam-rox^${3T%YQ=;n7;{-`| z=65=tYSQ40Go@lusi$&k<~5d%8F3|*2H(k^Evg94m$z=`<@F~Kk)(5+ZLdE(3teAH z7NDE_UEAaOPBp{kFC>l$LR+!OvX0nX94w|Uh!*yUcL1V(Au)1>Hv2{>Vud0g_eq)?yL-V=QBR2Pf755Er%xBpg@>&`KSQj5Y&Q| z@c_G7{NbF0_+Bv(!&O%igdb1EoB+P(|7wN=C1Hty3vx~Zx9g~`zuh609thp{;o0xb z>X_2asj)=JL5ec($Q?05$KfUyHRDPharQ%lN6aP8W;{?Eu*6BESx)zNIt4pKKMWfj zsDEy!Cb>6+Efi6cyGaZDwkrQG6$F3rAmRaL1?+K5*;#H0gqrK1caXCiRj3qi|En>B zBw*@~(t?nw)YUN&HB@eixjz+*ll<->dq94jD|)LK_iu0FtndFAQ)vZ zyR6JRD$m;7Z5$!#FUfvJ-}r&UC25qHW^Sj}TSY<+=f*074b$YR-ABd`NK{h(m)d-% zmx?~-mtuRG30c`Knq!@Z4Nak+lA6|`V+wvr71j!pELz~~NYUal?Igy1;Up@``K5*(uTxpM5f7>wXLapb3gcE zDz+Qv=!Pi;-A-QUVlw1x-B${(?(#y*TXml{?g1a_Ar)63AN21_n^_ud!hdpFeRvBt z7F!+KzgZ?5XMcBpos4x^*BXsekR5g$py8v4B2}23X1i-!JxHG1G6&ByE&e8%Whl`o|JB&33MkO(asUrfatoQ7N-0GP zSIWEK%WIlwJ)DUBI>kH;$m&N9i@eeL0c)wk#4cYNsg7-C@Z4n%GLDppwl*GC=T;ns-Y#?3II55|CMBk5;11ok=Bb#} z9w_rL@jdh{IoKAVDFYdH9(% zHn3XLb=#q_Ks)4iR29*n9TEz+-uAZ281Q^h{BL*c7j-bfK&z=1e3@VUC8=fJTSXqG zmrFGap>Q>aPP1WfV8Gh#Y`>h#yZUA3YpL}_vl_Jky13&qk^cZy1Lg%n8ROPl`7!EW zXjim*qR;hD9=WHo3a_iVY&yZS)_Smon#r1U5xyhqq~~_)2I!>g~Q;PM(f9 zq}Xj%3Kapf{I8TzRvFBxKrE-!j?Sq0?2>AQkD^_OwrVu7B$=g@UC;Trwgj>+<>a)Q z?KNSAU_L>DAoWf66@Xm^~S=LAUXafY9sUw^?nAVzUqwvPrYo zGRX0gBT?YdSYY}kM@6LF@LPb`2bvs;9}d9B9pn3;wI)H=km;hKT;Jn&&|ZGNd?B8i5et(P0{ohZ+a^4&CcbYc|e?HTe{_p2O@o}R1XP$#UYe@h5 zY0CTlA3gtn?DbKQXT3p_g26)9(?db1ed&x5lv=CYeIcevd7{{WL;Obs|C{DonWd-+ zvi3xpJCUX^vhipaB~A62 zqBj1yQ4@(UH}YjohpYH+*Wb1-F;Edci3kx2?E8KB(Z?P`?~XHhayTjDXZUTIHP0P& z@6@eU@8>m^W6Yo%2_iSlAA-oxrgiuB)sEN5N%waA@7qV?bjbb7%Y=X86_b#D`^~#& zseBNXVOn+Q?cd+up8}rf1|Wsf#Fx~sp7+a7SVl6!?+tk-L1NQHmWMr@rx-F{mH2*K z(@i;4G;$v(JG3c5cOZEwRVkGnu5M1v$FO=80!4o$*_?f%W>*Ld0H19)`E#qjT~qwJ znKXmNLB4*V_Pvc0+q#*yxa|I$zRJKVo9A_^t#G*L9P`(gQQjY%(xS{bf5_CPaNB(% zq&v5-a{LDTO(-$C(Npgv&}eE@*}lT9+BY&711*V(^0Ur`ejFM#hWuc`3h{h+cuS=a zjlHuS`qF$MGV_sj#Nn=x+T`R~d7rmMMP`-l99#8wo||g&W)J`90c7tKapuiUA>9U! znp|py$b$c+5vDgGx+CNMH0j5za4a(cv#dyqF~yq#7Fm>BDNL935^aHEos8=2gt{)E zaE7Ghv~`0^i57CAkZLdgkD5r?74+Y#r2%i(7l!2`H&gv!hs4LqzMXrc7p<__DG~sHs>mNtq9#Lln@ z_{KYv9;Wnl`y!@175z=j8_vQPu8`=V1??AUW2I(A_QHvx&>syttE3q&kH8mL*D-}> ztySu~fi|L)EVKLS-+b;rLJrC>zW>l@X4($X6zygEdyDO}SY{|*z zFFmsEY#KZAKaGDlOU zah8w}fMxMns1{#{I_na4Yis4V2Fh>M;()B~w}d@Q4k32J9CxSe3T;noY-CvMA*P$| z96vUvA%Win(Qg?tXiA>mw!9et-(F{UavRvTT@nkvt-{^U=tcJePbdKZTUuo*+BW@N z>0;x54yrUul}@>VVPmNEl}zFBa*uA4`&`E(@nBR}$=?kHDg83{U6H zsV%3xkg7t1j$QCWe~VMeZFhu`F;vNwG2Mk3bV<23OB){eGBoR;P|_X^FW=tVJ$mm5 zy$n8SygTX_1;Xvs;@#PXgn~^5`A}sqC7xL{(Bu10-{iS=t((c6@X0R1-P$U4^on6_ z4(xBt3lB|41f6>^MYCx z&uG}cU#zEtKZoJk&CaqFnC5NV@hZO;Zx3?B85QjPOV3W03^zbyW%=GSQ$rrHF|l)J zSWp%`-q`n9V3|wvQE1+Hkr6bY9PYjjgG0=Ct;$WzH~`LxVXO^k4m6R$=u%|Z$Kx~7 zOl@v#iaE+zECMjfy!*2MS!<~stYaCi_f?7VGGMUQ;OcfCCCyDfyVH2ZipOWZlirVb z*2$Y%Iu7^mGH`!pssBOfQlx{vO8TTpsWu*t3Al_d7>ar-rkz!L|JC_OjJIPrW3CZ5 z8I2FHlV#2gZN$QIHi)2Lng_rQ0n>pkkz~GLl_6$LnYq#hW}nEcQG>7HIO7v#WxfYb z(4U>Tr46j6!mwp#)5VD2|E65dsucE{k(vFJd*5+3pn7z%@g4utG?nB(OMDW@`;G1k zRv3!9SEcQUaf|{j$Q=vWLYQ(K8gyDdTjZ2d56=IZyx;cI8!A7rY$m5lbcWrg1MY`< z-rn8NJzV+Ixcud+r2E`h*wyUs>ld3=o8CG!0V5`5ARiv zOB}|A7vjqMcmae!NzA;rvo3-wXxV_lx_;^`cc1Pt0N(z+HIoEA!r#$;(9t=f4q{$5 zH<26>xr+teqC_ayML5Bq2_6H%LA;T4($-S6qM9xRjNXGps3 z7VnsIg%1B@gxt%Js3cTcurL8a1&2B-mZInHog6)pr+3X7ewu3eMj|hh-q52mqClxNwn;@wiHWWk-P8Ie! z%@eT^jIf-LMNQolq>fH5=)`uuK;f=U(rBu~&P~;)BA)m%Wm5bMRiyrQig^z3oBD?D zGwF$fr_JZ-`pSn6G_Ew_%vTrv1(LM;_YduPNRF)7HO~hd&vb}%?k4CQa*TA7Vf0RO z8ACRQ*b2kR*nPw5`$ZcFYYYqtWJPW$OEbutbi562S%b?SzuxqnXYX>Zkq^wsKYa@lKVVj%W@?@Kj~L;l+U|H1^T* zZgl?$oJHB)O@ea$8iB-B1;22bENJ}LffeK9je?j-qx-7f!z>V@edplJ0|Ou32Zfr1 z>d@pT+6CtbYT?mvkFh+Mg5UbuUP|H6YHiLVZtja=i*(YOB%19y4IK&nu}oqn6S)sW zU3`|z&DuLgVgUSJsEduh6t!>PfuXS`-A;~od_;(o1br8+Xc*?tmNhb7 zvre-rqU&g0N2_sPHx0tg3?cOTTt8qezm$jhHl=b-xyPqIu#NahoecxEbe>qt>TZ3kB)&Kd? zlJ&0$SD%Vqee3bh+^V%6SxD8~r#>&xhqGl3Dvc3WGw?ThJY0C*_)R$XccOfU2 zHX-ybppu^w4|7Enp9%-C_0r?TATF+=fOx2=99!ZXg`r6x{!-?VaqvE3rI<&*;&N5? zEIfSh&lbC*>qq~xPf74PFMItdfDHJY``myO!5c21HtcP_Le#ug+ z-b$CKBgfgN?_16YjuRjA+8bf8C-XqltFL0*#M2(qo{fn0*ZH&BqC?=K_2u-;M zx60iDxPp^?&9=lVPsP5zJV9WksQI%+WBzzM1EF8(Z8h&np_MK#=B_S+-=4U9Ux1df z3~UKiaeXJmMmVEd7gr*E*66$CG)`0v+-u+tnitg?gu0SFBB<|6g;7524rB`f1ES{f zc@#PZjLf`XZ5ssg?x&U$p6+!p1&*^wm@{psPy3xolJNQH;-igcQ1_S#pG!Rl{BWp4 zt1@1Eo@D89&U;CZ^D1!do9IcC)tM9q4`vibGq4&7$!63Mmrvp_8C^3uoa@j4sAkSl z|J?qXeM01-=3kQeloUF%0*nd5y9-47WQRR-8htV7u4hd|=ZQP=iY{0s6(*aU@ z6`{7tE%;aWd~Zjd3$fi@ncHpI--XQQmlA{_;!2mr<>Kx^6icNZr6;s%UO&P{;Zw88kc#U^bZywQw@Picy9-@Oh!Gj2;{Ia@iZ(cekTf7~<6D< z8MC=Sx}8W&wGuxfOC;Y5ORmEa>f*kJ!e;MI%No>RsKi@+MPj@D{Hy1iqOQHS?I`%| zvl?N%H0=ljWbkG+pEKr;GtBb7xbgJ*fXRum>$KAe*0T1^fma`Wb-7u3kK!8w1HFME zfyMpxPE!T~^6e#$RZecaRy?^9Qtih&x6>82F7?e9s-R>w8@%R&`8ZKLy-1;~mbjmH z&x1FzwLhgm3{G>c>eb;emm< zJaia=1K4C$GEIdTuV}6)7?J~vk?Cj0-XAb6a^FkpW_j=5xakJieQT`yaeoHl!$<}` z*3Iy7nvXGuXee1AQWnZEFjhDq{m>8LHKa4m%(sWu;eE$uqO5xnUbf6q+?si-mn?6S zj3GEs9_V!#Q|tDc`n#~V5Td*9eCusi;NVRX(}L{BNM7FQJojl83mkHsEd(+p-Xg0a zAc#6P9EQd=qh0ZoTpq1t7Da!N{Z?xZvU~aCUf)7M{984(C~;DqdUeX<0AR*n%fQw& zpt%2Ycl*<{AL{t^!%7N}Fm-oQBMV4)1*YKaRulV)gHoH_GN!}#uAkM3Dr#Q3$T6K; zjvm`DLGFcq61KpZ!6#G}XHiop11lmQQAvyLkT;Fn<$Gc7r82T4+Hj`FoFaeDUBH1I?O!(@YW00h<2n6*l0Kz|HJ?atRFh*cJUtgOoZ>3fe@!+2TDKMTPO zqM!$0_U8PgFS@)Y2FWF+Ty)EfzsecF`w*!7!a+_~#n#frM(6H`&f&#~R{Z?#q8|NA zY}*47$sRCw7}DmM({bd-{jR3Ex7k<-F;Qcg0{v5$nFHM?&6E8riMoVOPuH=b`9h<71w>e+z`=09&B+gJgVi-#3j%CT3R}c- zX2(b3w%fH(c*Uo$v4!(>>1m%1wGwSRZ_^Y^!JN6CLA$qmes%JYZN`4r&UKKl7-E}I z2}ZH%V6GuyLCBW%Z(?x6mpS?`BmCoYs!s&P#gj*JO!-zUy)xX&!Gd_mbeYsaB2w7x zbchLZ6MoZ?5K4yexTv}E!HqKBy#^Z9*XooE&!-~c^7E8&&WQO%2jF{zX28J-iV#PJ@mUZ^{h78Z||b@5_tz9%iZ+z z2~fk6388c1x<^HX=0%h#vzgL>FuKJD+~3qpwyL)DFvHsgdP3Zm?cCx2vvUge{8h-Vk* z)%O+aWOm?mH`A2+nXus5Ituhs`^{Hm;j*if3+8KhevZ8zj~0NI$%W^oDpM_>YoP6w zAQVi9wupqvh)GnAbp;l4^3RD)9ssDa2Roh34=BEa^t3Sv@vQreb4-3=I82bU4eJ?9 z#_Bu!AtMPS4!nW4nTTq2Pv$U{#uif(L`CcG2*b?xMDgQfpS>a*-`!QBi<|;$HLBR- ze~GWxvcXsTdV@_$a-iapM4O^$uFx3;)Dvu#u$c2J+-UEKKQ_byu+N-#z29^nYmy$G zs9M)6oU%6bu=Cgs6{+Q?U5&MWm%*-vg5WEwLsb?|-fOvj8Fe%EN$Q<&AXw#Q ze9+543@cJnc$ZH)e{YLiQsZEKs znfb6WMPKhp9}Lru7*hEf4S9F5v^fL<+twTBm0ubDC8O#uC(jb-yLeaN4^VNSVO9c+ zwMlUS+lSIWnJ8D`a;CF9*2YYh(jE6p z=d$|@G-4E6jYTGD2OF{Mzp)iz&-#jIrN(p++P{xBt6QB&o4ZLj=^!s(UG+#nh|Q6sT^B_S?rb(DmrT*U(T(QGmLgm$QHg(5ETvFmAL zW`UOb?>=l>xPI0lUPPuzc0KQ1ga|y4$C>?rpKt$Nag)QNHujl!Q-6YolJl zn=?pXY<|Bt`-IP0uWB1g2LN2VNXeLiNhpH)sPAMPj+*RD6g4CzQ|i!|wM|{H3fE3_ z7<=AKWUOS)CMd~TC~~q7&nVIx>MONE1PEsf5>R9(g5HebJ~xJjuvyX6Cld5KZgPVp z1zVwXzR!PoCWu)OlB~Blqxdyd`LP~O{7*;#c-1y5w%Mro5_>c)1r|vg-Y_+eddKV@ zMR^pw|4F10#3t(~_@&6n%O)!v|18 z1T*-xB?W&(L;biyHmVjj04g20TQTB_pT^Bo+v-7G$c!$kbQxl)n~z`WL;|LnKuv*e zI8OzTa5+7kBkog5CqT1)c4qOTfn0G04&R(kWCopx=KBN=XJvx{y=;>dS*Al&6cp_j zrBTy{?bj&HvfH5J$4bY{x;o3YOvqOO;{wkYEPLuV%mf&W1+~XaDW;=e4N5dgNOnOx zENJ#v)6IY!M@m>-Q|nNBz@dM?#-ZxU#FKdWS15oH+;h9&!>J9Xhh1xoPwIi5F(cVt z*jZ^!Os(uBSLz=!qw-*(qUlu+p@M9De6kvNEu{2)#tG;#InVC?OeT*vtV=Z$u%jc# zH8hySkRm+jR45vP45M7w))F-f(kvK@o55$lQy}6$4b@#~wsF#Jg?L~Tm>h<}-#ThKAh`{b;9^ATH z)-=IfrtoNel9zHU4~G;0nUFQZ$O1Fqvb`+Z)= z;Sd4MI~O10^oR3sGYxDa-+$wiv*3DVQx}jL0e%=B#GT@Th_)zi>$S-}=AHHU`IevtS^EhUo^wz&K zHk$N|mm24qfxQ-iRk3Xu4h`r&HM*(D-?pYTev+I-Eb6HcRO=9zBSkkl;Of0Wd1Ar| zfyruv;i!FA<7<(%hIVj7-ny>%X5G!9&U(sNuJBX`CgEuX-=pqHpJxs2t8iXFF4jR0 z)LH7Xla_u`V|{ja^u9zQ-_Ls$cqR!vr=~XfYTl5?1|~4pP`xV3OYYbDyu5fnz9!l+ z0!hy43JUTW#>v_A1NCWb&l6&tKN_f3txgODNQ6_lkq&%6^;6)+fGOl^S2|+C{+@IP zZogj$K3=hrJ~nW@4LPp-`}BvWz>Mf!DWN7A5c@%CyRbQZ^tUBVICi{z9K|wr{HU`&-nW3s?6}DhLiN_KX~FqFEKZ3+uEnc3 ztb{%+?s`tlXBFc;1uM7mT_}iSxg;TplJ1Pc2n)2P&DR;5k_|IM)>2gd@8ql0u~e9a zXa!+xVXrMM%^Onw@5H=5zgZ5%#b>r+w@i<%)r;zE430yBMlKEDV}X_epGTjMI5F%& z?#yY%$&7znbzL%fYgn~w*6342A@sZC=`_oCPW?bqvWBjKpj4@Wk`S)NQ!}I}!>^57 zw@L>)vESh$3MlBmqinaPq8I<;xcVx23!nU!UTkD>!*N6%8S3l?M@Ra9qj>{Zs8^V< ztSh$x({K*JjBl}-E!Vw&L8dh42fKC8yR=0hN_%2J(QT7#iBW>x_p{hAhWxLW8VVp2 ztJEfc%TSBDg+WcwpL=QTL{D{b)khR7Gs^nRbix$P%&JPqm+INR8wnya~TPjxF^_Q^1Vzg!xA140tMmh5T`v9w7aoj z!1PcTje`N}R|K$Y4pPj+j4`30k641?pE%JC!cPN*+HEK}DLy3qfRyuMz~0!5S-f0o zPAN((3 zB9z`*3l@-wzvy>6;nK_!o`|<22D}PnZpD4t`}zI5=tlhD-#7lhF3#!xgC$f^sA*ie z;3tCj8>lTM&NXipbx#f1$v4xKJcWKM%0IuI$<6i-8|L;U9Sq;5iHnCEc+&{a6nmRE zQu9Qs5827w9sDCfs{BTgep_-PYBl=cTWvp29##Az-u=SsgCo8%GN1t&8E!(ji88Lz z)ndNFP3!QW14jRU4B+0=`A1`hwVBh;)vw(+^wrqETHq+;AagL=fMS?e){S54U4qKeBAk~^jk9ROj zh;r*>*dPNU>+Ewix;A)u<$NF|+kvKTiUm>&{K`l;8zE;Yu(-Ey+SC(r9FUfy{gJB& z_3}&fR%NB{c97z=NH7Ixd9oH?UOh$$88QrV_)j7gy<)GKS`2F4l zpa5I{_)&{D8-rdprb?)hoF2ts)rRL%dN&Q^(M%djOiaFh!^`D85V*ZukiesLTQve- z42azz08C$CNyX)Re12=GDqd0`L4c0@K*(sM>f#F!b6Pn-j#h&~xOi?*tz}O(oGJ%35;(>fnr(CCc`ma?h z-3vJ1l)h+jf6`$OhRASXK;gGPt5dQIz%jtT+4yf#w@9C2c6&u(AHLC)95 zAGINm>Sa?bU7s4{1W>sGpEAT9nA%`#xKAnzGH>8=X@$vnix*_13a^fi+?V2uK01O-aH!SaxEhXAiF2=zaIsAALEa~UXM zru$hhHG2*ETGQ~Saq-@eQj&0V>ymxk*0gu?UTAnFS;75E9<$OjECX2grks_1e$S{( zen&o9yzKVfUp-w;1b5i(;>GQuA90w91%!{{X2>N#3PmRM&Ma-72Lo_6uIpxM`tVR> zVPQcc;^E=pdGW)>s{ZM(Ux#&aAI~cF)iUARAjq17tW|tbfGV1{4`ufd8O?>t36~(x|mwf&$FE5|}^vkE!?I@0ErYt61`Fnz)5dVCwAY`I-rg89eX7~HE zzd;NoM0GmfMV**`kQ3#%3*~D?GafOZ>h1wv3;w!Z4;vCk*9T=W3jRf1`M2Q#E~FQg`jDbOxW!; zHeI&tUSUmuOu8mdD~1At;A!u?>7G$KFHXObX*-g`rVz4qwzcy%(L1OD$;Y#SE37?b zqVb@$dGd>(aZv&W;4gmpvo8rfF-qwz*QcEU0RexV{H?kGPON61m%A}x05<_w-ciu6 zGL+^1uNEmz=Lbv4#rL1C@%3xdnhtm-`=|`RZ={7*MShknbO4D7OL9{2{EM_Sr6pqD z<>y)M93SY~tj{@zcP6Wcxz|2>X-FI`6gw!Sat$oNtQlB5DR`TtG{Yec=P8@so)HtI z>NSEbb8QOU)7Ev%8K|H~m#06h1QZKpXuNDFL|Oz*^ejmF0qcoL^1Rd&D(mtQk7zI| zI*6zBp*Za5G5kS*7e#3JH%?qWmmu7@_#Gds{;xaD;+6iv+61BCbKQs_%ZROjlZ^Jq&cywcgyK7_ohYS`E3r>*4WXFljSqY8Z`uw3Jter*v0H! ziz&2p;xsYkxm2Is0vOL_0HsUv`X$VP4*MB2zOq%am56B|Jx2DK%b&a3uH#voNBvsr zS)1O6JN`vU_MQHmW2v!yH)q`={r8ZcjY4$RI4^ux_tDf* zK*?BL%<%jGj#XAJAeWN#xg$9%Gp-$C5Eu{XnHD`4#4)2t0sZ>m8i3hMj! z|CTTF=l2|9hjcjm;1N7S5En`=uoN9r{^RZ|t{6nR0h^Uvpo@%7qm4uDY5Kg!^+Sx3 z0=u9!&G(zVD+EZ~GGI;nIc%w%`Fb#YQI6#3~B=&`IRgf+-mA#(1?= zG^s|~Nk`s@{E&H&3-z7)6PEqk?RSaQ`E>VnbC*EXq~L7#^=?sxL6Rvh(1Tdu-{s@U zn|JRnmmjObzaHPpcVcno2p*howj?ls&_FjY(^BT}VKshiKFK7uplStBTC@sOsf`Rw z5a_HN$HdK(-dCZ&N>MIBV;q*2y;j{Iy&a|KO^2>z`7%LzY`TLkLwa=Hl+&sTGoDO* z9x}A-^{U&P5uadifSy&@5Q{sW!!Tc~)XMJTwT=gCNezk%dNO9}uK=M>o8%HYu)4;x zPROSa9adMTpE;B6tYmH=F}d~rYRj6LXg$X$G*2p)sr!%Gi{)*)%$_Q~|Q8~)#gWTeXql+ox2$*L9 zCCOYz6=1izb}$M@%WsUtoEwH--aG)53Q?4}RVKleWG*cVFV7EY_=zrb;e?WLS8?6N zMJHg94|{zOu4hc#K}Fi;1U1Al5FI9Kptma}$FxBe7I!wKy3oHjucSI^<&!L5nH%ED zrYX9}R!Ao&3}yH1vpMcui~)NpDf0vHIS44#*T|UF!gar4=^{I`9n>(NFCj|fyBF(wF!gSYgN!5CM*LbjLZh3MX_ekVY{UE z2Hoke7j{iJ5$Xo-aFqP@d242n2ZW4>eVv60u8CLD%?s^EbW!@H<6#Qmoc;MRNd}6f zocwq6H|-}-V=Hg*iPvQSh7OvOuU2Q>&R5ID0%dG_CB_fwG>I2~M`P&-sFC#LV#TuD z#X8|o14uKYzn?1HsO#)Rhb54h2$}WHyv-Rr%r6uz+d8Xn0zMKapzw;jogPx*Sq<5!a>Q5EiOb z_t1EBa0EnF(5Oka!sjD%(U{VebhkZn1CZsO+(cz1R>Da7-h}@*=puNQmRZ#P9O@Voj@da+91#H zj!M=-YTQETgNITq@HpenP)DpW!p!RFr;~40(sH%mJIdgKcl?ZuZ(b%q5?uxW7%+nx zUsvr)O$=Cdn^H^=A(2ONy-vUvXkXP9jiC8jBpG{+;le215)3u~jfbuX)wgK{!%g~J zuBW$h3H=0btNr6JVM8Oaxjxjj_eKyy7Mrn+;Bj=2Jcw0?K>+rwID!w|2W3>5RMjs! zSLg|qo1T{^ayl8XPiLu}vVs$5*cDhpv(=kvixA~_k%Q89q8$_`Mk0#Y$^^0pUo~U$ z^^$i}-4h$Dw^8rvY=ed(+9{aSO7)c@o%1bnns_D8_P`jP6V`du$5#fcefZLd!;j2z z|0;5u9sA&&u9Q{RitN57;X1{)^)hKCpf~^#z{T6w6|s!9fb=G~4_9zkT=no@pP}@= z9n)gUD3>=?jfO&tLZ0+L>c0M%5J?Z`2V-~?qCqvMp>&8^yFQn$l^u!uZjwE4He#X1 z={+ZHK-E#T71;|A`Jdq1CMUmkzCL_1KYav51V$kQkZyz~aE0GRG`98Rbhu(c#dkhB zu&zR{wpttTc4K3AaMkaM;V4en@-SAf<63ILhOxp<@kj(uS8r2TsPbGaA^HTArrYk58PAM`o0HgU3nEXBI`;#7z*Wps1L6p`RdpLO=Vm zFu`&>6DQxiZeJ!%RK<^@Trp_Alb@Y?SUq9?iw9{VO90!4K_sYR6J0@zP|Oat#QQw{IipUjgho{`GW&^ZXj&bk+%rv`jjW|AqRIv zFXF{;%}ce;16x9=Vu5;tf8vNHvYjcL!$|yHczPdxQc(>C=uqo_-iQI3O!ze6ao{zH#bgATOY@1aaOn*KLS=igSp0%B?HhFDe1_>zaJ=v1B<4wdRS+XWZ?s}$2%QURsu znhbws5q-z2H*NAB75mRnvA+-0?d~E&uCl;I!cnw18hEw9tqxN2%zbt;6?vYkH%{riCO4;zC{o zA?0U*5$V6_A`E%M`zr%?iy=@y) zd!j`C>li*t=DxrJ`)}>-#{O{v@Dy6Y)`UuQ^+0#~2tc(m-Q4syww5<#aEv`PwWMcw zY8)<^CJhz7pI&6ytbN_&CZSHcWQ}Tdc3Q~M4r6hbm&lfdQd}w%T4sf_(^Voj^$tKH zuM&Rpv*D*$>0M4w(~5%!X8i8YxHD|#`!N6?Yxwj~l=5%>e&wGsvfa%gu;vms3Xo+K zbh0!wjpy`t07mSPu*Yh)-x<<-t8OfDy^^-ONhRAZwT1n*U7Anm-DQ{zLd|83*0RL!Jn)^RbQ9eo&%6v zpg^`U9)04qK{s@0WYMRUt&C3S1U@wLC%t%0$CdNO^^Vv7tgoi06&oZ-2=@5|3>Pb2 z(RjZ&jyGZ_NZdDB)kzV7DguybdL7kVFKpr34h0;ONK3fc6p=$fb#ss^jO!Khd4|U5h$> z9>V}4=D==K6=gs5;g(n9w{Z33K-gJ_79+WY z4hdAVUnza`3@)Qo=q`Ye?rx3P^?|Qr%rRDHo%Yzr9_YD zO5Rl#L22vFmCYl344(^t*_8fF^I(x%-H)`s2qR400N2G^N8Q!M&cur@a#?Je3`kt4 z3YMIg$4;PNRAmedc`NN)^({$yaIZCl9ZvCYclUZ%b}@aJg8EM_n7w!-M{R@6hfk)x ze*Y`<^r6fbxYfDIs~&UTkxIn{=H1+OIOHH9`G2?(+uc*L46-MRf`V?~U?UA5;C(iY z@R>#H5h)M<=QE5_x5hAp&y+cvr%U&;A0bGa=_0{CwY`;dgw!$8iHH$YrelZ>Gk6Ib z5v{`mugjAr%+GUshPXD7wpMj{Da_A|6R&1rgBlYmR{Ve+edFf?iXzzUR5jsJ$~6*z|iHn#f!mYJ7UVUh@B7f1Z&k(FV@FFTg{wuwn)3|(mM|_B)R;J z&p)etpE?Qw@Sm$%4?>CqYGGd$V`u&gL7Wwc`edFaih@`OACDS~z1g!}2~D)fiv= z+Nvf_Dw;tNPvZv za}on+MeL%JaeI2!-aWX-0wu>>R(Gtw6D1@R)PF?j%l4R$TikB9Jn~Y2rFdmMMd&0X zvHvTKGt$$B_Be*{g9q^ohPJU{APjg9<`gQMIcCrUf(*l%4`<2#!2UC3nploKyj5|X zi&%(x4kq66+a9%CxH*mT|=1FZU?dr>_em4TQU;oD?)HH2Qy1CT;O8TAg_k zz2?+=UjU891W81OIP1}k>V7=y7wPKSOv0583d#x4yOf(^WSZJ(iz}$ZhZ^K9>Wm1# zF!Ir{n%HQPx-2atBnD73q~!+xinC(5=B2t7MchUf$syI&rY}vaxkzrkiX`TDhq^ut z=+dPR>2#o>Y9g5hNo+hQs5J8T>f{5WxKwplX*K#{96ZR-XrBUk!*-YV_ev6q2L1c# zR~lIi;@|h;X*Ww_nvqvOWBy`Bf56wFmH13gnnFNM19qB^tKj@_qDh$OXX#)ZD@0Ve zTe0?bY`}b#oIpce6;Fvn$%;b}qd8h{y`eLI?8PT;%GuD8;8JOTETrgkQ`*<(yRX*; z^hfAOT#|h0t*nQkm~9aM=$^x(l6RAe$;Sd{JUVEDqT`#=>0k;y z{YK!AN424x25HV2m}V~(#qcF=u-Ln#9v7nEp4%C7q+hzCKP4D)1!$>aG9R7m{PN%y z4ISEd5S^&)9LVP=8!MR|InXK$r03t|PX*dHaP4v!W!;QvtZ@9&)qj-%YFW!5H_X}x ziws!zg`s_+^xTW;D6^+&pwcl-KObo4)Yb@iL!`SJJs`kOo+3<`@u1rHB9er7AMWoh z1%00!#oha^`V|h8t3Ol*#D3h*OwCLt*PLb#jUY)UZyt&8TW#uej_5U3gU4w4@uq56 zUu3^WIup7Kz6vq1I{PV<9slm=nrvPs7B*?CcXLwzm$)*|`X&bYr;k5EW+Zj*=~woH z>eO)V+KHm)#fGHhRn=aZ&Ker*r$Hh$&b&Dq$dK#fc_?Y=C}T>|^XGJvX&hUDqgU0c zG=(AQ@NXZ{ggQ{mx{I0s$tq$T*hb2G1^+n=&n2NoVOQ1$V)}MqZbk(*$P`zm=pq#b zJQ`>^$8OjZ*r1sGid$*eigpzruBj7 zkBIyfF4&h#2V%ig4NYU3viHz^wG@4lTe5ymQ42#RT+R*n->UJega>P7zShGAT z^9ah+9WQa;bGyIdRng~=-)u^C&kBZJld4eYwTpI zF9!IA-`r?gbHUmp5y60I^5mI)v#pM7>4J-ZPHy-tK^U01@vGjH*+1&toAqBSyv=YS zu3~{#?Y<8RIwNK$VNXYUF}Ph_T@Mdl7Z-9t;GoYXhgYyEh8fRo&%ssYGnpC2-aH=t z;?HMcB5?+F!`uZAFZf@K=PJDDx8e!8`Y;MtZ4fm>Nt#3A*}W0qJ|5>IBN~+`OjsJx zwb^SY(Jl5}E?cWqAk2^G$g5-v!vzuLpICjeouw ze0(iYd$C-4trs75$&QrC(uSO;o80YguS7Usli z{K-Rd<~RvO_{C0(su?HZ8*THaSOqnYt`uYrVi#U)o24t~i0(zT7<58QN)zxMse*Fu zikmRaEu|c*oi}!~*s=`RbCfv4exCafTI&kH?jjMxECZ)T(gQ%VTVQ?7O$-p>xE+%cZGXvn z49I?FZwRt2DnhKvp`%2fPxMi3fxwNlUbl(z6yINzt03Ema%W02Du7)EKgW;$MsnOz z8|@uZpbFO>y?er7w8&{~=KFR}QlYlI3D(O8%U6YL$nPha3tobpVVGjhw%BmhAWbWw zJwH8bTYq76*lkIxKyx2kaCZ74Q?DUDwm?5RtRuww-dd)2hqn^pW@D8xi$tNHm}KxN zvebcc;ffO+wXk06%B@?16myuTU+W+gKJX( zz<-bv)hvF)_#d8O0k;Zh6cn^mb0%&6zRY{Wm3TmMq0Mv0*c=J}1>k^@99>W)(-Ys``Op2=P+BDpUiVXyqC zP+US?4)q37PA2Hjx4nSmpSWy^pG>%c$2-l~53Cl^=qcraQUyhN%dzHv*c$qC^bP8G z01(&gN1m^lohZR;>4q)}Np7~?o3plwXwguLA}cN5@Nc z0e^PTU@_lT_CEuuMymW;vrG09192#8?=zRVc!i~OBmgfRbzr4^(wUi36Z^lt>s2CR zDC(xxiqoNgy`3-`80d?4ZYem3B~uY7BZHYu-c}dh!ghV}Rl% zXz{nRaKGzN6M|p6_&cUbYoLZ3Jsx04M+RQLc8v39YT)z@8cgSa(5c6t!x+&tRRuz3 z7fL#30l!GGfR4l`{u8AK_;n(`ItSw0HdmG9+0UZkJ?5Bsm336WCM zqYeupKZ?7sku7Z@oBIw-#J)=N^D+^70ZEAUaCFcZgWRW~y?wdr26qolnXY=bJ$UXC zJ5~Y-o-R3&sUwaj{WB*MjTb7Gql7*(iX3X4(Dgd-2;+9;eW{+U0Vh}3K(c{t1c1M= zTnJ#x#6kx67Dn@a!nqzEIvD{Ic{0%~nCK*X!&~+OK7tL^L=2;e6)UsBoFfrcpIA9{ z49+8*$z%x%L2T;o;L&z|&lp6%Dr6jz^%(IX6*RI-SvrhL2^~14kVNgy&pau>wuB~$ z`!DZ+vIW7Sj1m{{X3DZbo;?BU@(sjUGqB$-r>^Z^e~#0$`VZHK7YY*gK_ORQQzj=W zxo=Ou4KoC)W)^CiA`L;OP&N#ZM@kV`cKfuVOs&$p1!#}lc%JrDTkcm|96Q&+>dU7q z39XvQl=idlwl(q~YIgfbLy;3aK80kzR&o(p4|W%?7=z2^!tJm?im?dzS3ZL%G=Nt_ z#xvRR{1HJL@R-`QBv>kUyQ%Lq;o)6>lW4C=Zuj1(EJ&t|m@}-bApGz5y>>E_Hnj`{ z{tyq-?!l2k;oB0f#f%-t7h$>;uO+%5;n9Q|=w`Szm7iXkcV=gb&(RaPR4!@aB0j5h zkzMhSz1g$sqzp{=VwE>I5VD%K?p(1hrFh@C=ILiEp0EcZ-b(qN(`lf0TEt*d`o#_% z1d&Z0Z3dL@?rB(`EE@WvXb^LHX^mlI4+W|Fw-#@W$YTs+pTh?7MGM{!am!W+3^sKp zbiIQ)2TFa**?W``&Isz0ghE-wMY!8in%xEP=*H}Z+FSd5f%hHMBxCdkPZ91TOAEIY z=EMLF&k4=mFyDKhxhc3%q7n`$V;P?Qg-J{SD&<>IFTMaYFKfX}K^#par)qtY(%8a; zQtF*Ld&`UyNL%eLnq^jjd@I<|05tG*KcH-cXf7Oy39<Z|YQtL}01rVn}(8 zpXD0N6s0}~_Vieq|i$9$fuT<>%8#0$?KprlCJ8K7hD`P2 z7Q<;Ua&OOEkKlvs=%6z%hu6C|m{E`@r6uEWB!^U95Hz0$TEn%t zI>>uCvdCK7kOHk^m#*_fslVL?FTRgO99A84hPhsGfCj8Ehs!NAURPCpp6Dco#KbTy zHQ^O2?V5-f!%0ntv5sD6+iJ)#x0Cdn5=omHsC+jb!HY%g%av8|OWnKqqz zsfoW15^lXw>2s;1X%goWG3MxVS)hJ83i~vYLAiZUdIGvmy-IV^gpJeuSKU`*P8Kx` zIeMcie1OX0uVdk-Q9|ERuYsMMime)2*_+9q>VbZH#5Xye0?Ke{H7@ZkXZ&+H!eM13 zjshsg0t!u+V#cebR}uUraG|j@)OH!bg_<$^Ib8;rfBR-P-wcdH4SIwUF|a{D1h<4F z2Up7TGO+03h+12_jiZn2{8&r)`mXer4(JFBJVX|k3mcfcxpPeU%st{KM+ImZ64_}I z3TpZK**%KF?%rW5@9nFxJwN-?CpaM`CphHRAToqH^cf~Fm>B-hL{k=K>tF3i_%74b z7s2}yi0_rXF@d$@pM;S9@%`yVUy^|vq(e`UOercdNp+V?w$4+BAM}B}8JH%PV3_7G z=Fe3gStBBqFOk$*Eka5`sPt(S^$0qUcVvn3Zt+b~Hg@Q2C?@H`^N$?H+D!#j937Nq z89a8ipdnG50o$C#?6_v`hdKA>j-B8peyIvSx1cT_d&_h7z?!r%d~x;!*CkzNZ>1fx zi1&FfgMl5{|M=?68b32=EPzq*$c&jfMMChFyPFajr-<4ZcrCKb7OKWru@YJIUW;0# zI)0aPemUzE&5~i8FXzQK6WnHXg}UB>OnOFW}wz z`|p>I;c9p}6(^X0+bW1nhmq+8xDb!O0(3C@>Jwu>ss!B}!UFB8DS)*19XN;Jn#iFr z9bhHMqJ@mabvx9kcz#^be;y4m333+wl;vA^=WHT3xeElYO}9dHqtyG!Vw1xbD2(`| z$BVKne`*t@5)=n8Y?tvH{MmG`ikGkzXjK#EXncc&)9s|nJz45s$4^A4 z?4)1=ECl30{^>QpJ-txhHI}ltxOjcIn|EhgS?93H2RHB6&a%(99j>LKSPKg0XD&0P zM*m?+ao!hJIX>z?8`(nzO%pdVbpN*LF2xQNM+)&Q3I~Y}VX>+TEKt-{jes`+HP8z0 zXQ~&)BT78uZ1||)Urcvl9*th0O%w&n`sMk+Qf)9rf0BL(UVatU?}MRr$-+QB@u~(l z@45kG&O1FTTWyRGR*k*s!6R4KYqDnM`>d)MncAs96qDH%)m1!QW#;}J)@ z+y(&h;P;!W$)azl!OG=~T@E5(ZM6czr29g>0X*p^!_G1XNxJUHf>_n?25bJ3xr8Sb z3~2PR4lOxMJreShYZU1xl|Vs%zn^3Icpw6BVw@EU_)Nx(^p?6tH3jSo8PCO&A{hM6 z6vu3X;)HoP^#rEBLxzR@gG5igG*=>gYZIj`w@EA`o>S!yCb0}tJ!!SG)=P2HLE|Ik zcse?Y#o2^?N-0-!>6VWl(sSGf>@L42EIwha=fubf&^>w65?WAlM_eIpJKB1@WHNcednd1-`{-hX4PY) zfl3LXUZS|<%Cck`X2hq~rH})${bd+ck(2^pf?x8L7k54hJCfi23sV$?pxZr^potRl zXOC|i3!pBYi3!epc84~DwcYfqTbFFm5Rkh zXl^-u-7x;wjZ`m{eM8PkE%{3V*i3+SL`4B4YG{iKTngW5zK{rS4r*0K4OC^A!#yZS zYf@MMiq^E?B*AW{=beZSM;v*EYT*v=Hmo>vcL z$_6!+HF+3gEEwdpwy;rpFAWl?4J#RQzduK^I_I#cvLhdQydriEa`Qlt0vE@Th?fQO zUfbQlmv&EgPvJXW;i`#FWWcog`T!16buh%ZUG;w7R-#Wi~3D zO9WV9W@y5lQKAL?K4Wu2vj|6GZFo3n;`Z8 z8LDL}B?*RYWvU|&W{FGHe=#2n=eKnGn(C87-PbmZuWDL{$0?V1 zypaa}nNHC^wJ|7KxT6K%kkEs3C*KHGu;zp1P&g9F7+gJhrm*$bugwP{)ho9D>f zHul8Psrx9_{gajIf!@JF^yPazdpcR9uv9d_o(_`{!u8nhB!dP z*nhN-$E?k4J687{>LWnE&QXyOGKW4p?1IVq&ulPxM6Oi&%`_L7{L)}_*Fn5xKW6Jl zqI{+H+jQ|G+$6~l7_6QxQMaLMtE9-x0`p*A#aDk%U^sQWyrduDW-J(EC>2E!U1Yb| z(Y@61`60LLe;2|Arn3PDLl)b6Z141_y+x+*hFmHMaEz>7ziu|bV^ZJ|=A!nDAehdr zTIG`ScrF^?g@I{XlFnO-pEn}BXA@->OGH0wo)es{caP`n_1IdsW&rt96O4{f?< zpqyT7gLHI}R+muy1RoP}BVjXYjvc%B)>R2IgHC3U`eJnBvi&Qw3E-EB3vO6n!5uyL z8O4d;P)$HhE9aR;|LY(kabm$Qp#^wEx

    dk-)duz~D_SQhJOz!_4iA-bxFdQMD2V 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%0D8UB5C69Q~b=MLW-x{a!p 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


    61#osMoUDN;g&I5i2>jx!~^YnweY`Mk-ISn1mks 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 \ No newline at end of file diff --git a/src/stories/assets/docs.png b/src/stories/assets/docs.png deleted file mode 100644 index a749629df9ef3b4e20b86ab1a2482040df3ce8dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27875 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

    hxL-UTbgFOs%C>cNb?R-MvpJYh!+yR< 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 TCS{<%00000NkvXXu0mjfa^c^P diff --git a/src/stories/assets/figma-plugin.png b/src/stories/assets/figma-plugin.png deleted file mode 100644 index 8f79b08cdf28f568a9bfc9d2fee39bd85d4831e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44246 zcmZs>bx<77^8kt^xI2VHLLdnm+%C8UcX#{X7VIFn1%kV~y9YU(;O+qqhvRU#gW!+v z@BQ_v-qv>QPFHu&Om9zj&usrxRhGrYqQXK#Lc*1olTt@QLIoiqpDu(GlqJv^M=Kb+q` zoL=2t-921iUmrg_oLt^qU0pprJ?$JGA73C|xh^g)&d$!RZ~sA0FJb4`uWyHk(BtFd zqqFP1y}kAI^_`uaho5GL#}}8cqE1iuVduNh)BU5fgM$MI1afzO|CngHy$^d#G1=TZ zdMY)1%r}DHJ+Si#Tqy$z^%$_R^o~sQY zJBN>1#!uyjTU%S}+XokL#QM?E>dDFY#N^-2y{BTM#|)G7jLfHO2@_GFY)=U3L3);8gg1;ljU zL#xC5&W^c_-PZZV?9$(vnVA>au&&Xu;`+wLRmiWj%zw@HkiCPsxw-D1UJw5uBWv4< znZ?(uzO#F6Z+~ohzO12b_3&_HVitaS`1$kaoBrDN-aj-nG}H4dH_cg5F|m0S^@#2H zk;SFJ=$NA`#9i9=%M+-btNXv%DlL7Z)PjnCWs&)L`8WIXwY9ZR`Nj`jA&>PgH;cXf zBa=6O`_qd`ZpW+d`qJ+k!sO)SE_SvaD_qs|4F7dx+z+QcWt-gmseLGNcmD3#-rg=K zC>WZU2?Bxc^V}cp)XdDx?z6tHPv1vIMmEC!4iEi#De8ZTZNARce>uJ8YAkyBUi6}u zu%O|tH}Mp<^6;{}e^-#P-<5V;V)@cOJ9BzjVe>3B^fc4`(6D=d-PH=$VgDWe6s|Ux zxmHpYwTTRHxN>o^eo72DLscOs#z@C5zEHmORnCXLqNmwmx6A z$e8z2nfQCLdx_mwE64nN`Pr7ELI-uL)H8?QhAa#Hx1CU`I~*sl%IFJ;}evcCawGaJYGVQ;YIzwNsx#Tf&_G8o|JX3nKWY$pB zdh}vIFV-sn;z39(uiz^NL#}>>6XXi?dX!iA{~-Vhsw`gb{Chrg!!DzuPDzpSa9~RM z%x_$^G$O(xV#u^8Dl%uVKm_4jOfoE+6PDGaS<=COF}clK;Eu6yq!&NoPvgYKq#Bj9 z)6@HU*w3B5^kIZer_5!V&?$s#H2Yoh?}ApH`qD=z*^9|lUR^FmdkYa^6{9XMyZzI* zLvs-!8_WGrjU+CvZru0PtFG$}WNxLJ8=!@~dSI>BW59GkHwgd!!+}xz1b>Axo_r`( z;$CL2ZMhCN*z%O(%a^w9Wo|s+&+go$-(vApspy)lL}R=Zqk9bOpU;tY!_94colW12{+ zz>zU#w>I{od}s17&HDF;T`$kaf~Q`dLXXjpzM1uxa$h<{lxAFd73n%;G%a(Nh|9FT zDHmP^=D$_Qz5hQpkE4Bs0g+W+OU|EM+ggpR*E9NAl}u?-KAx)lYGHj;Ne=0&js+U3 zg2aG}8Px3Z{cXLwm!!wK4){dhajCK=#E0W6zIQhqEoW2ST4I}xuCYYkjFt7frt%+} z6rl|ynt8gQDl>+6fISXlPTmj5ecI0|X)i6^#~G{Bl0S+5>-y2E{$KrvVnU2_N4+v?I#U7K!9~9$hL=Su666P^yl5Q0+#|wLjk%+ThG6Q* zmSGCR{kgaHTXcP~=$xpg+)ob?SGTzOjiM(5uS3jxNqKe+>iK#J){{xif3hAv_DAc$ zIHNK64;+bgaslT^*k4t6(@_32n>}?&rT`1|Elw;)3PG72t4n!FItWNm0dlYDx`=D` z&6&$}N?H=HR+?J-=H|QwQxO!in_KsaRHfco5{)-W%ysCZjTCK>$jIu_Wd-_@?WtIK zHe3aaJ#t+2+s6K>Dso`(A+2-ewRsW=6jhvflawV9`pJTilOSE40fUCK;XC_V%$T*3 z&K**^Bw{ueCRVK9S1*TmCVLvw)&7=rgn=QnYqYy*t+;~IAN`wCQHf=EO`jWu`78^Y z)^zB7{0X9pNK$a~iEyhQ&of@GBTPUIdk34+a>S=KoesR(10D^Izs@KeY$T_Yj+l~JWn(jO!NZs8cOMWjOhOq9>b~AeiXY{ z+0ir^-8I}@^LU>05)uH*P_Ak0%Ku^CYOCxH`?Df#=vBHCzM=P@0rYEd?H;OIk?(H= z+arnnd^St?I8K5^w-+;@RA|M^BQZzI<(As0WooXN!G;vNL|Rx4^B56jaJG$SD6o{} z)f^lN*nH@|>XCeQhKO9uaSy}Sf(zNa%HD}g_Kf=z;~kkTt;?-R?g^Bw5+XD9Yg3GN z7An+XJd_IP$we}z$mObOq$bh_tb}5Hu-J^qTj)z+X(Q(Ot`*a8)g$|i4~Az__Vn>^ zgtY2{?t9nb2GDmeB*W62F2;X0X8~9d8&46i{X!YZ#;NZb^VQ{m#vnhL-^IqbZ^%RA z)Pn_TV|FwTYmRXWv)((&Oi>NfwKobI-EF>qX>+FaKB9by8R+Y<{{g4y-5rV^;23sI z5+A=2-k(7h%kUBv^PXSTL|1E=&%g?t7nig1|KV)PAshAGQbwNXyOLB&AM__nHTyzEahewx z7eR}Ml&M<;5m-`nR%`c8zWI|(lj`6XCVTt;;Hkdm;%4TQAtdE!YrbDVc}oDsiJt(Lv-gs`v{?l19!I zWsoS!bn^lStu#D75b^?QOK&`g<4|MzHoET?WqV^v1mMY@tu6y*%z4%_|4StX9{2~d z=lr-OQ$FnTT@1|VLtQdZ!Rj0^R?BL$Q61`=e+IMt>f)rUHA5A5*59*POKxN+_@TJz z1jMg7X0La1MHC3CTAtHzw(su>FTZ|QA@V8Yy4JNpnh}n4au$skY!)7T&D_@ zamG~Fh}tOCJx;0OCv4Nx*Y_Mc<@G=+Zvz?7Ahh4+^6NdP{ETBbIdEC_RqudErH<7> zL7OKzf+NJ@6yd(ZpIR{($<%)J7p@*KhoMKN83bx>rR>>SWw!&A*OM6`Q{hn({b?29Lz z0&w~u@fs%cy+4pQfqB-K=dohvH+^8@)3cQF7S2H zA_8yyE*cc)`HxU#IG1Fm6rhBN2hkC9RmvJZy9iAdxo6_ngrN6i8~(W(s-Yu3`*fb{ z{S91NmxrFwoOEPXW40!7nb&*Y?e-R0RRIv54HieOLkun z?&KTN!ynJm2Bvs@0|rZQu%|6gqMPn`Yn~U%i^zg+GFtF#{<3oT1NcvQh7-O2iUh0I zeT`T^Mcz^YNB`m10dh_6OBkQ2`F7N7ERb4ynux2CR-hxqFuXO+&+ZfvC;!d6@yQ}E z+#xmnhFG5$igxLV%F!iyvp|1DbimtxaoG25bG=tqk|6SXnkw(`gRIC1P-K9014>np z3|7R{9s}ShoyIklfuW^Dc43bTdjVB^O95Q93NvDy?HbG_i~Tvwzyc_6R?s=nO5@<* zukXi1=}iK8=~!JWM;@59-d?NI->+I1XdaAiTPu~zdRVIBqXjY}V&hcL#alr(SDhAp zw)*wNzywg}Hy~c`;A-b`G>Cjy<6Ht@aHKpR%+yGYEg_=L5d@;c=vQ@Sv$(?%{ICSh z^I(NnVOBQAI-tJlYa$Ai5H7f@Wb{Y9K*g~@4lE!83*ubqiQJ{S(tK^>y zbl>9|_bLKhhNE6!YZL*5b87&?#|0)T%(=dA%bXH;!&nnTWwJA1H48BM8!;x0;#ZQ@ z66G@=sCpcUHke2plHo~T1GxhIaH4s&5HT33Ki_x>_TBBMOhU$4`@@mwkcI|WfF8kj zg>zQ6I3R)jFUD4#<3Wn+(=QAn&T9|k9L9b>nhqggop-+^ z%Qny9zZGsjq7!R6ds|F$WSi!yCW-j=$?ttHJ8m~NECC=0v#{%QFl&DpDy;9C;-uo- z*L?VKHUo3z6hzb}*@sn>g-qk|E73%M0~P?njJdvn?O$Cq(H=w>mS7G3K;oXW^o2e5 z2gt?$J13N8cNm2FpKddV#7DZqW+SQKurdv@6n$KD0IFhCNda*PQm6p^>!Ku zgiyh|M`2YKHhb(jXq*6>{jX_cfqR^F>H~9Yq#_YEV&XvJ!0@~z``B^UbbaCYdn!+s z(znioM5nj~;(;kZg=|2kYMmScKvt3a$>NjVi8S_7mq5jGlSbTn=MDU5{`PSf?8{*W z`3+NBM|?!^WO*imLdZ%03oM2}EU>x8^mpt}bBB;`&Avamx4wHnr#}a%2vC@Sry8C; zi5wsDz3RukqM0kazCYymP{T;;Ad`iQ(do5W%A2m{D&Yh>6{J(`fBq<5FI5MDUWQAZ zbl4ql_)eW@7N?cqLKN@puf9HwBW3vwRV*88bb%%ecdM;ItqPuIEliWqRYhrf07>YAu51a=k{R{`o`(FAaP}oA+X-L{2k4$u};V+ zs}Mw;a`Tz0JnXoAoOe%0m-+Gm#zqyZS~n?D;ENa$F4KuCUtKZiHgsTjSRZ+H>)m|h zjgy_DkAz>!K>A8I>z4;tzuBiyLP2y$eidHtHNeLcIr;LXYpIMm3yU@5sA(8{DqMJ z#e#}qCo>lrx0?gR6Wn_=?%xD38@lxt z9kJb<#Q~FzK2IV@Oq0QHo)_LLi*$Yp&*XoMF8fG%k|3wWz4(4C=8sG{I*M2Y|C3Z` zt#v`qja;#2nnR-MNeZ`KmS%{Oad8-@_8TKnX+56v+00SY8kd~}FSntC%vHp1Sf>WNXjN;|qblAFASmi;9o;raWEI0aO0jf~964f`1< zR<5IODYSsuQdag&!1ky6hIKIjBal-49NpK(;k_V^|~zvNy>XGm7TF!!h|X zQ1E_V+;ePym0!)RGR52x9rt{L->j&P=3Zxm$l7_&=E_22R@dYnG)Vsw#8Pk5m#AKu zZ1H1c~pxAGk^9+#S-dF#zfQ!CfcI5HAJhh(xd5 zb&hUf`|Ztr5_5?SD@gnWOTb`Mb7oV}>#`}Y4%Uk1$tY6(N=<&VI|K&&6eB`x<^FJq zs%0plqC#XZ737v6V)+-}6OI%b>z$%-iSpYgU0)pGb?JDndA-gwm=SjLLMlR+>+hTz z#oX+E88|Ew2U28@C$Lnj^L7%icd=cuugUa{MX-x_%n%5Z%V9K@w~^HA5@tYlYOuXF zC6=v$O2;%D2M9T|#PYH%;0w52uAwUUn5Xd?W4*y~{WyWbQca}^8^rP)tuX=abnS~S zyA4s2WJHr+5VqGFj4D&OOlNMg`cJnFP&=ID3nU5^f%)KORHv?1sk83+2#(iZk9;3o zZl!UcVxS)>1XO3KslaQ!TRizI)_g2c#ho|r`s5{Em9^hPFX^qh4>_7FLgM#ikN;?? zHocDOh3sMPGA)a06m_fss9O*0$U+a>>3iV-|WbP6S1$oF{tZ?!2nDN0HQijf6J(^-x0QP=JV~x zus3+~aX=m=UJCdCZucI!Hs?Z|Sv1*1xHQK9`kz%><-Sg6+onLEGgA2zUe|S$qKOq86a=>x(Vgy6>ViJuE=vn!UgMozt2dc@beCq!QfXrf0 zG*TWp9?j+1OaAMFNzPri*tn3ukegM=#_C4HdGRAptk?1=Rpc`Z|wOE7uQK%ugyZH;G+_G+q&# zbUMm#*b@k8!_fqYF!T!N^~Tf>m6y50MX*8Rwey16oqhuuyf`#$AQbAR8D2d$G?XBk z(DG#it_4pm7W;6|P9y*R3|=%E0Qj!US?cHhUEGF7bS&WJTWPC|k)l~$Dz!3(>vWOv zcm?Z~f24^~$=Caq)LE;ky;EW=%2YPyErP#)0*`ie>Td)%td?VYQmn1NkKBhqDe2#47Lr(%MVnGeeztd` zJB-b5V)-VQ4=1{v&RFM&VN>E;By&kwWWJ z_sYf;u2@i&GhcO>kp<;*xjfw1ANB+3n>+pG>W7$+^Qseg@lJuqueGD{U zM?te4%sjVH+%ys@S>|@MBswnkOex?wM|g(*$fdLHJrI5X2=%Uqeuo08KUj}xBH2al ztT#lHnKNfG%2A%^{^1v)zyQ6QPYQ{)G{9qpW)>X&-v0jeR~TB6Sm=-7&|Xf%U7SyT z*658ZU_mPb%4nVuPZr!saYk;9>`x3{-VIn|4bGhRY;deGEW)yNIG*vT&&M}Y6}VxP zN|COa`tSj`(oa8%sVcSqN_opAFPgL(>FN?Ov$<*`4q0h$bclZ?3T$hs(YQqw3Q=`^ zwGt>`yi(Pa`q=qfGVZ$k)^3c0TCCJW-1S<^AcwQT1HJLd#7#LqYUq{ zuk6VDmZRgY((k-~F-WmUamTQ-MvxN;_aA-E>K_u0Nhs!wDQZu1wb-HB9aB#;%mwQ% zC4172B+p><2wd$>2h=JQ9pcmNKI3PQ^am1zp7hCzYd8~2^2#?Q$LqzCI4z+{pRtMu z;%ya3L`>i5zM+h?pTRn?1~sk9_u8}M>p1cSZ{Eya&!;&n-_tI^iJb+7IYa&vuwB~1 zyv3w;DW)q3dQF3@b{y6QH<-sn?n;I4T&g}V@go@#fg`zre%4Q~Jy&yeVAPT(k%1_Jdd`x^Blq>p77qAzriPR$_#-LG;jM^H%&{&kbI#b_jYo{I0qY0vRFa4{C zgpe9arm3eN8KobjZ^4{bjn3zn9?@{*JFdz1iqdK75><1dyV@31m?iqj57J70uYse! ztQoZ>U|VeU@J~2a8>ntU!e(nPC+_7O>~NunHi3%QlW&$Udmj&T{NS@4;#WLERft6R zHqrz79)Y0%2@Y|pcCbEK+!7-!4EsffH8yr^?Xg~NJEs!4nagIAO|_}2Mrk8aI{k0G13oOabv%}_8Y_NSueU?uw@DWOIq{aJESeFdG4`cOQ# zuXok+sro!cKp}gb%dOQGmhr9~6pu!>|N8&@*$~>!$F@vcBrA1U5~a!bz(U4oQ;77( z=y3Y0v(F>vG0GDg+;1$ZpsdGv=3)vD|9s7ANcGzBu_MK8Xh)w<%}SfO-2iI+wB%qZ ztF5mjjsFeEx1!fpA>@i~UeEhm>!bXyq>8z?-nFBnrnIs$=S#Np58Y7k3;YhDG<*6+ z<76d&X!4D{DSeyFUfZhOCS#W1I=AU4XYRd$jdcd}vPNa^Ewf>Ct=!*!b zo;znj@7+_JRg7-eS#Yi5tW1G=eRBN@t(fJ}!@8D@N)!9c-D*-q04mt0@7F)IlCR2! z&R@?|8pG?Jz*&*0IDTJFhEL5~Y|d+KjH)?o7B|J?R_<`VVbIt8-J}KnPT=(eQf#bk z8h*L>c|R}3F?WB2s6Id5xC@$9=s8ep5gB)GyEQf%6(Wl{+elbb&a$L>G!on7NxHQF z*5E}0+7+ySElS5QQ_-FSerT?%^_}dUx)>xNTh8?Sa(lIi>H< z`=BKi=*bL}es-%&4ZjHMIPSL2k|yhH)3}=Aru@9dTC_74p#hD-i#BHUV8b?|T0Y44 z`jvU&4CxoyJ(@DC6?mtBhZe`kCVzLZYkR;G8fC8}vK4cRUKv@WGVOZbgVHvf z;Lr~gadJWwJv8;v(49iUKlt@n-C|}G@eY0{IzNyM#=g%Eb)~-ePVK#OB5J{|B6VkK zHxcAlqU*WKTlYI90GY+1U=5gv#?EnV!HYt0{X=3n?9(fWK4uFtm&M$ z$zD!h=I6h2o_}ca9O1|Ur5S5$VcZH`^@`sJf_W6S=@!--wnN{{Gt{Y{%cdq9)eN{X zJni=92RKvfBi%I5r~@CmSlLer{bH7fUh)n>&u0ZT1;mrYi$y9ao1L3@0^~?|do{rG zb?Lg1GFK~g4sPQ#4}Mvul;_f4HcZ!ijg1%2zVG)0jsey|CxpK2epv;FFNJ-ZKumbR zVcea8tjak=ilNSJ810I{#n@*q3^Hckc9V(+D#+O3EN?Wkotwd)6Ob^VVjM`u8kj({ zC7LUcpcG;HWo!!US{Rfod%KUJFeCJfXfH`VzPJ^2F@E)L@!0(HPpshBL_SbkKlrH= zdB#0lA1;}(0X>bMc*MMZDTQHr)$3nN!7rXgF$HMgsSqLyR;OOdblAv&yi=6C?q1kv zAhBirXI33G>&pH;*^dY9@?G_uksO#{J+slz?f_1VkTFv|f=rayFYuZXHN?!O^_R@( zqKWjvfY=%HTcr{ED#*qY5;TFAgY!h9_eeNEw87|KT>TsP9wsn~-^zt}9v3ZJC--}S zSC?3~6JFEcpFOK@2_Fs!5b{`$@e%phN)6-(R;rrFoY-5)Sj74KlMy7&sQ_wy@jagA ze64n!O!{Wd99_d}0UpZ6Mtp%VAbnj4X!%wi&M8cI=(Ik$^ROm49nq5Yv7x<(1$y)z zyH{Bn-xCQA06Q8j3)c?oO&P)ow5-GAF@U|uloNEGBeSVC3pfW13u4Qma@=~BpLqyC zq*mltI;8Zf(#*jVD0Ypk<2INzUruHpK7jad|4SdrJxk!t1E|CO?5EVmK9PrF*FKmV zl8V;WcLH`!zhXhQxR|nB$z9z+&<^iHkUgR?tb=z-yD`nK#)A6frByTTz48;&au{?q zZW$=iyDH<{qFa411LWVraZDutWgL!Ggq}Kv(VmZPmc0O-WEhP5Kx~6jJiwYs+N#Yv z6Y^jG+~7OJ04w#I>^9e0odEPVOzXTH71#!!u}6;iO!5iDc&sJQ{#8T+o_=L`w(I7U z#9AlEN8fx(cj#cxT^Kh4cfjs{mu723Wv2<CNNSxyBtWb&wweL7>%4@@j#gkxrE64;*rY}Yfa;xB`@4DgRTm&*z_!q!{XOr2B3Zne^`-RsW>p=qfsFy>3Igw}@@$?_?Ah2BOVk1W2u(l~oQes;hFPB=_u05s3> z0EXU6VUWvpveZd;Fwc1DjUww5oxwaSUYFTBuH;A}<}ZI4JQWfeWGQG1LTUyqgd_v> zxo~HxR+Wu2z4u5kEKGgDL^#=vr{Tv zH3W;Ciu7H96p@=dvN@irKW})PXFi|RWn$;pB}?*9yXV8B^47u61`*4*6%0|sSwEr} zPBGX_`>kH~15gjw#Nt*pW_P!h0?~z$Kt`45!dcVgSr9ogB_&!Kq1G_!(Z9DYDB#YA zd--Xxz9RV<;*)fo7XoSD-YEYOLdENXz)!`54X6p_{0A-3bmZ@5i=-&;I4hS$@5M@z zhz*K)8>8PgSzOnim8wBUbu47+IO1>|94>jBE!X~Y|0%FNH+w+Ep90lb0)D2GU0Xs? zmWaD_AMw4|y1XU>9a}U^&M1sm_n_TAoNkj3vCTB%H5sn;C|Ald-MWpPTE@b@7@#tR zS`(p(V!%}~5Ye_RISZE^gkK-V<4G#-s?5b+n!p-%&2i(W+ z>MSYFL8Mjb{dG9l<6}$ejby6)x3?{Jf3*b)!qTp2mq)Ga2UtUMBXd9C&jK5ZEw#XY zJrXa6+3$Vd|C2+giU=&x5^|yheYtZwkML)pl2}_h6*w#Z?~l{+qV#-BC$#&V;98mj zD>=dwMZ}Rds-Rj3A1)*?#M0-?@7cYAYX&#c*lG-sjp-vF2;KRsq{n^S5!eF8W~d8| z7f&-YncDMQy>UO+9IkGEvRP}Vdk?n!1=;XTxAvijR{VGga%>b0@R!cJUR!3VdP-~E z_}Vr7a+o+-%b~lt#;BG+uV;=)o82V$jv0;L1YRSRd^De6__;(<2W~X`J3PFyJiOF7 zdMu{ks9$x-mtPV6(8~$SDg+dBEV)Q5lx-x4YlXku>OQFn_!|jXk?ciLBYeWs+F;ti?HI_- z0f~<3@z&S_eM-M=V+@wG0*L`kt>|Twm$n>OjBeO&A$l*(Pjg*{gFRS`Qw!TtNN2S< zaQ@4@=^#iMDfq+Ro2LPrHX>hEkjM)0RUsy5_zim|x6C*4-b8}G=DijBInhh%AIrwj zm;1|6v>gR;#OlVN^uDqoPv;7C9*If*`K-VVkJJYr-7CY~D5QqO8fhRUx7v8vSDNPCIk_x|{} zaHJI<8Rx*fY3TOna$`JAbSkD`8i^*!MfMYB@*CuimD8V^GiIrrj{BJIsQ3UamqSi+5S;{C)i__G1lrWt zr-HV+u~}Y{`>($R&RlO4Xe~+t|1$`~jv0h{TuM*^?OgSG>I^Mg;%<-QXLlO~ zaHUQLe~bxOPbwArc!U_qQ4+PfzOl(h1;YnU%y^AfIcAsst{)v; zfdjt~mWDRIsl%_ko|EV*@|kA+ng%El?0t@9&1zEJTMhgO^qRrQzgWEJpn=+y$2$Nw zN=!DK1slPYS^oYncL6%LB)GXA>0jaNkLh7hbaN!+X;>Z+3(xQ&Gd59OOltcs^H;f^ zm;+Cm_=sbIHk-xE{euQ3?zL3vO|1k&)oz~SIj%$H(vf9nGD;C&>&S^b+l_|sJWko8 z64~0OAAIj9x~&SvHrKkQGkwOqY5})g%dM@nSzL>kW($%M@+xc!_Wb*S`A$lP@mb1j z(t9$!Zl4{4eH4qxHHkuAaZn%3`CCIHr^^o>m}8_LhzU|z!aFoqA}1HiE#xl(;Y9z~ z<^5dAoNtRvl&SdX>p?AVUI}JJxoy}+`c*~54?ZK&k5UCKQZX&}%}+z?lDW2-(q;Ul zBHG|Aev>W(;q2(<(+3@jV<6d$=}ncT(4@Jeg~>@wWAd)hVQuaRNgPGihZ#$`8lNm1 zry{TV(pCNc7}RUy9OSa?dt&k&4}%lY;b&H}1~vj|_Fc8N0ztzkIZm2w3b20M@iZ%G z?$vRZB4%DAr?kw(36VU`enD!y!x`@O8^Xg4Ry)xql&)TXBvUu{H69t(F@g61bJ*v%U^x0+hnhkb^cEqKBe5nHPnk z07OH(jlO!sD8C*FSoR;*;W+>QeJR>N2wMWUJq&zI35?3i5F?4=84Yg+*(MLPBZ<0+ zYxFTr9y`J8YlRMzj>@QHLAR8H64tfjh^bwzVU}L{Ioj2c=AlK)L%LA^7WHo!2M;B~r z=9Jh>Ve_qV3ECT~A26lGKzOS_IL0#PgsBJyP@PltO*Gj3&~Ytl=O3$!+FE+c{E``^ zkcYi677D5niZ_O8zGneasNhK0XEbSAh2bd4g!a`$`I)qtC2`ui*L~-upin|B+A;%9 zyO7^HbKOX&=*xNZ-odIkZ6&h`E*t2-IBf|PD{DfQgokXMsu=6sv7x^WnP9oh`!t(t zn*%qW8&>}zXUZg89RUxj)$V++?^o{}!OS%^j=AE9+_|dF9B4a0Sq;dcr*?Iak(EG< z-LN~*-POJZ*#Wk)o4uY61~o43?CjgGDvwjE0xKM^=0U!~T-7%7Be5!NP{(p{L~;L7 z9`(14-dy|RNv_1nng5K7B;Ai1k%WdF(eft{q5rB~wRnd2z1+%-1D>PEQJJQ?RE5e2 z;g9x6R%dVvnB^+-;)7K*go$c$dm;#sRpkO&-1VK>^yi!6L(f0J1t4Uof>uO^+}YUM zZ)ujw-tK~zHz|mfwKd#!WVC_#64<1EMuWqkzZI? z<#&se5`sj?B>j&2XM1TQB|Kf^cBQ}Q$&>(Gv|9sntfUEzW0y0)FD*PQZ7PTP;F+Gq z?r|Qce@>?P(7h_s?Q25NA{S(@-TW?FS?x6a?x2Xlp2)_B0nF4j?=3hoQJXf9U69~J z_VTNP7lHRB;RFsZdlg$u^N4s#;^={sP9Z_odm+;R3@-a{AL0(bqzNvn_r`tM$+p{^ zR?0qJ%>7>gmwJkR4i2UeiRY6QEomd~C+!C(44{w9Mrnd;*!3PorB}BWIEDxAB7raz zjkbrGCA31=tWBl4zy6LqFr+yezbrsxq_o{PQi(gCm7Is>#vbS7Zic~r+*h}>7*qj_ zMW13O7_WiZ=K9+X{Qw^IsgO>g@zPwwUh6$V(0Y%LU$C>^lQ(+h?aA)al9TA~3$zey zRj_kl?$i#?ViQ)`(^Eiv#k-Zv42ejUo7CYs?z&GI2eUlf^6^SJiYU*T&3=#*5?1mz ztZ6Kw^T$P6>Wr&KJ%3<--+?suoBQ5C0n-e^LVrcSf{EeX8-;Cni!9I}ptiJ-6UqL!>#%Ypk z#d+cx%?4^~ihWl3M~~>&jGJ{wC<2s?U^G;igxv7qA++bR9HCC|^R)eM|ctGZlGt!^A}7Y?6OOt1zUd*!!D zQDa44qf`&I{yAg48-v^7xy#>YT6cx6U=-;7`oNvf{oP})F&g+LhKHja*@OQLsnpWmOvHbBsGL&Jx!0_NaKRgFjW9_h!ScJK|bC;TnpfC`0zO z>6W1a2DaTvbxeJm&+I7=-T3$JFRUGVksHn>6DLasy*7@sMLER$gWxRgMglj(B7hW> zvd%jYkFjQQ$+~wQ6ywW9eOz#F@^S?WC<43XbFlH|>pB#V8wrV-yK4n7B?6n3Q}60< zGhi(q1x6YlH{S69^M;^C=7jLSFHih`6ONs=5kxeq%SZF+(l`I&?XxM=L`@b3R`byI zvE@jMbcO5GV`ZdS72bqOCptwK+x*Fs^=HeuJgj*zr;D2%KV-?KSjMg_3xP5E9z~q@ zf(zH!Fog~FVjYrnf-j;aJNLbstRki8CJqXJctR}ccTpk80ww2HHP&!%vBjfhw^vTLC}s zKuh+afPyq_>EDTGj9OQZ@21KYCK;Rq(0}mc?Pmfba@i?`-LjfU{!8A)M_&Bs8KZeK zW7lQv=4~!(`<2N`+lM=9tiKY?<-1tiY2s|smDYma8zTScS>pIe{Px$%_GLxEAY*Q4 z#@#r5BG7*@S9IoZL~NdDk3KvZ)Fw-+Y(F;&LpQg?G#O(#L?f$pHD*a5bbySt0{=-u|g3MIscb|Fm36X{RKN6FR z&yDZG-D4t!ezMFYnRyST;S3w~CY-oK`_Nd%7(_z@IRs}J+0s|xW#7d=r7GCv2k>40 z0Cv%$B$d(oF#0}>LC%g+s156LiBIMNwYnnQ?XqPQHSV>jWa}tMrGr`(G0Qam%#I@) zL81zEye33xTF-(OiBCAwjh7o%Ss}^JywV$C+H)9(wXs}sJX}7 z`r3bfjO8)H9gW>mB<5ze#h@G(v`h-R)QPDvT)UV+(bQmGyahw{0ZA(`b zG56;S-1@jOMBM)RRL=*jOWl7?=0b*UG8%HGogN z1W+z3j3Xzd4Ij9C{SoPuYIu-fhPgr*c<+xPQ&;o%ZPqRZ6P>9=kM;{eGnkl^gRRoB z1B)>7HbOQ2>f?f(|2fWU+~o5P%++SDAvyQZ84{?NupwGHR+0Lp)nCEYDYMvA5XSi3 z8AUX+uU!_^cVU3?bM_`Ocx12-6iNMc3gCUTv=Qtan_e<-)J%c)bG^_@gBm}jD;);J z;gA{gVWNCZFCBttR;Zbkml{y`lI1*j@^77YKytr*KCJhadFX`jZud(9bPBZkxF|k2 zKRoGh+HXGHoSp1vP|a`;cDtm=x^WFmuroIGp<2L&I<4LMA4`M!-Ux^z{*8kk$)+Ul zm*mCbSh8KYZ+6IRrnOXxLa^6+B&GuLk-~D`oMo_`}RyAJb%tc(DuVju;MNx4jKU)C-i;2T< z4B!gAmVj4YfES{w+&CMoZ2!Tx${F#Uh{o_^@cxd}S-)QNqnKLp^hZICsE3)Qfe(vd zAsOTJfxA5g3H$@&>B3;8|oTnqY3b-?5GPdC%!X&gU=rBzgnRj^`>-zH4gQkf80?d)L-hHG=9eN;dN zX4CdH(on6u-(@EMj|=;U=FM_X+w`$xVOSdSl>-?Oa2^Z~`8vhYfxquL$Z(IYL6sok zlP*Du@z>j{FVPkqTNUHl4tu0V`V)~^phc{UJod{Jb z>pywiZ%ozdy06KPy(W;`SB?gltt)k-d=ZSHDG+dP@sNDaLO%F1x&JQ8OVWqFukAIxj~8{G&4CdwDg4Eg9G7 zW-TnPagedIWvu#9Ey44r)Tg^AL|uR!@Zlq}SJ2m5SK}%`99uRD_>_8-Z*FF3x9`o1 z&p1zsHlQvzw~y|g4v_G^y+G;Xmd$YCQ?}es4OfNYF2(V~!c}=G4PJkl($~6A-ddM# zjGMWcq=8>wk!ix@2q9lGyv*xl?Wh`Unw>4>a&q;0gMlOSUdVG&Tz>yS7jHILscj9n z(Lj7%Vu|FM93GOeN}{H#;+*@c_kCpc_k} z0-KwqX8$Pb>s(sjTBpe2$aW!4m8N)h zmiY3O5+yXqOg)>H1FZHDGe|4iQYS0ymNu? zpZ4lr^1O2~jtpUr-t0`U_LfDQQPnKy0l8I^TrWpYHZ_yZa7J<019{QR!jCyeI}1Dy zO`JZO<>MZ`ZpvQ}v9RFm;S~{YIC-q?$@ee=y(c2EIsL%=-`XHnT~wuicMG>dRL*PB`id*#hbR31zR;K^Q}Zv?!RnZ z57j&$y@{@c7(b2bo?xt6J%30h^|N9ERfX$%)}8K;sB;*n^(;icUbx;o zJ~Y(#>vdFcJ)*}i%kov61W#p7HnVu?DjY6|BR4{hTXVq_1JRne8*$w5P+U}Ak^!s{ zEDX(lqQJQ+^p=tUA<8QMglY=uW1D(Z_ND?=7 zSfD1(8q!wjNL*%^xD$HP?t_(;m8+Nozp?7*4VW^ycU1d)Mo#7QX>{=OLCjA-)@FY!s)X$De3w4-{5& zhGOm(LN2St^Jh8VE z{9ta(D%1?9-{?3MqJ`d2IW|EXR*Xzs%HCAfip07wc91$<4+YK-s37p@Dm(HpJ9_IN z&K9A!Dc1|zY8n+MT^6U3u3#ryS<9wwBzCY-0zH}Dv(6sGCl~l`2y`y6l?Cqt?3-CS zDn~CKQ-|%nm|QRW){yt>v9_h&wb&6E#HAKG28)Jmsy#yPm$!_PSGCMk@>v6gNGCXk ztNy+*PJx~T^v31riM~TJta5S9K0MDNHc6G|qH-dcEgp*0c_p?gR@Y+-3j*&`2Y8s{ zgRd%eY!&gC ze8rRfOo$irO`e4dK#Yki)`*IWvk%_!uxkQ6D7eG=5%dloY^`stuOkq8(qX!t3RiO1 zMi_U3H9}?s@d&Z&aklmxK)hvS3n6!_a;`_e!zz8(5(UoWdzUVuu7{7x-t5P4c2g{H zs-FRA-rmUsy#d(^GOX`Kr^L_>(TfX3iQFeSf>IF|DS9H%hGDp-qsy9~s^Tf=1u!#0mrOsOmH;P>m$ z*7dC|gj-v8_cv891bV!PDeT%syThVbw?vPRTVNLBZnA$CBrjFqWNDKR>-lSu%=BJK z%`7mzH+>9e-^|iYnd`keDsYDdL<_OJwcK?x>XJ1E3pEQQ2uA2~=?!xt~TpIkX9@3n7Gx#I%w>+a^v5CzQ zUVbPJ(FatOm5pX`^wh?g9@(SgAw)pe zbIby*pez&OsKzmE7}TTVzD0lZ4cnwqDhYiRQ4woV$q5_5FkCW?qqm-+=hSTgzCdr4 z@`~Y~kLEl`uYD)-pB#;uMFQm~a*PPxi=SN%J&k4Yjy(&#ffGtS>Q>k5TR1zbXyN2T zLkqwT=$&JUlkj1Jb~3oa`mi%W^hR4eEn&g7$e|nZVuaD*j(r+yj`YY(g`RY@E;)J| z8yk)uf%G}f`eoRjV$xr?;7(zcX9K6wnjU7L7cHE<>vdC6;2ibq3B7ZCXozBg z^GwR|p^vz*`B>?A%b-q0ZwqZI6c9Z4eS3R*V*|^!v3K|WH1t%9bh~94Gd7@BG7mjD z4Y444Zh4MhLeCzPb$Njktt?>g8qoW?e>Y1fwfN2D%ODTj`Ex_+*u$i*1@`NeknC)x zbkOAZldGAIu8%9wlkVQnIDI%{J`?ZL&Alp$o&|)@Uk2#idI26AIIT;4ZS6)se7c*m zZ!YK^xN^PlJy53t=l@SF^w6Fn0ljx!+nC-x6ME7!Q@y*Vuu9w(5hxxhmNoPZ^uB#`mUxwq_HS|_6QG27tOspI|V0Q;g zgwxO)X8NuA+cG0BhhF%eMzdI#I&2T4$k@Pn3Eg`0{=8ma;OwMqAQ|dk+eB zWNAan;p0hd)k3$09u)K?^rXFLRe?5aBhdR0liS`@^fK-1wkYjMI>c2m^yGce^NybN zF0i->@azS+K9H<`XsDxF{Cp7~*t0>LY~eJ;=hW5Ag4ta!H$H_KG84F*7*T7PAW;bP zB%qgi@q7V#?`|h0^g=*SWmD+EspxGAy)&sCdUQRa=k+`+Ko7IM9^wL@lr8+cUVY)y zUK4cTO5wWRB0sQaa`0$+CYqk3*T$os1Y$iExcme~a+;)LJR2MHYZ!@ne3Cj6)-Bv) zs|seD4u1YHDbO2N3%$`(e=)jxUm51cDS1^AZkIw2z!AJa&jt86eiOduj|{P{SFVNg z%BMfve!AD``swx$x33gNZ-74a^FiLi8*1RRg(EmI?M$zW$@SVR%xBU2nLau8=kp+2 zuO6R_np6ND7N95Hx#Q?bKo909^p1v^&iRE`M}J`dvHwZb|F-L~qQ{XeFL{r;ePrk& z>BF~9FqY-gJ9s16t#Yn+r3dfvy8Y>UCDFTV%`7Z%E@Y!w(nvDX&P?#s6HHG0X-BCh z>(xx}AFoP=9%tn}2zIZ#7f69)tP`6ga^hyYvwFivU5N zK5S{O=XJd`j%F!B-qXFN=m+{0JVirq+hR%-txGPPc|qF(scCL zq!K##`Lho{gA#gpfXHVT(95*9oaxMUy>|+ZW`XmuSI^jU^wg#9?|t_%oZlBh?{@Eb zGx%On*Bgwv-izu|2YF-gshMSVl}GO{_Rg-yr67#s*GMF+msQTv>aOPKmi5*fCxR|^ zD?y0J3L+AV;KGFqZsc4^T#!vhPD!u==*b?4sewRmi_*vB zZ6fm6$pXn)CkHvCjuGc!sadoYDR?TwO0<$KgRs+yvtW3BoL z6MUMnjxBLB^iY8w+K)|`M=8*a<@vLo;-eiU&`X9juKi{7aDuvJMZ$oSb0UF07(LC* z!e^aOMzYz|7Lr}uJk&aLFVzGQ6AB*4)2SXbLe*mGgkBmd{Th0n7(J7Z-Up!P>CMvd zZhdOraIptydH$p)M$eQ$@0!K(p{+mEv9zq7i>GhmxgHL-q`k71|F*!J)Q`-jcC_Wa z%|oq2uhO%6Gny7j7f=g$eujwObh89{1?i!8rdzE#PwO0fF&R0sa%fN&d(l%ug}~+c zDNpekPYLu+dHTEPDRp#HFAH&}TZVKQS+M}}ilda9B_;HRQ@wv^^(;3FP4+^6Im?K! zr+MEwt_O;=$gPYfQLKj-UGMZQ0U;YghKeS4a8J4)66n#Y6%>b_C!i++d1#a9347cC zJEw0gF9lljw~vV6?Y zUI7m)IEzKNI4K40?EM!*^!jO#t=0RhWUgyXm8GtA~*v$MtZTgVQ_Z3+##2 zGrLztNi5@Jg%h577h+}Ef~hgf@5y+bOF`9BfZkbDy`mO;lb=yVt%f=!>Gwf1Ab%e5qPJNV9NmaS`?XyA(ad^*|mO zy>qj-hgPq@2H5H$H;cXnRVs2{T&h6w5u=AL!YTyxylfI!3S+__-(2yI$*i|J+X7{8u6>!< zzeB24PYvEa$vh44I2qt}3G1CsAY#bB?FY>oD2KmWr5M7+|#486xSP~_hSt(de3aU?kt&tmOw@e4U(_K1IYba#!qmbebX1E-B zP6_nHz;T7*u0I&HxdJ0+iRA08^PZglDDnR34LCKrpvfUfv~xjETmW|mCr6JJk72+$ z^lu#vq{?>SR=kUgGZj6Y->m#aw7LDjgdRC8$2m?+H>|v@0fxRLmTV;nK^?n*) z^qynDi4kYUq6?wGH{vg#o+I99Mw5^qAIL>aO2@1*dZq+=5xPo$YI0TluoimR@k6>t zapP+Hf~wYF#ww_Wo~aLd(8I-qkH&dJp@om9yH&5LbF{rWvVpa8q8J3_gn~5C6XvAd z-tn{WfzG=MW4wH`P%Mm&(#D0^OaHai+xF)V3^00k!An-Mvv_kof)B;wdVzhl`{JbfJnx~}M5CrwKM zdS2&;ixtNi?!BYcg-4YpeBFeP89h@Hz2s=M!k3`;ow~DWZQ}^z z_*pW@1WoKll3Q7JOfhvNf)9J~wV?EnyMwDOObcDMMO(E&+blIL-2(Yd?vPtwwxCD6_41vWU;O1o&;KCz$2aGd zIrQp3eX+41KZQY0264i@i@-hkTJLhj1?|>DWsjys`sRo4Zh3*z&}Phg&|)AQxP=@B z?bqwmKuKNkghYB5%E4r^=)%+OYej2(;brG(bsoLOvz_gw$j(=r^XLt}?=Pl#)(q9c zsZA}iq%4n|cIaU&ixfEb_rDA`n#BkpMg?JZ#M3ByUR-0|IUG(W8%Na@xy(|gb(vY~ z--c+MI7An8EWTPD-RWTQa^B?mgBCcu{XW(7h&;EnEU=TFJ!P+2KWZ&c8b=;_oo=VK z6zTLE9(qTO#WeQ=pw}+f8A1q6EHsL93kA-Pc}^snmxb3lp>91ivwZVwumb12c`~}q zQPlqIL{8G45guIw$^vxPZC~cKO=p#}*L1qx&*^ zTEE!aCGfbe2cgPdRSKM&>!{}7fcsy|dau!(NAJPf`V#Jfp1!^_k6yFUTfC1>JxqZU zjxKAta_^Hn7{W0S!mgmrdiUq+O5I zg}e?57tyflRlynH%jVt3yb2=eyiM45G?kulIo;(JpWnN?fL-cGUG3JBL7Xyx8awx> zui=n&_JH1Uz=QPa{W39kzK z2d~pu5_p#{#YP59p;K#O zd=Aq*Q&K16lo5gq5k!E0nMLj4^sKaV&VFXIc$(msAwxQGkx^RtF$cadN6#fny?aEx z=XWJg*X$ayOZ|Qyqbz}*SUnUtn=RL;&g_-wRo-IuTGx>D;Tbw8>9xAMoUOOX#k_aR z=7J_n2AIA2_D+vOt!`_8Px7{cfX+n{ICt6Lw2T1bV#Rx zQ^TaG>3~Anq=aS&RPr3&Fp09v0*mP|8X1$KsA$a$^+2F!Gm}OsXc*hn#3P_rFl9im zFjH%&ut^6_5k$t=Gh^a$5{;21Hx^e(&tTYQ*(9UiPRBN~BZC6xG#=r1kc&-r8?M1Y zk0yatB58G%&mc@`=*Ag2L{5=Nld_6Dazk1@La*_l0ddQzdrLYKdsWo+oGb}Gmdet_ zyN~ebwePg4mM1fjk;!ALw}rkv8qNX%dwVo166Ev!N9flJW%Z;0)@H&;ltlQ@A?iX# zPN;AYC)n4_kUY+FOZc6EyK!u-9RovSF075Mv4HR_Pa+F}k~ktAAdQTf06pX!F?w`> zr3vNbG)N1W$xGouMc2MCmy%4QG))b_P2y2D%ZK_bvbp;wzqH}1H|%LdMgJxwU3~Ol&;M zb6}F^GY>s8jqJEY56GS2D4@**Jqw%?L65V~rW2cw`8eO+uG&23spg{>|40fxBk31IjG!JJ}OR529@W> z?~&!;xKb&Ok?V#sI5|EZ3{Fm--!#MP zUHM9uy?Z<>k~4a|tR2};Sj`P?u(5VUEU$%H~h zHl!Gbk_nlqG)KKH$uiO*5obYyG^JLR6yP8k&KEcmC7JLXA_Fc&Su}f6WD~J^P)=tF zdC*Hdap3u8PV^j9zC`IU=q$M^Ll!vcqoHkl?%E+C`kKU^2tg-np18Umpc7Bz@Ofpk zsN7Tl(Cfp)W8&$ia(rAleElB3aePo241PYWy#D%z84BzN#X;ry;k9@FH+$#u8cPv{ z@pa!>B!Zb_BAAXDV(`%mxr^QecYH6J{`R-{i{a8IynX|9Jdo%jFQu+|9BrBkEi%I3uz8+4Zc1g39h&wUe7B8?AJ=YApMwUML4SLC< zF@z5LO_216V9+n5Jo!Na_q#HO=A>4~&u=>nU2BAZ^{Aq?!D9JA`xw6RwdlZ)o) zou8imad9$1TdZhW;;1;8p#FGp(X?%dk2p9zDkjH`(7QN5?RWFr{92FTfj2nqYLT!b zL+hQm&(IEzFp&)4=~n95(EG}Mf)<#rb4tMaAg;hL1%YQbLFT!3r8Ln8H^42$(|fS_ zmOd~2eyaw=2j(_`tK)iHxxlGpZ4T`{Fs+xs2X}OS@MO}w&*Za{lQk)FTr?JGRvkP! zXqtU;I{AM0;CpyY)#PMyjsoy*eEX9>PL7VwCs2HNqvOoz(F_^f3TJO3;NE&GIJUqZ zu+xn#QRUQLmWL0qR5q8^TXKw8#8t&SPjrr#WMIr+V&H%3DKV*d)>3BaF^`Ru@Weli zahJ8x_vc+S^!D3g7K!8ucQnKq*2+@rRW_O~-fHaV+?_P00+|mE4t80jschc%87D{d zn!?(&z!Bd52rnZ!@kY7P18rvWR{L7Qc?;-mVMJXPE&x2*o)-At0(u`zzRNwhK#g;` zriq9KOj+_A_^c4er-zF7_LpOl6t+jYg3Q2|qbI&Y$X?GO=k>3pxQmUxKd)J&_04Y3 zdHAy}orSyyaHjQu8hwRsJ|>sUncM|EWiK3zNQG0|dQ#z}Ju(cbb9X&-vtSNqF0J=v z_;phZp%5^Uev%Oqf1pgG_>##rE9*1ct*nrf>d9@x{i9?;{OA+f`WJr{DJx71WT zI0n!C%kzd;)BM+GC5t?oNKUgzF#KMDJOvMSez>bM`#4qadGrdxrzZ>cGNQ*Cr!ZJ* z2-jH&tMxkC)C-M0+9Q+E1&pbGoKx%B&)b?~h{nK_h8#R+#4^)og7}Q^FoIYx#l&u6 z@594$lfI^TJgl@Qm=Cw0!S^p^9a7(ZyW(sX>11JzlUrMcb+XphV;hgituE$s=0h)z z>6Kw|y8Ph`;K4S_Mu+C7)fgc5T+lAghiiKnTsX-ot2?^#bT@oIl5_TO%HTqmL+Un_Om!Zok_mlX>)>P<$Xn>WoE1(u z2o~x|JC9c1J1v>PDQ&%t0Nzf}c|cE>%1*w^S>ZGy(x0_CdMS2k9?zR&!ZYoz`7540 zpYKZgte7t?;$gP%#_!Ln^$vA(VO=DGr|^k2GF>R^E1V=w91|9bFIR<=^a*=_k9rS( z($B)3Ep>-IwD#2O`)hCQar$%?^nABRN?7`HPnk#)d}^vduP*PA;NhrBJs0=o(|1eiq7-s(HFPqYRQG(YudvZH#q@u5`a3bazZ*B zU4Y(uU8a$VF~Em1xbSf`MCm z>3P<@)U~Pi5@)l(<9;V{NQLu3FpE@JTQ3mD=%TMB+mJesvPF|D!eS@rKJKN?wjSUU z@^tz%=5Xdh&m)%pY<=J=jb*BSj0arhnVfneJODn;pR)K3P}z+nvpw5$?Tfhk`ip6& zO!loUwZ^Gt-&OC04Hv{~n;lL{Ab zJxbbXfBDH9#HO{ZE}M`AFG-|t$q9o=9rY?={T;Mq*1-jAcT#ak9b#Ras`Y4@#n5v# zObIkx4De+dQdj&+VNXo~iXYYtZOEbUfjn46Vq5PGm_^Fh*1MActLF1xZl944xcfW) z->!CAbNB>t5lqoi4)sU}{q z6#ns^7A-B4C7UpX&fmCXnq{T0x24b0?#6nBp1+fQuK#|%Tz2%n5cIkj*rOdz>*C~8 zGPds@%d}Zm)E2}U#5v^k_eHzQCF6^Cz5Sj7bmSE33{|hW^Fyi%zOqoA%2UV zmOG=zVFes)=)tu%T4H?~1|l$nGc4D85j&}4CK=5l%}Iqb1*E)|xspM`+#Mc#|FzNF zL+aaAHz++?M&hC&IUcmbwz6*Jg4w|hu|+RuKJe`%5 zIz7aN)44Isemj{j^r-WIoc3_4>g(X(W+%F62;lAL-~#HKIn5${nP0_}NzL$|Nb9QS z{{G=*`SmvUTyB!&FXu;3r%zW^-0p^~mNDFIT#urSy=WF` z1^q10d@``7^T;-KUfsg}ZW2d9jvLuio<)~Ekx z=(TQN!Ubf@qxUY*bF%CsnI!MHo+v%#PPHDy2KICcr_*}2V8}-IW&z7VyW4+EtvA~* z{u>!o;#UKo+MiurVt&w5g~u)yXg!sdR5yh^T{1-U#4rmjl8Fi2{}*~0Dfs4HVn?la z%|qr9J>6+&bCdAJoh>C+h3yKk-MxtS+PDxA3`{pj2VBDUALqcg~Z zgHYw^qM>vSr;RM=-?-jiEvj+dD=U((8yKSy)?yXP}NUIqy1_9OS`y7si)HdkFJYq zTGvn8`yg>TZjbu~o?iE-^|)QtgJMt@{V^f~yzAVc*Ah|wIJCeJeJrSPJ|~uuxZTOl zYr1R*b2!n%`Dw;+z2zuN>M@kxF5FT}Q`FNxc+9NVoiJ*mrI&nqfQ`4tp}F+DWjRyf zHLGyKDSB6Am;Cl<2K|GY z9vlM1;b?Bq19htK$})DeNJnR<+|U}QP9w|nN7nYR+xTxQFB0i7E z1)&5yNU);(({et6hb1Yy5eq_h>Cob-lS_(1qV?i4DLf;re73zAQ~569NhJOLSXy%A ztZ<6)Y0-Mx&7$ND(FoMBq1PrjL0wl9;NQ} zf5H0*dc)zUUlhOKd5YdXXv6h>K#vie%?)}~c^pz#rKc;0HgKX_I-|N7R_nnSpe|g% zrm`4O&u1Va@FYIqk8Ks@MB1lJjHSy+O9;qIkg@kb02XZIp{&otk=ieAjs z;$vEHBwsxG1Tp5fcjSqEe>lqcRvEP(*6USVxd8a0EkJHI1bL8lvry?VHtw%Z>#EBN zXIFmJe?_nQ_t0yP#|6;aANMMtSJk6oKyPpfz5RJa573c5QG1GBu==h$I(LBH7JE1W zURbXu2FWr`pZ1(7Jq8RAS!Re7r>&S8!oRSCyTNOPyI#Kgqb0`~@2#$7H)3M&c|+Dw zQ?1AR3L8Qc(a=7E=MMH(WQ&>jhQ=K8O1s`(R47LNAzr!I()%SeaxK> zOBXs^r4A>1sbf$N?7j8y{e0{7Sd}Y{h%1kXRaAz-2cE8yYQQ{l>Z3&nG?ie&`9~l# zb0Cb=mewfz=1tLd?*`qcT2GXy(~c+}AMO8T=*_4N?ZZs?AGV9xusWL+!yZm>eO4S!hlAm>NN+el=mEJ{OjyzWDELw>9= zF}v}{PGdAtA0q(+l~_ngtW@KVSfN%BUo0ZTY7s1`APQ~X6hshFABxaF(C<0tyXWk2 z8aA36vzVN@GxyG&JF~N4Kl$F@7ncUXqMX(5kDOlCMtTJQ%eA#jm)2wxbJgQjCZ&Gs z=Q&vpb1)UpHy^i9=i~bqR=thKH#*XhOv&T=da<@87Ws-Mbsv@|8(jjDg}>9>tK~=; zPHf_YI5CbHYCoz|BdO}iD0Q6;P-O3UEO)X~QuUbOiuy)#7kI|=nlwm~fjbx(N)>@I zk~vUxFPTf^FyX=f>Prx}Zrq9L*;C=D zw0wp_=z5(Av>TX^h0s}xmZ(%ML=-u(NW6#d{% z^YULutl`vyFEoT5rM!p0omO!!z<}P|()66Dp7bLFdLNb>rA`7Ye{~^Y){JH@FW5PN z;v2X;z^Qne$2( zUG_wWF8Bnv$ZqyT^`>>9q3QE)lpCckKf+mYeVf;lc~GdAm_MAA4S|SKf;1s*%stf* zGr!5U{$2c3UhsqptvNYd(8mD1OM~dGuVEv3>-PXl{~msmV z&d#C(_Ba=yE<*m;s{o{`Shg?!zxg2xk2c|lY2u>k;M0@?7$ zMSPl}NBD@|fUVtg+yyrMbbl80HD1k7M?!?D#xRq2OEk}P*$Sig#6}0?aj-1g_4=dr z#@Uq&=#i>8Fp$)cdCk+y-Vw`saJH8E1m&-(6)iUV^c)=Wo4u!|k>AvQWY52WkqdhT z(W4$UCFG|ef&2w$<)b)dRcTVUJSp`DSJWX);o+wZZivZIjvkxOiQcMFXWl*kkO7Ra zGepxw2gtFwxMCFYD*e*vSw}Km?u4U;h#oeXk4&?i9r8uTJf+2@IU{)ev{rH+X}q4g zCL7c_PlPDm#Kgixd!daC=i)+7TJ_YXQNt-^y@IMY>+HBe5+WF4h>a(ydkW$ht-%8| zE@f5qG!@EdUQ%=PXo249sBV4kx_KAhnLSrwpv~U4{I?ODF1u>N$FYrmDw}uv_Epc}m4& zTp%9lhFEFzp4c$ehZ8mS_++876oNhp)FC=4boq&E~j!8gnw zoUNIQri^is&fnUlk^5}X#s!F;HZEufYMUYg+DFyHZav9jRoMg`L(U-2PH%DV2{mh-Q{QN@*1_U2mI4Qx zl|1{Zx2FA9P}mdxzWTk6UVb}<)WsD(EgPecUG?&Ky=QbrGJq%MOAU?p$1YeEXJ;xK z`C`bM85nll?g7jYEM?=K*ZDy=?);3QnDe6X=yzz5Fj92M-+x5v90Y!Ckr}I>wvu; zI+FDkWrOP3NZIoRR~oAQ;Qy^P?D4=Vza|!g~Gr=uz{cRS%)Ij9Y-Ngy zx-E7B(JMCv?#B-vx3!L%W`BLq{xN#3(LxVR>QdIT0ek0c?)Ol=$Z>X31q%^$$AhX- zmsFbWoeuOm#pY(gKHq0gk5a>e36Z32p|>yxXCr0dP|t#S-%Fy$d{xW0;lEoZWAeIG zw(N;j3r7hI-iBE9;~ADBl3h#o{r>8@Y;cC&b7Cvl5_*1jJTn3?_ah0d{{8D#v~gjB zswbK!lGioC^TjRGTI$h#jA$_wa@bvt$s>~NouM}bJwT^6-&E?b$?;L-II*kf^|W!J zx1>`~KPye@FTed^G4x0X9fG!3w&NPZ7R%j|_Q^_D{pViERpJ%5@sr|S1|%7`CzHLu zze-ydr|5+Nz4**{1F~$-)i?*AOwKZ%>C^YG26lUX$!Zqq&7!M(abl!%*1QliBW2Z# zeqy=4(}4tf-qv7_c81=tK|>~dFxGN{K3mNh1BSF=uLrZ0Ex{fd7i8Y|t6!8tkH32- zf&udxc3^BLc=Rn$`6c>sA1_M6=rk#N<*5frJODjf9X-3V@^{PMB+ePqKqWpe@M`#W zO#-~HaJ$|H>sd6*3C&Ye>fks-L~2~%fpDcVpsQY_JwxxGmi0J61Ux|xf~T!|b8X3Q zE{N*&rnRVtvYym%eqIVa3WR!NBu2@qGJInmA}T!b*o0fl35|H!$f+LrAU?xCqK4ke zDs82X-XH#7gJPDMil#)yhPZjlrGLfz?}OjJLXv8>=qPoY4A7Td@EXoX03B;t96eXF zpo^OeAkd50Gu8X2bF z41MD{U7Qs}5309;;d(I7Zq8T*CwA#c2Ft3~$o<7UWG6sR!bu8`#jLS>>VJbCVAC9@ z&46pxl(zH*rB8;b_jJIX<~BKM2yF`=l|s+a2?c7Y1lDqz1WvD4AgyJm6f53KP19g- zYd?KP(`VRjPt+5-P`yF>_4gOW9KFeF$@Gz-dab%J^W0_KMLaT{t&mdsg}YDNsdn>q*=BFyi^i1f+ksLte;epPl_q-SIbTuu=2 z2*>M*p`d3&7gY5+xoM%c;8zSEVun-CUVUeCYV*~Z#@Cn!`ef1j@y@q$es{O=&0b^g zo5l;*JEMl47&~q@v9Vq6A&k{i&9i|Es(M`Fi*vJ-R6R;wC`2v-1yu-{U|9Z=sc~+I z@fh`o;5wM1qB6kFFPey-p$vVvY;~cjx)UmW>hL89$$T*_M+~;Gr-`vzhpJ0`(lSOa0aTmuM zdn$i-I$-hEsG;Wz4Kqu^n#(o}sr@NAD7k_U05fB8In%l4nap z*hv}RK&3HsyPCxroc(pmqKDor9rh&S%cX`6o^iu%NQJu=(+v+)7GF7 zJue)Ray(rb3$Ej(`8MiDxmFYxM}?EO#yw>_lA(sv)|C~_<5*c>r&XLd%BZ19M=!1N zl~s>{uJ>!%-kuWlCf|JX1564%V(9IRDtc1ZYqBegOg+toEgxl3Z!xAt!UPc)FP2li z7Hqas+FGh~2*BVYQZGt$rDuq1iGvSMtdjKD^$LO-O~rs&*{Vge-#mRuV0Ymr`?2f2 zIOu#ww!_uXyL|cb*5xg@K<|AF$9JNk4sO;%VEALZe;|FdR_yO8yOnR@t?vGyBAJ;r@3ibp&eb4w5zL{q>E!h7& zeNiJ47c{NNwBA_Zz*j7U9#@scP+9BE0`B0L<&+IJE_u#`Uc(%@(_rdA4fHJb%J%j) z3VV|cpm)2`7zOmCfVX#}apQAPxHn?xH3L1k2~Nv0(Y97S?3@d5skdm$IirSChRS|a z5It%YG3#@rF%%-hh`(k=!WWaDFg#0OT8Im#F3N!#FO$ET$pw-MTOBl@_o6o^yeR0s z1iO402cl=}(OQ+iYWifu5LgLQMx%ZelX51rgXyD&{dEgZi^Q^?%?6kzpjPxm`Fzk& zYD<9g13ha}XM|)pUw`-O?RP(EG)@-1y<6Yj+H34yzj@>O3#i__b@R@sH7;;EvUzOE zUt8(JQM-_d>q%KpOsBwIlC{)1O1%tvp#z|Z+QY(-LTCY`D_hhw^>xBzgE~cC^+@S6 z6;o5C)1y;h>8mhe?m1D7TTQ0ug(-SrzW_b4bsj@j5em@leFZMV&jheFAlR<=_U#bC zus)*bc)e$AX-l1)#Uu|^oa{W!_0)3>r@@!Ao5U~Ia6;}Tr>15$U!TGG$)eZU+1Zh^ zovXVzzHoJ?F>2^3a3Om@&#c{+nE)|RU9+2uXw{RU3rpI%AT^u?RgXVE<%9x2& z?j~#!Qpji`8g3LWz0qP!=%|I19rJBdwUbykd${yk!FDiuzX^2keiQW8`$qI=A+-D! z@L8_yhg1gn29!ElyfXu3=i%JoD0Nn|#DG2JFHaB=T1WhN%5$n-Ov%aPiKADu5kwC) zo3g>$3Lgw5zJ<04(v$ z9suNw@3z#*oc7_Awml3}w~61;qW*S4^jKzdupEt0B3$>#Yzk&jMjf*)#E}82NZs;1 z8NDBV-a?h88_)|=^pgDzJXUJfVnemDRTbsjHzo)rF1*rE%)_aw2l!&dkXEwf@p|Nq zN0Q}U7ru)g)1IMsxIsg7+Koj41b9-*iJ7ORz$f6%Edf1%XZ^@_-Y(a;kV;^rB^gUc z2a)Ge=M)XG>b~spb|oBb=LtR3r-c3b(`#yk?_l(3)vz~GMbCiN{{&@K4-I=n4^0bQ z>&qgOB5_G)U3MX>UKTrS^qAq~g}5gB8G45->&**tvb9zAq$7*B>@5mUgp{);f z1uCehje3C40~{*Kr6;UPRLTLAOVqTgTGWaHCnRn?x1XS&fKS4IX8zu{`($YLKot8BJp4f{+LFq|xY6WqLS$OnqpX zI>cLQ^&Fbors!>r-XWrg`hUq>55rAyvw%SOH#K+q4c+8Rx3)wM=hxSBL~jRn%8NdX zJTx9X3h13UapDVU@GGPyHF zZ_BtI$%Czv4l)46=*?;t=MiB~$kVtUs!w0Jo}bmrLp5nziVls;lfQi9R344q?{Kat zdI0Xuojd4(-Ye1`Dz~(16-`+X!RtK1!GQyZx+{C?zdnS$p9Z>>gM4Ddgp-NkNKlFlAl@*{MB%v zcQ1HfUWE*3J^Lrq0(zgOrRV`ZX*eIRdQgi)`uXj&Zf*G$vbQFI9?Tx|r|IHU2WQzL z>gCMJ1-Gk0c8}-EB5(6nc$uf>=C)HH^FJwp`)X9kZLUY>CXhRXiJs7RNV8dxNe1-L zggrzTSob~061X=48>0ZK@u$QjMNRf+0W+r>FXIti5#T6A&n*kO_p3Tpq~Qd5O5M^4 zV{aSieI||QWx?9c_Xm1;@43)Q{46@xgDj$6LMQMQ{9G?-jxSyp1>s4nzP-h_g?cn` zRqCag9MQ9=f{rwC(F9JZ4Iy*A!e#lz>zBJo&+ z&;diaQh1r4wr`RquRQlsx5Q~&G2+Cb6TMj)Jsi4d=*T;g#3|!VRG-dsuIEhI2zism z)8F>@ygY29Bx#s9L~mn9q5kJ-UAXrvSu^j-!v{+$BTvwC%Aki2<;UZq=y^F)K5_Ku zX2E2yLiWHN)J!UImT+V}oFQmV+IqLHSIx2u5T|LWWQH{jg9I*qjAm5-eIaArz+CUtM)L`rwE z=!t1eR1CEuq+9vheRP7}o(C6_z+R=w@n$Ifu0eI@;SBLQUyGXW!Z^%%LZ?=5tKb5d zlS9BmFLv*cO!aVz-o#{YFx7+I!)7Ols7qO-mj=DoP(n%{&J>9w$R(h+gww2Euh(0W zgXr1fA#|!DxdV8Hp8M#1VD-McdiiY3ZDlQ_j?S_;(UnWgpLXbttcGhB_Pjyf4$>~O zyL7X#4w?E{G_ptT(7mA{b&W1Cn?*dF=dOSI@}L*5d|;_4EOXn}JTW;{_cjbNu!j?K zyC4+=K22xmtkIiGLG4L+V~>%-jZG$u+&S?|_iE zEA(dR*i-;PAMw-LEE-T}I?KY5!-y?teF*HOzR%FB)t$QAKraqf?_H<9x>KMpREl2E z!?okR9vV-eN9%|VXAx67Z6=_X)*nT$KW;fq9z8A^!qNrVRTku_to$^^Vt@$NIT5=| zR4*YcA(3Y9fWTKT?8fRDbqRFPo4QIJD~2HRvmkq#ZWg#W_aA!QhSOH)#c|w-DWLbB z3TWurhfhU3DiqM`dGt)Zq)s=B79>M#0pMY^ zo^0~9zY@uIfL>5*C@S7xa( z!U_7+=wX%mmAu_7%<$qt`L|yDDK8oH?16T8P_H~P=$&-xCviJDJzm-4TM`zIc(8SU%#gX4XXY_1q%Orss=(z!>2Gntsqi8I0;k`@lWGDSW2``kR z!Vb|pc8s-<I+&E2_DY(^Br*VuZy4%8s6kvf3&ke)*2W& z;^3vrPt)i5#8|6WUuE8kc0@1e9?&Cu(hZ}xKCq5;xd{5B3kdFI3xa~>@BJ|)i z{`=p^bwg(?8cM8Qb5MVpewMkC(N`)pqpgje-&#G1DzLruL(Vd0dOM!$&6>&62I$an zyoshZ&wMOem*pKS8DedgTs@qgu55ay(`X=Tu~Rp|=01t!c3Psir2=}44N!f~?I^W+ zK~L7s3}jZ%o??2-($I>dl|RF0qk89q+lCz)Lk~{H%=e#!)q~lq%YG;7;RJh3pysL} zZZ(8fs>G#Hp@nRaUBUBQieB~+=VBCLyz5$K&dlj!dHl2h@d z)9Pb`Ym8MIY1R2m zvKEMT3{ARj?4E9RJ85-0^*WG4CnwM|=cM*fpWaKkpu4}J77mBEdPHxPgf3Z_y?DWC z^|5^@_29Pd%Ptjm>Hl;Z|NU>|8rRdkEj79Tg#>CvkI@C3((4Uonc*^3P?;8QH*-B} zJOLdDwA$0GJS|PCPrs(&1u=T(ujGhco1;KKC2P0ab|sd@$fH;DQuKl;>$W_4L)>=j zX;oHJ>Cq6-3nF?!Pu5PII)jG8&lHt7T75kDWL?z$;J37qga0$NE)d7~@1Lui zfoWbqMmr0*zH7;IP(lH;4iE_ zyoQc{cXGdN4>Y%f9tF1C)72qvyM|mq&#BM3oQ*Sqo;sx&7K$L2>Qi`Ka?36(-nfi%3 zkxl^vdX(j!qBYG6jJAE3~E}%z9IUg)C(OUC81-%fBM_c<1eoko+_9|L^ z`~}37xPY&Q@0-Wu%iCCMy@v2p>jMe0|s0uKJ5irj&dyQjQKxVKJ%g067RB8H@v?r`*~GPnpF(~( zNBxkbd|ZH`~EpwJ)kG))5$JhfG#9ZgF7_Um=PzrV#jL&U&;&?ru=O_*Awa} z8a}annnpHjfjxv4-ck6FNcN7b*VBq*xs||eQ~LjUxw3CZ1`i?XRO@L0Jq1g9i0DxP zz0v=;n*uK`qoTp1XU`Q4qUUsfgQTgoJ5BT`pvT8ZYn#FMo`IY}FE#T^4@aNAxL;UY zTy9=ET;tadDx&3x-n`EB;uc+;K7pEBTYBg`b?Cj(<0Q|q$491qmd!kzOl3iIFO@(o zMc=utC9K|?S`6@rSv}-%!o~S@-sojj(d-maj8?5CxZtQXyLG2w^ddYI%-|^Wq6!pW zF0-J=qvyxZP<=IM(g8Jx9t89*di3y2kf28qz2KpN)*dbe1)JD=`fQQEN4x;`vdT4w z^K4A3XJ)U8!}eTY0(Dtsz7_)K@Y6HAqJblohT_z@xixx18}&*^pceLUGN2Cd5MAJ0 z4+Bmtl|@CeiKE9b9U9c>IJTN)&swb#r4OK&*6=^>4k}CC45g(WJwHQwfL>Zz^e$dJ zt*4>qpKg;h^0t1>S!4<62+ew;LVQ9Ui8 zM{$Yd0(yqfi=2QSAJt2F40`jCX28xgBp2#g@08Kg2UV&8dKXhN^n$Lf^Es;RY#`9H z+q9u;Ph6maV4is{WgRPpnFcP)m%6oySv_uT3HAnF7E7Oof{T;BO{SA&l;$pU((@`E zkExq;vqUmdhwk-|K#h82md0t@3>|?M#Oxt~TBdp!aDF>+^qSsq%{jKJ-N>mn^tS2V zmPh~N`c)a`Me)q#Wn6!GE`VGV^qdsEpe%Y$?bA-{*VH^xKrb1~0z?B7Z=TISN6Rxm z$hH1P7QI@|bGGK^_;u%8f)6m{#>C;SOVJS{apayuh zNEX5@PlF4(;ljeg`#GmiU+RvNw|Y(gwlY_D>LfqVDNLs#FK~|h#}WT=6~v9t4Gf!Gg|0pK}21uv#=E45#YyVL#)kmKEJu% z&3Mn$I69w3@71ek<2_O1YLrH=aC5}(@m-D~b+vk|!zp5dG_Yd=by*Jx{aB@3D`UPJ*E?F?GgT``)95W;j^@gH zp=#{VE6rE4zsG#O#Q@>H3V}VYTmX2iKkX8zvkD#*ec@t!0l}%8Wjg~-CQuuGX7ygt z-~t-A8B+2V7+gRO=k@KCz}-K)GL0$_z8t@rLaz`n;_ZJb{vM@98oj7F;`gZMIM=&; zbP!#L#1U-V4HhPpnLeE)a&DSL#up+6)u##6+aGY!=84qF2?=|c?7gmL&s>}uQGX3q z&r&#Lr=kBpdW)^O6ngdQ;>@1t)#bCxhTcsvzKz1-%p}nRc@i--qX+VoJ&UPJbYaT` zYCqd^P8Pn@H`4^_t!uN;(Q-(xwroMj;~qmeg*&l%i0Y};!(8vuxhr4&@6p2^9i_92 z$=(2^MqzKN8Q}M5w&Vg&4=&aEGJcPVqKB!T+vO{&0=+pqR3(EC{W$Qv(zRv8-o0;ak9)OFfrU4cWA;bda30#djpjGPAe_-_v&s!$( z`QgjFe|*0B>guq`-+a;C_!v}DuRC<#dT`anbF@S~hFOLzU7*<$dv{{l1yi&DUO*l4 zH+}ZpQ_Ot@B#*OMNG9+Fdswwdy+`Ja-fQpa5!EacO)fm_0rk$ieYkh}{_HS+`9G*f z^EN5?FGqj#<*Wr989w(=K)pHB~aJ?T^58OK(p1}s34PWFiHvfxyc#e}RJjeI5e#XB5 ztx=B+A|N?uGeCffmS_QW-Pz<@0qNFF0_rG-)65-1oS>ftS(JB#kndDo&Wj7RdN2JE$EDUi{ zK+R%VARKA&29Btw*}I8+0qPOYv`lu@3s9*in>}`Ym&ul=`Lvf%H^YZHNxz!snHoARb<)s$~%g=LGWUmZ>*b zlX`a*>|Q+e?(RBkQg1QN#VW;9uPUnLdep-c$@`Y6_Z`WFkJ_6>vI|nYpiOWOm{9kD z7MvmK)%!rW6dtekMGA8U<SwXk-}pG>3;A#?;A;fTddeK^!J#Y1J04Q3(I~nEt{Phw0zT-rQ1;?cpE=WhRwj-QXRaWuA#Gh4F zbjl?n713CLPRn_8jB{C5Gh5;?m_6VJsA3*zxhM-Rl7=pr+ZA zH8bYP5dgi)dNT;xIWK2P3hHn(K=x(<;BT_~G=iJ#fcsjjhNKyws#&D*d(pavbFfb2 zACtRs+>)=ASXl3d@t8{_@@dZhA@<=zpFh}WGeB59@i<*l-LiTLT-lo?#_n}%Z|(Gz zeD*eN_MW63xJR&J2=qgH2+r1%KAbjkK^2^@@Ipf}q}1>BCZ)a$*kqUm8cvas8C1h* zAx?mW>T+TY3#jX&7TP)z&hPkAdzN5ckA0`H8uPH#1L?p$gT^>Nn3Bw_-sgR&Qr{_T zvOxr>$Fv?poF{y`FKd$2iLyo8@eqJ#@e&^F+cq zK`%h;_4Y=?xf|H%Uhmy1w?OJq&7$nflyhJm4(D&iNI7fMhU%5W7J)Fr&h z-tR7>{$7+UYVE?8S6_5yT`-|57g^A|%isWzxvBlJTCj*_2KdP9;M>vIhesDUtM+Sz`t+UV1 zl}#O}BZXwdvq#wlDOzA3PHX#40jC_F(fB=4FNp1>o=zG%mZ`h8*%NQm$yr3bse%^m z5y7l_n0EC6421G74Y-U-F0c>aGm%b<*9iiukPH~X z+w8sNW{(5*)b3>}o~D30((Ki;=zvT4@k|QpzfzC9qj(cg>WQ-n>T%K#IjkmJ)N^f-04DaBQD<&Xc?S+kgfnWh_j^Y`z~$7Fgu2n{;nLIWf|5_` zWP7f3K_Z-D^4JUz4rj6Z-KTd7n=O^qsv%lEnXlJZqo+Eu7tE;RA`Fa?PW#}>-vrc2 zOBS$t9unQuNDI78R_j@Z2w1%jrzD6oA!q{%=NtOD*CH6e^Tv~J zUI8HIQlE%m(U2duU@A`R_Jnyjx!HriIU3ncPc@vA36cwY(iUk~u<2%iI)feyi-rJd zSyVWUixZN?ZT5I@(Ubp_^ehck>NqT)_hu#IJOX<3HxXkQNtlI&3!-NEmZ%rPR#Wdv znokS)Tqn*$1smY9BN-6oa@MB}`5{A2MV;Dlh8<4I$gpTy&r%D(k@f-nAd@Yr;hac= zh$4kqg4kl}-J@to2h=+y*@*-=S230YnmqR7jNIz!%HvVl5J{JsL9T@RDP(SA<%mBUz8)X)$^u?ZbItqbH;plVmtfIKFT?W5}*15K+oD%hiR9z8l3!pRc-C?q1Ys+tSVi-xl>RTlkD zq!{2)8GgONAi~&f`M5ho@9MynFZ&S!V5^gR+n)44f|*6{(!2|1_0+Fd&jqwBr_)WQ z4^06t8+c0$Lj~%h6HZIgdjctfmMgoqv1Tn7Hqyo3b`xv8QleP~Er8}*EgyM@qaWib z!r@~V#agkrrwtJ_GMBS;L@oqSPe$(%&Zl&#<3zfiRELn-5R7ISy7kJldfi^+60v$M z-)UVBT5UYR77kk1*S%Kk0D}Gn54Qubafj+Az1SUG;~TGgN$VmSB<^b9yNOG#d%fgZ zm>eA7e-m*mzq32&UC%Ij$C4@QHI9tvfjhH$>~+F!L$c2~wE}hif-~QOA*9JpLr+Yd z#FCLdxb#4uq%K&>P=kfvWvwUZos`kgdC*A?I)j+##qRc6(Mwz#4}+@|y}s++;$7tK zPTlT7;(L93BkbGlt@FL4=bfN8a2En(H$@K*^3KmJdT4h7k2+U+8cJ5Jvo4YxTumzOhR!!7VXqvk*NJeDJvQ#o5Fclip`p%mwsPD9kwM_PNDjfOxVpp!$(zGo9o2+jq#)XP9GipHY{F1v&B z&~x4ay{LD4)k~tmEq;y9p?B509n1xK+U~?Nb78f{#a^9hLqw0B_37S)TnStqN8W~H zy<%%UNs%>&I_|CAiJ+%tksz6FvdP!}Nhw+C7hcAw6XEdKTZ}JU9J`Cy`A&oj{?hjL zmy2V4cXz_~iaOr;_C=StoAz@BWEK|IKno|c&qn>euYPi7$s|A1>o6?)0&;Y?y1oOdI;eRwOJ-> zw$a;L^@bjISw=byRdklA7Z$-SpbWUIN3q5E--~5!7&}Yo4qw z^%T9s{TGL!BH3ikGJ41Cxlqk2zb`Kvdo+5LtO9l6DQDgS=F3rs0P6AR8GK;QqR0e3 zmS@?3r0#pe(A$P~caP4`g4LU-8Ak8;Slh~afltB13GyUikMOB4FS1jOUoqea8wtz2 z3^+njvhnDt7(*r#PMqm{b3?p(m~N_f!IFl~LxG6Nnql<%#~@GG8!Zq~OFLWAzn~v> zJi$;@Is9;=W2itqzATa=r?btcdMbcx=Gt5NZ3CYyd>RUCy{VdE^bpO$eHIV$*wI-| z?r*X*gbo<>Q+%z*r5-GkEIwO*wd!6C84(! z-MzM4A#GKnJJ)G>R!k^)!0grklFx z(==I;_!iXaS&q7N8ag~Lqc%&e{_~xyQZ3|wi)tnOr?XuBr3Cci{yME5u)|5Kw`^kS zf~M+WfOIHk^axoNx5*cwqxuA^2lg~|LC{kU*F=`4zA3p2nxw9NJ!vXiN*&IhBUgrM zrv+?Y)s>;8sHA+o=eEs4qi6dpwIyz|fH*DBGNevE#YD;oACa^ngtUB%o~Fr~7WsLK z7ebzfPs8Y;I!nWrdRhQi9DC;_?dhuod`MR$4o-tidZJzaA zfTCq)4dwjlQSs79qAaQ`WXeuKPf8Nkhfko)9#eK0AVU;hP;!#!hDe z)EMxTlDDDdA;h)NgfvkW?7a?aJ<%MZ2dii8PM!@*vse^ony|+bxSVztj-Xb`IOdjl zxDWBuV>%6)ofBXB;v=(sEW?S77Kz}rII>M$>*-Q&8*9Ci(Yt`lD{i+vAMX*p!&4c5 z|G0|r^yX$~-q4FL*Cl)!@WW^XmW#koxShE1JW z3XpcMSnCCXmajk^+6|4jdW)uh zQ-(5+op1_zHy?5H^;B+mzRnqXuP)8%tpdHOiZPsZmLvmuROZo(ieQ&ZRnS4Mq1Dhd ztB30&dKVVe@S&me1}vXe!2PX(k2us-QhmDA9nQ{y6ZGOiuPcvtir$v}yV;tE-bY1m z=L>G#yrK72*LuTBoYh=^J$!If)a2oUL#LZM6wK2jgrrXIL*e&-L+@d8*hV(Z)5Av* zv~3pn(=BO;iL$7QgbKKb;XEr3J)by554vjeT?rG;0#@%#=ACnf9(FjjE)v*FcQ{4M zDy7eWi*Oa<3g+yM?z51>%&i`BWpk=je^~gjxx!A)Y29gE^JxSpwE^^C_gI=mTB*aQ zUZ!)QeVrsNn`*{g4EK-T;b)y`-rUIToS_$^`1GE{Piv|yr<-*}k2B6l4xCUy?8sU+ z@l^3*=!Gh{BU-BdwD6$WAbDKy=}J$uwuU41>q!)6!#XbPieC?@vhPZDF2L%wJAI$r z_cqJU;g=h*_x0V*`;V}AtE*pE=L|jZ>sf<65Bh4^gj2Dj-J?s-(Bs`SaVIlRV};;_ ztf5iWs^2YqzrVer>pXn)pkHs1r2sb|31(678u063rH2V8&?`A};VN>zbK50(_lMru z2M7ed|9m4Let->}JM>Tta8KHNsZ*WK1v7YT^Tk?#ODf_w9zFt=J!CGtd=g*iIg}c` zhYJe}-!&hvr9Ji1v>`mg;wgLLQwMu8<7{kiH+IFlaP;EjWr${><_$eeIM+d*IQFc^ z9(yjR-6MOl!jo|+Di%OZy7(c71Q16^UdX9Zh0%i^G@D}ga6nq1g)L?A+0a~BK@Slv z62fWy^>!tYEW~h%<`6xdaEfmMD?MM$T3!kqkP$ml(O&lS{Frp)8!!&d^tOM3tqQkVk#@a9h;WaTha6+~cwj##Dz#5TZ6uUcWv+ zgI>OT`RUUifBfB#{tvB3|ujCIyA8!AHs`jx% isSD^m{OQ5>%G^J3Sw0|FW7|9c0000 \ No newline at end of file diff --git a/src/stories/assets/share.png b/src/stories/assets/share.png deleted file mode 100644 index 8097a370777a782bbe52082a338584d04e62e796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40767 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 MsOkXq$~KYz50#aYqW}N^ diff --git a/src/stories/assets/testing.png b/src/stories/assets/testing.png deleted file mode 100644 index d4ac39a0ced924068b7625735c9bccac7b17f45d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49313 zcmbqYWm6nXvn5Ed0Kt863mQm*F0R2LI4r?~yDjeS3GVLhun^qcZE;vE*e((R+~@rb z_e)px>8dl`GiRixqtsO7aIh$_kdTmY6y&8fkdRQoNJz*S7%2ZCc<=2#{pZlDDSeaq z&)q#f-#t3pJ3jl*?i`)&9G-1&U;YQ~A6@*1Y#*HL9-X|tzW%v=xVX80ettf`zB{`@ zSoVtSAD_QUBb{BspPrsh{@lVYZVnF*udlC< JACFEikIt@6Pfrg{{#;&Oa(xoW z$jG?8z2)QMJAnO<8G%5!2FL!#e{pf~@bI{EczS<-zqxz3dw2@nhaDfoK7IOhdU-oJ zIk~lWtgNiu)YKFh7$~o-et2?m^5^Eige@&CH?|K)UN!M(k|#l^+X&(BjcvKH62ge7Dy;eQ*qb4p7~m)4;h+xxMxvCA7fD;wLx z$E{JZ3G*u(CnqOs_U!XBi}-k zGlLHgCMG62eh;7DALp%vA)an$7FRDWuNxa1U!%V-EG)cs4WO(>Rt_K z*Dj|60s^%3jfRJZS5{WyXPts4Oq>SfeWFtMmln3Rwo(f!UT1rGcz9mnmp(o|ot>R! z4Q-W`m6Hhg{_XnA%uGZ?#QFVEUS8h7*wia*`_+o4zN05JDJwZSdFHIY`p<>k&URd8 z;j5?2tJ?d#iu&&T%KZF%IXStCjU*Ejlg!hTzP>&n5Lj4P`0d-b!^g+h&6)CzBrYy4 z2L}hkt<`d$W22<6KOm0d%cs|`?~*fs9zU87DPhop;M5S z_~x~KzS3cjBJo~&&IsxfuA3j%08>Fly`51aWz4jTF#80Z*ez0 z19+p<_%hNK(~hu3fjV?0L~a>-7x8~j7WLoQ7+Iy@nfkH^{{^M^f>(NaEfA0ZLMiPW zauytfywOAmaM0|Y^qH^drbWJ0BB29%DTCEQ;IvZzUn{y+W=8Q}t>F?cMl+I^Xd*~q z;429r>tYDrsYC(5R}Bvfu@eGTD@UhU43Pvr{-=MKM7K9!^6A@U`FUghXGr+reuA8L4jQ;86;S#PWhRj3Iq7^S!A@Fh(TQ^+4% zgUP>jTsv11rO(6kL|I*~h=t-TPIkMX0r~?jZ3dZx3Byg!YBb;&D!F;K9BFFf1CmtE zKaiIIz?Irur8|4pWBc%32_OS$fX;e#FA>&)rU!C0mtHXWgz%5b(*nUG2R721C;L~sg@7g9>!iC@ zKxmR?Blw*+6%s{TK7)u04(Omk8=u+uP0&VKRMK0SH*Hc)F&vdfZY3&LPIYyr-aS6A z7O(q#p6jdN>Oy!&OfB(M;o%{jkolkw%t9XpWcD`6GAmL-Qw#`9Efp5M%bBsnW z3S+&SB5UQ(Yt*fVi3ju1#LyP+phT!@==E7Mas|(r6+L?Wx}9ONI(&;`s_~iNC=-zd zR!K~SJf=0$B2Xv)W#Wj_cifDN3VR#q3hnTuC}Bla&mTR!FND!$D$Zw!2ImtVX&_dP z|L%S_r%H=8;}&JniwD~Y>MEmsLfOdn;*lKLCzBYZmB~yE(!fF_C7*E8sB4jgGF%X! z*0ufp==W4>aIww6tQQH^q2ZIxI5o}F;ZFR=n)4E%Ve)U`2SSu+D`v%5$W`;tn#<*1 zX1#Fm6leO#@++QN{M^)Y@>2Zus&;gH%lau&30sr0o~qfI^UA_sE$VHd+PNMfQ-R?W z*3C-`HshfAY1$pu;m!oI^(f=2*Zkt`JnU-061~_h!Rw$h$Mn?aRXdrs0R<0H2ERC0h z7H?4++m#)v1Nr%eIlsr@`n*3z5m5V~MlmE^j`K39Bq3N#Nqa`5OTY(63&b6i0}`3& zRr*KF)?dBD&2(*BSDYa(KPKny{iir*g#I~SCoYsn3e{3PLfo8eI#aWT+z_i_Dw?zG z%X<+`fVNxv+T~^;~!gCxNn1} z_fM*j!p*1y#!E`$4jS47XE24^xm@C1zv6i8BJz9wJPu5^9DKnYm?dnEZ{A51e=FL@ z(E)$1`+Rw#poZo~jUL3BvbRED(iCl0;@+BQf^w3Ip3)hkHU7*^IK<; zC9#e8Qa+A7n$MxS-7gGWJv`}p&P}K{@AosTy_ve&_goSf zWz&n$&Uf)~sedMNe{vn4{;vAASi;5`o;D@U&OvJujov{o75}b184`4b(IpVvzq|d` za(}Wvi=EQyXEJ%%TTzPQj}!-mQyiIcYG1E@xiA_Pvf!VlYawMmb}|KMzF>Ziqg^b@ zXiy~ntnaQ}y4>T=umjz7Q9YTOsF!@DI(+sg!3mHR*&1rdQAK8R6VDtIv%X0YS`#12 z&cW};!57_Ry;9RuU^k zPm~E+V5cJAjT)M{IEyRR$z-b8Fr+~;g(QuEil5zVkm86{+eOyx#<4J)L zWrOrS(FY5X=-fmuTr~X`5-YLo4Tgf{0NXk3Gs!b+){3_bv~Df02Nt>eUCg*W+?0 zLbn69Gq28s1bq67unLBj(*yjTAM%?D;p2<&;?8$e@Ab;Kcgbse@-nZVRGscZ%G5~) zc~xx)yHBUr!1Ia$^`CQ6Gd)5v2wbTL?kW?5ZsgoA0EY)jCOD4Iag*Z-oDss^c1bLMpdVJ z#cnOB;drX*B7Uol@fD|CLhYn43$6w{JX%srj!Dy~AFc|O>_(){+P)6=@QdAeRGY6j zmy}NOW5O6IhaSc}p+0=Km2wHGZ-O}+! zByUi5>C6y#b$Q`x7Xzn~VFH6{F8u#EeI_|4TjxBzvw0bE61Y8dfr z+m{Lry>KPoc{obLUIX6KUT4>>0|e`PqK(^Ej4}JS`x7mpFC$bGOj0?KAec}?RkE}2 zhz`KwqHu1+>klR{xO9k%Nq9OmWrlH(T?x4R9=P;&WW?Q^dkGO9Q!16|c?kJVO`>!{ zB6aa{jM!vbY<`mHqT#>-96sv<$Au;mtfb1s^H|=A9t^0gTArp?t(1@8e)0QSp0q{d(@?(ev5A;nv1r*6}D|^R|ij9qFGK{5$MYC3j2~)6$^%FDi&lrwMI7HLwFY`^v_pzUmuOtJ8stErf z5xYHbH=IdGZng-7YQQ{vd|M1_q0hhvA78&Nv&33{X>Om!ZaL;z%Dp%fI+;*O9utc> zvlJ5m#9?>AEK4ar&8Kvru#8mYDgqODEWF{%BUhKS%s`753f~O?*_7M1O#nU)C}hDu zEu?G_3X6jb`NSQMy)2K^t0!SNcP4oTuv_O@d>fmhVVMQl$p8xk(>F+b|fhEQp z`}_v2_dEG8%D+2WXfO*UR;0@fY>4IE=y(xJGlpUj%g-=33rx7=n=SK$#7+(#Iqtaq za_$d44`GGj*H^d=yHIuJY}!WPnl{FPi;1F^SZ!H2j8h^FiYFV{3Z4{MO?Y(xbYQE%f;+ShreE}!AQG-%=3EH2yd z`fz=3fgNT}sOd?BuGP8$V-cs;8}EQELp$1(;e-GO_^(+TYS@Pn*s3$CYtvc~>@#U> zGbuPd;iEWSGwwuDnJp1XA-~B~PRJ4AG>E_?z=r%X2sFUbfIhm`l1*HMo=0>6Q9n4e zpE+Z3HncS+D~gEZ_*__fZHoQB~U^i`V;Od#5q+iIhqAA#mB--HCVTFP%jUFbTVS9SAFe^y>Qzp-}m{b7_4 z>)1pJ_A0>yXFcY+L*hIv@WI$5=k@)<`< zCV^s)iE!lGXYo1!`;8&qN;8sM$CCM-TPlN+0F!^A+xS?DFo}p7x*Z<>_;T!Qi1p#} z?8A$Hc9$~SufrKizzb(fH4Bb*U@k*4bEJ$m39#g`SOlC^eezRI^~mhMoojiLgH3s7 zBz1Yq@N}Nu1?n2s%%;VAz2S4MZc02GW1R2+6B02&*7NPc7YwV`>{@KE z>X$fZP{HQLZ+hppTzf$RA7VhB+s|OnJ#x$@MtCXHOUZlif?TIwjyU8{?>DNu>^uNBrz@d>jXA)? z`DKVi;s!tozq+4sJ}C;w{0B++MB$em6Co9 z=UVBO1(g7MJ@FeMKqm+lhCl+IfmzBeXQf|@qy(ov2{`g={Ic}^P!-aOYu)f{!LHOK z|F0bKK9Ge`r%_s9JC?GBl=4jPmotRKT!6{vo3^K*k4wLG3^sA$y^QukMdiKr5B9O- zLF<~Ozvez%|Jo=Fe}nYmL7@jp7X|0Yr>Aop(5f<(?C_OthSQULj0FzhYWo!xIIYCG zAtzi#9c9u9*}JiOcI;w(0FSFHuu}sbDJq1gAPokj@c@;YvVr`&#TIN~jhs2E>L)Tq zMlpM+YiGxn*^-rwR@gpTow?9yjSEsq?^>lsBp)@yK;6rO&T){S_7dx}SL(8f>m5-^1r^A)Jj23zNlmbC8R6ytvk? zV+23`PK=lt8FiR5ypoy0;D34gtuPS-eJA=($WRw;E^7o0#Yc_CGD7V(xMupz={#(R zP?{oTs%gQ8#t3L}ZYI6-l)!WGm-+8_ILH~E&4UVH{P^WyNph`r0{GodiM*pew=j&= z_7O~c_OVWP+9eg(F(LH^!i=Y8-0_Flw#o3;!hB?<<)aJSjAQ#ha1yPqI-;VIo=`Csb5Y$9>E$6o@v>ur{949kXC z`MhpC=xG%S^#jI=SVfJm|t;BCjNs4zP9cY>Bt7sNj?0>WmBan^Phy%xi0Z z?bg+we-ZDJOZw2rV<9_bSzSiVwcyXT8CD`E?{F$F4r)Ff9Uk0;15e81kJWBxaVT~Q8c z+Oq8HczxF=;1-eNF+B@>t2qe3LxEG}AD@>Z(Cd_niJc^G*t36SFM_bFd#)(8bLILs zTWZ`~m2N~y57z5)BC{=?cPelV{9a2$rHM#_8$esw<|NA6a@;ztktPY z_0GzkUAG$hgqD%`3>qN}%PUe1dym1fI z!BtBG{R8}S`xn_=i(pTB>prS09Ji4&6$VB#zND+>?JN_Wfc9;s_^?}SpsMDyN&Qr9 zD*iH|xG_gcvwYU_7Tn)yee|D5k-;%)SI#DEC(U?jmMM)Q^*S%V72tDYg|=A&t>Vfg z^;WU&@y7@o5?_c6?Q|hJ**m{hhTvK3SB8I`AbdE1A5K(zmkG5V_ke}!fVy0|1%>xl zh-JZ4u&0Go9@;SA_XgX{M&VNMBw>r*swTG^1x{E2&=RT%_`0CgBYLZY}L+- zzaPm%!U@fG(x^mnVb%=Y#sR0TOyI&5BLILFm5|=*#_Q7}XjGT3d?T zS3V(+-V@YP?P>ve+WW^y@}g!VB^Uv?4sOl^N$$KI>I%Lvxu@)*dOh4z$F*BybWW!a zp^ah>{K#p4XO(9EH<1xx68at;HaCMc#KFjQMUNVTzvkBW8K*^0l+&PMLY(pCY#|(* z(3-q(IP7t8YWKWR9mk4bL?VbWrXBc*@m(9kv3BNfO4j6j>x$HkjngOE;N!-0QN8>K zWeY-<3ePpx0l@?Yg{DLkE4?bN`cmlm$vJa!ONM2Vw%&<;VEA}Rlevcca89Fh@}^MT ziV=emcf+~!o6o9!z|&OfO=_~XV|~(fg{ILqvQ)4V;Cdva>_X#`!T}F9b<96~=Du2< z$&^7qWf}@pXnyY89pdbxbqhA2Ay2-4xG|ZjVRajIGyJ(`Vxs< z%$XmVA~|ilkIC*VdCSFK68Ep`%aWpml$fgRP=*S>Jai zv5ex~couxHo?2az;>`QoowM0!3K{10z)2qJj!|KDq7l(b3j=z+6dqSs$$}h(jO5Us z16=E^GcELN_IA;3rj#}X>sCPFga;XO3#I86^~plKS$iDFB&1Z}th$#tY+izaeOn45P25TfBH(@bNis-o&&VI z`9*XEX6|ESoBp+k*rV@+Qs*BZNg2ihqGx4P<&M0*f1a+iPGNx0la%p@12=?-!ZaEpC{FaP^T`a&N68H-|lDd2x zB--5CzO`tusYrdE0YG%=Se^^7hikJkrsNi|V(pO^+!x!!=i#9tN@0*~lLEh!Zvj(X z7mpSJu>dGY&R*rsv6CprEC=?L?otu9_6z;_e+#yx(iRHU)ceA){`22Q$J!Bt$;1^( zN~5}+Efvc#`wdv%3nQ4vxax}C-2TNAo;<>jcQnwB(H@xjG!zIWsKGW|ivdQAZGuiO z@*`}zMg9MBY{;9xks5%e4}}G013bs)uTHija*qR|axVj%`%f-?FAo$BcKGK)N-A$u z^S)ITu{?^+nK_#PB-W&&311)CqkRv29>zUzu5D&41i0m9w4F?!ISx7A0@o(VubC4V zunPqWcNZ>vAo@PcBL!}M5O?dy4E`4vg1hyNy4Gv?xgTa>VrNcsgv?7r7MR){8qDNkOVjMNnAd`NJmda_Ha zYD_yE{FZwx8vn~g_k)BcA+Aa7UFCt?(cnRCo4Np#&My}9D&QZxN?t}rPhX_~VxZn? zi59VC7fQ~_v3ChfYXMXPQ;@7d$}0Q1AL05Wo7J`=ktOP%J{bj}{m>q$|6we3r`FLo zm+gnd;>o!NT)^h|l$N}CbfC=K7V;|xRRFWF90`o)$R%4hS#$ChLLD-H+bV}|#I;fo zRCBjm`oVSP`_D(0aS$$6P%yDn8;+;33^%G$t~1EukpInbxatl2VL&)EfY51LUNfSd z7Uj*9d9j41xc#i_wPltM7j1l-0?EmWL9O;mYdRX;@lWJw(zHTPa}ppGG`Cbwq$J^n zhIraW92GmxyV3#ILCa#aUQiS|T4ZDl z3Ga*eof2@S6|vB<6j+6;8n103ysReXP%*h11xjz$Be?w)e`i#Lcm_kYFL2PLWo>8^ zDJ5;pas|`Z_)vkDKCp{~PcFam3L{cp#oz){1nBr!{NW(WS0$d&n!Pvw_Zh<=3% zY^@5yI5nTI=FdPi$4??{GoG3!iaNha+Wwq(L0x+u7boLrHrGVoC#tw`p<1L1 zXHNmYE4Nly@O6%b?ukj@8J*smsBP{e+qC|=&`cw5*AS1JiK$|=wVgrhB*?Qml9I#GvJYD173fr*ry)4`Pqj`MCrPKtsC(k%{LoS-9 zvug{SviwohBK}2Kudd)MC&}`S_vLTsBP=X=ekFOnPQ+Q{vm3&YvGwa=McT<cRt5H;DhT$XV;^6Q=h!ZGk{0+_j+NqC4>Sh2XqxCsh!LPVd<@7{DK9!Nr!{>gK zImK50&m2qNHvvo^OC74}Z`r?{ywkwOe-W_$EWxJEdU^{J)W5@x%h-DYrMU%s%V25f z2Gqy&(id)1Vq3mmK&5j?H`rHM&93$LJYL{2iQg88G7|(K@kfDZDs1UztXraWpG#;N zoFR6wNZmm;-i;TM)Z>-Ofv!a)f9v~PxyGefLZ;b}r}Y9Qd6N)o3bMegJ%o9HBH!Z{ zV!ZXeQ?T$0Jt16LElqUI7EADwZpsDkyg=)2mz;dsleP~1t|u6jTE^1mDLA`+gkE!T z*{DIo+an6=Wb2;fohjC9^fmK2$ITQUA2_Oj7}l@;cOrfMc=&~MW2|abXWkt)@pxom zQ*#gfqI!|DdFv9?8T!_78-)Jf?imYK$Z9BT?L6CtB$4I3B{G+E9fR*euxVKo zysAx7g+1QrG{}awh#?TS60((4zM!1%U?Ps{3urHjvAb^R@8zFG@g=+i%Y0H|9e9+2 zLwoEUdQMs_$p3pisR@_eQ*w3;efs^w2-SR()0SDym=oWrFj48P^ZGPh8TY>r;JrIW zUs#hqR!ThGEI&m85}+FjF@@x^d?Go~yS&uZFS08+H3#n-Hwbn^Io^VqXLt+CQzmUr zTNS9+b1^fr>-{s@X%U#E3ORPaL*88FM0llCvxcv(xnR}ZuS}l3DAo7cj_q%lf6W9t zC!nZwImxBU-<0`X`P>;>^#M6AXAlq0;~A519)nWhR@-`OPsiC`6Vvu&p(etpyY z17j@sQ2T6fOl?WSpcuW3x4|nfV+2)B)o=105#@!(O_(W(k$BE=6j#1>S4utqJ3x8C zmD8QgrMm`$H=E=&k}th!thH z0GLWQv8pe1K%Vrzp?Hak(oi(osE%ubH*6mJ^4HK4r+qUz-03tl`}I&3c4QL&oY)k} zdvJ39W7-T_5ftX1W3sOoTLV7-5QhmR84GA4_$obxjDOBJK; z6}KFkO0Foq9Ev}(HWnqf1X`0$8aoKHjdZFh9_@B22#}-oE{5fqqoHE3HJQC2s z?#Hn|WQ~yoTbDjq{dROFo8%Un>X*qTgLeq}g?V%4?fk5bSSR_~eR0s>`R_%rK-Bh4 z*z8=PhYJRBFI~1kHbWN^k~DTThiSn`sv~!nfFw&NJIgvgRvi` zxd?~92pw=OC(&20TT)3XpBgjR_|trEtjgTE%u}ORqw6k{OHj>srxRf0yK$q7p(?#C zUC>x2HremLIq6ve=PkJZlQCds%$Ba?>@8Cc9x#>slWi+Gj^&%UV#?N=N&PJ>ci(7z z_ow~ol3iPsd0+u<`BHzP#Xgl7wvjTk-0DZ{lH+WFkBdt2R8bAQ$YT__Eu$S0@!nMf zmEDtFAegB;OQfp9qOJ4Als8OO3<&;r=i{>}KNyScov%vDw`xk_KA<-PuJMc%1~MGc z<}z{*CRUVJs>}Z(*`mTb@#3Sj@i5AOj|_cpVpD43NWHCu7O(uls}H0!7j#XsL#s)P zqxC`Uym~?IEUJlLH3>PYc`;Gg0B(Rw>|nTE2(iOf{?jUsp1whI00{%WWU zdQ3Bmu1bx{z_c0cbBYgD1h{WTDDxvMy4PAquhI3W@4tTw);yrs4P7&0boH<2ADO6@ zeJ0$cw0O|8htizYKYVE&%Py-Z(MtgT>^qs`tFCxjtd1bO#QS{tK5-a;FcQk*1jAW( z(UnGN<0(Shudsrm1)_KazPtYjg5eDE@T)U!c8i%((iG}$PfUlA{~m~KeRo$XI*?%{ zlSJG>PKE@cA9s-cZI~WkU@|4IKUr^D-9TT7NqozZ5SI86V^G+vSeL;=xB^)<0&tvd zN1V|mJ+9+IM85n{*OL%dVxf--#(S>f3`t~6`0U~|s>EuavPXa~X;SlmB{feWL4%_3 zQ;hq}s+}=Qr=C+ugZgNo2mSBtK1U-*m%Ma%pK6Cn!WlVRRV1Ne_E+3CX(ciByKw?V z_9XjO&doezU~+852l-&BDgM(qyI8!J4R&8^eXU!BRBxutkabkt>YTeUE57_Ie^QwF z*;=EDC-GaK6KQbvN~b&PcK8MMQ4~exj3LTj>|CZGl%SILK?;UaUnL`%{K(6Xq*PS# zx^Ymo3-H5Z{A0H5gLy+iX!vK|VKYTa(SkKnu7jAf`#c_(uivBGLOO8}t*791C~q^{ z!kJC0p%|Pm8!I=Air;(nbmAFr_b)meKpKMp_f(x4>5sj-dA;r9&PVdcgl+Vn3lki& z0H-H+@~voCehb3g9-JI0G8&1jZMNx6^$zF**C^Z z7xyA>wV{s@xT;uI2~ITy-SNx4XGzS)M=sono^5DQiv7TbkbNeQ?3aJgoAz1tFP|&k z2tzP1tv2hb9p@keMTcRoEZK>swlAaoKkAeeKXbwL>!L_?yscksOI0i$|FMcX9b0Ri zQk;&JqPo|g$CW*5L!>NQn=F1z2ohFO;WsWZCvAy=EX8}sKK*G-v2PLF#Sy?OH?*v# zII+Sso&U#nqyOO=b%7&1|Cya|&gV;41~Hn7?&1Ydib>SH#ZbiEKb){SscCt0PbZH0 z;ACLmlye!)O<+k-qoZ#dB*@dthGa@A)f!wU?{rM)O7MA6TQZ(jLEb2If>q^;PJ*sA z3*VZ!jwX|d-#6Nd>xvBVi$p9-KR!w~K`4J7m3{Wlcg%HU$$uVj0arrtk)i?wd`2JU zcuL}a|CdYOkrR{zK&K{IZ#TY*8Fs(q_!)VF%Tj9{iA0CG_TIK(#5se1fPmdXMszrL zmeqf6C>9_m|>-e3f!Om!;v3O}*#&;7} zgeyvcGJ-N4ytW8@vY6C2GIlDVr|*^|1!Ith|B_Kq*K9ImYn!IuR75pZ-%}pQ?-!RY zME3PcCMe3ri9LB1u;caJoH+Av?J&T8Eh!l`iFkGnkc&$Z88nO$nptLab|#atFr=O_ zX$!FG#O^=oh9X_usE-cf3^l$uy?S{@h#q(6mfZ4gDSw3v5B2b5knAgP9cyn{)W{0a zO9^h9Obztt=l|s3gjuP}9t4s7z!MSFE&0Y{TeLm5q`A{d1$)p)$R+ zKEtNfRJbm(7UOy{5bJXdv1&&wmGqJbNc5`!61)f>f)CV(qdD`H8}E#b=Zdskd5&lL zVA$=hUmQ&gbxsVUooQ;Ew0x%Ye?(Fgdw(EuqSyQV5WuVGtsGAZP1;lmT1Ir&9-S~N9|rs@RSJ_(@+1+u40pHC6pW@fIKh+Yuhu2@ZVlU|X6wj4 z2s4)`|LGWpWAUY_%_6#5Tc&{XNB0x~k=aGPznTU6h_?RrkwTD%QnS(r`o?i5tKe-; zfUdl&Mk!k6>Nvz@bf0k^3rw#3Jt~*+ z;5mqunCLT$wO_1d65r~aH?zl7Nt&bN48>LY5sB9AgH#ydHu)bisR-A!Xp_r=rY8g! zXY754Wb+ww2WVOay7dkXBlFqm;Ze3`B!jZpE)(g)n#jK)%^MQWoUM*o z!%mqEQ2J{7X@{^uM?bBbbQ21TJfjc*0(7@BGZHT~pwsE&j2e3Y z-EF1JnoTR1&rfqroghAvTRVyMpojDoJM=+E2MTVxIt)m8^mAaTbQ0W4?&eL1y^{fc zNV{*@jb;KgV?wxk4_{oKig3h3po4WIEupiImofSqa#*x{)pO zB}+kng?FF>2Gv#d-XGzOhYCy7<(UckbWoWsy!FIzF@SW4_Op5u65LkY;@k>c?dSqGmL5c4|CH$_GVptth?nfV zA9mr*Vtf4?FNALgXxrVfio?nE!L%d!#WDee&IrjR$+!%bge|T)A4u|YVaRwC)7NAj zQ?{I*1PQ8iBPuqRew}Mvu76V8QPymjm-4(lig5g2VZ|whqnTNDW&uTY(%de0*nb#z zv+!q5r97d)NTp_^D#^ubWgiapfh*zN*AGNzhe>M95{YJvyo%u zte^P)!9Jt;3o8gpGq^0(uLjrCXmqDJ1P_3(>cf(m&T{N)9%vN5#;1=zV+V zVazcqxk6H~5gg6^FqHN>bGylxk`nuoPuWUp1+H-3?dG6i5+HJ)>w4MIr)bD6=_N4q zi+1BiB~61=_xkN<NskC<3~lEKdFBF~3)?b&e(IQm z-C3=N<;LE8%i^s5a`!VhtTuVYf7bQlJ|Zt#?A(CW8u&SkuTKx6_8}}=s6dCZN+{d! zYbCZPBQH=D?%(^o33Gc&@+e@T3)$l^@k;sji4d-`w(I6QZ$0%(FEFn%NxfBPkI=V! zDiOaw7kh18*o?^1c`vgSwMS*Qo)iQ=DVYcvqx|7bdJbe7{|F|0M>FxZ44X*|){%0} z*oBn>`AWTdT}XFc6#oxd<5Xv)YT#s@rrZE20nXb26^8@*Ze=S**29oV4Y|X}7d_@A z**Z7)lGf3|z>=xrMpkbC-F(nDd&iXS0h(BWdE`DW3tX_wbY?c126<24b31|=94B1L~3xlBc*%Oz- zQ4{iKJ;+o~ zPT|4B6PEX4Sm!CGd?h?|E?A2`!2mBG=#bu3?zTScKf8>blIC3#93?ize@HYSi-cBk z>vDm!k3k61x5jAPjTSU6$&TNO8i(?vH|KI�B6};G&Xp9}-Hnlio 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

    -
    { void open; } })}>...
    +
    { + void open; + } + })} +> + ... +
    n === 0 })}>...
    @@ -116,28 +124,28 @@ Zero-config FLIP layout animation. Attach to any element that may shift position ### Flip options -| Option | Type | Default | -|---|---|---| -| `duration` | `number \| (distance, rects) => number` | `280` | -| `easing` | `EasingFn \| string` | `cubicOut` | -| `delay` | `number` | `0` | -| `translate` | `boolean` | `true` | -| `scale` | `boolean` | `true` | -| `opacity` | `boolean \| { from?, to? }` | — | -| `auto` | `false \| (() => void) \| ObserverManager` | — | -| `skip` | `boolean \| (render, rects) => boolean` | — | -| `disablePointerEvents` | `boolean` | — | -| `respectReducedMotion` | `boolean` | `true` | -| `layoutId` | `string` | — | -| `onStart` | `(el, rects) => void` | — | -| `onEnd` | `(el, { finished, rects }) => void` | — | +| Option | Type | Default | +| ---------------------- | ------------------------------------------ | ---------- | +| `duration` | `number \| (distance, rects) => number` | `280` | +| `easing` | `EasingFn \| string` | `cubicOut` | +| `delay` | `number` | `0` | +| `translate` | `boolean` | `true` | +| `scale` | `boolean` | `true` | +| `opacity` | `boolean \| { from?, to? }` | — | +| `auto` | `false \| (() => void) \| ObserverManager` | — | +| `skip` | `boolean \| (render, rects) => boolean` | — | +| `disablePointerEvents` | `boolean` | — | +| `respectReducedMotion` | `boolean` | `true` | +| `layoutId` | `string` | — | +| `onStart` | `(el, rects) => void` | — | +| `onEnd` | `(el, { finished, rects }) => void` | — | ### Shared-element transitions (`createFlipScope`) ```svelte @@ -165,24 +173,24 @@ Sequence and parallelize `animate()` calls on a shared clock. import { timeline } from '@ixirjs/pulse'; timeline({ duration: 400 }) - .add(card, { y: [20, 0], opacity: [0, 1] }) - .add(title, { y: [10, 0], opacity: [0, 1] }, undefined, '<+50') - .label('reveal') - .add(actions, { opacity: [0, 1] }, undefined, 'reveal+=100') - .call(() => console.log('done'), '>+50') - .play(); + .add(card, { y: [20, 0], opacity: [0, 1] }) + .add(title, { y: [10, 0], opacity: [0, 1] }, undefined, '<+50') + .label('reveal') + .add(actions, { opacity: [0, 1] }, undefined, 'reveal+=100') + .call(() => console.log('done'), '>+50') + .play(); ``` ### Position grammar -| Syntax | Meaning | -|---|---| -| `undefined` | Append at current end | -| `123` | Absolute time in ms | -| `"+=200"`, `"-=100"` | Offset from current end | -| `">"`, `">+200"` | End of last child ± offset | -| `"<"`, `"<+200"` | Start of last child ± offset | -| `"label"`, `"label+=200"` | Named label ± offset | +| Syntax | Meaning | +| ------------------------- | ---------------------------- | +| `undefined` | Append at current end | +| `123` | Absolute time in ms | +| `"+=200"`, `"-=100"` | Offset from current end | +| `">"`, `">+200"` | End of last child ± offset | +| `"<"`, `"<+200"` | Start of last child ± offset | +| `"label"`, `"label+=200"` | Named label ± offset | ## `stagger(interval, options?)` @@ -191,7 +199,7 @@ import { animate, stagger } from '@ixirjs/pulse'; const delay = stagger(50); items.forEach((el, i) => { - animate(el, { opacity: [0, 1], y: [20, 0] }, { delay: delay(i, items.length) }); + animate(el, { opacity: [0, 1], y: [20, 0] }, { delay: delay(i, items.length) }); }); // Center-out wave @@ -211,12 +219,12 @@ import { spring } from '@ixirjs/pulse'; const { samples, duration } = spring({ stiffness: 200, damping: 20 }); ``` -| Option | Default | -|---|---| -| `stiffness` | `170` | -| `damping` | `26` | -| `mass` | `1` | -| `velocity` | `0` | +| Option | Default | +| ----------- | ------- | +| `stiffness` | `170` | +| `damping` | `26` | +| `mass` | `1` | +| `velocity` | `0` | | `restDelta` | `0.001` | | `restSpeed` | `0.001` | @@ -255,6 +263,16 @@ import { animate, timeline, spring } from '@ixirjs/pulse/animate'; import { flip, createFlipScope, flipFrom } from '@ixirjs/pulse/flip'; ``` +## Public API and controller lifecycle + +The root import and every documented subpath in `package.json` are supported public API. High-level helpers (`animate`, `flip`, and gesture attachments) are the preferred entry points; the low-level exports remain supported for advanced integrations and are not removed without a documented migration. + +`AnimationController.finished` preserves the terminal semantics of its underlying platform. Controllers returned by `animate()` and APIs built on WAAPI reject when `cancel()` aborts them; native view-transition and no-animation fallback controllers resolve once their update settles. Handle cancellation when terminal notification is all you need: + +```ts +await controller.finished.catch(() => undefined); +``` + ## Contributing ```sh @@ -270,4 +288,3 @@ npm run lint # lint + format check ## License [MIT](./LICENSE) - diff --git a/src/lib/animate/README.md b/src/lib/animate/README.md deleted file mode 100644 index 3e5c1b2..0000000 --- a/src/lib/animate/README.md +++ /dev/null @@ -1,601 +0,0 @@ -# `animate()` - -A tiny WAAPI animation runtime with spring physics, independent transform components, and full TypeScript types. - -## Table of contents - -- [`animate()`](#animate) - - [Table of contents](#table-of-contents) - - [Basic usage](#basic-usage) - - [Property shorthands](#property-shorthands) - - [Animatable properties](#animatable-properties) - - [Defaults](#defaults) - - [Spring animations](#spring-animations) - - [Per-prop `spring:`](#per-prop-spring) - - [`springEasing()`](#springeasing) - - [Choosing between them](#choosing-between-them) - - [Spring physics parameters](#spring-physics-parameters) - - [Easings](#easings) - - [Live spring values](#live-spring-values) - - [Motion path](#motion-path) - - [SVG draw-on](#svg-draw-on) - - [The `AnimationController`](#the-animationcontroller) - - [Lifecycle callbacks](#lifecycle-callbacks) - - [Reduced motion](#reduced-motion) - - [Intrinsic-size keywords](#intrinsic-size-keywords) - - [Independent transform components](#independent-transform-components) - - [Timelines](#timelines) - - [Position grammar](#position-grammar) - - [`set` and `call`](#set-and-call) - - [Labels](#labels) - - [Playback control](#playback-control) - - [API reference](#api-reference) - - [`animate(element, props, defaults?)`](#animateelement-props-defaults) - - [`spring(options?)`](#springoptions) - - [`springEasing(options?)`](#springeasingoptions) - - [`cubicBezier(x1, y1, x2, y2)`](#cubicbezierx1-y1-x2-y2) - - [`timeline(defaults?)`](#timelinedefaults) - ---- - -## Basic usage - -```ts -import { animate } from './index'; - -animate(element, { opacity: 1, x: 100 }); -``` - -`animate(element, props, defaults?)` returns an [`AnimationController`](#the-animationcontroller). - ---- - -## Property shorthands - -Each property in `props` accepts one of three forms: - -```ts -// 1. Scalar — animate from the current computed value to the target. -animate(el, { opacity: 1 }); -animate(el, { x: 120 }); // unitless → appends default unit (px) - -// 2. Tuple — explicit [from, to]. -animate(el, { opacity: [0, 1] }); -animate(el, { width: ['100px', '300px'] }); - -// 3. Multi-stop sequence — three or more values become evenly-spaced keyframes. -animate(el, { x: [0, 120, 80, 140] }); // overshoot then settle -animate(el, { rotate: [0, -10, 10, 0] }); // wiggle - -// 4. Full PropConfig — all options available, incl. explicit keyframe offsets. -animate(el, { - x: { from: 0, to: 200, duration: 600, easing: easeInOut, delay: 100 }, - y: { values: [0, -60, 0], offset: [0, 0.3, 1] }, // custom timing per stop -}); -``` - -> **Multi-stop sequences.** Any property whose value is an array of **3+** entries is handed to WAAPI as that many keyframes (2-entry arrays remain `[from, to]`). Stops are spaced evenly across the duration unless you pass a matching `offset` array (0–1 positions) via the `PropConfig` form. The shared `easing` applies across the whole sequence. - ---- - -## Animatable properties - -The following named properties are understood directly. Unknown camelCase keys -are converted to kebab-case and treated as plain CSS properties. - -| Key | CSS property | Default unit | -|---|---|---| -| `x` | `--motion-x` (translate X) | `px` | -| `y` | `--motion-y` (translate Y) | `px` | -| `z` | `--motion-z` (translate Z) | `px` | -| `scale` | `--motion-scale` | — | -| `scaleX` | `--motion-scale-x` | — | -| `scaleY` | `--motion-scale-y` | — | -| `rotate` | `--motion-rotate` | `deg` | -| `opacity` | `opacity` | — | -| `width` | `width` | `px` | -| `height` | `height` | `px` | -| `top / left / right / bottom` | position props | `px` | -| `margin / padding` | box model | `px` | -| `fontSize` | `font-size` | `px` | -| `borderRadius` | `border-radius` | `px` | -| `color / backgroundColor / borderColor` | color | — | -| `fill / stroke` | SVG paint | — | -| `strokeDashoffset / strokeDasharray` | SVG stroke dash | — | -| `offsetDistance` | `offset-distance` (motion path) | `%` | -| `offsetRotate` | `offset-rotate` | `deg` | - -Any other key is treated as a raw CSS property: - -```ts -animate(el, { '--my-var': [0, 1], lineHeight: ['1', '1.6'] }); -``` - ---- - -## Defaults - -The third argument sets fallback values for every prop in the call. - -```ts -animate(el, { x: 100, opacity: 1 }, { - duration: 400, // ms. Default: 300. - easing: easeOut, // any EasingFn. Default: ease-out cubic. - spring: true, // use spring physics for all props. - delay: 50, // ms. Default: 0. - fill: 'forwards', // WAAPI fill. Default: 'both'. - composite: 'add', // WAAPI composite. Default: 'replace'. - respectReducedMotion: false, - onStart: (el) => { ... }, - onEnd: (el, { finished }) => { ... }, -}); -``` - -Per-prop values always win over defaults. - ---- - -## Spring animations - -Springs are driven by a physics simulation (Euler integration at 60 fps from -`0 → 1`). They produce a `linear(…)` WAAPI easing at full simulation fidelity. - -### Per-prop `spring:` - -Set `spring` on any individual prop (or in defaults to apply to all props). -The duration is **auto-sized** from the simulation — no manual duration needed. - -```ts -// Single prop: -animate(el, { - scale: { to: 1.2, spring: { stiffness: 220, damping: 18 } }, -}); - -// true = use all defaults (stiffness 170, damping 26, mass 1): -animate(el, { x: 100, scale: 1.1 }, { spring: true }); - -// Mix spring and non-spring props: -animate(el, { - x: { to: 100, spring: { stiffness: 200, damping: 20 } }, - opacity: [0, 1], // uses regular easing + default 300ms -}); -``` - -You can still override the duration to stretch or compress the curve in time -while preserving its shape (overshoot ratio, settle character): - -```ts -animate(el, { x: { to: 100, spring: true, duration: 800 } }); -``` - -### `springEasing()` - -`springEasing(options?)` returns a `SpringEasingFn` — a plain easing function -that can be stored, shared, and passed wherever `easing` is accepted, including -`defaults.easing`. - -```ts -import { animate, springEasing } from './index'; - -const bouncy = springEasing({ stiffness: 300, damping: 18 }); - -// Duration auto-sized from simulation (same behaviour as `spring:`): -animate(el, { scale: 1.2 }, { easing: bouncy }); - -// Override duration: -animate(el, { scale: 1.2 }, { easing: bouncy, duration: 500 }); - -// As a shared default — all props follow the same spring curve: -animate(el, { x: 100, opacity: 1 }, { easing: bouncy }); - -// Per-prop, mixing with other easings: -animate(el, { - x: { to: 100, easing: bouncy }, - opacity: [0, 1], // uses default easing -}); -``` - -`SpringEasingFn` exposes one public property: - -| Property | Type | Description | -|---|---|---| -| `duration` | `number` | Natural settling time in ms from the simulation. | - -### Choosing between them - -| | `spring:` per-prop | `springEasing()` | -|---|---|---| -| Duration auto-sized | ✓ | ✓ (when `duration` is omitted) | -| Reusable across calls | — | ✓ | -| Settable as `defaults.easing` | — | ✓ | -| Inline, no variable needed | ✓ | — | - -#### Spring physics parameters - -| Option | Default | Effect | -|---|---|---| -| `stiffness` | `170` | Higher → faster and snappier | -| `damping` | `26` | Lower → more overshoot/bounce | -| `mass` | `1` | Higher → slower, heavier feel | -| `velocity` | `0` | Initial velocity in target-units/s | -| `restDelta` | `0.001` | Position threshold to stop simulation | -| `restSpeed` | `0.001` | Velocity threshold to stop simulation | - ---- - -## Easings - -All easing functions have the signature `(t: number) => number` where `t ∈ [0, 1]`. -Functions may return values outside `[0, 1]` for overshooting curves. - -```ts -import { - linear, - quadIn, quadOut, quadInOut, - cubicIn, cubicOut, cubicInOut, - quartIn, quartOut, quartInOut, - quintIn, quintOut, quintInOut, - expoIn, expoOut, expoInOut, - sineIn, sineOut, sineInOut, - circIn, circOut, circInOut, - backIn, backOut, backInOut, - elasticIn, elasticOut, elasticInOut, - bounceIn, bounceOut, bounceInOut, - ease, easeIn, easeOut, easeInOut, // CSS keyword equivalents - cubicBezier, // custom cubic-bezier factory - springEasing, // spring physics factory -} from './easings'; -``` - -**`cubicBezier(x1, y1, x2, y2)`** — matches CSS `cubic-bezier(…)` exactly, -including Newton-Raphson with binary-subdivision fallback: - -```ts -const snappy = cubicBezier(0.2, 0.9, 0.2, 1); -animate(el, { x: 100 }, { easing: snappy }); -``` - -You can define your own easing as any function: - -```ts -const myEasing = (t: number) => t * t * (3 - 2 * t); // smoothstep -animate(el, { opacity: 1 }, { easing: myEasing }); -``` - ---- - -## The `AnimationController` - -```ts -const ctrl = animate(el, { x: 100 }); - -await ctrl.finished; // resolves when every animation has settled - -ctrl.pause(); -ctrl.play(); -ctrl.reverse(); -ctrl.cancel(); // immediately stops all animations - -// Access the raw WAAPI Animation objects: -ctrl.animations; // readonly Animation[] -``` - -`ctrl.finished` resolves to `void` when all animations finish normally, -and rejects if any animation is cancelled externally. - ---- - -## Lifecycle callbacks - -```ts -animate(el, { x: 100 }, { - onStart: (el) => { - console.log('animation started on', el); - }, - onEnd: (el, { finished }) => { - // finished = false if animation was cancelled before completing - console.log('done, finished normally:', finished); - }, -}); -``` - -Both callbacks fire even when animations are skipped due to reduced-motion -preference — `onEnd` is called immediately with `{ finished: true }`. - -### `onUpdate` — per-frame progress - -WAAPI can't call JS each frame, so passing `onUpdate` spins up a lightweight -`requestAnimationFrame` loop for the animation's lifetime. Use it to drive a -canvas, SVG attributes, or JS state alongside the CSS animation: - -```ts -animate(el, { x: [0, 300] }, { - duration: 800, - onUpdate: (progress) => { - // progress is the current iteration position, 0 → 1 - bar.style.setProperty('--p', String(progress)); - }, -}); -``` - -For tweening a raw number with no element involved, reach for -[`animateValue`](#value-tweening) instead. - ---- - -## Value tweening - -`animateValue(from, to, options)` tweens a plain number through the same easing -engine and calls `onUpdate(value)` each frame — for counters, canvas, or any -non-CSS target. `countUp(el, to)` is a convenience that writes the running value -into an element's `textContent`. - -```ts -import { animateValue, countUp } from '@ixirjs/pulse/animate'; - -animateValue(0, 100, { duration: 800, round: true, onUpdate: (v) => (label.textContent = `${v}%`) }); - -countUp(statEl, 1280, { duration: 1200 }); // 0 → 1,280 in the element's text -``` - -| Option | Default | Description | -| ---------------------- | ------- | ------------------------------------------------------ | -| `duration` | `300` | Tween length in ms. | -| `easing` | ease-out| Easing function. | -| `delay` | `0` | Delay before starting. | -| `onUpdate` (required) | — | Called each frame with the interpolated value. | -| `onComplete` | — | Called once when the tween settles. | -| `round` | — | `true` → integers; a number `N` → round to N decimals. | - -Both return a `{ stop(), finished }` controller. Honors reduced motion (jumps to -the end value). - ---- - -## Reduced motion - -By default, `animate()` respects `prefers-reduced-motion: reduce`. When -active, all keyframe animations are skipped and the final state is applied -immediately. - -```ts -// Opt out for a specific call: -animate(el, { x: 100 }, { respectReducedMotion: false }); -``` - ---- - -## Intrinsic-size keywords - -`width` and `height` (and other `measurable` props) accept `auto`, -`fit-content`, `min-content`, and `max-content` as targets: - -```ts -// Animate from current height to its natural auto height, then restore -// `height: auto` so the element remains responsive: -animate(el, { height: 'auto' }); - -// Explicit [from, to]: -animate(el, { height: ['0px', 'auto'] }); -``` - -Internally, the keyword is measured (via a hidden layout pass), animated as a -concrete pixel value, then the keyword is re-applied inline once the animation -finishes so the element responds to content changes. - ---- - -## Independent transform components - -`x`, `y`, `z`, `scale`, `scaleX`, `scaleY`, and `rotate` each animate their -own registered CSS custom property (`--motion-x`, `--motion-scale`, …). -The element's `translate`, `scale`, and `rotate` CSS properties are wired to -read those variables. - -This means you can run two separate `animate()` calls on the same element — -one for position and one for scale — and they will never clobber each other, -even with different durations, easings, or springs. - -```ts -animate(el, { x: 100 }, { duration: 300 }); -animate(el, { scale: 1.2 }, { spring: true }); // runs independently -``` - ---- - -## Timelines - -`timeline()` sequences and parallelizes `animate()` calls along a shared -clock. Each entry is placed at a position; the timeline tracks a running -duration and the start/end of the most recent entry so subsequent entries -can be anchored relative to them. - -```ts -import { timeline, easings } from './index'; - -timeline({ duration: 400, easing: easings.easeOut }) - .add(card, { y: [20, 0], opacity: [0, 1] }) - .add(title, { y: [10, 0], opacity: [0, 1] }, undefined, '<+50') - .add(actions, { opacity: [0, 1] }, undefined, '+=100') - .call(() => emit('opened')); -``` - -Timelines build lazily — the chain above just describes the schedule. They -auto-play on the next microtask (so chaining stays synchronous) unless you -pass `paused: true` to defer playback. - -### Position grammar - -The fourth argument to `add()` (and the second argument to `set` / `call` / -`label`) accepts: - -| Position | Meaning | -|---|---| -| `undefined` | Append at the current end (same as `">"`). | -| `123` | Absolute time, in ms, from the timeline start. | -| `"+=200"`, `"-=100"` | Offset from the current end. | -| `">"`, `">+200"`, `">-50"` | End of the most recent entry, with optional offset. | -| `"<"`, `"<+200"`, `"<-50"` | Start of the most recent entry — useful for "fire alongside the previous". | -| `"label"`, `"label+=200"` | A previously-declared label, with optional offset. | - -```ts -timeline() - .add(a, { x: 100 }) // 0 → 300 - .add(b, { x: 100 }, undefined, '<') // 0 → 300 (alongside a) - .add(c, { opacity: 1 }, undefined, '>+100') // 400 → 700 - .add(d, { opacity: 0 }, undefined, '+=200'); // 900 → 1200 -``` - -### `set` and `call` - -`set()` writes CSS values instantly at a position — handy for "reset frames" -between sequenced animations. `call()` fires a callback at a position. - -```ts -timeline() - .set(panel, { opacity: 0, y: 20 }) // immediate - .add(panel, { opacity: 1, y: 0 }) - .call(() => focus(panel), '<+50'); // 50ms after the fade starts -``` - -> Callbacks and `set()` writes fire on their original schedule and are not -> rewound by `pause()` / `seek()`. Use them for side-effects, not for visual -> state that needs to survive scrubbing. - -### Labels - -```ts -const tl = timeline() - .add(hero, { opacity: [0, 1] }) - .label('reveal') - .add(cta, { opacity: [0, 1] }, undefined, 'reveal+=200'); - -tl.labels.get('reveal'); // → 300 -``` - -### Playback control - -`Timeline` mirrors `AnimationController` and adds `seek()`: - -```ts -const tl = timeline({ paused: true }) - .add(el, { x: 200 }) - .add(el, { opacity: 0 }, undefined, '+=100'); - -tl.duration; // total ms -tl.play(); -tl.pause(); -tl.reverse(); -tl.seek(150); -tl.cancel(); - -await tl.finished; -``` - -`tl.animations` returns every materialized WAAPI `Animation` if you need to -hook into them directly. - ---- - -## Live spring values - -`spring:` and `springEasing()` bake a fixed `linear(…)` curve up front. When you -need motion that can be **re-targeted mid-flight without losing velocity** — -drag-release, pointer-following, rapid toggles — use `createSpringValue()`, a -continuous rAF integrator. - -```ts -import { createSpringValue } from './index'; - -const x = createSpringValue({ stiffness: 220, damping: 24 }); -x.subscribe((v) => el.style.setProperty('--motion-x', `${v}px`)); - -x.set(200); // springs toward 200, carrying any current velocity -x.set(0); // reverse mid-flight — momentum is preserved, no snap -x.setVelocity(800); // seed a flick before set() -await x.finished; // resolves when it settles -``` - -This is the engine behind [`draggable()`](../gestures/README.md)'s release momentum. - ---- - -## Motion path - -`motionPath(element, path, options?)` moves an element along an arbitrary path by -animating the natively-interpolated `offset-distance`. Auto-rotation along the -path is on by default. - -```ts -import { motionPath } from './index'; - -motionPath(el, 'M0,0 C 50,-80 150,80 200,0', { duration: 1200 }); -motionPath(el, 'circle(80px at 50% 50%)', { from: 0, to: 50, rotate: false, spring: true }); -``` - -A bare SVG path string is wrapped in `path(...)`; any value already containing a -function (`path()`, `ray()`, `circle()`, `url()`) is used verbatim. - ---- - -## SVG draw-on - -`draw(element, options?)` animates a stroked `SVGGeometryElement` so it appears to -be drawn: it sets `stroke-dasharray` to the path length and animates -`stroke-dashoffset`. - -```ts -import { draw } from './index'; - -draw(pathEl, { duration: 1000 }); // draw on -draw(pathEl, { from: 1, to: 0 }); // erase -draw(pathEl, { from: 0.2, to: 0.8, reverse: true }); // partial, other end -``` - -Like `animate()`, it accepts spring / easing / duration defaults and returns an -`AnimationController`. - ---- - -## API reference - -### `animate(element, props, defaults?)` - -| Argument | Type | Description | -|---|---|---| -| `element` | `HTMLElement \| SVGElement` | Target element | -| `props` | `AnimateProps` | Properties to animate | -| `defaults` | `AnimateDefaults` | Optional shared options | - -Returns `AnimationController`. - -### `spring(options?)` - -Low-level simulator. Returns `{ samples: number[], duration: number }`. -Useful if you need the raw curve data (e.g. to drive a non-WAAPI renderer). - -```ts -import { spring } from './index'; -const { samples, duration } = spring({ stiffness: 200, damping: 20 }); -``` - -### `springEasing(options?)` - -Returns a `SpringEasingFn` — an `EasingFn` with a `.duration` property -carrying the simulation's natural settling time. See [springEasing()](#springeasing). - -### `cubicBezier(x1, y1, x2, y2)` - -Returns an `EasingFn` matching CSS `cubic-bezier(x1, y1, x2, y2)`. - -### `timeline(defaults?)` - -Returns a `Timeline` (see [Timelines](#timelines)). `defaults` extends -`AnimateDefaults` with one extra option: - -| Option | Default | Description | -|---|---|---| -| `paused` | `false` | When `true`, the timeline does not auto-play; call `.play()` manually. | - -All other options are forwarded as defaults to every `add()` entry; per-call -`options` and per-prop config still override them. diff --git a/src/lib/animate/core/README.md b/src/lib/animate/core/README.md deleted file mode 100644 index 0da9be7..0000000 --- a/src/lib/animate/core/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# animate/core - -The animation engine — the `animate()` orchestrator and the `AnimationController` that owns each animation's lifecycle. This is the heart that the rest of [`animate`](../README.md) feeds into. - -| File | Responsibility | -| --- | --- | -| `animate.ts` | The `animate()` entry point. Resolves keyframes (via [`../keyframes`](../keyframes/README.md)), registers transform wiring (via [`../properties`](../properties/README.md)), starts the WAAPI animations, and returns a controller. Handles the SSR and reduced-motion fast paths (apply end state, skip animation). | -| `controller.ts` | `AnimationController` — wraps one or more WAAPI `Animation` objects behind a single lifecycle: `pause`, `play`, `reverse`, `seek(ms)`, `stop` (commit current position, then cancel), `cancel`, a settable `playbackRate`, and a lazily-built `finished` promise. Owns the `onStart`/`onEnd` hooks and inline-style cleanup. | - -Because each transform component animates through its own `--motion-*` custom property, one controller may drive several `Animation` objects at once (`controller.animations` exposes them). diff --git a/src/lib/animate/keyframes/README.md b/src/lib/animate/keyframes/README.md deleted file mode 100644 index 230d081..0000000 --- a/src/lib/animate/keyframes/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# animate/keyframes - -Turns user input into WAAPI keyframes and timing. Given the loose shorthands a caller passes to [`animate()`](../README.md) (`120`, `[from, to]`, or a full `PropConfig`), this module normalizes them, resolves timing buckets, and builds the keyframe arrays. - -| File | Responsibility | -| --- | --- | -| `normalize.ts` | Expand shorthands into uniform per-property config. `normalizeInput()` parses the input form; `resolveTiming()` derives WAAPI timing, including sampling a spring's duration. | -| `keyframes.ts` | Resolve `from`/`to` endpoints, group properties by shared timing (duration / easing / delay), and build the WAAPI keyframe sets. Measures and restores intrinsic-size keywords. | -| `keyword.ts` | Detect and measure intrinsic-size keywords (`auto`, `fit-content`, `min-content`, `max-content`). `isAutoKeyword()` identifies them; `measureKeywordValue()` forces a layout pass to resolve concrete pixels. | -| `easing-utils.ts` | Convert JS easing functions into WAAPI `linear(...)` strings, cached by function reference. Spring easings carry a pre-built, high-fidelity string. | - -Spring sampling and the `linear(...)` conversion lean on the spring core in [`$lib/shared`](../../shared/README.md). diff --git a/src/lib/animate/properties/README.md b/src/lib/animate/properties/README.md deleted file mode 100644 index 73cdced..0000000 --- a/src/lib/animate/properties/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# animate/properties - -The property registry and transform wiring. Maps animation keys (`x`, `scale`, `width`, `opacity`, …) to their CSS targets and manages the `--motion-*` custom properties that let transform components animate independently. - -| File | Responsibility | -| --- | --- | -| `properties.ts` | The static `PROPERTY_REGISTRY` (50+ props) mapping each key to its CSS equivalent, default unit, and initial value. Transform components map to motion custom properties (`--motion-x`, `--motion-scale`, …). | -| `prop-utils.ts` | `formatValue()` appends default units; `resolveProp()` looks up known props or kebab-cases unknown keys into raw CSS; `readCurrentValue()` snapshots the computed value for an implicit `from`. | -| `style-utils.ts` | `saveStyleProp()` / `restoreStyleProp()` capture and restore inline properties (with `!important` priority) around temporary writes. | -| `transform-setup.ts` | `ensurePropertiesRegistered()` registers the motion vars via `CSS.registerProperty` for smooth interpolation; `ensureTransformWired()` injects the `translate`/`scale`/`rotate` inline styles that read those vars. | -| `transform-tracker.ts` | Per-element ref-counting of in-flight transform animations. `registerTransformAnimation()` / `deregisterTransformAnimation()` track active vars; `measureWithoutAncestorTransforms()` temporarily suppresses ancestor motion vars to read at-rest rects. | - -This wiring is what lets two separate `animate()` calls (or a sibling [`flip()`](../../flip/README.md)) touch the same element's transform without clobbering each other. diff --git a/src/lib/animate/timeline/README.md b/src/lib/animate/timeline/README.md deleted file mode 100644 index 04c149d..0000000 --- a/src/lib/animate/timeline/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# animate/timeline - -Sequences and parallelizes `animate()` calls along a shared clock. Backs the public `timeline()` factory documented in the [animate README](../README.md#timelines). - -| File | Responsibility | -| --- | --- | -| `timeline.ts` | The `Timeline` factory. Builds lazily — the chain describes a plan that materializes on `play()` (or first access to `finished`/`animations`). | -| `timeline-types.ts` | The public `Timeline` interface (`add`, `set`, `call`, `label`, `play`, `pause`, `reverse`, `cancel`, `stop`, `seek`, `setPlaybackRate`) and `TimelineDefaults` (extends `AnimateDefaults` with a `paused` flag). | -| `timeline-position.ts` | The position-grammar parser. Resolves a `TimelinePosition` (`number \| string \| undefined`) to an absolute ms offset: absolute `123`, relative `+=200`, anchors `<` / `>`, and `label+=N` references. | -| `timeline-internals.ts` | Entry shapes (`AnimateEntry`, `SetEntry`, `CallEntry`), `computeAnimateDuration()` (estimates total time, including spring sampling), and `offsetProps()` (injects the timeline offset into per-prop delays). | - -Entries are placed by the flexible position syntax, and the timeline tracks a running duration plus the most recent entry's start/end so later entries can anchor relative to them. diff --git a/src/lib/easing/README.md b/src/lib/easing/README.md deleted file mode 100644 index f418389..0000000 --- a/src/lib/easing/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# easing - -Easing functions for animation timing. Every easing is a pure `EasingFn` — `(t: number) => number` mapping normalized time `t ∈ [0, 1]` to normalized progress (typically `[0, 1]`, may overshoot for `back`/`elastic`). Pass one to `animate()` as the `easing` option, or as a per-property override. - -## Quick start - -```ts -import { easeInOut, cubicBezier, springEasing } from '$lib/easing'; -import { animate } from '$lib/animate'; - -animate(node, { x: 100 }, { easing: easeInOut }); - -const swoop = cubicBezier(0.22, 1, 0.36, 1); -animate(node, { x: 100 }, { easing: swoop }); -``` - -## What's here - -| File | Provides | -| --- | --- | -| `primitive.ts` | 20+ preset curves across families: power (`quad`/`cubic`/`quart`/`quint` × `In`/`Out`/`InOut`), `expo*`, `sine*`, `circ*`, `back*` (overshoot), `elastic*`, `bounce*`, and `linear`. Plus helpers `pow(n)`, `powOut(n)`, `powInOut(n)`. | -| `cubic-bezier.ts` | `cubicBezier(x1, y1, x2, y2)` — build an easing from CSS control points, solved with Newton-Raphson (matches Blink/WebKit). | -| `css.ts` | The CSS keyword curves `ease`, `easeIn`, `easeOut`, `easeInOut`, and the `CSS_EASINGS` keyword lookup. | -| `spring.ts` | `springEasing(options?)` — a physics-driven easing that auto-sizes its own duration. | - -## Spring easing - -`springEasing` returns a `SpringEasingFn`: a callable easing that also carries a `duration` (natural settling time in ms). When no explicit duration is given, the spring sizes itself; passing one stretches/compresses the curve. - -```ts -const bouncy = springEasing({ stiffness: 300, damping: 18 }); - -animate(node, { scale: 1.2 }, { easing: bouncy }); // auto-sized duration -animate(node, { scale: 1.2 }, { easing: bouncy, duration: 500 }); // stretched - -// Mix per-property: -animate(node, { - x: { to: 100, easing: bouncy }, - opacity: [0, 1], -}); -``` - -Use `isSpringEasing(fn)` to type-guard a spring easing. The underlying simulation lives in [`$lib/shared`](../shared/README.md) (`spring-core.ts`) and is cached. diff --git a/src/lib/flip/README.md b/src/lib/flip/README.md deleted file mode 100644 index 78745bd..0000000 --- a/src/lib/flip/README.md +++ /dev/null @@ -1,92 +0,0 @@ -# flip - -FLIP (**F**irst, **L**ast, **I**nvert, **P**lay) layout animations for Svelte 5. Animate elements smoothly between layout positions using inverse transforms — no manual measuring, delivered as a Svelte 5 `{@attach}` attachment. - -- **Zero-config** — `{@attach flip()}` animates any layout shift the element undergoes. -- **Auto-tracking** — a `ResizeObserver` on the element plus a `MutationObserver` on its parent detect reflows automatically. -- **Shared-element transitions** — opt in with `createFlipScope()` + `layoutId` to hand off between an unmounting and a mounting element. -- **Reduced-motion aware** and **pointer-safe** during animation. - -## Quick start - -```svelte - - - -
    content
    - - -
    { void open; } })}>content
    - - -
    n === 0 })}>content
    -``` - -## Public API - -| Export | Signature | Purpose | -| --- | --- | --- | -| `flip` | `(options?) => Attachment` | Svelte 5 attachment with automatic layout tracking. | -| `flipFrom` | `(element, from, options?) => AnimationController \| null` | Inverse FLIP: animate from a captured rect to current position. | -| `flipTo` | `(element, to, options?) => AnimationController \| null` | Forward FLIP: animate current position toward a target rect (e.g. on exit). | -| `snapshotRect` | `(element) => FlipRect` | Capture an element's current rect. | -| `createFlipScope` | `(opts?) => { flip, clear }` | Isolated shared-layout registry with a scoped `flip()`. | -| `createFlipSwitcher` | `(resolver, options?) => { source, target }` | Animate transitions between two elements based on a reactive role. | - -Lower-level building blocks (`animateFlip`, `createFlipAttachment`, `createLayoutBridge`, `createObserverManager`, `createReflowScheduler`, and the geometry helpers) are also re-exported. - -### Key options (`FlipOptions`) - -`duration` (ms or `(distance, rects) => ms`), `easing`, `delay`, `translate` / `scale` (default `true`), `opacity` (`true` → crossfade), `layoutId`, `auto`, `disabled`, `skip`, `disablePointerEvents`, `respectReducedMotion` (default `true`), `composite`, and `onStart` / `onEnd` hooks. - -## Shared-element transitions - -```ts -const scope = createFlipScope(); -``` - -```svelte - -
    Card
    - - -
    Card
    - -``` - -A `LayoutBridge` stores each `layoutId`'s last rect with a short TTL (default 250 ms), enabling the handoff. - -## Switching between two elements - -```ts -const switcher = createFlipSwitcher(() => (tab === 'a' ? 'source' : 'target')); -``` - -```svelte -
    Panel A
    -
    Panel B
    -``` - -`$effect.pre` snapshots pre-update rects, then plays FLIP on the newly-active panel when the role changes. - -## Manual FLIP - -```ts -const rect = snapshotRect(element); -// ...move element in the DOM... -flipFrom(element, rect, { duration: 250 }); -``` - -## Internal structure - -| Submodule | Responsibility | -| --- | --- | -| `animation/` | `animateFlip()` core animator (delta + transform-origin compensation), cancellation, and a single-slot controller holder. | -| `integration/` | Svelte wiring — the attachment (`$effect`-driven reflow detection), the shared-layout `bridge`, the `scope` factory, and the element `switcher`. | -| `tracking/` | `ResizeObserver` + `MutationObserver` layout observers, an observer manager, and a RAF-batched reflow scheduler. | -| `geometry.ts` | `measure`, `rectsEqual`, `diagonal`, and delta math (`computeDelta`, `isIdentityDelta`, `resolveFlipDelta`). | -| `options.ts` | Parse/resolve options (duration, opacity, easing) and unwrap reactive thunks. | - -> Built on the [`$lib/animate`](../animate/README.md) runtime via `--motion-*` custom properties, so a `flip()` and a sibling `animate()` on the same element compose without overwriting each other's transform. diff --git a/src/lib/flip/animation/README.md b/src/lib/flip/animation/README.md deleted file mode 100644 index c6e3fa0..0000000 --- a/src/lib/flip/animation/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# flip/animation - -Transform execution and lifecycle for [`flip`](../README.md). Given a `from` and `to` rect, this layer computes the inverse transform, plays it, and manages cancellation. - -| File | Responsibility | -| --- | --- | -| `animator.ts` | `animateFlip(args)` — the stateless core animator. Computes the delta between `from` and `to`, compensates for transform-origin, animates through motion custom properties (`--motion-x`, `--motion-y`, `--motion-scale-x`, `--motion-scale-y`), and optionally crossfades opacity. Returns an `AnimationController` or `null` when there's no work to do. | -| `cancel-controller.ts` | `cancelController(controller)` — safely cancel an in-flight animation, swallowing errors if it was already torn down. | -| `controller-slot.ts` | `createControllerSlot()` — a single-slot holder for the current FLIP controller. Cancels the previous animation when a new one starts and auto-clears when one finishes naturally, centralizing the lifecycle boilerplate. | - -`animateFlip` runs through the same `--motion-*` properties as [`$lib/animate`](../../animate/README.md), so a FLIP and a sibling `animate()` compose without overwriting each other's transform. diff --git a/src/lib/flip/integration/README.md b/src/lib/flip/integration/README.md deleted file mode 100644 index 867aca4..0000000 --- a/src/lib/flip/integration/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# flip/integration - -The Svelte 5 wiring for [`flip`](../README.md) — the `{@attach}` attachment, the shared-layout registry, and the higher-level scope and switcher factories. - -| File | Responsibility | -| --- | --- | -| `attachment.svelte.ts` | `createFlipAttachment(input, bridge)` — the core attachment. Wires the animator to lifecycle events, detects reflows via `$effect`, optionally syncs with an `ObserverManager` for auto-tracking, and reads/writes layouts to the bridge for shared-element transitions. | -| `bridge.ts` | `createLayoutBridge(ttlMs?)` — an in-memory registry storing each `layoutId`'s last-known rect with a configurable TTL (default 250 ms), enabling handoff between an unmounting and a mounting element. | -| `scope.ts` | `createFlipScope(opts?)` — returns `{ flip, clear }`, wrapping a bridge + attachment into a self-contained namespace for cross-component shared transitions. | -| `switcher.svelte.ts` | `createFlipSwitcher(resolver, options?)` — animates between two elements. Uses `$effect.pre` to snapshot pre-update rects, then plays FLIP on the newly-active element when the role changes. Returns `{ source, target }` attachments. | - -These rely on Svelte 5 runes (`$effect`, `$effect.pre`, `untrack`) and the `{@attach}` directive — hence the `.svelte.ts` extensions where rune syntax is used. diff --git a/src/lib/flip/tracking/README.md b/src/lib/flip/tracking/README.md deleted file mode 100644 index 6c9859c..0000000 --- a/src/lib/flip/tracking/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# flip/tracking - -Layout observation and frame scheduling for [`flip`](../README.md). This is what makes `flip()` auto-track layout shifts without the caller manually triggering a remeasure. - -| File | Responsibility | -| --- | --- | -| `observers.ts` | `createLayoutObservers({ element, onChange })` — combines a `ResizeObserver` (on the element) and a `MutationObserver` (on its parent) to detect size and reflow changes. `connect()` is idempotent and handles reparenting. | -| `observer-manager.ts` | `createObserverManager()` — wraps `LayoutObservers` behind a `{ connect, disconnect }` interface so the attachment can reconnect to a new element without leaking observers. | -| `scheduler.ts` | `createReflowScheduler(task)` — a RAF-batched scheduler. Coalesces multiple `schedule()` calls in a frame into a single task on the next animation frame; degrades to synchronous execution outside the DOM. | - -The attachment in [`../integration`](../integration/README.md) drives these: observers report a change → the scheduler batches it → the animator replays the FLIP. diff --git a/src/lib/gestures/README.md b/src/lib/gestures/README.md deleted file mode 100644 index 896e89f..0000000 --- a/src/lib/gestures/README.md +++ /dev/null @@ -1,149 +0,0 @@ -# gestures - -Pointer-gesture attachments for Svelte 5. Each is a plain `{@attach}` — no component wrapper — and composes with [`animate()`](../animate/README.md) on the same element through the shared `--motion-*` transform chain. - -| File | Responsibility | -| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `draggable.ts` | `draggable(options)` — pointer drag that writes `--motion-x` / `--motion-y` (so it never clobbers sibling animations). On release it hands the live pointer velocity to a [`SpringValue`](../animate/README.md), giving natural momentum and elastic snap-back. Supports axis lock, static or reactive `constraints`, rubber-band `elastic`, `snapToOrigin`, and start/move/end callbacks. | -| `move.ts` | `moveable(options)` — tracks the pointer over the element (no button) and reports its position normalised from the centre (`nx` / `ny` in `-1…1`), for tilt, parallax and spotlight effects. Optionally applies a springy "magnetic" pull via `--motion-x` / `--motion-y`. Touch filtered out by default. | -| `swipe.ts` | `swipeable(options)` — discrete directional fling. Tracks press travel and live velocity, then fires `onSwipe('left' \| 'right' \| 'up' \| 'down', info)` once a distance _or_ velocity threshold is cleared. Supports `axis` lock. For swipe-to-dismiss, card stacks and carousel paging. | -| `hover.ts` | `hoverable(options)` — `pointerenter` / `pointerleave` with touch "sticky hover" filtered out by default (`includeTouch` to opt in). | -| `focus.ts` | `focusable(options)` — the keyboard counterpart of `hoverable`. Symmetric `onFocusStart` / `onFocusEnd` with `:focus-within` semantics (no flicker as focus moves between children), so hover motion has an accessible equivalent. | -| `press.ts` | `pressable(options)` — press with native cancel semantics: a press that drifts off the element fires `onPressEnd(pressed=false)` and skips `onPress`. Also exposes `onLongPress` (held past `longPressDelay`, then suppresses the click) and `onDoubleTap`. Pointer capture tracks the same pointer throughout. | -| `pinch.ts` | `pinchable(options)` — two-pointer pinch-zoom + rotate. Tracks the distance/angle between two active pointers and reports live `scale` / `rotation`, optionally writing `--motion-scale` / `--motion-rotate` so it composes with `animate()`. Supports `scaleBounds`, `rotate: false`, and start/move/end callbacks. | -| `wheel.ts` | `wheelable(options)` — desktop wheel / trackpad zoom; the pointer-free counterpart of `pinchable`. Turns `wheel` deltas (incl. `ctrlKey` trackpad pinch) into a multiplicative `scale`, optionally writing `--motion-scale` (spring-smoothed by default so notched wheels ramp instead of snapping). Brackets discrete ticks into one gesture with `onStart` / `onEnd`. | -| `reorder.ts` | `reorder({ items, onReorder })` — headless drag-to-reorder. Returns `{ item(value) }`: attach it to each row. The dragged row follows the pointer while siblings slide to open a slot; on drop the array is reordered via `onReorder(next)` and every row FLIPs into its new position. Composes [`draggable`](#) with the [FLIP engine](../flip/README.md). | -| `constraints.ts` | Pure constraint math (`applyConstraint`, `xBounds`, `yBounds`) — clamping and elastic overflow, DOM-free and unit-tested. | -| `pointer-capture.ts` | `capture` / `release` wrappers that swallow the `NotFoundError` thrown when a pointer id is no longer active. | - -```svelte - - - -
    - - - -``` - -### `draggable` options - -| Option | Default | Effect | -| -------------- | --------------- | ------------------------------------------------------------------------- | -| `axis` | `'both'` | Lock dragging to `'x'` or `'y'`. Sets `touch-action` accordingly. | -| `constraints` | — | `{ left, right, top, bottom }` bounds, or a thunk re-read per drag. | -| `elastic` | `0` | Resistance past constraints: `0` = wall, `1` = none, `0.2` = rubber-band. | -| `spring` | spring defaults | Physics for release momentum and snap-back. | -| `snapToOrigin` | `false` | Spring back to the start instead of staying put. | -| `momentum` | `true` | Carry release velocity into the settle spring. | - -### `moveable`, `swipeable` & `focusable` - -```svelte - - - - - - -
    animate(el, { rotateY: nx * 12 }) })}>
    - - -
    dir === 'left' && dismiss() })}>
    - - - -``` - -| `moveable` option | Default | Effect | -| ----------------- | ------- | -------------------------------------------------------------------------------- | -| `applyTransform` | `false` | Apply a springy magnetic pull via `--motion-x` / `--motion-y` (report-only off). | -| `strength` | `0.3` | Magnetic pull as a fraction of the pointer's offset from centre. | -| `spring` | — | Spring used for the snap back to rest on leave. | -| `includeTouch` | `false` | Also react to touch pointers. | - -| `swipeable` option | Default | Effect | -| ------------------- | -------- | -------------------------------------------------------- | -| `axis` | `'both'` | Restrict recognised swipes to `'x'` or `'y'`. | -| `threshold` | `30` | Minimum travel (px) to count as a swipe. | -| `velocityThreshold` | `300` | Release speed (px/s) that counts regardless of distance. | - -`focusable` mirrors `hoverable`: `onFocusStart` / `onFocusEnd`, with `disabled` to opt out. - -`pressable` adds two discrete variants on the same lifecycle: - -| `pressable` option | Default | Effect | -| ------------------ | ------- | ------------------------------------------------------------------------------------------ | -| `onLongPress` | — | Fires when a press is held past `longPressDelay`, then suppresses the following `onPress`. | -| `onDoubleTap` | — | Fires when two completed presses land within `doubleTapDelay`. | -| `longPressDelay` | `500` | Hold time (ms) before a long press fires. | -| `doubleTapDelay` | `300` | Maximum gap (ms) between two presses to count as a double tap. | - -### `pinchable`, `wheelable` & `reorder` - -```svelte - - - - - - - -{#each list as value (value)} -
    {value}
    -{/each} -``` - -| `pinchable` option | Default | Effect | -| ------------------ | ------- | --------------------------------------------------- | -| `applyTransform` | `true` | Write `--motion-scale` / `--motion-rotate` live. | -| `rotate` | `true` | Track rotation as well as scale. | -| `scaleBounds` | — | `{ min, max }` clamp on the reported/applied scale. | - -| `wheelable` option | Default | Effect | -| ------------------ | ------- | --------------------------------------------------- | -| `applyTransform` | `true` | Write `--motion-scale` on each tick. | -| `scaleBounds` | — | `{ min, max }` clamp on the reported/applied scale. | -| `speed` | `0.01` | Zoom sensitivity per wheel unit. | -| `requireCtrl` | `false` | Only act when `ctrlKey` is held (trackpad pinch). | -| `preventDefault` | `true` | Stop the page scrolling / browser-zooming. | -| `smooth` | `true` | Spring-ease applied scale; `false` or `SpringOptions`. | - -| `reorder` option | Default | Effect | -| ---------------- | ------- | ---------------------------------------------------------- | -| `items` | — | Reactive thunk returning the current ordered list. | -| `onReorder` | — | Called with the new array when a drag drops on a new slot. | -| `axis` | `'y'` | `'x'` for horizontal lists. | -| `duration` | `220` | Settle (FLIP-into-slot) length in ms. | diff --git a/src/lib/gradient/README.md b/src/lib/gradient/README.md deleted file mode 100644 index 155b3dd..0000000 --- a/src/lib/gradient/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# gradient - -Tween between CSS `linear-gradient` backgrounds — something WAAPI cannot do natively (`background-image` is not interpolable). - -| File | Responsibility | -| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `gradient.ts` | `animateGradient(element, from, to, options)` — runs its own rAF loop: parses both gradients, resolves colour keywords through a canvas (so `"rebeccapurple"`, `hsl(...)`, resolved `currentColor`, etc. all work), and writes an interpolated gradient string each frame. Returns `{ finished, cancel }`. | -| `parse.ts` | Pure, DOM-free gradient parsing and interpolation (`parseLinearGradient`, `parseRGBA`, `lerpRGBA`, `formatLinearGradient`, `splitTopLevel`, `resolvePositions`). Unit-tested. | - -```ts -import { animateGradient } from '@ixirjs/pulse/gradient'; - -animateGradient( - el, - 'linear-gradient(90deg, #f00 0%, #00f 100%)', - 'linear-gradient(180deg, #0f0 0%, #ff0 100%)', - { duration: 600 } -); -``` - -### Options - -| Option | Default | Description | -| ------------ | -------------------- | ----------------------------------------------------- | -| `duration` | `400` | Tween length in ms. | -| `easing` | ease-out | Easing function. | -| `delay` | `0` | Delay before starting (ms). | -| `property` | `'background-image'` | CSS property to write (e.g. `'border-image-source'`). | -| `onComplete` | — | Fired once when the tween settles. | - -> **Stop-for-stop interpolation.** Best results when both gradients share the same number of colour stops; angle, each stop's colour (RGBA) and position are interpolated independently. When the stop counts differ they can't be matched one-to-one, so the tween snaps to the target. Colour keywords are resolved to RGBA before interpolation, so any valid CSS colour works on either end. diff --git a/src/lib/morph/README.md b/src/lib/morph/README.md deleted file mode 100644 index d9e0d52..0000000 --- a/src/lib/morph/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# morph - -SVG path morphing — tween an SVG ``'s `d` between two shapes. WAAPI can't interpolate `d` across arbitrary command lists, so this normalizes both paths to a common cubic-bézier form, aligns them, and runs its own rAF loop. - -| File | Responsibility | -| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `parse.ts` | `parsePath(d)` — character-scanning tokenizer that expands implicit repeats and correctly reads arc flags and scientific notation. | -| `normalize.ts` | `normalizePath(d)` — converts every command (`M L H V C S Q T A Z`, relative or absolute) into absolute cubic-bézier subpaths. Lines become thirds-placed cubics, quadratics are elevated, arcs are split into ≤90° cubic segments. | -| `interpolate.ts` | `planMorph(from, to)` aligns the two paths subpath-by-subpath, growing the one with fewer segments by De Casteljau subdivision of its longest segments, then (via `minimizeAnchorTravel`) rotates/reverses each closed ring to the shortest-travel correspondence. `interpolatePlan(plan, t)` lerps every control point and serializes back to a `d` string. | -| `morph.ts` | `morph(element, from, to, options)` — the rAF driver. Writes the interpolated `d` each frame; honors `prefers-reduced-motion`. | - -```ts -import { morph } from '@ixirjs/pulse/morph'; - -const heart = - 'M12 21s-7-4.35-9.5-8.5C1 9 3 5 6.5 5 9 5 12 8 12 8s3-3 5.5-3C21 5 23 9 21.5 12.5 19 16.65 12 21 12 21z'; -const star = 'M12 2l3 7h7l-5.5 4 2 7L12 16l-6.5 4 2-7L2 9h7z'; - -morph(pathEl, heart, star, { duration: 600 }); -``` - -### Options - -| Option | Default | Description | -| ---------------------- | -------- | ----------------------------------------------------------------- | -| `duration` | `400` | Tween length in ms. | -| `easing` | ease-out | Easing function. | -| `delay` | `0` | Delay before starting (ms). | -| `respectReducedMotion` | `true` | Snap to the target when reduced motion is requested. | -| `optimize` | `true` | Rotate/reverse closed rings to the minimal-travel correspondence. | -| `onComplete` | — | Fired once when the morph settles. | - -> **Structure alignment.** Within matching subpaths, differing segment counts are reconciled automatically by subdivision, so two shapes with different point counts still morph point-for-point. When the two paths have a **different number of subpaths** the morph can't pair them up and snaps to the target (same fallback philosophy as [`animateGradient`](../gradient/README.md)). -> -> **Minimal-distance anchor alignment** (`optimize`, on by default). For each closed subpath, the `from` ring is cyclically rotated — and reversed if its winding is opposite — to the orientation that minimizes total anchor travel against the `to` ring. This prevents the visible "twist" that happens when point 0 of one shape is paired with a far-away point on the other, so anchors take the shortest path. Open subpaths are left as-is (their start/end are fixed and must not rotate). Set `optimize: false` to pair anchors strictly in document order. diff --git a/src/lib/presence/README.md b/src/lib/presence/README.md deleted file mode 100644 index 9eeadaa..0000000 --- a/src/lib/presence/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# presence - -Spring-powered enter/exit transitions that plug into Svelte's built-in `transition:` / `in:` / `out:` directives. - -Svelte already _orchestrates_ presence — a keyed `{#each}` runs `out:` before unmount and `in:` on mount. What it lacks is spring timing. These transitions accept a `spring` option and derive **both** the eased curve and the natural settling `duration` from the simulation, so enters and exits feel like the rest of the library. - -| File | Responsibility | -| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `transitions.ts` | `fade`, `fly`, `scale`, and `size` — each returns a Svelte `TransitionConfig`. `resolveTiming()` turns a `spring` option into `{ duration, easing }` via [`springEasing()`](../animate/README.md), or falls back to a duration + ease-out when no spring is given. | - -```svelte - - -{#each items as item (item.id)} -
    {item.text}
    -{/each} - - -{#if open} -
    -{/if} - - -{#if open} -
    -{/if} -``` - -### Shared params - -| Param | Description | -| ---------- | ------------------------------------------------------------------------- | -| `spring` | Spring physics for the curve + auto-sized duration. `true` uses defaults. | -| `duration` | Explicit ms; overrides the spring's natural duration. | -| `easing` | Easing function; overrides the spring curve when both are given. | -| `delay` | Delay before the transition starts (ms). | - -`fly` adds `x` / `y` / `opacity`; `scale` adds `start` / `opacity`. - -Both `fly` and `scale` also take **optional `width` / `height`** — a start size that tweens to the element's measured natural (auto-resolved) size _alongside_ the travel/pop. Omit them for transform-only behavior: - -```svelte - -
    - - -
    -``` - -| Param | Description | -| -------- | ----------------------------------------------------------------- | -| `width` | Start width; tweens to the natural width. Omit to leave width be. | -| `height` | Start height; tweens to the natural height. Omit to leave it be. | - -The start accepts a **px number or any CSS length** — `0`, `'2rem'`, `'50%'`, `'10vw'`, `'calc(…)'`. CSS values are resolved to px against the element in its real context (so `%` is relative to its containing block), then interpolated. The **target is always the element's natural size**, measured automatically — so `width: 0` grows to whatever `width: auto` would be, with no fixed pixel target needed. - -The collapse scales the axis's **padding, border, and margin** by the same fraction as the width/height (just like `size`), so the box reaches a true zero footprint. Without this, `box-sizing: border-box` would floor the element at its padding (`width: 0` ⇒ still padding-wide), leaving a stub and a layout slot that snaps shut on unmount. - -`size` collapses an element's **width and/or height** (with its padding, border, and margin on that axis) — the way to drive width/height on enter/exit. Like Svelte's `slide`, but either axis: - -| Param | Default | Description | -| --------- | ------- | --------------------------------------------------------------------- | -| `axis` | `'y'` | `'x'`, `'y'`, or `'both'` — which dimension(s) to collapse. | -| `start` | `0` | Fraction of the natural size to start/end at (`0` = fully collapsed). | -| `opacity` | — | Omit for size-only; pass `0` to fade alongside the collapse. | - -> These are CSS-driven transitions (they return a `css` function), so they animate `transform` / `opacity` directly and are independent of the `--motion-*` chain — appropriate for short-lived mount/unmount, where the element is not simultaneously being driven by `animate()`. diff --git a/src/lib/scroll/README.md b/src/lib/scroll/README.md deleted file mode 100644 index d4aeade..0000000 --- a/src/lib/scroll/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# scroll - -Scroll-driven animation for Svelte 5. Two complementary primitives: bind an animation's _progress_ to scroll position, or _trigger_ effects when an element crosses the viewport. - -| File | Responsibility | -| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `scroll.ts` | `scroll(options)` — a Svelte attachment that drives a paused [`AnimationController`](../animate/README.md) by seeking it: progress `0…1` maps to `0…totalDuration`. Rather than depend on the still-patchy native `ScrollTimeline`, it pauses the animation and `seek()`s it on every scroll frame, so it works in every browser and composes with springs, per-prop timing, and the `--motion-*` chain. Also accepts a raw `onProgress(p)` callback. | -| `in-view.ts` | `inView(options)` — an `IntersectionObserver`-backed attachment that fires `onEnter` / `onLeave` (with `once`, `amount`, `margin`, `root`). This is the "play when in view" / `whileInView` primitive. | -| `progress.ts` | Pure, DOM-free progress math (`coverProgress`, `containProgress`, `pageProgress`) so the mapping is unit-testable without a browser. | - -```svelte - - - -
    animate(el, { y: [40, -40], opacity: [0, 1] }) })}>…
    - - -
    animate(el, { opacity: [0, 1], y: [24, 0] }) })} -> - … -
    - - -
    (bar.style.scaleX = String(p)) })} /> -``` - -### Ranges - -| `range` | Maps progress across | -| ------------------- | ----------------------------------------------------------------------- | -| `'cover'` (default) | The element crossing the viewport — `0` about to enter, `1` fully gone. | -| `'contain'` | Only the span where the element is fully visible. | -| `'page'` | Whole-scroller progress; ignores the element. | - -Pass `axis: 'x'` for horizontal scrollers and `container` to track a scrollable element instead of the window. diff --git a/src/lib/shared/README.md b/src/lib/shared/README.md deleted file mode 100644 index 771f1d9..0000000 --- a/src/lib/shared/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# shared - -Internal infrastructure shared across the library — core types, browser/accessibility detection, math helpers, and the spring physics engine. Nothing here is end-user-facing; it exists so [`animate`](../animate/README.md), [`flip`](../flip/README.md), and [`easing`](../easing/README.md) can share primitives without circular imports. - -## What's here - -| File | Provides | -| --- | --- | -| `types.ts` | `EasingFn` (`(t) => number`), `MotionElement` (`HTMLElement \| SVGElement`), and `SpringOptions` (`stiffness`, `damping`, `mass`, `velocity`, `restDelta`, `restSpeed`). | -| `browser.ts` | `isBrowser()`, `prefersReducedMotion()` (cached media-query check), and `shouldReduceMotion(respectFlag?)`. | -| `math.ts` | `atLeast0(n)` → `max(0, n)` and `clamp01(n)` → clamp to `[0, 1]`. | -| `spring-core.ts` | The spring simulation engine and WAAPI easing-string helpers. | - -## Spring core - -`spring-core.ts` simulates a mass-spring-damper system at 60 fps and caches the result (128-entry LRU keyed by the canonical options string), so repeated `springEasing(...)` calls with the same parameters never re-simulate. - -```ts -import { getCachedSpring, sampleAt, samplesToLinearEasing } from '$lib/shared/spring-core'; - -const { spring, linearEasingCss } = getCachedSpring({ stiffness: 200, damping: 20 }); -// spring.samples: number[] spring.duration: ms -// linearEasingCss: "linear(0.00000, 0.20000, …, 1.00000)" for WAAPI -``` - -| Export | Purpose | -| --- | --- | -| `getCachedSpring(options?)` | Simulate (or fetch cached) `{ spring: { samples, duration }, linearEasingCss }`. | -| `sampleAt(samples, t)` | Linear-interpolate normalized progress at fractional `t ∈ [0, 1]`. | -| `samplesToLinearEasing(samples)` | Convert a sample array to a WAAPI `linear(...)` easing string. | - -**Physics** — each frame (`dt = 1000/60` ms): `accel = (-stiffness·pos − damping·vel) / mass`, then integrate velocity and position. Terminates once position and velocity stay under their rest thresholds for 3 frames, capped at 10 s. Defaults: `stiffness 170`, `damping 26`, `mass 1`. diff --git a/src/lib/text/README.md b/src/lib/text/README.md deleted file mode 100644 index 710cf36..0000000 --- a/src/lib/text/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# text - -SplitText — break an element's text into per-character, per-word, or per-line wrapper ``s so the pieces can be animated individually. The GSAP-SplitText analog. Pair the returned spans with [`stagger()`](../animate/README.md) for cascading reveals. - -| File | Responsibility | -| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `split.ts` | `tokenizeWords(text)` / `tokenizeChars(text)` — pure, DOM-free tokenizers (whitespace-preserving, surrogate-pair-aware) that are server-testable. `splitText(element, options)` — the DOM wrapper that builds `inline-block` spans, groups chars inside word spans (so words never fracture at line ends), measures `offsetTop` to bucket words into line wrappers, and returns the spans plus a `revert()`. SSR-safe via [`isBrowser`](../shared). | - -```svelte - - -

    Reveal me, one letter at a time

    -``` - -### Options - -| Option | Default | Description | -| ----------- | --------- | --------------------------------------------------------------------------------------- | -| `type` | `'chars'` | `'chars'`, `'words'`, `'lines'`, or an array of these — which granularities to produce. | -| `charClass` | — | Class applied to every character wrapper span. | -| `wordClass` | — | Class applied to every word wrapper span. | -| `lineClass` | — | Class applied to every line wrapper span. | - -### Result - -`splitText()` returns `{ chars, words, lines, revert }`: - -| Field | Type | Description | -| -------- | --------------- | ---------------------------------------------------------- | -| `chars` | `HTMLElement[]` | Per-character spans. Empty unless `'chars'` was requested. | -| `words` | `HTMLElement[]` | Per-word spans. Empty unless `'words'` was requested. | -| `lines` | `HTMLElement[]` | Per-line spans. Empty unless `'lines'` was requested. | -| `revert` | `() => void` | Restores the element's original `innerHTML`. | - -> **Words stay intact.** Word spans are always built internally (even when only `chars` is requested) and carry `white-space: nowrap`, so characters never break mid-word at a line end. **Lines** are grouped by measuring each word span's `offsetTop` after layout — words sharing an offset are on the same visual line — so the line buckets reflect the element's _current_ width. Re-run after a resize if the wrap changes. -> -> **SSR.** Outside a browser, `splitText()` returns empty arrays and a no-op `revert`, so it is safe to call unconditionally; do the actual split in `onMount`. diff --git a/src/lib/variants/README.md b/src/lib/variants/README.md deleted file mode 100644 index 057c69e..0000000 --- a/src/lib/variants/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# variants - -Named animation states layered over [`animate()`](../animate/README.md). Define a set of states once, then move between them by name — the orchestration primitive for interactive components (rest / hover / pressed, open / closed, …). - -Each transition interrupts the previous one by committing the live on-screen values first (via the controller's `stop()`), so re-targeting mid-flight starts from where the element actually is instead of snapping back. - -| File | Responsibility | -| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `variants.ts` | `createVariants(element, options)` — the framework-agnostic imperative core. `to(name)` animates to a state, `apply(name)` snaps to it, `stop()` commits the in-flight values. `current` reports the last targeted state. | -| `variants.svelte.ts` | `variants(options)` — a Svelte attachment that drives `createVariants` from reactive state. Pass an `active: () => string` thunk; an `$effect` animates to that state whenever it changes. Snaps to the initial state on mount (or animates it with `animateInitial`). | - -```svelte - - - -``` - -Prefer the imperative `createVariants()` when you are not in a Svelte component or want to drive states from your own event handling. diff --git a/src/lib/view-transition/README.md b/src/lib/view-transition/README.md deleted file mode 100644 index e982e5f..0000000 --- a/src/lib/view-transition/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# view-transition - -Drives the browser's native [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) with pulse's spring/easing engine. The browser still computes the old→new geometry; pulse **re-eases** the resulting pseudo-element animations, so you get GPU-composited morphs shaped by a spring — something plain CSS-driven view transitions can't do — exposed through the same [`AnimationController`](../animate/README.md) every other feature returns. - -| File | Responsibility | -| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `view-transition.ts` | `viewTransition(update, options)` — wraps `document.startViewTransition`, returns an `AnimationController`. `supportsViewTransitions()` feature-detects. Falls back to running `update` un-animated when the API is missing (Firefox, older Safari), under `prefers-reduced-motion`, or during SSR. | -| `controller.ts` | Wraps the running `ViewTransition` in the uniform controller. After `transition.ready` it collects the live `::view-transition-*` pseudo animations, re-times them with the resolved easing, and forwards `seek`/`pause`/`reverse`/`finished` to them. `resolvedController` is the no-transition fast-path. | -| `timing.ts` | `resolveViewTransitionTiming(options)` — pure (DOM-free, node-tested) resolution of `spring`/`easing`/`duration` into an `EffectTiming` patch. Reuses `springEasing()` and `easingToCss()`. | -| `name.svelte.ts` | `viewTransitionName(name)` — Svelte attachment that sets `view-transition-name` (static or reactive thunk) so an element morphs as a shared element. The counterpart of `flip({ layoutId })`. | -| `navigation.ts` | `viewTransitionNavigate(navigation, options)` — wrap a SvelteKit client navigation. Call from `onNavigate`. `navigation` is typed structurally (`{ complete }`) so the module never imports `$app/navigation`. | - -```svelte - - -
    - {#each items as item (item.id)} - -
    {item.label}
    - {/each} -
    - -``` - -### SvelteKit page transitions - -```ts -import { onNavigate } from '$app/navigation'; -import { viewTransitionNavigate } from '@ixirjs/pulse/view-transition'; - -onNavigate((navigation) => viewTransitionNavigate(navigation, { spring: true })); -``` - -### Notes - -- **Re-easing, not re-computing.** The native API positions the snapshots; pulse only reshapes the timing curve. Omit `spring`/`easing`/`duration` to keep the browser default. -- **Controllability.** Because the morph runs on real WAAPI `Animation` objects, `seek`/`pause`/`reverse` work — but only once `transition.ready` has resolved (the pseudo-elements exist). `cancel()`/`stop()` skip to the end state and take effect immediately. -- **Interactive local transitions.** The View Transitions specification removes captured elements from hit-testing while a transition is active. For an interruptible local morph, set `html { view-transition-name: none }`, put `viewTransitionName()` on a non-interactive child rather than its button/link, and let the transition pseudo-elements pass pointer input with `::view-transition { pointer-events: none }`. -- **Interruptions.** Starting another document transition cancels the active one, and the specification permits their asynchronous update callbacks to overlap. If updates depend on previous state, call `stop()`, await `finished`, and discard superseded requests before starting the replacement transition. -- **Relationship to FLIP.** [`flip()`](../flip/README.md) remains the choice for fully interruptible, retargetable layout animation and for shared-element transitions that must work in every browser. View transitions add native cross-document (MPA) navigations and zero manual rect bookkeeping where supported. From 5b2679023dce1943868f5b7c5406e053c196aa93 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:44:52 -0400 Subject: [PATCH 06/30] docs(changelog): reformat headings for markdownlint Co-Authored-By: Claude Opus 5 (1M context) --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index babcb5c..22dbacc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added #### `animate(element, props, defaults?)` + - Spring-physics WAAPI animation runtime with per-property spring curves. - Independent transform component animation (`x`, `y`, `scale`, `rotate`, `skewX`, `skewY`) via registered CSS custom properties — never clobbers sibling transforms. - `[from, to]` shorthand, `PropConfig` full form, and bare-value (current → target) inputs. @@ -18,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `prefers-reduced-motion` support (skips animation and applies end-state). #### `timeline(defaults?)` + - Sequence and parallelize `animate()` calls along a shared clock. - Position grammar: absolute ms, `"+=N"`/`"-=N"`, `"<"`/`">"` anchors with offsets, named labels. - `.add()`, `.set()`, `.call()`, `.label()` builder API (chainable). @@ -25,30 +27,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `finished` promise aggregating all child animations. #### `spring(options?)` + - Simulate a spring from 0 → 1 and return per-frame samples + duration. - Memoized by physics parameters (LRU cache, max 128 entries). - Used internally by `animate()` spring props. #### `springEasing(options?)` + - Returns a `SpringEasingFn` usable anywhere an `easing` is accepted. - Carries `.duration` (natural settling time) and `._linearEasing` (pre-built WAAPI string). #### `stagger(interval, options?)` + - Generate staggered delays for list animations. - `from`: `'start'` | `'end'` | `'center'` | `number` (normalized 0–1 position). - Optional `easing` for non-linear wave staggers. #### `cubicBezier(x1, y1, x2, y2)` + - Build an easing function equivalent to CSS `cubic-bezier(x1, y1, x2, y2)`. - Newton-Raphson root-finding with binary-subdivision fallback. #### `easings` namespace + - `linear`, `ease`, `easeIn`, `easeOut`, `easeInOut` - `quadIn/Out/InOut`, `cubicIn/Out/InOut`, `quartIn/Out/InOut`, `quintIn/Out/InOut` - `expoIn/Out/InOut`, `sineIn/Out/InOut`, `circIn/Out/InOut` - `backIn/Out/InOut`, `elasticIn/Out/InOut`, `bounceIn/Out/InOut` #### `flip(options?)` (Svelte 5 attachment) + - Zero-config FLIP (First, Last, Invert, Play) layout-shift animator via `{@attach flip()}`. - Reactive remeasure: pass a thunk `auto: () => { void open; }` to track rune dependencies. - Auto-tracking via `ResizeObserver` + `MutationObserver` (`auto: createObserverManager()`). @@ -57,14 +65,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `prefers-reduced-motion` support. #### `createFlipScope()` + - Shared-element cross-component transitions via `layoutId`. - `flip` attachment factory bound to a shared layout registry. - `layoutTtlMs` configurable TTL for stored rects. #### `flipFrom(element, from, options?)` + - Imperatively animate an element from a captured rect to its current position. #### `snapshotRect(element)` + - Capture an element's current rect for use with `flipFrom`. [0.1.0]: https://github.com/svelte-atoms/vibra/releases/tag/v0.1.0 From 7e107ef0874ac8b814a26897c4ab7f3f998084cb Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:45:04 -0400 Subject: [PATCH 07/30] refactor(shared): extract frame-batch, frame-tween and inline-style helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three concerns were duplicated across attachments, JS-driven animations and the property registry: - frame-batch: one rAF per burst of subscribers instead of one each - frame-tween: shared delay/completion/cancellation lifecycle - inline-style: save/restore of a forced inline property + !important Also drops the shared/index.ts barrel — callers import the module they need. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/shared/browser.test.ts | 18 +++--- src/lib/shared/browser.ts | 17 ++---- src/lib/shared/frame-batch.test.ts | 55 +++++++++++++++++++ src/lib/shared/frame-batch.ts | 59 ++++++++++++++++++++ src/lib/shared/frame-tween.test.ts | 85 +++++++++++++++++++++++++++++ src/lib/shared/frame-tween.ts | 68 +++++++++++++++++++++++ src/lib/shared/index.ts | 4 -- src/lib/shared/inline-style.test.ts | 59 ++++++++++++++++++++ src/lib/shared/inline-style.ts | 28 ++++++++++ src/lib/shared/math.test.ts | 41 -------------- src/lib/shared/math.ts | 11 ++-- src/lib/shared/spring-core.test.ts | 39 ++++++++++++- src/lib/shared/spring-core.ts | 10 +++- 13 files changed, 417 insertions(+), 77 deletions(-) create mode 100644 src/lib/shared/frame-batch.test.ts create mode 100644 src/lib/shared/frame-batch.ts create mode 100644 src/lib/shared/frame-tween.test.ts create mode 100644 src/lib/shared/frame-tween.ts delete mode 100644 src/lib/shared/index.ts create mode 100644 src/lib/shared/inline-style.test.ts create mode 100644 src/lib/shared/inline-style.ts delete mode 100644 src/lib/shared/math.test.ts diff --git a/src/lib/shared/browser.test.ts b/src/lib/shared/browser.test.ts index 894a094..a785d29 100644 --- a/src/lib/shared/browser.test.ts +++ b/src/lib/shared/browser.test.ts @@ -1,11 +1,11 @@ /** * Tests for browser environment detection utilities. * Runs in the `server` (node) vitest project where `window` is undefined, - * so isBrowser() is always false and prefersReducedMotion() always false. + * so isBrowser() is always false and reduced motion never suppresses animation. */ import { describe, expect, it } from 'vitest'; -import { isBrowser, prefersReducedMotion } from './browser'; +import { isBrowser, shouldReduceMotion } from './browser'; describe('isBrowser()', () => { it('returns false in node environment', () => { @@ -17,18 +17,16 @@ describe('isBrowser()', () => { }); }); -describe('prefersReducedMotion()', () => { +describe('shouldReduceMotion()', () => { it('returns false in node environment (no matchMedia)', () => { - expect(prefersReducedMotion()).toBe(false); + expect(shouldReduceMotion()).toBe(false); }); - it('returns a boolean', () => { - expect(typeof prefersReducedMotion()).toBe('boolean'); + it('returns false when the respect flag is off, regardless of environment', () => { + expect(shouldReduceMotion(false)).toBe(false); }); - it('calling it multiple times returns the same value', () => { - const a = prefersReducedMotion(); - const b = prefersReducedMotion(); - expect(a).toBe(b); + it('returns a boolean', () => { + expect(typeof shouldReduceMotion()).toBe('boolean'); }); }); diff --git a/src/lib/shared/browser.ts b/src/lib/shared/browser.ts index df9592a..17c56f5 100644 --- a/src/lib/shared/browser.ts +++ b/src/lib/shared/browser.ts @@ -1,19 +1,10 @@ export const isBrowser = (): boolean => typeof window !== 'undefined' && typeof document !== 'undefined'; -let reducedMotionQuery: MediaQueryList | null | undefined; - -export const prefersReducedMotion = (): boolean => { - if (reducedMotionQuery === undefined) { - reducedMotionQuery = - isBrowser() && typeof window.matchMedia === 'function' - ? window.matchMedia('(prefers-reduced-motion: reduce)') - : null; - } - return reducedMotionQuery?.matches ?? false; -}; - /** Returns true when reduced motion should suppress animation. * `respectFlag` defaults to `true`, matching `AnimateDefaults.respectReducedMotion`. */ export const shouldReduceMotion = (respectFlag?: boolean): boolean => - (respectFlag ?? true) && prefersReducedMotion(); + (respectFlag ?? true) && + isBrowser() && + typeof window.matchMedia === 'function' && + window.matchMedia('(prefers-reduced-motion: reduce)').matches; diff --git a/src/lib/shared/frame-batch.test.ts b/src/lib/shared/frame-batch.test.ts new file mode 100644 index 0000000..7627f2b --- /dev/null +++ b/src/lib/shared/frame-batch.test.ts @@ -0,0 +1,55 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { createFrameBatch } from './frame-batch'; + +afterEach(() => { + vi.restoreAllMocks(); + vi.unstubAllGlobals(); +}); + +describe('createFrameBatch()', () => { + it('coalesces independent subscribers into one browser frame', () => { + let frame: FrameRequestCallback | undefined; + const request = vi.fn((callback: FrameRequestCallback) => { + frame = callback; + return 1; + }); + vi.stubGlobal('requestAnimationFrame', request); + vi.stubGlobal('cancelAnimationFrame', vi.fn()); + const first = vi.fn(); + const second = vi.fn(); + const a = createFrameBatch(first); + const b = createFrameBatch(second); + + a.schedule(); + b.schedule(); + a.schedule(); + expect(request).toHaveBeenCalledOnce(); + + frame!(0); + expect(first).toHaveBeenCalledOnce(); + expect(second).toHaveBeenCalledOnce(); + }); + + it('removes a cancelled subscriber without cancelling other work', () => { + let frame: FrameRequestCallback | undefined; + vi.stubGlobal('requestAnimationFrame', (callback: FrameRequestCallback) => { + frame = callback; + return 7; + }); + const cancel = vi.fn(); + vi.stubGlobal('cancelAnimationFrame', cancel); + const first = vi.fn(); + const second = vi.fn(); + const a = createFrameBatch(first); + const b = createFrameBatch(second); + + a.schedule(); + b.schedule(); + a.cancel(); + frame!(0); + + expect(first).not.toHaveBeenCalled(); + expect(second).toHaveBeenCalledOnce(); + expect(cancel).not.toHaveBeenCalled(); + }); +}); diff --git a/src/lib/shared/frame-batch.ts b/src/lib/shared/frame-batch.ts new file mode 100644 index 0000000..53d2125 --- /dev/null +++ b/src/lib/shared/frame-batch.ts @@ -0,0 +1,59 @@ +/** + * Shared requestAnimationFrame batch for independently-owned visual updates. + * + * A batch preserves each subscriber's callback while ensuring a burst of + * schedules across attachments produces one browser frame request. Subscribers + * may safely remove themselves during a flush. + */ + +export interface FrameBatch { + /** Queue this subscriber once for the next animation frame. */ + schedule(): void; + /** Remove this subscriber without affecting other queued work. */ + cancel(): void; +} + +const pending = new Set<() => void>(); +let frame: number | null = null; + +const flush = (): void => { + frame = null; + const callbacks = [...pending]; + pending.clear(); + for (const callback of callbacks) callback(); +}; + +/** Create a cancellable subscriber to the shared visual-update frame. */ +export const createFrameBatch = (callback: () => void): FrameBatch => { + let queued = false; + + const schedule = (): void => { + if (queued) return; + if (typeof requestAnimationFrame !== 'function') { + // Non-DOM environments — run synchronously so tests still observe the + // effect. Real browsers always have RAF. + callback(); + return; + } + queued = true; + pending.add(run); + if (frame == null) frame = requestAnimationFrame(flush); + }; + + const run = (): void => { + queued = false; + callback(); + }; + + const cancel = (): void => { + if (!queued) return; + queued = false; + pending.delete(run); + if (pending.size === 0 && frame != null) { + cancelAnimationFrame(frame); + frame = null; + } + }; + + return { schedule, cancel }; +}; diff --git a/src/lib/shared/frame-tween.test.ts b/src/lib/shared/frame-tween.test.ts new file mode 100644 index 0000000..8bd6f48 --- /dev/null +++ b/src/lib/shared/frame-tween.test.ts @@ -0,0 +1,85 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { frameTween } from './frame-tween'; + +type Queue = Map; + +const installFrames = (): { queue: Queue; flush: (time: number) => void } => { + let id = 0; + const queue: Queue = new Map(); + vi.stubGlobal('requestAnimationFrame', (callback: FrameRequestCallback) => { + queue.set(++id, callback); + return id; + }); + vi.stubGlobal('cancelAnimationFrame', (handle: number) => queue.delete(handle)); + return { + queue, + flush(time) { + const next = queue.entries().next().value as [number, FrameRequestCallback] | undefined; + if (!next) throw new Error('No frame is scheduled'); + queue.delete(next[0]); + next[1](time); + } + }; +}; + +afterEach(() => { + vi.restoreAllMocks(); + vi.unstubAllGlobals(); +}); + +describe('frameTween()', () => { + it('renders an optional initial sample and completes exactly once', async () => { + const { flush } = installFrames(); + const samples: number[] = []; + const complete = vi.fn(); + const tween = frameTween({ + duration: 100, + delay: 20, + renderInitial: true, + onFrame: (progress) => samples.push(progress), + onComplete: complete + }); + + expect(samples).toEqual([0]); + flush(100); // Establishes the delay window. + flush(120); + flush(170); + flush(220); + await tween.finished; + + expect(samples).toEqual([0, 0, 0.5, 1]); + expect(complete).toHaveBeenCalledOnce(); + }); + + it('holds progress at 0 until the delay window elapses', () => { + const { flush } = installFrames(); + const samples: number[] = []; + frameTween({ + duration: 100, + delay: 50, + onFrame: (progress) => samples.push(progress) + }); + + flush(100); // Establishes the delay window. + flush(120); + flush(150); + expect(samples).toEqual([0]); + }); + + it('cancels pending work without a terminal sample or completion callback', async () => { + const { queue } = installFrames(); + const complete = vi.fn(); + const tween = frameTween({ + duration: 100, + delay: 0, + onFrame: vi.fn(), + onComplete: complete + }); + + tween.cancel(); + tween.cancel(); + await tween.finished; + expect(queue).toHaveLength(0); + expect(complete).not.toHaveBeenCalled(); + }); +}); diff --git a/src/lib/shared/frame-tween.ts b/src/lib/shared/frame-tween.ts new file mode 100644 index 0000000..2c16469 --- /dev/null +++ b/src/lib/shared/frame-tween.ts @@ -0,0 +1,68 @@ +/** + * Small lifecycle owner for requestAnimationFrame-based, duration-bound work. + * + * The caller owns what each progress sample means; this module owns scheduling, + * delay, completion, cancellation, and the settled promise. Keeping those + * concerns together prevents the library's JS-driven animation helpers from + * drifting in their terminal and cancellation behavior. + */ + +export interface FrameTween { + /** Resolves when the tween reaches its terminal progress or is cancelled. */ + readonly finished: Promise; + /** Stop future frames without rendering a terminal sample or calling `onComplete`. */ + cancel(): void; +} + +interface FrameTweenOptions { + duration: number; + /** Delay in ms, counted from the first browser frame. */ + delay: number; + /** Render progress 0 synchronously before scheduling the first frame. */ + renderInitial?: boolean; + onFrame: (progress: number) => void; + onComplete?: () => void; +} + +/** Run a cancellable rAF tween while preserving the caller's timing contract. */ +export const frameTween = ({ + duration, + delay, + renderInitial = false, + onFrame, + onComplete +}: FrameTweenOptions): FrameTween => { + let frame: number | null = null; + let startTime: number | null = null; + let done = false; + let resolveFinished!: () => void; + const finished = new Promise((resolve) => (resolveFinished = resolve)); + + const finish = (completed: boolean): void => { + if (done) return; + done = true; + if (frame != null) cancelAnimationFrame(frame); + frame = null; + if (completed) onComplete?.(); + resolveFinished(); + }; + + const tick = (now: number): void => { + if (startTime == null) startTime = now + delay; + const elapsed = now - startTime; + if (elapsed < 0) { + frame = requestAnimationFrame(tick); + return; + } + + const progress = duration > 0 ? Math.min(elapsed / duration, 1) : 1; + onFrame(progress); + if (progress >= 1) finish(true); + else frame = requestAnimationFrame(tick); + }; + + if (renderInitial) onFrame(0); + frame = requestAnimationFrame(tick); + + return { finished, cancel: () => finish(false) }; +}; diff --git a/src/lib/shared/index.ts b/src/lib/shared/index.ts deleted file mode 100644 index 2405a0b..0000000 --- a/src/lib/shared/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './browser'; -export * from './math'; -export * from './types'; -export * from './spring-core'; diff --git a/src/lib/shared/inline-style.test.ts b/src/lib/shared/inline-style.test.ts new file mode 100644 index 0000000..6a0cd40 --- /dev/null +++ b/src/lib/shared/inline-style.test.ts @@ -0,0 +1,59 @@ +/** + * Tests for the inline-style save / restore helpers. + * Uses a minimal in-memory CSSStyleDeclaration stub so it runs in the + * `server` (node) vitest project without a real DOM. + */ + +import { describe, expect, it } from 'vitest'; +import { restoreStyleProp, saveStyleProp } from './inline-style'; + +/** Minimal CSSStyleDeclaration stand-in backed by a Map. */ +const fakeStyle = () => { + const map = new Map(); + return { + getPropertyValue: (n: string) => map.get(n)?.value ?? '', + getPropertyPriority: (n: string) => map.get(n)?.priority ?? '', + setProperty: (n: string, v: string, p = '') => map.set(n, { value: v, priority: p }), + removeProperty: (n: string) => void map.delete(n), + has: (n: string) => map.has(n) + } as unknown as CSSStyleDeclaration & { has: (n: string) => boolean }; +}; + +describe('saveStyleProp()', () => { + it('captures the current value and priority', () => { + const style = fakeStyle(); + style.setProperty('--motion-x', '10px', 'important'); + expect(saveStyleProp(style, '--motion-x')).toEqual({ + value: '10px', + priority: 'important' + }); + }); + + it('captures empty value/priority for an unset property', () => { + const style = fakeStyle(); + expect(saveStyleProp(style, '--motion-x')).toEqual({ value: '', priority: '' }); + }); +}); + +describe('restoreStyleProp()', () => { + it('re-applies a saved value and its priority over a temporary write', () => { + const style = fakeStyle(); + style.setProperty('--motion-x', '10px', ''); + const saved = saveStyleProp(style, '--motion-x'); + // Simulate a temporary suppression write. + style.setProperty('--motion-x', '0px', 'important'); + + restoreStyleProp(style, '--motion-x', saved); + expect(style.getPropertyValue('--motion-x')).toBe('10px'); + expect(style.getPropertyPriority('--motion-x')).toBe(''); + }); + + it('removes the property when the saved value was empty (clears the temp write)', () => { + const style = fakeStyle(); + const saved = saveStyleProp(style, '--motion-x'); // unset → empty + style.setProperty('--motion-x', '0px', 'important'); + + restoreStyleProp(style, '--motion-x', saved); + expect(style.has('--motion-x')).toBe(false); + }); +}); diff --git a/src/lib/shared/inline-style.ts b/src/lib/shared/inline-style.ts new file mode 100644 index 0000000..83fcbac --- /dev/null +++ b/src/lib/shared/inline-style.ts @@ -0,0 +1,28 @@ +/** + * Inline-style save / restore, for the places that force a temporary value on + * an element and must put the prior one back. + * + * Dependency-free on purpose: kept out of `prop-utils` so the static property + * registry can import it without forming a cycle. + */ + +/** A captured inline style property — its value plus `!important` priority. */ +export interface SavedStyleProp { + value: string; + priority: string; +} + +export const saveStyleProp = (style: CSSStyleDeclaration, name: string): SavedStyleProp => ({ + value: style.getPropertyValue(name), + priority: style.getPropertyPriority(name) +}); + +/** Re-apply a captured value + priority, or remove the property if it was unset. */ +export const restoreStyleProp = ( + style: CSSStyleDeclaration, + name: string, + saved: SavedStyleProp +): void => { + if (saved.value) style.setProperty(name, saved.value, saved.priority); + else style.removeProperty(name); +}; diff --git a/src/lib/shared/math.test.ts b/src/lib/shared/math.test.ts deleted file mode 100644 index 2720b3e..0000000 --- a/src/lib/shared/math.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Tests for the shared numeric clamp helpers. - * No DOM access — runs in the `server` vitest project. - */ - -import { describe, expect, it } from 'vitest'; -import { atLeast0, clamp01 } from './math'; - -describe('atLeast0()', () => { - it('passes through positive values', () => { - expect(atLeast0(5)).toBe(5); - expect(atLeast0(0.001)).toBe(0.001); - }); - - it('clamps negatives to 0', () => { - expect(atLeast0(-1)).toBe(0); - expect(atLeast0(-0.0001)).toBe(0); - }); - - it('returns 0 unchanged', () => { - expect(atLeast0(0)).toBe(0); - }); -}); - -describe('clamp01()', () => { - it('passes through values within [0, 1]', () => { - expect(clamp01(0)).toBe(0); - expect(clamp01(0.5)).toBe(0.5); - expect(clamp01(1)).toBe(1); - }); - - it('clamps values above 1 to 1', () => { - expect(clamp01(1.5)).toBe(1); - expect(clamp01(100)).toBe(1); - }); - - it('clamps values below 0 to 0', () => { - expect(clamp01(-0.5)).toBe(0); - expect(clamp01(-100)).toBe(0); - }); -}); diff --git a/src/lib/shared/math.ts b/src/lib/shared/math.ts index f854dd3..be538e9 100644 --- a/src/lib/shared/math.ts +++ b/src/lib/shared/math.ts @@ -1,10 +1,7 @@ -/** - * Tiny numeric clamps shared across the animation modules so the same - * bound-checking lives in one place instead of being re-spelled inline. - */ +/** Scalar helpers shared across the animation, scroll and interpolation code. */ -/** Clamp `n` to be non-negative (≥ 0). */ -export const atLeast0 = (n: number): number => Math.max(0, n); +/** Linear interpolation between `a` and `b` at `t`. */ +export const lerp = (a: number, b: number, t: number): number => a + (b - a) * t; -/** Clamp `n` into the inclusive `[0, 1]` range. */ +/** Clamp into `[0, 1]`. */ export const clamp01 = (n: number): number => Math.min(1, Math.max(0, n)); diff --git a/src/lib/shared/spring-core.test.ts b/src/lib/shared/spring-core.test.ts index b37ef6a..4518bfb 100644 --- a/src/lib/shared/spring-core.test.ts +++ b/src/lib/shared/spring-core.test.ts @@ -6,7 +6,7 @@ */ import { describe, expect, it } from 'vitest'; -import { getCachedSpring, sampleAt, samplesToLinearEasing } from './spring-core'; +import { getCachedSpring, sampleAt, samplesToLinearEasing, spring } from './spring-core'; // --------------------------------------------------------------------------- // samplesToLinearEasing() @@ -124,3 +124,40 @@ describe('getCachedSpring()', () => { expect(reborn.linearEasingCss).toBe(first.linearEasingCss); }); }); + +// --------------------------------------------------------------------------- +// spring() +// --------------------------------------------------------------------------- + +describe('spring()', () => { + it('returns samples starting at 0 and ending at 1', () => { + const { samples } = spring(); + expect(samples[0]).toBe(0); + expect(samples[samples.length - 1]).toBe(1); + }); + + it('duration is samples.length - 1 frames at 60fps', () => { + const { samples, duration } = spring(); + expect(duration).toBeCloseTo((samples.length - 1) * (1000 / 60), 1); + }); + + it('stiffer spring settles faster', () => { + const stiff = spring({ stiffness: 500, damping: 40 }); + const soft = spring({ stiffness: 50, damping: 8 }); + expect(stiff.duration).toBeLessThan(soft.duration); + }); + + it('respects custom restDelta / restSpeed thresholds', () => { + const tight = spring({ restDelta: 1e-6, restSpeed: 1e-6 }); + const loose = spring({ restDelta: 0.05, restSpeed: 0.05 }); + // Tighter tolerance = more frames = longer duration + expect(tight.duration).toBeGreaterThanOrEqual(loose.duration); + }); + + it('all samples are finite numbers', () => { + const { samples } = spring({ stiffness: 300, damping: 18, velocity: 200 }); + for (const s of samples) { + expect(Number.isFinite(s)).toBe(true); + } + }); +}); diff --git a/src/lib/shared/spring-core.ts b/src/lib/shared/spring-core.ts index e66314a..8e4cf63 100644 --- a/src/lib/shared/spring-core.ts +++ b/src/lib/shared/spring-core.ts @@ -11,7 +11,8 @@ import type { SpringOptions } from './types'; const DT_MS = 1000 / 60; const MAX_DURATION_MS = 10_000; -const SPRING_DEFAULTS = { +/** The library's default spring feel — shared by the sampled spring and the live integrator. */ +export const SPRING_DEFAULTS = { stiffness: 170, damping: 26, mass: 1, @@ -89,6 +90,13 @@ export const getCachedSpring = (options: SpringOptions = {}): CachedSpring => { return entry; }; +/** + * Simulate a spring travelling from 0 → 1 and return per-frame normalized + * samples plus the settling duration. Results are memoized by option key. + */ +export const spring = (options: SpringOptions = {}): SpringSamples => + getCachedSpring(options).spring; + const simulateSpring = (options: SpringOptions): SpringSamples => { const { stiffness, damping, mass, restDelta, restSpeed, velocity } = withSpringDefaults(options); From 38b17abc362bf4d4953b264cf5be3e63f856aa4d Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:45:16 -0400 Subject: [PATCH 08/30] refactor(animate)!: drop the duplicated flip and spring modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit animate/flip.ts reimplemented what flip/ already does with a richer option set; its exports (flipFromRect, flipToRect, captureRect, AnimateFlipRect) are gone — use @ixirjs/pulse/flip instead. animate/spring.ts was a second copy of shared/spring-core, now re-exported from there. style-utils moved to shared/inline-style. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/animate/flip.test.ts | 67 ------ src/lib/animate/flip.ts | 202 ------------------ src/lib/animate/index.ts | 7 +- .../animate/properties/style-utils.test.ts | 59 ----- src/lib/animate/properties/style-utils.ts | 41 ---- src/lib/animate/spring.test.ts | 71 ------ src/lib/animate/spring.ts | 10 - 7 files changed, 2 insertions(+), 455 deletions(-) delete mode 100644 src/lib/animate/flip.test.ts delete mode 100644 src/lib/animate/flip.ts delete mode 100644 src/lib/animate/properties/style-utils.test.ts delete mode 100644 src/lib/animate/properties/style-utils.ts delete mode 100644 src/lib/animate/spring.test.ts delete mode 100644 src/lib/animate/spring.ts diff --git a/src/lib/animate/flip.test.ts b/src/lib/animate/flip.test.ts deleted file mode 100644 index 0a9b88c..0000000 --- a/src/lib/animate/flip.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Tests for the FLIP animate-layer helpers. - * `captureRect`, `flipFromRect`, and `flipToRect` all delegate to - * `measureWithoutAncestorTransforms` which uses DOM globals (HTMLElement, - * getBoundingClientRect). Those paths require the `client` browser project. - * - * This file covers the module's exports and the FlipRect type shape. - * Runs in the `server` vitest project. - */ - -import { describe, expect, it } from 'vitest'; -import * as flipModule from './flip'; -import { buildFlipProps, resolveFlipDelta } from './flip'; - -describe('animate/flip module exports', () => { - it('exports captureRect as a function', () => { - expect(typeof flipModule.captureRect).toBe('function'); - }); - - it('exports flipFromRect as a function', () => { - expect(typeof flipModule.flipFromRect).toBe('function'); - }); - - it('exports flipToRect as a function', () => { - expect(typeof flipModule.flipToRect).toBe('function'); - }); - - it('exports captureVisualRect as a function', () => { - expect(typeof flipModule.captureVisualRect).toBe('function'); - }); -}); - -// --------------------------------------------------------------------------- -// FLIP direction — the inverse / forward contract shared by both FLIP layers. -// These drive `resolveFlipDelta` (the same helper `flipToRect`/`flipFromRect` -// and the animator use) so they guard the forward swap directly, not just the -// keyframe pairing. The visual `animate()` path only runs in a browser. -// --------------------------------------------------------------------------- - -const rect = (x: number, w: number) => ({ x, y: 0, width: w, height: 50 }); - -describe('resolveFlipDelta() direction', () => { - // Element physically at {x:0,w:100}; we want it to look like {x:200,w:50}. - const current = rect(0, 100); - const target = rect(200, 50); - - it('inverse FLIP returns the (from − to) transform placing the element at `from`', () => { - // flipFromRect: from = old rect, to = current DOM position; no swap. - const delta = resolveFlipDelta(target, current, false); - expect(delta.dx).toBe(200); // target.x − current.x - expect(delta.sx).toBe(0.5); // target.w / current.w - const props = buildFlipProps(delta, false); - expect(props.flipX).toEqual(['200px', '0px']); // starts offset, ends at rest - }); - - it('forward FLIP swaps the pair so the element is driven toward the target', () => { - // flipToRect: from = current, to = target, forward = true → swap to (to − from). - const delta = resolveFlipDelta(current, target, true); - // Swapped: dx = target.x − current.x = +200 (NOT current.x − target.x = −200), - // sx = target.w / current.w = 0.5 (NOT 2). The swap is what makes the element - // move toward the target rather than the mirror-opposite direction. - expect(delta.dx).toBe(200); - expect(delta.sx).toBe(0.5); - const props = buildFlipProps(delta, true); - expect(props.flipX).toEqual(['0px', '200px']); // starts at rest, ends at target - }); -}); diff --git a/src/lib/animate/flip.ts b/src/lib/animate/flip.ts deleted file mode 100644 index 7d74d4f..0000000 --- a/src/lib/animate/flip.ts +++ /dev/null @@ -1,202 +0,0 @@ -/** - * FLIP helpers that compose directly on top of `animate()`. - * - * These are pure `animate()`-layer functions — no attachment, no scope, no - * observer wiring. Use them when you only need a one-shot position transition - * and want a single import surface (`$lib/animate`). - * - * For full FLIP integration (Svelte attachments, shared-element transitions, - * auto-tracking via rune observers) use the `$lib/flip` module instead. - * - * @example - * ```ts - * // Standard inverse-FLIP (element already moved in the DOM): - * const from = captureRect(el); - * await tick(); // let the DOM update - * flipFromRect(el, from, { duration: 320 }); - * - * // Forward FLIP (element is still at its current position, drive it away): - * const to = targetRect; - * flipToRect(el, to, { duration: 320 }); - * ``` - */ - -import { animate } from './core/animate'; -import { measureWithoutAncestorTransforms } from './properties/properties'; -import type { AnimateDefaults, AnimateProps, AnimationController, MotionElement } from './types'; - -// --------------------------------------------------------------------------- -// Rect type -// --------------------------------------------------------------------------- - -/** Axis-aligned bounding rectangle in viewport coordinates. */ -export interface FlipRect { - x: number; - y: number; - width: number; - height: number; -} - -/** A pair of rects describing a layout change (`from` → `to`). */ -export interface FlipRectPair { - from: FlipRect; - to: FlipRect; -} - -export interface FlipDelta { - /** Horizontal translate component (`from.x - to.x`). */ - dx: number; - /** Vertical translate component (`from.y - to.y`). */ - dy: number; - /** Horizontal scale component (`from.width / to.width`). */ - sx: number; - /** Vertical scale component (`from.height / to.height`). */ - sy: number; -} - -export interface DeltaOptions { - translate?: boolean; - scale?: boolean; -} - -export const DEFAULT_FLIP_DURATION = 280; - -// --------------------------------------------------------------------------- -// Geometry — the single source of truth for FLIP delta math. -// --------------------------------------------------------------------------- - -/** Capture the element's current layout rect, suppressing in-flight transforms. */ -export const captureRect = (element: Element): FlipRect => { - const { left: x, top: y, width, height } = measureWithoutAncestorTransforms(element); - return { x, y, width, height }; -}; - -/** - * Capture the element's current *visual* rect — its own in-flight motion - * transform included, ancestor transforms still suppressed. Use this as the - * `from` rect when interrupting an in-flight FLIP so the replacement animation - * starts exactly where the element is on-screen, instead of snapping to its - * resting layout box first. - */ -export const captureVisualRect = (element: Element): FlipRect => { - const { left: x, top: y, width, height } = measureWithoutAncestorTransforms(element, { - suppressSelf: false - }); - return { x, y, width, height }; -}; - -/** - * Compute the inverted transform that places the element back at `from`. - * Components disabled in `opts` resolve to their identity. - */ -export const computeDelta = ( - { from, to }: FlipRectPair, - { translate = true, scale = true }: DeltaOptions = {} -): FlipDelta => ({ - dx: translate ? from.x - to.x : 0, - dy: translate ? from.y - to.y : 0, - sx: scale && to.width > 0 ? from.width / to.width : 1, - sy: scale && to.height > 0 ? from.height / to.height : 1 -}); - -/** True when the delta would produce no visible movement. */ -export const isIdentityDelta = (delta: FlipDelta): boolean => - delta.dx === 0 && delta.dy === 0 && delta.sx === 1 && delta.sy === 1; - -/** - * Resolve the FLIP delta for a layout change, honoring direction. - * - * Inverse (`forward: false`): DOM is at `to`; the delta is the inverse - * transform `(from − to)` that places the element back at `from`. - * Forward (`forward: true`): DOM is at `from`; the rect pair is swapped so the - * delta becomes `(to − from)`, driving the element visually toward `to`. - * - * This is the single source of truth for FLIP direction — both the - * `animate()`-layer helpers and the `flip` animator route through it, so the - * two layers can never disagree on which way a forward FLIP moves. - */ -export const resolveFlipDelta = ( - from: FlipRect, - to: FlipRect, - forward: boolean, - opts?: DeltaOptions -): FlipDelta => computeDelta(forward ? { from: to, to: from } : { from, to }, opts); - -/** - * Build the `animate()` props object for a FLIP delta. - * - * Inverse (default): DOM is at `to`; apply `[Δ→0]` to start visually at `from`. - * Forward: DOM is at `from`; apply `[0→Δ]` to drive visually toward `to`. - */ -export const buildFlipProps = ({ dx, dy, sx, sy }: FlipDelta, forward: boolean): AnimateProps => { - // `pair` orders the [from, to] keyframe by direction; `translate`/`scale` - // capture each component's unit and identity so they live in one place. - const pair = (delta: string, identity: string): [string, string] => - forward ? [identity, delta] : [delta, identity]; - const translate = (v: number): [string, string] => pair(`${v}px`, '0px'); - const scale = (v: number): [string, string] => pair(`${v}`, '1'); - return { - flipX: translate(dx), - flipY: translate(dy), - flipScaleX: scale(sx), - flipScaleY: scale(sy) - }; -}; - -/** Shared kernel: animate the computed FLIP delta, forward or inverse. */ -const applyFlipDelta = ( - element: MotionElement, - from: FlipRect, - to: FlipRect, - forward: boolean, - defaults: AnimateDefaults -): AnimationController | null => { - const delta = resolveFlipDelta(from, to, forward); - if (isIdentityDelta(delta)) return null; - return animate(element, buildFlipProps(delta, forward), { - duration: DEFAULT_FLIP_DURATION, - ...defaults - }); -}; - -// --------------------------------------------------------------------------- -// Public API -// --------------------------------------------------------------------------- - -/** - * Animate an element from a previously captured rect to its current DOM - * position (standard inverse-FLIP). - * - * Call this **after** the DOM has moved the element to its new position so - * the "from" rect differs from the element's current rect. - * - * @param element The element to animate. - * @param from Rect captured before the DOM update (e.g. via `captureRect`). - * @param defaults Optional `animate()` defaults (duration, easing, delay, …). - * @returns The `AnimationController`, or `null` when no work is needed. - */ -export const flipFromRect = ( - element: MotionElement, - from: FlipRect, - defaults: AnimateDefaults = {} -): AnimationController | null => - applyFlipDelta(element, from, captureRect(element), false, defaults); - -/** - * Animate an element from its current DOM position toward a target rect - * (forward FLIP). - * - * The DOM stays at the element's current position; only the visual - * representation is driven toward `to`. Use this for exit/collapse - * animations where the DOM has not yet been moved. - * - * @param element The element to animate. - * @param to The target rect to animate toward. - * @param defaults Optional `animate()` defaults (duration, easing, delay, …). - * @returns The `AnimationController`, or `null` when no work is needed. - */ -export const flipToRect = ( - element: MotionElement, - to: FlipRect, - defaults: AnimateDefaults = {} -): AnimationController | null => applyFlipDelta(element, captureRect(element), to, true, defaults); diff --git a/src/lib/animate/index.ts b/src/lib/animate/index.ts index c38ce46..b49f815 100644 --- a/src/lib/animate/index.ts +++ b/src/lib/animate/index.ts @@ -7,8 +7,8 @@ export { animate } from './core/animate'; export { timeline } from './timeline/timeline'; export type { Timeline, TimelineDefaults, TimelinePosition } from './timeline/timeline'; -export { spring } from './spring'; -export type { Spring } from './spring'; +export { spring } from '../shared/spring-core'; +export type { SpringSamples as Spring } from '../shared/spring-core'; export { cubicBezier, springEasing } from '../easing'; export type { SpringEasingFn } from '../easing'; export * as easings from '../easing'; @@ -24,9 +24,6 @@ export type { SpringValue, SpringValueOptions } from './spring-value'; export { animateValue, countUp } from './animate-value'; export type { AnimateValueOptions, CountUpOptions, ValueController } from './animate-value'; -export { flipFromRect, flipToRect, captureRect } from './flip'; -export type { FlipRect as AnimateFlipRect } from './flip'; - export type { AnimatableValue, AnimateDefaults, diff --git a/src/lib/animate/properties/style-utils.test.ts b/src/lib/animate/properties/style-utils.test.ts deleted file mode 100644 index 69faee3..0000000 --- a/src/lib/animate/properties/style-utils.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Tests for the inline-style save / restore helpers. - * Uses a minimal in-memory CSSStyleDeclaration stub so it runs in the - * `server` (node) vitest project without a real DOM. - */ - -import { describe, expect, it } from 'vitest'; -import { restoreStyleProp, saveStyleProp } from './style-utils'; - -/** Minimal CSSStyleDeclaration stand-in backed by a Map. */ -const fakeStyle = () => { - const map = new Map(); - return { - getPropertyValue: (n: string) => map.get(n)?.value ?? '', - getPropertyPriority: (n: string) => map.get(n)?.priority ?? '', - setProperty: (n: string, v: string, p = '') => map.set(n, { value: v, priority: p }), - removeProperty: (n: string) => void map.delete(n), - has: (n: string) => map.has(n) - } as unknown as CSSStyleDeclaration & { has: (n: string) => boolean }; -}; - -describe('saveStyleProp()', () => { - it('captures the current value and priority', () => { - const style = fakeStyle(); - style.setProperty('--motion-x', '10px', 'important'); - expect(saveStyleProp(style, '--motion-x')).toEqual({ - value: '10px', - priority: 'important' - }); - }); - - it('captures empty value/priority for an unset property', () => { - const style = fakeStyle(); - expect(saveStyleProp(style, '--motion-x')).toEqual({ value: '', priority: '' }); - }); -}); - -describe('restoreStyleProp()', () => { - it('re-applies a saved value and its priority over a temporary write', () => { - const style = fakeStyle(); - style.setProperty('--motion-x', '10px', ''); - const saved = saveStyleProp(style, '--motion-x'); - // Simulate a temporary suppression write. - style.setProperty('--motion-x', '0px', 'important'); - - restoreStyleProp(style, '--motion-x', saved); - expect(style.getPropertyValue('--motion-x')).toBe('10px'); - expect(style.getPropertyPriority('--motion-x')).toBe(''); - }); - - it('removes the property when the saved value was empty (clears the temp write)', () => { - const style = fakeStyle(); - const saved = saveStyleProp(style, '--motion-x'); // unset → empty - style.setProperty('--motion-x', '0px', 'important'); - - restoreStyleProp(style, '--motion-x', saved); - expect(style.has('--motion-x')).toBe(false); - }); -}); diff --git a/src/lib/animate/properties/style-utils.ts b/src/lib/animate/properties/style-utils.ts deleted file mode 100644 index 729f50c..0000000 --- a/src/lib/animate/properties/style-utils.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Inline-style save / restore helpers. - * - * Several places force a temporary inline value on an element — measuring an - * intrinsic-size keyword, or suppressing motion vars during a rect read — and - * must put the prior value (and its `!important` priority) back afterwards. - * This is the single source of truth for that capture / restore dance. - * - * Dependency-free on purpose: kept separate from `prop-utils` so the static - * property registry (`properties` → `transform-tracker`) can import it without - * forming an import cycle. - */ - -/** A captured inline style property — its value plus `!important` priority. */ -export interface SavedStyleProp { - value: string; - priority: string; -} - -/** - * Capture an inline style property so it can be restored after a temporary - * write (e.g. forcing a keyword to measure it, or suppressing a motion var). - */ -export const saveStyleProp = (style: CSSStyleDeclaration, name: string): SavedStyleProp => ({ - value: style.getPropertyValue(name), - priority: style.getPropertyPriority(name) -}); - -/** - * Restore a property captured by {@link saveStyleProp}. Re-applies the saved - * value and priority, or removes the property entirely when it was unset — - * which also clears any temporary `!important` write. - */ -export const restoreStyleProp = ( - style: CSSStyleDeclaration, - name: string, - saved: SavedStyleProp -): void => { - if (saved.value) style.setProperty(name, saved.value, saved.priority); - else style.removeProperty(name); -}; diff --git a/src/lib/animate/spring.test.ts b/src/lib/animate/spring.test.ts deleted file mode 100644 index ec56340..0000000 --- a/src/lib/animate/spring.test.ts +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Tests for spring simulation, memoization, and sampling correctness. - * All logic is pure (no DOM), so this runs in the `server` vitest project. - */ - -import { describe, expect, it } from 'vitest'; -import { spring } from './spring'; -import { getCachedSpring } from '$lib/shared/spring-core'; - -describe('spring()', () => { - it('returns samples starting at 0 and ending at 1', () => { - const { samples } = spring(); - expect(samples[0]).toBe(0); - expect(samples[samples.length - 1]).toBe(1); - }); - - it('duration is samples.length - 1 frames at 60fps', () => { - const { samples, duration } = spring(); - expect(duration).toBeCloseTo((samples.length - 1) * (1000 / 60), 1); - }); - - it('returns positive duration', () => { - expect(spring().duration).toBeGreaterThan(0); - }); - - it('stiffer spring settles faster', () => { - const stiff = spring({ stiffness: 500, damping: 40 }); - const soft = spring({ stiffness: 50, damping: 8 }); - expect(stiff.duration).toBeLessThan(soft.duration); - }); - - it('respects custom restDelta / restSpeed thresholds', () => { - const tight = spring({ restDelta: 1e-6, restSpeed: 1e-6 }); - const loose = spring({ restDelta: 0.05, restSpeed: 0.05 }); - // Tighter tolerance = more frames = longer duration - expect(tight.duration).toBeGreaterThanOrEqual(loose.duration); - }); - - it('all samples are finite numbers', () => { - const { samples } = spring({ stiffness: 300, damping: 18, velocity: 200 }); - for (const s of samples) { - expect(Number.isFinite(s)).toBe(true); - } - }); -}); - -describe('getCachedSpring()', () => { - it('same options object returns identical reference', () => { - const opts = { stiffness: 170, damping: 26 }; - const a = getCachedSpring(opts); - const b = getCachedSpring(opts); - expect(a).toBe(b); - }); - - it('equivalent options with different object identity returns same cached entry', () => { - const a = getCachedSpring({ stiffness: 200, damping: 30 }); - const b = getCachedSpring({ stiffness: 200, damping: 30 }); - expect(a).toBe(b); - }); - - it("produces a pre-rendered linearEasingCss string starting with 'linear('", () => { - const { linearEasingCss } = getCachedSpring(); - expect(linearEasingCss.startsWith('linear(')).toBe(true); - }); - - it('linearEasingCss contains the correct number of samples', () => { - const { spring: s, linearEasingCss } = getCachedSpring({ stiffness: 170, damping: 26 }); - const commaCount = (linearEasingCss.match(/,/g) ?? []).length; - expect(commaCount).toBe(s.samples.length - 1); - }); -}); diff --git a/src/lib/animate/spring.ts b/src/lib/animate/spring.ts deleted file mode 100644 index c7578a0..0000000 --- a/src/lib/animate/spring.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { SpringOptions } from './types'; -import { getCachedSpring, type SpringSamples } from '$lib/shared/spring-core'; - -export type Spring = SpringSamples; - -/** - * Simulate a spring travelling from 0 → 1 and return per-frame normalized - * samples plus the settling duration. Results are memoized by option key. - */ -export const spring = (options: SpringOptions = {}): Spring => getCachedSpring(options).spring; From 74dd735e99320996498b8e7b3cd19769203a2a8c Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:45:16 -0400 Subject: [PATCH 09/30] refactor(animate,easing): unexport internals and tighten docs Helpers with no callers outside their module lose their export; adds a transform-tracker browser test covering concurrent transform components. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/animate/animate-value.ts | 52 ++++--------------- src/lib/animate/core/animate.ts | 2 +- src/lib/animate/core/controller.ts | 10 +++- src/lib/animate/draw.ts | 2 +- .../animate/keyframes/easing-utils.test.ts | 21 ++------ src/lib/animate/keyframes/easing-utils.ts | 9 ++-- src/lib/animate/keyframes/keyframes.ts | 2 +- src/lib/animate/keyframes/keyword.ts | 4 +- src/lib/animate/keyframes/normalize.ts | 7 ++- src/lib/animate/properties/prop-utils.ts | 2 +- src/lib/animate/properties/properties.ts | 20 ++++++- .../transform-tracker.svelte.test.ts | 46 ++++++++++++++++ .../animate/properties/transform-tracker.ts | 32 ++++++++---- src/lib/animate/spring-value.ts | 13 ++--- src/lib/animate/stagger.ts | 4 +- .../animate/timeline/timeline-internals.ts | 4 +- src/lib/animate/timeline/timeline-position.ts | 12 ++--- src/lib/animate/timeline/timeline.ts | 2 +- src/lib/animate/types.ts | 15 ++++-- src/lib/easing/css.ts | 2 +- src/lib/easing/cubic-bezier.ts | 2 +- src/lib/easing/primitive.ts | 2 +- src/lib/easing/spring.ts | 4 +- 23 files changed, 151 insertions(+), 118 deletions(-) create mode 100644 src/lib/animate/properties/transform-tracker.svelte.test.ts diff --git a/src/lib/animate/animate-value.ts b/src/lib/animate/animate-value.ts index 1eee7db..86b90bc 100644 --- a/src/lib/animate/animate-value.ts +++ b/src/lib/animate/animate-value.ts @@ -25,8 +25,9 @@ * ``` */ -import { isBrowser, shouldReduceMotion } from '$lib/shared/browser'; -import { easeOut } from '$lib/easing'; +import { isBrowser, shouldReduceMotion } from '../shared/browser'; +import { frameTween } from '../shared/frame-tween'; +import { easeOut } from '../easing'; import type { EasingFn } from './types'; /** Default tween duration in ms when none is supplied. */ @@ -99,53 +100,22 @@ export const animateValue = ( const emit = makeRounder(round); - let frame: number | null = null; - let resolveFinished!: () => void; - const finished = new Promise((resolve) => (resolveFinished = resolve)); - // SSR, or reduced motion: jump to the end value and settle immediately. if (!isBrowser() || shouldReduceMotion(respectReducedMotion)) { onUpdate(emit(to)); onComplete?.(); - resolveFinished(); - return { stop: () => {}, finished }; + return { stop: () => {}, finished: Promise.resolve() }; } const span = to - from; - const start = performance.now() + delay; - - const tick = (now: number): void => { - const elapsed = now - start; - if (elapsed < 0) { - // Still inside the delay window — keep waiting. - frame = requestAnimationFrame(tick); - return; - } - const progress = duration > 0 ? Math.min(elapsed / duration, 1) : 1; - const value = from + span * easing(progress); - onUpdate(emit(value)); - - if (progress >= 1) { - frame = null; - onComplete?.(); - resolveFinished(); - return; - } - frame = requestAnimationFrame(tick); - }; - - frame = requestAnimationFrame(tick); + const tween = frameTween({ + duration, + delay, + onFrame: (progress) => onUpdate(emit(from + span * easing(progress))), + onComplete + }); - return { - stop() { - if (frame != null) { - cancelAnimationFrame(frame); - frame = null; - } - resolveFinished(); - }, - finished - }; + return { stop: tween.cancel, finished: tween.finished }; }; /** Options for {@link countUp}; same as {@link animateValue} but `onUpdate` is supplied. */ diff --git a/src/lib/animate/core/animate.ts b/src/lib/animate/core/animate.ts index 781bf7e..ba9ccaf 100644 --- a/src/lib/animate/core/animate.ts +++ b/src/lib/animate/core/animate.ts @@ -25,7 +25,7 @@ import { normalizeInput } from '../keyframes/normalize'; import { deregisterTransformAnimation, registerTransformAnimation } from '../properties/properties'; import { ensurePropertiesRegistered, ensureTransformWired } from '../properties/transform-setup'; import type { AnimateDefaults, AnimateProps, AnimationController, MotionElement } from '../types'; -import { isBrowser, shouldReduceMotion } from '$lib/shared/browser'; +import { isBrowser, shouldReduceMotion } from '../../shared/browser'; import { formatValue, resolveProp } from '../properties/prop-utils'; /** diff --git a/src/lib/animate/core/controller.ts b/src/lib/animate/core/controller.ts index 4bc9d06..46ba824 100644 --- a/src/lib/animate/core/controller.ts +++ b/src/lib/animate/core/controller.ts @@ -3,7 +3,7 @@ * and own the lifecycle hooks (`onStart` / `onEnd`) plus inline-style cleanup. */ -import { isBrowser } from '$lib/shared/browser'; +import { isBrowser } from '../../shared/browser'; import type { AnimateDefaults, AnimationController, MotionElement } from '../types'; import type { CssWrite } from '../keyframes/keyframes'; @@ -138,7 +138,15 @@ export const createController = ({ if (animations.length === 0) return (finishedPromise = Promise.resolve()); return (finishedPromise = Promise.all(animations.map((a) => a.finished)).then( () => { + // Capture the terminal timing before finalize() cancels the effects. + // This is 1 for a normal one-shot animation, but correctly preserves + // alternate/reverse iteration direction. + const terminalProgress = primaryAnimation?.effect?.getComputedTiming().progress ?? 1; finalize(); + // The last rAF can run just before WAAPI reaches its terminal time. + // Publish the terminal sample explicitly so onUpdate has the same + // end-state guarantee as the animation controller itself. + defaults.onUpdate?.(terminalProgress, element); defaults.onEnd?.(element, { finished: true }); }, (err) => { diff --git a/src/lib/animate/draw.ts b/src/lib/animate/draw.ts index 44c7d83..af840ec 100644 --- a/src/lib/animate/draw.ts +++ b/src/lib/animate/draw.ts @@ -19,7 +19,7 @@ */ import { animate } from './core/animate'; -import { isBrowser } from '$lib/shared/browser'; +import { isBrowser } from '../shared/browser'; import { noopController } from './core/controller'; import type { AnimateDefaults, AnimationController } from './types'; diff --git a/src/lib/animate/keyframes/easing-utils.test.ts b/src/lib/animate/keyframes/easing-utils.test.ts index bc48156..dcf555f 100644 --- a/src/lib/animate/keyframes/easing-utils.test.ts +++ b/src/lib/animate/keyframes/easing-utils.test.ts @@ -4,7 +4,7 @@ */ import { describe, expect, it } from 'vitest'; -import { DEFAULT_DURATION, DEFAULT_EASING, DEFAULT_EASING_CSS, easingToCss } from './easing-utils'; +import { DEFAULT_DURATION, DEFAULT_EASING, easingToCss } from './easing-utils'; import { springEasing } from '$lib/easing/spring'; // --------------------------------------------------------------------------- @@ -46,28 +46,13 @@ describe('DEFAULT_EASING', () => { }); }); -describe('DEFAULT_EASING_CSS', () => { - it("is a string starting with 'linear('", () => { - expect(typeof DEFAULT_EASING_CSS).toBe('string'); - expect(DEFAULT_EASING_CSS.startsWith('linear(')).toBe(true); - }); - - it("ends with ')'", () => { - expect(DEFAULT_EASING_CSS.endsWith(')')).toBe(true); - }); - - it('matches easingToCss(DEFAULT_EASING)', () => { - expect(DEFAULT_EASING_CSS).toBe(easingToCss(DEFAULT_EASING)); - }); -}); - // --------------------------------------------------------------------------- // easingToCss() // --------------------------------------------------------------------------- describe('easingToCss()', () => { - it('returns DEFAULT_EASING_CSS when called with undefined', () => { - expect(easingToCss(undefined)).toBe(DEFAULT_EASING_CSS); + it('falls back to DEFAULT_EASING when called with undefined', () => { + expect(easingToCss(undefined)).toBe(easingToCss(DEFAULT_EASING)); }); it('returns a linear(...) CSS string for a plain function', () => { diff --git a/src/lib/animate/keyframes/easing-utils.ts b/src/lib/animate/keyframes/easing-utils.ts index 2b3d504..0fe3809 100644 --- a/src/lib/animate/keyframes/easing-utils.ts +++ b/src/lib/animate/keyframes/easing-utils.ts @@ -6,9 +6,9 @@ */ import type { EasingFn } from '../types'; -import { cubicOut } from '$lib/easing/primitive'; -import { isSpringEasing } from '$lib/easing/spring'; -import { samplesToLinearEasing } from '$lib/shared/spring-core'; +import { cubicOut } from '../../easing/primitive'; +import { isSpringEasing } from '../../easing/spring'; +import { samplesToLinearEasing } from '../../shared/spring-core'; export const DEFAULT_DURATION = 300; /** Default easing — CSS `ease-out` cubic-bezier, shared with `cubicOut`. */ @@ -36,6 +36,3 @@ export const easingToCss = (easing: EasingFn | undefined): string => { EASING_CACHE.set(fn, css); return css; }; - -/** Precomputed `linear(...)` string for the library default easing. */ -export const DEFAULT_EASING_CSS: string = easingToCss(DEFAULT_EASING); diff --git a/src/lib/animate/keyframes/keyframes.ts b/src/lib/animate/keyframes/keyframes.ts index 50d7003..11b4ff6 100644 --- a/src/lib/animate/keyframes/keyframes.ts +++ b/src/lib/animate/keyframes/keyframes.ts @@ -6,7 +6,7 @@ import { VAR_BIT, type PropDef } from '../properties/properties'; import type { AnimatableValue, AnimateDefaults, AnimateProps, MotionElement } from '../types'; import { normalizeInput, resolveTiming } from './normalize'; -import { isBrowser } from '$lib/shared/browser'; +import { isBrowser } from '../../shared/browser'; import { isAutoKeyword, measureKeywordValue } from './keyword'; import { formatValue, diff --git a/src/lib/animate/keyframes/keyword.ts b/src/lib/animate/keyframes/keyword.ts index 6b10247..63efedd 100644 --- a/src/lib/animate/keyframes/keyword.ts +++ b/src/lib/animate/keyframes/keyword.ts @@ -11,8 +11,8 @@ import type { PropDef } from '../properties/properties'; import type { AnimatableValue, MotionElement } from '../types'; -import { isBrowser } from '$lib/shared/browser'; -import { restoreStyleProp, saveStyleProp } from '../properties/style-utils'; +import { isBrowser } from '../../shared/browser'; +import { restoreStyleProp, saveStyleProp } from '../../shared/inline-style'; const AUTO_KEYWORDS = new Set([ 'auto', diff --git a/src/lib/animate/keyframes/normalize.ts b/src/lib/animate/keyframes/normalize.ts index e376b2a..2eeef96 100644 --- a/src/lib/animate/keyframes/normalize.ts +++ b/src/lib/animate/keyframes/normalize.ts @@ -6,8 +6,7 @@ * / delay) — including spring sampling. */ -import { getCachedSpring } from '$lib/shared/spring-core'; -import { atLeast0 } from '$lib/shared/math'; +import { getCachedSpring } from '../../shared/spring-core'; import type { AnimatableValue, AnimateDefaults, @@ -19,7 +18,7 @@ import type { SpringOptions } from '../types'; import { DEFAULT_DURATION, easingToCss } from './easing-utils'; -import { isSpringEasing } from '$lib/easing/spring'; +import { isSpringEasing } from '../../easing/spring'; interface ResolvedTiming { duration: number; @@ -62,7 +61,7 @@ const resolveDurationMs = ( fallback: number ): number => { if (duration == null) return fallback; - if (typeof duration === 'function') return atLeast0(duration(element!)); + if (typeof duration === 'function') return Math.max(0, duration(element!)); return duration; }; diff --git a/src/lib/animate/properties/prop-utils.ts b/src/lib/animate/properties/prop-utils.ts index f15a6bd..798dc76 100644 --- a/src/lib/animate/properties/prop-utils.ts +++ b/src/lib/animate/properties/prop-utils.ts @@ -7,7 +7,7 @@ import type { AnimatableValue, MotionElement } from '../types'; import { PROPERTY_REGISTRY, type PropDef } from './properties'; -import { isBrowser } from '$lib/shared/browser'; +import { isBrowser } from '../../shared/browser'; /** * Convert a possibly-numeric value to its CSS string form, applying the diff --git a/src/lib/animate/properties/properties.ts b/src/lib/animate/properties/properties.ts index a44552b..739f866 100644 --- a/src/lib/animate/properties/properties.ts +++ b/src/lib/animate/properties/properties.ts @@ -65,6 +65,22 @@ export const PROPERTY_REGISTRY: Readonly> = { // clobber sibling position animations that share --motion-x / --motion-y. flipX: { css: '--flip-x', unit: 'px', initial: '0px', syntax: '', transform: true }, flipY: { css: '--flip-y', unit: 'px', initial: '0px', syntax: '', transform: true }, + // Reorder-exclusive offsets — direct-manipulation drag and sibling shifts + // compose with animation and FLIP instead of replacing `transform`. + reorderX: { + css: '--motion-reorder-x', + unit: 'px', + initial: '0px', + syntax: '', + transform: true + }, + reorderY: { + css: '--motion-reorder-y', + unit: 'px', + initial: '0px', + syntax: '', + transform: true + }, // FLIP-exclusive scale vars — compose with scaleX/scaleY so FLIP scale // never clobbers sibling scale animations that share --motion-scale-x/y. flipScaleX: { @@ -179,8 +195,8 @@ export const PROPERTY_REGISTRY: Readonly> = { */ export const TRANSFORM_TEMPLATES = { translate: - 'calc(var(--motion-x, 0px) + var(--flip-x, 0px)) ' + - 'calc(var(--motion-y, 0px) + var(--flip-y, 0px)) ' + + 'calc(var(--motion-x, 0px) + var(--flip-x, 0px) + var(--motion-reorder-x, 0px)) ' + + 'calc(var(--motion-y, 0px) + var(--flip-y, 0px) + var(--motion-reorder-y, 0px)) ' + 'var(--motion-z, 0px)', scale: 'calc(var(--flip-scale-x, 1) * var(--motion-scale-x, 1) * var(--motion-scale, 1)) ' + diff --git a/src/lib/animate/properties/transform-tracker.svelte.test.ts b/src/lib/animate/properties/transform-tracker.svelte.test.ts new file mode 100644 index 0000000..d4dec42 --- /dev/null +++ b/src/lib/animate/properties/transform-tracker.svelte.test.ts @@ -0,0 +1,46 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { + deregisterTransformAnimation, + measureWithoutAncestorTransforms, + registerTransformAnimation, + VAR_BIT +} from './transform-tracker'; + +let mounted: HTMLElement[] = []; + +afterEach(() => { + for (const element of mounted) element.remove(); + mounted = []; + vi.restoreAllMocks(); +}); + +describe('measureWithoutAncestorTransforms()', () => { + it('tracks overlapping transform animations without scanning inactive channels', () => { + const parent = document.createElement('div'); + const child = document.createElement('div'); + parent.appendChild(child); + document.body.appendChild(parent); + mounted.push(parent); + parent.style.setProperty('--motion-x', '20px'); + const observed: Array<[string, string]> = []; + vi.spyOn(child, 'getBoundingClientRect').mockImplementation(() => { + observed.push([ + parent.style.getPropertyValue('--motion-x'), + parent.style.getPropertyPriority('--motion-x') + ]); + return new DOMRect(); + }); + const x = VAR_BIT['--motion-x']!; + + registerTransformAnimation(parent, x); + registerTransformAnimation(parent, x); + deregisterTransformAnimation(parent, x); + measureWithoutAncestorTransforms(child); + expect(observed).toEqual([['0px', 'important']]); + expect(parent.style.getPropertyValue('--motion-x')).toBe('20px'); + + deregisterTransformAnimation(parent, x); + measureWithoutAncestorTransforms(child); + expect(observed[1]).toEqual(['20px', '']); + }); +}); diff --git a/src/lib/animate/properties/transform-tracker.ts b/src/lib/animate/properties/transform-tracker.ts index 9bdbe3b..0cb3074 100644 --- a/src/lib/animate/properties/transform-tracker.ts +++ b/src/lib/animate/properties/transform-tracker.ts @@ -10,7 +10,7 @@ * static registry data and the dynamic runtime state live in different modules. */ -import { restoreStyleProp, saveStyleProp, type SavedStyleProp } from './style-utils'; +import { restoreStyleProp, saveStyleProp, type SavedStyleProp } from '../../shared/inline-style'; import type { MotionElement } from '../types'; /** @@ -27,6 +27,8 @@ const MOTION_TRANSFORM_IDENTITIES: ReadonlyArray = [ ['--motion-rotate', '0deg'], ['--flip-x', '0px'], ['--flip-y', '0px'], + ['--motion-reorder-x', '0px'], + ['--motion-reorder-y', '0px'], ['--flip-scale-x', '1'], ['--flip-scale-y', '1'] ]; @@ -47,6 +49,8 @@ export const VAR_BIT: Readonly> = Object.fromEntries( * Entry is removed when all slots reach zero so suppressNode bails early. */ const activeTransformCounts = new WeakMap(); +/** Active slots mirror the count map, avoiding a full registry scan on hot paths. */ +const activeTransformBits = new WeakMap(); const forEachBit = (bits: number, fn: (i: number) => void): void => { for (let b = bits, i = 0; b !== 0; b >>>= 1, i++) { @@ -61,18 +65,27 @@ export const registerTransformAnimation = (element: Element, bits: number): void counts = new Uint8Array(N_TRANSFORM_VARS); activeTransformCounts.set(element, counts); } - const c = counts; - forEachBit(bits, (i) => c[i]++); + let activeBits = activeTransformBits.get(element) ?? 0; + forEachBit(bits, (i) => { + if (counts![i]++ === 0) activeBits |= 1 << i; + }); + activeTransformBits.set(element, activeBits); }; /** Mark that a WAAPI transform animation on an element has ended or was cancelled. */ export const deregisterTransformAnimation = (element: Element, bits: number): void => { const counts = activeTransformCounts.get(element); if (!counts) return; + let activeBits = activeTransformBits.get(element) ?? 0; forEachBit(bits, (i) => { - if (counts[i] > 0) counts[i]--; + if (counts[i] > 0 && --counts[i] === 0) activeBits &= ~(1 << i); }); - if (!counts.some((v) => v > 0)) activeTransformCounts.delete(element); + if (activeBits === 0) { + activeTransformCounts.delete(element); + activeTransformBits.delete(element); + } else { + activeTransformBits.set(element, activeBits); + } }; /** @@ -104,15 +117,14 @@ export const measureWithoutAncestorTransforms = ( const suppressed: Suppressed[] = []; const suppressNode = (target: MotionElement): void => { - const counts = activeTransformCounts.get(target); - if (!counts) return; + const bits = activeTransformBits.get(target); + if (!bits) return; const props: SavedProp[] = []; - for (let i = 0; i < N_TRANSFORM_VARS; i++) { - if (!counts[i]) continue; + forEachBit(bits, (i) => { const [name, identity] = MOTION_TRANSFORM_IDENTITIES[i]!; props.push({ name, saved: saveStyleProp(target.style, name) }); target.style.setProperty(name, identity, 'important'); - } + }); if (props.length > 0) suppressed.push({ node: target, props }); }; diff --git a/src/lib/animate/spring-value.ts b/src/lib/animate/spring-value.ts index 7f49f3d..ff89d36 100644 --- a/src/lib/animate/spring-value.ts +++ b/src/lib/animate/spring-value.ts @@ -23,16 +23,9 @@ * ``` */ -import { isBrowser } from '$lib/shared/browser'; -import type { SpringOptions } from '$lib/shared/types'; - -const SPRING_DEFAULTS = { - stiffness: 170, - damping: 26, - mass: 1, - restDelta: 0.001, - restSpeed: 0.001 -} as const; +import { isBrowser } from '../shared/browser'; +import { SPRING_DEFAULTS } from '../shared/spring-core'; +import type { SpringOptions } from '../shared/types'; /** Largest physics step (s) — clamps dt after a tab regains focus. */ const MAX_DT = 1 / 30; diff --git a/src/lib/animate/stagger.ts b/src/lib/animate/stagger.ts index 79db647..9a994fa 100644 --- a/src/lib/animate/stagger.ts +++ b/src/lib/animate/stagger.ts @@ -28,7 +28,7 @@ * ``` */ -import { clamp01 } from '$lib/shared/math'; +import { clamp01 } from '../shared/math'; import type { EasingFn } from './types'; export interface StaggerOptions { @@ -73,7 +73,7 @@ export const stagger = ( ? n - 1 : from === 'center' ? (n - 1) / 2 - : // Clamp a 0-1 normalized position into [0, n-1]. + : // Map a 0-1 normalized position onto [0, n-1]. clamp01(from) * (n - 1); // Distance from this index to the origin, normalized to [0, 1] relative diff --git a/src/lib/animate/timeline/timeline-internals.ts b/src/lib/animate/timeline/timeline-internals.ts index ef17395..0960987 100644 --- a/src/lib/animate/timeline/timeline-internals.ts +++ b/src/lib/animate/timeline/timeline-internals.ts @@ -29,7 +29,7 @@ interface ElementEntry extends BaseEntry { props: AnimateProps; } -export interface AnimateEntry extends ElementEntry { +interface AnimateEntry extends ElementEntry { readonly kind: 'animate'; options: AnimateDefaults; } @@ -38,7 +38,7 @@ export interface SetEntry extends ElementEntry { readonly kind: 'set'; } -export interface CallEntry extends BaseEntry { +interface CallEntry extends BaseEntry { readonly kind: 'call'; callback: () => void; } diff --git a/src/lib/animate/timeline/timeline-position.ts b/src/lib/animate/timeline/timeline-position.ts index 069b84d..c3c6689 100644 --- a/src/lib/animate/timeline/timeline-position.ts +++ b/src/lib/animate/timeline/timeline-position.ts @@ -11,8 +11,6 @@ * `"label"` / `"label+=N"`→ named label ± offset */ -import { atLeast0 } from '$lib/shared/math'; - /** * Where to place a timeline entry. See file header for the full grammar. * `undefined` means "append after the current end" — the most common case. @@ -49,7 +47,7 @@ const splitOffset = (expr: string): [string, number] => { */ export const resolvePosition = (position: TimelinePosition, anchor: Anchor): number => { if (position == null) return anchor.duration; - if (typeof position === 'number') return atLeast0(position); + if (typeof position === 'number') return Math.max(0, position); const trimmed = position.trim(); if (trimmed === '') return anchor.duration; @@ -59,17 +57,17 @@ export const resolvePosition = (position: TimelinePosition, anchor: Anchor): num // parsing lives in one place; the base is empty for these. if (trimmed.startsWith('+=') || trimmed.startsWith('-=')) { const [, offset] = splitOffset(trimmed); - return atLeast0(anchor.duration + offset); + return Math.max(0, anchor.duration + offset); } const [base, offset] = splitOffset(trimmed); - if (base === '' || base === '>') return atLeast0(anchor.lastEnd + offset); - if (base === '<') return atLeast0(anchor.lastStart + offset); + if (base === '' || base === '>') return Math.max(0, anchor.lastEnd + offset); + if (base === '<') return Math.max(0, anchor.lastStart + offset); const labelTime = anchor.labels.get(base); if (labelTime === undefined) { throw new Error(`[timeline] Unknown label or position: "${position}"`); } - return atLeast0(labelTime + offset); + return Math.max(0, labelTime + offset); }; diff --git a/src/lib/animate/timeline/timeline.ts b/src/lib/animate/timeline/timeline.ts index b95fc04..19d036b 100644 --- a/src/lib/animate/timeline/timeline.ts +++ b/src/lib/animate/timeline/timeline.ts @@ -42,7 +42,7 @@ import { computeAnimateDuration, offsetProps } from './timeline-internals'; -import { isBrowser } from '$lib/shared/browser'; +import { isBrowser } from '../../shared/browser'; import type { Timeline, TimelineDefaults, TimelinePosition } from './timeline-types'; // --------------------------------------------------------------------------- diff --git a/src/lib/animate/types.ts b/src/lib/animate/types.ts index 786b25d..5e71657 100644 --- a/src/lib/animate/types.ts +++ b/src/lib/animate/types.ts @@ -2,7 +2,7 @@ * Public types for the `animate()` library. */ -import type { EasingFn, MotionElement, SpringOptions } from '$lib/shared/types'; +import type { EasingFn, MotionElement, SpringOptions } from '../shared/types'; export type { EasingFn, MotionElement, SpringOptions }; @@ -110,10 +110,19 @@ export interface AnimateDefaults { export type AnimateProps = Record; +/** + * Playback controls shared by WAAPI, FLIP, timelines, and native view transitions. + * + * `finished` deliberately preserves its engine's terminal semantics: controllers + * created by `animate()` reject when cancelled (matching WAAPI), while native + * view-transition and no-animation fallback controllers resolve after settling. + * Callers that only need terminal notification may await it with their own + * rejection handling; cancellation is not normalized by this interface. + */ export interface AnimationController { - /** All underlying WAAPI animations. */ + /** Underlying browser animations when the engine exposes them. */ readonly animations: readonly Animation[]; - /** Resolves when every underlying animation finishes (or rejects on cancel). */ + /** Settles when the engine reaches a terminal state; see the interface contract. */ readonly finished: Promise; /** * Current playback position in ms from the animation start, or `null` diff --git a/src/lib/easing/css.ts b/src/lib/easing/css.ts index 3cb17ab..17d6d7a 100644 --- a/src/lib/easing/css.ts +++ b/src/lib/easing/css.ts @@ -1,4 +1,4 @@ -import type { EasingFn } from '$lib/shared/types'; +import type { EasingFn } from '../shared/types'; import { cubicBezier } from './cubic-bezier'; import { linear } from './primitive'; diff --git a/src/lib/easing/cubic-bezier.ts b/src/lib/easing/cubic-bezier.ts index c4c9c61..af3b41a 100644 --- a/src/lib/easing/cubic-bezier.ts +++ b/src/lib/easing/cubic-bezier.ts @@ -1,4 +1,4 @@ -import type { EasingFn } from '$lib/shared/types'; +import type { EasingFn } from '../shared/types'; import { linear } from './primitive'; const NEWTON_ITERATIONS = 8; diff --git a/src/lib/easing/primitive.ts b/src/lib/easing/primitive.ts index e67c742..c9d1094 100644 --- a/src/lib/easing/primitive.ts +++ b/src/lib/easing/primitive.ts @@ -1,4 +1,4 @@ -import type { EasingFn } from '$lib/shared/types'; +import type { EasingFn } from '../shared/types'; export const linear: EasingFn = (t) => t; diff --git a/src/lib/easing/spring.ts b/src/lib/easing/spring.ts index 679ae71..9f329e9 100644 --- a/src/lib/easing/spring.ts +++ b/src/lib/easing/spring.ts @@ -1,5 +1,5 @@ -import type { EasingFn, SpringOptions } from '$lib/shared/types'; -import { getCachedSpring, sampleAt } from '$lib/shared/spring-core'; +import type { EasingFn, SpringOptions } from '../shared/types'; +import { getCachedSpring, sampleAt } from '../shared/spring-core'; /** * A spring-physics easing function returned by `springEasing()`. From 1232ee2c8acc8c2724037552386660ddf8b71f06 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:45:39 -0400 Subject: [PATCH 10/30] feat(flip): add anchoredFlip Forward FLIP that animates an element from its current box to a target element's box, for popovers/tooltips that adopt an anchor's geometry. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/flip/anchored.svelte.test.ts | 315 +++++++++++++++++++++++++++ src/lib/flip/anchored.test.ts | 14 ++ src/lib/flip/anchored.ts | 163 ++++++++++++++ 3 files changed, 492 insertions(+) create mode 100644 src/lib/flip/anchored.svelte.test.ts create mode 100644 src/lib/flip/anchored.test.ts create mode 100644 src/lib/flip/anchored.ts diff --git a/src/lib/flip/anchored.svelte.test.ts b/src/lib/flip/anchored.svelte.test.ts new file mode 100644 index 0000000..b950251 --- /dev/null +++ b/src/lib/flip/anchored.svelte.test.ts @@ -0,0 +1,315 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { anchoredFlip } from './index'; + +const FLIP_PROPERTIES = ['--flip-x', '--flip-y', '--flip-scale-x', '--flip-scale-y'] as const; + +let mounted: Element[] = []; + +const mountBox = (styles: Partial): HTMLDivElement => { + const element = document.createElement('div'); + Object.assign(element.style, { position: 'fixed', ...styles }); + document.body.appendChild(element); + mounted.push(element); + return element; +}; + +const settleAnimations = async (element: Element): Promise => { + const animations = element.getAnimations(); + await Promise.all(animations.map((animation) => animation.finished.catch(() => undefined))); + await Promise.resolve(); +}; + +const expectRestingVisualState = (element: HTMLElement): void => { + const rect = element.getBoundingClientRect(); + expect(rect.x).toBeCloseTo(200, 0); + expect(rect.y).toBeCloseTo(100, 0); + expect(rect.width).toBeCloseTo(240, 0); + expect(rect.height).toBeCloseTo(120, 0); + expect(getComputedStyle(element).opacity).toBe('1'); + expect(element.style.pointerEvents).toBe(''); + for (const property of FLIP_PROPERTIES) { + expect(element.style.getPropertyValue(property)).toBe(''); + } +}; + +afterEach(() => { + for (const element of mounted) element.remove(); + mounted = []; +}); + +describe('anchoredFlip()', () => { + it('opens, closes, and reopens a mounted element at its resting geometry', async () => { + const reference = mountBox({ left: '20px', top: '30px', width: '40px', height: '20px' }); + const overlay = mountBox({ left: '200px', top: '100px', width: '240px', height: '120px' }); + let open = true; + const transition = anchoredFlip( + () => open, + () => reference, + { + duration: 30, + disablePointerEvents: true + } + ); + + let cleanup = transition(overlay); + await settleAnimations(overlay); + expectRestingVisualState(overlay); + + open = false; + cleanup?.(); + cleanup = transition(overlay); + await settleAnimations(overlay); + + open = true; + cleanup?.(); + cleanup = transition(overlay); + await settleAnimations(overlay); + expectRestingVisualState(overlay); + + cleanup?.(); + }); + + it('clears stale FLIP variables before measuring an enter', async () => { + const reference = mountBox({ left: '20px', top: '30px', width: '40px', height: '20px' }); + const overlay = mountBox({ left: '200px', top: '100px', width: '240px', height: '120px' }); + overlay.style.translate = + 'calc(var(--motion-x, 0px) + var(--flip-x, 0px)) calc(var(--motion-y, 0px) + var(--flip-y, 0px))'; + overlay.style.scale = 'var(--flip-scale-x, 1) var(--flip-scale-y, 1)'; + overlay.style.setProperty('--flip-x', '-180px'); + overlay.style.setProperty('--flip-y', '-70px'); + overlay.style.setProperty('--flip-scale-x', `${40 / 240}`); + overlay.style.setProperty('--flip-scale-y', `${20 / 120}`); + const transition = anchoredFlip( + () => true, + () => reference, + { duration: 30 } + ); + + const cleanup = transition(overlay); + await settleAnimations(overlay); + + expectRestingVisualState(overlay); + cleanup?.(); + }); + + it('restores the open visual state when an exit is interrupted by a new enter', async () => { + const reference = mountBox({ left: '20px', top: '30px', width: '40px', height: '20px' }); + const overlay = mountBox({ left: '200px', top: '100px', width: '240px', height: '120px' }); + let open = true; + const transition = anchoredFlip( + () => open, + () => reference, + { duration: 150 } + ); + + let cleanup = transition(overlay); + await settleAnimations(overlay); + + open = false; + cleanup?.(); + cleanup = transition(overlay); + await new Promise((resolve) => requestAnimationFrame(resolve)); + + open = true; + cleanup?.(); + cleanup = transition(overlay); + await settleAnimations(overlay); + + expectRestingVisualState(overlay); + expect(overlay.style.opacity).toBe(''); + cleanup?.(); + }); + + it('does nothing for an initially closed mounted element', () => { + const overlay = mountBox({ left: '200px', top: '100px', width: '240px', height: '120px' }); + let referenceReads = 0; + const transition = anchoredFlip( + () => false, + () => { + referenceReads++; + return null; + } + ); + + const cleanup = transition(overlay); + + expect(referenceReads).toBe(0); + expect(overlay.getAnimations()).toHaveLength(0); + expectRestingVisualState(overlay); + cleanup?.(); + }); + + it('settles closed without geometry when the reference disappears before exit', async () => { + const reference = mountBox({ left: '20px', top: '30px', width: '40px', height: '20px' }); + const overlay = mountBox({ left: '200px', top: '100px', width: '240px', height: '120px' }); + let open = true; + let currentReference: Element | null = reference; + const transition = anchoredFlip( + () => open, + () => currentReference, + { duration: 150 } + ); + + let cleanup = transition(overlay); + await settleAnimations(overlay); + + currentReference = null; + open = false; + cleanup?.(); + cleanup = transition(overlay); + + expect(overlay.getAnimations()).toHaveLength(0); + expect(getComputedStyle(overlay).opacity).toBe('0'); + expect(overlay.getBoundingClientRect().width).toBeCloseTo(240, 0); + cleanup?.(); + }); + + it('cancels safely and restores styles when the reference disappears', async () => { + const reference = mountBox({ left: '20px', top: '30px', width: '40px', height: '20px' }); + const overlay = mountBox({ left: '200px', top: '100px', width: '240px', height: '120px' }); + let open = true; + let currentReference: Element | null = reference; + const transition = anchoredFlip( + () => open, + () => currentReference, + { duration: 150 } + ); + + let cleanup = transition(overlay); + await settleAnimations(overlay); + + open = false; + cleanup?.(); + cleanup = transition(overlay); + await new Promise((resolve) => requestAnimationFrame(resolve)); + + currentReference = null; + open = true; + cleanup?.(); + expect(() => { + cleanup = transition(overlay); + }).not.toThrow(); + + expect(overlay.getAnimations()).toHaveLength(0); + expectRestingVisualState(overlay); + cleanup?.(); + }); + + it('restores pre-existing inline styles when destroyed during a transition', async () => { + const reference = mountBox({ left: '20px', top: '30px', width: '40px', height: '20px' }); + const overlay = mountBox({ + left: '200px', + top: '100px', + width: '240px', + height: '120px', + opacity: '0.75', + pointerEvents: 'auto' + }); + const transition = anchoredFlip( + () => true, + () => reference, + { + duration: 200, + disablePointerEvents: true + } + ); + + const cleanup = transition(overlay); + await new Promise((resolve) => requestAnimationFrame(resolve)); + cleanup?.(); + + expect(overlay.getAnimations()).toHaveLength(0); + expect(overlay.style.opacity).toBe('0.75'); + expect(overlay.style.pointerEvents).toBe('auto'); + for (const property of FLIP_PROPERTIES) { + expect(overlay.style.getPropertyValue(property)).toBe(''); + } + }); + + it('reaches the closed anchor state when enter is interrupted by exit', async () => { + const reference = mountBox({ left: '20px', top: '30px', width: '40px', height: '20px' }); + const overlay = mountBox({ left: '200px', top: '100px', width: '240px', height: '120px' }); + let open = true; + const transition = anchoredFlip( + () => open, + () => reference, + { duration: 150 } + ); + + let cleanup = transition(overlay); + await new Promise((resolve) => requestAnimationFrame(resolve)); + + open = false; + cleanup?.(); + cleanup = transition(overlay); + await settleAnimations(overlay); + + const rect = overlay.getBoundingClientRect(); + expect(rect.x).toBeCloseTo(20, 0); + expect(rect.y).toBeCloseTo(30, 0); + expect(rect.width).toBeCloseTo(40, 0); + expect(rect.height).toBeCloseTo(20, 0); + expect(getComputedStyle(overlay).opacity).toBe('0'); + cleanup?.(); + }); + + it('settles immediately in valid open and closed states under reduced motion', async () => { + const originalMatchMedia = window.matchMedia; + window.matchMedia = vi.fn().mockReturnValue({ + matches: true, + addEventListener: vi.fn(), + removeEventListener: vi.fn() + }) as unknown as typeof window.matchMedia; + vi.resetModules(); + + try { + const { anchoredFlip: reducedAnchoredFlip } = await import('./index'); + const reference = mountBox({ left: '20px', top: '30px', width: '40px', height: '20px' }); + const overlay = mountBox({ left: '200px', top: '100px', width: '240px', height: '120px' }); + let open = true; + const transition = reducedAnchoredFlip( + () => open, + () => reference, + { duration: 500 } + ); + + let cleanup = transition(overlay); + expect(overlay.getAnimations()).toHaveLength(0); + expectRestingVisualState(overlay); + + open = false; + cleanup?.(); + cleanup = transition(overlay); + expect(overlay.getAnimations()).toHaveLength(0); + expect(getComputedStyle(overlay).opacity).toBe('0'); + expect(overlay.getBoundingClientRect().width).toBeCloseTo(240, 0); + + open = true; + cleanup?.(); + cleanup = transition(overlay); + expectRestingVisualState(overlay); + cleanup?.(); + } finally { + window.matchMedia = originalMatchMedia; + vi.resetModules(); + } + }); + + it('accepts a virtual reference element', async () => { + const overlay = mountBox({ left: '200px', top: '100px', width: '240px', height: '120px' }); + const reference = { + getBoundingClientRect: () => ({ left: 20, top: 30, width: 40, height: 20 }) + }; + const transition = anchoredFlip( + () => true, + () => reference, + { duration: 30 } + ); + + const cleanup = transition(overlay); + await settleAnimations(overlay); + + expectRestingVisualState(overlay); + cleanup?.(); + }); +}); diff --git a/src/lib/flip/anchored.test.ts b/src/lib/flip/anchored.test.ts new file mode 100644 index 0000000..953eb86 --- /dev/null +++ b/src/lib/flip/anchored.test.ts @@ -0,0 +1,14 @@ +import { describe, expect, it, vi } from 'vitest'; +import { anchoredFlip } from './index'; + +describe('anchoredFlip() — non-browser environment', () => { + it('does not read state or geometry during SSR', () => { + const isOpen = vi.fn(() => true); + const getReference = vi.fn(() => null); + const transition = anchoredFlip(isOpen, getReference); + + expect(() => transition({} as HTMLElement)).not.toThrow(); + expect(isOpen).not.toHaveBeenCalled(); + expect(getReference).not.toHaveBeenCalled(); + }); +}); diff --git a/src/lib/flip/anchored.ts b/src/lib/flip/anchored.ts new file mode 100644 index 0000000..a2bf82b --- /dev/null +++ b/src/lib/flip/anchored.ts @@ -0,0 +1,163 @@ +import type { AnimationController } from '../animate/types'; +import { saveStyleProp, restoreStyleProp, type SavedStyleProp } from '../shared/inline-style'; +import { isBrowser } from '../shared/browser'; +import { animateFlip } from './animation/animator'; +import { measure } from './geometry'; +import { resolveOpacity } from './options'; +import type { FlipOptions, FlipRect, MotionElement } from './types'; + +const FLIP_STYLE_PROPERTIES = ['--flip-x', '--flip-y', '--flip-scale-x', '--flip-scale-y'] as const; +const OWNED_STYLE_PROPERTIES = [...FLIP_STYLE_PROPERTIES, 'opacity', 'pointer-events'] as const; + +type OwnedStyleProperty = (typeof OWNED_STYLE_PROPERTIES)[number]; +type StyleSnapshot = Record; + +/** A DOM element or virtual anchor that can provide viewport geometry. */ +export interface AnchoredFlipReference { + getBoundingClientRect(): Pick; +} + +export type AnchoredFlipReferenceGetter = () => AnchoredFlipReference | null | undefined; + +/** Animation options shared by the anchored enter and exit transitions. */ +export type AnchoredFlipOptions = Omit; + +/** Framework-neutral lifecycle function suitable for actions, attachments, and node hooks. */ +export type AnchoredFlipNodeFunction = (element: MotionElement) => (() => void) | void; + +const snapshotStyles = (element: MotionElement): StyleSnapshot => + Object.fromEntries( + OWNED_STYLE_PROPERTIES.map((property) => [ + property, + property.startsWith('--flip-') + ? { value: '', priority: '' } + : saveStyleProp(element.style, property) + ]) + ) as StyleSnapshot; + +const restoreStyles = (element: MotionElement, snapshot: StyleSnapshot): void => { + for (const property of OWNED_STYLE_PROPERTIES) { + restoreStyleProp(element.style, property, snapshot[property]); + } +}; + +const measureReference = (reference: AnchoredFlipReference): FlipRect => { + if (reference instanceof Element) return measure(reference); + const { left: x, top: y, width, height } = reference.getBoundingClientRect(); + return { x, y, width, height }; +}; + +/** + * Create a lifecycle-safe FLIP transition between a mounted element and an + * anchor. Invoke the returned node function whenever `isOpen()` changes and + * run its cleanup before the next invocation or when the node is destroyed. + * + * The transition owns cancellation and its temporary FLIP, opacity, and + * pointer-event styles. Enter always clears a previous exit's committed FLIP + * state before measuring the mounted element. + */ +export const anchoredFlip = ( + isOpen: () => boolean, + getReference: AnchoredFlipReferenceGetter, + options: AnchoredFlipOptions = {} +): AnchoredFlipNodeFunction => { + let element: MotionElement | null = null; + let initialStyles: StyleSnapshot | null = null; + let active: AnimationController | null = null; + let generation = 0; + let hasOpened = false; + + const reset = (): void => { + if (element && initialStyles) restoreStyles(element, initialStyles); + }; + + const cancelActive = (): void => { + const controller = active; + active = null; + controller?.cancel(); + }; + + return (node) => { + if (!isBrowser()) return; + + if (element !== node) { + generation++; + cancelActive(); + reset(); + element = node; + initialStyles = snapshotStyles(node); + hasOpened = false; + } + + const token = ++generation; + cancelActive(); + // A completed forward FLIP intentionally holds its closed visual state. + // Remove it before any new geometry read, especially a subsequent enter. + reset(); + + const open = isOpen(); + const cleanup = (): void => { + if (token !== generation || element !== node) return; + generation++; + cancelActive(); + reset(); + }; + + if (!open && !hasOpened) return cleanup; + + const reference = getReference(); + if (!reference || typeof reference.getBoundingClientRect !== 'function') { + if (!open) { + const resolvedOpacity = resolveOpacity(options.opacity ?? true); + if (resolvedOpacity) node.style.opacity = String(resolvedOpacity.from); + } + return cleanup; + } + + const referenceRect = measureReference(reference); + const overlayRect = measure(node); + if (open) hasOpened = true; + + if (options.disablePointerEvents) node.style.pointerEvents = 'none'; + + const { onEnd } = options; + const opacity = options.opacity ?? true; + const controller = animateFlip({ + element: node, + from: open ? referenceRect : overlayRect, + to: open ? overlayRect : referenceRect, + forward: !open, + options: { + ...options, + disablePointerEvents: false, + opacity, + onEnd: (finishedElement, info) => { + try { + onEnd?.(finishedElement, info); + } finally { + if (token === generation && element === node) { + active = null; + if (initialStyles) { + restoreStyleProp(node.style, 'pointer-events', initialStyles['pointer-events']); + if (open) restoreStyles(node, initialStyles); + } + } + } + } + } + }); + + active = controller; + if (!controller && initialStyles) { + restoreStyleProp(node.style, 'pointer-events', initialStyles['pointer-events']); + if (open) { + restoreStyles(node, initialStyles); + } else { + const resolvedOpacity = resolveOpacity(opacity); + if (resolvedOpacity) node.style.opacity = String(resolvedOpacity.from); + } + } + + return cleanup; + }; +}; From 9bea0192c5cc785e4844f7c4664091e849364e28 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:45:50 -0400 Subject: [PATCH 11/30] refactor(flip)!: consolidate internals and trim the public surface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - geometry lives in one module instead of being split across animate/ and flip/ - cancel-controller folded into controller-slot; scope into bridge; observer-manager + scheduler into tracking/observers - delta math (computeDelta, isIdentityDelta, diagonal, rectsEqual, FlipDelta, DeltaOptions) is no longer exported — it is an animator internal Co-Authored-By: Claude Opus 5 (1M context) --- .../flip/animation/animator.svelte.test.ts | 36 +++++ src/lib/flip/animation/animator.ts | 20 ++- .../flip/animation/cancel-controller.test.ts | 31 ---- src/lib/flip/animation/cancel-controller.ts | 14 -- src/lib/flip/animation/controller-slot.ts | 17 ++- src/lib/flip/geometry.test.ts | 60 ++++++-- src/lib/flip/geometry.ts | 138 ++++++++++++++++-- src/lib/flip/index.ts | 62 ++++---- src/lib/flip/integration/attachment.svelte.ts | 8 +- src/lib/flip/integration/bridge.test.ts | 56 +++---- src/lib/flip/integration/bridge.ts | 37 ++--- src/lib/flip/integration/scope.test.ts | 57 -------- src/lib/flip/integration/scope.ts | 32 ---- src/lib/flip/integration/switcher.svelte.ts | 2 +- src/lib/flip/options.test.ts | 4 +- src/lib/flip/options.ts | 13 +- .../flip/tracking/observer-manager.test.ts | 51 ------- src/lib/flip/tracking/observer-manager.ts | 22 --- src/lib/flip/tracking/observers.test.ts | 63 +++++--- src/lib/flip/tracking/observers.ts | 49 +++---- src/lib/flip/tracking/scheduler.test.ts | 101 ------------- src/lib/flip/tracking/scheduler.ts | 39 ----- src/lib/flip/types.ts | 13 +- 23 files changed, 372 insertions(+), 553 deletions(-) create mode 100644 src/lib/flip/animation/animator.svelte.test.ts delete mode 100644 src/lib/flip/animation/cancel-controller.test.ts delete mode 100644 src/lib/flip/animation/cancel-controller.ts delete mode 100644 src/lib/flip/integration/scope.test.ts delete mode 100644 src/lib/flip/integration/scope.ts delete mode 100644 src/lib/flip/tracking/observer-manager.test.ts delete mode 100644 src/lib/flip/tracking/observer-manager.ts delete mode 100644 src/lib/flip/tracking/scheduler.test.ts delete mode 100644 src/lib/flip/tracking/scheduler.ts diff --git a/src/lib/flip/animation/animator.svelte.test.ts b/src/lib/flip/animation/animator.svelte.test.ts new file mode 100644 index 0000000..b992b92 --- /dev/null +++ b/src/lib/flip/animation/animator.svelte.test.ts @@ -0,0 +1,36 @@ +import { afterEach, describe, expect, it } from 'vitest'; +import { animateFlip } from './animator'; +import { measure } from '../geometry'; + +let element: HTMLDivElement | null = null; + +afterEach(() => { + element?.remove(); + element = null; +}); + +describe('forward FLIP opacity', () => { + it('reverses crossfade endpoints for a forward exit', async () => { + element = document.createElement('div'); + Object.assign(element.style, { + position: 'fixed', + left: '200px', + top: '100px', + width: '240px', + height: '120px' + }); + document.body.appendChild(element); + + const controller = animateFlip({ + element, + from: measure(element), + to: { x: 20, y: 30, width: 40, height: 20 }, + options: { duration: 30, opacity: { from: 0.2, to: 0.8 } }, + forward: true + }); + + expect(controller).not.toBeNull(); + await controller?.finished; + expect(getComputedStyle(element).opacity).toBe('0.2'); + }); +}); diff --git a/src/lib/flip/animation/animator.ts b/src/lib/flip/animation/animator.ts index 4f1cdd6..5d5e413 100644 --- a/src/lib/flip/animation/animator.ts +++ b/src/lib/flip/animation/animator.ts @@ -16,12 +16,12 @@ * the same controller so a single `cancel()` aborts the whole effect. */ -import { animate } from '$lib/animate/core/animate'; -import { buildFlipProps } from '$lib/animate/flip'; -import type { AnimationController, MotionElement } from '$lib/animate/types'; -import { isIdentityDelta, rectsEqual, resolveFlipDelta } from '../geometry'; +import { animate } from '../../animate/core/animate'; +import type { AnimationController, MotionElement } from '../../animate/types'; +import { buildFlipProps, isIdentityDelta, rectsEqual, resolveFlipDelta } from '../geometry'; import type { FlipDelta } from '../geometry'; -import { isBrowser, shouldReduceMotion } from '$lib/shared/browser'; +import { isBrowser, shouldReduceMotion } from '../../shared/browser'; +import { restoreStyleProp, saveStyleProp } from '../../shared/inline-style'; import { DEFAULT_DELAY, resolveDuration, resolveEasing, resolveOpacity } from '../options'; import type { FlipAnimateArgs } from '../types'; @@ -49,11 +49,9 @@ const suppressPointerEvents = ( enabled: boolean | undefined ): (() => void) => { if (!enabled) return () => {}; - const previous = element.style.pointerEvents; - element.style.pointerEvents = 'none'; - return () => { - element.style.pointerEvents = previous; - }; + const previous = saveStyleProp(element.style, 'pointer-events'); + element.style.setProperty('pointer-events', 'none'); + return () => restoreStyleProp(element.style, 'pointer-events', previous); }; /** @@ -121,7 +119,7 @@ export const animateFlip = ({ // CSS variable so this never collides with concurrent animate() calls. const props = buildFlipProps(delta, forward); if (opacity) { - props.opacity = [opacity.from, opacity.to]; + props.opacity = forward ? [opacity.to, opacity.from] : [opacity.from, opacity.to]; } const restorePointerEvents = suppressPointerEvents(element, options.disablePointerEvents); diff --git a/src/lib/flip/animation/cancel-controller.test.ts b/src/lib/flip/animation/cancel-controller.test.ts deleted file mode 100644 index 618e8e0..0000000 --- a/src/lib/flip/animation/cancel-controller.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Tests for cancelController() — the defensive cancel wrapper. - * No DOM access — runs in the `server` vitest project. - */ - -import { describe, expect, it, vi } from 'vitest'; -import { cancelController } from './cancel-controller'; -import type { AnimationController } from '$lib/animate/types'; - -const controller = (cancel: () => void): AnimationController => - ({ cancel }) as unknown as AnimationController; - -describe('cancelController()', () => { - it('no-ops when given null', () => { - expect(() => cancelController(null)).not.toThrow(); - }); - - it('calls cancel() on a live controller', () => { - const cancel = vi.fn(); - cancelController(controller(cancel)); - expect(cancel).toHaveBeenCalledTimes(1); - }); - - it('swallows errors thrown by cancel() (already torn down)', () => { - const cancel = vi.fn(() => { - throw new Error('already cancelled'); - }); - expect(() => cancelController(controller(cancel))).not.toThrow(); - expect(cancel).toHaveBeenCalledTimes(1); - }); -}); diff --git a/src/lib/flip/animation/cancel-controller.ts b/src/lib/flip/animation/cancel-controller.ts deleted file mode 100644 index 29b8c47..0000000 --- a/src/lib/flip/animation/cancel-controller.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { AnimationController } from '$lib/animate/types'; - -/** - * Cancel an in-flight animation controller, ignoring errors thrown when the - * underlying animations have already been torn down (e.g. during cleanup). - */ -export const cancelController = (controller: AnimationController | null): void => { - if (!controller) return; - try { - controller.cancel(); - } catch { - // noop — animation may already be torn down - } -}; diff --git a/src/lib/flip/animation/controller-slot.ts b/src/lib/flip/animation/controller-slot.ts index 1e9370a..17511ba 100644 --- a/src/lib/flip/animation/controller-slot.ts +++ b/src/lib/flip/animation/controller-slot.ts @@ -8,9 +8,8 @@ * cancel / wrap-onEnd / null-on-finish boilerplate. */ -import type { AnimationController } from '$lib/animate/types'; +import type { AnimationController } from '../../animate/types'; import { animateFlip } from './animator'; -import { cancelController } from './cancel-controller'; import type { FlipAnimateArgs } from '../types'; interface ControllerSlot { @@ -22,12 +21,22 @@ interface ControllerSlot { cancel: () => void; } +/** Cancel a controller, tolerating animations already torn down during cleanup. */ +const cancelSafely = (controller: AnimationController | null): void => { + if (!controller) return; + try { + controller.cancel(); + } catch { + // noop — animation may already be torn down + } +}; + export const createControllerSlot = (): ControllerSlot => { let current: AnimationController | null = null; return { run: ({ options, ...rest }) => { - cancelController(current); + cancelSafely(current); current = animateFlip({ ...rest, options: { @@ -44,7 +53,7 @@ export const createControllerSlot = (): ControllerSlot => { }, isActive: () => current !== null, cancel: () => { - cancelController(current); + cancelSafely(current); current = null; } }; diff --git a/src/lib/flip/geometry.test.ts b/src/lib/flip/geometry.test.ts index 14178fb..907233d 100644 --- a/src/lib/flip/geometry.test.ts +++ b/src/lib/flip/geometry.test.ts @@ -1,11 +1,17 @@ /** - * Tests for pure geometry primitives (rectsEqual, diagonal, computeDelta, isIdentityDelta). + * Tests for pure geometry primitives (rectsEqual, diagonal, delta math, isIdentityDelta). * No DOM access — runs in the `server` vitest project. */ import { describe, expect, it } from 'vitest'; -import { computeDelta, diagonal, isIdentityDelta, rectsEqual } from './geometry'; -import type { FlipRect } from './types'; +import { + buildFlipProps, + diagonal, + isIdentityDelta, + rectsEqual, + resolveFlipDelta +} from './geometry'; +import type { FlipRect } from './geometry'; const rect = (x: number, y: number, w: number, h: number): FlipRect => ({ x, @@ -70,10 +76,10 @@ describe('diagonal()', () => { }); }); -describe('computeDelta()', () => { +describe('resolveFlipDelta() — inverse delta math', () => { it('returns identity delta for identical rects', () => { const r = rect(0, 0, 100, 50); - const delta = computeDelta({ from: r, to: r }); + const delta = resolveFlipDelta(r, r, false); expect(delta.dx).toBe(0); expect(delta.dy).toBe(0); expect(delta.sx).toBe(1); @@ -83,7 +89,7 @@ describe('computeDelta()', () => { it('computes translation correctly', () => { const from = rect(10, 20, 100, 50); const to = rect(30, 50, 100, 50); - const delta = computeDelta({ from, to }); + const delta = resolveFlipDelta(from, to, false); expect(delta.dx).toBe(-20); // from.x - to.x expect(delta.dy).toBe(-30); // from.y - to.y expect(delta.sx).toBe(1); @@ -93,7 +99,7 @@ describe('computeDelta()', () => { it('computes scale correctly', () => { const from = rect(0, 0, 200, 100); const to = rect(0, 0, 100, 50); - const delta = computeDelta({ from, to }); + const delta = resolveFlipDelta(from, to, false); expect(delta.sx).toBe(2); // from.width / to.width expect(delta.sy).toBe(2); // from.height / to.height expect(delta.dx).toBe(0); @@ -103,7 +109,7 @@ describe('computeDelta()', () => { it('disabling translate zeroes dx/dy', () => { const from = rect(10, 20, 100, 50); const to = rect(30, 50, 100, 50); - const delta = computeDelta({ from, to }, { translate: false }); + const delta = resolveFlipDelta(from, to, false, { translate: false }); expect(delta.dx).toBe(0); expect(delta.dy).toBe(0); expect(delta.sx).toBe(1); @@ -113,7 +119,7 @@ describe('computeDelta()', () => { it('disabling scale sets sx/sy to 1', () => { const from = rect(0, 0, 200, 100); const to = rect(0, 0, 100, 50); - const delta = computeDelta({ from, to }, { scale: false }); + const delta = resolveFlipDelta(from, to, false, { scale: false }); expect(delta.sx).toBe(1); expect(delta.sy).toBe(1); }); @@ -121,7 +127,7 @@ describe('computeDelta()', () => { it('handles zero-size `to` rect without NaN (guards division by zero)', () => { const from = rect(0, 0, 100, 50); const to = rect(0, 0, 0, 0); - const delta = computeDelta({ from, to }); + const delta = resolveFlipDelta(from, to, false); expect(delta.sx).toBe(1); expect(delta.sy).toBe(1); }); @@ -148,3 +154,37 @@ describe('isIdentityDelta()', () => { expect(isIdentityDelta({ dx: 0, dy: 0, sx: 1, sy: 0.9 })).toBe(false); }); }); + +// --------------------------------------------------------------------------- +// FLIP direction — the inverse / forward contract. The animator and every +// attachment route through `resolveFlipDelta`, so these guard the forward swap +// directly, not just the keyframe pairing. (`measure` needs DOM globals and is +// covered by the `client` browser project.) +// --------------------------------------------------------------------------- + +describe('resolveFlipDelta() direction', () => { + // Element physically at {x:0,w:100}; we want it to look like {x:200,w:50}. + const current = rect(0, 0, 100, 50); + const target = rect(200, 0, 50, 50); + + it('inverse FLIP returns the (from − to) transform placing the element at `from`', () => { + // from = old rect, to = current DOM position; no swap. + const delta = resolveFlipDelta(target, current, false); + expect(delta.dx).toBe(200); // target.x − current.x + expect(delta.sx).toBe(0.5); // target.w / current.w + const props = buildFlipProps(delta, false); + expect(props.flipX).toEqual(['200px', '0px']); // starts offset, ends at rest + }); + + it('forward FLIP swaps the pair so the element is driven toward the target', () => { + // from = current, to = target, forward = true → swap to (to − from). + const delta = resolveFlipDelta(current, target, true); + // Swapped: dx = target.x − current.x = +200 (NOT current.x − target.x = −200), + // sx = target.w / current.w = 0.5 (NOT 2). The swap is what makes the element + // move toward the target rather than the mirror-opposite direction. + expect(delta.dx).toBe(200); + expect(delta.sx).toBe(0.5); + const props = buildFlipProps(delta, true); + expect(props.flipX).toEqual(['0px', '200px']); // starts at rest, ends at target + }); +}); diff --git a/src/lib/flip/geometry.ts b/src/lib/flip/geometry.ts index 7db283d..ac8dd81 100644 --- a/src/lib/flip/geometry.ts +++ b/src/lib/flip/geometry.ts @@ -1,20 +1,77 @@ /** - * Pure geometry primitives for FLIP — no DOM mutation, no side effects. + * FLIP geometry — rect capture and delta math. The single source of truth for + * which way a FLIP moves; the animator and every attachment route through it, + * so no two call sites can disagree on direction. * - * This is a thin flip-layer surface: `rectsEqual` and `diagonal` live here, - * while delta math (`computeDelta`, `isIdentityDelta`) and the transform-aware - * rect reader (`measure`, aliased to `captureRect`) are owned by the lower - * `animate()` layer and re-exported so flip consumers keep a single import. + * Only `measure` / `measureVisual` touch the DOM (read-only); everything else + * is pure. */ -import { captureRect, captureVisualRect } from '$lib/animate/flip'; -import type { FlipRect } from './types'; +import { measureWithoutAncestorTransforms } from '../animate/properties/properties'; +import type { AnimateProps } from '../animate/types'; + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- + +/** Axis-aligned bounding rectangle in viewport coordinates. */ +export interface FlipRect { + x: number; + y: number; + width: number; + height: number; +} + +/** A pair of rects describing a layout change (`from` → `to`). */ +export interface FlipRectPair { + from: FlipRect; + to: FlipRect; +} + +export interface FlipDelta { + /** Horizontal translate component (`from.x - to.x`). */ + dx: number; + /** Vertical translate component (`from.y - to.y`). */ + dy: number; + /** Horizontal scale component (`from.width / to.width`). */ + sx: number; + /** Vertical scale component (`from.height / to.height`). */ + sy: number; +} + +interface DeltaOptions { + translate?: boolean; + scale?: boolean; +} + +export const DEFAULT_DURATION = 280; + +// --------------------------------------------------------------------------- +// Measurement +// --------------------------------------------------------------------------- /** Read the element's layout rect, suppressing any in-flight motion transforms. */ -export const measure = captureRect; +export const measure = (element: Element): FlipRect => { + const { left: x, top: y, width, height } = measureWithoutAncestorTransforms(element); + return { x, y, width, height }; +}; -/** Read the element's live visual rect, keeping its own in-flight transform. */ -export const measureVisual = captureVisualRect; +/** + * Read the element's current *visual* rect — its own in-flight motion + * transform included, ancestor transforms still suppressed. Use this as the + * `from` rect when interrupting an in-flight FLIP so the replacement animation + * starts exactly where the element is on-screen, instead of snapping to its + * resting layout box first. + */ +export const measureVisual = (element: Element): FlipRect => { + const { + left: x, + top: y, + width, + height + } = measureWithoutAncestorTransforms(element, { suppressSelf: false }); + return { x, y, width, height }; +}; /** Approximate equality so sub-pixel jitter doesn't trigger reflows. */ export const rectsEqual = (a: FlipRect, b: FlipRect, epsilon = 0.5): boolean => @@ -27,7 +84,60 @@ export const rectsEqual = (a: FlipRect, b: FlipRect, epsilon = 0.5): boolean => export const diagonal = (a: FlipRect, b: FlipRect): number => Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2); -// Delta math is owned by the lower `animate` layer — re-export so flip-layer -// consumers keep a single `./geometry` import surface. -export { computeDelta, isIdentityDelta, resolveFlipDelta } from '$lib/animate/flip'; -export type { FlipDelta, DeltaOptions } from '$lib/animate/flip'; +// --------------------------------------------------------------------------- +// Delta math +// --------------------------------------------------------------------------- + +/** + * Compute the inverted transform that places the element back at `from`. + * Components disabled in `opts` resolve to their identity. + */ +const computeDelta = ( + { from, to }: FlipRectPair, + { translate = true, scale = true }: DeltaOptions = {} +): FlipDelta => ({ + dx: translate ? from.x - to.x : 0, + dy: translate ? from.y - to.y : 0, + sx: scale && to.width > 0 ? from.width / to.width : 1, + sy: scale && to.height > 0 ? from.height / to.height : 1 +}); + +/** True when the delta would produce no visible movement. */ +export const isIdentityDelta = (delta: FlipDelta): boolean => + delta.dx === 0 && delta.dy === 0 && delta.sx === 1 && delta.sy === 1; + +/** + * Resolve the FLIP delta for a layout change, honoring direction. + * + * Inverse (`forward: false`): DOM is at `to`; the delta is the inverse + * transform `(from − to)` that places the element back at `from`. + * Forward (`forward: true`): DOM is at `from`; the rect pair is swapped so the + * delta becomes `(to − from)`, driving the element visually toward `to`. + */ +export const resolveFlipDelta = ( + from: FlipRect, + to: FlipRect, + forward: boolean, + opts?: DeltaOptions +): FlipDelta => computeDelta(forward ? { from: to, to: from } : { from, to }, opts); + +/** + * Build the `animate()` props object for a FLIP delta. + * + * Inverse (default): DOM is at `to`; apply `[Δ→0]` to start visually at `from`. + * Forward: DOM is at `from`; apply `[0→Δ]` to drive visually toward `to`. + */ +export const buildFlipProps = ({ dx, dy, sx, sy }: FlipDelta, forward: boolean): AnimateProps => { + // `pair` orders the [from, to] keyframe by direction; `translate`/`scale` + // capture each component's unit and identity so they live in one place. + const pair = (delta: string, identity: string): [string, string] => + forward ? [identity, delta] : [delta, identity]; + const translate = (v: number): [string, string] => pair(`${v}px`, '0px'); + const scale = (v: number): [string, string] => pair(`${v}`, '1'); + return { + flipX: translate(dx), + flipY: translate(dy), + flipScaleX: scale(sx), + flipScaleY: scale(sy) + }; +}; diff --git a/src/lib/flip/index.ts b/src/lib/flip/index.ts index 4300a94..d7cb60d 100644 --- a/src/lib/flip/index.ts +++ b/src/lib/flip/index.ts @@ -1,18 +1,18 @@ /** * Public entry point for the FLIP module. * - * - Low-level primitives (`animateFlip`, `createFlipScope`, `createLayoutBridge`, …) - * are re-exported for consumers that need direct access. - * - High-level helpers (`flip`, `snapshotRect`, `flipFrom`) live here so - * callers import from a single path instead of from a parallel barrel. + * Everything a consumer needs — `flip`, `snapshotRect`, `flipFrom`, + * `createFlipScope`, `anchoredFlip` — lives here. Observers, schedulers, and + * the layout bridge are internals and deliberately not exported. */ import type { Attachment } from 'svelte/attachments'; -import type { AnimationController } from '$lib/animate/types'; +import type { AnimationController } from '../animate/types'; import { animateFlip } from './animation/animator'; import { createFlipAttachment } from './integration/attachment.svelte'; +import { createLayoutBridge } from './integration/bridge'; import { measure } from './geometry'; -import type { FlipOptions, FlipOptionsInput, FlipRect, MotionElement } from './types'; +import type { FlipOptions, FlipOptionsInput, FlipRect, FlipScope, MotionElement } from './types'; // --------------------------------------------------------------------------- // High-level API @@ -44,20 +44,32 @@ export const flipFrom = ( ): AnimationController | null => animateFlip({ element, from, to: measure(element), options }); /** - * Animate an element from its current position to a captured rect. + * Create an isolated FLIP scope with a shared-layout registry. + * Use `layoutId` on attachments from the same scope for cross-component + * shared-element transitions. No global state involved. * - * This is a *forward* FLIP: the DOM stays at its current position while the - * element is driven visually toward `to` via keyframes `[0 → Δ]`. Use it for - * collapse / exit animations where the DOM has not yet been moved (e.g. the - * element is about to be removed). Standard inverse-FLIP (`flipFrom`) requires - * the DOM to already be at the target position. + * @example + * ```ts + * const { flip } = createFlipScope(); + * ``` + * ```svelte + *
    ...
    + * ``` */ -export const flipTo = ( - element: MotionElement, - to: FlipRect, - options: FlipOptions = {} -): AnimationController | null => - animateFlip({ element, from: measure(element), to, options, forward: true }); +export const createFlipScope = (): FlipScope => { + const bridge = createLayoutBridge(); + return { + flip: (input?: FlipOptionsInput) => createFlipAttachment(input, bridge) + }; +}; + +export { anchoredFlip } from './anchored'; +export type { + AnchoredFlipNodeFunction, + AnchoredFlipOptions, + AnchoredFlipReference, + AnchoredFlipReferenceGetter +} from './anchored'; // --------------------------------------------------------------------------- // Low-level re-exports @@ -67,15 +79,9 @@ export { createFlipSwitcher } from './integration/switcher.svelte'; export type { FlipSwitcher, FlipSwitchRole } from './integration/switcher.svelte'; export { animateFlip } from './animation/animator'; -export { createFlipAttachment } from './integration/attachment.svelte'; -export { createFlipScope } from './integration/scope'; -export { createLayoutBridge } from './integration/bridge'; -export { computeDelta, diagonal, isIdentityDelta, measure, rectsEqual } from './geometry'; -export { createObserverManager } from './tracking/observer-manager'; -export type { ObserverManager } from './tracking/observer-manager'; -export { createReflowScheduler } from './tracking/scheduler'; +export { measure } from './geometry'; +// Public because `FlipOptions.auto` accepts an ObserverManager. +export { createObserverManager } from './tracking/observers'; +export type { ObserverManager } from './tracking/observers'; -export type { FlipDelta, DeltaOptions } from './geometry'; -export type { LayoutBridgeHandle } from './integration/bridge'; -export type { ReflowScheduler } from './tracking/scheduler'; export type * from './types'; diff --git a/src/lib/flip/integration/attachment.svelte.ts b/src/lib/flip/integration/attachment.svelte.ts index 08af591..c354e6e 100644 --- a/src/lib/flip/integration/attachment.svelte.ts +++ b/src/lib/flip/integration/attachment.svelte.ts @@ -9,13 +9,13 @@ import { untrack } from 'svelte'; import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '$lib/shared/browser'; +import { isBrowser } from '../../shared/browser'; +import { createFrameBatch } from '../../shared/frame-batch'; import type { LayoutBridge } from './bridge'; import { createControllerSlot } from '../animation/controller-slot'; import { measure, measureVisual, rectsEqual } from '../geometry'; -import type { ObserverManager } from '../tracking/observer-manager'; +import type { ObserverManager } from '../tracking/observers'; import { readOptions } from '../options'; -import { createReflowScheduler } from '../tracking/scheduler'; import type { FlipAuto, FlipOptions, FlipOptionsInput, FlipRect, MotionElement } from '../types'; /** @@ -64,7 +64,7 @@ export const createFlipAttachment = ( run(from, next); }; - const scheduler = createReflowScheduler(reflow); + const scheduler = createFrameBatch(reflow); let connectedManager: ObserverManager | null = null; const syncObservers = (): void => { diff --git a/src/lib/flip/integration/bridge.test.ts b/src/lib/flip/integration/bridge.test.ts index 72937a4..2d5102a 100644 --- a/src/lib/flip/integration/bridge.test.ts +++ b/src/lib/flip/integration/bridge.test.ts @@ -15,55 +15,44 @@ const rect = (x = 0, y = 0, w = 100, h = 50): FlipRect => ({ }); describe('createLayoutBridge()', () => { - it('returns an object with bridge and clear', () => { - const { bridge, clear } = createLayoutBridge(); + it('returns a read/write pair', () => { + const bridge = createLayoutBridge(); expect(typeof bridge.writeLayout).toBe('function'); expect(typeof bridge.readLayout).toBe('function'); - expect(typeof clear).toBe('function'); }); it('readLayout returns null for an unknown id', () => { - const { bridge } = createLayoutBridge(); + const bridge = createLayoutBridge(); expect(bridge.readLayout('unknown')).toBeNull(); }); it('writeLayout + readLayout round-trips the rect', () => { - const { bridge } = createLayoutBridge(); + const bridge = createLayoutBridge(); const r = rect(10, 20, 300, 150); bridge.writeLayout('hero', r); expect(bridge.readLayout('hero')).toEqual(r); }); - it('readLayout deletes the entry on expiry', () => { + it('readLayout returns the rect while still within the 250ms TTL', () => { vi.useFakeTimers(); - const { bridge } = createLayoutBridge(100); - bridge.writeLayout('card', rect()); - // Advance past TTL - vi.advanceTimersByTime(150); - expect(bridge.readLayout('card')).toBeNull(); - vi.useRealTimers(); - }); - - it('readLayout returns the rect while still within TTL', () => { - vi.useFakeTimers(); - const { bridge } = createLayoutBridge(200); + const bridge = createLayoutBridge(); bridge.writeLayout('card', rect(1, 2, 3, 4)); - vi.advanceTimersByTime(100); + vi.advanceTimersByTime(200); expect(bridge.readLayout('card')).toEqual(rect(1, 2, 3, 4)); vi.useRealTimers(); }); - it('clear() removes all stored entries', () => { - const { bridge, clear } = createLayoutBridge(); - bridge.writeLayout('a', rect()); - bridge.writeLayout('b', rect(5, 5)); - clear(); - expect(bridge.readLayout('a')).toBeNull(); - expect(bridge.readLayout('b')).toBeNull(); + it('readLayout deletes the entry once the TTL has passed', () => { + vi.useFakeTimers(); + const bridge = createLayoutBridge(); + bridge.writeLayout('card', rect()); + vi.advanceTimersByTime(251); + expect(bridge.readLayout('card')).toBeNull(); + vi.useRealTimers(); }); it('writeLayout overwrites a previously stored rect', () => { - const { bridge } = createLayoutBridge(); + const bridge = createLayoutBridge(); bridge.writeLayout('id', rect(0, 0, 100, 50)); const newer = rect(99, 99, 200, 200); bridge.writeLayout('id', newer); @@ -73,18 +62,7 @@ describe('createLayoutBridge()', () => { it('separate bridges are independent', () => { const a = createLayoutBridge(); const b = createLayoutBridge(); - a.bridge.writeLayout('shared', rect(1, 2, 3, 4)); - expect(b.bridge.readLayout('shared')).toBeNull(); - }); - - it('custom ttlMs is respected', () => { - vi.useFakeTimers(); - const { bridge } = createLayoutBridge(50); - bridge.writeLayout('x', rect()); - vi.advanceTimersByTime(49); - expect(bridge.readLayout('x')).not.toBeNull(); - vi.advanceTimersByTime(2); - expect(bridge.readLayout('x')).toBeNull(); - vi.useRealTimers(); + a.writeLayout('shared', rect(1, 2, 3, 4)); + expect(b.readLayout('shared')).toBeNull(); }); }); diff --git a/src/lib/flip/integration/bridge.ts b/src/lib/flip/integration/bridge.ts index 9a2a9ac..3ccf6bb 100644 --- a/src/lib/flip/integration/bridge.ts +++ b/src/lib/flip/integration/bridge.ts @@ -1,9 +1,10 @@ /** * Layout bridge for shared-element transitions. * - * Stores the last-known rect for a `layoutId` with a TTL so a sibling - * mounting just after another unmounts can read the position without - * incurring a global registry. + * Stores the last-known rect for a `layoutId` so a sibling mounting just after + * another unmounts can read the position without incurring a global registry. + * Records expire after {@link LAYOUT_TTL_MS} — a handoff happens within a frame + * or two, so anything older is stale by definition. */ import type { FlipRect } from '../types'; @@ -18,45 +19,27 @@ export interface LayoutBridge { writeLayout: (id: string, rect: FlipRect) => void; } -export interface LayoutBridgeHandle { - bridge: LayoutBridge; - /** Drop every stored rect — useful between routes or in tests. */ - clear: () => void; -} - -/** Default lifetime of an unread layout record, in ms. */ -const DEFAULT_LAYOUT_TTL_MS = 250; +/** Lifetime of an unread layout record, in ms. */ +const LAYOUT_TTL_MS = 250; const now = (): number => (typeof performance !== 'undefined' ? performance.now() : Date.now()); -/** - * Create an in-memory layout registry exposing the {@link LayoutBridge} - * interface plus a `clear()` escape hatch. - * - * @param ttlMs How long an unread record stays valid. Defaults to - * {@link DEFAULT_LAYOUT_TTL_MS}. - */ -export const createLayoutBridge = (ttlMs?: number): LayoutBridgeHandle => { - const ttl = ttlMs ?? DEFAULT_LAYOUT_TTL_MS; +/** Create an in-memory, scope-local layout registry. */ +export const createLayoutBridge = (): LayoutBridge => { const registry = new Map(); - const bridge: LayoutBridge = { + return { writeLayout: (id, rect) => { registry.set(id, { rect, timestamp: now() }); }, readLayout: (id) => { const entry = registry.get(id); if (!entry) return null; - if (now() - entry.timestamp > ttl) { + if (now() - entry.timestamp > LAYOUT_TTL_MS) { registry.delete(id); return null; } return entry.rect; } }; - - return { - bridge, - clear: () => registry.clear() - }; }; diff --git a/src/lib/flip/integration/scope.test.ts b/src/lib/flip/integration/scope.test.ts deleted file mode 100644 index 4a8571d..0000000 --- a/src/lib/flip/integration/scope.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Tests for createFlipScope(). - * Verifies the returned API surface and the shared-layout bridge integration. - * Runs in the `server` vitest project. - */ - -import { describe, expect, it } from 'vitest'; -import { createFlipScope } from './scope'; - -describe('createFlipScope()', () => { - it('returns an object with flip and clear', () => { - const scope = createFlipScope(); - expect(typeof scope.flip).toBe('function'); - expect(typeof scope.clear).toBe('function'); - }); - - it('flip() returns a function (Svelte attachment)', () => { - const { flip } = createFlipScope(); - const attachment = flip(); - expect(typeof attachment).toBe('function'); - }); - - it('flip() accepts options', () => { - const { flip } = createFlipScope(); - expect(() => flip({ duration: 300 })).not.toThrow(); - }); - - it('flip() accepts no options', () => { - const { flip } = createFlipScope(); - expect(() => flip()).not.toThrow(); - }); - - it('clear() does not throw on empty scope', () => { - const { clear } = createFlipScope(); - expect(() => clear()).not.toThrow(); - }); - - it('accepts custom layoutTtlMs option', () => { - expect(() => createFlipScope({ layoutTtlMs: 500 })).not.toThrow(); - }); - - it('each call returns an independent scope', () => { - const a = createFlipScope(); - const b = createFlipScope(); - // Scopes use independent bridges; they don't share state - expect(a).not.toBe(b); - }); - - it('clear() is independent between scopes (no shared state)', () => { - // Verify scopes are truly isolated — clearing one does not affect the other. - // We test this indirectly: both scopes' clear() can run without throwing. - const a = createFlipScope(); - const b = createFlipScope(); - a.clear(); - expect(() => b.clear()).not.toThrow(); - }); -}); diff --git a/src/lib/flip/integration/scope.ts b/src/lib/flip/integration/scope.ts deleted file mode 100644 index 41cbddf..0000000 --- a/src/lib/flip/integration/scope.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Public scope factory. - * - * Wraps the registry from `bridge.ts` together with the attachment factory - * so callers get a self-contained shared-layout namespace. - */ - -import { createFlipAttachment } from './attachment.svelte'; -import { createLayoutBridge } from './bridge'; -import type { CreateFlipScopeOptions, FlipOptionsInput, FlipScope } from '../types'; - -/** - * Create an isolated FLIP scope with a shared-layout registry. - * Use `layoutId` on attachments from the same scope for cross-component - * shared-element transitions. No global state involved. - * - * @example - * ```ts - * const { flip } = createFlipScope(); - * ``` - * ```svelte - *
    ...
    - * ``` - */ -export const createFlipScope = (opts: CreateFlipScopeOptions = {}): FlipScope => { - const { bridge, clear } = createLayoutBridge(opts.layoutTtlMs); - - return { - flip: (input?: FlipOptionsInput) => createFlipAttachment(input, bridge), - clear - }; -}; diff --git a/src/lib/flip/integration/switcher.svelte.ts b/src/lib/flip/integration/switcher.svelte.ts index 703872d..8262dd1 100644 --- a/src/lib/flip/integration/switcher.svelte.ts +++ b/src/lib/flip/integration/switcher.svelte.ts @@ -20,7 +20,7 @@ import { untrack } from 'svelte'; import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '$lib/shared/browser'; +import { isBrowser } from '../../shared/browser'; import { createControllerSlot } from '../animation/controller-slot'; import { measure } from '../geometry'; import type { FlipOptions, FlipRect, MotionElement } from '../types'; diff --git a/src/lib/flip/options.test.ts b/src/lib/flip/options.test.ts index 7785051..2dda270 100644 --- a/src/lib/flip/options.test.ts +++ b/src/lib/flip/options.test.ts @@ -7,13 +7,13 @@ import { describe, expect, it } from 'vitest'; import { easeOut } from '$lib/easing'; import { DEFAULT_DELAY, - DEFAULT_DURATION, - DEFAULT_EASING, readOptions, resolveDuration, resolveEasing, resolveOpacity } from './options'; +import { DEFAULT_DURATION } from './geometry'; +import { DEFAULT_EASING } from '../animate/keyframes/easing-utils'; import type { FlipRectPair } from './types'; const pairAt = (dx = 0, dy = 0): FlipRectPair => ({ diff --git a/src/lib/flip/options.ts b/src/lib/flip/options.ts index d13ca56..e0b7360 100644 --- a/src/lib/flip/options.ts +++ b/src/lib/flip/options.ts @@ -3,12 +3,10 @@ * animator. All helpers are pure — no DOM access, no side effects. */ -import { CSS_EASINGS } from '$lib/easing'; -import type { EasingFn } from '$lib/shared/types'; -import { DEFAULT_FLIP_DURATION as DEFAULT_DURATION } from '$lib/animate/flip'; -import { DEFAULT_EASING } from '$lib/animate/keyframes/easing-utils'; -import { atLeast0 } from '$lib/shared/math'; -import { diagonal } from './geometry'; +import { CSS_EASINGS } from '../easing'; +import type { EasingFn } from '../shared/types'; +import { DEFAULT_EASING } from '../animate/keyframes/easing-utils'; +import { DEFAULT_DURATION, diagonal } from './geometry'; import type { FlipDuration, FlipEasing, @@ -18,7 +16,6 @@ import type { FlipRectPair } from './types'; -export { DEFAULT_DURATION, DEFAULT_EASING }; export const DEFAULT_DELAY = 0; /** Unwrap an options thunk; thunks let callers track reactive state. */ @@ -34,7 +31,7 @@ export const readOptions = (input: FlipOptionsInput): FlipOptions => { export const resolveDuration = (d: FlipDuration | undefined, rects: FlipRectPair): number => { if (d == null) return DEFAULT_DURATION; const raw = typeof d === 'function' ? d(diagonal(rects.from, rects.to), rects) : d; - return atLeast0(raw); + return Math.max(0, raw); }; /** Normalize the `opacity` shorthand into a fully-populated config or `null`. */ diff --git a/src/lib/flip/tracking/observer-manager.test.ts b/src/lib/flip/tracking/observer-manager.test.ts deleted file mode 100644 index 4d4a1a3..0000000 --- a/src/lib/flip/tracking/observer-manager.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Tests for createObserverManager(). - * Delegates to createLayoutObservers internally; tested at the manager level. - * Runs in the `server` vitest project. - */ - -import { describe, expect, it, vi } from 'vitest'; -import { createObserverManager } from './observer-manager'; - -const fakeEl = { parentElement: null } as unknown as Element; - -describe('createObserverManager()', () => { - it('returns an object with connect and disconnect', () => { - const mgr = createObserverManager(); - expect(typeof mgr.connect).toBe('function'); - expect(typeof mgr.disconnect).toBe('function'); - }); - - it('connect() does not throw', () => { - const mgr = createObserverManager(); - expect(() => mgr.connect(fakeEl, () => {})).not.toThrow(); - }); - - it('disconnect() does not throw before connect()', () => { - const mgr = createObserverManager(); - expect(() => mgr.disconnect()).not.toThrow(); - }); - - it('disconnect() does not throw after connect()', () => { - const mgr = createObserverManager(); - mgr.connect(fakeEl, () => {}); - expect(() => mgr.disconnect()).not.toThrow(); - }); - - it('calling connect() twice disconnects the previous observers', () => { - const mgr = createObserverManager(); - const el2 = { parentElement: null } as unknown as Element; - mgr.connect(fakeEl, () => {}); - // Second connect should not throw — previous inner is disconnected first - expect(() => mgr.connect(el2, vi.fn())).not.toThrow(); - }); - - it('disconnect() is idempotent', () => { - const mgr = createObserverManager(); - mgr.connect(fakeEl, () => {}); - expect(() => { - mgr.disconnect(); - mgr.disconnect(); - }).not.toThrow(); - }); -}); diff --git a/src/lib/flip/tracking/observer-manager.ts b/src/lib/flip/tracking/observer-manager.ts deleted file mode 100644 index f8056c1..0000000 --- a/src/lib/flip/tracking/observer-manager.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createLayoutObservers, type LayoutObservers } from './observers'; - -export interface ObserverManager { - connect: (element: Element, onChange: () => void) => void; - disconnect: () => void; -} - -export const createObserverManager = (): ObserverManager => { - let inner: LayoutObservers | null = null; - - return { - connect(element, onChange) { - inner?.disconnect(); - inner = createLayoutObservers({ element, onChange }); - inner.connect(); - }, - disconnect() { - inner?.disconnect(); - inner = null; - } - }; -}; diff --git a/src/lib/flip/tracking/observers.test.ts b/src/lib/flip/tracking/observers.test.ts index e612fd8..226f99e 100644 --- a/src/lib/flip/tracking/observers.test.ts +++ b/src/lib/flip/tracking/observers.test.ts @@ -1,37 +1,39 @@ /** - * Tests for createLayoutObservers(). + * Tests for createObserverManager(). * In non-DOM environments (node), ResizeObserver and MutationObserver are * undefined — connect() is a safe no-op, and disconnect() is idempotent. * Runs in the `server` vitest project. */ import { describe, expect, it, vi } from 'vitest'; -import { createLayoutObservers } from './observers'; +import { createObserverManager } from './observers'; const fakeEl = { parentElement: null } as unknown as Element; -describe('createLayoutObservers() — non-DOM environment', () => { +const noop = (): void => {}; + +describe('createObserverManager() — non-DOM environment', () => { it('returns an object with connect and disconnect', () => { - const obs = createLayoutObservers({ element: fakeEl, onChange: () => {} }); + const obs = createObserverManager(); expect(typeof obs.connect).toBe('function'); expect(typeof obs.disconnect).toBe('function'); }); it('connect() does not throw when observers are unavailable', () => { - const obs = createLayoutObservers({ element: fakeEl, onChange: () => {} }); - expect(() => obs.connect()).not.toThrow(); + const obs = createObserverManager(); + expect(() => obs.connect(fakeEl, noop)).not.toThrow(); }); it('disconnect() does not throw before connect()', () => { - const obs = createLayoutObservers({ element: fakeEl, onChange: () => {} }); + const obs = createObserverManager(); expect(() => obs.disconnect()).not.toThrow(); }); it('disconnect() is idempotent', () => { - const obs = createLayoutObservers({ element: fakeEl, onChange: () => {} }); - obs.connect(); + const obs = createObserverManager(); + obs.connect(fakeEl, noop); expect(() => { obs.disconnect(); obs.disconnect(); @@ -39,14 +41,14 @@ describe('createLayoutObservers() — non-DOM environment', () => { }); it('re-connect() after disconnect() does not throw', () => { - const obs = createLayoutObservers({ element: fakeEl, onChange: () => {} }); - obs.connect(); + const obs = createObserverManager(); + obs.connect(fakeEl, noop); obs.disconnect(); - expect(() => obs.connect()).not.toThrow(); + expect(() => obs.connect(fakeEl, noop)).not.toThrow(); }); }); -describe('createLayoutObservers() — with mocked observers', () => { +describe('createObserverManager() — with mocked observers', () => { it('calls ResizeObserver.observe when available', () => { const observe = vi.fn(); const disconnect = vi.fn(); @@ -61,9 +63,8 @@ describe('createLayoutObservers() — with mocked observers', () => { const origRO = (globalThis as Record).ResizeObserver; (globalThis as Record).ResizeObserver = MockResizeObserver; - const onChange = vi.fn(); - const obs = createLayoutObservers({ element: fakeEl, onChange }); - obs.connect(); + const obs = createObserverManager(); + obs.connect(fakeEl, vi.fn()); expect(constructorCalls).toHaveLength(1); expect(observe).toHaveBeenCalledWith(fakeEl); @@ -81,8 +82,8 @@ describe('createLayoutObservers() — with mocked observers', () => { const origRO = (globalThis as Record).ResizeObserver; (globalThis as Record).ResizeObserver = MockResizeObserver; - const obs = createLayoutObservers({ element: fakeEl, onChange: vi.fn() }); - obs.connect(); + const obs = createObserverManager(); + obs.connect(fakeEl, vi.fn()); obs.disconnect(); expect(roDisconnect).toHaveBeenCalledOnce(); @@ -90,6 +91,28 @@ describe('createLayoutObservers() — with mocked observers', () => { (globalThis as Record).ResizeObserver = origRO; }); + it('re-connecting drops the previous element’s observers', () => { + const roDisconnect = vi.fn(); + const observe = vi.fn(); + class MockResizeObserver { + observe = observe; + disconnect = roDisconnect; + constructor() {} + } + const origRO = (globalThis as Record).ResizeObserver; + (globalThis as Record).ResizeObserver = MockResizeObserver; + + const other = { parentElement: null } as unknown as Element; + const obs = createObserverManager(); + obs.connect(fakeEl, vi.fn()); + obs.connect(other, vi.fn()); + + expect(roDisconnect).toHaveBeenCalledOnce(); + expect(observe).toHaveBeenNthCalledWith(2, other); + + (globalThis as Record).ResizeObserver = origRO; + }); + it('calls MutationObserver.observe on the parent element when available', () => { const moObserve = vi.fn(); const moDisconnect = vi.fn(); @@ -104,8 +127,8 @@ describe('createLayoutObservers() — with mocked observers', () => { const parent = { parentElement: null } as unknown as Element; const elWithParent = { parentElement: parent } as unknown as Element; - const obs = createLayoutObservers({ element: elWithParent, onChange: vi.fn() }); - obs.connect(); + const obs = createObserverManager(); + obs.connect(elWithParent, vi.fn()); expect(moObserve).toHaveBeenCalledWith(parent, { childList: true, diff --git a/src/lib/flip/tracking/observers.ts b/src/lib/flip/tracking/observers.ts index 8709a1c..04972af 100644 --- a/src/lib/flip/tracking/observers.ts +++ b/src/lib/flip/tracking/observers.ts @@ -2,25 +2,17 @@ * Auto-tracking observers. * * Wraps a `ResizeObserver` on the element plus a `MutationObserver` on its - * parent (sibling reorder/insertion/removal) into a single connect/disconnect - * pair. Connection is idempotent, and re-`connect()`ing rewires to the - * current parent (handy when the element is reparented). + * parent (sibling reorder/insertion/removal) behind one connect/disconnect + * pair. `connect()` is idempotent and rewires to the element's current parent, + * so re-connecting after a reparent (or with a different element) is safe. */ -export interface LayoutObservers { - connect: () => void; +export interface ObserverManager { + connect: (element: Element, onChange: () => void) => void; disconnect: () => void; } -interface LayoutObserverArgs { - element: Element; - onChange: () => void; -} - -export const createLayoutObservers = ({ - element, - onChange -}: LayoutObserverArgs): LayoutObservers => { +export const createObserverManager = (): ObserverManager => { let resizeObserver: ResizeObserver | null = null; let mutationObserver: MutationObserver | null = null; @@ -31,20 +23,21 @@ export const createLayoutObservers = ({ mutationObserver = null; }; - const connect = (): void => { - disconnect(); - - if (typeof ResizeObserver === 'function') { - resizeObserver = new ResizeObserver(onChange); - resizeObserver.observe(element); - } - - const parent = element.parentElement; - if (parent && typeof MutationObserver === 'function') { - mutationObserver = new MutationObserver(onChange); - mutationObserver.observe(parent, { childList: true, subtree: false }); + return { + disconnect, + connect(element, onChange) { + disconnect(); + + if (typeof ResizeObserver === 'function') { + resizeObserver = new ResizeObserver(onChange); + resizeObserver.observe(element); + } + + const parent = element.parentElement; + if (parent && typeof MutationObserver === 'function') { + mutationObserver = new MutationObserver(onChange); + mutationObserver.observe(parent, { childList: true, subtree: false }); + } } }; - - return { connect, disconnect }; }; diff --git a/src/lib/flip/tracking/scheduler.test.ts b/src/lib/flip/tracking/scheduler.test.ts deleted file mode 100644 index 8f90c72..0000000 --- a/src/lib/flip/tracking/scheduler.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Tests for the RAF-batched reflow scheduler. - * In non-DOM environments (node), the scheduler falls back to synchronous - * execution — all logic is exercised without a real RAF. - * Runs in the `server` vitest project. - */ - -import { describe, expect, it, vi } from 'vitest'; -import { createReflowScheduler } from './scheduler'; - -describe('createReflowScheduler() — non-DOM (synchronous fallback)', () => { - it('returns an object with schedule and cancel', () => { - const s = createReflowScheduler(() => {}); - expect(typeof s.schedule).toBe('function'); - expect(typeof s.cancel).toBe('function'); - }); - - it('task is called synchronously when schedule() is invoked (no RAF)', () => { - let called = false; - const s = createReflowScheduler(() => { - called = true; - }); - s.schedule(); - expect(called).toBe(true); - }); - - it('task is called exactly once per schedule() when RAF is absent', () => { - let count = 0; - const s = createReflowScheduler(() => count++); - s.schedule(); - s.schedule(); - // Synchronous fallback runs immediately on each call - // (no coalescing needed since there is no async queue) - expect(count).toBeGreaterThanOrEqual(1); - }); - - it('cancel() does not throw even with no pending task', () => { - const s = createReflowScheduler(() => {}); - expect(() => s.cancel()).not.toThrow(); - }); - - it('cancel() after schedule() does not throw', () => { - const s = createReflowScheduler(() => {}); - s.schedule(); - expect(() => s.cancel()).not.toThrow(); - }); - - it('task receives no arguments', () => { - const task = vi.fn(); - const s = createReflowScheduler(task); - s.schedule(); - expect(task).toHaveBeenCalledWith(); - }); -}); - -describe('createReflowScheduler() — with mocked RAF', () => { - it('coalesces multiple schedule() calls into one task invocation', () => { - vi.useFakeTimers(); - let rafCallback: FrameRequestCallback | null = null; - const origRaf = globalThis.requestAnimationFrame; - const origCaf = globalThis.cancelAnimationFrame; - globalThis.requestAnimationFrame = (cb) => { - rafCallback = cb; - return 1; - }; - globalThis.cancelAnimationFrame = () => {}; - - let count = 0; - const s = createReflowScheduler(() => count++); - s.schedule(); - s.schedule(); - s.schedule(); - - expect(count).toBe(0); - rafCallback!(0); - expect(count).toBe(1); - - globalThis.requestAnimationFrame = origRaf; - globalThis.cancelAnimationFrame = origCaf; - vi.useRealTimers(); - }); - - it('cancel() calls cancelAnimationFrame with the scheduled handle', () => { - const origRaf = globalThis.requestAnimationFrame; - const origCaf = globalThis.cancelAnimationFrame; - globalThis.requestAnimationFrame = () => 42; - let cancelled: number | null = null; - globalThis.cancelAnimationFrame = (id) => { - cancelled = id; - }; - - const s = createReflowScheduler(() => {}); - s.schedule(); - s.cancel(); - - expect(cancelled).toBe(42); - - globalThis.requestAnimationFrame = origRaf; - globalThis.cancelAnimationFrame = origCaf; - }); -}); diff --git a/src/lib/flip/tracking/scheduler.ts b/src/lib/flip/tracking/scheduler.ts deleted file mode 100644 index 11b0e37..0000000 --- a/src/lib/flip/tracking/scheduler.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * RAF-batched scheduler. - * - * Multiple `schedule()` calls within the same frame coalesce into a single - * `task()` invocation on the next animation frame. - */ - -export interface ReflowScheduler { - /** Request a deferred run; coalesces with any pending request. */ - schedule: () => void; - /** Drop any pending run (without invoking the task). */ - cancel: () => void; -} - -export const createReflowScheduler = (task: () => void): ReflowScheduler => { - let handle: number | null = null; - - const schedule = (): void => { - if (handle != null) return; - if (typeof requestAnimationFrame !== 'function') { - // Non-DOM environments — run synchronously so tests still observe the - // effect. Real browsers always have RAF. - task(); - return; - } - handle = requestAnimationFrame(() => { - handle = null; - task(); - }); - }; - - const cancel = (): void => { - if (handle == null) return; - cancelAnimationFrame(handle); - handle = null; - }; - - return { schedule, cancel }; -}; diff --git a/src/lib/flip/types.ts b/src/lib/flip/types.ts index f981fb8..f2343c9 100644 --- a/src/lib/flip/types.ts +++ b/src/lib/flip/types.ts @@ -1,7 +1,7 @@ import type { Attachment } from 'svelte/attachments'; -import type { FlipRect, FlipRectPair } from '$lib/animate/flip'; -import type { EasingFn, MotionElement } from '$lib/shared/types'; -import type { ObserverManager } from './tracking/observer-manager'; +import type { FlipRect, FlipRectPair } from './geometry'; +import type { EasingFn, MotionElement } from '../shared/types'; +import type { ObserverManager } from './tracking/observers'; // --------------------------------------------------------------------------- // Core geometry @@ -107,14 +107,7 @@ export interface FlipAnimateArgs { // Public scope API // --------------------------------------------------------------------------- -export interface CreateFlipScopeOptions { - /** Time in ms a layoutId rect remains valid after unmount. Default: 250. */ - layoutTtlMs?: number; -} - export interface FlipScope { /** Attachment factory bound to this scope's shared-layout registry. */ flip: (input?: FlipOptionsInput) => Attachment; - /** Drop all stored layouts (useful between routes / tests). */ - clear: () => void; } From 35f6f20a240c08d482f6b519c503bd8d2a550571 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:46:10 -0400 Subject: [PATCH 12/30] feat(flip): restore flipTo as the mirror of flipFrom flipTo was cut as dead code while flipFrom survived, leaving the surface with a 'from' half and no 'to' half. It is a four-line forward-FLIP wrapper over animateFlip; the symmetry is worth more than the lines. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/flip/index.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib/flip/index.ts b/src/lib/flip/index.ts index d7cb60d..4c52d2c 100644 --- a/src/lib/flip/index.ts +++ b/src/lib/flip/index.ts @@ -43,6 +43,14 @@ export const flipFrom = ( options: FlipOptions = {} ): AnimationController | null => animateFlip({ element, from, to: measure(element), options }); +/** Animate an element from its current position to a captured rect. */ +export const flipTo = ( + element: MotionElement, + to: FlipRect, + options: FlipOptions = {} +): AnimationController | null => + animateFlip({ element, from: measure(element), to, options, forward: true }); + /** * Create an isolated FLIP scope with a shared-layout registry. * Use `layoutId` on attachments from the same scope for cross-component From 0163a14b089382dcb144c0bafc6f9f64c530425b Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:46:23 -0400 Subject: [PATCH 13/30] refactor(gestures): split reorder slot math into reorder-internals The nearest-slot search and ascending-order check are pure functions that were buried in the attachment; testing them no longer needs a browser. Binary search for ordinary linear lists, linear scan for wrapped/grid layouts. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/gestures/reorder-internals.test.ts | 23 +++ src/lib/gestures/reorder-internals.ts | 37 +++++ src/lib/gestures/reorder.svelte.test.ts | 96 +++++++++++- src/lib/gestures/reorder.ts | 163 ++++++++++++++------- 4 files changed, 269 insertions(+), 50 deletions(-) create mode 100644 src/lib/gestures/reorder-internals.test.ts create mode 100644 src/lib/gestures/reorder-internals.ts diff --git a/src/lib/gestures/reorder-internals.test.ts b/src/lib/gestures/reorder-internals.test.ts new file mode 100644 index 0000000..ec20af5 --- /dev/null +++ b/src/lib/gestures/reorder-internals.test.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from 'vitest'; +import { centersAreAscending, nearestCenterIndex } from './reorder-internals'; + +describe('nearestCenterIndex()', () => { + it('finds the same nearest slot at either boundary and between centers', () => { + const centers = [10, 40, 90, 160]; + expect(nearestCenterIndex(centers, -10)).toBe(0); + expect(nearestCenterIndex(centers, 67)).toBe(2); + expect(nearestCenterIndex(centers, 999)).toBe(3); + }); + + it('uses an O(log n) lookup for ascending list centers', () => { + const centers = Array.from({ length: 1024 }, (_, index) => index * 10); + expect(centersAreAscending(centers)).toBe(true); + expect(nearestCenterIndex(centers, 5_555)).toBe(555); + }); + + it('retains linear nearest-slot semantics for non-linear arrangements', () => { + const centers = [10, 90, 40]; + expect(centersAreAscending(centers)).toBe(false); + expect(nearestCenterIndex(centers, 35, false)).toBe(2); + }); +}); diff --git a/src/lib/gestures/reorder-internals.ts b/src/lib/gestures/reorder-internals.ts new file mode 100644 index 0000000..20cd973 --- /dev/null +++ b/src/lib/gestures/reorder-internals.ts @@ -0,0 +1,37 @@ +/** Whether centers describe a normal ascending single-axis list. */ +export const centersAreAscending = (centers: readonly number[]): boolean => { + for (let i = 1; i < centers.length; i++) { + if (centers[i]! < centers[i - 1]!) return false; + } + return true; +}; + +/** Find the nearest slot center, using binary search for ordinary linear lists. */ +export const nearestCenterIndex = ( + centers: readonly number[], + target: number, + ascending = true +): number => { + if (centers.length === 0) return -1; + if (!ascending) return nearestUnsortedCenterIndex(centers, target); + + let low = 0; + let high = centers.length; + while (low < high) { + const middle = (low + high) >>> 1; + if (centers[middle]! < target) low = middle + 1; + else high = middle; + } + if (low === 0) return 0; + if (low === centers.length) return centers.length - 1; + return target - centers[low - 1]! <= centers[low]! - target ? low - 1 : low; +}; + +/** Preserve nearest-slot semantics for non-linear visual arrangements. */ +const nearestUnsortedCenterIndex = (centers: readonly number[], target: number): number => { + let nearest = 0; + for (let i = 1; i < centers.length; i++) { + if (Math.abs(centers[i]! - target) < Math.abs(centers[nearest]! - target)) nearest = i; + } + return nearest; +}; diff --git a/src/lib/gestures/reorder.svelte.test.ts b/src/lib/gestures/reorder.svelte.test.ts index 9af3537..521ab9e 100644 --- a/src/lib/gestures/reorder.svelte.test.ts +++ b/src/lib/gestures/reorder.svelte.test.ts @@ -3,7 +3,7 @@ * browser. Runs in the `client` project. */ -import { afterEach, describe, expect, it } from 'vitest'; +import { afterEach, describe, expect, it, vi } from 'vitest'; import { reorder } from './reorder'; let container: HTMLElement | null = null; @@ -29,6 +29,7 @@ const setup = () => { }; afterEach(() => { + vi.restoreAllMocks(); container?.remove(); container = null; }); @@ -51,6 +52,30 @@ describe('reorder()', () => { expect(order).toEqual(['b', 'a', 'c']); }); + it('composes drag offsets without replacing consumer transforms and restores owned styles', () => { + const { values, els } = setup(); + let order = [...values]; + els[0]!.style.transform = 'rotate(12deg)'; + els[1]!.style.transition = 'opacity 100ms'; + const r = reorder({ items: () => order, onReorder: (next) => (order = next) }); + els.forEach((el, i) => r.item(values[i]!)(el)); + + els[0]!.dispatchEvent(pointer('pointerdown', 20)); + els[0]!.dispatchEvent(pointer('pointermove', 70)); + + expect(els[0]!.style.transform).toBe('rotate(12deg)'); + expect(els[0]!.style.getPropertyValue('--motion-reorder-y')).toBe('50px'); + expect(Number.parseFloat(els[1]!.style.getPropertyValue('--motion-reorder-y'))).toBeCloseTo( + -40 + ); + + els[0]!.dispatchEvent(pointer('pointerup', 70)); + expect(order).toEqual(['b', 'a', 'c']); + expect(els[0]!.style.transform).toBe('rotate(12deg)'); + expect(els[0]!.style.getPropertyValue('--motion-reorder-y')).toBe(''); + expect(els[1]!.style.transition).toBe('opacity 100ms'); + }); + it('does not reorder when the drag stays within its own slot', () => { const { values, els } = setup(); let order = [...values]; @@ -85,6 +110,75 @@ describe('reorder()', () => { expect(order).toEqual(['b', 'c', 'a']); }); + it('uses actual slot centers for variable-size rows', () => { + const { values, els } = setup(); + els[0]!.style.height = '20px'; + els[1]!.style.top = '20px'; + els[1]!.style.height = '100px'; + els[2]!.style.top = '120px'; + let order = [...values]; + const r = reorder({ items: () => order, onReorder: (next) => (order = next) }); + els.forEach((el, i) => r.item(values[i]!)(el)); + + // The second row's center is 70px, not the old average-stride slot at 80px. + els[0]!.dispatchEvent(pointer('pointerdown', 10)); + els[0]!.dispatchEvent(pointer('pointermove', 60)); + els[0]!.dispatchEvent(pointer('pointerup', 60)); + + expect(order).toEqual(['b', 'a', 'c']); + }); + + it('supports recreated or duplicate values through a stable getKey', () => { + const { els } = setup(); + let order = [{ id: 'a' }, { id: 'b' }, { id: 'c' }]; + const r = reorder({ + items: () => order, + getKey: (item) => item.id, + onReorder: (next) => (order = next) + }); + order.forEach((item, i) => r.item(item)(els[i]!)); + + els[0]!.dispatchEvent(pointer('pointerdown', 20)); + els[0]!.dispatchEvent(pointer('pointermove', 70)); + els[0]!.dispatchEvent(pointer('pointerup', 70)); + + expect(order.map((item) => item.id)).toEqual(['b', 'a', 'c']); + }); + + it('cancels an active drag and restores owned styles on detach', () => { + const { values, els } = setup(); + let order = [...values]; + const r = reorder({ items: () => order, onReorder: (next) => (order = next) }); + const cleanup = r.item(values[0]!)(els[0]!); + els.slice(1).forEach((el, i) => r.item(values[i + 1]!)(el)); + + els[0]!.dispatchEvent(pointer('pointerdown', 20)); + els[0]!.dispatchEvent(pointer('pointermove', 70)); + cleanup?.(); + + expect(els[0]!.style.getPropertyValue('--motion-reorder-y')).toBe(''); + expect(order).toEqual(['a', 'b', 'c']); + }); + + it('cancels the scheduled FLIP handoff when detached after drop', () => { + const { values, els } = setup(); + let order = [...values]; + const requestFrame = vi.spyOn(window, 'requestAnimationFrame').mockReturnValue(42); + const cancelFrame = vi.spyOn(window, 'cancelAnimationFrame'); + const r = reorder({ items: () => order, onReorder: (next) => (order = next) }); + const cleanup = r.item(values[0]!)(els[0]!); + els.slice(1).forEach((el, i) => r.item(values[i + 1]!)(el)); + + els[0]!.dispatchEvent(pointer('pointerdown', 20)); + els[0]!.dispatchEvent(pointer('pointermove', 70)); + els[0]!.dispatchEvent(pointer('pointerup', 70)); + cleanup?.(); + + expect(order).toEqual(['b', 'a', 'c']); + expect(requestFrame).toHaveBeenCalledTimes(1); + expect(cancelFrame).toHaveBeenCalledWith(42); + }); + it('detaches cleanly (cleanup removes the listener)', () => { const { values, els } = setup(); let order = [...values]; diff --git a/src/lib/gestures/reorder.ts b/src/lib/gestures/reorder.ts index c5cd8d0..c587400 100644 --- a/src/lib/gestures/reorder.ts +++ b/src/lib/gestures/reorder.ts @@ -11,27 +11,38 @@ * @example * ```svelte * * * {#each list as value (value)} - *
    {value}
    + *
    {value}
    * {/each} * ``` */ import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '$lib/shared/browser'; -import { snapshotRect, flipFrom } from '$lib/flip'; -import type { EasingFn } from '$lib/shared/types'; +import { isBrowser } from '../shared/browser'; +import { snapshotRect, flipFrom } from '../flip'; +import type { EasingFn } from '../shared/types'; +import { + ensurePropertiesRegistered, + ensureTransformWired +} from '../animate/properties/transform-setup'; +import { restoreStyleProp, saveStyleProp, type SavedStyleProp } from '../shared/inline-style'; import { capture, release } from './pointer-capture'; +import { centersAreAscending, nearestCenterIndex } from './reorder-internals'; export interface ReorderOptions { /** Reactive thunk returning the current ordered list. */ items: () => T[]; /** Called with the new order when a drag drops on a different slot. */ onReorder: (next: T[]) => void; + /** + * Returns the stable, unique identity for each row. Required when item values + * are duplicated or recreated; defaults to the value itself. + */ + getKey?: (item: T) => unknown; /** Drag axis. Default `'y'`. */ axis?: 'x' | 'y'; /** Disable dragging without detaching. */ @@ -55,51 +66,86 @@ const arrayMove = (arr: readonly T[], from: number, to: number): T[] => { return next; }; -const clamp = (n: number, lo: number, hi: number): number => Math.min(hi, Math.max(lo, n)); +const REORDER_X = '--motion-reorder-x'; +const REORDER_Y = '--motion-reorder-y'; +const DRAG_STYLE_PROPERTIES = [REORDER_X, REORDER_Y, 'transition', 'position', 'z-index'] as const; +type DragStyleProperty = (typeof DRAG_STYLE_PROPERTIES)[number]; +type DragStyleSnapshot = Record; + +const snapshotDragStyles = (element: HTMLElement): DragStyleSnapshot => + Object.fromEntries( + DRAG_STYLE_PROPERTIES.map((property) => [property, saveStyleProp(element.style, property)]) + ) as DragStyleSnapshot; + +const restoreDragStyles = (element: HTMLElement, snapshot: DragStyleSnapshot): void => { + for (const property of DRAG_STYLE_PROPERTIES) { + restoreStyleProp(element.style, property, snapshot[property]); + } +}; + +const setReorderOffset = (element: HTMLElement, horizontal: boolean, offset: number): void => { + element.style.setProperty(horizontal ? REORDER_X : REORDER_Y, `${offset}px`); +}; interface DragState { pointerId: number; el: HTMLElement; from: number; over: number; - stride: number; + centers: number[]; + centersAscending: boolean; start: number; els: HTMLElement[]; - centers: number[]; + styles: Map; } /** Create a reorder controller for one list. */ export const reorder = (options: ReorderOptions): ReorderHandle => { const { axis = 'y', duration = 220 } = options; const horizontal = axis === 'x'; - const elements = new Map(); + const keyOf = options.getKey ?? ((value: T): unknown => value); + const elements = new Map(); const coordOf = (e: PointerEvent): number => (horizontal ? e.clientX : e.clientY); const centerOf = (r: DOMRect): number => horizontal ? r.left + r.width / 2 : r.top + r.height / 2; - const translate = (px: number): string => - horizontal ? `translateX(${px}px)` : `translateY(${px}px)`; let drag: DragState | null = null; + // The data callback commits synchronously, but the framework needs one frame + // to render that order before FLIP can measure it. Keep that deferred handoff + // owned by this attachment so teardown cannot animate a detached node. + let settleFrame: number | null = null; + + const cancelPendingSettle = (): void => { + if (settleFrame == null) return; + cancelAnimationFrame(settleFrame); + settleFrame = null; + }; + + const restoreDrag = (state: DragState): void => { + for (const node of state.els) restoreDragStyles(node, state.styles.get(node)!); + }; - /** Slide siblings between `from` and `over` to open the drop slot. */ + /** Slide siblings into the dragged row's actual slot, including variable item sizes and gaps. */ const layoutSiblings = (): void => { if (!drag) return; - const { els, from, over, stride } = drag; + const { els, from, over, centers } = drag; for (let i = 0; i < els.length; i++) { - if (i === drag.from) continue; + if (i === from) continue; let shift = 0; - if (from < over && i > from && i <= over) shift = -stride; - else if (over < from && i >= over && i < from) shift = stride; - els[i]!.style.transform = shift ? translate(shift) : ''; + if (from < over && i > from && i <= over) shift = centers[i - 1]! - centers[i]!; + else if (over < from && i >= over && i < from) shift = centers[i + 1]! - centers[i]!; + setReorderOffset(els[i]!, horizontal, shift); } }; const onMove = (e: PointerEvent): void => { if (!drag || e.pointerId !== drag.pointerId) return; + const { centers, centersAscending, from } = drag; const delta = coordOf(e) - drag.start; - drag.el.style.transform = translate(delta); - const over = clamp(drag.from + Math.round(delta / drag.stride), 0, drag.els.length - 1); + setReorderOffset(drag.el, horizontal, delta); + const targetCenter = centers[from]! + delta; + const over = nearestCenterIndex(centers, targetCenter, centersAscending); if (over !== drag.over) { drag.over = over; layoutSiblings(); @@ -108,67 +154,79 @@ export const reorder = (options: ReorderOptions): ReorderHandle => { const endDrag = (e: PointerEvent): void => { if (!drag || e.pointerId !== drag.pointerId) return; - const { el, els, from, over, pointerId } = drag; + const state = drag; + const { el, els, from, over, pointerId } = state; el.removeEventListener('pointermove', onMove as EventListener); el.removeEventListener('pointerup', endDrag as EventListener); el.removeEventListener('pointercancel', endDrag as EventListener); release(el, pointerId); drag = null; - // Capture every row's current (transformed) position, drop the inline - // transforms, commit the reorder, then FLIP each row from where it - // visually was into its freshly-laid-out slot. + // Capture the composed visual position, restore every property this drag + // owns, commit data, then FLIP into the freshly laid-out slots. const fromRects = els.map((node) => snapshotRect(node)); - for (const node of els) { - node.style.transform = ''; - node.style.transition = ''; - } - el.style.zIndex = ''; - el.style.position = ''; + restoreDrag(state); if (over !== from) options.onReorder(arrayMove(options.items(), from, over)); - requestAnimationFrame(() => { + cancelPendingSettle(); + settleFrame = requestAnimationFrame(() => { + settleFrame = null; for (let i = 0; i < els.length; i++) { flipFrom(els[i]!, fromRects[i]!, { duration, easing: options.easing }); } }); }; + const cancelDrag = (): void => { + if (!drag) return; + const state = drag; + const { el, pointerId } = state; + el.removeEventListener('pointermove', onMove as EventListener); + el.removeEventListener('pointerup', endDrag as EventListener); + el.removeEventListener('pointercancel', endDrag as EventListener); + release(el, pointerId); + drag = null; + restoreDrag(state); + }; + const onDown = (el: HTMLElement) => (e: PointerEvent): void => { if (options.disabled || e.button !== 0 || drag) return; const order = options.items(); - const els = order.map((v) => elements.get(v)).filter((n): n is HTMLElement => !!n); - const from = els.indexOf(el); + const keys = order.map(keyOf); + // A value is a safe default key only while it is unique. Refuse an + // ambiguous drag rather than moving the wrong row; callers can supply getKey. + if (new Set(keys).size !== keys.length) return; + const els = keys.map((key) => elements.get(key)); + if (els.some((node): node is undefined => !node)) return; + const rows = els as HTMLElement[]; + const from = rows.indexOf(el); if (from < 0) return; - const rects = els.map((node) => node.getBoundingClientRect()); + const rects = rows.map((node) => node.getBoundingClientRect()); const centers = rects.map(centerOf); - const stride = - els.length > 1 - ? (centers[centers.length - 1]! - centers[0]!) / (els.length - 1) - : horizontal - ? rects[0]!.width - : rects[0]!.height; + const styles = new Map(rows.map((node) => [node, snapshotDragStyles(node)])); drag = { pointerId: e.pointerId, el, from, over: from, - stride, + centers, + centersAscending: centersAreAscending(centers), start: coordOf(e), - els, - centers + els: rows, + styles }; - // Lift the dragged row; give siblings a transition so they glide. + // Reorder owns only its dedicated motion channel and temporary drag + // presentation; existing transform and inline styles are never replaced. el.style.position = 'relative'; el.style.zIndex = '1'; - for (let i = 0; i < els.length; i++) { - if (i !== from) els[i]!.style.transition = `transform ${duration}ms`; + for (let i = 0; i < rows.length; i++) { + if (i !== from) rows[i]!.style.transition = `translate ${duration}ms`; } capture(el, e.pointerId); @@ -181,13 +239,20 @@ export const reorder = (options: ReorderOptions): ReorderHandle => { (value: T): Attachment => (el) => { if (!isBrowser()) return; - elements.set(value, el); - el.style.touchAction = horizontal ? 'pan-y' : 'pan-x'; + ensurePropertiesRegistered(); + ensureTransformWired(el); + const key = keyOf(value); + elements.set(key, el); + const savedTouchAction = saveStyleProp(el.style, 'touch-action'); + el.style.setProperty('touch-action', horizontal ? 'pan-y' : 'pan-x'); const down = onDown(el); el.addEventListener('pointerdown', down as EventListener); return () => { + if (drag?.els.includes(el)) cancelDrag(); + cancelPendingSettle(); el.removeEventListener('pointerdown', down as EventListener); - elements.delete(value); + if (elements.get(key) === el) elements.delete(key); + restoreStyleProp(el.style, 'touch-action', savedTouchAction); }; }; From f0ecab79404787e9cc885e6a0a1ed376534e244b Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:46:23 -0400 Subject: [PATCH 14/30] refactor(gestures): unexport internals and share the frame batch Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/gestures/draggable.ts | 17 +++++++++-------- src/lib/gestures/focus.ts | 4 ++-- src/lib/gestures/hover.ts | 4 ++-- src/lib/gestures/move.ts | 10 +++++----- src/lib/gestures/pinch.ts | 32 +++++++++++++------------------- src/lib/gestures/press.ts | 4 ++-- src/lib/gestures/swipe.ts | 11 ++++++----- src/lib/gestures/wheel.ts | 23 ++++++++--------------- 8 files changed, 47 insertions(+), 58 deletions(-) diff --git a/src/lib/gestures/draggable.ts b/src/lib/gestures/draggable.ts index ea4dad7..fc0f968 100644 --- a/src/lib/gestures/draggable.ts +++ b/src/lib/gestures/draggable.ts @@ -11,15 +11,16 @@ */ import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '$lib/shared/browser'; -import type { MotionElement } from '$lib/animate'; -import type { SpringOptions } from '$lib/shared/types'; -import { createSpringValue } from '$lib/animate/spring-value'; +import { isBrowser } from '../shared/browser'; +import { restoreStyleProp, saveStyleProp } from '../shared/inline-style'; +import type { MotionElement } from '../animate'; +import type { SpringOptions } from '../shared/types'; +import { createSpringValue } from '../animate/spring-value'; import { capture, release } from './pointer-capture'; import { ensurePropertiesRegistered, ensureTransformWired -} from '$lib/animate/properties/transform-setup'; +} from '../animate/properties/transform-setup'; import { applyConstraint, xBounds, yBounds, type DragConstraints } from './constraints'; export type DragAxis = 'x' | 'y' | 'both'; @@ -76,8 +77,8 @@ export const draggable = (options: DraggableOptions = {}): Attachment void; diff --git a/src/lib/gestures/hover.ts b/src/lib/gestures/hover.ts index a98e4cc..1118434 100644 --- a/src/lib/gestures/hover.ts +++ b/src/lib/gestures/hover.ts @@ -15,8 +15,8 @@ */ import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '$lib/shared/browser'; -import type { MotionElement } from '$lib/animate'; +import { isBrowser } from '../shared/browser'; +import type { MotionElement } from '../animate'; export interface HoverableOptions { onHoverStart?: (element: MotionElement, event: PointerEvent) => void; diff --git a/src/lib/gestures/move.ts b/src/lib/gestures/move.ts index 2558e76..fd3736e 100644 --- a/src/lib/gestures/move.ts +++ b/src/lib/gestures/move.ts @@ -18,14 +18,14 @@ */ import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '$lib/shared/browser'; -import type { MotionElement } from '$lib/animate'; -import type { SpringOptions } from '$lib/shared/types'; -import { createSpringValue } from '$lib/animate/spring-value'; +import { isBrowser } from '../shared/browser'; +import type { MotionElement } from '../animate'; +import type { SpringOptions } from '../shared/types'; +import { createSpringValue } from '../animate/spring-value'; import { ensurePropertiesRegistered, ensureTransformWired -} from '$lib/animate/properties/transform-setup'; +} from '../animate/properties/transform-setup'; export interface MoveInfo { /** Pointer position in client coordinates. */ diff --git a/src/lib/gestures/pinch.ts b/src/lib/gestures/pinch.ts index b4bc9d1..f0a8b35 100644 --- a/src/lib/gestures/pinch.ts +++ b/src/lib/gestures/pinch.ts @@ -11,13 +11,15 @@ */ import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '$lib/shared/browser'; -import type { MotionElement } from '$lib/animate'; +import { isBrowser } from '../shared/browser'; +import { applyConstraint, type AxisBounds } from './constraints'; +import { restoreStyleProp, saveStyleProp } from '../shared/inline-style'; +import type { MotionElement } from '../animate'; import { capture, release } from './pointer-capture'; import { ensurePropertiesRegistered, ensureTransformWired -} from '$lib/animate/properties/transform-setup'; +} from '../animate/properties/transform-setup'; export interface PinchInfo { /** Distance ratio of the two pointers relative to gesture start. */ @@ -32,7 +34,7 @@ export interface PinchableOptions { /** Track rotation alongside scale. Default `true`. */ rotate?: boolean; /** Clamp the reported (and applied) scale. */ - scaleBounds?: { min?: number; max?: number }; + scaleBounds?: AxisBounds; /** Write `--motion-scale` / `--motion-rotate` on move. Default `true`. */ applyTransform?: boolean; /** Disable pinching without removing the attachment. */ @@ -50,14 +52,6 @@ const distance = (ax: number, ay: number, bx: number, by: number): number => const angle = (ax: number, ay: number, bx: number, by: number): number => (Math.atan2(by - ay, bx - ax) * 180) / Math.PI; -const clampScale = (scale: number, bounds?: { min?: number; max?: number }): number => { - if (!bounds) return scale; - let next = scale; - if (bounds.min !== undefined) next = Math.max(bounds.min, next); - if (bounds.max !== undefined) next = Math.min(bounds.max, next); - return next; -}; - /** Create a pinchable attachment. */ export const pinchable = (options: PinchableOptions = {}): Attachment => { const { @@ -77,8 +71,8 @@ export const pinchable = (options: PinchableOptions = {}): Attachment(); @@ -118,9 +112,9 @@ export const pinchable = (options: PinchableOptions = {}): Attachment 0 ? currentDistance / startDistance : 1, - scaleBounds + scaleBounds ?? {} ); const rotation = rotate ? angle(a.x, a.y, b.x, b.y) - startAngle : 0; @@ -138,9 +132,9 @@ export const pinchable = (options: PinchableOptions = {}): Attachment 0 ? currentDistance / startDistance : 1, - scaleBounds + scaleBounds ?? {} ); const rotation = rotate ? angle(a.x, a.y, b.x, b.y) - startAngle : 0; onEnd?.(info(scale, rotation), element); @@ -164,7 +158,7 @@ export const pinchable = (options: PinchableOptions = {}): Attachment { if (!isBrowser() || disabled) return; - const prevTouchAction = element.style.touchAction; - element.style.touchAction = touchActionFor(axis); + const savedTouchAction = saveStyleProp(element.style, 'touch-action'); + element.style.setProperty('touch-action', touchActionFor(axis)); let tracking = false; let pointerId = -1; @@ -146,7 +147,7 @@ export const swipeable = (options: SwipeableOptions = {}): Attachment { - if (!bounds) return scale; - let next = scale; - if (bounds.min !== undefined) next = Math.max(bounds.min, next); - if (bounds.max !== undefined) next = Math.min(bounds.max, next); - return next; -}; - /** Create a wheelable (wheel-zoom) attachment. */ export const wheelable = (options: WheelableOptions = {}): Attachment => { const { @@ -142,7 +135,7 @@ export const wheelable = (options: WheelableOptions = {}): Attachment Date: Thu, 30 Jul 2026 20:46:23 -0400 Subject: [PATCH 15/30] refactor(morph)!: hide the path-alignment internals planMorph, interpolatePlan, toPathString, subdivideTo, alignSubpaths, minimizeAnchorTravel, rotateClosed, reverseClosed and MorphPlan are no longer exported. morph, parsePath and normalizePath are unchanged. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/morph/index.ts | 11 --- src/lib/morph/interpolate.test.ts | 118 ++++++++++++----------------- src/lib/morph/interpolate.ts | 58 ++++++-------- src/lib/morph/morph.svelte.test.ts | 5 +- src/lib/morph/morph.ts | 55 ++++---------- 5 files changed, 89 insertions(+), 158 deletions(-) diff --git a/src/lib/morph/index.ts b/src/lib/morph/index.ts index afd140b..70d3e42 100644 --- a/src/lib/morph/index.ts +++ b/src/lib/morph/index.ts @@ -9,14 +9,3 @@ export { parsePath } from './parse'; export type { PathCommand } from './parse'; export { normalizePath } from './normalize'; export type { Subpath, CubicSegment, Point } from './normalize'; -export { - planMorph, - interpolatePlan, - toPathString, - subdivideTo, - alignSubpaths, - minimizeAnchorTravel, - rotateClosed, - reverseClosed -} from './interpolate'; -export type { MorphPlan } from './interpolate'; diff --git a/src/lib/morph/interpolate.test.ts b/src/lib/morph/interpolate.test.ts index aac5a07..7fa82da 100644 --- a/src/lib/morph/interpolate.test.ts +++ b/src/lib/morph/interpolate.test.ts @@ -1,43 +1,41 @@ /** * Pure path alignment + interpolation. Runs in the `server` (node) project. + * + * The alignment internals (subdivision, ring rotation/reversal, anchor-travel + * minimization) are exercised through `planMorph` / `interpolatePlan`, the two + * entry points `morph()` itself uses — `interpolatePlan(plan, 0)` and + * `(plan, 1)` render the plan's from- and to-paths. */ import { describe, expect, it } from 'vitest'; -import { normalizePath } from './normalize'; -import { - alignSubpaths, - interpolatePlan, - minimizeAnchorTravel, - planMorph, - reverseClosed, - rotateClosed, - subdivideTo, - toPathString -} from './interpolate'; - -describe('subdivideTo()', () => { - it('grows the segment count while preserving endpoints', () => { - const [line] = normalizePath('M0 0 L10 0'); - const grown = subdivideTo(line!, 2); - expect(grown.segments).toHaveLength(2); - // Midpoint of a straight line subdivided at 0.5. - expect(grown.segments[0]!.end[0]).toBeCloseTo(5); - expect(grown.segments.at(-1)!.end).toEqual([10, 0]); +import { interpolatePlan, planMorph } from './interpolate'; + +/** Rendered endpoints of a plan — what the element's `d` shows at t=0 and t=1. */ +const ends = (from: string, to: string, optimize = true) => { + const plan = planMorph(from, to, optimize); + return { plan, start: interpolatePlan(plan, 0), end: interpolatePlan(plan, 1) }; +}; + +describe('subpath alignment', () => { + it('grows the shorter side to the larger segment count, preserving endpoints', () => { + // 1 segment vs 2 segments — both sides must end up at 2. + const { plan } = ends('M0 0 L10 0', 'M0 0 C0 0 5 5 5 5 C5 5 8 8 10 10'); + expect(plan.from[0]!.segments).toHaveLength(2); + expect(plan.to[0]!.segments).toHaveLength(2); + // Subdivision must not move the path's real endpoints. + expect(plan.from[0]!.start).toEqual([0, 0]); + expect(plan.from[0]!.segments.at(-1)!.end).toEqual([10, 0]); }); - it('is a no-op when already at the target count', () => { - const [line] = normalizePath('M0 0 L10 0'); - expect(subdivideTo(line!, 1).segments).toHaveLength(1); + it('splits a straight line at its midpoint', () => { + const { plan } = ends('M0 0 L10 0', 'M0 0 C0 0 5 5 5 5 C5 5 8 8 10 10'); + expect(plan.from[0]!.segments[0]!.end[0]).toBeCloseTo(5); }); -}); -describe('alignSubpaths()', () => { - it('brings both subpaths to the larger segment count', () => { - const [a] = normalizePath('M0 0 L10 0'); // 1 segment - const [b] = normalizePath('M0 0 C0 0 5 5 5 5 C5 5 8 8 10 10'); // 2 segments - const [aa, bb] = alignSubpaths(a!, b!); - expect(aa.segments).toHaveLength(2); - expect(bb.segments).toHaveLength(2); + it('leaves equal segment counts untouched', () => { + const { plan } = ends('M0 0 L10 0', 'M0 0 L0 10'); + expect(plan.from[0]!.segments).toHaveLength(1); + expect(plan.to[0]!.segments).toHaveLength(1); }); }); @@ -56,60 +54,42 @@ describe('planMorph()', () => { }); describe('interpolatePlan()', () => { - it('returns the from-path at t=0 and the to-path at t=1', () => { - const plan = planMorph('M0 0 L10 0', 'M0 0 L0 10'); - expect(interpolatePlan(plan, 0)).toBe(toPathString(plan.from)); - expect(interpolatePlan(plan, 1)).toBe(toPathString(plan.to)); - }); - it('lerps anchor positions at the midpoint', () => { const plan = planMorph('M0 0 L10 0', 'M10 10 L20 10'); expect(interpolatePlan(plan, 0.5).startsWith('M5 5C')).toBe(true); }); -}); - -describe('rotateClosed() / reverseClosed()', () => { - const [square] = normalizePath('M0 0 L10 0 L10 10 L0 10 Z'); - - it('rotation keeps the shape but moves the start anchor', () => { - const rotated = rotateClosed(square!, 1); - expect(rotated.start).toEqual([10, 0]); // second corner becomes the start - expect(rotated.segments).toHaveLength(square!.segments.length); - }); - - it('rotation by 0 (or a full turn) is a no-op', () => { - expect(rotateClosed(square!, 0)).toBe(square); - expect(rotateClosed(square!, square!.segments.length).start).toEqual(square!.start); - }); - it('reversal keeps the start anchor but flips winding', () => { - const reversed = reverseClosed(square!); - expect(reversed.start).toEqual([0, 0]); - // First step now heads to the previous *last* corner (0,10) instead of (10,0). - expect(reversed.segments[0]!.end).toEqual([0, 10]); + it('is monotonic between its endpoints', () => { + const { start, end } = ends('M0 0 L10 0', 'M10 10 L20 10'); + expect(start).not.toBe(end); + expect(start.startsWith('M0 0')).toBe(true); + expect(end.startsWith('M10 10')).toBe(true); }); }); -describe('minimizeAnchorTravel()', () => { +describe('anchor-travel minimization', () => { it('rotates the from-ring so an identical, differently-started shape coincides', () => { - // Same square, started at a different corner. - const plan = planMorph('M0 0 L10 0 L10 10 L0 10 Z', 'M10 0 L10 10 L0 10 L0 0 Z'); - expect(toPathString(plan.from)).toBe(toPathString(plan.to)); + // Same square, started at a different corner — rotating the ring makes the + // two rings identical, so nothing should visually move across the morph. + const { start, end } = ends('M0 0 L10 0 L10 10 L0 10 Z', 'M10 0 L10 10 L0 10 L0 0 Z'); + expect(start).toBe(end); }); it('reverses the from-ring when the target has the opposite winding', () => { - const plan = planMorph('M0 0 L10 0 L10 10 L0 10 Z', 'M0 0 L0 10 L10 10 L10 0 Z'); - expect(toPathString(plan.from)).toBe(toPathString(plan.to)); + const { start, end } = ends('M0 0 L10 0 L10 10 L0 10 Z', 'M0 0 L0 10 L10 10 L10 0 Z'); + expect(start).toBe(end); }); it('can be disabled, leaving anchors paired in document order', () => { - const unoptimized = planMorph('M0 0 L10 0 L10 10 L0 10 Z', 'M10 0 L10 10 L0 10 L0 0 Z', false); - expect(toPathString(unoptimized.from)).not.toBe(toPathString(unoptimized.to)); + const { start, end } = ends('M0 0 L10 0 L10 10 L0 10 Z', 'M10 0 L10 10 L0 10 L0 0 Z', false); + expect(start).not.toBe(end); }); - it('leaves open paths untouched (start/end are fixed)', () => { - const [open] = normalizePath('M0 0 L10 0'); - const [target] = normalizePath('M0 0 L0 10'); - expect(minimizeAnchorTravel(open!, target!)).toBe(open); + it('leaves open paths untouched — their start/end are fixed', () => { + // An open path may not be rotated or reversed, so the from-ring must still + // begin where it was authored. + const { plan } = ends('M0 0 L10 0', 'M0 10 L0 0'); + expect(plan.from[0]!.start).toEqual([0, 0]); + expect(plan.from[0]!.segments.at(-1)!.end).toEqual([10, 0]); }); }); diff --git a/src/lib/morph/interpolate.ts b/src/lib/morph/interpolate.ts index aef1e43..006c6c5 100644 --- a/src/lib/morph/interpolate.ts +++ b/src/lib/morph/interpolate.ts @@ -8,6 +8,7 @@ * DOM-free and pure. */ +import { lerp } from '../shared/math'; import { normalizePath, type CubicSegment, type Point, type Subpath } from './normalize'; const lerpPoint = (a: Point, b: Point, t: number): Point => [ @@ -40,7 +41,7 @@ const segmentStarts = (subpath: Subpath): Point[] => { }; /** Grow a subpath to exactly `count` segments by subdividing the longest ones. */ -export const subdivideTo = (subpath: Subpath, count: number): Subpath => { +const subdivideTo = (subpath: Subpath, count: number): Subpath => { const starts = segmentStarts(subpath); const items = subpath.segments.map((seg, i) => ({ start: starts[i]!, seg })); @@ -66,7 +67,7 @@ export const subdivideTo = (subpath: Subpath, count: number): Subpath => { }; /** Make two subpaths share an equal segment count. */ -export const alignSubpaths = (a: Subpath, b: Subpath): [Subpath, Subpath] => { +const alignSubpaths = (a: Subpath, b: Subpath): [Subpath, Subpath] => { if (a.segments.length < b.segments.length) return [subdivideTo(a, b.segments.length), b]; if (b.segments.length < a.segments.length) return [a, subdivideTo(b, a.segments.length)]; return [a, b]; @@ -90,7 +91,7 @@ const anchorsOf = (sp: Subpath): Point[] => { * is geometrically identical — only the starting anchor (and therefore the * point-correspondence with another path) changes. */ -export const rotateClosed = (sp: Subpath, k: number): Subpath => { +const rotateClosed = (sp: Subpath, k: number): Subpath => { const n = sp.segments.length; const r = ((k % n) + n) % n; if (r === 0) return sp; @@ -102,7 +103,7 @@ export const rotateClosed = (sp: Subpath, k: number): Subpath => { }; /** Reverse a closed subpath's winding (same start anchor, opposite direction). */ -export const reverseClosed = (sp: Subpath): Subpath => { +const reverseClosed = (sp: Subpath): Subpath => { const n = sp.segments.length; const anchors = anchorsOf(sp); const segments: CubicSegment[] = []; @@ -120,7 +121,7 @@ export const reverseClosed = (sp: Subpath): Subpath => { * rings of equal segment count; open paths are returned unchanged (their start * and end are fixed and must not rotate). */ -export const minimizeAnchorTravel = (from: Subpath, to: Subpath): Subpath => { +const minimizeAnchorTravel = (from: Subpath, to: Subpath): Subpath => { const n = from.segments.length; if (!from.closed || !to.closed || n < 2 || to.segments.length !== n) return from; @@ -142,38 +143,11 @@ export const minimizeAnchorTravel = (from: Subpath, to: Subpath): Subpath => { return best; }; -const interpolateSubpath = (a: Subpath, b: Subpath, t: number): Subpath => ({ - start: lerpPoint(a.start, b.start, t), - segments: a.segments.map((sa, i) => { - const sb = b.segments[i]!; - return { - c1: lerpPoint(sa.c1, sb.c1, t), - c2: lerpPoint(sa.c2, sb.c2, t), - end: lerpPoint(sa.end, sb.end, t) - }; - }), - closed: t < 0.5 ? a.closed : b.closed -}); - const num = (n: number): string => { const r = Math.round(n * 1000) / 1000; return Object.is(r, -0) ? '0' : String(r); }; -const point = (p: Point): string => `${num(p[0])} ${num(p[1])}`; - -/** Serialize normalized cubic subpaths back into a path `d` string. */ -export const toPathString = (subpaths: Subpath[]): string => - subpaths - .map((sp) => { - const head = `M${point(sp.start)}`; - const body = sp.segments - .map((s) => `C${point(s.c1)} ${point(s.c2)} ${point(s.end)}`) - .join(''); - return head + body + (sp.closed ? 'Z' : ''); - }) - .join(''); - export interface MorphPlan { /** Whether the two paths share a structure that can be morphed point-for-point. */ compatible: boolean; @@ -207,5 +181,21 @@ export const planMorph = (from: string, to: string, optimize = true): MorphPlan }; /** Interpolate a prepared, aligned plan at progress `t` into a `d` string. */ -export const interpolatePlan = (plan: MorphPlan, t: number): string => - toPathString(plan.from.map((sp, i) => interpolateSubpath(sp, plan.to[i]!, t))); +export const interpolatePlan = (plan: MorphPlan, t: number): string => { + let path = ''; + for (let i = 0; i < plan.from.length; i++) { + const from = plan.from[i]!; + const to = plan.to[i]!; + path += `M${num(lerp(from.start[0], to.start[0], t))} ${num(lerp(from.start[1], to.start[1], t))}`; + for (let j = 0; j < from.segments.length; j++) { + const a = from.segments[j]!; + const b = to.segments[j]!; + path += + `C${num(lerp(a.c1[0], b.c1[0], t))} ${num(lerp(a.c1[1], b.c1[1], t))}` + + ` ${num(lerp(a.c2[0], b.c2[0], t))} ${num(lerp(a.c2[1], b.c2[1], t))}` + + ` ${num(lerp(a.end[0], b.end[0], t))} ${num(lerp(a.end[1], b.end[1], t))}`; + } + if (t < 0.5 ? from.closed : to.closed) path += 'Z'; + } + return path; +}; diff --git a/src/lib/morph/morph.svelte.test.ts b/src/lib/morph/morph.svelte.test.ts index 7adcd88..6a6fdb3 100644 --- a/src/lib/morph/morph.svelte.test.ts +++ b/src/lib/morph/morph.svelte.test.ts @@ -5,8 +5,7 @@ import { afterEach, describe, expect, it } from 'vitest'; import { morph } from './morph'; -import { normalizePath } from './normalize'; -import { toPathString } from './interpolate'; +import { interpolatePlan, planMorph } from './interpolate'; const SVG_NS = 'http://www.w3.org/2000/svg'; let svg: SVGSVGElement | null = null; @@ -31,7 +30,7 @@ describe('morph()', () => { const to = 'M0 0 L0 10'; const ctrl = morph(path, 'M0 0 L10 0', to, { duration: 60 }); await ctrl.finished; - expect(path.getAttribute('d')).toBe(toPathString(normalizePath(to))); + expect(path.getAttribute('d')).toBe(interpolatePlan(planMorph('M0 0 L10 0', to), 1)); }); it('writes an interpolated path on the first frame', () => { diff --git a/src/lib/morph/morph.ts b/src/lib/morph/morph.ts index 6f61ca3..0172d86 100644 --- a/src/lib/morph/morph.ts +++ b/src/lib/morph/morph.ts @@ -15,9 +15,10 @@ * ``` */ -import { isBrowser, shouldReduceMotion } from '$lib/shared/browser'; -import { easeOut } from '$lib/easing'; -import type { EasingFn } from '$lib/shared/types'; +import { isBrowser, shouldReduceMotion } from '../shared/browser'; +import { frameTween } from '../shared/frame-tween'; +import { easeOut } from '../easing'; +import type { EasingFn } from '../shared/types'; import { interpolatePlan, planMorph } from './interpolate'; export interface MorphOptions { @@ -61,56 +62,28 @@ export const morph = ( onComplete } = options; - let resolveFinished!: () => void; - const finished = new Promise((res) => (resolveFinished = res)); const setD = (d: string): void => element.setAttribute('d', d); if (!isBrowser() || shouldReduceMotion(respectReducedMotion)) { setD(to); onComplete?.(); - resolveFinished(); - return { finished, cancel: () => {} }; + return { finished: Promise.resolve(), cancel: () => {} }; } const plan = planMorph(from, to, optimize); if (!plan.compatible) { setD(to); onComplete?.(); - resolveFinished(); - return { finished, cancel: () => {} }; + return { finished: Promise.resolve(), cancel: () => {} }; } - let frame: number | null = null; - let startTime = 0; - let done = false; - - const finish = (): void => { - if (done) return; - done = true; - if (frame != null) cancelAnimationFrame(frame); - frame = null; - resolveFinished(); - }; - - const tick = (now: number): void => { - if (!startTime) startTime = now + delay; - const elapsed = now - startTime; - if (elapsed < 0) { - frame = requestAnimationFrame(tick); - return; - } - const t = duration <= 0 ? 1 : Math.min(elapsed / duration, 1); - setD(interpolatePlan(plan, easing(t))); - if (t >= 1) { - onComplete?.(); - finish(); - } else { - frame = requestAnimationFrame(tick); - } - }; - - setD(interpolatePlan(plan, 0)); - frame = requestAnimationFrame(tick); + const tween = frameTween({ + duration, + delay, + renderInitial: true, + onFrame: (progress) => setD(interpolatePlan(plan, easing(progress))), + onComplete + }); - return { finished, cancel: finish }; + return { finished: tween.finished, cancel: tween.cancel }; }; From 99a50e80f4e0b787d7f546645fe85631b6ef4ede Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:46:23 -0400 Subject: [PATCH 16/30] refactor(gradient): unexport splitTopLevel Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/gradient/gradient.ts | 92 ++++++++++++---------------------- src/lib/gradient/parse.test.ts | 29 +++++++++-- src/lib/gradient/parse.ts | 41 +++++++++++++-- 3 files changed, 94 insertions(+), 68 deletions(-) diff --git a/src/lib/gradient/gradient.ts b/src/lib/gradient/gradient.ts index 98fb133..229a072 100644 --- a/src/lib/gradient/gradient.ts +++ b/src/lib/gradient/gradient.ts @@ -7,6 +7,13 @@ * an interpolated gradient string each frame. Best results when both gradients * share the same number of colour stops; otherwise it snaps to the target. * + * ponytail: main-thread rAF loop + hand-rolled colour math. Registered + * `@property` custom properties (`` / `` / ``) would + * let the browser interpolate the stops and drop `lerpRGBA` + the canvas + * keyword-resolution hack — at the cost of a permanent global property + * registry and a Firefox 128 / Safari 16.4 floor. Switch when that floor is + * acceptable; the parser is needed either way. + * * @example * ```ts * animateGradient( @@ -18,13 +25,12 @@ * ``` */ -import { isBrowser } from '$lib/shared/browser'; -import { easeOut } from '$lib/easing'; -import type { EasingFn } from '$lib/shared/types'; +import { isBrowser } from '../shared/browser'; +import { frameTween } from '../shared/frame-tween'; +import { easeOut } from '../easing'; +import type { EasingFn } from '../shared/types'; import { - formatLinearGradient, - lerp, - lerpRGBA, + formatInterpolatedLinearGradient, parseLinearGradient, parseRGBA, resolvePositions, @@ -94,13 +100,7 @@ export const animateGradient = ( onComplete } = options; - let resolveFinished!: () => void; - const finished = new Promise((res) => (resolveFinished = res)); - - if (!isBrowser()) { - resolveFinished(); - return { finished, cancel: () => {} }; - } + if (!isBrowser()) return { finished: Promise.resolve(), cancel: () => {} }; const a = resolve(from); const b = resolve(to); @@ -110,53 +110,27 @@ export const animateGradient = ( if (a.colors.length !== b.colors.length) { write(to); onComplete?.(); - resolveFinished(); - return { finished, cancel: () => {} }; + return { finished: Promise.resolve(), cancel: () => {} }; } - let frame: number | null = null; - let startTime = 0; - let done = false; - - const finish = (): void => { - if (done) return; - done = true; - if (frame != null) cancelAnimationFrame(frame); - frame = null; - resolveFinished(); - }; - - const render = (t: number): void => { - const e = easing(t); - const stops = a.colors.map((color, i) => ({ - rgba: lerpRGBA(color, b.colors[i]!, e), - pos: lerp(a.positions[i]!, b.positions[i]!, e) - })); - write(formatLinearGradient(lerp(a.angle, b.angle, e), stops)); - }; - - const tick = (now: number): void => { - if (!startTime) startTime = now + delay; - const elapsed = now - startTime; - if (elapsed < 0) { - frame = requestAnimationFrame(tick); - return; - } - const t = duration <= 0 ? 1 : Math.min(elapsed / duration, 1); - render(t); - if (t >= 1) { - onComplete?.(); - finish(); - } else { - frame = requestAnimationFrame(tick); - } - }; - - render(0); - frame = requestAnimationFrame(tick); + const tween = frameTween({ + duration, + delay, + renderInitial: true, + onFrame: (progress) => + write( + formatInterpolatedLinearGradient( + a.angle, + b.angle, + a.colors, + b.colors, + a.positions, + b.positions, + easing(progress) + ) + ), + onComplete + }); - return { - finished, - cancel: finish - }; + return { finished: tween.finished, cancel: tween.cancel }; }; diff --git a/src/lib/gradient/parse.test.ts b/src/lib/gradient/parse.test.ts index 8ddfe79..7c23c06 100644 --- a/src/lib/gradient/parse.test.ts +++ b/src/lib/gradient/parse.test.ts @@ -4,12 +4,12 @@ import { describe, expect, it } from 'vitest'; import { + formatInterpolatedLinearGradient, formatLinearGradient, lerpRGBA, parseLinearGradient, parseRGBA, - resolvePositions, - splitTopLevel + resolvePositions } from './parse'; describe('parseRGBA()', () => { @@ -34,9 +34,17 @@ describe('lerpRGBA()', () => { }); }); -describe('splitTopLevel()', () => { +describe('stop splitting', () => { it('ignores commas nested in parentheses', () => { - expect(splitTopLevel('a, rgb(1, 2, 3), b')).toEqual(['a', 'rgb(1, 2, 3)', 'b']); + // A functional color contains its own commas — splitting on them naively + // would report four stops instead of two. + const g = parseLinearGradient( + 'linear-gradient(90deg, rgb(1, 2, 3) 0%, rgba(4, 5, 6, 0.5) 100%)' + ); + expect(g.stops).toEqual([ + { color: 'rgb(1, 2, 3)', pos: 0 }, + { color: 'rgba(4, 5, 6, 0.5)', pos: 100 } + ]); }); }); @@ -81,3 +89,16 @@ describe('formatLinearGradient()', () => { expect(css).toBe('linear-gradient(90deg, rgba(255, 0, 0, 1) 0%, rgba(0, 0, 255, 1) 100%)'); }); }); + +describe('formatInterpolatedLinearGradient()', () => { + it('matches the existing formatter’s interpolated output without stop objects', () => { + const from = [[0, 0, 0, 0] as const, [255, 0, 0, 1] as const]; + const to = [[255, 255, 255, 1] as const, [0, 0, 255, 0.5] as const]; + expect(formatInterpolatedLinearGradient(0, 90, from, to, [0, 20], [10, 100], 0.5)).toBe( + formatLinearGradient(45, [ + { rgba: lerpRGBA(from[0], to[0], 0.5), pos: 5 }, + { rgba: lerpRGBA(from[1], to[1], 0.5), pos: 60 } + ]) + ); + }); +}); diff --git a/src/lib/gradient/parse.ts b/src/lib/gradient/parse.ts index f02cc35..f2999a5 100644 --- a/src/lib/gradient/parse.ts +++ b/src/lib/gradient/parse.ts @@ -4,6 +4,8 @@ * driver layer, which feeds already-resolved `rgb/rgba/#hex` colours here. */ +import { lerp } from '../shared/math'; + export type RGBA = readonly [r: number, g: number, b: number, a: number]; export interface GradientStop { @@ -18,9 +20,6 @@ export interface LinearGradient { stops: GradientStop[]; } -/** Linear interpolation. */ -export const lerp = (a: number, b: number, t: number): number => a + (b - a) * t; - /** Interpolate two RGBA colours channel-wise (alpha included). */ export const lerpRGBA = (a: RGBA, b: RGBA, t: number): RGBA => [ Math.round(lerp(a[0], b[0], t)), @@ -59,11 +58,11 @@ export const parseRGBA = (input: string): RGBA => { }; /** Format an RGBA tuple as a CSS `rgba(...)` string. */ -export const formatRGBA = ([r, g, b, a]: RGBA): string => +const formatRGBA = ([r, g, b, a]: RGBA): string => `rgba(${r}, ${g}, ${b}, ${Number(a.toFixed(3))})`; /** Split a comma-separated list, ignoring commas nested in parentheses. */ -export const splitTopLevel = (input: string): string[] => { +const splitTopLevel = (input: string): string[] => { const out: string[] = []; let depth = 0; let start = 0; @@ -133,6 +132,38 @@ export const formatLinearGradient = (angle: number, stops: { rgba: RGBA; pos: nu .map((s) => `${formatRGBA(s.rgba)} ${Number(s.pos.toFixed(2))}%`) .join(', ')})`; +/** + * Format an interpolated gradient directly from two resolved stop lists. + * + * The rAF driver calls this every frame. Keeping interpolation and formatting + * together avoids allocating a tuple and object for each stop before creating + * the unavoidable CSS string, while preserving `formatLinearGradient()`'s + * rounding and output format. + */ +export const formatInterpolatedLinearGradient = ( + fromAngle: number, + toAngle: number, + fromColors: readonly RGBA[], + toColors: readonly RGBA[], + fromPositions: readonly number[], + toPositions: readonly number[], + t: number +): string => { + let stops = ''; + for (let i = 0; i < fromColors.length; i++) { + const from = fromColors[i]!; + const to = toColors[i]!; + const r = Math.round(lerp(from[0], to[0], t)); + const g = Math.round(lerp(from[1], to[1], t)); + const b = Math.round(lerp(from[2], to[2], t)); + const a = Number(lerp(from[3], to[3], t).toFixed(3)); + const pos = Number(lerp(fromPositions[i]!, toPositions[i]!, t).toFixed(2)); + if (i > 0) stops += ', '; + stops += `rgba(${r}, ${g}, ${b}, ${a}) ${pos}%`; + } + return `linear-gradient(${Number(lerp(fromAngle, toAngle, t).toFixed(2))}deg, ${stops})`; +}; + /** Distribute `null` stop positions evenly across `[0, 100]`. */ export const resolvePositions = (stops: GradientStop[]): number[] => stops.map((s, i) => From e1868d7b6dba6166d41dd235f88cc929ffda094e Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:46:23 -0400 Subject: [PATCH 17/30] refactor(presence,scroll,text,variants,view-transition): unexport internals Same surface trim as the other modules: helpers with no callers outside their own file stop being part of the package API. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/presence/transitions.ts | 11 +++++------ src/lib/scroll/in-view.ts | 4 ++-- src/lib/scroll/progress.ts | 2 +- src/lib/scroll/scroll.ts | 23 +++++++++++----------- src/lib/text/split.ts | 2 +- src/lib/variants/variants.svelte.ts | 6 +++--- src/lib/variants/variants.ts | 9 ++------- src/lib/view-transition/controller.ts | 2 +- src/lib/view-transition/name.svelte.ts | 4 ++-- src/lib/view-transition/navigation.ts | 12 ++++------- src/lib/view-transition/timing.ts | 4 ++-- src/lib/view-transition/types.ts | 2 +- src/lib/view-transition/view-transition.ts | 4 ++-- 13 files changed, 37 insertions(+), 48 deletions(-) diff --git a/src/lib/presence/transitions.ts b/src/lib/presence/transitions.ts index 119f2db..5062c3a 100644 --- a/src/lib/presence/transitions.ts +++ b/src/lib/presence/transitions.ts @@ -17,8 +17,9 @@ */ import type { TransitionConfig } from 'svelte/transition'; -import { easeOut, springEasing } from '$lib/easing'; -import type { EasingFn, SpringOptions } from '$lib/shared/types'; +import { easeOut, springEasing } from '../easing'; +import { restoreStyleProp, saveStyleProp } from '../shared/inline-style'; +import type { EasingFn, SpringOptions } from '../shared/types'; export interface PresenceParams { /** Delay before the transition starts (ms). */ @@ -81,12 +82,10 @@ export interface SizeFields { const resolveSize = (node: Element, axis: 'width' | 'height', value: SizeValue): number => { if (typeof value === 'number') return value; const style = (node as HTMLElement).style; - const prev = style.getPropertyValue(axis); - const priority = style.getPropertyPriority(axis); + const saved = saveStyleProp(style, axis); style.setProperty(axis, value); const resolved = px(getComputedStyle(node), axis); - if (prev) style.setProperty(axis, prev, priority); - else style.removeProperty(axis); + restoreStyleProp(style, axis, saved); return resolved; }; diff --git a/src/lib/scroll/in-view.ts b/src/lib/scroll/in-view.ts index c41c96b..cfae8cd 100644 --- a/src/lib/scroll/in-view.ts +++ b/src/lib/scroll/in-view.ts @@ -17,8 +17,8 @@ */ import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '$lib/shared/browser'; -import type { MotionElement } from '$lib/animate'; +import { isBrowser } from '../shared/browser'; +import type { MotionElement } from '../animate'; export interface InViewOptions { /** Fired when the element crosses into view. */ diff --git a/src/lib/scroll/progress.ts b/src/lib/scroll/progress.ts index 260fed3..d6cebf3 100644 --- a/src/lib/scroll/progress.ts +++ b/src/lib/scroll/progress.ts @@ -4,7 +4,7 @@ * progress value. */ -import { clamp01 } from '$lib/shared/math'; +import { clamp01 } from '../shared/math'; /** Whole-scroller progress: how far the scroll position has travelled. */ export const pageProgress = (scroll: number, scrollSize: number, viewport: number): number => diff --git a/src/lib/scroll/scroll.ts b/src/lib/scroll/scroll.ts index edd18a6..a12b4f3 100644 --- a/src/lib/scroll/scroll.ts +++ b/src/lib/scroll/scroll.ts @@ -24,8 +24,9 @@ */ import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '$lib/shared/browser'; -import type { AnimationController, MotionElement } from '$lib/animate'; +import { isBrowser } from '../shared/browser'; +import { createFrameBatch } from '../shared/frame-batch'; +import type { AnimationController, MotionElement } from '../animate'; import { coverProgress, containProgress, pageProgress } from './progress'; export type ScrollAxis = 'x' | 'y'; @@ -134,25 +135,23 @@ export const scroll = (options: ScrollOptions = {}): Attachment = const duration = controller ? totalDuration(controller) : 0; const scrollSource: EventTarget = container ?? window; - let frame: number | null = null; const update = (): void => { - frame = null; const progress = progressFor(range, readState(element, container, axis)); controller?.seek(progress * duration); onProgress?.(progress, element); }; - const schedule = (): void => { - if (frame == null) frame = requestAnimationFrame(update); - }; + // Scroll attachments remain independently owned, but their geometry work + // shares one rAF when several receive the same scroll/resize burst. + const batch = createFrameBatch(update); update(); - scrollSource.addEventListener('scroll', schedule, { passive: true }); - window.addEventListener('resize', schedule, { passive: true }); + scrollSource.addEventListener('scroll', batch.schedule, { passive: true }); + window.addEventListener('resize', batch.schedule, { passive: true }); return () => { - if (frame != null) cancelAnimationFrame(frame); - scrollSource.removeEventListener('scroll', schedule); - window.removeEventListener('resize', schedule); + batch.cancel(); + scrollSource.removeEventListener('scroll', batch.schedule); + window.removeEventListener('resize', batch.schedule); controller?.cancel(); }; }; diff --git a/src/lib/text/split.ts b/src/lib/text/split.ts index bfa2e97..911ae4f 100644 --- a/src/lib/text/split.ts +++ b/src/lib/text/split.ts @@ -8,7 +8,7 @@ * wrapper that builds the spans and is browser-only. */ -import { isBrowser } from '$lib/shared/browser'; +import { isBrowser } from '../shared/browser'; /** Which granularity / granularities to split into. Default: `'chars'`. */ export type SplitType = 'chars' | 'words' | 'lines'; diff --git a/src/lib/variants/variants.svelte.ts b/src/lib/variants/variants.svelte.ts index 6d0031f..650ef71 100644 --- a/src/lib/variants/variants.svelte.ts +++ b/src/lib/variants/variants.svelte.ts @@ -24,10 +24,10 @@ import { untrack } from 'svelte'; import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '$lib/shared/browser'; -import type { MotionElement } from '$lib/animate'; +import { isBrowser } from '../shared/browser'; +import type { MotionElement } from '../animate'; import { createVariants, type VariantMap } from './variants'; -import type { AnimateDefaults } from '$lib/animate'; +import type { AnimateDefaults } from '../animate'; export interface VariantsAttachmentOptions { /** The named states. */ diff --git a/src/lib/variants/variants.ts b/src/lib/variants/variants.ts index 8e9679e..b84f9cb 100644 --- a/src/lib/variants/variants.ts +++ b/src/lib/variants/variants.ts @@ -24,13 +24,8 @@ * ``` */ -import { animate } from '$lib/animate'; -import type { - AnimateDefaults, - AnimateProps, - AnimationController, - MotionElement -} from '$lib/animate'; +import { animate } from '../animate'; +import type { AnimateDefaults, AnimateProps, AnimationController, MotionElement } from '../animate'; /** Map of state name → target props. */ export type VariantMap = Record; diff --git a/src/lib/view-transition/controller.ts b/src/lib/view-transition/controller.ts index 8a69ec3..283721d 100644 --- a/src/lib/view-transition/controller.ts +++ b/src/lib/view-transition/controller.ts @@ -11,7 +11,7 @@ * controllable. */ -import type { AnimationController } from '$lib/animate/types'; +import type { AnimationController } from '../animate/types'; import { resolveViewTransitionTiming } from './timing'; import type { ViewTransitionOptions } from './types'; diff --git a/src/lib/view-transition/name.svelte.ts b/src/lib/view-transition/name.svelte.ts index 730462c..758c98a 100644 --- a/src/lib/view-transition/name.svelte.ts +++ b/src/lib/view-transition/name.svelte.ts @@ -5,8 +5,8 @@ */ import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '$lib/shared/browser'; -import type { MotionElement } from '$lib/shared/types'; +import { isBrowser } from '../shared/browser'; +import type { MotionElement } from '../shared/types'; /** A static name, or a thunk read reactively so the name can track `$state`. */ export type ViewTransitionNameInput = string | (() => string | undefined); diff --git a/src/lib/view-transition/navigation.ts b/src/lib/view-transition/navigation.ts index 660c715..252701c 100644 --- a/src/lib/view-transition/navigation.ts +++ b/src/lib/view-transition/navigation.ts @@ -1,12 +1,12 @@ /** * SvelteKit glue — wrap a view transition around a client-side navigation. * - * Kept framework-decoupled: instead of importing `$app/navigation` (a - * SvelteKit-only virtual module), `navigation` is typed structurally so the + * Kept framework-decoupled: rather than importing SvelteKit's navigation + * module, `navigation` is typed structurally so the * helper works with any object exposing a `complete` promise. */ -import { isBrowser, shouldReduceMotion } from '$lib/shared/browser'; +import { isBrowser, shouldReduceMotion } from '../shared/browser'; import { supportsViewTransitions, viewTransition } from './view-transition'; import type { ViewTransitionOptions } from './types'; @@ -22,11 +22,7 @@ export interface NavigationLike { * swapping the DOM. Returns `undefined` (a plain navigation) when the API is * unavailable or reduced motion is requested. * - * @example - * ```ts - * import { onNavigate } from '$app/navigation'; - * onNavigate((nav) => viewTransitionNavigate(nav, { spring: true })); - * ``` + * Register this with SvelteKit's `onNavigate` hook and return its result. */ export const viewTransitionNavigate = ( navigation: NavigationLike, diff --git a/src/lib/view-transition/timing.ts b/src/lib/view-transition/timing.ts index 64c1230..f6ccbe1 100644 --- a/src/lib/view-transition/timing.ts +++ b/src/lib/view-transition/timing.ts @@ -4,8 +4,8 @@ * browser integration in `controller.ts`. */ -import { springEasing } from '$lib/easing'; -import { easingToCss } from '$lib/animate/keyframes/easing-utils'; +import { springEasing } from '../easing'; +import { easingToCss } from '../animate/keyframes/easing-utils'; import type { ViewTransitionOptions } from './types'; /** diff --git a/src/lib/view-transition/types.ts b/src/lib/view-transition/types.ts index 864fbfd..9cfc432 100644 --- a/src/lib/view-transition/types.ts +++ b/src/lib/view-transition/types.ts @@ -2,7 +2,7 @@ * Public types for the `view-transition` module. */ -import type { EasingFn, SpringInput } from '$lib/animate/types'; +import type { EasingFn, SpringInput } from '../animate/types'; export type { EasingFn, SpringInput }; diff --git a/src/lib/view-transition/view-transition.ts b/src/lib/view-transition/view-transition.ts index c5d4249..ed24dd5 100644 --- a/src/lib/view-transition/view-transition.ts +++ b/src/lib/view-transition/view-transition.ts @@ -3,8 +3,8 @@ * spring/easing engine, behind the uniform {@link AnimationController}. */ -import { isBrowser, shouldReduceMotion } from '$lib/shared/browser'; -import type { AnimationController } from '$lib/animate/types'; +import { isBrowser, shouldReduceMotion } from '../shared/browser'; +import type { AnimationController } from '../animate/types'; import { createViewTransitionController, resolvedController } from './controller'; import type { ViewTransitionOptions, ViewTransitionUpdate } from './types'; From c7f38da5f0747236bc217ee6420e6586600f60a6 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:46:33 -0400 Subject: [PATCH 18/30] fix(exports): re-export easing from the root entry and use an explicit scroll index Directory imports resolved fine in this repo but not in consuming Vite projects; easing was reachable only via the subpath export. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/index.ts b/src/lib/index.ts index d42af15..c5a4982 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -11,7 +11,9 @@ */ export * from './flip'; export * from './animate'; -export * from './scroll'; +export * from './easing'; +// Explicit index avoids relying on directory-import resolution in consuming Vite projects. +export * from './scroll/index'; export * from './gestures'; export * from './presence'; export * from './variants'; From ebd9b672d399faa162ef32f991c8fe70778da217 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:46:33 -0400 Subject: [PATCH 19/30] feat(demo): add MotionLab and dark-mode boot script Interactive playground for the new modules; app.html applies the stored or system theme before first paint to avoid a flash. Co-Authored-By: Claude Opus 5 (1M context) --- src/app.html | 9 + src/routes/+page.svelte | 1139 +------------------------------ src/routes/DemoCard.svelte | 27 +- src/routes/MotionLab.svelte | 1266 +++++++++++++++++++++++++++++++++++ src/routes/layout.css | 12 + 5 files changed, 1312 insertions(+), 1141 deletions(-) create mode 100644 src/routes/MotionLab.svelte diff --git a/src/app.html b/src/app.html index 359c394..f5627e8 100644 --- a/src/app.html +++ b/src/app.html @@ -5,6 +5,15 @@ + %sveltekit.head% diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index b872fc1..f3d2df7 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,1134 +1,13 @@ -{#snippet trigger(label: string, onclick: () => void, disabled = false)} - -{/snippet} - -
    -
    -
    -

    pulse

    -

    A WAAPI motion library for Svelte 5.

    -
    -
    - 26 examples - -
    - -
    - - c.stop()); - controllers = boxes.map((el, i) => { - const lift = -Math.sin((i / (boxes.length - 1)) * Math.PI) * 38; - return animate(el, { - y: on ? lift : 0, - borderRadius: on ? 18 : 6, - backgroundColor: on ? '#a855f7' : '#6366f1', - }, { delay: i * 55, duration: 520, easing: backOut }); - }); -}`} - > -
    - {#each range(BASIC_COUNT) as i (i)} -
    - {/each} -
    - {@render trigger(basicOn ? 'Reset' : 'Launch', runBasic)} -
    - - - - animate(el, { - scale: { to: 1.2, spring: { stiffness: 240 - i * 8, damping: 10 } }, - rotate: { to: 45, spring: { stiffness: 200, damping: 12 } }, - }) -);`} - > -
    - {#each range(9) as i (i)} -
    - {/each} -
    - {@render trigger(springActive ? 'Reset' : 'Spring', triggerSpring)} -
    - - - c.stop()); -controllers = els.map((el, i) => - animate(el, { opacity: show ? 1 : 0, scale: show ? 1 : 0.3 }, { - delay: delay(i, els.length), - duration: 320, - easing: backOut, - }) -);`} - > -
    - {#each range(STAGGER_COUNT) as i (i)} -
    - {/each} -
    - {@render trigger(staggerVisible ? 'Hide' : 'Show', toggleStagger)} -
    - - - -
    -
    - New -
    -
    Card reveal
    -
    - Each child enters on its own offset. -
    - -
    - {@render trigger('Replay', runTimeline)} -
    - - - { void items; } })}> - {item} -
    -{/each}`} - > -
    - {#each flipItems as item (item)} -
    { - void flipItems; - } - })} - class="flex size-12 items-center justify-center rounded-lg bg-amber-100 text-xl" - > - {item} -
    - {/each} -
    - {@render trigger('Shuffle', shuffleFlip)} - - - - -
    -

    {expanded ? 'Expanded' : 'Collapsed'}

    - {#if expanded} -

    - Captured before the DOM update, animated from the old rect to the new. -

    - {/if} -
    - -
    - - - `} - > -
    - {#each ['drag', 'me', 'too'] as label, i (label)} -
    - {label} -
    - {/each} -
    -
    - - - state, - initial: 'rest', - variants: { - rest: { scale: 1, y: 0 }, - hover: { scale: 1.06, y: -4 }, - pressed: { scale: 0.95, y: 0 }, - }, - defaults: { spring: { stiffness: 320, damping: 20 } }, -})} />`} - > -
    - {#each ['Tap', 'Me', 'Now'] as label, i (label)} - - {/each} -
    -
    - - - animate(el, { opacity: [0, 1], y: [24, 0] }), -})} />`} - > -
    - {#each ['Lazy', 'Reveal', 'On', 'Scroll', 'Into', 'View'] as label (label)} -
    - animate(el, { opacity: [0, 1], y: [20, 0] }, { duration: 420, easing: easeOut }) - })} - class="flex h-14 items-center justify-center rounded-lg bg-orange-100 text-xs font-medium text-orange-800 opacity-0" - > - {label} -
    - {/each} -
    -
    - - - - {chip.label} - -{/each}`} - > - -
    - {#each chips as chip (chip.id)} - - {/each} -
    - {@render trigger('+ Add', addChip)} -
    - - - - {row.label} -
    -{/each} - -// axis: 'x' | 'y' | 'both' · start: 0..1 · opacity?`} - > - -
    - {#each rows as row (row.id)} -
    - {row.label} - -
    - {/each} -
    - {@render trigger('+ Add row', addRow)} - - - - -
    - {#each range(6) as i (i)} -
    - {/each} -
    - {@render trigger('Tween', toggleGradient)} -
    - - - -
    - {#each range(PATHS.length) as i (i)} -
    - {/each} -
    - {@render trigger('Travel', runPath)} -
    - - - - draw(p, { duration: 1100, delay: i * 180, easing: easeInOut }) -); // animates stroke-dashoffset from length → 0`} - > - - {#each ['M5,25 C 50,-5 70,55 100,25 S 160,-5 195,25', 'M5,45 C 50,15 70,75 100,45 S 160,15 195,45', 'M5,65 C 50,35 70,95 100,65 S 160,35 195,65'] as d, i (d)} - - {/each} - - {@render trigger('Draw', runDraw)} - - - - -
    -
    - - - -
    optimize: true
    -
    -
    - - - -
    optimize: false
    -
    -
    - {@render trigger('Morph', runMorph)} -
    - - - -
    - {#each range(5) as i (i)} -
    - {/each} -
    - {@render trigger('Sequence', runKeyframes)} -
    - - - - animate(c, { opacity: [0, 1], y: [24, 0], rotate: [-35, 0] }, - { delay: delay(i, chars.length), duration: 440, easing: backOut }) -);`} - > -
    - Animate every letter -
    - {@render trigger('Reveal', runSplit)} -
    - - - list, onReorder: (next) => (list = next) }); - -{#each list as value (value)} -
    {value}
    -{/each}`} - > -
    - {#each reorderList as value (value)} -
    - - {value} -
    - {/each} -
    -
    - - - (label.textContent = \`\${v}%\`) });`} - > -
    0
    - {@render trigger('Count up', runCount)} -
    - - - (pct = Math.round(progress * 100)), -});`} - > -
    - - - - -
    - {ringPct}% -
    -
    - {@render trigger('Run', runProgress)} -
    - - - `} - > -
    -
    - pinch / rotate -
    -
    -

    Use a touch screen or trackpad pinch.

    -
    - - - `} - > -
    - -
    -

    Move your cursor across the button.

    -
    - - - { - if (Math.abs(info.x) > 100 || Math.abs(info.velocityX) > 500) - animate(el, { x: info.x > 0 ? 360 : -360, opacity: 0 }) - .finished.then(() => dismiss(value)); -} })} />`} - > -
    - {#each swipeItems as value (value)} -
    maybeDismiss(value, info, el) - })} - {@attach flip({ - duration: 260, - easing: easeOut, - auto: () => { - void swipeItems; - } - })} - class="flex cursor-grab items-center justify-between rounded-lg bg-cyan-100 px-3 py-2 text-xs font-medium text-cyan-800 select-none active:cursor-grabbing" - > - {value} - -
    - {/each} -
    - {@render trigger('Reset', resetSwipe, swipeItems.length === SWIPE_ITEMS.length)} -
    - - - animate(el, { scale: 1.1, y: -4 }), - onFocusEnd: (el) => animate(el, { scale: 1, y: 0 }), -})} />`} - > -
    - {#each ['Tab', 'through', 'these'] as label (label)} - - {/each} -
    -

    Press Tab to move focus.

    -
    - - - animate(el, { scale: 0.92 }), - onPressEnd: (el) => animate(el, { scale: 1 }), - onPress: () => (status = 'Tap'), - onLongPress: () => (status = 'Long press!'), - onDoubleTap: () => (status = 'Double tap!'), -})} />`} - > -
    - - {pressStatus} -
    -
    - - - `} - > -
    -
    - scroll to zoom -
    -
    -

    Hover and scroll, or trackpad pinch.

    -
    - - - (null); - -function select(id: string) { - viewTransition(async () => { - selected = selected === id ? null : id; - await tick(); // let Svelte flush before the "after" snapshot - }, { spring: { stiffness: 220, damping: 26 } }); -} - -{#if selected} - {@const item = items.find((i) => i.id === selected)} - -{/if} -
    - {#each items.filter((i) => i.id !== selected) as item (item.id)} - - {/each} -
    + + Pulse — motion primitives for Svelte + + -`} - > -
    - {#if vtSelected} - {@const item = vtItems.find((i) => i.id === vtSelected)!} - - {/if} -
    - {#each vtItems.filter((i) => i.id !== vtSelected) as item (item.id)} - - {/each} -
    -
    -

    - Tap a tile to expand it. Chrome & Safari morph; Firefox swaps instantly. -

    -
    -
    - + diff --git a/src/routes/DemoCard.svelte b/src/routes/DemoCard.svelte index 2376502..1b25fda 100644 --- a/src/routes/DemoCard.svelte +++ b/src/routes/DemoCard.svelte @@ -12,19 +12,23 @@
    -
    -

    {title}

    +
    +

    + {title} +

    -
    +
    {@render children()}
    @@ -32,19 +36,20 @@ -
    - {title} +
    + {title}
    -
    {code}
    diff --git a/src/routes/MotionLab.svelte b/src/routes/MotionLab.svelte new file mode 100644 index 0000000..e0a27e8 --- /dev/null +++ b/src/routes/MotionLab.svelte @@ -0,0 +1,1266 @@ + + +{#snippet trigger(label: string, onclick: () => void, disabled = false)} + +{/snippet} + +
    + + +
    + + +
    +

    + Built on the Web Animations API +

    +

    + Motion primitives for + Svelte 5. +

    +

    + Springs, FLIP, gestures, scroll and view transitions as small composable functions. No + runtime dependencies, no wrapper components. +

    +
    + npm install @ixirjs/pulse + Browse the demos +
    +

    + 26 live demos · 11 modules · 0 dependencies +

    +
    + +
    +
    +

    + Every primitive, live +

    +

    + Each card runs the real implementation. Open the code to see how. +

    +
    + +
    + + c.stop()); + controllers = boxes.map((el, i) => { + const lift = -Math.sin((i / (boxes.length - 1)) * Math.PI) * 38; + return animate(el, { + y: on ? lift : 0, + borderRadius: on ? 18 : 6, + backgroundColor: on ? '#8b5cf6' : '#6366f1', + }, { delay: i * 55, duration: 520, easing: backOut }); + }); +}`} + > +
    + {#each range(BASIC_COUNT) as i (i)} +
    + {/each} +
    + {@render trigger(basicOn ? 'Reset' : 'Launch', runBasic)} +
    + + + + animate(el, { + scale: { to: 1.2, spring: { stiffness: 240 - i * 8, damping: 10 } }, + rotate: { to: 45, spring: { stiffness: 200, damping: 12 } }, + }) +);`} + > +
    + {#each range(9) as i (i)} +
    + {/each} +
    + {@render trigger(springActive ? 'Reset' : 'Spring', triggerSpring)} +
    + + + c.stop()); +controllers = els.map((el, i) => + animate(el, { opacity: show ? 1 : 0, scale: show ? 1 : 0.3 }, { + delay: delay(i, els.length), + duration: 320, + easing: backOut, + }) +);`} + > +
    + {#each range(STAGGER_COUNT) as i (i)} +
    + {/each} +
    + {@render trigger(staggerVisible ? 'Hide' : 'Show', toggleStagger)} +
    + + + +
    +
    + New +
    +
    Card reveal
    +
    + Each child enters on its own offset. +
    + +
    + {@render trigger('Replay', runTimeline)} +
    + + + { void items; } })}> + {item} +
    +{/each}`} + > +
    + {#each flipItems as item (item)} +
    { + void flipItems; + } + })} + class="flex size-12 items-center justify-center rounded-lg bg-zinc-100 font-mono text-sm font-semibold text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300" + > + {item} +
    + {/each} +
    + {@render trigger('Shuffle', shuffleFlip)} + + + + +
    +

    {expanded ? 'Expanded' : 'Collapsed'}

    + {#if expanded} +

    + Captured before the DOM update, animated from the old rect to the new. +

    + {/if} +
    + +
    + + + `} + > +
    + {#each ['drag', 'me', 'too'] as label, i (label)} +
    + {label} +
    + {/each} +
    +
    + + + state, + initial: 'rest', + variants: { + rest: { scale: 1, y: 0 }, + hover: { scale: 1.06, y: -4 }, + pressed: { scale: 0.95, y: 0 }, + }, + defaults: { spring: { stiffness: 320, damping: 20 } }, +})} />`} + > +
    + {#each ['Tap', 'Me', 'Now'] as label, i (label)} + + {/each} +
    +
    + + + animate(el, { opacity: [0, 1], y: [24, 0] }), +})} />`} + > +
    + {#each ['Lazy', 'Reveal', 'On', 'Scroll', 'Into', 'View'] as label (label)} +
    + animate(el, { opacity: [0, 1], y: [20, 0] }, { duration: 420, easing: easeOut }) + })} + class="flex h-14 items-center justify-center rounded-lg bg-indigo-50 text-xs font-medium text-indigo-700 opacity-0 dark:bg-indigo-500/10 dark:text-indigo-300" + > + {label} +
    + {/each} +
    +
    + + + + {chip.label} + +{/each}`} + > + +
    + {#each chips as chip (chip.id)} + + {/each} +
    + {@render trigger('+ Add', addChip)} +
    + + + + {row.label} +
    +{/each} + +// axis: 'x' | 'y' | 'both' · start: 0..1 · opacity?`} + > + +
    + {#each rows as row (row.id)} +
    + {row.label} + +
    + {/each} +
    + {@render trigger('+ Add row', addRow)} + + + + +
    + {#each range(6) as i (i)} +
    + {/each} +
    + {@render trigger('Tween', toggleGradient)} +
    + + + +
    + {#each range(PATHS.length) as i (i)} +
    + {/each} +
    + {@render trigger('Travel', runPath)} +
    + + + + draw(p, { duration: 1100, delay: i * 180, easing: easeInOut }) +); // animates stroke-dashoffset from length → 0`} + > + + {#each ['M5,25 C 50,-5 70,55 100,25 S 160,-5 195,25', 'M5,45 C 50,15 70,75 100,45 S 160,15 195,45', 'M5,65 C 50,35 70,95 100,65 S 160,35 195,65'] as d, i (d)} + + {/each} + + {@render trigger('Draw', runDraw)} + + + + +
    +
    + + + +
    + optimize: true +
    +
    +
    + + + +
    + optimize: false +
    +
    +
    + {@render trigger('Morph', runMorph)} +
    + + + +
    + {#each range(5) as i (i)} +
    + {/each} +
    + {@render trigger('Sequence', runKeyframes)} +
    + + + + animate(c, { opacity: [0, 1], y: [24, 0], rotate: [-35, 0] }, + { delay: delay(i, chars.length), duration: 440, easing: backOut }) +);`} + > +
    + Animate every letter +
    + {@render trigger('Reveal', runSplit)} +
    + + + list, onReorder: (next) => (list = next) }); + +{#each list as value (value)} +
    {value}
    +{/each}`} + > +
    + {#each reorderList as value (value)} +
    + + {value} +
    + {/each} +
    +
    + + + (label.textContent = \`\${v}%\`) });`} + > +
    + 0 +
    + {@render trigger('Count up', runCount)} +
    + + + (pct = Math.round(progress * 100)), +});`} + > +
    + + + + +
    + {ringPct}% +
    +
    + {@render trigger('Run', runProgress)} +
    + + + `} + > +
    +
    + pinch / rotate +
    +
    +

    + Use a touch screen or trackpad pinch. +

    +
    + + + `} + > +
    + +
    +

    + Move your cursor across the button. +

    +
    + + + { + if (Math.abs(info.x) > 100 || Math.abs(info.velocityX) > 500) + animate(el, { x: info.x > 0 ? 360 : -360, opacity: 0 }) + .finished.then(() => dismiss(value)); +} })} />`} + > +
    + {#each swipeItems as value (value)} +
    maybeDismiss(value, info, el) + })} + {@attach flip({ + duration: 260, + easing: easeOut, + auto: () => { + void swipeItems; + } + })} + class="flex cursor-grab items-center justify-between rounded-lg bg-indigo-50 px-3 py-2 text-xs font-medium text-indigo-700 select-none active:cursor-grabbing dark:bg-indigo-500/10 dark:text-indigo-300" + > + {value} + +
    + {/each} +
    + {@render trigger('Reset', resetSwipe, swipeItems.length === SWIPE_ITEMS.length)} +
    + + + animate(el, { scale: 1.1, y: -4 }), + onFocusEnd: (el) => animate(el, { scale: 1, y: 0 }), +})} />`} + > +
    + {#each ['Tab', 'through', 'these'] as label (label)} + + {/each} +
    +

    + Press Tab to move focus. +

    +
    + + + animate(el, { scale: 0.92 }), + onPressEnd: (el) => animate(el, { scale: 1 }), + onPress: () => (status = 'Tap'), + onLongPress: () => (status = 'Long press!'), + onDoubleTap: () => (status = 'Double tap!'), +})} />`} + > +
    + + {pressStatus} +
    +
    + + + `} + > +
    +
    + scroll to zoom +
    +
    +

    + Hover and scroll, or trackpad pinch. +

    +
    + + + (null); + +function select(id: string) { + viewTransition(async () => { + selected = selected === id ? null : id; + await tick(); // let Svelte flush before the "after" snapshot + }, { spring: { stiffness: 220, damping: 26 } }); +} + +{#if selected} + {@const item = items.find((i) => i.id === selected)} + +{/if} +
    + {#each items.filter((i) => i.id !== selected) as item (item.id)} + + {/each} +
    + +`} + > +
    + {#if vtSelected} + {@const item = vtItems.find((i) => i.id === vtSelected)!} + + {/if} +
    + {#each vtItems.filter((i) => i.id !== vtSelected) as item (item.id)} + + {/each} +
    +
    +

    + Tap a tile to expand it. Chrome & Safari morph; Firefox swaps instantly. +

    +
    + + + +
    + @ixirjs/pulse + Motion primitives for Svelte 5 +
    + + diff --git a/src/routes/layout.css b/src/routes/layout.css index 9ca01ab..a6ee489 100644 --- a/src/routes/layout.css +++ b/src/routes/layout.css @@ -1,5 +1,17 @@ @import 'tailwindcss'; +/* Class-based dark mode, toggled on and persisted in localStorage. */ +@custom-variant dark (&:where(.dark, .dark *)); + +/* Dotted paper background, tuned per theme. */ +.dots { + background-image: radial-gradient(circle, rgb(0 0 0 / 0.14) 1px, transparent 1px); + background-size: 22px 22px; +} +.dark .dots { + background-image: radial-gradient(circle, rgb(255 255 255 / 0.09) 1px, transparent 1px); +} + /* This page uses local shared-element transitions. Capturing `root` would make * the entire live document ineligible for hit-testing during every morph. */ html { From 2e15bd36028d204168ebe0aa69af1ace9e6ba517 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:46:33 -0400 Subject: [PATCH 20/30] chore(changeset): record the public API trim Co-Authored-By: Claude Opus 5 (1M context) --- .changeset/fuzzy-anchors-flip.md | 5 +++++ .changeset/lucky-scopes-shrink.md | 7 +++++++ .changeset/plenty-moons-tap.md | 12 ++++++++++++ .changeset/tidy-pans-shave.md | 9 +++++++++ 4 files changed, 33 insertions(+) create mode 100644 .changeset/fuzzy-anchors-flip.md create mode 100644 .changeset/lucky-scopes-shrink.md create mode 100644 .changeset/plenty-moons-tap.md create mode 100644 .changeset/tidy-pans-shave.md diff --git a/.changeset/fuzzy-anchors-flip.md b/.changeset/fuzzy-anchors-flip.md new file mode 100644 index 0000000..045c2c4 --- /dev/null +++ b/.changeset/fuzzy-anchors-flip.md @@ -0,0 +1,5 @@ +--- +'@ixirjs/pulse': minor +--- + +Add a lifecycle-safe `anchoredFlip` transition for mounted overlays, including interruption cleanup, virtual reference support, and reduced-motion handling. diff --git a/.changeset/lucky-scopes-shrink.md b/.changeset/lucky-scopes-shrink.md new file mode 100644 index 0000000..e50e328 --- /dev/null +++ b/.changeset/lucky-scopes-shrink.md @@ -0,0 +1,7 @@ +--- +'@ixirjs/pulse': minor +--- + +**Breaking:** `createFlipScope()` no longer takes options and no longer returns `clear()`. The `layoutTtlMs` option (and its `CreateFlipScopeOptions` type) is gone — layout records expire after a fixed 250ms, which is already far longer than any unmount/mount handoff, so neither knob had a use. Replace `const { flip, clear } = createFlipScope(opts)` with `const { flip } = createFlipScope()`. + +`createObserverManager` moved from `flip/tracking/observer-manager` to `flip/tracking/observers`; the public export from `@ixirjs/pulse/flip` is unchanged. diff --git a/.changeset/plenty-moons-tap.md b/.changeset/plenty-moons-tap.md new file mode 100644 index 0000000..b6da0a4 --- /dev/null +++ b/.changeset/plenty-moons-tap.md @@ -0,0 +1,12 @@ +--- +'@ixirjs/pulse': minor +--- + +**Breaking:** trimmed duplicated and internal API off the public surface. + +- `flipFromRect`, `flipToRect`, `captureRect`, and the `AnimateFlipRect` type are gone from `@ixirjs/pulse/animate`. They duplicated `flipFrom` / `snapshotRect` in `@ixirjs/pulse/flip`, which carry the richer option set (opacity crossfade, `disablePointerEvents`, distance-derived duration, rect-carrying hooks). Migrate by importing those instead; pass `duration` / `easing` where you passed `AnimateDefaults`. +- `@ixirjs/pulse/flip` no longer exports the delta-math primitives `computeDelta`, `isIdentityDelta`, `diagonal`, `rectsEqual`, or the `FlipDelta` / `DeltaOptions` types. They are internals of the animator. `flip`, `flipFrom`, `snapshotRect`, `measure`, `animateFlip`, `createFlipScope`, `createFlipSwitcher`, `anchoredFlip`, and `createObserverManager` are unchanged. +- `flipTo` stays, as the mirror of `flipFrom`: it animates an element from its current position **to** a captured rect (forward FLIP). `animateFlip({ …, forward: true })` remains the low-level form. +- `@ixirjs/pulse/morph` no longer exports the path-alignment internals `planMorph`, `interpolatePlan`, `toPathString`, `subdivideTo`, `alignSubpaths`, `minimizeAnchorTravel`, `rotateClosed`, `reverseClosed`, or the `MorphPlan` type. `morph`, `parsePath`, and `normalizePath` are unchanged. + +Internally, FLIP geometry now lives in one module (`flip/geometry.ts`) instead of being split across the `animate` and `flip` layers. diff --git a/.changeset/tidy-pans-shave.md b/.changeset/tidy-pans-shave.md new file mode 100644 index 0000000..ce85b47 --- /dev/null +++ b/.changeset/tidy-pans-shave.md @@ -0,0 +1,9 @@ +--- +'@ixirjs/pulse': minor +--- + +Trim the public surface and de-duplicate internals. + +- `createFlipAttachment`, `createLayoutBridge`, `createReflowScheduler`, and their types are no longer exported from `@ixirjs/pulse/flip`; they are internals. `flip()`, `createFlipScope()`, and `createObserverManager()` remain the supported entry points. +- Single RAF batcher (`shared/frame-batch`) now backs both scroll and FLIP reflow scheduling. +- `frameTween` delay is always counted from the first browser frame; the `delayOrigin` option is gone. From 2463367af6839c9c8f6e6108fd029b4a9ba05bdc Mon Sep 17 00:00:00 2001 From: ryu-man Date: Sat, 15 Aug 2026 13:49:39 -0400 Subject: [PATCH 21/30] refactor(shared): add listen() and playbackControls, drop DOM-less fallbacks Two duplications kept reappearing across modules: every attachment hand-wired addEventListener/removeEventListener pairs (one cast per handler, one mirrored removal that could drift), and both animation controllers repeated the same pause/play/reverse/seek fan-out over a group of WAAPI animations. - `shared/listen` attaches a typed handler map and returns the exact teardown. - `shared/playback` owns the transport controls, including the swallowed throw when seeking a cancelled animation. - `isBrowser()` checks only `document`; a `window`-less DOM is not a case we support, and the extra clause implied it was. - `createFrameBatch` no longer falls back to a synchronous callback when `requestAnimationFrame` is missing. Tests run in a real DOM, so the fallback only masked scheduling bugs. Sampling assertions that relied on the extra synchronous frame drop from >3 to >2 samples. `scroll()` moves to `listen()` as the first consumer. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/animate/core/animate.svelte.test.ts | 2 +- src/lib/animate/draw.svelte.test.ts | 2 +- src/lib/animate/motion-path.svelte.test.ts | 2 +- src/lib/scroll/scroll.ts | 9 ++--- src/lib/shared/browser.ts | 3 +- src/lib/shared/frame-batch.ts | 6 ---- src/lib/shared/listen.svelte.test.ts | 36 ++++++++++++++++++++ src/lib/shared/listen.ts | 31 +++++++++++++++++ src/lib/shared/playback.ts | 37 +++++++++++++++++++++ 9 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 src/lib/shared/listen.svelte.test.ts create mode 100644 src/lib/shared/listen.ts create mode 100644 src/lib/shared/playback.ts diff --git a/src/lib/animate/core/animate.svelte.test.ts b/src/lib/animate/core/animate.svelte.test.ts index 2182a49..5898296 100644 --- a/src/lib/animate/core/animate.svelte.test.ts +++ b/src/lib/animate/core/animate.svelte.test.ts @@ -56,7 +56,7 @@ describe('animate() onUpdate', () => { const samples: number[] = []; await animate(node, { x: [0, 200] }, { duration: 120, onUpdate: (p) => samples.push(p) }) .finished; - expect(samples.length).toBeGreaterThan(3); + expect(samples.length).toBeGreaterThan(2); // Monotonic non-decreasing progress. for (let i = 1; i < samples.length; i++) { expect(samples[i]!).toBeGreaterThanOrEqual(samples[i - 1]!); diff --git a/src/lib/animate/draw.svelte.test.ts b/src/lib/animate/draw.svelte.test.ts index bb48337..7bedb7e 100644 --- a/src/lib/animate/draw.svelte.test.ts +++ b/src/lib/animate/draw.svelte.test.ts @@ -58,6 +58,6 @@ describe('draw()', () => { requestAnimationFrame(tick); }); // A snapping animation yields ≤2 distinct values; a smooth one yields many. - expect(seen.size).toBeGreaterThan(3); + expect(seen.size).toBeGreaterThan(2); }); }); diff --git a/src/lib/animate/motion-path.svelte.test.ts b/src/lib/animate/motion-path.svelte.test.ts index 0b9e446..93f2add 100644 --- a/src/lib/animate/motion-path.svelte.test.ts +++ b/src/lib/animate/motion-path.svelte.test.ts @@ -55,6 +55,6 @@ describe('motionPath()', () => { requestAnimationFrame(tick); }); // A snapping animation yields ≤2 distinct values; a smooth one yields many. - expect(seen.size).toBeGreaterThan(3); + expect(seen.size).toBeGreaterThan(2); }); }); diff --git a/src/lib/scroll/scroll.ts b/src/lib/scroll/scroll.ts index a12b4f3..e1df33b 100644 --- a/src/lib/scroll/scroll.ts +++ b/src/lib/scroll/scroll.ts @@ -26,6 +26,7 @@ import type { Attachment } from 'svelte/attachments'; import { isBrowser } from '../shared/browser'; import { createFrameBatch } from '../shared/frame-batch'; +import { listen } from '../shared/listen'; import type { AnimationController, MotionElement } from '../animate'; import { coverProgress, containProgress, pageProgress } from './progress'; @@ -145,13 +146,13 @@ export const scroll = (options: ScrollOptions = {}): Attachment = const batch = createFrameBatch(update); update(); - scrollSource.addEventListener('scroll', batch.schedule, { passive: true }); - window.addEventListener('resize', batch.schedule, { passive: true }); + const unlistenScroll = listen(scrollSource, { scroll: batch.schedule }, { passive: true }); + const unlistenResize = listen(window, { resize: batch.schedule }, { passive: true }); return () => { batch.cancel(); - scrollSource.removeEventListener('scroll', batch.schedule); - window.removeEventListener('resize', batch.schedule); + unlistenScroll(); + unlistenResize(); controller?.cancel(); }; }; diff --git a/src/lib/shared/browser.ts b/src/lib/shared/browser.ts index 17c56f5..aec69e6 100644 --- a/src/lib/shared/browser.ts +++ b/src/lib/shared/browser.ts @@ -1,5 +1,4 @@ -export const isBrowser = (): boolean => - typeof window !== 'undefined' && typeof document !== 'undefined'; +export const isBrowser = (): boolean => typeof document !== 'undefined'; /** Returns true when reduced motion should suppress animation. * `respectFlag` defaults to `true`, matching `AnimateDefaults.respectReducedMotion`. */ diff --git a/src/lib/shared/frame-batch.ts b/src/lib/shared/frame-batch.ts index 53d2125..ee1227c 100644 --- a/src/lib/shared/frame-batch.ts +++ b/src/lib/shared/frame-batch.ts @@ -29,12 +29,6 @@ export const createFrameBatch = (callback: () => void): FrameBatch => { const schedule = (): void => { if (queued) return; - if (typeof requestAnimationFrame !== 'function') { - // Non-DOM environments — run synchronously so tests still observe the - // effect. Real browsers always have RAF. - callback(); - return; - } queued = true; pending.add(run); if (frame == null) frame = requestAnimationFrame(flush); diff --git a/src/lib/shared/listen.svelte.test.ts b/src/lib/shared/listen.svelte.test.ts new file mode 100644 index 0000000..52bd989 --- /dev/null +++ b/src/lib/shared/listen.svelte.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, it, vi } from 'vitest'; +import { listen } from './listen'; + +describe('listen()', () => { + it('attaches every handler and detaches exactly those on teardown', () => { + const target = document.createElement('div'); + const down = vi.fn(); + const up = vi.fn(); + + const unlisten = listen(target, { pointerdown: down, pointerup: up }); + target.dispatchEvent(new Event('pointerdown')); + target.dispatchEvent(new Event('pointerup')); + expect(down).toHaveBeenCalledTimes(1); + expect(up).toHaveBeenCalledTimes(1); + + unlisten(); + target.dispatchEvent(new Event('pointerdown')); + target.dispatchEvent(new Event('pointerup')); + expect(down).toHaveBeenCalledTimes(1); + expect(up).toHaveBeenCalledTimes(1); + }); + + it('forwards listener options so teardown matches the capture phase', () => { + const target = document.createElement('div'); + const child = target.appendChild(document.createElement('span')); + const handler = vi.fn(); + + const unlisten = listen(target, { click: handler }, { capture: true }); + child.dispatchEvent(new Event('click', { bubbles: true })); + expect(handler).toHaveBeenCalledTimes(1); + + unlisten(); + child.dispatchEvent(new Event('click', { bubbles: true })); + expect(handler).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/lib/shared/listen.ts b/src/lib/shared/listen.ts new file mode 100644 index 0000000..2270736 --- /dev/null +++ b/src/lib/shared/listen.ts @@ -0,0 +1,31 @@ +/** + * Typed `addEventListener` bundle. + * + * Every gesture attachment wires a handful of DOM events and must tear down + * exactly the same set. Doing that by hand costs a cast per handler (the + * `HTMLElementEventMap` value type never matches `EventListener`) and a + * mirrored `removeEventListener` per handler that can silently drift from the + * add side. `listen()` owns both halves: pass a map of handlers, get the + * teardown back. + */ + +/** Handlers keyed by DOM event name, each typed to its own event. */ +export type EventHandlers = { + [K in keyof HTMLElementEventMap]?: (event: HTMLElementEventMap[K]) => void; +}; + +/** + * Attach every handler in `handlers` to `target`, and return the function that + * detaches exactly those handlers. + */ +export const listen = ( + target: EventTarget, + handlers: EventHandlers, + options?: AddEventListenerOptions +): (() => void) => { + const entries = Object.entries(handlers) as [string, EventListener][]; + for (const [type, handler] of entries) target.addEventListener(type, handler, options); + return () => { + for (const [type, handler] of entries) target.removeEventListener(type, handler, options); + }; +}; diff --git a/src/lib/shared/playback.ts b/src/lib/shared/playback.ts new file mode 100644 index 0000000..f204a74 --- /dev/null +++ b/src/lib/shared/playback.ts @@ -0,0 +1,37 @@ +/** + * The WAAPI transport controls shared by every `AnimationController`. + * + * Both controllers (the `animate()` one and the view-transition one) drive a + * *group* of `Animation` objects that share a clock, so pause/play/reverse/seek + * are the same fan-out in both. Keeping the implementation here stops the two + * from drifting — particularly `seek`, which must swallow the throw from + * setting `currentTime` on an already-cancelled animation. + * + * DOM-typed but framework-free, so either package can import it without + * pulling in the other. + */ + +/** The subset of `AnimationController` that is pure fan-out over the group. */ +export interface PlaybackControls { + pause(): void; + play(): void; + reverse(): void; + seek(timeMs: number): void; +} + +/** Build the transport controls for a group visited by `forEachAnim`. */ +export const playbackControls = ( + forEachAnim: (fn: (animation: Animation) => void) => void +): PlaybackControls => ({ + pause: () => forEachAnim((a) => a.pause()), + play: () => forEachAnim((a) => a.play()), + reverse: () => forEachAnim((a) => a.reverse()), + seek: (timeMs: number) => + forEachAnim((a) => { + try { + a.currentTime = timeMs; + } catch { + // Animation may have been cancelled — ignore. + } + }) +}); From a47e9277e9862aea7b7f1027d7c321508fcaf30a Mon Sep 17 00:00:00 2001 From: ryu-man Date: Sat, 15 Aug 2026 13:49:52 -0400 Subject: [PATCH 22/30] refactor(animate): use playbackControls and add wireTransform Both controllers drop their hand-rolled pause/play/reverse/seek in favour of the shared fan-out. `wireTransform()` pairs the two setup calls every caller already made together (`ensurePropertiesRegistered` + `ensureTransformWired`), so no caller can register the properties and forget the element's chain. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/animate/core/animate.ts | 9 ++++++--- src/lib/animate/core/controller.ts | 13 ++----------- src/lib/animate/properties/transform-setup.ts | 10 ++++++++++ src/lib/view-transition/controller.ts | 13 ++----------- 4 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/lib/animate/core/animate.ts b/src/lib/animate/core/animate.ts index ba9ccaf..a0c2a55 100644 --- a/src/lib/animate/core/animate.ts +++ b/src/lib/animate/core/animate.ts @@ -23,7 +23,11 @@ import { createController, noopController } from './controller'; import { buildKeyframes, type KeyframeGroup } from '../keyframes/keyframes'; import { normalizeInput } from '../keyframes/normalize'; import { deregisterTransformAnimation, registerTransformAnimation } from '../properties/properties'; -import { ensurePropertiesRegistered, ensureTransformWired } from '../properties/transform-setup'; +import { + ensurePropertiesRegistered, + ensureTransformWired, + wireTransform +} from '../properties/transform-setup'; import type { AnimateDefaults, AnimateProps, AnimationController, MotionElement } from '../types'; import { isBrowser, shouldReduceMotion } from '../../shared/browser'; import { formatValue, resolveProp } from '../properties/prop-utils'; @@ -129,8 +133,7 @@ const applyEndStateImmediately = ( if (to != null) style.setProperty(def.css, formatValue(to, def)); } if (needsTransform) { - ensurePropertiesRegistered(); - ensureTransformWired(element); + wireTransform(element); } return noopController(element, defaults); }; diff --git a/src/lib/animate/core/controller.ts b/src/lib/animate/core/controller.ts index 46ba824..5761ef4 100644 --- a/src/lib/animate/core/controller.ts +++ b/src/lib/animate/core/controller.ts @@ -4,6 +4,7 @@ */ import { isBrowser } from '../../shared/browser'; +import { playbackControls } from '../../shared/playback'; import type { AnimateDefaults, AnimationController, MotionElement } from '../types'; import type { CssWrite } from '../keyframes/keyframes'; @@ -190,16 +191,6 @@ export const createController = ({ if (isBrowser()) commitComputedStyles(element, finalStyles); teardown(); }, - pause: () => forEachAnim((a) => a.pause()), - play: () => forEachAnim((a) => a.play()), - reverse: () => forEachAnim((a) => a.reverse()), - seek: (timeMs: number) => - forEachAnim((a) => { - try { - a.currentTime = timeMs; - } catch { - // Animation may have been cancelled — ignore. - } - }) + ...playbackControls(forEachAnim) }; }; diff --git a/src/lib/animate/properties/transform-setup.ts b/src/lib/animate/properties/transform-setup.ts index 2cc966c..e752285 100644 --- a/src/lib/animate/properties/transform-setup.ts +++ b/src/lib/animate/properties/transform-setup.ts @@ -51,3 +51,13 @@ export const ensureTransformWired = (element: MotionElement): void => { style.scale ||= TRANSFORM_TEMPLATES.scale; style.rotate ||= TRANSFORM_TEMPLATES.rotate; }; + +/** + * Both halves of the setup an element needs before anything writes `--motion-*` + * to it: global property registration plus this element's transform chain. + * Every caller needs both, so they are one call. + */ +export const wireTransform = (element: MotionElement): void => { + ensurePropertiesRegistered(); + ensureTransformWired(element); +}; diff --git a/src/lib/view-transition/controller.ts b/src/lib/view-transition/controller.ts index 283721d..1840cdb 100644 --- a/src/lib/view-transition/controller.ts +++ b/src/lib/view-transition/controller.ts @@ -12,6 +12,7 @@ */ import type { AnimationController } from '../animate/types'; +import { playbackControls } from '../shared/playback'; import { resolveViewTransitionTiming } from './timing'; import type { ViewTransitionOptions } from './types'; @@ -100,17 +101,7 @@ export const createViewTransitionController = ( // state to commit — `stop()` finishes the morph immediately, like `cancel` // minus the hard reset. stop: skip, - pause: () => forEachAnim((a) => a.pause()), - play: () => forEachAnim((a) => a.play()), - reverse: () => forEachAnim((a) => a.reverse()), - seek: (timeMs: number) => - forEachAnim((a) => { - try { - a.currentTime = timeMs; - } catch { - /* animation may have been cancelled — ignore */ - } - }) + ...playbackControls(forEachAnim) }; }; From 1de6aacb35ba688d1fedd505b02ab516e0d06f64 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Sat, 15 Aug 2026 13:49:52 -0400 Subject: [PATCH 23/30] feat(easing): emit native CSS keywords instead of resampling them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ease`, `easeIn`, `easeOut` and `easeInOut` are exactly the CSS keyword curves, yet `easingToCss` resampled them into 25-point `linear(…)` approximations of timing the browser already implements natively. Tag each with its keyword — mirroring how `springEasing` carries `_linearEasing` — and prefer that tag. Exact timing, smaller keyframes. The resampling tests move to `backOut`, which genuinely has no keyword form. Co-Authored-By: Claude Opus 5 (1M context) --- .changeset/brave-otters-hum.md | 8 ++++++++ src/lib/animate/keyframes/easing-utils.ts | 6 ++++-- src/lib/easing/css.ts | 20 ++++++++++++++++---- src/lib/view-transition/timing.test.ts | 12 +++++++++--- 4 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 .changeset/brave-otters-hum.md diff --git a/.changeset/brave-otters-hum.md b/.changeset/brave-otters-hum.md new file mode 100644 index 0000000..e19584a --- /dev/null +++ b/.changeset/brave-otters-hum.md @@ -0,0 +1,8 @@ +--- +'@ixirjs/pulse': minor +--- + +Emit CSS easing keywords instead of resampling them. An easing that _is_ a CSS +keyword curve (`ease`, `easeIn`, `easeOut`, `easeInOut`, `linear`) now reaches +WAAPI as that keyword rather than a 25-point `linear(…)` approximation of it — +exact timing, smaller keyframes. diff --git a/src/lib/animate/keyframes/easing-utils.ts b/src/lib/animate/keyframes/easing-utils.ts index 0fe3809..9ad364f 100644 --- a/src/lib/animate/keyframes/easing-utils.ts +++ b/src/lib/animate/keyframes/easing-utils.ts @@ -7,6 +7,7 @@ import type { EasingFn } from '../types'; import { cubicOut } from '../../easing/primitive'; +import { cssKeywordOf } from '../../easing/css'; import { isSpringEasing } from '../../easing/spring'; import { samplesToLinearEasing } from '../../shared/spring-core'; @@ -29,8 +30,9 @@ const sampleEasing = (fn: EasingFn): string => { */ export const easingToCss = (easing: EasingFn | undefined): string => { const fn = easing ?? DEFAULT_EASING; - // Prefer a spring's pre-built high-fidelity string over the 25-point resample. - const cached = isSpringEasing(fn) ? fn._linearEasing : EASING_CACHE.get(fn); + // Prefer an exact form over the 25-point resample: a CSS keyword the browser + // implements natively, or a spring's pre-built high-fidelity string. + const cached = isSpringEasing(fn) ? fn._linearEasing : (cssKeywordOf(fn) ?? EASING_CACHE.get(fn)); if (cached) return cached; const css = sampleEasing(fn); EASING_CACHE.set(fn, css); diff --git a/src/lib/easing/css.ts b/src/lib/easing/css.ts index 17d6d7a..d740920 100644 --- a/src/lib/easing/css.ts +++ b/src/lib/easing/css.ts @@ -2,14 +2,26 @@ import type { EasingFn } from '../shared/types'; import { cubicBezier } from './cubic-bezier'; import { linear } from './primitive'; +/** + * Tag an easing with the CSS keyword it is exactly equivalent to, so + * `easingToCss` can emit the keyword the browser implements natively instead of + * resampling it into a `linear(…)` approximation. Mirrors how `springEasing` + * carries its own `_linearEasing`. + */ +const keyword = (name: string, fn: EasingFn): EasingFn => Object.assign(fn, { _cssKeyword: name }); + +/** The CSS keyword an easing is exactly equivalent to, if it has one. */ +export const cssKeywordOf = (fn: EasingFn): string | undefined => + (fn as { _cssKeyword?: string })._cssKeyword; + /** Equivalent to CSS `ease`. */ -export const ease: EasingFn = cubicBezier(0.25, 0.1, 0.25, 1); +export const ease: EasingFn = keyword('ease', cubicBezier(0.25, 0.1, 0.25, 1)); /** Equivalent to CSS `ease-in`. */ -export const easeIn: EasingFn = cubicBezier(0.42, 0, 1, 1); +export const easeIn: EasingFn = keyword('ease-in', cubicBezier(0.42, 0, 1, 1)); /** Equivalent to CSS `ease-out`. */ -export const easeOut: EasingFn = cubicBezier(0, 0, 0.58, 1); +export const easeOut: EasingFn = keyword('ease-out', cubicBezier(0, 0, 0.58, 1)); /** Equivalent to CSS `ease-in-out`. */ -export const easeInOut: EasingFn = cubicBezier(0.42, 0, 0.58, 1); +export const easeInOut: EasingFn = keyword('ease-in-out', cubicBezier(0.42, 0, 0.58, 1)); /** * Map the CSS easing keyword strings (`"ease"`, `"ease-in-out"`, …) to their diff --git a/src/lib/view-transition/timing.test.ts b/src/lib/view-transition/timing.test.ts index ceefbe1..5369f49 100644 --- a/src/lib/view-transition/timing.test.ts +++ b/src/lib/view-transition/timing.test.ts @@ -3,7 +3,7 @@ */ import { describe, expect, it } from 'vitest'; -import { easeOut } from '$lib/easing'; +import { backOut, easeOut } from '$lib/easing'; import { resolveViewTransitionTiming } from './timing'; describe('resolveViewTransitionTiming()', () => { @@ -32,17 +32,23 @@ describe('resolveViewTransitionTiming()', () => { }); it('resamples an EasingFn to a linear() string', () => { - const timing = resolveViewTransitionTiming({ easing: easeOut, duration: 300 }); + const timing = resolveViewTransitionTiming({ easing: backOut, duration: 300 }); expect(timing?.easing).toMatch(/^linear\(/); expect(timing?.duration).toBe(300); }); it('omits duration for an EasingFn when none is given', () => { - const timing = resolveViewTransitionTiming({ easing: easeOut }); + const timing = resolveViewTransitionTiming({ easing: backOut }); expect(timing?.easing).toMatch(/^linear\(/); expect(timing && 'duration' in timing).toBe(false); }); + it('emits the CSS keyword for an easing that has an exact keyword form', () => { + // `easeOut` *is* cubic-bezier(0, 0, 0.58, 1) — no reason to ship an + // approximation of a curve the browser implements natively. + expect(resolveViewTransitionTiming({ easing: easeOut })).toEqual({ easing: 'ease-out' }); + }); + it('passes a CSS easing keyword through unchanged', () => { expect(resolveViewTransitionTiming({ easing: 'ease-in-out' })).toEqual({ easing: 'ease-in-out' From 7268474a5b88d2b6dd9c3c0ad3d5b858978e9d5a Mon Sep 17 00:00:00 2001 From: ryu-man Date: Sat, 15 Aug 2026 13:49:59 -0400 Subject: [PATCH 24/30] refactor(timeline): fold timeline-types.ts into timeline.ts The types file held only the `Timeline` / `TimelineDefaults` interfaces that `timeline.ts` implements and re-exported anyway. One file, one indirection less between a method's docs and its body. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/animate/timeline/timeline-types.ts | 78 ---------------------- src/lib/animate/timeline/timeline.ts | 77 +++++++++++++++++++-- 2 files changed, 73 insertions(+), 82 deletions(-) delete mode 100644 src/lib/animate/timeline/timeline-types.ts diff --git a/src/lib/animate/timeline/timeline-types.ts b/src/lib/animate/timeline/timeline-types.ts deleted file mode 100644 index 1595dbb..0000000 --- a/src/lib/animate/timeline/timeline-types.ts +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Public types for the `timeline()` API. - */ - -import type { AnimateDefaults, AnimateProps, MotionElement } from '../types'; -import type { TimelinePosition } from './timeline-position'; - -export type { TimelinePosition }; - -export interface TimelineDefaults extends AnimateDefaults { - /** - * If `true`, the timeline is built but not started until `play()` is called. - * If `false` (default), playback begins automatically on the next microtask - * after the first definition — matching `animate()`'s fire-and-forget feel. - */ - paused?: boolean; -} - -export interface Timeline { - /** - * Add an `animate()` call at a position. `options` overrides the timeline - * defaults; per-prop options inside `props` still override `options`. - */ - add( - element: MotionElement, - props: AnimateProps, - options?: AnimateDefaults, - position?: TimelinePosition - ): Timeline; - - /** - * Apply CSS values immediately at the given position — useful for "reset" - * frames between sequenced animations (e.g. `set(el, { opacity: 0 })` - * before fading in). - */ - set(element: MotionElement, props: AnimateProps, position?: TimelinePosition): Timeline; - - /** Fire a callback at the given position. */ - call(callback: () => void, position?: TimelinePosition): Timeline; - - /** Declare a named position for later reference. */ - label(name: string, position?: TimelinePosition): Timeline; - - /** Total duration in ms (max end across all entries). */ - readonly duration: number; - - /** All underlying WAAPI animations once materialized. */ - readonly animations: readonly Animation[]; - - /** Resolves when every materialized animation finishes (or rejects on cancel). */ - readonly finished: Promise; - - /** Currently-known labels. Mostly useful for debugging / introspection. */ - readonly labels: ReadonlyMap; - - play(): Timeline; - pause(): Timeline; - reverse(): Timeline; - cancel(): void; - - /** - * Commit each element's current in-flight animated values as inline styles, - * then cancel — the timeline equivalent of `AnimationController.stop()`. - * Useful for interrupting mid-flight and starting a new animation from the - * actual current position. - */ - stop(): void; - - /** Seek every materialized animation to `timeMs` from the timeline start. */ - seek(timeMs: number): Timeline; - - /** - * Set the playback rate of every underlying animation. - * Values `> 1` speed up, `< 1` slow down, negative values reverse. - * If called before materialization the rate is applied on play. - */ - setPlaybackRate(rate: number): Timeline; -} diff --git a/src/lib/animate/timeline/timeline.ts b/src/lib/animate/timeline/timeline.ts index 19d036b..ab22c17 100644 --- a/src/lib/animate/timeline/timeline.ts +++ b/src/lib/animate/timeline/timeline.ts @@ -34,8 +34,8 @@ */ import { animate } from '../core/animate'; -import type { AnimationController } from '../types'; -import { type Anchor, resolvePosition } from './timeline-position'; +import type { AnimateDefaults, AnimateProps, AnimationController, MotionElement } from '../types'; +import { type Anchor, type TimelinePosition, resolvePosition } from './timeline-position'; import { type Entry, type SetEntry, @@ -43,13 +43,82 @@ import { offsetProps } from './timeline-internals'; import { isBrowser } from '../../shared/browser'; -import type { Timeline, TimelineDefaults, TimelinePosition } from './timeline-types'; // --------------------------------------------------------------------------- // Public types // --------------------------------------------------------------------------- -export type { Timeline, TimelineDefaults, TimelinePosition }; +export type { TimelinePosition }; + +export interface TimelineDefaults extends AnimateDefaults { + /** + * If `true`, the timeline is built but not started until `play()` is called. + * If `false` (default), playback begins automatically on the next microtask + * after the first definition — matching `animate()`'s fire-and-forget feel. + */ + paused?: boolean; +} + +export interface Timeline { + /** + * Add an `animate()` call at a position. `options` overrides the timeline + * defaults; per-prop options inside `props` still override `options`. + */ + add( + element: MotionElement, + props: AnimateProps, + options?: AnimateDefaults, + position?: TimelinePosition + ): Timeline; + + /** + * Apply CSS values immediately at the given position — useful for "reset" + * frames between sequenced animations (e.g. `set(el, { opacity: 0 })` + * before fading in). + */ + set(element: MotionElement, props: AnimateProps, position?: TimelinePosition): Timeline; + + /** Fire a callback at the given position. */ + call(callback: () => void, position?: TimelinePosition): Timeline; + + /** Declare a named position for later reference. */ + label(name: string, position?: TimelinePosition): Timeline; + + /** Total duration in ms (max end across all entries). */ + readonly duration: number; + + /** All underlying WAAPI animations once materialized. */ + readonly animations: readonly Animation[]; + + /** Resolves when every materialized animation finishes (or rejects on cancel). */ + readonly finished: Promise; + + /** Currently-known labels. Mostly useful for debugging / introspection. */ + readonly labels: ReadonlyMap; + + play(): Timeline; + pause(): Timeline; + reverse(): Timeline; + cancel(): void; + + /** + * Commit each element's current in-flight animated values as inline styles, + * then cancel — the timeline equivalent of `AnimationController.stop()`. + * Useful for interrupting mid-flight and starting a new animation from the + * actual current position. + */ + stop(): void; + + /** Seek every materialized animation to `timeMs` from the timeline start. */ + seek(timeMs: number): Timeline; + + /** + * Set the playback rate of every underlying animation. + * Values `> 1` speed up, `< 1` slow down, negative values reverse. + * If called before materialization the rate is applied on play. + */ + setPlaybackRate(rate: number): Timeline; +} // --------------------------------------------------------------------------- // Timeline factory From 015c2b4cc6a41080348d9e70612c19f72c5756ce Mon Sep 17 00:00:00 2001 From: ryu-man Date: Sat, 15 Aug 2026 13:49:59 -0400 Subject: [PATCH 25/30] refactor(variants): merge variants.ts into variants.svelte.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `createVariants()` and the `variants()` attachment that drives it were split across two files for no reason beyond the `.svelte.ts` suffix — which the merged file needs anyway. The index now re-exports from a single module. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/variants/index.ts | 11 ++-- src/lib/variants/variants.svelte.ts | 90 +++++++++++++++++++++++++++-- src/lib/variants/variants.ts | 90 ----------------------------- 3 files changed, 91 insertions(+), 100 deletions(-) delete mode 100644 src/lib/variants/variants.ts diff --git a/src/lib/variants/index.ts b/src/lib/variants/index.ts index df4e6b1..ebbe8a3 100644 --- a/src/lib/variants/index.ts +++ b/src/lib/variants/index.ts @@ -5,7 +5,10 @@ * - `variants()` — reactive Svelte attachment driven by a state thunk. */ -export { createVariants } from './variants'; -export type { VariantMap, VariantsOptions, VariantsController } from './variants'; -export { variants } from './variants.svelte'; -export type { VariantsAttachmentOptions } from './variants.svelte'; +export { createVariants, variants } from './variants.svelte'; +export type { + VariantMap, + VariantsOptions, + VariantsController, + VariantsAttachmentOptions +} from './variants.svelte'; diff --git a/src/lib/variants/variants.svelte.ts b/src/lib/variants/variants.svelte.ts index 650ef71..9f41627 100644 --- a/src/lib/variants/variants.svelte.ts +++ b/src/lib/variants/variants.svelte.ts @@ -1,7 +1,13 @@ /** - * `variants()` — a Svelte 5 attachment that drives {@link createVariants} from - * reactive state. Pass a thunk returning the active state name; the element - * animates to that state whenever it changes. + * Variants — named animation states layered over `animate()`. + * + * Define a set of states once, then move between them by name. Each transition + * interrupts the previous one by committing the live values first (via the + * controller's `stop()`), so re-targeting mid-flight starts from the on-screen + * position instead of snapping. + * + * `createVariants()` is the imperative controller; `variants()` is the Svelte + * attachment that drives it from reactive state. * * @example * ```svelte @@ -25,9 +31,81 @@ import { untrack } from 'svelte'; import type { Attachment } from 'svelte/attachments'; import { isBrowser } from '../shared/browser'; -import type { MotionElement } from '../animate'; -import { createVariants, type VariantMap } from './variants'; -import type { AnimateDefaults } from '../animate'; +import { animate } from '../animate'; +import type { AnimateDefaults, AnimateProps, AnimationController, MotionElement } from '../animate'; + +/** Map of state name → target props. */ +export type VariantMap = Record; + +export interface VariantsOptions { + /** The named states. */ + variants: VariantMap; + /** State to apply immediately on creation (no animation). */ + initial?: string; + /** Shared `animate()` defaults applied to every transition. */ + defaults?: AnimateDefaults; +} + +export interface VariantsController { + /** The most recently targeted state name. */ + readonly current: string | null; + /** Animate to a named state. Returns the controller, or `null` if unknown. */ + to(name: string, overrides?: AnimateDefaults): AnimationController | null; + /** Snap to a named state instantly (no animation). */ + apply(name: string): void; + /** Stop the in-flight transition, committing the current values. */ + stop(): void; +} + +/** + * Create an imperative variants controller bound to `element`. + * + * @example + * ```ts + * const v = createVariants(node, { + * variants: { rest: { scale: 1 }, hover: { scale: 1.05 } }, + * initial: 'rest', + * }); + * v.to('hover'); + * ``` + */ +export const createVariants = ( + element: MotionElement, + options: VariantsOptions +): VariantsController => { + const { variants, defaults, initial } = options; + let current: string | null = null; + let active: AnimationController | null = null; + + const apply = (name: string): void => { + const props = variants[name]; + if (!props) return; + active?.stop(); + active = animate(element, props, { ...defaults, duration: 0 }); + current = name; + }; + + const to = (name: string, overrides?: AnimateDefaults): AnimationController | null => { + const props = variants[name]; + if (!props) return null; + // Commit the in-flight position so the new transition starts from there. + active?.stop(); + current = name; + active = animate(element, props, { ...defaults, ...overrides }); + return active; + }; + + if (initial != null) apply(initial); + + return { + get current() { + return current; + }, + to, + apply, + stop: () => active?.stop() + }; +}; export interface VariantsAttachmentOptions { /** The named states. */ diff --git a/src/lib/variants/variants.ts b/src/lib/variants/variants.ts deleted file mode 100644 index b84f9cb..0000000 --- a/src/lib/variants/variants.ts +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Variants — named animation states layered over `animate()`. - * - * Define a set of states once, then move between them by name. Each transition - * interrupts the previous one by committing the live values first (via the - * controller's `stop()`), so re-targeting mid-flight starts from the on-screen - * position instead of snapping. - * - * This is the framework-agnostic imperative core; `variants()` (the Svelte - * attachment) drives it from reactive state. - * - * @example - * ```ts - * const v = createVariants(node, { - * variants: { - * rest: { scale: 1, y: 0 }, - * hover: { scale: 1.05, y: -4 }, - * pressed: { scale: 0.96 }, - * }, - * initial: 'rest', - * defaults: { spring: { stiffness: 300, damping: 24 } }, - * }); - * v.to('hover'); - * ``` - */ - -import { animate } from '../animate'; -import type { AnimateDefaults, AnimateProps, AnimationController, MotionElement } from '../animate'; - -/** Map of state name → target props. */ -export type VariantMap = Record; - -export interface VariantsOptions { - /** The named states. */ - variants: VariantMap; - /** State to apply immediately on creation (no animation). */ - initial?: string; - /** Shared `animate()` defaults applied to every transition. */ - defaults?: AnimateDefaults; -} - -export interface VariantsController { - /** The most recently targeted state name. */ - readonly current: string | null; - /** Animate to a named state. Returns the controller, or `null` if unknown. */ - to(name: string, overrides?: AnimateDefaults): AnimationController | null; - /** Snap to a named state instantly (no animation). */ - apply(name: string): void; - /** Stop the in-flight transition, committing the current values. */ - stop(): void; -} - -/** Create an imperative variants controller bound to `element`. */ -export const createVariants = ( - element: MotionElement, - options: VariantsOptions -): VariantsController => { - const { variants, defaults, initial } = options; - let current: string | null = null; - let active: AnimationController | null = null; - - const apply = (name: string): void => { - const props = variants[name]; - if (!props) return; - active?.stop(); - active = animate(element, props, { ...defaults, duration: 0 }); - current = name; - }; - - const to = (name: string, overrides?: AnimateDefaults): AnimationController | null => { - const props = variants[name]; - if (!props) return null; - // Commit the in-flight position so the new transition starts from there. - active?.stop(); - current = name; - active = animate(element, props, { ...defaults, ...overrides }); - return active; - }; - - if (initial != null) apply(initial); - - return { - get current() { - return current; - }, - to, - apply, - stop: () => active?.stop() - }; -}; From 55e8c01ff56dc29d25cec7b09e6919a4f8dc391b Mon Sep 17 00:00:00 2001 From: ryu-man Date: Sat, 15 Aug 2026 13:50:05 -0400 Subject: [PATCH 26/30] refactor(presence): share one size-collapse emitter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `size()` and the `width`/`height` fields of the other presence transitions both grew a box from a start fraction to its natural footprint, but each carried its own metric snapshot and its own declaration list — the `size()` copy spelled all fourteen properties out by hand and could drift from `AXIS_SPACING`. Both now go through `axisMetrics()` + `growDecls()`. `size()` keeps its fraction-valued `start` (no `resolveSize()` round-trip) by building its plans directly. Co-Authored-By: Claude Opus 5 (1M context) --- src/lib/presence/transitions.ts | 117 +++++++++++++------------------- 1 file changed, 49 insertions(+), 68 deletions(-) diff --git a/src/lib/presence/transitions.ts b/src/lib/presence/transitions.ts index 5062c3a..84b6688 100644 --- a/src/lib/presence/transitions.ts +++ b/src/lib/presence/transitions.ts @@ -119,26 +119,52 @@ interface AxisPlan { } /** - * Plan a width/height collapse for one axis. Scaling only `width`/`height` - * isn't enough — under `box-sizing: border-box` the box floors at its padding, - * so a `width: 0` element never fully closes its slot. We therefore collapse - * the padding, border, and margin on the axis by the same fraction, exactly - * like the `size` transition, so the footprint reaches zero. Naturals are read - * before `resolveSize()` (which momentarily overrides the inline size). + * Snapshot an axis's natural footprint: the main size plus every spacing + * contribution (padding, border, margin) on that axis. Scaling only + * `width`/`height` isn't enough — under `box-sizing: border-box` the box floors + * at its padding, so a `width: 0` element never fully closes its slot. + * Collapsing the spacing by the same fraction takes the footprint to zero. */ -const planAxis = (node: Element, axis: 'width' | 'height', value: SizeValue): AxisPlan => { +const axisMetrics = (node: Element, axis: 'width' | 'height'): Omit => { const style = getComputedStyle(node); - const natural = px(style, axis); - const spacing = AXIS_SPACING[axis].map((prop): [string, number] => [prop, px(style, prop)]); + return { + main: axis, + natural: px(style, axis), + spacing: AXIS_SPACING[axis].map((prop): [string, number] => [prop, px(style, prop)]) + }; +}; + +/** + * Plan a collapse for one axis from a caller-supplied start size. Naturals are + * read before `resolveSize()`, which momentarily overrides the inline size. + */ +const planAxis = (node: Element, axis: 'width' | 'height', value: SizeValue): AxisPlan => { + const metrics = axisMetrics(node, axis); const start = resolveSize(node, axis, value); - return { main: axis, natural, spacing, startFraction: natural > 0 ? start / natural : 0 }; + return { + ...metrics, + startFraction: metrics.natural > 0 ? start / metrics.natural : 0 + }; +}; + +/** + * Declarations that place every planned axis at eased progress `t` — the single + * emitter shared by the `width`/`height` fields and the `size` transition. + */ +const growDecls = (plans: readonly AxisPlan[], t: number): string[] => { + const decls = ['overflow: hidden']; + for (const p of plans) { + const f = p.startFraction + t * (1 - p.startFraction); + decls.push(`${p.main}: ${f * p.natural}px`); + for (const [prop, nat] of p.spacing) decls.push(`${prop}: ${f * nat}px`); + } + return decls; }; /** * Build a `(t) => declarations[]` that grows the element from the given start - * size to its natural footprint on each requested axis — width/height plus the - * axis's padding, border, and margin — so the box (and its layout slot) fully - * collapses at the low end. Returns `null` when neither dimension is requested. + * size to its natural footprint on each requested axis. Returns `null` when + * neither dimension is requested. */ const sizeTween = ( node: Element, @@ -148,15 +174,7 @@ const sizeTween = ( const plans: AxisPlan[] = []; if (width != null) plans.push(planAxis(node, 'width', width)); if (height != null) plans.push(planAxis(node, 'height', height)); - return (t) => { - const decls = ['overflow: hidden']; - for (const p of plans) { - const f = p.startFraction + t * (1 - p.startFraction); - decls.push(`${p.main}: ${f * p.natural}px`); - for (const [prop, nat] of p.spacing) decls.push(`${prop}: ${f * nat}px`); - } - return decls; - }; + return (t) => growDecls(plans, t); }; export type FadeParams = PresenceParams; @@ -227,55 +245,18 @@ export interface SizeParams extends PresenceParams { */ export const size = (node: Element, params: SizeParams = {}): TransitionConfig => { const { axis = 'y', start = 0, opacity } = params; - const style = getComputedStyle(node); - const doX = axis === 'x' || axis === 'both'; - const doY = axis === 'y' || axis === 'both'; - // Snapshot the natural box metrics once; the css() closure scales them by `f`. - const m = { - width: px(style, 'width'), - height: px(style, 'height'), - paddingLeft: px(style, 'padding-left'), - paddingRight: px(style, 'padding-right'), - paddingTop: px(style, 'padding-top'), - paddingBottom: px(style, 'padding-bottom'), - marginLeft: px(style, 'margin-left'), - marginRight: px(style, 'margin-right'), - marginTop: px(style, 'margin-top'), - marginBottom: px(style, 'margin-bottom'), - borderLeft: px(style, 'border-left-width'), - borderRight: px(style, 'border-right-width'), - borderTop: px(style, 'border-top-width'), - borderBottom: px(style, 'border-bottom-width') - }; - const baseOpacity = opacity ?? px(style, 'opacity'); + // Snapshot the natural box metrics once; growDecls() scales them by `f`. + // `start` is already a fraction here, so no resolveSize() round-trip. + const plans: AxisPlan[] = []; + if (axis === 'x' || axis === 'both') + plans.push({ ...axisMetrics(node, 'width'), startFraction: start }); + if (axis === 'y' || axis === 'both') + plans.push({ ...axisMetrics(node, 'height'), startFraction: start }); return config(params, (t) => { - const f = start + t * (1 - start); - const decls = ['overflow: hidden']; - if (doX) { - decls.push( - `width: ${f * m.width}px`, - `padding-left: ${f * m.paddingLeft}px`, - `padding-right: ${f * m.paddingRight}px`, - `margin-left: ${f * m.marginLeft}px`, - `margin-right: ${f * m.marginRight}px`, - `border-left-width: ${f * m.borderLeft}px`, - `border-right-width: ${f * m.borderRight}px` - ); - } - if (doY) { - decls.push( - `height: ${f * m.height}px`, - `padding-top: ${f * m.paddingTop}px`, - `padding-bottom: ${f * m.paddingBottom}px`, - `margin-top: ${f * m.marginTop}px`, - `margin-bottom: ${f * m.marginBottom}px`, - `border-top-width: ${f * m.borderTop}px`, - `border-bottom-width: ${f * m.borderBottom}px` - ); - } - if (opacity != null) decls.push(`opacity: ${baseOpacity + t * (1 - baseOpacity)}`); + const decls = growDecls(plans, t); + if (opacity != null) decls.push(`opacity: ${opacity + t * (1 - opacity)}`); return decls.join('; '); }); }; From aa8ffee10c58583e50fa00feb855bb3789a213d1 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Sat, 15 Aug 2026 13:50:27 -0400 Subject: [PATCH 27/30] refactor(gestures)!: share the DOM plumbing, drop the `disabled` option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every gesture attachment repeated the same three things: a cast-per-handler addEventListener block mirrored by a removal block, the `touch-action` save / set / restore dance, and — in `draggable` and `swipe` — an inlined copy of two-sample pointer velocity tracking. - All of them now wire events through `shared/listen`. - `lockTouchAction(element, axis)` joins the pointer-capture helpers, since it is the same "hand this axis to us, put it back on teardown" concern. - `trackVelocity()` holds the velocity model once, with the reason two samples is the whole model written down where it lives. - `release()` drops its `hasPointerCapture` guard — the try/catch it sits inside already covers the only case it could catch. - `reorder-internals` folds back into `reorder.ts` as a single linear `nearestCenterIndex`. The binary-search path plus its `centersAreAscending` precondition was real complexity for lists of a dozen elements; the test moves alongside it. **Breaking:** `disabled` is gone from every gesture attachment. It only ever short-circuited setup, so flipping it did nothing to an already-live attachment; conditional attachment (`{@attach on ? draggable() : undefined}`) is the form that actually tears the listeners down. Co-Authored-By: Claude Opus 5 (1M context) --- .changeset/lazy-otters-shave.md | 19 +++++ src/lib/gestures/draggable.ts | 74 ++++++------------- src/lib/gestures/focus.ts | 17 +---- src/lib/gestures/hover.ts | 17 +---- src/lib/gestures/move.ts | 29 +++----- src/lib/gestures/pinch.ts | 85 ++++++++-------------- src/lib/gestures/pointer-capture.ts | 29 +++++++- src/lib/gestures/press.ts | 23 +++--- src/lib/gestures/reorder-internals.test.ts | 23 ------ src/lib/gestures/reorder-internals.ts | 37 ---------- src/lib/gestures/reorder.test.ts | 19 +++++ src/lib/gestures/reorder.ts | 62 ++++++++-------- src/lib/gestures/swipe.ts | 72 ++++++------------ src/lib/gestures/velocity.ts | 55 ++++++++++++++ src/lib/gestures/wheel.ts | 19 ++--- 15 files changed, 255 insertions(+), 325 deletions(-) create mode 100644 .changeset/lazy-otters-shave.md delete mode 100644 src/lib/gestures/reorder-internals.test.ts delete mode 100644 src/lib/gestures/reorder-internals.ts create mode 100644 src/lib/gestures/reorder.test.ts create mode 100644 src/lib/gestures/velocity.ts diff --git a/.changeset/lazy-otters-shave.md b/.changeset/lazy-otters-shave.md new file mode 100644 index 0000000..8b62691 --- /dev/null +++ b/.changeset/lazy-otters-shave.md @@ -0,0 +1,19 @@ +--- +'@ixirjs/pulse': minor +--- + +Remove the `disabled` option from every gesture attachment. + +It duplicated what Svelte already gives you, and did it worse: `disabled: true` +only short-circuited the setup, so toggling it did nothing to an attachment that +was already live. Conditional attachment is the working form and actually tears +the listeners down: + +```svelte + +
    + + +
    +``` + diff --git a/src/lib/gestures/draggable.ts b/src/lib/gestures/draggable.ts index fc0f968..a6d1155 100644 --- a/src/lib/gestures/draggable.ts +++ b/src/lib/gestures/draggable.ts @@ -12,15 +12,13 @@ import type { Attachment } from 'svelte/attachments'; import { isBrowser } from '../shared/browser'; -import { restoreStyleProp, saveStyleProp } from '../shared/inline-style'; +import { listen } from '../shared/listen'; +import { trackVelocity } from './velocity'; import type { MotionElement } from '../animate'; import type { SpringOptions } from '../shared/types'; import { createSpringValue } from '../animate/spring-value'; -import { capture, release } from './pointer-capture'; -import { - ensurePropertiesRegistered, - ensureTransformWired -} from '../animate/properties/transform-setup'; +import { capture, lockTouchAction, release } from './pointer-capture'; +import { wireTransform } from '../animate/properties/transform-setup'; import { applyConstraint, xBounds, yBounds, type DragConstraints } from './constraints'; export type DragAxis = 'x' | 'y' | 'both'; @@ -47,16 +45,11 @@ export interface DraggableOptions { snapToOrigin?: boolean; /** Carry release velocity into the settle spring. Default true. */ momentum?: boolean; - /** Disable dragging without removing the attachment. */ - disabled?: boolean; onStart?: (info: DragInfo, element: MotionElement) => void; onMove?: (info: DragInfo, element: MotionElement) => void; onEnd?: (info: DragInfo, element: MotionElement) => void; } -const touchActionFor = (axis: DragAxis): string => - axis === 'x' ? 'pan-y' : axis === 'y' ? 'pan-x' : 'none'; - /** Create a draggable attachment. */ export const draggable = (options: DraggableOptions = {}): Attachment => { const { @@ -66,19 +59,16 @@ export const draggable = (options: DraggableOptions = {}): Attachment { - if (!isBrowser() || disabled) return; + if (!isBrowser()) return; - ensurePropertiesRegistered(); - ensureTransformWired(element); - const savedTouchAction = saveStyleProp(element.style, 'touch-action'); - element.style.setProperty('touch-action', touchActionFor(axis)); + wireTransform(element); + const unlockTouchAction = lockTouchAction(element, axis); const lockX = axis === 'y'; const lockY = axis === 'x'; @@ -98,12 +88,7 @@ export const draggable = (options: DraggableOptions = {}): Attachment typeof constraints === 'function' ? constraints() : (constraints ?? {}); @@ -111,8 +96,8 @@ export const draggable = (options: DraggableOptions = {}): Attachment ({ x, y, - velocityX: velX, - velocityY: velY + velocityX: velocity.x, + velocityY: velocity.y }); const onPointerDown = (event: PointerEvent): void => { @@ -125,24 +110,13 @@ export const draggable = (options: DraggableOptions = {}): Attachment { if (!dragging || event.pointerId !== pointerId) return; - const dt = (event.timeStamp - lastT) / 1000; - if (dt > 0) { - velX = (event.clientX - lastX) / dt; - velY = (event.clientY - lastY) / dt; - } - lastX = event.clientX; - lastY = event.clientY; - lastT = event.timeStamp; + velocity.sample(event); const c = bounds(); if (!lockX) { @@ -159,8 +133,8 @@ export const draggable = (options: DraggableOptions = {}): Attachment { - element.removeEventListener('pointerdown', down); - element.removeEventListener('pointermove', move); - element.removeEventListener('pointerup', up); - element.removeEventListener('pointercancel', up); + unlisten(); unsubX(); unsubY(); springX.stop(); springY.stop(); - restoreStyleProp(element.style, 'touch-action', savedTouchAction); + unlockTouchAction(); }; }; }; diff --git a/src/lib/gestures/focus.ts b/src/lib/gestures/focus.ts index 84b6b87..a0bedf0 100644 --- a/src/lib/gestures/focus.ts +++ b/src/lib/gestures/focus.ts @@ -20,21 +20,20 @@ import type { Attachment } from 'svelte/attachments'; import { isBrowser } from '../shared/browser'; +import { listen } from '../shared/listen'; import type { MotionElement } from '../animate'; export interface FocusableOptions { onFocusStart?: (element: MotionElement, event: FocusEvent) => void; onFocusEnd?: (element: MotionElement, event: FocusEvent) => void; - /** Disable without removing the attachment. */ - disabled?: boolean; } /** Create a focus attachment. */ export const focusable = (options: FocusableOptions = {}): Attachment => { - const { onFocusStart, onFocusEnd, disabled = false } = options; + const { onFocusStart, onFocusEnd } = options; return (element) => { - if (!isBrowser() || disabled) return; + if (!isBrowser()) return; let focused = false; @@ -53,14 +52,6 @@ export const focusable = (options: FocusableOptions = {}): Attachment { - element.removeEventListener('focusin', focusIn); - element.removeEventListener('focusout', focusOut); - }; + return listen(element, { focusin: onFocusIn, focusout: onFocusOut }); }; }; diff --git a/src/lib/gestures/hover.ts b/src/lib/gestures/hover.ts index 1118434..761a25a 100644 --- a/src/lib/gestures/hover.ts +++ b/src/lib/gestures/hover.ts @@ -16,6 +16,7 @@ import type { Attachment } from 'svelte/attachments'; import { isBrowser } from '../shared/browser'; +import { listen } from '../shared/listen'; import type { MotionElement } from '../animate'; export interface HoverableOptions { @@ -23,16 +24,14 @@ export interface HoverableOptions { onHoverEnd?: (element: MotionElement, event: PointerEvent) => void; /** Also react to touch pointers. Default false (mouse/pen only). */ includeTouch?: boolean; - /** Disable without removing the attachment. */ - disabled?: boolean; } /** Create a hover attachment. */ export const hoverable = (options: HoverableOptions = {}): Attachment => { - const { onHoverStart, onHoverEnd, includeTouch = false, disabled = false } = options; + const { onHoverStart, onHoverEnd, includeTouch = false } = options; return (element) => { - if (!isBrowser() || disabled) return; + if (!isBrowser()) return; const ignore = (event: PointerEvent): boolean => !includeTouch && event.pointerType === 'touch'; @@ -43,14 +42,6 @@ export const hoverable = (options: HoverableOptions = {}): Attachment { - element.removeEventListener('pointerenter', enter); - element.removeEventListener('pointerleave', leave); - }; + return listen(element, { pointerenter: onEnter, pointerleave: onLeave }); }; }; diff --git a/src/lib/gestures/move.ts b/src/lib/gestures/move.ts index fd3736e..9aee447 100644 --- a/src/lib/gestures/move.ts +++ b/src/lib/gestures/move.ts @@ -19,13 +19,11 @@ import type { Attachment } from 'svelte/attachments'; import { isBrowser } from '../shared/browser'; +import { listen } from '../shared/listen'; import type { MotionElement } from '../animate'; import type { SpringOptions } from '../shared/types'; import { createSpringValue } from '../animate/spring-value'; -import { - ensurePropertiesRegistered, - ensureTransformWired -} from '../animate/properties/transform-setup'; +import { wireTransform } from '../animate/properties/transform-setup'; export interface MoveInfo { /** Pointer position in client coordinates. */ @@ -52,8 +50,6 @@ export interface MoveableOptions { spring?: SpringOptions; /** Also react to touch pointers. Default `false` (mouse/pen only). */ includeTouch?: boolean; - /** Disable without removing the attachment. */ - disabled?: boolean; onMoveStart?: (info: MoveInfo, element: MotionElement) => void; onMove?: (info: MoveInfo, element: MotionElement) => void; onMoveEnd?: (element: MotionElement) => void; @@ -66,14 +62,13 @@ export const moveable = (options: MoveableOptions = {}): Attachment { - if (!isBrowser() || disabled) return; + if (!isBrowser()) return; // Only spring the axes we actually write, mirroring draggable. const springX = applyTransform ? createSpringValue({ ...spring, initial: 0 }) : null; @@ -81,8 +76,7 @@ export const moveable = (options: MoveableOptions = {}): Attachment {}; let unsubY = (): void => {}; if (applyTransform) { - ensurePropertiesRegistered(); - ensureTransformWired(element); + wireTransform(element); unsubX = springX!.subscribe((v) => element.style.setProperty('--motion-x', `${v}px`)); unsubY = springY!.subscribe((v) => element.style.setProperty('--motion-y', `${v}px`)); } @@ -128,17 +122,14 @@ export const moveable = (options: MoveableOptions = {}): Attachment { - element.removeEventListener('pointerenter', enter); - element.removeEventListener('pointermove', move); - element.removeEventListener('pointerleave', leave); + unlisten(); unsubX(); unsubY(); springX?.stop(); diff --git a/src/lib/gestures/pinch.ts b/src/lib/gestures/pinch.ts index f0a8b35..6a2ceb5 100644 --- a/src/lib/gestures/pinch.ts +++ b/src/lib/gestures/pinch.ts @@ -12,14 +12,11 @@ import type { Attachment } from 'svelte/attachments'; import { isBrowser } from '../shared/browser'; +import { listen } from '../shared/listen'; import { applyConstraint, type AxisBounds } from './constraints'; -import { restoreStyleProp, saveStyleProp } from '../shared/inline-style'; import type { MotionElement } from '../animate'; -import { capture, release } from './pointer-capture'; -import { - ensurePropertiesRegistered, - ensureTransformWired -} from '../animate/properties/transform-setup'; +import { capture, lockTouchAction, release } from './pointer-capture'; +import { wireTransform } from '../animate/properties/transform-setup'; export interface PinchInfo { /** Distance ratio of the two pointers relative to gesture start. */ @@ -37,8 +34,6 @@ export interface PinchableOptions { scaleBounds?: AxisBounds; /** Write `--motion-scale` / `--motion-rotate` on move. Default `true`. */ applyTransform?: boolean; - /** Disable pinching without removing the attachment. */ - disabled?: boolean; onStart?: (info: PinchInfo, element: MotionElement) => void; onMove?: (info: PinchInfo, element: MotionElement) => void; onEnd?: (info: PinchInfo, element: MotionElement) => void; @@ -54,25 +49,15 @@ const angle = (ax: number, ay: number, bx: number, by: number): number => /** Create a pinchable attachment. */ export const pinchable = (options: PinchableOptions = {}): Attachment => { - const { - rotate = true, - scaleBounds, - applyTransform = true, - disabled = false, - onStart, - onMove, - onEnd - } = options; + const { rotate = true, scaleBounds, applyTransform = true, onStart, onMove, onEnd } = options; return (element) => { - if (!isBrowser() || disabled) return; + if (!isBrowser()) return; if (applyTransform) { - ensurePropertiesRegistered(); - ensureTransformWired(element); + wireTransform(element); } - const savedTouchAction = saveStyleProp(element.style, 'touch-action'); - element.style.setProperty('touch-action', 'none'); + const unlockTouchAction = lockTouchAction(element, 'both'); // Live pointer positions keyed by pointerId; at most two are tracked. const points = new Map(); @@ -89,6 +74,16 @@ export const pinchable = (options: PinchableOptions = {}): Attachment { + const [a, b] = [...points.values()]; + const scale = applyConstraint( + startDistance > 0 ? distance(a.x, a.y, b.x, b.y) / startDistance : 1, + scaleBounds ?? {} + ); + return info(scale, rotate ? angle(a.x, a.y, b.x, b.y) - startAngle : 0); + }; + const onPointerDown = (event: PointerEvent): void => { if (points.size >= 2) return; points.set(event.pointerId, { x: event.clientX, y: event.clientY }); @@ -110,55 +105,35 @@ export const pinchable = (options: PinchableOptions = {}): Attachment 0 ? currentDistance / startDistance : 1, - scaleBounds ?? {} - ); - const rotation = rotate ? angle(a.x, a.y, b.x, b.y) - startAngle : 0; - + const current = read(); if (applyTransform) { // Baseline scale of 1; multiplying keeps composition explicit. - element.style.setProperty('--motion-scale', `${1 * scale}`); - if (rotate) element.style.setProperty('--motion-rotate', `${rotation}deg`); + element.style.setProperty('--motion-scale', `${1 * current.scale}`); + if (rotate) element.style.setProperty('--motion-rotate', `${current.rotation}deg`); } - onMove?.(info(scale, rotation), element); + onMove?.(current, element); }; const onPointerUp = (event: PointerEvent): void => { if (!points.has(event.pointerId)) return; release(element, event.pointerId); - if (pinching) { - const [a, b] = [...points.values()]; - const currentDistance = distance(a.x, a.y, b.x, b.y); - const scale = applyConstraint( - startDistance > 0 ? currentDistance / startDistance : 1, - scaleBounds ?? {} - ); - const rotation = rotate ? angle(a.x, a.y, b.x, b.y) - startAngle : 0; - onEnd?.(info(scale, rotation), element); - } + if (pinching) onEnd?.(read(), element); // Lifting either pointer ends the gesture and resets. pinching = false; points.delete(event.pointerId); }; - const down = onPointerDown as EventListener; - const move = onPointerMove as EventListener; - const up = onPointerUp as EventListener; - element.addEventListener('pointerdown', down); - element.addEventListener('pointermove', move); - element.addEventListener('pointerup', up); - element.addEventListener('pointercancel', up); + const unlisten = listen(element, { + pointerdown: onPointerDown, + pointermove: onPointerMove, + pointerup: onPointerUp, + pointercancel: onPointerUp + }); return () => { - element.removeEventListener('pointerdown', down); - element.removeEventListener('pointermove', move); - element.removeEventListener('pointerup', up); - element.removeEventListener('pointercancel', up); + unlisten(); points.clear(); - restoreStyleProp(element.style, 'touch-action', savedTouchAction); + unlockTouchAction(); }; }; }; diff --git a/src/lib/gestures/pointer-capture.ts b/src/lib/gestures/pointer-capture.ts index fd80bab..94bed1a 100644 --- a/src/lib/gestures/pointer-capture.ts +++ b/src/lib/gestures/pointer-capture.ts @@ -1,5 +1,6 @@ /** - * Pointer-capture helpers that never throw. + * Shared DOM plumbing for the pointer-gesture attachments: capture that never + * throws, and the `touch-action` lock every drag-like gesture needs. * * `setPointerCapture` / `releasePointerCapture` raise `NotFoundError` when the * pointer id is not active (common with synthetic events in tests, and with @@ -7,6 +8,28 @@ * teardown is always safe. */ +import { restoreStyleProp, saveStyleProp } from '../shared/inline-style'; +import type { MotionElement } from '../shared/types'; + +/** The axis a gesture owns; the browser keeps panning on the other one. */ +export type GestureAxis = 'x' | 'y' | 'both'; + +const TOUCH_ACTION: Record = { + x: 'pan-y', + y: 'pan-x', + both: 'none' +}; + +/** + * Hand the gesture's axis to us rather than the browser's native panning, and + * return the teardown that puts the element's own `touch-action` back. + */ +export const lockTouchAction = (element: MotionElement, axis: GestureAxis): (() => void) => { + const saved = saveStyleProp(element.style, 'touch-action'); + element.style.setProperty('touch-action', TOUCH_ACTION[axis]); + return () => restoreStyleProp(element.style, 'touch-action', saved); +}; + export const capture = (element: Element, pointerId: number): void => { try { element.setPointerCapture(pointerId); @@ -17,9 +40,7 @@ export const capture = (element: Element, pointerId: number): void => { export const release = (element: Element, pointerId: number): void => { try { - if (element.hasPointerCapture(pointerId)) { - element.releasePointerCapture(pointerId); - } + element.releasePointerCapture(pointerId); } catch { // Already released or never captured. } diff --git a/src/lib/gestures/press.ts b/src/lib/gestures/press.ts index 0648cb0..87ca29a 100644 --- a/src/lib/gestures/press.ts +++ b/src/lib/gestures/press.ts @@ -24,6 +24,7 @@ import type { Attachment } from 'svelte/attachments'; import { isBrowser } from '../shared/browser'; +import { listen } from '../shared/listen'; import type { MotionElement } from '../animate'; import { capture, release } from './pointer-capture'; @@ -42,8 +43,6 @@ export interface PressableOptions { longPressDelay?: number; /** Maximum gap between two presses to count as a double tap, ms. Default `300`. */ doubleTapDelay?: number; - /** Disable without removing the attachment. */ - disabled?: boolean; } /** Create a press attachment. */ @@ -55,12 +54,11 @@ export const pressable = (options: PressableOptions = {}): Attachment { - if (!isBrowser() || disabled) return; + if (!isBrowser()) return; let pressed = false; let pointerId = -1; @@ -121,18 +119,15 @@ export const pressable = (options: PressableOptions = {}): Attachment { clearLongPress(); - element.removeEventListener('pointerdown', down); - element.removeEventListener('pointerup', up); - element.removeEventListener('pointercancel', cancel); + unlisten(); }; }; }; diff --git a/src/lib/gestures/reorder-internals.test.ts b/src/lib/gestures/reorder-internals.test.ts deleted file mode 100644 index ec20af5..0000000 --- a/src/lib/gestures/reorder-internals.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { centersAreAscending, nearestCenterIndex } from './reorder-internals'; - -describe('nearestCenterIndex()', () => { - it('finds the same nearest slot at either boundary and between centers', () => { - const centers = [10, 40, 90, 160]; - expect(nearestCenterIndex(centers, -10)).toBe(0); - expect(nearestCenterIndex(centers, 67)).toBe(2); - expect(nearestCenterIndex(centers, 999)).toBe(3); - }); - - it('uses an O(log n) lookup for ascending list centers', () => { - const centers = Array.from({ length: 1024 }, (_, index) => index * 10); - expect(centersAreAscending(centers)).toBe(true); - expect(nearestCenterIndex(centers, 5_555)).toBe(555); - }); - - it('retains linear nearest-slot semantics for non-linear arrangements', () => { - const centers = [10, 90, 40]; - expect(centersAreAscending(centers)).toBe(false); - expect(nearestCenterIndex(centers, 35, false)).toBe(2); - }); -}); diff --git a/src/lib/gestures/reorder-internals.ts b/src/lib/gestures/reorder-internals.ts deleted file mode 100644 index 20cd973..0000000 --- a/src/lib/gestures/reorder-internals.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** Whether centers describe a normal ascending single-axis list. */ -export const centersAreAscending = (centers: readonly number[]): boolean => { - for (let i = 1; i < centers.length; i++) { - if (centers[i]! < centers[i - 1]!) return false; - } - return true; -}; - -/** Find the nearest slot center, using binary search for ordinary linear lists. */ -export const nearestCenterIndex = ( - centers: readonly number[], - target: number, - ascending = true -): number => { - if (centers.length === 0) return -1; - if (!ascending) return nearestUnsortedCenterIndex(centers, target); - - let low = 0; - let high = centers.length; - while (low < high) { - const middle = (low + high) >>> 1; - if (centers[middle]! < target) low = middle + 1; - else high = middle; - } - if (low === 0) return 0; - if (low === centers.length) return centers.length - 1; - return target - centers[low - 1]! <= centers[low]! - target ? low - 1 : low; -}; - -/** Preserve nearest-slot semantics for non-linear visual arrangements. */ -const nearestUnsortedCenterIndex = (centers: readonly number[], target: number): number => { - let nearest = 0; - for (let i = 1; i < centers.length; i++) { - if (Math.abs(centers[i]! - target) < Math.abs(centers[nearest]! - target)) nearest = i; - } - return nearest; -}; diff --git a/src/lib/gestures/reorder.test.ts b/src/lib/gestures/reorder.test.ts new file mode 100644 index 0000000..9d871a5 --- /dev/null +++ b/src/lib/gestures/reorder.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from 'vitest'; +import { nearestCenterIndex } from './reorder'; + +describe('nearestCenterIndex()', () => { + it('finds the same nearest slot at either boundary and between centers', () => { + const centers = [10, 40, 90, 160]; + expect(nearestCenterIndex(centers, -10)).toBe(0); + expect(nearestCenterIndex(centers, 67)).toBe(2); + expect(nearestCenterIndex(centers, 999)).toBe(3); + }); + + it('retains nearest-slot semantics for non-linear arrangements', () => { + expect(nearestCenterIndex([10, 90, 40], 35)).toBe(2); + }); + + it('reports no slot for an empty list', () => { + expect(nearestCenterIndex([], 0)).toBe(-1); + }); +}); diff --git a/src/lib/gestures/reorder.ts b/src/lib/gestures/reorder.ts index c587400..3db5b66 100644 --- a/src/lib/gestures/reorder.ts +++ b/src/lib/gestures/reorder.ts @@ -23,15 +23,22 @@ import type { Attachment } from 'svelte/attachments'; import { isBrowser } from '../shared/browser'; +import { listen } from '../shared/listen'; import { snapshotRect, flipFrom } from '../flip'; import type { EasingFn } from '../shared/types'; -import { - ensurePropertiesRegistered, - ensureTransformWired -} from '../animate/properties/transform-setup'; +import { wireTransform } from '../animate/properties/transform-setup'; import { restoreStyleProp, saveStyleProp, type SavedStyleProp } from '../shared/inline-style'; -import { capture, release } from './pointer-capture'; -import { centersAreAscending, nearestCenterIndex } from './reorder-internals'; +import { capture, lockTouchAction, release } from './pointer-capture'; + +/** Find the nearest slot center to `target`. Linear — reorder lists are short. */ +export const nearestCenterIndex = (centers: readonly number[], target: number): number => { + if (centers.length === 0) return -1; + let nearest = 0; + for (let i = 1; i < centers.length; i++) { + if (Math.abs(centers[i]! - target) < Math.abs(centers[nearest]! - target)) nearest = i; + } + return nearest; +}; export interface ReorderOptions { /** Reactive thunk returning the current ordered list. */ @@ -45,8 +52,6 @@ export interface ReorderOptions { getKey?: (item: T) => unknown; /** Drag axis. Default `'y'`. */ axis?: 'x' | 'y'; - /** Disable dragging without detaching. */ - disabled?: boolean; /** Settle animation length in ms (the FLIP into the new slot). Default 220. */ duration?: number; /** Settle easing. */ @@ -93,10 +98,11 @@ interface DragState { from: number; over: number; centers: number[]; - centersAscending: boolean; start: number; els: HTMLElement[]; styles: Map; + /** Detaches the move/up/cancel listeners this drag installed. */ + unlisten: () => void; } /** Create a reorder controller for one list. */ @@ -141,11 +147,11 @@ export const reorder = (options: ReorderOptions): ReorderHandle => { const onMove = (e: PointerEvent): void => { if (!drag || e.pointerId !== drag.pointerId) return; - const { centers, centersAscending, from } = drag; + const { centers, from } = drag; const delta = coordOf(e) - drag.start; setReorderOffset(drag.el, horizontal, delta); const targetCenter = centers[from]! + delta; - const over = nearestCenterIndex(centers, targetCenter, centersAscending); + const over = nearestCenterIndex(centers, targetCenter); if (over !== drag.over) { drag.over = over; layoutSiblings(); @@ -156,9 +162,7 @@ export const reorder = (options: ReorderOptions): ReorderHandle => { if (!drag || e.pointerId !== drag.pointerId) return; const state = drag; const { el, els, from, over, pointerId } = state; - el.removeEventListener('pointermove', onMove as EventListener); - el.removeEventListener('pointerup', endDrag as EventListener); - el.removeEventListener('pointercancel', endDrag as EventListener); + state.unlisten(); release(el, pointerId); drag = null; @@ -182,9 +186,7 @@ export const reorder = (options: ReorderOptions): ReorderHandle => { if (!drag) return; const state = drag; const { el, pointerId } = state; - el.removeEventListener('pointermove', onMove as EventListener); - el.removeEventListener('pointerup', endDrag as EventListener); - el.removeEventListener('pointercancel', endDrag as EventListener); + state.unlisten(); release(el, pointerId); drag = null; restoreDrag(state); @@ -193,7 +195,7 @@ export const reorder = (options: ReorderOptions): ReorderHandle => { const onDown = (el: HTMLElement) => (e: PointerEvent): void => { - if (options.disabled || e.button !== 0 || drag) return; + if (e.button !== 0 || drag) return; const order = options.items(); const keys = order.map(keyOf); // A value is a safe default key only while it is unique. Refuse an @@ -215,10 +217,14 @@ export const reorder = (options: ReorderOptions): ReorderHandle => { from, over: from, centers, - centersAscending: centersAreAscending(centers), start: coordOf(e), els: rows, - styles + styles, + unlisten: listen(el, { + pointermove: onMove, + pointerup: endDrag, + pointercancel: endDrag + }) }; // Reorder owns only its dedicated motion channel and temporary drag @@ -230,29 +236,23 @@ export const reorder = (options: ReorderOptions): ReorderHandle => { } capture(el, e.pointerId); - el.addEventListener('pointermove', onMove as EventListener); - el.addEventListener('pointerup', endDrag as EventListener); - el.addEventListener('pointercancel', endDrag as EventListener); }; const item = (value: T): Attachment => (el) => { if (!isBrowser()) return; - ensurePropertiesRegistered(); - ensureTransformWired(el); + wireTransform(el); const key = keyOf(value); elements.set(key, el); - const savedTouchAction = saveStyleProp(el.style, 'touch-action'); - el.style.setProperty('touch-action', horizontal ? 'pan-y' : 'pan-x'); - const down = onDown(el); - el.addEventListener('pointerdown', down as EventListener); + const unlockTouchAction = lockTouchAction(el, horizontal ? 'x' : 'y'); + const unlisten = listen(el, { pointerdown: onDown(el) }); return () => { if (drag?.els.includes(el)) cancelDrag(); cancelPendingSettle(); - el.removeEventListener('pointerdown', down as EventListener); + unlisten(); if (elements.get(key) === el) elements.delete(key); - restoreStyleProp(el.style, 'touch-action', savedTouchAction); + unlockTouchAction(); }; }; diff --git a/src/lib/gestures/swipe.ts b/src/lib/gestures/swipe.ts index 28e1728..f2a091e 100644 --- a/src/lib/gestures/swipe.ts +++ b/src/lib/gestures/swipe.ts @@ -14,9 +14,10 @@ import type { Attachment } from 'svelte/attachments'; import { isBrowser } from '../shared/browser'; -import { restoreStyleProp, saveStyleProp } from '../shared/inline-style'; +import { listen } from '../shared/listen'; +import { trackVelocity } from './velocity'; import type { MotionElement } from '../animate'; -import { capture, release } from './pointer-capture'; +import { capture, lockTouchAction, release } from './pointer-capture'; export type SwipeAxis = 'x' | 'y' | 'both'; export type SwipeDirection = 'left' | 'right' | 'up' | 'down'; @@ -38,63 +39,37 @@ export interface SwipeableOptions { threshold?: number; /** Release speed that counts as a swipe regardless of distance, px/s. Default `300`. */ velocityThreshold?: number; - /** Disable without removing the attachment. */ - disabled?: boolean; onSwipe?: (direction: SwipeDirection, info: SwipeInfo, element: MotionElement) => void; } -const touchActionFor = (axis: SwipeAxis): string => - axis === 'x' ? 'pan-y' : axis === 'y' ? 'pan-x' : 'none'; - /** Create a swipeable attachment. */ export const swipeable = (options: SwipeableOptions = {}): Attachment => { - const { - axis = 'both', - threshold = 30, - velocityThreshold = 300, - disabled = false, - onSwipe - } = options; + const { axis = 'both', threshold = 30, velocityThreshold = 300, onSwipe } = options; return (element) => { - if (!isBrowser() || disabled) return; + if (!isBrowser()) return; - const savedTouchAction = saveStyleProp(element.style, 'touch-action'); - element.style.setProperty('touch-action', touchActionFor(axis)); + const unlockTouchAction = lockTouchAction(element, axis); let tracking = false; let pointerId = -1; let startX = 0; let startY = 0; - // Velocity from the last two pointer samples. - let lastX = 0; - let lastY = 0; - let lastT = 0; - let velX = 0; - let velY = 0; + const velocity = trackVelocity(); const onPointerDown = (event: PointerEvent): void => { if (tracking || event.button !== 0) return; tracking = true; pointerId = event.pointerId; capture(element, pointerId); - startX = lastX = event.clientX; - startY = lastY = event.clientY; - lastT = event.timeStamp; - velX = 0; - velY = 0; + startX = event.clientX; + startY = event.clientY; + velocity.reset(event); }; const onPointerMove = (event: PointerEvent): void => { if (!tracking || event.pointerId !== pointerId) return; - const dt = (event.timeStamp - lastT) / 1000; - if (dt > 0) { - velX = (event.clientX - lastX) / dt; - velY = (event.clientY - lastY) / dt; - } - lastX = event.clientX; - lastY = event.clientY; - lastT = event.timeStamp; + velocity.sample(event); }; const onPointerUp = (event: PointerEvent): void => { @@ -109,7 +84,7 @@ export const swipeable = (options: SwipeableOptions = {}): Attachment= Math.abs(dy); const distance = horizontal ? Math.abs(dx) : Math.abs(dy); - const speed = horizontal ? Math.abs(velX) : Math.abs(velY); + const speed = horizontal ? Math.abs(velocity.x) : Math.abs(velocity.y); if (distance < threshold && speed < velocityThreshold) return; const direction: SwipeDirection = horizontal @@ -121,7 +96,7 @@ export const swipeable = (options: SwipeableOptions = {}): Attachment { - element.removeEventListener('pointerdown', down); - element.removeEventListener('pointermove', move); - element.removeEventListener('pointerup', up); - element.removeEventListener('pointercancel', cancel); - restoreStyleProp(element.style, 'touch-action', savedTouchAction); + unlisten(); + unlockTouchAction(); }; }; }; diff --git a/src/lib/gestures/velocity.ts b/src/lib/gestures/velocity.ts new file mode 100644 index 0000000..a7c1ba7 --- /dev/null +++ b/src/lib/gestures/velocity.ts @@ -0,0 +1,55 @@ +/** + * Two-sample pointer velocity tracking, shared by the gestures that hand a + * release velocity onward — `draggable` (into its settle spring) and `swipe` + * (into its velocity threshold). + * + * Two samples is deliberately the whole model: it reads the *current* flick + * rather than an average that lags behind a direction change mid-drag. + */ + +export interface VelocityTracker { + /** Horizontal velocity in px/second, from the last two samples. */ + readonly x: number; + /** Vertical velocity in px/second, from the last two samples. */ + readonly y: number; + /** Start a new gesture at this event: seed the sample point, zero velocity. */ + reset(event: PointerEvent): void; + /** Fold another pointer position into the velocity estimate. */ + sample(event: PointerEvent): void; +} + +/** Create a velocity tracker; `reset()` on pointerdown, `sample()` on pointermove. */ +export const trackVelocity = (): VelocityTracker => { + let lastX = 0; + let lastY = 0; + let lastT = 0; + let velX = 0; + let velY = 0; + + return { + get x() { + return velX; + }, + get y() { + return velY; + }, + reset(event) { + lastX = event.clientX; + lastY = event.clientY; + lastT = event.timeStamp; + velX = 0; + velY = 0; + }, + sample(event) { + // A zero (or backwards) dt would divide by zero; keep the last estimate. + const dt = (event.timeStamp - lastT) / 1000; + if (dt > 0) { + velX = (event.clientX - lastX) / dt; + velY = (event.clientY - lastY) / dt; + } + lastX = event.clientX; + lastY = event.clientY; + lastT = event.timeStamp; + } + }; +}; diff --git a/src/lib/gestures/wheel.ts b/src/lib/gestures/wheel.ts index b4df2c1..0a55df9 100644 --- a/src/lib/gestures/wheel.ts +++ b/src/lib/gestures/wheel.ts @@ -19,14 +19,12 @@ import type { Attachment } from 'svelte/attachments'; import { isBrowser } from '../shared/browser'; +import { listen } from '../shared/listen'; import { applyConstraint, type AxisBounds } from './constraints'; import type { MotionElement } from '../animate'; import { createSpringValue } from '../animate/spring-value'; import type { SpringOptions } from '../shared/types'; -import { - ensurePropertiesRegistered, - ensureTransformWired -} from '../animate/properties/transform-setup'; +import { wireTransform } from '../animate/properties/transform-setup'; export interface WheelInfo { /** Accumulated scale since the element mounted (baseline 1). */ @@ -60,8 +58,6 @@ export interface WheelableOptions { preventDefault?: boolean; /** Idle time before the gesture is considered ended, ms. Default `120`. */ endDelay?: number; - /** Disable without removing the attachment. */ - disabled?: boolean; onStart?: (info: WheelInfo, element: MotionElement) => void; onMove?: (info: WheelInfo, element: MotionElement) => void; onEnd?: (info: WheelInfo, element: MotionElement) => void; @@ -79,7 +75,6 @@ export const wheelable = (options: WheelableOptions = {}): Attachment { - if (!isBrowser() || disabled) return; + if (!isBrowser()) return; // `scale` is the logical target (what callbacks report); the spring // carries the rendered value smoothly toward it across frames. @@ -110,8 +105,7 @@ export const wheelable = (options: WheelableOptions = {}): Attachment void) | null = null; if (applyTransform) { - ensurePropertiesRegistered(); - ensureTransformWired(element); + wireTransform(element); detachSpring = springScale?.subscribe((v) => element.style.setProperty('--motion-scale', `${v}`)) ?? null; } @@ -150,13 +144,12 @@ export const wheelable = (options: WheelableOptions = {}): Attachment { if (endTimer != null) clearTimeout(endTimer); - element.removeEventListener('wheel', wheel); + unlisten(); detachSpring?.(); springScale?.stop(); }; From 5b14abb278d31f40318f1109292dd7598a0338f5 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Sat, 15 Aug 2026 13:51:10 -0400 Subject: [PATCH 28/30] feat(flip)!: reactive class/style thunks, always-on layout tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `auto` asked the caller to do the library's job. `auto: () => { void open }` read the state, discarded it, and left flip to re-measure a frame later — and the `ObserverManager` variant made an internal a public type just so it could be passed back in. Instead the attachment owns the attribute:
    ({ 'is-open': open }) })}> The thunk is tracked, so flip writes the class (or inline style) itself and measures `from` → write → `to` → animate in one tick. Writes are diffed against what flip previously applied — never a wholesale `className` / `cssText` assignment — so markup classes and the animator's own `--motion-*` writes survive. Style strings go through the platform's parser (a detached element), which handles `!important`, comments, and malformed input for free. Layout tracking (`ResizeObserver` + parent `MutationObserver`) is now unconditional, so a shuffled `{#each}` animates with no options at all. Also in this pass: - Interrupted runs converge. A burst of retargets (drag, rapid shuffles) used to restart the full duration on every trigger and never settle; the slot now charges elapsed time against the replacement, floored at 120ms. - `carryVisualOffset()` re-expresses a live visual rect in the previous layout frame. An in-flight transform is an offset from the resting box, so once layout changes the raw visual rect belongs to the *new* box — using it directly made an interrupting FLIP shoot out of place. - The skip counter only counts cycles that would actually animate, so `skip: (n) => n === 0` lands on the first real move rather than the no-op callback observers fire on connect. - `flip/animation/`, `flip/integration/`, and `flip/tracking/` flatten into `flip/`. Three directories held one to four files each and every import paid for the nesting. - `DEFAULT_DURATION` → `FLIP_DEFAULT_DURATION`, unambiguous next to the animate-side default; the layout bridge drops its `performance.now` fallback. **Breaking:** `auto`, the `FlipAuto` type, and `createObserverManager` / `ObserverManager` are removed from the public API. Delete `auto:` from existing call sites — tracking is on by default. Co-Authored-By: Claude Opus 5 (1M context) --- .changeset/lucky-scopes-shrink.md | 2 - .changeset/plenty-moons-tap.md | 2 +- .changeset/tidy-pans-shave.md | 2 +- .changeset/wild-moons-attend.md | 17 +++ README.md | 59 ++++++---- src/lib/flip/anchored.ts | 4 +- .../{animation => }/animator.svelte.test.ts | 2 +- src/lib/flip/{animation => }/animator.test.ts | 2 +- src/lib/flip/{animation => }/animator.ts | 16 +-- src/lib/flip/attachment.svelte.test.ts | 108 +++++++++++++++++ .../{integration => }/attachment.svelte.ts | 102 ++++++++-------- src/lib/flip/{integration => }/bridge.test.ts | 2 +- src/lib/flip/{integration => }/bridge.ts | 8 +- src/lib/flip/burst.svelte.test.ts | 80 +++++++++++++ .../{animation => }/controller-slot.test.ts | 32 ++++- .../flip/{animation => }/controller-slot.ts | 31 ++++- src/lib/flip/dynamic.svelte.test.ts | 74 ++++++++++++ src/lib/flip/dynamic.ts | 111 ++++++++++++++++++ src/lib/flip/geometry.ts | 23 +++- src/lib/flip/index.ts | 25 ++-- src/lib/flip/{tracking => }/observers.test.ts | 0 src/lib/flip/{tracking => }/observers.ts | 0 src/lib/flip/options.test.ts | 10 +- src/lib/flip/options.ts | 4 +- .../flip/{integration => }/switcher.svelte.ts | 8 +- src/lib/flip/types.ts | 25 ++-- 26 files changed, 617 insertions(+), 132 deletions(-) create mode 100644 .changeset/wild-moons-attend.md rename src/lib/flip/{animation => }/animator.svelte.test.ts (95%) rename src/lib/flip/{animation => }/animator.test.ts (96%) rename src/lib/flip/{animation => }/animator.ts (91%) create mode 100644 src/lib/flip/attachment.svelte.test.ts rename src/lib/flip/{integration => }/attachment.svelte.ts (54%) rename src/lib/flip/{integration => }/bridge.test.ts (97%) rename src/lib/flip/{integration => }/bridge.ts (80%) create mode 100644 src/lib/flip/burst.svelte.test.ts rename src/lib/flip/{animation => }/controller-slot.test.ts (78%) rename src/lib/flip/{animation => }/controller-slot.ts (61%) create mode 100644 src/lib/flip/dynamic.svelte.test.ts create mode 100644 src/lib/flip/dynamic.ts rename src/lib/flip/{tracking => }/observers.test.ts (100%) rename src/lib/flip/{tracking => }/observers.ts (100%) rename src/lib/flip/{integration => }/switcher.svelte.ts (93%) diff --git a/.changeset/lucky-scopes-shrink.md b/.changeset/lucky-scopes-shrink.md index e50e328..90e5410 100644 --- a/.changeset/lucky-scopes-shrink.md +++ b/.changeset/lucky-scopes-shrink.md @@ -3,5 +3,3 @@ --- **Breaking:** `createFlipScope()` no longer takes options and no longer returns `clear()`. The `layoutTtlMs` option (and its `CreateFlipScopeOptions` type) is gone — layout records expire after a fixed 250ms, which is already far longer than any unmount/mount handoff, so neither knob had a use. Replace `const { flip, clear } = createFlipScope(opts)` with `const { flip } = createFlipScope()`. - -`createObserverManager` moved from `flip/tracking/observer-manager` to `flip/tracking/observers`; the public export from `@ixirjs/pulse/flip` is unchanged. diff --git a/.changeset/plenty-moons-tap.md b/.changeset/plenty-moons-tap.md index b6da0a4..9e9e23f 100644 --- a/.changeset/plenty-moons-tap.md +++ b/.changeset/plenty-moons-tap.md @@ -5,7 +5,7 @@ **Breaking:** trimmed duplicated and internal API off the public surface. - `flipFromRect`, `flipToRect`, `captureRect`, and the `AnimateFlipRect` type are gone from `@ixirjs/pulse/animate`. They duplicated `flipFrom` / `snapshotRect` in `@ixirjs/pulse/flip`, which carry the richer option set (opacity crossfade, `disablePointerEvents`, distance-derived duration, rect-carrying hooks). Migrate by importing those instead; pass `duration` / `easing` where you passed `AnimateDefaults`. -- `@ixirjs/pulse/flip` no longer exports the delta-math primitives `computeDelta`, `isIdentityDelta`, `diagonal`, `rectsEqual`, or the `FlipDelta` / `DeltaOptions` types. They are internals of the animator. `flip`, `flipFrom`, `snapshotRect`, `measure`, `animateFlip`, `createFlipScope`, `createFlipSwitcher`, `anchoredFlip`, and `createObserverManager` are unchanged. +- `@ixirjs/pulse/flip` no longer exports the delta-math primitives `computeDelta`, `isIdentityDelta`, `diagonal`, `rectsEqual`, or the `FlipDelta` / `DeltaOptions` types. They are internals of the animator. `flip`, `flipFrom`, `snapshotRect`, `measure`, `animateFlip`, `createFlipScope`, `createFlipSwitcher`, and `anchoredFlip` are unchanged. - `flipTo` stays, as the mirror of `flipFrom`: it animates an element from its current position **to** a captured rect (forward FLIP). `animateFlip({ …, forward: true })` remains the low-level form. - `@ixirjs/pulse/morph` no longer exports the path-alignment internals `planMorph`, `interpolatePlan`, `toPathString`, `subdivideTo`, `alignSubpaths`, `minimizeAnchorTravel`, `rotateClosed`, `reverseClosed`, or the `MorphPlan` type. `morph`, `parsePath`, and `normalizePath` are unchanged. diff --git a/.changeset/tidy-pans-shave.md b/.changeset/tidy-pans-shave.md index ce85b47..eb76deb 100644 --- a/.changeset/tidy-pans-shave.md +++ b/.changeset/tidy-pans-shave.md @@ -4,6 +4,6 @@ Trim the public surface and de-duplicate internals. -- `createFlipAttachment`, `createLayoutBridge`, `createReflowScheduler`, and their types are no longer exported from `@ixirjs/pulse/flip`; they are internals. `flip()`, `createFlipScope()`, and `createObserverManager()` remain the supported entry points. +- `createFlipAttachment`, `createLayoutBridge`, `createReflowScheduler`, and their types are no longer exported from `@ixirjs/pulse/flip`; they are internals. `flip()` and `createFlipScope()` remain the supported entry points. - Single RAF batcher (`shared/frame-batch`) now backs both scroll and FLIP reflow scheduling. - `frameTween` delay is always counted from the first browser frame; the `delayOrigin` option is gone. diff --git a/.changeset/wild-moons-attend.md b/.changeset/wild-moons-attend.md new file mode 100644 index 0000000..e39b254 --- /dev/null +++ b/.changeset/wild-moons-attend.md @@ -0,0 +1,17 @@ +--- +'@ixirjs/pulse': minor +--- + +Replace `flip()`'s `auto` option with reactive `class` / `style` thunks. + +`flip({ class: () => ClassValue })` and `flip({ style: () => string })` let the attachment own +the attribute: it writes the class or inline style itself, then measures and animates the +resulting layout change in the same tick — no discarded thunk and no frame of latency. + +Layout auto-tracking (`ResizeObserver` + parent `MutationObserver`) is now always on, so a +shuffled `{#each}` animates with no option at all. Consequently `auto`, the `FlipAuto` type, and +`createObserverManager` / `ObserverManager` are removed from the public API — delete the `auto:` +option from existing call sites. + +Note: use flip's `class` option or a dynamic `class={…}` in markup, not both on the same element +— Svelte assigns `className` wholesale and would drop flip's tokens. A static `class="…"` is safe. diff --git a/README.md b/README.md index 97f035b..969b6cf 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ The following shorthands animate independent transform components without clobbe ## `flip(options?)` — Svelte 5 attachment Zero-config FLIP layout animation. Attach to any element that may shift position or size. +Layout tracking is built in — resizes and `{#each}` reorders animate with no options at all. ```svelte - +
    ...
    ...
    - -
    { - void open; - } - })} -> - ... -
    + +
    ({ 'is-open': open }) })}>...
    + + +
    (open ? 'height: 320px' : 'height: 64px') })}>...
    n === 0 })}>...
    ``` +`class` and `style` are thunks so their rune dependencies are tracked. Because `flip` writes the +attribute itself, it measures the element before and after the write and animates the difference +in the same tick — no extra frame, and nothing to keep in sync by hand. + +> Use `flip`'s `class` option **or** a dynamic `class={…}` on the same element, not both: Svelte +> assigns `className` wholesale and would drop flip's tokens. A static `class="…"` is safe, and +> `style` never conflicts (it merges per declaration). Neither is applied during SSR — put +> server-rendered state in markup as well. + ### Flip options -| Option | Type | Default | -| ---------------------- | ------------------------------------------ | ---------- | -| `duration` | `number \| (distance, rects) => number` | `280` | -| `easing` | `EasingFn \| string` | `cubicOut` | -| `delay` | `number` | `0` | -| `translate` | `boolean` | `true` | -| `scale` | `boolean` | `true` | -| `opacity` | `boolean \| { from?, to? }` | — | -| `auto` | `false \| (() => void) \| ObserverManager` | — | -| `skip` | `boolean \| (render, rects) => boolean` | — | -| `disablePointerEvents` | `boolean` | — | -| `respectReducedMotion` | `boolean` | `true` | -| `layoutId` | `string` | — | -| `onStart` | `(el, rects) => void` | — | -| `onEnd` | `(el, { finished, rects }) => void` | — | +| Option | Type | Default | +| ---------------------- | --------------------------------------- | ---------- | +| `duration` | `number \| (distance, rects) => number` | `280` | +| `easing` | `EasingFn \| string` | `cubicOut` | +| `delay` | `number` | `0` | +| `translate` | `boolean` | `true` | +| `scale` | `boolean` | `true` | +| `opacity` | `boolean \| { from?, to? }` | — | +| `class` | `() => ClassValue` | — | +| `style` | `() => string` | — | +| `skip` | `boolean \| (render, rects) => boolean` | — | +| `disablePointerEvents` | `boolean` | — | +| `respectReducedMotion` | `boolean` | `true` | +| `layoutId` | `string` | — | +| `onStart` | `(el, rects) => void` | — | +| `onEnd` | `(el, { finished, rects }) => void` | — | ### Shared-element transitions (`createFlipScope`) diff --git a/src/lib/flip/anchored.ts b/src/lib/flip/anchored.ts index a2bf82b..e39770c 100644 --- a/src/lib/flip/anchored.ts +++ b/src/lib/flip/anchored.ts @@ -1,7 +1,7 @@ import type { AnimationController } from '../animate/types'; import { saveStyleProp, restoreStyleProp, type SavedStyleProp } from '../shared/inline-style'; import { isBrowser } from '../shared/browser'; -import { animateFlip } from './animation/animator'; +import { animateFlip } from './animator'; import { measure } from './geometry'; import { resolveOpacity } from './options'; import type { FlipOptions, FlipRect, MotionElement } from './types'; @@ -20,7 +20,7 @@ export interface AnchoredFlipReference { export type AnchoredFlipReferenceGetter = () => AnchoredFlipReference | null | undefined; /** Animation options shared by the anchored enter and exit transitions. */ -export type AnchoredFlipOptions = Omit; +export type AnchoredFlipOptions = Omit; /** Framework-neutral lifecycle function suitable for actions, attachments, and node hooks. */ export type AnchoredFlipNodeFunction = (element: MotionElement) => (() => void) | void; diff --git a/src/lib/flip/animation/animator.svelte.test.ts b/src/lib/flip/animator.svelte.test.ts similarity index 95% rename from src/lib/flip/animation/animator.svelte.test.ts rename to src/lib/flip/animator.svelte.test.ts index b992b92..91721b4 100644 --- a/src/lib/flip/animation/animator.svelte.test.ts +++ b/src/lib/flip/animator.svelte.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, it } from 'vitest'; import { animateFlip } from './animator'; -import { measure } from '../geometry'; +import { measure } from './geometry'; let element: HTMLDivElement | null = null; diff --git a/src/lib/flip/animation/animator.test.ts b/src/lib/flip/animator.test.ts similarity index 96% rename from src/lib/flip/animation/animator.test.ts rename to src/lib/flip/animator.test.ts index df32c42..4a3a91a 100644 --- a/src/lib/flip/animation/animator.test.ts +++ b/src/lib/flip/animator.test.ts @@ -6,7 +6,7 @@ import { describe, expect, it, vi } from 'vitest'; import { animateFlip } from './animator'; -import type { FlipRect } from '../types'; +import type { FlipRect } from './types'; const rect = (x = 0, y = 0, w = 100, h = 50): FlipRect => ({ x, diff --git a/src/lib/flip/animation/animator.ts b/src/lib/flip/animator.ts similarity index 91% rename from src/lib/flip/animation/animator.ts rename to src/lib/flip/animator.ts index 5d5e413..f244adc 100644 --- a/src/lib/flip/animation/animator.ts +++ b/src/lib/flip/animator.ts @@ -16,14 +16,14 @@ * the same controller so a single `cancel()` aborts the whole effect. */ -import { animate } from '../../animate/core/animate'; -import type { AnimationController, MotionElement } from '../../animate/types'; -import { buildFlipProps, isIdentityDelta, rectsEqual, resolveFlipDelta } from '../geometry'; -import type { FlipDelta } from '../geometry'; -import { isBrowser, shouldReduceMotion } from '../../shared/browser'; -import { restoreStyleProp, saveStyleProp } from '../../shared/inline-style'; -import { DEFAULT_DELAY, resolveDuration, resolveEasing, resolveOpacity } from '../options'; -import type { FlipAnimateArgs } from '../types'; +import { animate } from '../animate/core/animate'; +import type { AnimationController, MotionElement } from '../animate/types'; +import { buildFlipProps, isIdentityDelta, rectsEqual, resolveFlipDelta } from './geometry'; +import type { FlipDelta } from './geometry'; +import { isBrowser, shouldReduceMotion } from '../shared/browser'; +import { restoreStyleProp, saveStyleProp } from '../shared/inline-style'; +import { DEFAULT_DELAY, resolveDuration, resolveEasing, resolveOpacity } from './options'; +import type { FlipAnimateArgs } from './types'; /** * Parse a CSS `transform-origin` computed value (always in `px` in computed diff --git a/src/lib/flip/attachment.svelte.test.ts b/src/lib/flip/attachment.svelte.test.ts new file mode 100644 index 0000000..ef2596e --- /dev/null +++ b/src/lib/flip/attachment.svelte.test.ts @@ -0,0 +1,108 @@ +import { flushSync } from 'svelte'; +import { afterEach, describe, expect, it } from 'vitest'; +import { flip } from './index'; +import type { FlipOptions } from './types'; + +let mounted: Element[] = []; +let roots: Array<() => void> = []; + +const mountBox = (): HTMLDivElement => { + const element = document.createElement('div'); + Object.assign(element.style, { + position: 'fixed', + top: '0px', + left: '20px', + width: '40px', + height: '20px' + }); + document.body.appendChild(element); + mounted.push(element); + return element; +}; + +/** Attach `flip()` inside an effect root so its `$effect`s run under `flushSync`. */ +const attach = (element: HTMLElement, options: () => FlipOptions): void => { + // Returning the attachment's cleanup makes the root's dispose tear it down, + // the way Svelte's attachment machinery does. + const dispose = $effect.root(() => flip(options)(element)); + roots.push(dispose); + flushSync(); +}; + +const settleAnimations = async (element: Element): Promise => { + await Promise.all( + element.getAnimations().map((animation) => animation.finished.catch(() => undefined)) + ); + await Promise.resolve(); +}; + +afterEach(() => { + for (const dispose of roots) dispose(); + roots = []; + for (const element of mounted) element.remove(); + mounted = []; +}); + +describe('flip() reactive class/style', () => { + it('applies a style change and animates the resulting layout shift', async () => { + const element = mountBox(); + let open = $state(false); + attach(element, () => ({ + duration: 40, + style: () => (open ? 'left: 200px' : 'left: 20px') + })); + + expect(element.getAnimations()).toHaveLength(0); + + open = true; + flushSync(); + + expect(element.style.left).toBe('200px'); + expect(element.getAnimations().length).toBeGreaterThan(0); + + await settleAnimations(element); + expect(element.getBoundingClientRect().x).toBeCloseTo(200, 0); + expect(element.style.getPropertyValue('--motion-x')).toBe(''); + }); + + it('applies the initial class before the first measure, so mounting does not animate', () => { + const element = mountBox(); + attach(element, () => ({ duration: 40, class: () => ({ 'is-open': true }) })); + + expect(element.classList.contains('is-open')).toBe(true); + expect(element.getAnimations()).toHaveLength(0); + }); + + it('counts only cycles that move, so skip sees the first real change', async () => { + const element = mountBox(); + let open = $state(false); + const renders: number[] = []; + attach(element, () => ({ + duration: 40, + skip: (render) => { + renders.push(render); + return render === 0; + }, + style: () => (open ? 'left: 200px' : 'left: 20px') + })); + + open = true; + flushSync(); + + expect(renders).toEqual([0]); + expect(element.getAnimations()).toHaveLength(0); + await settleAnimations(element); + }); + + it('removes the classes it applied on teardown', () => { + const element = mountBox(); + element.classList.add('from-markup'); + attach(element, () => ({ class: () => 'is-open' })); + expect(element.classList.contains('is-open')).toBe(true); + + for (const dispose of roots) dispose(); + roots = []; + + expect([...element.classList]).toEqual(['from-markup']); + }); +}); diff --git a/src/lib/flip/integration/attachment.svelte.ts b/src/lib/flip/attachment.svelte.ts similarity index 54% rename from src/lib/flip/integration/attachment.svelte.ts rename to src/lib/flip/attachment.svelte.ts index c354e6e..4e45336 100644 --- a/src/lib/flip/integration/attachment.svelte.ts +++ b/src/lib/flip/attachment.svelte.ts @@ -9,14 +9,15 @@ import { untrack } from 'svelte'; import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '../../shared/browser'; -import { createFrameBatch } from '../../shared/frame-batch'; +import { isBrowser } from '../shared/browser'; +import { createFrameBatch } from '../shared/frame-batch'; import type { LayoutBridge } from './bridge'; -import { createControllerSlot } from '../animation/controller-slot'; -import { measure, measureVisual, rectsEqual } from '../geometry'; -import type { ObserverManager } from '../tracking/observers'; -import { readOptions } from '../options'; -import type { FlipAuto, FlipOptions, FlipOptionsInput, FlipRect, MotionElement } from '../types'; +import { createDynamicAttrs } from './dynamic'; +import { createControllerSlot } from './controller-slot'; +import { carryVisualOffset, measure, measureVisual, rectsEqual } from './geometry'; +import { createObserverManager } from './observers'; +import { readOptions } from './options'; +import type { FlipOptions, FlipOptionsInput, FlipRect, MotionElement } from './types'; /** * Core FLIP attachment factory. Shared between the standalone `flip()` @@ -30,7 +31,6 @@ export const createFlipAttachment = ( if (!isBrowser()) return; let options: FlipOptions = untrack(() => readOptions(input)); - let auto: FlipAuto | undefined = options.auto; let layoutId = options.layoutId; let prevRect: FlipRect | null = layoutId && bridge ? bridge.readLayout(layoutId) : null; let renderCount = 0; @@ -46,44 +46,53 @@ export const createFlipAttachment = ( const reflow = (): void => { if (!prevRect) return; const next = measure(element); + // Count only cycles that would actually animate — observers deliver a + // callback on connect, and `skip: (n) => n === 0` must land on the first + // real move rather than that no-op. + if (rectsEqual(prevRect, next)) { + prevRect = next; + return; + } const render = renderCount++; const { skip } = options; const shouldSkip = typeof skip === 'function' ? skip(render, { from: prevRect, to: next }) : (skip ?? false); - if (shouldSkip || rectsEqual(prevRect, next)) { + if (shouldSkip) { prevRect = next; return; } - // Interrupting an in-flight FLIP: start from the element's live on-screen - // rect (transform included) so the replacement run continues from where it - // visually is, instead of snapping back to its resting box first. When idle - // the element already sits at its new resting box, so the captured `from` - // must be the previous rect to produce any movement. - const from = slot.isActive() ? measureVisual(element) : prevRect; + // Interrupting an in-flight FLIP: continue from where the element was on + // screen *before* this layout change. The live transform is an offset from + // the element's old resting box, so the visual rect measured now (against + // the new box) has to be carried back onto `prevRect` — using it raw would + // add the offset to the new slot and fling the element out of place. + const from = slot.isActive() + ? carryVisualOffset(prevRect, next, measureVisual(element)) + : prevRect; prevRect = next; run(from, next); }; - const scheduler = createFrameBatch(reflow); - let connectedManager: ObserverManager | null = null; - - const syncObservers = (): void => { - connectedManager?.disconnect(); - connectedManager = null; - if (typeof auto === 'object') { - auto.connect(element, scheduler.schedule); - connectedManager = auto; + // The first scheduled pass after mount only re-baselines: layout is not + // settled when the attachment runs (siblings still mounting, fonts, images + // loading), so a diff on that pass is the page settling, not a move worth + // animating. + let primed = false; + const scheduler = createFrameBatch(() => { + if (!primed) { + primed = true; + prevRect = measure(element); + return; } - }; + reflow(); + }); + const observers = createObserverManager(); + const attrs = createDynamicAttrs(element); // ----------------------------------------------------------------- // Track option changes (when caller passes a thunk). // ----------------------------------------------------------------- - let autoEffectVersion = $state(0); - const applyOptions = (next: FlipOptions): void => { - const autoChanged = next.auto !== auto; - options = next; if (next.layoutId !== layoutId) { @@ -91,25 +100,18 @@ export const createFlipAttachment = ( const restored = layoutId && bridge ? bridge.readLayout(layoutId) : null; prevRect = restored ?? measure(element); } - - if (autoChanged) { - auto = next.auto; - // Use untrack so the read of autoEffectVersion is not registered as a - // dependency of the enclosing $effect. Without this, `+= 1` would both - // read *and* write the signal inside the same effect, causing Svelte to - // immediately re-schedule the effect and loop until depth is exceeded. - autoEffectVersion = untrack(() => autoEffectVersion) + 1; - syncObservers(); - } }; // ----------------------------------------------------------------- // Initial enter animation (when restored from a shared-layout entry). + // Attributes are applied *before* the first measure so mounting in the + // styled state does not animate out of the unstyled one. // ----------------------------------------------------------------- + untrack(() => attrs.write(options.class?.(), options.style?.())); const initialRect = measure(element); if (prevRect) run(prevRect, initialRect); prevRect = initialRect; - syncObservers(); + observers.connect(element, scheduler.schedule); if (typeof input === 'function') { $effect(() => { @@ -118,13 +120,18 @@ export const createFlipAttachment = ( }); } - // Re-run the user's auto thunk whenever its tracked dependencies change. + // Reactive class/style. Reads the options thunk directly rather than the + // closed-over `options` (a plain `let`, not a signal) so a changed + // class/style thunk identity is picked up without extra bookkeeping. $effect(() => { - void autoEffectVersion; - const trigger = options.auto; - if (typeof trigger !== 'function') return; - trigger(); - scheduler.schedule(); + const current = typeof input === 'function' ? readOptions(input) : options; + const classValue = current.class?.(); + const styleValue = current.style?.(); + // Write and measure untracked — reflow() reads geometry and reassigns + // state that must not become a dependency of this effect. + untrack(() => { + if (attrs.write(classValue, styleValue)) reflow(); + }); }); // ----------------------------------------------------------------- @@ -132,9 +139,10 @@ export const createFlipAttachment = ( // ----------------------------------------------------------------- return () => { scheduler.cancel(); - connectedManager?.disconnect(); + observers.disconnect(); if (layoutId && bridge && prevRect) bridge.writeLayout(layoutId, prevRect); slot.cancel(); + attrs.reset(); }; }; }; diff --git a/src/lib/flip/integration/bridge.test.ts b/src/lib/flip/bridge.test.ts similarity index 97% rename from src/lib/flip/integration/bridge.test.ts rename to src/lib/flip/bridge.test.ts index 2d5102a..a8debd0 100644 --- a/src/lib/flip/integration/bridge.test.ts +++ b/src/lib/flip/bridge.test.ts @@ -5,7 +5,7 @@ import { describe, expect, it, vi } from 'vitest'; import { createLayoutBridge } from './bridge'; -import type { FlipRect } from '../types'; +import type { FlipRect } from './types'; const rect = (x = 0, y = 0, w = 100, h = 50): FlipRect => ({ x, diff --git a/src/lib/flip/integration/bridge.ts b/src/lib/flip/bridge.ts similarity index 80% rename from src/lib/flip/integration/bridge.ts rename to src/lib/flip/bridge.ts index 3ccf6bb..f74956b 100644 --- a/src/lib/flip/integration/bridge.ts +++ b/src/lib/flip/bridge.ts @@ -7,7 +7,7 @@ * or two, so anything older is stale by definition. */ -import type { FlipRect } from '../types'; +import type { FlipRect } from './types'; interface LayoutRecord { rect: FlipRect; @@ -22,20 +22,18 @@ export interface LayoutBridge { /** Lifetime of an unread layout record, in ms. */ const LAYOUT_TTL_MS = 250; -const now = (): number => (typeof performance !== 'undefined' ? performance.now() : Date.now()); - /** Create an in-memory, scope-local layout registry. */ export const createLayoutBridge = (): LayoutBridge => { const registry = new Map(); return { writeLayout: (id, rect) => { - registry.set(id, { rect, timestamp: now() }); + registry.set(id, { rect, timestamp: performance.now() }); }, readLayout: (id) => { const entry = registry.get(id); if (!entry) return null; - if (now() - entry.timestamp > LAYOUT_TTL_MS) { + if (performance.now() - entry.timestamp > LAYOUT_TTL_MS) { registry.delete(id); return null; } diff --git a/src/lib/flip/burst.svelte.test.ts b/src/lib/flip/burst.svelte.test.ts new file mode 100644 index 0000000..9ca6046 --- /dev/null +++ b/src/lib/flip/burst.svelte.test.ts @@ -0,0 +1,80 @@ +/** + * Rapid re-trigger behaviour: reordering faster than a FLIP settles must keep + * every item inside the row it belongs to. An in-flight transform is an offset + * from the *old* resting box, so an interrupting run that treats the live + * visual rect as its `from` flings the element a full slot out of place. + */ + +import { afterEach, describe, expect, it } from 'vitest'; +import { flip } from './index'; + +const GAP = 10; +const WIDTH = 40; +const SLOT = WIDTH + GAP; +const COUNT = 5; + +let dispose: (() => void) | null = null; +let container: HTMLDivElement | null = null; + +const frame = (): Promise => new Promise((r) => requestAnimationFrame(() => r())); +/** rAF then a task tick — samples what the frame actually painted, after every + * rAF callback (including flip's frame batch) has run. */ +const paintedFrame = async (): Promise => { + await frame(); + await new Promise((r) => setTimeout(r, 0)); +}; + +afterEach(() => { + dispose?.(); + dispose = null; + container?.remove(); + container = null; +}); + +describe('reordering faster than the animation settles', () => { + it('never pushes an item outside the row, and lands on the layout slots', async () => { + container = document.createElement('div'); + Object.assign(container.style, { + position: 'fixed', + top: '0px', + left: '0px', + display: 'flex', + gap: `${GAP}px` + }); + document.body.appendChild(container); + + const boxes = Array.from({ length: COUNT }, () => { + const box = document.createElement('div'); + Object.assign(box.style, { width: `${WIDTH}px`, height: '20px' }); + container!.appendChild(box); + return box; + }); + + dispose = $effect.root(() => { + for (const box of boxes) flip({ duration: 300 })(box); + }); + await paintedFrame(); + + const lastSlot = (COUNT - 1) * SLOT; + const positions = (): number[] => boxes.map((b) => b.getBoundingClientRect().x); + const offRow: number[] = []; + + // Rotate the row every other frame — far faster than any run settles. + for (let i = 0; i < 6; i++) { + container.appendChild(container.firstElementChild!); + for (let f = 0; f < 2; f++) { + await paintedFrame(); + offRow.push(...positions().filter((x) => x < -1 || x > lastSlot + 1)); + } + } + expect(offRow).toEqual([]); + + await Promise.all( + boxes.flatMap((b) => b.getAnimations().map((a) => a.finished.catch(() => undefined))) + ); + await paintedFrame(); + + const resting = [...container.children].map((c) => c.getBoundingClientRect().x); + expect(resting).toEqual(Array.from({ length: COUNT }, (_, i) => i * SLOT)); + }); +}); diff --git a/src/lib/flip/animation/controller-slot.test.ts b/src/lib/flip/controller-slot.test.ts similarity index 78% rename from src/lib/flip/animation/controller-slot.test.ts rename to src/lib/flip/controller-slot.test.ts index e531c4f..a15981a 100644 --- a/src/lib/flip/animation/controller-slot.test.ts +++ b/src/lib/flip/controller-slot.test.ts @@ -13,7 +13,7 @@ const { animateFlipMock } = vi.hoisted(() => ({ animateFlipMock: vi.fn() })); vi.mock('./animator', () => ({ animateFlip: animateFlipMock })); import { createControllerSlot } from './controller-slot'; -import type { FlipAnimateArgs, FlipRect, FlipRectPair } from '../types'; +import type { FlipAnimateArgs, FlipRect, FlipRectPair } from './types'; const rect = (x = 0, y = 0): FlipRect => ({ x, y, width: 10, height: 10 }); const rects: FlipRectPair = { from: rect(), to: rect(5, 5) }; @@ -123,3 +123,33 @@ describe('createControllerSlot()', () => { expect(ctrl.cancel).toHaveBeenCalledTimes(1); }); }); + +describe('interrupted runs', () => { + /** Resolve the duration the slot handed to the most recent animateFlip() call. */ + const lastDuration = () => { + const d = animateFlipMock.mock.calls.at(-1)![0].options.duration; + return typeof d === 'function' ? d(0, rects) : d; + }; + + it('charges elapsed time against each replacement until it hits the floor', () => { + animateFlipMock.mockImplementation(() => ({ cancel: vi.fn(), currentTime: 100 })); + const slot = createControllerSlot(); + + slot.run(args({ options: { duration: 400 } })); + expect(lastDuration()).toBe(400); + + slot.run(args({ options: { duration: 400 } })); + expect(lastDuration()).toBe(300); + + slot.run(args({ options: { duration: 400 } })); + expect(lastDuration()).toBe(200); + + slot.run(args({ options: { duration: 400 } })); + expect(lastDuration()).toBe(120); // floored, not 100 + + // A natural finish ends the burst — the next run gets the full duration. + lastWrappedOnEnd()({} as Element, { finished: true, rects }); + slot.run(args({ options: { duration: 400 } })); + expect(lastDuration()).toBe(400); + }); +}); diff --git a/src/lib/flip/animation/controller-slot.ts b/src/lib/flip/controller-slot.ts similarity index 61% rename from src/lib/flip/animation/controller-slot.ts rename to src/lib/flip/controller-slot.ts index 17511ba..03678eb 100644 --- a/src/lib/flip/animation/controller-slot.ts +++ b/src/lib/flip/controller-slot.ts @@ -8,9 +8,16 @@ * cancel / wrap-onEnd / null-on-finish boilerplate. */ -import type { AnimationController } from '../../animate/types'; +import type { AnimationController } from '../animate/types'; import { animateFlip } from './animator'; -import type { FlipAnimateArgs } from '../types'; +import { resolveDuration } from './options'; +import type { FlipAnimateArgs } from './types'; + +/** + * Floor for an interrupted run's shortened duration — below this a retarget + * reads as a snap rather than a movement. + */ +const MIN_INTERRUPT_DURATION = 120; interface ControllerSlot { /** Cancel any in-flight controller, then start a new FLIP animation. */ @@ -33,28 +40,46 @@ const cancelSafely = (controller: AnimationController | null): void => { export const createControllerSlot = (): ControllerSlot => { let current: AnimationController | null = null; + /** Time already spent animating in the current burst of interruptions. */ + let carried = 0; return { run: ({ options, ...rest }) => { + // A burst of triggers (drag, rapid shuffles) would otherwise restart the + // full duration on every retarget and never settle. Charge the time already + // spent against the replacement so the burst converges. + carried = current ? carried + (current.currentTime ?? 0) : 0; cancelSafely(current); + const requested = options?.duration; current = animateFlip({ ...rest, options: { ...options, + duration: + carried > 0 + ? (_distance, rects) => + Math.max(MIN_INTERRUPT_DURATION, resolveDuration(requested, rects) - carried) + : requested, // Clear the slot only on a natural finish — a cancel (finished: // false) is always followed by a fresh assignment below, so guarding // on `finished` prevents the outgoing run from nulling the new one. onEnd: (el, info) => { - if (info.finished) current = null; + if (info.finished) { + current = null; + carried = 0; + } options?.onEnd?.(el, info); } } }); + // Nothing to animate (identity delta, reduced motion) ends the burst. + if (!current) carried = 0; }, isActive: () => current !== null, cancel: () => { cancelSafely(current); current = null; + carried = 0; } }; }; diff --git a/src/lib/flip/dynamic.svelte.test.ts b/src/lib/flip/dynamic.svelte.test.ts new file mode 100644 index 0000000..b17b928 --- /dev/null +++ b/src/lib/flip/dynamic.svelte.test.ts @@ -0,0 +1,74 @@ +import { afterEach, describe, expect, it } from 'vitest'; +import { createDynamicAttrs } from './dynamic'; + +let mounted: Element[] = []; + +const mountBox = (className = ''): HTMLDivElement => { + const element = document.createElement('div'); + element.className = className; + document.body.appendChild(element); + mounted.push(element); + return element; +}; + +afterEach(() => { + for (const element of mounted) element.remove(); + mounted = []; +}); + +describe('createDynamicAttrs()', () => { + it('flattens ClassValue shapes and leaves markup classes alone', () => { + const element = mountBox('from-markup'); + const attrs = createDynamicAttrs(element); + + expect(attrs.write(['a', { b: true, c: false }], undefined)).toBe(true); + expect([...element.classList].sort()).toEqual(['a', 'b', 'from-markup']); + + expect(attrs.write(['b'], undefined)).toBe(true); + expect([...element.classList].sort()).toEqual(['b', 'from-markup']); + }); + + it('diffs style declarations without disturbing the animator’s properties', () => { + const element = mountBox(); + element.style.setProperty('--motion-x', '5px'); + const attrs = createDynamicAttrs(element); + + expect(attrs.write(undefined, 'color: red; --x: 1px')).toBe(true); + expect(element.style.getPropertyValue('color')).toBe('red'); + expect(element.style.getPropertyValue('--x')).toBe('1px'); + + expect(attrs.write(undefined, 'color: blue')).toBe(true); + expect(element.style.getPropertyValue('color')).toBe('blue'); + expect(element.style.getPropertyValue('--x')).toBe(''); + expect(element.style.getPropertyValue('--motion-x')).toBe('5px'); + }); + + it('preserves !important priority', () => { + const element = mountBox(); + const attrs = createDynamicAttrs(element); + + attrs.write(undefined, 'color: red !important'); + expect(element.style.getPropertyPriority('color')).toBe('important'); + }); + + it('reports no change when nothing moved, so callers can skip the reflow', () => { + const element = mountBox(); + const attrs = createDynamicAttrs(element); + + expect(attrs.write('a', 'color: red')).toBe(true); + expect(attrs.write('a', 'color: red')).toBe(false); + }); + + it('resets only what it applied', () => { + const element = mountBox('from-markup'); + element.style.setProperty('--motion-x', '5px'); + const attrs = createDynamicAttrs(element); + + attrs.write('a', 'color: red'); + attrs.reset(); + + expect([...element.classList]).toEqual(['from-markup']); + expect(element.style.getPropertyValue('color')).toBe(''); + expect(element.style.getPropertyValue('--motion-x')).toBe('5px'); + }); +}); diff --git a/src/lib/flip/dynamic.ts b/src/lib/flip/dynamic.ts new file mode 100644 index 0000000..2b9f659 --- /dev/null +++ b/src/lib/flip/dynamic.ts @@ -0,0 +1,111 @@ +/** + * Reactive `class` / `style` application for the FLIP attachment. + * + * The attachment owns these writes so the FLIP sequence is deterministic: + * measure `from` → write → measure `to` → animate, with no frame in between. + * + * Every write is a diff against what *we* previously applied — never a + * wholesale `className =` / `cssText =`. The animator writes `--motion-*` and + * `pointer-events` inline on the same element, and markup may carry its own + * classes; clobbering either would break an in-flight animation or the + * component's own styling. + * + * ponytail: a *dynamic* `class={…}` in markup still wins — Svelte's `set_class` + * assigns `className` wholesale when its expression changes, and we have no + * dependency on that. Use this option or a dynamic `class={…}`, not both. If + * that ever bites in practice, re-assert from a `MutationObserver` on the + * `class` attribute. + */ + +import type { ClassValue } from 'svelte/elements'; +import type { MotionElement } from '../shared/types'; + +export interface DynamicAttrs { + /** Write class/style; returns `true` when the DOM actually changed. */ + write: (classValue: ClassValue | undefined, styleValue: string | undefined) => boolean; + /** Remove everything we applied (teardown). */ + reset: () => void; +} + +/** Flatten Svelte's `ClassValue` shape into individual class tokens. */ +const flattenClass = (value: ClassValue | undefined): string[] => { + if (!value) return []; + if (typeof value === 'string') return value.split(/\s+/).filter(Boolean); + if (Array.isArray(value)) return value.flatMap((entry) => flattenClass(entry as ClassValue)); + return Object.keys(value).filter((key) => value[key]); +}; + +/** + * Parse a CSS declaration string with the platform's own parser — a detached + * element handles `!important`, comments, quoting, custom properties, and + * malformed input for free. Never assign `cssText` on the live element. + */ +let parser: MotionElement | null = null; + +const parseStyle = (value: string | undefined): Map => { + const declarations = new Map(); + if (!value) return declarations; + parser ??= document.createElement('div'); + parser.style.cssText = value; + const { style } = parser; + for (let i = 0; i < style.length; i++) { + const name = style[i]; + const priority = style.getPropertyPriority(name); + declarations.set(name, style.getPropertyValue(name) + (priority ? ` !${priority}` : '')); + } + return declarations; +}; + +/** Split a stored declaration back into the value/priority pair `setProperty` wants. */ +const splitPriority = (declaration: string): [value: string, priority: string] => + declaration.endsWith(' !important') + ? [declaration.slice(0, -' !important'.length), 'important'] + : [declaration, '']; + +export const createDynamicAttrs = (element: MotionElement): DynamicAttrs => { + let classes: string[] = []; + let styles = new Map(); + + return { + write(classValue, styleValue) { + const nextClasses = flattenClass(classValue); + const nextStyles = parseStyle(styleValue); + let changed = false; + + for (const token of classes) { + if (!nextClasses.includes(token)) { + element.classList.remove(token); + changed = true; + } + } + for (const token of nextClasses) { + if (!element.classList.contains(token)) { + element.classList.add(token); + changed = true; + } + } + classes = nextClasses; + + for (const name of styles.keys()) { + if (!nextStyles.has(name)) { + element.style.removeProperty(name); + changed = true; + } + } + for (const [name, declaration] of nextStyles) { + if (styles.get(name) === declaration) continue; + element.style.setProperty(name, ...splitPriority(declaration)); + changed = true; + } + styles = nextStyles; + + return changed; + }, + reset() { + for (const token of classes) element.classList.remove(token); + for (const name of styles.keys()) element.style.removeProperty(name); + classes = []; + styles = new Map(); + } + }; +}; diff --git a/src/lib/flip/geometry.ts b/src/lib/flip/geometry.ts index ac8dd81..5275e5b 100644 --- a/src/lib/flip/geometry.ts +++ b/src/lib/flip/geometry.ts @@ -44,7 +44,7 @@ interface DeltaOptions { scale?: boolean; } -export const DEFAULT_DURATION = 280; +export const FLIP_DEFAULT_DURATION = 280; // --------------------------------------------------------------------------- // Measurement @@ -73,6 +73,27 @@ export const measureVisual = (element: Element): FlipRect => { return { x, y, width, height }; }; +/** + * Re-express a live visual rect in the *previous* layout frame. + * + * An in-flight transform is an offset from the element's resting box. Once the + * layout changes, that same offset is measured against the *new* box, so the + * visual rect is no longer the position the element occupied a moment ago. + * Carrying the offset back onto `prev` recovers it, which is what an + * interrupting FLIP must animate from — otherwise the offset is added to the + * new slot and the element visibly shoots out of place. + */ +export const carryVisualOffset = ( + prev: FlipRect, + resting: FlipRect, + visual: FlipRect +): FlipRect => ({ + x: prev.x + (visual.x - resting.x), + y: prev.y + (visual.y - resting.y), + width: resting.width > 0 ? prev.width * (visual.width / resting.width) : prev.width, + height: resting.height > 0 ? prev.height * (visual.height / resting.height) : prev.height +}); + /** Approximate equality so sub-pixel jitter doesn't trigger reflows. */ export const rectsEqual = (a: FlipRect, b: FlipRect, epsilon = 0.5): boolean => Math.abs(a.x - b.x) < epsilon && diff --git a/src/lib/flip/index.ts b/src/lib/flip/index.ts index 4c52d2c..56d4483 100644 --- a/src/lib/flip/index.ts +++ b/src/lib/flip/index.ts @@ -2,15 +2,16 @@ * Public entry point for the FLIP module. * * Everything a consumer needs — `flip`, `snapshotRect`, `flipFrom`, - * `createFlipScope`, `anchoredFlip` — lives here. Observers, schedulers, and - * the layout bridge are internals and deliberately not exported. + * `createFlipScope`, `anchoredFlip` — lives here. Observers, schedulers, + * attribute application, and the layout bridge are internals and deliberately + * not exported. */ import type { Attachment } from 'svelte/attachments'; import type { AnimationController } from '../animate/types'; -import { animateFlip } from './animation/animator'; -import { createFlipAttachment } from './integration/attachment.svelte'; -import { createLayoutBridge } from './integration/bridge'; +import { animateFlip } from './animator'; +import { createFlipAttachment } from './attachment.svelte'; +import { createLayoutBridge } from './bridge'; import { measure } from './geometry'; import type { FlipOptions, FlipOptionsInput, FlipRect, FlipScope, MotionElement } from './types'; @@ -26,8 +27,9 @@ import type { FlipOptions, FlipOptionsInput, FlipRect, FlipScope, MotionElement * ```svelte *
    auto-tracks layout shifts
    *
    ...
    - * - *
    { void open; } })}>...
    + * + *
    ({ 'is-open': open }) })}>...
    + *
    (open ? 'height: 320px' : 'height: 64px') })}>...
    * ``` */ export const flip = (input?: FlipOptionsInput): Attachment => @@ -83,13 +85,10 @@ export type { // Low-level re-exports // --------------------------------------------------------------------------- -export { createFlipSwitcher } from './integration/switcher.svelte'; -export type { FlipSwitcher, FlipSwitchRole } from './integration/switcher.svelte'; +export { createFlipSwitcher } from './switcher.svelte'; +export type { FlipSwitcher, FlipSwitchRole } from './switcher.svelte'; -export { animateFlip } from './animation/animator'; +export { animateFlip } from './animator'; export { measure } from './geometry'; -// Public because `FlipOptions.auto` accepts an ObserverManager. -export { createObserverManager } from './tracking/observers'; -export type { ObserverManager } from './tracking/observers'; export type * from './types'; diff --git a/src/lib/flip/tracking/observers.test.ts b/src/lib/flip/observers.test.ts similarity index 100% rename from src/lib/flip/tracking/observers.test.ts rename to src/lib/flip/observers.test.ts diff --git a/src/lib/flip/tracking/observers.ts b/src/lib/flip/observers.ts similarity index 100% rename from src/lib/flip/tracking/observers.ts rename to src/lib/flip/observers.ts diff --git a/src/lib/flip/options.test.ts b/src/lib/flip/options.test.ts index 2dda270..c62ec3f 100644 --- a/src/lib/flip/options.test.ts +++ b/src/lib/flip/options.test.ts @@ -12,7 +12,7 @@ import { resolveEasing, resolveOpacity } from './options'; -import { DEFAULT_DURATION } from './geometry'; +import { FLIP_DEFAULT_DURATION } from './geometry'; import { DEFAULT_EASING } from '../animate/keyframes/easing-utils'; import type { FlipRectPair } from './types'; @@ -22,8 +22,8 @@ const pairAt = (dx = 0, dy = 0): FlipRectPair => ({ }); describe('constants', () => { - it('DEFAULT_DURATION is a positive number', () => { - expect(DEFAULT_DURATION).toBeGreaterThan(0); + it('FLIP_DEFAULT_DURATION is a positive number', () => { + expect(FLIP_DEFAULT_DURATION).toBeGreaterThan(0); }); it('DEFAULT_DELAY is 0', () => { @@ -63,8 +63,8 @@ describe('readOptions()', () => { describe('resolveDuration()', () => { const rects = pairAt(); - it('returns DEFAULT_DURATION when undefined', () => { - expect(resolveDuration(undefined, rects)).toBe(DEFAULT_DURATION); + it('returns FLIP_DEFAULT_DURATION when undefined', () => { + expect(resolveDuration(undefined, rects)).toBe(FLIP_DEFAULT_DURATION); }); it('returns the literal value for a number', () => { diff --git a/src/lib/flip/options.ts b/src/lib/flip/options.ts index e0b7360..109bea4 100644 --- a/src/lib/flip/options.ts +++ b/src/lib/flip/options.ts @@ -6,7 +6,7 @@ import { CSS_EASINGS } from '../easing'; import type { EasingFn } from '../shared/types'; import { DEFAULT_EASING } from '../animate/keyframes/easing-utils'; -import { DEFAULT_DURATION, diagonal } from './geometry'; +import { FLIP_DEFAULT_DURATION, diagonal } from './geometry'; import type { FlipDuration, FlipEasing, @@ -29,7 +29,7 @@ export const readOptions = (input: FlipOptionsInput): FlipOptions => { * function of the rect-to-rect diagonal distance. */ export const resolveDuration = (d: FlipDuration | undefined, rects: FlipRectPair): number => { - if (d == null) return DEFAULT_DURATION; + if (d == null) return FLIP_DEFAULT_DURATION; const raw = typeof d === 'function' ? d(diagonal(rects.from, rects.to), rects) : d; return Math.max(0, raw); }; diff --git a/src/lib/flip/integration/switcher.svelte.ts b/src/lib/flip/switcher.svelte.ts similarity index 93% rename from src/lib/flip/integration/switcher.svelte.ts rename to src/lib/flip/switcher.svelte.ts index 8262dd1..45400cd 100644 --- a/src/lib/flip/integration/switcher.svelte.ts +++ b/src/lib/flip/switcher.svelte.ts @@ -20,10 +20,10 @@ import { untrack } from 'svelte'; import type { Attachment } from 'svelte/attachments'; -import { isBrowser } from '../../shared/browser'; -import { createControllerSlot } from '../animation/controller-slot'; -import { measure } from '../geometry'; -import type { FlipOptions, FlipRect, MotionElement } from '../types'; +import { isBrowser } from '../shared/browser'; +import { createControllerSlot } from './controller-slot'; +import { measure } from './geometry'; +import type { FlipOptions, FlipRect, MotionElement } from './types'; // --------------------------------------------------------------------------- // Public types diff --git a/src/lib/flip/types.ts b/src/lib/flip/types.ts index f2343c9..bd6770d 100644 --- a/src/lib/flip/types.ts +++ b/src/lib/flip/types.ts @@ -1,7 +1,7 @@ import type { Attachment } from 'svelte/attachments'; +import type { ClassValue } from 'svelte/elements'; import type { FlipRect, FlipRectPair } from './geometry'; import type { EasingFn, MotionElement } from '../shared/types'; -import type { ObserverManager } from './tracking/observers'; // --------------------------------------------------------------------------- // Core geometry @@ -17,8 +17,6 @@ export type FlipEasing = EasingFn | string; export type FlipDuration = number | ((distance: number, rects: FlipRectPair) => number); -export type FlipAuto = false | (() => void) | ObserverManager; - /** * Controls whether a particular reflow cycle should be skipped (no animation * played). `true` skips every cycle; a function receives the zero-based render @@ -50,13 +48,24 @@ export interface FlipOptions { */ layoutId?: string; /** - * Control automatic layout tracking. + * Classes applied to the element by the attachment. The thunk is tracked, so + * changing the rune state it reads writes the classes and animates the + * resulting layout change in the same tick. + * + * Use this *or* a dynamic `class={…}` in markup, not both — Svelte assigns + * `className` wholesale and would drop these tokens. A static `class="…"` + * is safe. + * + * @example `class: () => ({ 'is-open': open })` + */ + class?: () => ClassValue; + /** + * Inline style declarations applied to the element by the attachment, as CSS + * text. Tracked and measured exactly like {@link FlipOptions.class}. * - * - `false` / omitted: no automatic tracking - * - `() => void`: remeasure whenever rune state read inside the callback changes - * - `ObserverManager`: use the provided observer manager (see `createObserverManager`) + * @example `style: () => (open ? 'height: 320px' : 'height: 64px')` */ - auto?: FlipAuto; + style?: () => string; /** Disable animation entirely (still tracks rects). */ disabled?: boolean; /** From f1aa3107118ebd6ba0923ec667fbf6ba090386fa Mon Sep 17 00:00:00 2001 From: ryu-man Date: Sat, 15 Aug 2026 13:51:20 -0400 Subject: [PATCH 29/30] docs(demo): show flip({ class }) in MotionLab Adds a card for the new option and drops the now-unnecessary `auto:` thunks from the existing FLIP demos. Co-Authored-By: Claude Opus 5 (1M context) --- src/routes/MotionLab.svelte | 51 ++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/routes/MotionLab.svelte b/src/routes/MotionLab.svelte index e0a27e8..0884462 100644 --- a/src/routes/MotionLab.svelte +++ b/src/routes/MotionLab.svelte @@ -138,6 +138,10 @@ flipItems = [...flipItems].sort(() => Math.random() - 0.5); } + // 5b. flip({ class }) — flip owns the attribute, so the write and the + // measurement happen in the same tick. + let flipExpanded = $state(false); + // 6. flipFrom() — manual expand / collapse. FLIP the card *and* the button // below it: FLIP animates transform, not flow, so the sibling would jump to // the new layout instantly unless it animates from its old rect too. @@ -587,7 +591,7 @@ controllers = els.map((el, i) => code={`let items = $state(['A', 'B', 'C', …]); {#each items as item (item)} -
    { void items; } })}> +
    {item}
    {/each}`} @@ -595,13 +599,7 @@ controllers = els.map((el, i) =>
    {#each flipItems as item (item)}
    { - void flipItems; - } - })} + {@attach flip({ duration: 400, easing: easeInOut })} class="flex size-12 items-center justify-center rounded-lg bg-zinc-100 font-mono text-sm font-semibold text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300" > {item} @@ -611,6 +609,35 @@ controllers = els.map((el, i) => {@render trigger('Shuffle', shuffleFlip)} + + +
    (expanded ? 'w-48 h-24' : 'w-16 h-16') + })} + class="rounded-lg bg-indigo-600" +>
    `} + > +
    +
    (flipExpanded ? 'w-48 h-24' : 'w-16 h-16') + })} + class="rounded-lg bg-indigo-600" + >
    +
    + {@render trigger('Toggle', () => (flipExpanded = !flipExpanded))} +
    + maybeDismiss(value, info, el) })} - {@attach flip({ - duration: 260, - easing: easeOut, - auto: () => { - void swipeItems; - } - })} + {@attach flip({ duration: 260, easing: easeOut })} class="flex cursor-grab items-center justify-between rounded-lg bg-indigo-50 px-3 py-2 text-xs font-medium text-indigo-700 select-none active:cursor-grabbing dark:bg-indigo-500/10 dark:text-indigo-300" > {value} From dcba23b191bfcd20a18e86bd21debe596a4b5f86 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Sat, 15 Aug 2026 13:51:20 -0400 Subject: [PATCH 30/30] chore: fix repository metadata `repository.url` gets the `git+` prefix npm expects, and the CHANGELOG release link points at ixirjs/pulse instead of the old svelte-atoms/vibra path. Co-Authored-By: Claude Opus 5 (1M context) --- CHANGELOG.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22dbacc..a0bee5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,4 +78,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Capture an element's current rect for use with `flipFrom`. -[0.1.0]: https://github.com/svelte-atoms/vibra/releases/tag/v0.1.0 +[0.1.0]: https://github.com/ixirjs/pulse/releases/tag/v0.1.0 diff --git a/package.json b/package.json index 218cdf3..6d03919 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "license": "MIT", "repository": { "type": "git", - "url": "https://github.com/ixirjs/pulse.git" + "url": "git+https://github.com/ixirjs/pulse.git" }, "homepage": "https://github.com/ixirjs/pulse#readme", "bugs": {

    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 \ No newline at end of file diff --git a/src/stories/assets/youtube.svg b/src/stories/assets/youtube.svg deleted file mode 100644 index a7515d7..0000000 --- a/src/stories/assets/youtube.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/stories/button.css b/src/stories/button.css deleted file mode 100644 index 4e3620b..0000000 --- a/src/stories/button.css +++ /dev/null @@ -1,30 +0,0 @@ -.storybook-button { - display: inline-block; - cursor: pointer; - border: 0; - border-radius: 3em; - font-weight: 700; - line-height: 1; - font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; -} -.storybook-button--primary { - background-color: #555ab9; - color: white; -} -.storybook-button--secondary { - box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset; - background-color: transparent; - color: #333; -} -.storybook-button--small { - padding: 10px 16px; - font-size: 12px; -} -.storybook-button--medium { - padding: 11px 20px; - font-size: 14px; -} -.storybook-button--large { - padding: 12px 24px; - font-size: 16px; -} diff --git a/src/stories/header.css b/src/stories/header.css deleted file mode 100644 index 5efd46c..0000000 --- a/src/stories/header.css +++ /dev/null @@ -1,32 +0,0 @@ -.storybook-header { - display: flex; - justify-content: space-between; - align-items: center; - border-bottom: 1px solid rgba(0, 0, 0, 0.1); - padding: 15px 20px; - font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; -} - -.storybook-header svg { - display: inline-block; - vertical-align: top; -} - -.storybook-header h1 { - display: inline-block; - vertical-align: top; - margin: 6px 0 6px 10px; - font-weight: 700; - font-size: 20px; - line-height: 1; -} - -.storybook-header button + button { - margin-left: 10px; -} - -.storybook-header .welcome { - margin-right: 10px; - color: #333; - font-size: 14px; -} diff --git a/src/stories/page.css b/src/stories/page.css deleted file mode 100644 index 77c81d2..0000000 --- a/src/stories/page.css +++ /dev/null @@ -1,68 +0,0 @@ -.storybook-page { - margin: 0 auto; - padding: 48px 20px; - max-width: 600px; - color: #333; - font-size: 14px; - line-height: 24px; - font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; -} - -.storybook-page h2 { - display: inline-block; - vertical-align: top; - margin: 0 0 4px; - font-weight: 700; - font-size: 32px; - line-height: 1; -} - -.storybook-page p { - margin: 1em 0; -} - -.storybook-page a { - color: inherit; -} - -.storybook-page ul { - margin: 1em 0; - padding-left: 30px; -} - -.storybook-page li { - margin-bottom: 8px; -} - -.storybook-page .tip { - display: inline-block; - vertical-align: top; - margin-right: 10px; - border-radius: 1em; - background: #e7fdd8; - padding: 4px 12px; - color: #357a14; - font-weight: 700; - font-size: 11px; - line-height: 12px; -} - -.storybook-page .tip-wrapper { - margin-top: 40px; - margin-bottom: 40px; - font-size: 13px; - line-height: 20px; -} - -.storybook-page .tip-wrapper svg { - display: inline-block; - vertical-align: top; - margin-top: 3px; - margin-right: 4px; - width: 12px; - height: 12px; -} - -.storybook-page .tip-wrapper svg path { - fill: #1ea7fd; -} From faac90e44be9e658f91f2f2ce437f7c8d76ea6a4 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:44:43 -0400 Subject: [PATCH 02/30] chore(tooling): purge Storybook deps, add verify script and CI Drops the Storybook devDependencies, eslint plugin and vitest project left behind by the scaffolding removal. Adds a single `verify` script (check + lint + test + size budgets) and a GitHub workflow that runs it. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/verify.yml | 25 ++++++++++ eslint.config.js | 5 +- package.json | 11 +---- vite.config.ts | 92 ++++++++++++++---------------------- 4 files changed, 63 insertions(+), 70 deletions(-) create mode 100644 .github/workflows/verify.yml diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml new file mode 100644 index 0000000..bff596a --- /dev/null +++ b/.github/workflows/verify.yml @@ -0,0 +1,25 @@ +name: Verify + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +jobs: + verify: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: '1.3.9' + - uses: actions/setup-node@v4 + with: + node-version: 22 + - run: bun install --frozen-lockfile + # One authoritative release-quality command: type/Svelte checks, style, + # browser/server tests, packed-consumer verification, and size budgets. + - run: bun run verify diff --git a/eslint.config.js b/eslint.config.js index 2e67621..0014edd 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,6 +1,3 @@ -// For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format -import storybook from "eslint-plugin-storybook"; - import prettier from 'eslint-config-prettier'; import path from 'node:path'; import { includeIgnoreFile } from '@eslint/compat'; @@ -25,7 +22,7 @@ export default defineConfig( rules: { // typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects. // see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors - "no-undef": 'off' + 'no-undef': 'off' } }, { diff --git a/package.json b/package.json index 39a62c7..218cdf3 100644 --- a/package.json +++ b/package.json @@ -39,8 +39,7 @@ "format": "prettier --write .", "test:unit": "vitest", "test": "npm run test:unit -- --run", - "storybook": "storybook dev -p 6006", - "build-storybook": "storybook build", + "verify": "npm run check && npm run lint && npm run test && npm run analyze", "analyze": "npm run prepack && size-limit", "changeset": "changeset", "version": "changeset version", @@ -115,15 +114,9 @@ }, "devDependencies": { "@changesets/cli": "^2.31.0", - "@chromatic-com/storybook": "^5.1.2", "@eslint/compat": "^2.0.4", "@eslint/js": "^10.0.1", "@size-limit/preset-small-lib": "^12.1.0", - "@storybook/addon-a11y": "^10.3.6", - "@storybook/addon-docs": "^10.3.6", - "@storybook/addon-svelte-csf": "^5.1.2", - "@storybook/addon-vitest": "^10.3.6", - "@storybook/sveltekit": "^10.3.6", "@sveltejs/adapter-auto": "^7.0.1", "@sveltejs/kit": "^2.57.0", "@sveltejs/package": "^2.5.7", @@ -134,7 +127,6 @@ "@vitest/coverage-v8": "^4.1.3", "eslint": "^10.2.0", "eslint-config-prettier": "^10.1.8", - "eslint-plugin-storybook": "^10.3.6", "eslint-plugin-svelte": "^3.17.0", "globals": "^17.4.0", "mdsvex": "^0.12.7", @@ -144,7 +136,6 @@ "prettier-plugin-tailwindcss": "^0.7.2", "publint": "^0.3.18", "size-limit": "^12.1.0", - "storybook": "^10.3.6", "svelte": "^5.55.2", "svelte-check": "^4.4.6", "tailwindcss": "^4.2.2", diff --git a/vite.config.ts b/vite.config.ts index a53cf91..9458c51 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,62 +1,42 @@ -/// import tailwindcss from '@tailwindcss/vite'; import { defineConfig } from 'vitest/config'; import { playwright } from '@vitest/browser-playwright'; import { sveltekit } from '@sveltejs/kit/vite'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; -import { storybookTest } from '@storybook/addon-vitest/vitest-plugin'; -const dirname = typeof __dirname !== 'undefined' ? __dirname : path.dirname(fileURLToPath(import.meta.url)); -// More info at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon export default defineConfig({ - plugins: [tailwindcss(), sveltekit()], - test: { - expect: { - requireAssertions: true - }, - projects: [{ - extends: './vite.config.ts', - test: { - name: 'client', - browser: { - enabled: true, - provider: playwright(), - instances: [{ - browser: 'chromium', - headless: true - }] - }, - include: ['src/**/*.svelte.{test,spec}.{js,ts}'], - exclude: ['src/lib/server/**'] - } - }, { - extends: './vite.config.ts', - test: { - name: 'server', - environment: 'node', - include: ['src/**/*.{test,spec}.{js,ts}'], - exclude: ['src/**/*.svelte.{test,spec}.{js,ts}'] - } - }, { - extends: true, - plugins: [ - // The plugin will run tests for the stories defined in your Storybook config - // See options at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon#storybooktest - storybookTest({ - configDir: path.join(dirname, '.storybook') - })], - test: { - name: 'storybook', - browser: { - enabled: true, - headless: true, - provider: playwright({}), - instances: [{ - browser: 'chromium' - }] - } - } - }] - } -}); \ No newline at end of file + plugins: [tailwindcss(), sveltekit()], + test: { + expect: { + requireAssertions: true + }, + projects: [ + { + extends: './vite.config.ts', + test: { + name: 'client', + browser: { + enabled: true, + provider: playwright(), + instances: [ + { + browser: 'chromium', + headless: true + } + ] + }, + include: ['src/**/*.svelte.{test,spec}.{js,ts}'], + exclude: ['src/lib/server/**'] + } + }, + { + extends: './vite.config.ts', + test: { + name: 'server', + environment: 'node', + include: ['src/**/*.{test,spec}.{js,ts}'], + exclude: ['src/**/*.svelte.{test,spec}.{js,ts}'] + } + } + ] + } +}); From 5d583bbbcfad90b42447b409024b1ef207044da2 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:44:43 -0400 Subject: [PATCH 03/30] style: reformat config files with prettier Tabs + single quotes to match the rest of the repo; no behaviour change. Co-Authored-By: Claude Opus 5 (1M context) --- .changeset/config.json | 18 +++++++++--------- .claude/CLAUDE.md | 2 +- .prettierrc | 5 +---- svelte.config.js | 2 +- vitest.shims.d.ts | 2 +- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/.changeset/config.json b/.changeset/config.json index ec98e35..199c9ef 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,11 +1,11 @@ { - "$schema": "https://unpkg.com/@changesets/config@3.1.4/schema.json", - "changelog": "@changesets/cli/changelog", - "commit": false, - "fixed": [], - "linked": [], - "access": "public", - "baseBranch": "main", - "updateInternalDependencies": "patch", - "ignore": [] + "$schema": "https://unpkg.com/@changesets/config@3.1.4/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "public", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [] } diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 71a4ab9..43f61e3 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -1 +1 @@ -- after each fix or change do a global review of the change and how it is consistent with the codebase \ No newline at end of file +- after each fix or change do a global review of the change and how it is consistent with the codebase diff --git a/.prettierrc b/.prettierrc index 891c0f8..819fa57 100644 --- a/.prettierrc +++ b/.prettierrc @@ -3,10 +3,7 @@ "singleQuote": true, "trailingComma": "none", "printWidth": 100, - "plugins": [ - "prettier-plugin-svelte", - "prettier-plugin-tailwindcss" - ], + "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], "overrides": [ { "files": "*.svelte", diff --git a/svelte.config.js b/svelte.config.js index 0442732..0e93b3b 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -5,7 +5,7 @@ import adapter from '@sveltejs/adapter-auto'; const config = { compilerOptions: { // Force runes mode for the project, except for libraries. Can be removed in svelte 6. - runes: ({ filename }) => filename.split(/[/\\]/).includes('node_modules') ? undefined : true + runes: ({ filename }) => (filename.split(/[/\\]/).includes('node_modules') ? undefined : true) }, kit: { // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list. diff --git a/vitest.shims.d.ts b/vitest.shims.d.ts index 7782f28..03b1801 100644 --- a/vitest.shims.d.ts +++ b/vitest.shims.d.ts @@ -1 +1 @@ -/// \ No newline at end of file +/// From e4b1d6aed5505839e8b2df3cca0e0d0f7df986a3 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:44:43 -0400 Subject: [PATCH 04/30] chore(size-limit): retarget budgets at the full public API Root entry now re-exports every module, not just animate + flip, so the old 12 kB budget measured the wrong thing. Co-Authored-By: Claude Opus 5 (1M context) --- .size-limit.json | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.size-limit.json b/.size-limit.json index 9f65b3f..5dc1964 100644 --- a/.size-limit.json +++ b/.size-limit.json @@ -1,17 +1,17 @@ [ - { - "name": "Root (animate + flip)", - "path": "./dist/index.js", - "limit": "12 kB" - }, - { - "name": "animate only", - "path": "./dist/animate/index.js", - "limit": "8 kB" - }, - { - "name": "flip only", - "path": "./dist/flip/index.js", - "limit": "6 kB" - } + { + "name": "Root public API", + "path": "./dist/index.js", + "limit": "19 kB" + }, + { + "name": "animate only", + "path": "./dist/animate/index.js", + "limit": "8 kB" + }, + { + "name": "flip only", + "path": "./dist/flip/index.js", + "limit": "7 kB" + } ] From ec7d504efabf3a1140544660ebb48db2da718673 Mon Sep 17 00:00:00 2001 From: ryu-man Date: Thu, 30 Jul 2026 20:44:52 -0400 Subject: [PATCH 05/30] docs: drop per-module READMEs and INDEX.md, refresh root README Fourteen module READMEs and INDEX.md restated what the TSDoc and the root README already say, and drifted every time the API moved. One document to keep in sync instead of sixteen. Co-Authored-By: Claude Opus 5 (1M context) --- INDEX.md | 142 ------- README.md | 155 ++++--- src/lib/animate/README.md | 601 --------------------------- src/lib/animate/core/README.md | 10 - src/lib/animate/keyframes/README.md | 12 - src/lib/animate/properties/README.md | 13 - src/lib/animate/timeline/README.md | 12 - src/lib/easing/README.md | 43 -- src/lib/flip/README.md | 92 ---- src/lib/flip/animation/README.md | 11 - src/lib/flip/integration/README.md | 12 - src/lib/flip/tracking/README.md | 11 - src/lib/gestures/README.md | 149 ------- src/lib/gradient/README.md | 31 -- src/lib/morph/README.md | 35 -- src/lib/presence/README.md | 69 --- src/lib/scroll/README.md | 39 -- src/lib/shared/README.md | 32 -- src/lib/text/README.md | 52 --- src/lib/variants/README.md | 36 -- src/lib/view-transition/README.md | 61 --- 21 files changed, 86 insertions(+), 1532 deletions(-) delete mode 100644 INDEX.md delete mode 100644 src/lib/animate/README.md delete mode 100644 src/lib/animate/core/README.md delete mode 100644 src/lib/animate/keyframes/README.md delete mode 100644 src/lib/animate/properties/README.md delete mode 100644 src/lib/animate/timeline/README.md delete mode 100644 src/lib/easing/README.md delete mode 100644 src/lib/flip/README.md delete mode 100644 src/lib/flip/animation/README.md delete mode 100644 src/lib/flip/integration/README.md delete mode 100644 src/lib/flip/tracking/README.md delete mode 100644 src/lib/gestures/README.md delete mode 100644 src/lib/gradient/README.md delete mode 100644 src/lib/morph/README.md delete mode 100644 src/lib/presence/README.md delete mode 100644 src/lib/scroll/README.md delete mode 100644 src/lib/shared/README.md delete mode 100644 src/lib/text/README.md delete mode 100644 src/lib/variants/README.md delete mode 100644 src/lib/view-transition/README.md diff --git a/INDEX.md b/INDEX.md deleted file mode 100644 index 1021d9b..0000000 --- a/INDEX.md +++ /dev/null @@ -1,142 +0,0 @@ -# Repository Index - -> Repository-wide router and architectural map for AI agents. This is a single-project Svelte library repository; read this index before modifying the project. - -## Repository overview - -`@ixirjs/pulse` is a TypeScript/Svelte 5 library of spring-powered Web Animations API utilities, FLIP layout transitions, gestures, scroll utilities, presence transitions, and related motion helpers. The repository is a **single project**, not a monorepo: the root `package.json` contains one package and its scripts, `src/lib/index.ts` is the public barrel, and `src/routes`/`src/stories` provide the SvelteKit demo and Storybook material. Build and package behavior is defined by `vite.config.ts`, `svelte.config.js`, `tsconfig.json`, and the package scripts. - -## Start here - -- `package.json` — package identity, public exports, peer dependency, and verified scripts. -- `README.md` — public API examples and consumer-facing behavior. -- `src/lib/index.ts` — root public export surface. -- `src/lib/animate/index.ts` and `src/lib/flip/index.ts` — the two deepest core API entry points. -- `vite.config.ts` — SvelteKit/Vite and Vitest client, server, and Storybook test projects. -- `svelte.config.js` and `tsconfig.json` — Svelte 5 compiler and TypeScript setup. -- `src/routes/+page.svelte` — executable demo exercising the library features. - -## Project index router - -This is a single-project repository. There are no subordinate `INDEX.md` files: `src/lib` is the library source tree, not an independently built package, and `src/routes` and `src/stories` are project-local demo/documentation surfaces. - -| Project or subsystem | Responsibility | Index | When to read it | -|---|---|---|---| -| Root project | Published `@ixirjs/pulse` package plus SvelteKit demo and Storybook fixtures | `INDEX.md` | Always; this index is the local project guide | - -## Repository topology - -| Path | Responsibility | Index or source of truth | -|---|---|---| -| `src/lib/` | Authored library implementation and public subpath entry points | `src/lib/index.ts`, each module's `index.ts`, and module `README.md` files | -| `src/lib/animate/` | WAAPI animation runtime, controllers, keyframes, springs, timelines, and numeric helpers | `src/lib/animate/index.ts` | -| `src/lib/flip/` | FLIP measurement, animation, Svelte attachments, shared-element bridges, and tracking | `src/lib/flip/index.ts` | -| `src/lib/easing/` | Easing primitives, CSS easings, cubic bezier, and spring easing | `src/lib/easing/index.ts` | -| `src/lib/gestures/` | Svelte 5 pointer, touch, wheel, and reorder attachments | `src/lib/gestures/index.ts` | -| `src/lib/scroll/` | Scroll progress and in-view utilities | `src/lib/scroll/index.ts` | -| `src/lib/presence/`, `variants/`, `view-transition/` | Svelte transitions, named animation states, and native View Transitions integration | Their local `index.ts` files | -| `src/lib/gradient/`, `morph/`, `text/` | Gradient interpolation, SVG path morphing, and text splitting | Their local `index.ts` files | -| `src/lib/shared/` | Browser checks, math, shared types, and spring core used across modules | `src/lib/shared/index.ts` | -| `src/routes/` | SvelteKit demo page and layout; imports library internals through `$lib` | `src/routes/+page.svelte` | -| `src/stories/` | Storybook component stories and Storybook test inputs | `.storybook/main.ts` | -| `static/` | Static SvelteKit assets | SvelteKit configuration | -| `.storybook/` | Storybook framework, addons, story discovery, and preview configuration | `.storybook/main.ts`, `.storybook/preview.ts` | -| `.changeset/` | Release notes and Changesets publishing configuration | `.changeset/config.json` | - -## Cross-project architecture - -There are no cross-project dependencies: this is one package. Within the package, `src/lib/index.ts` re-exports feature barrels, while `package.json` also exposes feature subpaths such as `./animate`, `./flip`, and `./gestures`. The `animate` and FLIP implementations share motion types and browser helpers; FLIP, gestures, presence, variants, scroll, and view-transition features use the animation/easing machinery or shared `--motion-*` transform conventions where applicable. Feature modules are authored together and are packaged by `svelte-package` into `dist`. - -The SvelteKit demo (`src/routes/+page.svelte`) is a consumer-like integration surface and imports feature modules directly from `$lib`; changes to public exports or behavior should be checked against it. Storybook stories are a separate test/documentation surface in the same project, discovered by `.storybook/main.ts` and included in the Storybook Vitest project. - -```text -public package entry points (src/lib/index.ts, package.json exports) - ├── animate / easing / shared - ├── flip / gestures / scroll - └── presence / variants / gradient / morph / text / view-transition - ├── SvelteKit demo: src/routes - └── Storybook stories/tests: src/stories + .storybook -``` - -## Shared development workflows - -| Task | Command | Scope | Evidence or notes | -|---|---|---|---| -| Start SvelteKit/Vite development server | `npm run dev` | Root app | `package.json` | -| Type and Svelte validation | `npm run check` | Whole configured project | Runs `svelte-kit sync` and `svelte-check` from `package.json` | -| Unit tests | `npm test` | Root Vitest suite; configured client/server projects | `test` invokes `test:unit -- --run`; `vite.config.ts` defines test projects | -| Watch unit tests | `npm run test:unit` | Vitest in watch mode | `package.json` | -| Lint and formatting check | `npm run lint` | Repository files not ignored by ESLint/Prettier | `eslint.config.js`, `.gitignore`, and `package.json` | -| Build package and app | `npm run build` | SvelteKit build followed by package preparation | `package.json`; `prepack` runs `svelte-package` and `publint` | -| Build Storybook | `npm run build-storybook` | Storybook stories | `.storybook/main.ts` and `package.json` | -| Analyze package size | `npm run analyze` | Package output and size-limit check | `package.json`, `.size-limit.json` | -| Release | `npm run release` | Package publishing via Changesets | `.changeset/config.json`; publishing is an external side effect and requires release intent | - -No command is claimed here for deployment: `svelte.config.js` uses `adapter-auto`, but no repository deployment workflow or platform configuration was found. - -## Shared configuration and infrastructure - -- `package.json` controls package exports, Svelte peer dependency, build/package tooling, test/lint scripts, and Changesets release scripts. -- `bun.lock` records dependency resolution; `.npmrc` enables strict engine checking. -- `vite.config.ts` configures Tailwind, SvelteKit, Vitest browser testing through Playwright, Node tests, and Storybook tests. -- `svelte.config.js` configures Svelte 5 runes mode, `adapter-auto`, and mdsvex extensions. -- `tsconfig.json` extends generated SvelteKit settings and enables strict TypeScript/bundler resolution. -- `eslint.config.js`, `.prettierrc`, and `.prettierignore` define lint/format behavior. -- `.storybook/main.ts` and `.storybook/preview.ts` define Storybook discovery, addons, and accessibility settings. -- `.changeset/config.json` defines public Changesets release behavior. - -## Repository-wide conventions and constraints - -- Keep library implementation under `src/lib`; expose new public APIs through the appropriate local barrel and, when intended, `src/lib/index.ts` and `package.json` exports. -- Svelte source uses Svelte 5 runes by default through `svelte.config.js`; library code also has non-component TypeScript modules. -- The package targets Svelte `^5.0.0` as a peer dependency and Node `>=18`. -- Transform-related features compose through the library's `--motion-*` custom-property approach; avoid introducing transform clobbering in animation, FLIP, or gesture code. -- Tests sit beside implementations as `*.test.ts` and `*.svelte.test.ts`; preserve that association. -- `.claude/CLAUDE.md` requests a global review after each change. No source file should be treated as generated merely because it is under `src`. - -## Cross-project change guide - -This is a single project, so the table identifies project-local surfaces rather than separate workspaces. - -| Change type | Affected indexes or projects | Validation | Risks | -|---|---|---|---| -| Public API, type, or export change | `src/lib`, `package.json`, demo, relevant stories | `npm run check`, `npm test`, `npm run build` | Broken subpath exports or consumer types | -| Animation/keyframe/controller change | `src/lib/animate`, `src/lib/shared`, dependent motion modules | Narrow colocated tests, `npm test`, `npm run check` | WAAPI timing, browser-only behavior, transform composition | -| FLIP/layout/observer change | `src/lib/flip`, demo and relevant Svelte tests | FLIP tests, browser tests, `npm test` | Layout measurement, reflow timing, shared-element state | -| Gesture/scroll/transition feature change | Relevant `src/lib/` module and demo | Colocated tests, browser tests, `npm run check` | Pointer/browser APIs and reduced-motion behavior | -| Storybook/demo change | `src/routes`, `src/stories`, `.storybook` | `npm run check`, `npm run build-storybook`, Storybook Vitest via `npm test` | Integration examples can expose public API regressions | -| Release metadata or package output change | `.changeset`, `package.json`, generated `dist` | `npm run prepack` or `npm run build` | Do not hand-edit generated package output | - -## Generated, vendored, and ignored areas - -- `node_modules/` is installed dependency content and must not be edited. -- `.svelte-kit/` is generated by SvelteKit synchronization and is ignored by `.gitignore`. -- `dist/` is package/build output and is ignored; its source of truth is `src/lib/` plus package/build configuration. -- `.output/`, `.vercel/`, `.netlify/`, `.wrangler/`, and `/build` are ignored output/deployment areas when produced. -- Environment files matching `.env*` are ignored except explicitly allowed example/test names; never copy values into documentation. -- `bun.lock` is committed dependency metadata, not authored runtime source. - -## Risks and fragile boundaries - -**Verified:** browser APIs are central: the animation runtime uses WAAPI, FLIP uses DOM measurement/observers, gestures use pointer/touch/wheel behavior, and view transitions depend on optional platform support. `vite.config.ts` separates browser Svelte tests from Node tests. Reduced-motion handling is part of the public behavior described in `README.md` and implemented in motion modules. - -**Verified:** package consumers use the `package.json` export map and generated `dist` declarations; changing barrels without updating intended subpath exports can make APIs unavailable after packaging. - -**Inference:** the broad root barrel and shared transform custom properties create higher coupling than the directory layout suggests. Validate changes across adjacent feature tests and the demo rather than relying only on a narrow unit test. - -No deployment, database, migration, or external service boundary is defined in the current working tree. - -## Unindexed areas - -None identified. Internal feature directories are meaningful implementation modules but are not independent package, build, deployment, or ownership boundaries; local module READMEs and barrels provide sufficient navigation without nested indexes. - -## Open questions - -- The repository contains `src/routes` and Storybook configuration alongside a publishable library, but no separate manifest or deployment configuration establishes them as independent projects; they are treated as project-local demo/test surfaces. -- `adapter-auto` selects a deployment adapter based on the consuming environment; the current working tree does not identify a deployment target. - -## Index maintenance - -Update this index when the package exports, workspace shape, major library module boundaries, scripts, test projects, generated-output rules, or deployment/release configuration changes. Recheck the root router if a new independent package, application, service, or ownership/build boundary appears; only then add a subordinate `INDEX.md`. - -_Last verified against the current working tree on 2026-07-18. No claim in this index overrides source code or executable configuration._ diff --git a/README.md b/README.md index ee027cd..97f035b 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,8 @@ animate(el, { opacity: [0, 1], y: [20, 0] }); // Full PropConfig animate(el, { - x: { from: -100, to: 0, duration: 400, easing: easeOut }, - scale: { to: 1.05, spring: { stiffness: 300, damping: 20 } }, + x: { from: -100, to: 0, duration: 400, easing: easeOut }, + scale: { to: 1.05, spring: { stiffness: 300, damping: 20 } } }); // Shared defaults @@ -47,18 +47,18 @@ animate(el, { x: 100, opacity: 1 }, { duration: 300, easing: cubicOut }); ### `animate()` defaults -| Option | Type | Default | -|---|---|---| -| `duration` | `number` | `300` | -| `easing` | `EasingFn` | cubic ease-out | -| `spring` | `SpringInput` | — | -| `delay` | `number` | `0` | -| `fill` | `FillMode` | `'both'` | -| `iterations` | `number` | `1` | -| `direction` | `PlaybackDirection` | `'normal'` | -| `respectReducedMotion` | `boolean` | `true` | -| `onStart` | `(el) => void` | — | -| `onEnd` | `(el, { finished }) => void` | — | +| Option | Type | Default | +| ---------------------- | ---------------------------- | -------------- | +| `duration` | `number` | `300` | +| `easing` | `EasingFn` | cubic ease-out | +| `spring` | `SpringInput` | — | +| `delay` | `number` | `0` | +| `fill` | `FillMode` | `'both'` | +| `iterations` | `number` | `1` | +| `direction` | `PlaybackDirection` | `'normal'` | +| `respectReducedMotion` | `boolean` | `true` | +| `onStart` | `(el) => void` | — | +| `onEnd` | `(el, { finished }) => void` | — | ### `AnimationController` @@ -68,28 +68,28 @@ const ctrl = animate(el, { x: 100 }); ctrl.play(); ctrl.pause(); ctrl.reverse(); -ctrl.cancel(); // cancel + snap back -ctrl.stop(); // commit current position + cancel -ctrl.seek(150); // seek to 150ms +ctrl.cancel(); // cancel + snap back +ctrl.stop(); // commit current position + cancel +ctrl.seek(150); // seek to 150ms ctrl.playbackRate = 2; // 2× speed -await ctrl.finished; // resolves when done +await ctrl.finished; // resolves on normal completion ``` ### Transform shorthands The following shorthands animate independent transform components without clobbering each other: -| Key | CSS custom property | -|---|---| -| `x` | `--motion-x` (px) | -| `y` | `--motion-y` (px) | -| `scale` | `--motion-scale` | -| `scaleX` | `--motion-scale-x` | -| `scaleY` | `--motion-scale-y` | +| Key | CSS custom property | +| -------- | ----------------------- | +| `x` | `--motion-x` (px) | +| `y` | `--motion-y` (px) | +| `scale` | `--motion-scale` | +| `scaleX` | `--motion-scale-x` | +| `scaleY` | `--motion-scale-y` | | `rotate` | `--motion-rotate` (deg) | -| `skewX` | `--motion-skew-x` (deg) | -| `skewY` | `--motion-skew-y` (deg) | +| `skewX` | `--motion-skew-x` (deg) | +| `skewY` | `--motion-skew-y` (deg) | ## `flip(options?)` — Svelte 5 attachment @@ -97,8 +97,8 @@ Zero-config FLIP layout animation. Attach to any element that may shift position ```svelte @@ -108,7 +108,15 @@ Zero-config FLIP layout animation. Attach to any element that may shift position