From 10f370bf2838bb59400d4e5d5455cd9180750454 Mon Sep 17 00:00:00 2001 From: marketing <267783801+marketing291@users.noreply.github.com> Date: Thu, 14 May 2026 12:36:18 -0700 Subject: [PATCH 1/8] fix update --- background.ts | 157 ++++++++++++++++++++++++++++++++++++------- content.ts | 88 ++++++++++++++++++------ package.json | 5 +- pnpm-workspace.yaml | 8 +++ tabs/ImageViewer.tsx | 16 +++++ 5 files changed, 227 insertions(+), 47 deletions(-) create mode 100644 pnpm-workspace.yaml diff --git a/background.ts b/background.ts index a4e5043..ff588b6 100644 --- a/background.ts +++ b/background.ts @@ -1,47 +1,152 @@ import { Storage } from "@plasmohq/storage"; -// Create a context menu item -chrome.contextMenus.create({ - id: "captureRightClickedImg", - title: "Open Image in BetterViewer", - contexts: ["image"], +const CONTEXT_MENU_ID = "captureRightClickedImg"; +const VIEWER_PAGE_PATH = "tabs/ImageViewer.html"; +const VIEWER_PAGE_URL = chrome.runtime.getURL(VIEWER_PAGE_PATH); + +const IMAGE_EXTENSIONS = [ + "jpg", + "jpeg", + "png", + "gif", + "webp", + "bmp", + "svg", + "avif", + "ico", + "tif", + "tiff", + "apng", + "jfif", + "pjpeg", + "pjp", + "heic", + "heif", +]; + +const pendingImageTabById = new Map(); + +const isViewerPage = (url?: string) => !!url?.startsWith(VIEWER_PAGE_URL); + +const buildViewerUrl = (imageUrl: string) => + `${VIEWER_PAGE_URL}?url=${encodeURIComponent(imageUrl)}`; + +const looksLikeImageUrl = (url?: string) => { + if (!url) return false; + try { + const parsed = new URL(url); + if (!["http:", "https:", "file:"].includes(parsed.protocol)) { + return false; + } + const path = parsed.pathname.toLowerCase(); + return IMAGE_EXTENSIONS.some((ext) => + path.endsWith(`.${ext}`) + ); + } catch { + return false; + } +}; + +const maybeRedirectTabToViewer = async (tabId: number, imageUrl: string) => { + if (!imageUrl || isViewerPage(imageUrl)) { + return; + } + const storage = new Storage({ area: "local" }); + await storage.set("imageUrl", imageUrl); + await chrome.tabs.update(tabId, { + url: buildViewerUrl(imageUrl), + }); +}; + +const ensureContextMenu = async () => { + // Recreate to avoid duplicate-id errors when service worker restarts. + await chrome.contextMenus.removeAll(); + chrome.contextMenus.create({ + id: CONTEXT_MENU_ID, + title: "Open Image in BetterViewer", + contexts: ["image"], + }); +}; + +chrome.runtime.onInstalled.addListener(async (details) => { + await ensureContextMenu(); + + // When the extension is installed, open the welcome page + if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) { + chrome.tabs.create({ + url: "https://betterviewer.surge.sh/welcome.html", + }); + } +}); + +chrome.runtime.onStartup.addListener(async () => { + await ensureContextMenu(); }); // When the context menu item is clicked chrome.contextMenus.onClicked.addListener(async (info, tab) => { - if (info.menuItemId === "captureRightClickedImg") { + if (info.menuItemId === CONTEXT_MENU_ID) { const imageUrl = info.srcUrl; - const storage = new Storage({ - area: "local", - }); + if (!imageUrl) return; + const storage = new Storage({ area: "local" }); await storage.set("imageUrl", imageUrl); - chrome.tabs.create({ - url: chrome.runtime.getURL("tabs/ImageViewer.html"), - }); + chrome.tabs.create({ url: buildViewerUrl(imageUrl) }); } }); -// When the extension is installed, open the welcome page -chrome.runtime.onInstalled.addListener((details) => { - if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) { - chrome.tabs.create({ - url: "https://betterviewer.surge.sh/welcome.html", - }); +chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => { + if (changeInfo.status !== "complete") return; + if (!tab.url || isViewerPage(tab.url)) return; + + if (looksLikeImageUrl(tab.url)) { + await maybeRedirectTabToViewer(tabId, tab.url); + } +}); + +chrome.webRequest.onHeadersReceived.addListener( + (details) => { + if (details.tabId < 0) return; + if (details.type !== "main_frame") return; + if (isViewerPage(details.url)) return; + + const contentTypeHeader = + details.responseHeaders?.find( + (h) => h.name.toLowerCase() === "content-type" + )?.value || ""; + + if (contentTypeHeader.toLowerCase().startsWith("image/")) { + pendingImageTabById.set(details.tabId, details.url); + } + }, + { urls: [""], types: ["main_frame"] }, + ["responseHeaders"] +); + +chrome.webNavigation.onCommitted.addListener(async ({ tabId, url, frameId }) => { + if (frameId !== 0) return; + if (isViewerPage(url)) return; + + const headerDetectedImageUrl = pendingImageTabById.get(tabId); + if (headerDetectedImageUrl) { + pendingImageTabById.delete(tabId); + await maybeRedirectTabToViewer(tabId, headerDetectedImageUrl); } }); // When the content script sends a message chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => { if (request.name === "openImageInNewTab") { - const tabId = sender.tab.id; + const tabId = sender.tab?.id; + if (!tabId) { + return; + } + const imageUrl = request.body.src; - const storage = new Storage({ - area: "local", - }); - await storage.set("imageUrl", imageUrl); - await chrome.tabs.update(tabId, { - url: chrome.runtime.getURL("tabs/ImageViewer.html"), - }); + if (!imageUrl) { + return; + } + + await maybeRedirectTabToViewer(tabId, imageUrl); } }); diff --git a/content.ts b/content.ts index cf0f871..b2e09ff 100644 --- a/content.ts +++ b/content.ts @@ -8,20 +8,43 @@ export const config: PlasmoCSConfig = { }; try { + let hasForwarded = false; + + const forwardImageToViewer = () => { + if (hasForwarded) { + return; + } + + const img = document.body?.querySelector("img"); + const src = img?.currentSrc || img?.getAttribute("src"); + if (!src) { + return; + } + + hasForwarded = true; + sendToBackground({ + name: "openImageInNewTab" as never, + body: { + src, + }, + }); + }; + const isNewImageTabChromium = () => { - // is body styled correctly - const isStyledCorrectly = - document.body.getAttribute("style") === - "margin: 0px; height: 100%; background-color: rgb(14, 14, 14);"; - // is body has only one child and it is image - const hasSingleImageChild = - document.body.children.length === 1 && - document.body.children[0]?.tagName === "IMG"; - // is image src matching - const isImageSrcMatching = - document.body.children[0]?.getAttribute("src") === window.location.href; - - return isStyledCorrectly && hasSingleImageChild && isImageSrcMatching; + if (!document.body) { + return false; + } + + const images = document.body.querySelectorAll("img"); + if (images.length !== 1) { + return false; + } + + // Chromium image documents usually contain only the image node and no app UI. + const hasSingleElementChild = document.body.children.length === 1; + const bodyHasNoText = (document.body.textContent || "").trim().length === 0; + + return hasSingleElementChild && bodyHasNoText; }; const isNewImageTabFirefox = () => { @@ -48,15 +71,40 @@ try { // ); }; - if (isNewImageTabChromium() || isNewImageTabFirefox()) { - console.log("This is a new image tab"); - sendToBackground({ - name: "openImageInNewTab" as never, - body: { - src: document.body.children[0]?.getAttribute("src"), - }, + const tryInterceptImageTab = () => { + if (isNewImageTabChromium() || isNewImageTabFirefox()) { + forwardImageToViewer(); + } + }; + + // Try immediately when script runs. + tryInterceptImageTab(); + + // Image documents can finalize structure slightly after document_end. + const observer = new MutationObserver(() => { + tryInterceptImageTab(); + if (hasForwarded) { + observer.disconnect(); + } + }); + + if (document.documentElement) { + observer.observe(document.documentElement, { + childList: true, + subtree: true, }); } + + window.addEventListener( + "load", + () => { + tryInterceptImageTab(); + if (hasForwarded) { + observer.disconnect(); + } + }, + { once: true } + ); } catch (error) { console.error("An error occurred:", error); } diff --git a/package.json b/package.json index bc804f4..c12fd2c 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,10 @@ "manifest": { "permissions": [ "storage", - "contextMenus" + "contextMenus", + "tabs", + "webRequest", + "webNavigation" ], "host_permissions": [ "https://*/*", diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..5cbd283 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,8 @@ +allowBuilds: + '@parcel/watcher': true + '@swc/core': true + core-js: true + esbuild: true + lmdb: true + msgpackr-extract: true + sharp: true diff --git a/tabs/ImageViewer.tsx b/tabs/ImageViewer.tsx index add3444..b346c9f 100644 --- a/tabs/ImageViewer.tsx +++ b/tabs/ImageViewer.tsx @@ -65,6 +65,22 @@ function ImageViewer() { const [winboxCropperWidth, setWinboxCropperWidth] = useState(0); const [winboxCropperHeight, setWinboxCropperHeight] = useState(0); + useEffect(() => { + const syncImageUrlFromQuery = async () => { + const params = new URLSearchParams(window.location.search); + const rawUrl = params.get("url"); + if (!rawUrl) return; + + const decodedUrl = decodeURIComponent(rawUrl); + if (!decodedUrl) return; + + const storage = new Storage({ area: "local" }); + await storage.set("imageUrl", decodedUrl); + }; + + syncImageUrlFromQuery(); + }, []); + const initImageViewer = ( imageUrl: string, imageRef: React.RefObject From 62df5b9f7a9541ff811626a1859cbcf0787a0a2d Mon Sep 17 00:00:00 2001 From: marketing <267783801+marketing291@users.noreply.github.com> Date: Mon, 25 May 2026 14:09:47 -0700 Subject: [PATCH 2/8] updated name and logo --- README.md | 210 +++++++++++++------------------- _options/OptionsConfig.ts | 4 +- _options/index.tsx | 6 +- assets/icon.png | Bin 14947 -> 19121 bytes background.ts | 4 +- components/About.tsx | 22 ++-- components/BetterViewerLogo.tsx | 38 ++---- components/Help.tsx | 22 ++-- config/ImageViewerConfig.ts | 2 +- docs/STORE_LISTING.md | 86 +++++++++++++ docs/welcome.html | 27 ++-- package.json | 27 ++-- 12 files changed, 232 insertions(+), 216 deletions(-) create mode 100644 docs/STORE_LISTING.md diff --git a/README.md b/README.md index 0388566..0a549a7 100644 --- a/README.md +++ b/README.md @@ -1,164 +1,124 @@ -

- Logo -
- BetterViewer -

+# OpenImage Viewer -
- - - -
+**Fast advanced image viewer for Chrome & Edge** -

- Fast, Simple, Easy image viewer. -

+OpenImage Viewer is a community-maintained fork inspired by the original BetterViewer project. It preserves the existing UI/UX and toolset while adding a Manifest V3-compatible hybrid detection architecture that restores automatic image-tab opening in modern Chromium browsers. -

BetterViewer makes image viewing faster, easier, and more fun.

+## Why this fork exists -

BetterViewer was designed as a replacement for the image viewing mode built into Firefox & Chrome-based web browsers.

+When Chromium moved from MV2 to MV3, automatic behavior for **“Open image in new tab”** became unreliable in many image viewer extensions. -

With BetterViewer you can use various keyboard shortcuts to quickly pan, zoom images, edit and a lot more!

+This fork solves that with a hybrid approach: -

- - - -

+- URL-based image detection +- File extension detection +- MIME/content-type detection from response headers +- Navigation event detection +- Direct image-tab DOM detection +- Automatic redirect to the viewer page -

- BetterViewer - A chrome extension for better image viewing experience | Product Hunt -

+Fallback remains available: -

- Screenshots -

+- Right-click image → **Open Image in OpenImage Viewer** -

- Preview 1 -

+## Features -

- Preview 2 -

- -

- Preview 3 -

- -

- Preview 3 -

- -### Features - -ℹ️ _(Some features are not available in V2 yet due to Manifest V3 limitations, but I will add them back soon)_ - -- Zoom in / Zoom Out / Reset +- Zoom in / zoom out / 1:1 / reset - Fullscreen -- Rotate Left / Rotate Right -- Flip Horizontal / Flip Vertical -- Crop Image -- Photo Editor (Adjust, Draw, Watermark, Filters, Finetune, Resize, Export As PNG, JPEG, JPG, WEBP) -- Download Image -- Upload Image to imgBB or imgur +- Rotate / flip +- Crop image +- Photo editor +- Annotate image - Color picker -- Image Details -- Change background color (Dark / Light / Blurred) -- Print Image -- Extract Text from Image -- Edit in Photopea -- Reverse Image Search -- QR Code Scanner -- Settings to customize Toolbar +- Download image +- Image details (EXIF/metadata) +- QR scanner +- Reverse image search +- Photopea integration +- Keyboard shortcuts and toolbar customization + +## Screenshots -# Changelog +> Replace or update screenshots here before store launch. -## [2.0.2] - 2025-03-19 +![Screenshot 1](./docs/screenshot1.png) +![Screenshot 2](./docs/screenshot2.png) +![Screenshot 3](./docs/screenshot3.png) +![Screenshot 4](./docs/screenshot4.png) -- Add "Open image in new tab". -- Bug fixes. +## Installation -## [2.0.1] - 2025-03-11 +### Local development -- New Annotation Tool – Draw and mark up images easily! -- Bug fixes and code cleanup. +```bash +pnpm install +pnpm dev +``` +### Build packages -- New version of BetterViewer is here! -- Completely rewritten from scratch (React, TypeScript, [Plasmo](https://www.plasmo.com/)) -- Using Manifest V3 (I had to remove some features because of this change, but I will add them back soon) -- Better UI/UX +```bash +pnpm build:chrome +pnpm build +``` -## [2.0.0] - 2025-03-09 +## MV3 compatibility notes -- New version of BetterViewer is here! -- Completely rewritten from scratch (React, TypeScript, [Plasmo](https://www.plasmo.com/)) -- Using Manifest V3 (I had to remove some features because of this change, but I will add them back soon) -- Better UI/UX +This extension is built on Manifest V3 and uses a layered detection strategy to preserve auto-open behavior for direct image tabs in Chromium-based browsers. -## [1.0.5] - 2022-09-14 +It keeps permissions focused on what is required for: -- Add "Zoom Ratio" option to Settings. (Thanks to @Metacor) +- tab/navigation tracking +- content-type checks +- context menu fallback +- local state storage -## [1.0.4] - 2022-04-19 +## Keyboard shortcuts -- Add New Photo Editor [Filerobot Image Editor](https://scaleflex.github.io/filerobot-image-editor/) (Adjust, Draw, Watermark, Filters, Finetune, Resize, Export As PNG, JPEG, JPG, WEBP) -- Fix a bug where Chrome/Edge adds a duplicate image (Thanks to @patrykdziurkowski) -- Remove Photo Editor [Painterro](https://github.com/devforth/painterro) +Default shortcuts include: -## [1.0.3] - 2022-02-10 +- `+` / `-` / `0` for zoom controls +- `Shift + Arrow` for rotation +- `Ctrl + E` editor +- `Ctrl + X` crop +- `Shift + C` color picker +- `Ctrl + D` download +- `Ctrl + I` image details -- Fix major bugs (Croppig issues, Going back issues, etc...) -- Add [Firefox](https://addons.mozilla.org/en-US/firefox/addon/betterviewer) Compatibilty -- Fix Cropping issues -- Zoom In / Zoom Out is now smoother -- Fix some UI issues -- Add new settings -- Add "Default theme" setting -- Add "Toolbar position" setting -- Add "Notification toolbar" setting -- Add "Show/Hide all tools at the start" setting +## Supported image formats -## [1.0.2] - 2021-11-28 +Common formats include: -- Fix minor bugs -- Add "Reverse Image Search" -- Add "QR Code Scanner" -- Add Settings window -- Fix Shortcuts (Combo keys / Ctrl + Key +- JPG / JPEG / PNG / GIF / WEBP +- SVG / BMP / ICO +- AVIF +- TIFF / TIF +- APNG / JFIF / PJPEG / PJP +- HEIC / HEIF (site/browser support dependent) -## [1.0.1] - 2021-11-20 +## Known limitations -- Fix Crop problem -- Fix random shutdown -- Replace Imgur with ImgBB (Many users requested this) -- Add "Edit with Photopea" -- Add Contributors in About popup -- Edit in Photopea (Thanks to @bbbenji) +- Some websites intentionally block direct image access via headers/CSP. +- HEIC/HEIF behavior depends on browser decoding support. +- Firefox MV3 behavior may differ from Chromium behavior. -## [1.0.0] - 2021-11-10 +## Roadmap -- First version +- [ ] Refine Firefox-specific image-tab detection +- [ ] Add automated end-to-end regression tests for redirect flow +- [ ] Add refreshed store assets and icon set for OpenImage Viewer branding +- [ ] Improve onboarding and in-app settings UX -## Contributors ✨ +## Attribution -Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): +- Inspired by / based on: **BetterViewer** (original open-source project) +- License: **MIT** +- Icon attribution: **Icons made by Graphics Plazza from Flaticon** - - - - - - - - - -

Benji

💻

Patryk Dziurkowski

💻

Metacor

💻
+## Contributors - - +Community-maintained. Contributions are welcome via pull requests and issues. - +## License -This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! +MIT License. See [LICENSE](./LICENSE). diff --git a/_options/OptionsConfig.ts b/_options/OptionsConfig.ts index aecf49f..b9585a6 100644 --- a/_options/OptionsConfig.ts +++ b/_options/OptionsConfig.ts @@ -116,8 +116,8 @@ export const config = { }, { key: "viewer-about", - name: "About BetterViewer", - description: "About BetterViewer", + name: "About OpenImage Viewer", + description: "About OpenImage Viewer", isEnable: true, }, { diff --git a/_options/index.tsx b/_options/index.tsx index 34a7c5b..7a8a9e1 100644 --- a/_options/index.tsx +++ b/_options/index.tsx @@ -89,13 +89,13 @@ const SettingsCard: React.FC = () => { return (
- BetterViewer Logo + OpenImage Viewer Logo
- BetterViewer Settings + OpenImage Viewer Settings - Customize your BetterViewer experience + Customize your OpenImage Viewer experience diff --git a/assets/icon.png b/assets/icon.png index fcc7e580b9367408630f037acac911cb911a131e..44630379c568c4dfcc756e20946fd46c8005a53a 100644 GIT binary patch literal 19121 zcmXtAcRbX8{QsOYvO6Vvbe*P(Y-i@I6p1tlWo3_xvz-<a*%Bg>QOMrsDw*d<L*`x9 z8FBW=`n~V_`~Cj#;PLr<-mmxT{aWwW>-~N`MO`)4=jIURfFOw5&;WA{f|$UcOwa*V z@N3oo$3O6k-OJz>7J_)bFn(Zdo(1;cq0j@}n-9!99UtKC`Zz#19PXU6hbz|Zu9w3( zPamiB1vOy^l7tK~+UEWle@Ae^ch*Aom-=sXB}fPGs(r$<wQ^M)wTH3GX|<1{ofE1J zUn$DF52CINJ)dGTOxHca{pO$^{$tFi-?lQXaFYO|(O;EPt}ovA&|jP(Dpr38@?F?{ zja}H@^3RAUlgeDt>;JWZZT@}~`Nq-l3Gt?_6-6P3E*#Jv#>@7UDKDh?$lC5LZAxjx zX*kD=%?gj~$w*CCW<IS$y)2bX?jg;J;@)D@+f_#j;4Yb1^_hK}XoGhu6d1-QEiH!S zINS_h7_zS}^b%8ECNYH5H5DrrU~ULk4{2V2{9p~4*tNZ}s0l@W2q|RmxP=l~Hw!n5 zU3QIXe(<K3$Bm_WZ8vZ_jQ)VU7DzhI=Xx5#Fx_)J6h1(liP#BL>^K)-ct@b)qOJN> z@AguWOe}lWC(M`@3*O+_zt#ySh$imSEv2$|F0G&24Q3(gQ~ZEj6>vq0PZrSm_pSel zrbz9<+5@$aa?HepD*FrZgeLfT_<5L7I0yI9NYQi-C|>8~fDH8-^$PJTF+i)X|7t?X zBjSYwmQS3-do-&GiUIP^8zwEES82(K!MHG%j;H%fqqP|0v7<0IrXz3@c#jMJ!-)(0 zP=Xoh!()4${aC`B^eSEQ#v0T6@U4)3KqCUs7|4|f<_mK4JK`nP!McAf`?n{Oz0i*u zknokLMjO7}6M(sJi3Q&ho5r8$Hcep}Ht-Q67!>(ID|r3zty!_ST2q*0nXO}PxCnmE zFqY;z-^5(V@6X{c=>J=#hJqE3*EWMm#ydFL;a%|?@qfqqC)7KhGIu1iY``{DY3l*x zV+lw2A-+?NisJrZ6kql@no|5kEpvy|(~Sga)>$<gLP!R@4-AppD1~dpj?NhQHx0^p zv3b?3i^hEfwBOh}vJkHm+YF4Sy4G~CsM~`EWP#d4{@0uY3<L|IxT~@iX~YP;$(w;~ zKHhEcZZi|>5kr?jmR^HNj;_tOZfGaO?0tPb9%<jlNt`FDlk1L9?xJc6p@W_zw<C*& z)D@yZvoof=NT^n1^9k0YiY}9oZVnk(q}@Vvto_S6QD<#~>Mw>uxp%&)^e>>FPw)Vt z^E)acHu*Z9hJBzZBk!6Ul^@)EvVJ7a?J7)C$ia~Y*+|wsHVImc7PS#r6rftrhWWsx z1VENblIE>t-xTiX4#c3;qr)x3BQmf}gf9k-1yCGuHHIE`aPzoK7gjW0xsZ8Jr1nY# zpW#(=s6Bh_?D)3)A}<lu<Bb{nz`Du5c!*||OPAquKMkSW9TlJ1EA3ODFY0ZG4yhPa z5Oe5Q2AYa~j!EQz3~y1sHH5)~Sp@&6#2TD)g@y9$80a51Dgt!zYhumY{lpvJ(4p}% z&ahD4oqTLbD^4(ql^^o4a<pI#PMes}P}o8KS#x<o+{naU0ld}%!Q0KI|J*mEQt(Tm z-y;n;gz@`Kp+(o>KGLV53GRQfW4nhJONsV?SyTu*oX!;18{guC0yG8X8klNXl)vDP zAlONIRC)&1WRvGVTZd#S22c%LrAwK*m<v;;)c52%cfzB{umA!)(#BD-gXF>XE2q^4 zwNL{8l|I1R?e>x`GnN_%`6Q+BC#Yr8gS6^^G7>_#QTx05msj9Ei5z%Qd&ktoVO_Us zx-@cZ<P0i;<@JgfrrbyeQfVO>%T@%1=bMh7M;c<obsg6u)2^(D>6PoVXz|EYT$I~B zVJo(%K?%U1lB_c&7Gnr`L_VxAQ>2O<T4eLAR|z1=C*+FnQKhA9@gUQ3#qlpMRPf1d z!#;{C>>(3g$%PAa|IK$){DBkf;97%P;?kN}Ho0XOE01ctMCByc<%h7v+ZM7(>XF<Y zr;V^mV`7>knaAyI327rkxWlzAj{~85pGl)EJA5xE(9w}C7Tk;6v|%yAqjqW`6sati z&b;$%g3B5a@3zUgs7o8xplG8)PD4l%Y4nQE2b&QeWP*DPDjKf|_?!7Aia#)${%7Be z3j47c9Vu}P-_ZS+NA3(*^0j<%e57o}3VvTFaR-A^E5g4}rlkP2z!@)O<eVIBVAfiI zxyN1dR28}H*tE%Qo?~#Z;sY`jg+wu;Wr!03p%N>F3W65}v&HX$HBFHIHla-Bt^w(q zddV(6OABei9h}Jugf4cHp29TY8dG3J2Cw!6HbrPw(R9gWz0=Uec9LU4#-Gw-LAt0} zMYxg*?bkLBGUEF|t@f7#Ys71SZv!<Fl(Ne0bSbg`I>0X1MMpQ$kJ{GK)sRToX|{!V z^qr4HoS<RfL9GKX2L!3-sA7bQ$VmI&NGhCMCrr`y$>e}~NPk7CJw(ITx!_Hg2epY@ zmq&Osae*7=Z|^9<b|kme2IJFZZyTQ$LdL~ey%UFcNp1%gHSv4P(FP^k#}-*=Rt<E? zIz1Mxl(Yd%!l7OA2C!KaDuqc&l~xqO)**EoDsLxEK`&rt49T#ksS|z4b=Scp9Nn;X zKDma66aLM@VTgF8SD0n3H}Am^elUbc(qK`G{k0JtxtcHP|C>ahq7BYng~e%y=x>Iy zZK_|LR*8)?ID8mto*j}m`0_*Ot*6J+)$Y}OvFt--7)&2lV$mDKeY&LgTP8_3$?b5* zm*5AFOC#H<jR%IQ8Sgj5P#)$GGl^t;T;+RM3NT=#Y#D!Tt4hsRT%0m65GZYcg=kc; zB!FP=D<rNs`jr4$IZTq0j_ZoH8Zy7IhY|70!o1S*6*b#Dd;+H-CR;~3(`)GI78!}; zvvVNkI<6a2w81_}luR4YH#FWnv(AtVTN2ZYmjewUY*DKG&?8$%8~B1`oyT<yrabpR zZ5v4gtTU+)GDu9@g?n+{Hav<P(>b~r=D03I(ayQVq9siF>qylnU?U?ZYJ;gtj_cRK za|0HwXaB0#cf;wTNF);~=&q+ig(u)jVU}PVo)*HpnZkJCW3KstyqiluX!=GR54%vY z&oE<ymm_YD`%`F)c>$X(v`V(Ypso>SGQMA(_bz~xdE~ZlP#YMt8C)VPWHfxmMar1L zdU@rxRTu3jDi{pPfi?J(%7zF<`|~9hqU`F~Gj%_4JP3rLCDUdkc0n9GH(()}z8q-7 zYi845L>m0?h10#s>SJhw-v#05hiN0w@QdmVeneFCIjSCQ_z>aI<0uY1NC+H=cGI>J zi1=D(c!?iborX5JSpZGjISN2MacUmdFqpA?_S#{Un$Ng6nX549<$yd@$~J?c#{|<g z;#YEAG2zi>$_g6xYTzW5o#Eya4`qqR92NU;2Pr=FAi^T48n*BL8=z2uk07~4(j_$} z-C(wkJRqc{{rAGx6Sh}VdbZtA#S(({d4fr}0|>;@)FUmj__2({<QHin!kd{4*^Xtx zvV6$9pKx(*U3E-E(kLql{!C3Dfr$5-W-S2=o<|!fPMQPa72yJS1j7*x3PhRD`I3v* z#88$#?*KpSsQ!N@YrsY@7oE`^>P!spd7AN(`M%><qRmwhJdkaEe2cav(!8W7CTLU0 zi$FgJOf66Vrnx4D6uD;ugg^`L*(4uDBIB1><f20w5OXR}2-}Vt+XMy|8yU&`4(?xp z^{Asurtu8{F7@DDhOsk|k&$m*PI#4IOGa^Vmm?<+;?pMKxHrJ_F?~w>n`SoYeCRT1 z2rmKASH&)3Fi5%&l@c7${`faH?BzfV5#F-6e<ilGKd=MqUF@pcatJ<3&uF0F;v~No z#mj@7q>Cs+xrMr^-o!q8d#=EvFz;Pe%Bz&yE|zom=?mF%-wcCrY+~wStGCZXQcu1f zp5(o25Q+eQJwGkfvH50P@P=XvyTiE94aL|uPx4;xmts&CUxi0!VEGA;n57h1@M+w~ z1~z+EGj&-369XY$ydtxT6=k7^EJcc@7v_0Zh3qcrV+VhyWn6F(mTSB0WMAeNc_cpc zIwYV<yB*BNelddskM3O}#Q(~icJ%F5O<A!1^zPr;2U7Lr>uwQtV;|Wwl)TRg7;B`O zN*$|McSA%aQB-Ieb7;)Ld!|6>LE+oMw74Hat<}5N8!KIf&a4;bG&Ov|p)#<SC44yq zuBc>Tk7ww5hgZiRjQ<kctAcw$Klq4$3uxdt{C&77p`x9bCgkdR#y@z)%*}In22Gab z7vTDna7w`E=js_j#ka#aQ3QL09#xuV<satHt@V}@lIw!MW*uEXM{_+-EAycUiw~@# zex6kzjC1{t+d+=XuU#Asn00u5QhWg&8@ah5>Xn8)_XllIpJNT}$Su+d*mj~@!4PR= zPCWZv-Y;BICI6Iw&st$BcCs+lH0}nKG0L|ByP!|dd3&ZD2sx9p@xWma+;&}OmD}MW z;tn$l{DM<xW64$?v2Hfna7%`F{#Gm!x%U8`s!Fq77ek4~OG6~LlOLJRZgDDnxp{Mq ziPt?iBlfj1#rwk8aFo;18##}h#sU)VFk;E>jEvGVBY5s@Xy=I7l8DRvh}dx1KXHo% z%W?FjR&J4N<a}D_%kQn^MKN8>&So-pAsR4t+6OS!ls;k6%y(@_1h<qviMvXvrr?r3 zbYKIl<i<HlGM9MVb)^&1JwWIK(aRiD1U$_UmAVrHqH(N;_T<WN&EB8>>WOZJiZ=4Z z3N0if;qyI;DF)Rr8!nfL-413GDk$KGcwtJwu{`YsUwFLg$xVN~EcUe_YVyQla<pdt z<U?c~O_nz7OVHsmx95Q5wk5r4=%UMdO~1PCxbBfw&?*07`Gj+g^p}#OHQF}I%LuuV z27VzeD!5eoK{z6c;fnEUkMB0prG07_M#V#$c6ff7w@u+c5R-UMjh_(+i9Pk@1Vgw3 z-=U0!49;C+C)2dz2b?ZDI{E#9Tf3bNx6GQt?avm@^}esGNY0Yp;{J&k-2~OLqHt|D zE;9T;2nao%Y#Iybh{kVCbK;JZqnqbfM4qRVScH~O^o!p2Tm^D1r#&U;%w9bELkDuS z;P?PD2Kgt?MsMqhfZ!E5f*q!{WqB!hyzji(?VDrhXOZ^$++MG+3wXL@8{fJ(p8lp) z^T82%a9W$vc_L0AD5<2WyK2X0Kuo1U?HY<LhHdXVE^_a2HBi7xcqx!(#L#!E?yO&W zE~U}Ezs;Lt^cA}|#B=}`V7HB;A8h061cKo(FwSWQIfZq9+Vog|7ya#-Z}aF&_UZ%& z7{70NNZY~qzwK}jxr&Pv?bzc<EYKpiZ3+FLPi@05wHCsZYA`Nef9t{{N^xUEYwRQE zMkXYmHWuH!A~tsa;tk-tr-;oAPAmyHZX>_qMX_T?UZE{(?SAeO>>>@;ciyLEPNQ4m z!KY9S)1ZMmMm12i4mXlZuxsh8AH4EmxQ2}5LUhDlqqY%rL{FJB%<+(aDqYm4HbSX8 zzbv-{_xv{)aO}bQgRR)3$bltmxrRPmq|OsY#79z_Luhed=ABFa3=~OiilbkQS2Z_9 z=~tybG&onMaQP6Eju`~musQzYIU2G3eK5js^>}bwWO4o(0kfe&D*9=peVa3pvdObl zboDUgsK~x~f}%3vmCWW>UKpBA7c5JezOp!x^5nm@1P_redRJdL$pKL{@fRpZC%j&` z1+r2`ChEM-4(xJptDez9-Qa@nb>j{k&<57x1d~|F)ZwYAa6UihT5bEZgv&-firK_H zWOT#m9CBbqNDlo4cYw|Ub>t!LwjYh~cl*x7wIX)RNv+vVhz)HS{GV#rLdVdL`=9oc zO5i1nY1*UHwoaVyi<HJ1T-8!b7BIX<eoYsMHw-ZMs23<*Oilby$oB4jd;iMhZxDs^ z%;wbmy=j*y2;h#PZjPhm#-#!HqH}@~5@o+?{NqJax58hSK^j94J)&yl@Re)O%UiOG zXC-=4_6iZpMqg76$Xl^#+)GQgHtJ9q_vNKkx0$xSJMWj&#b0;zm#e!fY+XauWE=?o z)b^;t8Vpuh<Q)ht;kv9lVnIRp+_r1`L^zhJi;4(-U+PXeEujukpw<BY5>b7yXQ6-Y z(nnfV=Lshh>{^*@I@Wb6ZUd7NRNFD>B)Yj2<n(h<MyPe6?jK53_oAhc-YXl9iWky( zNq)RU3j7v*DlUBB=8YNjLnwXrOcj?IYJ-c7@T!~5u^8CKH)3k}nwsIruU)ik@8p)t z{6cnp-d=5KYGe!fM#TVUT(>yBG#9u3#^QS)p1$CDr^DzFOxLGRrd;{*>*W6;iq*dp zM}PkQb~(r-pDx&^uMQzq&bT%~1GBJA^y-4<j~~>>MlsgB@m30=n?r7DC&w9EDV&fo zLu;p^IHCPJl=_4lzD8fXtz{8WWu-4~-FhdH5F?I14?9-AC@S>$X|)~&F>!D$P#xnl zU_doX3pLQ=#1nR7D*BR-KFVF%_nPUQJDM;@_=R)vXtl3rqb3p`b7|@@^%k<8Ft6tu z8RXPL)m(v(W_GaIf2f~Ek8jSU)i*Q0&u!o&0dI+zo}PJI`LP9f*b+?wzkR`X<?=ez zDDv|4r)?v=YG8e^e%!HX1w=;xEqx#_tv=v5C%(Ch+9YK=(xgr}){X#E5ROGgh6&9X z_OyevCX>@DBPz(q@$jTTyw$_wcV$t{?Koz{5}j2J-K|n{bXvrzh)s*Wcg)d1JAOlb z(N`>#U!VXwh!7RJeMP_@IK`px4b~8wjt}>mhPe16>>@cJgyFxpX)(P2-la{$HZNpn zSs~1<l$j|Fl$pTY)1Bv0Jr3KI9tifrd(_g01m|qcyZ;pTwyfedlK!4NE4?nJ&10I= zuY=*)$Rj8!%4j!#^_P%Qqy}9&^89S~AmYabX#DBy8ps-+!#y~bpK1$0He8#b2~sDL zVwS+zH(+QiviB~Ym;&<LG@_LDh)Ma}<K=Jng>3yZu9h%qVMeKE9TnSDYR*Nbvkbtq zar+1h3-e32;;S>cqYriJZO2L?{~Z3U)}Y0KCt#yBMO&I$ve+kI5fDd&nGVL=Z9Y!p z<{s12UW0-U2p;KeYDt{Q%^wTeN<Y`OIOfxu9HY80CxujTR_<Wmcyz=Zwm5@dI40gL zj7^{)V9HSRd*uk?XqX0n%N162_Fj@BlK^X+u3EZAAjej~)+z{R`W?;{tr^qkhmntm z(!2kf(}sV28b(Em<9o7a#>=iI*|c{YJ2BqCsn%cmz10}a@S{2sEKBt771ry(Utx>i zK0S?Fd?~kJ5Bzno_D!y!nd)a?G3?DIuWs$xddU11$G;C}f7BT9xLwz5ssP=V8=X%A z!o%d;<@5T=_<)IO_h=`OJxw<6*gp$+B(H$61xykNS1eFeo;SohTJTsYy^JtYzN0qD zrPxnj7CT0}ETNuusB*^y!@8g+cLqzYdb{%V(G0AXz4w>5?1N8l2M$lNRU1`u^?o%2 z2@9CY;pAe;gJypj7QEkHbYa5hqqEP*<$a&;oy+j4rwbza)Fm!$aDG1x(j`%^TlKuj ziw%BLQWJH-!RMp8lINb8k@Me5_U00FQA$=0j?QA@2_C#eHugo7HhY%0j=s;{+wZ|` z?d&?soONSKD~!l{|1_$*IQ;urXf$i8-|%sx>#uY#<7g(i`S}xBMz>508I#@_I0cdZ zGE>JMh#&uUp)8n-W}NYazObZh^OZ%XcG-OX?OEib<zIw1TS;%f!@bO2*_=SEev&(v zUyywOen+UbB+K{ImuR@kfEmW;hK5&2kxi1Z&faTzf*#VvyhCPGVTF$(d(XM=qio}N z(h6g%_BW_=H!g&x)15a{%q5WD{3Z(pWWdCPhOY4kDxwnVbC;G^exw~ohSv_0^xiGA z6z;9oiFfbysIUZV1^@kfM&YQ8mZ$2{WyhFrDP2gumlv-MXDa<<qP8B^w7GZh*ULgH zxjTtJAIf-48)yViO)@sVowxG5wnRo~(@x)?s7!ZkelnALVmlV${A7zIc;=x<)y#`X z`_I=y+}H4L``}(GS5pGTqoUPP+XQ-=-*|S{?|ZMFw3g5q=P(wP)yVX0j%;5_f_aKh zpUA%kO;2dvwKr7BLeo{3Gme+$&5oU_2pFoY_;0Zde%V<sJ582c`wk#wA53i~Zjn^_ zvrmP?af81Lga3){9^#9CF0!bGhw(#>e#gD;4SJ*e&ZPya(p7egHy5tG`0U%)&b~9R zOMfGIUUQya6WI=Bx;a*`E=R%d^x=L=em1y#2R)8_rFuK9+5HLq<QoNo8_K3(v+1zF zVUR6q>6-`y@%+MOH>JHJTc`%r+ic%74Ly47S;U3L+UJH}TCd(Nh<e3$>jq5Z#fBjq z*otheG~W#g)$t2~-Tw7Hd4Qtan_&5{u#Rm(MGV{Srq9QUn6;{*Tb5>DQ+9(2Jl$JZ zH>>O-VyP4Hhm`Gh<jJC%F?V$;9V#%bXnd9^Juw#j+!d6sq1h<>RX#IbPpi+5_@mi& zz9=jh3n_$`-dPs!e74$ie5n4A`iI{QPXzo*oI>XP0^JwG&SYXq!g5b)UOzYv%+mNS zVO=Njsw;~gnx?wF{WknCL}#92Nxn4Z`fXid=TCAz(^j~MgHvo)YwG#N@S`kG2)PqU z)eFY23xl6*S>EvaSaH^_=aj^?&g<WM#+MUmF8B36|D7k-J=qQU3_{;N)1F2FhR^f; zy8C#4mqc!H1Ld<^^*QvGn}*NS<lwkwbYS2i(olVdzS7w|_2@8q=d(+-OO-~oe<$iD zoYURdv-UxOfep)&iDR<m_p-2!N3GA^PT!pDdT}+tHj94pmf5wNEhlK!9ZwS3<hLxC z%3Uamd!F4)v$sW>9A2shi)OvtHU={JWXT$zdvhwIA-maRx(4I{rdnb%Vj|Ki(s!HG zK8DJ^@C;R1Utt2K7<>NC;<?t;yaxwUxh@9b1U5ccwtp^CAml=E^yONYe*wet+t=3i z3~sI_WUzUWW;gv=h%v-R+W85?W$)?}G)qFC*8e(AF=e_Dm)gUS%F|l{uGelJaUW?; zwUG{aygT1b$Zh=e{9EGY@{@kK#+zqYQHM*gWOcs}yyB%$Ez9O@YCJ0cfm9$UTf5Zi zolk)RpW@9V>q<JT;kQ0{Sy-_Zmy}Wd(S;jV5_<ec*bBXsBv1fRx(!uVw0E}Su?tgn zA&Y=34r&JRn4xizhYB(Cy}-v3#|HXIXOUaiTG^%=lcV3=|Dc)9_p3|7I^Y$px^zv< zLF*YO#}?oT+q#(;tRFvI{X+%!txUt81hSr|@mBk#yGBx1Ek)Lsr{Cp$C@FbP+QEOz z`%=670}EVJ?$kA0n1%29gO#pS35V;xz{pRXYVV>&3s`m49m?O1Mb^D%6P(OI&-&jA zV<9RKW!rc#tgiZY+`xJ}J3}nX;ugfbE^eJHN%w{cn5bMyY)}Ko7!z&hchcOqbL(<Y zn&)4fzvGqp3|gAWB-d@}Z)*WMVN4X#O;o%F+o0vmYA3m9+y^HovrM{j(qW#v3y;nG zzyBB@i7Q>t7Z2<k9pRs8-M`L=cxz)KX>!)I!YBa>mb^RnO{3Qa_7U<AYDGqg>i!HD zwjQnuuTmHq=x@|??Gd|uljLld@AYXyC`0bg;qKXu54rj263vTF)$)JW#H0>NJ<$zb z>88_K5aSH7tt4R=I&(v)1t2y~!r1V4(=JQ(Wwpj0IqiZoHLXd!vKCa}>dN6(V0-_r zZ2t3C#J}EV%I<#;8;ff2<c|zrJbJfj=Rt?f%{zA{(U-FIl9N_4yEHy~iSbAc{KWW( zYtiE+lr3Oh$3LomFT`B?mOTBYeo|}M#dvS<*NCB$iIV$BX642M@cf<R`K*M8$Y-3- z1g~8+FuaS%HF_%hCKv^hoO}1SPIg92$G!eoA2JzyM9;oDtjIAot))AaV6tL}8ZyR_ zuZwO)w9V2QWxm|ST(d~BA^!Mdm!=y0fqpXK=nHpi^5^+ELE^c|_{zf2^SIKG*cY$Y z6e*^t8Y||;H;}T0P!ULy%8PRRPHdFg{6*`vsyEH^TMq~nOU3X7=(~S^aUEI>!s8<i z;%0|<mZMW8dZKdQa&L}w=HLH&e@#r+r;P|I{xht`UH+m7gygrOuAUSPJ?ss(j*|UN zo9;}pVZ!oEHsJ}fO|GHTU6b@J5F$_f#=<cerZwu*)B@G3<7mBK#YH7!lOv#<jT^pt zfTXd^`@#Yubq60oAbwjlr?x4cHCm6RQGIE%x|M#utjkS@RbrJY=fMSQOEmelhli!& z3u`##&N89oU994Q&HhD*awUFT_$n;>`#uIWzSkJazUIyr(zfVv_ou3#($DSKqf7l^ zAfMeLW_<XHh|e&uYkrkqUA#O3mw0yOZfoZIERod>^9g10-=WD31^sm>gXw;>Jfh>} z<F)06<erHK{rmAZbVodXnbQR)a29WE9Eed7d!OQ2h%*CSNMzl8?aAAI3JROC2-S@n z(w~AO;%d<!Vl>Mk|1TF{i1=)<ibdP6*C?_VowvhpTg<;-7SkD<|EOrqf{(QC-knSB z?fdx$t#@DjW|?^tlwb%}irQXRq&wZc&O&G#`V#E!`N7UTW{Sz6RkR7@6JpA8bKrjM z#Bi0PEPK$G_z9oKCls5<&<|VsogJsFce~%HLnm^;{dWTF)ue{koGY#@w+xi-QTZ2a z``+KZ|488fdjXnNDj{Ws?OPbs0_k~!#ram;MqpCOiRurRRvOOwSd~_-F?h*+O(_e{ z9Gp2PWrXwmqty`0netrO1?KfELJ}PQ--!|zFYq70J#RN$T`%|A4y4GUUR%4){e(** zg;u8DCCgXV+*7`D%9`_Z|M&0di@SW6cJ3e0!d!S?SaHQ};8E}IZ>?QH)u04g!urE{ zYou*o)hHwR&>O`;QL(Q*D6&ZRy<ZB1V+K2ocMsTdU7bAvZp6Av-mwC%zJXbX>YJas zZ@UJ!#rdC7s)%0<gvorh6GTL%HS`k-zV9*BPkCCV&eqsW_`k!03Wojn>}=+T;(<xD zo}2VY(-UArfMIKMDAM3#V0W$4JfF-1mIrI7z<}x^<j>TLZ#B)dfu5M}oBm|=Q<!hV z)dUQeI8_(t=ii{6G_d8FgT4GK8yVRG@((3mb7^oUkRps8yh+IK0|I~Xg##ZY{wUIb zORau}Us%B+Q`W@&&K%HG8#DePf%1Gq5F9ZtXa$`y@wlZ^-gW!JT_YXtWHuL-fC**b zxBptd%&9{R9k>H=q>*2XgB+7SQ>-eX#U#rk*+b$8kAM9o(f~8>=0e@dOb;<h>4|df zC@Gfrt>oRTLa02Ib+m}nFXy}3oEiCcvgD_c44fi2iTyLXFh4m^#0?K|#>7hT3hugq z8X%!OdE4(}iQfylpvq)gCkNkczLSrXG<XH)&`%;UCZ$3fC3j}gdSsQ}(av)9>jXQ4 z)tGLb@qJ{%Q<h}@zZ(8T-1Cgp9~POsl8+Q~Ai+P3VMYwGc=)qikyy6F>Tq9Yn|-Nx zO{_MdI(`;*Fg|J5Vf>70c5B7fP$lXrs{=+{W*EnTh>G2vFD4D;oV!m+`8(YD$@naL zQYCkfjt(&Che5vxmv11$=~CWxp}rgIV9Wi!WFr%wD^e&9A%s58$8a~+x`OkdKBv9v zHL!#k;dr*BE#sreZ(jYcQa?_VX!0?!4G!HT;2P+Hd{=Zh@z*G)FsPjr`pBn$gCX~) z!fHuFw?92eG+7tZ$;p@JJ-L*55%c-%-KOCNk2JcV&*Ajh_l2rg>FB2z6GL&vGRFM_ zhgjF;75-^*>-U?MZVjFO7qW|q%`w-3#xm2&YU-jwx?_G+%2zZuCI2chzTMCuGnaR= z8KQ|!>O4DjUikB7`Jc-tCCG2@9y@vN<f@qF`e1#7|Hm<YitJknBR`AfH*)8)gAK~) zC;7zkSb+1W{r>p?e|_7ptlE(`nQazq$;Mma0c2T+&6AF?LOr)mTy|WqjXFF@bCPuT z*zS6IT^{F`Q?|c2dkN)V?Q*EUN3{!gI4YLU$+2o$OS0o3eBK=#WO4SmQ$7=>-Vy0G zU}pjO!SYn%JCJu6PN*o{e005k@UteVA!`Bi83!Wrw>*d8!0zpKTmT{0K>o*Jh=pKg z&^Yfl++&yCUv7WHL9bsLClz?J{C$E{!)c*Aw_C4&H=&g$I=Q^GJ-BeI;c`qEM!vG@ z<Gmi^b1#Dvz|y!`$Rr-7NkXE*&W~zEY|r4N^vLxmrOD%YPjs!&D_kY7LsfM+%;(<S zo7+<*tdNe4TB8j|ob61gmYxl*z}uecIXM>JM`kk@G$?)2;eQ|S;Ja|(#d4#8$T7ZA zG|g&M(fz4jIootYk4Ed%KVjhZx|A?l%w;i+P8=6|^ARUUG2%grAxgY@p%f&>ubp~6 z=}}B$U0SETgZ~XH$vV{XeEQqd)ljqYU5XRL8~MhNK`xD;(LCS^n^kDJIlUFgK91{U zP2R(Xere9`hCREEo-UATIxQ~@IJxFfO;=afeO4OT3O!V&(a+w#IjNboU$+2H;-3l0 zTz!w`?X5p0lmwhS^xqiMUagDsv`82p<9VLf{KMFGPj_yaPFtb)%#6Fpk4^oXH;|t` z7j-jco&+=Nat2FX*&edoS{ifuJ^Gu9zH}SpD9a!LC9i%12@v~}UnS=V>n*#L4}AZ{ zA|J`Tt9+hiwPL;IWf&H?0u?XCR|5N78F7+$;Wp0uvAHRRem3~wSM-CHv&2Ut7KKYM z!v9qtvG_YOgMRwhG6!!D%T|FB5<<GK?6l<s{PpxaHY;YJ-qd>DCiL~wbqkM|zVGPD zqYRQie#KyR*OJ}_SSoq#y*&gr{l!^RUi{k+gyJXr!3%|iR!wm(5OyyuST#vI^*8N1 z&p$ID{fP@NEGTxo@f`-V)W`=~U8LC1=*>N>$+zBLv*=5DYJ>oFTw}RB?HRtCyQ;A< zh~dm1!6cipl7D_CvaN0!AN|(*eW<JWyhayc$}wT2WvOw>eWX3}eG1EFCZ`e{%qPnE zX~X))$9_(9k$k>RtQ2UxV*R^u#^#<`NHJaT)>2CfhxqWvR^0OsH|t%|mLju2>0Hy7 zS3iDqc@L&DRu9mMpdaQ7<vgua@zEt34DqGZ-|$zQ+V2@@VqdUs0B18D*;_-3eXezi z1yb-{Yv}%o!!!LQ@AQCrRXRMr4li#f8wsH+pR0@?-;7N_tW>+bEvZVj3U<fp-f=y1 zW@BNh(a;PeuwKqR@G-e$OQ!yjbZWEBZHyCAN&gvNQ`62y0_|R%oVC%76TI#>=g?2> z!;ix|O)EjGPUuLpheFV+R|#@oeO6s&{!TQ%w$Td0fh*y@-dfi+j=}o+#;`D7hrQc2 zX5C~x5M;kpPQEz`sXXo6<yNaMWco6>Q&m%!W^>-=;Z~?AQ+XjF<;nG-#xNUS2YR4O zI+-o*3kXKBWIWp9?1?uWI;8>5{XF6n^FQd;Y$;N0$YfX9DMx$TBc7!{60}szEya7s z&`%!s7&TPWND0m6!%dD-{8b7BJFd=Lk^Tyukxwf5a^Jq>oX!k5TI$>l7Y@mf^O`Y6 z)dqE+A=o{>_W8M`jTOe%r~*_>1J%v1xBE*$h*k^miB4hebX|WB#VLX6?5R%5(;3xe zmzmiyww|+8Tc^tE-uv^jWBEo$zJGV!+!LQ&#{R6STIwXIM?x{6Ye@!JmcRcv$XhO! zzROFqv<Z$~7`-o=cb8b2a`sKh^<$xR9-}E&Kn9{L52X4<?PghQ^~<xkuA~^>s-4+M zsrZ*C1Nvu^r70C%AdZClDs2A_`PhNuTB3u5BjAdiKAQ7%%~(VFg-iX>Xq;CUXY@4B zl59P%$IZ6fbVcfRP~I8Q)Ia{0nxH-<=Ij|F6H$kMZsrmu*9d*tVqxUV+4IsIlN%m; z)n|trEE4x7yn5VAbMoGU$(G)q;_a2S{k*rXcx3v=$I9Ztnp6pmeQ7rImkRQ~KQa8n zgbTP>g_Q8Q%d3mS>z639Ev2v2BnP8kNgd?%EXYQGi>5DhoV4MustR5yJn`GgCad+# z!Hma3%{FDv8~Q&WRn$N2Z|L3FEICo*)|WsWw%B&z)$(VPks42+?^S6V99*xdS!#M> zBInuVcpg2k;8(e_tIPSa`Rr($U>EggRW&I6t--7>n0v2MGv;I~c8P+NsFoKIisp}f zc2tY%gM#XIlP9GIni5U2u;OMBFWNh?HiK1(l;WFu71cq>ut1+VM{=4n5N8J=kY<&W zO;@TafZ7eWhlc#Cui5RVeJnetg7TVNO>3mBs&Ji^?rg{UNw|%@cyCc&A84buaDJ(( zI#41gofjPXy##gA9R-LbV#l$%S$eEXN96Q$sJoLg`|Z!vrS9~bSL<SwuBb=3I+3~l zM$D62^~47%!v*{nrbW7bx}GeQrFNW6-&$3nf%B$;>zt(mP~cqLBOnQd^(<~Nb#*nf zx@4B?L&{E{G30dls0!nk?F9)5NegEEgCJvS2ng6Xr}(pf2BRrdNvrXsJ#xy>b-w!s z@T9&?U1QR+d_0*w(Gb?XPdYAV_jME;5~UBn*lj@^Q}+EK*qY4kFx-2gH7O+_D^=el zCzXuhbsrh|>#oth@a{M$Kguc$xBU!14hGfVs%%PlpWg#6Im?|+09oDQc6V2^ycJa+ zvpe|hcS~%md9}mOIjK+SH4dCNGF9QU)r~Xyf0_6pmAN<lzji^d(|Zq(yVut=ri@>L zeagP=9KKN}>{#8KH^nhek_TBXW2`qOj?9b2>+py${hpDHv>(vnf3<ZU8DUvb`l^YI z_k#D!6y_;>e-M;`<<?5?S5Dwxb9a~iPy`Ae%*9rGezl89oTyi?N<VWcFAOR$QD#F? zc3uD4U`FqoUgrnP0{fa{Q}ucSHBNJwgVYgvq$A~Dwc_jIqP{_Igi2BMYw;u3uY0dO z7Xr!0RO7F1tUXLpcHLH&MO}DXAU;&B&f(0BD_JE{;Y(|`EyJb{;;SD=mreZM_oK*S zP!mO#w?QF44`L<R)x8OH3&sa;l$M1dR0t=k3v`rQV^!F+?w#CP2xFW5ClDWgvk9!K zyZf^A`3*7Mhqxa{@nTv*>lFs?)IWwk8r_X<$4jL$7nvzPy^U8d-J7anBC7Orx~;|= zT*xn}iqRda0Tn0`QSq_-ncrFV=jj}@VOP#i9I-o+GD-~rs6_FC-`Qy(i!NV(%^Y1# zrxwlRgDv_~q4KIyz;4LZoMJ$PR!v_7vO~^xoVAqwPChCNnzL^FpUnCyO6#5|C{zKN zdGWZ8zffeBl#L7CXg=f%ShHn_!YNZ`6htPyW_4(&_l;H=xEMk5J-)GS0Y-ksaS1gZ zNqE0&jlIc>$DX_E=o-#hk#^}}a>iD(S<qf|dv;SjYVi=ZXIV^_)#*CLrMX{p01ho) zO8IQ?bhy+PkjiFB9;!mg{2T49mQZ1%7G$Bmnf4F1t_<PAoq<vxejClC*3CE6`uytv z`ub-fw#BAD2fLZ}L^9#%M(Ov4Fa-PPczTV?P1(WG#i_mfEX3PdA?gV8?|p+xE1*g1 z=JqSgo0i2=;fSAKO)a*X?j8UVc6JoO%T>f*dbmPc6EPILKa&LxwhviWdrz^CgMIqP zb!D3Bi=8jIYY-&e?Ip;5^NNwH58wu+W3lipffyM$b3d$rN%A<ueJ`Fsrr8m9iWx=C zZ0z7W33q;?tmduHr+^J8F>K&+P_@emy5_k2GtStb!3GENe!#E7<Q>jMGtca;rLQj7 zV9Il<-lx;#hXti#h*SR^G-**hw7cZe3?7<}^mX3bwL2Uy9e59$m%^;qW~9FWZ5HkQ z^Ri|-*K=8%y>oX?u@BsDA`^5Qcoi$a!G>Jx3vk{NOMj{JZ<ilBZ!a0iTu`5v{1v^P z4GguT`h?<*A}I3d*S3GevMH$XpRW2Rr}*sQ8e_YC<XGEslfsY6%73v(cjs7BMCTs0 zNdr&p7ImQ8vPaCOSXloq8)Dq#n>x0dSu(71*K#2P?U?M>=quU-qp_sxKLiHEJG&=< zuz6iL+_6m~-80Z8&`<h2=vmwNwD%N>-Tpe(MwntyYGY9HzRf2X_~<nBn(aZQRr~!B z&@%dUJpFwoN+yGk7`+>Eu~`Qq*X=r13%?YxKW%8UJhE^7W9>Zh?#FFg&N<iFG`Y~{ zfP5`Kxvq6j<Bz{O1g*e1j=_3Kz&6rPR8I%v52|_$6*Ea*Tvw=B9wRq_+m1+4$F0}G zE|x<;-Cx9N=Ed8cd7{Jpvh91l?XND}sktS$uZwyR$UWsg@TrZg(TzK7=rSqD28qqq zvf!~LUr0yb^aIG`w@&m=N34g-1iGsc@iMnRx&uYqvFa=Xi)Mc9OZF9~C$a{<9uGE$ z{MUM)x-$Yyugk*h)Yg1Z?O0MFA-5fhSYW%r22rE5nd7xx{!UK>6oZfAg4_~Qn4h*Z zh6nfI1AzkONFO*}Di#<dr06SM|CT8uzYYXY{l4(Yvq4s438g_?l2tXhnRS-TQtlOp z@NIou#~$@&PCM-V%4DpTtKH0Ub)~bSnQQgXb?EW1QNw%Z`B{(wVeGY17D}dUol@z7 zb#6rWHLVjcCN)lZ_~fa!_{y`tt2sd=Ffd<T6^<@iUo5#LEW1vX?8w`OU!aQP2~sR3 z`H2R7pvQt-Kgj3=iF|9XoyT)vdBTu3jBl{HCd35!D}U`t)xKGdm3WsIhUAlNcy$}3 zIA3wktyT?AXJvFAgorvscP-OrHYc3@18`@7<;0&1biTn&S8pPLuljVKVb`wB!lu!; z?wg*rIX2_`ciJAS)6Aw475VsA-<_X?V-v5o$aV0-VC^Cu2nsVEcSY%*+4xnsZG%C& zZihdT_Y=h_-DWrLbjN}Z;zU_DRkFFW<nG_;4xKNMLdH9w!eZ|PjxkeAeYAN`#qR3} zGgRD4vW7+zX8Svd*MEp<fujmO2heUib&F=jxW6L<wnLmlGr6?fUD3Y9^ZyAMbh@yD z%hj*DGr^|yEJSrwgD48F*zdZW6^XI&#frF(xSYQ5AzGd`l_$pr(X2Al)VZya$^AzA ze)84X3t@;TRd^AP=)|gbZm@n-#fc28vv1YgAvomKFG;ZYSJqTE0B+&qwamqOdn&jZ z&?DzXFT)n0Ue(CbRJ-4W;C%MpJzSz6Gb!7G`t3opa`90J%<?`>og-LsB&b~k9C`Hh z4n{o%XF@zKma4(}krixUj%I|!WnPFV!M3&L^Z4m6p5lFh_}>LTpS`;*Y%Zb(ZhZ}H zHzestBktcftCB`8nNkMd+_@rWr}WWQMoG{dM$IsS_LW`+wf_+wtnz&q*`km0Jnufj zPLUm(UMDCjyF2&5lw0WGp4r-ST9tll*`9fkErzZ*C7tMp_dVXefQ1QyJL=tM$~49F z0X}NNr%|Kq;s$*z;L_rDL!fN|{cu@%yGo7wM<t=ZqWBxT8rj<ujj`gs$x#N4_mzmm z5%HEQ4`&nW*lJn8&HJv8g;S0IH!RX1<35jVwy+_VzJH9R4^GW+g)MN6S=XH_I46Wa zMCEBJ(*_^bn#Rp{_h^6Vf0RsPgkntWjFR@q$&b!y<T?(yAXu$@LC{o=T51GCXvQ4N zKWl{Io{;O-v`3_;Z%p2RQO?s23rsPZ1NaKwJh{yz7^gM#JDU@~9bS*8r<rv|bA;$0 zM6jC|a^NL@K)kF0U$kuaX;%4ZyBwRTlJs<=&WOV~M<GPiA$}-)GY?yGrd`DGp6yhs zR`yY>VL522h>Ga@%ydb<QsrhQ(OsJ&zX(!<8s1u^>Fud!WjfLSktfw&*uBh2yhE;= z&Gvj%7@B4o{=#v3v`o?OzHC51ET+`L{F%Y(%#|yWd+0+--3CBsmd=jRU@J?SM7Pzx zk^1ZUOK1?u7jmf6C`3Q9o&_|Xr`38N7jPPV^(m-r5VQLT5&u%z8IwjoV7ifbc|<wU zOiqI7G=4xRSWi0hLQw{PkTAGSM+j9qAL{}X%DIVlpwFb01K3|_+6dE*qFGPmdoz7r z9U~a%)8|-OeyMg@{nevIIL*rQoyY5$T_HN;=ddYMCKr-)+7S^&n6c~Z==q+WCO^-* zmjv2gDj_ejZ{nMQXm7=ww~<Q@Qvd658B50)(@C&3E%n5gm#KeuCu+j}rN=$2IPu(m zG=&G`Y?wYpr=0^7M2?H*V#8%k)VRL93hh<+e#a_yZ0f@y^Yc*#5BLQp<XlNI6xp2F z6Xd!S@Rg;L{3w&W<IJrxuU7VB9XMh1q4@i+(B6lisIn@HU9q3Jg0-*~qgfqVtZ-91 zbFT9lhw?bHZ&s9n{2h6R=Ri!p(b#imJYQA>V7~9e_k^#$SJX;<tsHxO`-e9Y`R!U9 zP1&>WB$%)uO4>N1=l1?(8{L&?H}&&8=U!cS`mj-r>%mN4-kA&iEQxK?2dJyVuZnT| zabKCTd(IL+No&fLKRv?lRZ?^x5%uznvHB<6<CCh;jy&j@a*3MCaGf3!TSN~8dnDaa z2w^%u-&ajU@^RZ;ittLAI-fV*T)wp+QBHwF9d(d`_-heErz?UTEq4bG8(?z&%nBW9 z|IYEw{O8!+oZw%eO{pqIvwa<#+X=g2lErAHYxhn*GKEbJway!-{97k=oIdaHDvci| z67H<=T0%igon2$U*N4Z?58MzUeJ;~qtEZWe)Iob+!2l1*hwSUP{mI(Td3uPlNeNLy zKYPZxTo?Ka!_ZS~;YrOGxEY$cDq%i%iOqyXD@zk{RnySCR+6R?UyeNc9(0M<drV>U zlEJM#Lg77re`U?f69nsXu;8ElE4l9~WwLNRum3Wb6iMRe_xe8bZ!76(>3Y=@YyS|V znT()cBylE>)wE-$M-^O=Cho;=-s$EuKQr)e^dy_FU46G;O&dmL!9IIk`_d0PKQ3Wv zmXy_YqDKW(kcjyH%VO4@RdNa|nz~}dZi0^g`GE{<vg5iLRfJH1`SjIH4?DGq_)zjo z2!<R>#V+P?n&e5E%<Y-2+R=vnC`T_Y6{X!$`N)1%NCm1oo4M1S`+j<QN$~*+`T3`u zF}3uZGPnpS7|`(<umRYXyMj#Fp76(EOPR+`gZk}{9TsHvN0BOSRs#n$G&X?1a;7D| z^ls`HaNsp+;9bEHk<VP6F58kf?*h*-;OWH1HV1v@y2QB>q964t&);et_x36mtg(}H z4tC^Fxz*jDy}!QRkg)9jL>6as@kRtwpLYaremDi%S7TtF-sH3EViVWz&ccW)8%VD# zx~QpaePv{6le4NS4z!*+fO&$cmy5SdzGU8Y**R(tl;sJ{6Lc_NRSxMd5>)=RokXT7 zc}yQ9EKLbb%-zv1x{dez$K#EncR?>EGKTItQglzS^8AkI$@pCI&JUc`(?O?fi@9m2 zxKgvj@h{PwfbX0zZ}R+-*qFf^>2cBr$e&%gAD2=v{dZ<Ei+1B<-qFK}M!G1y<&5#E zn#;7DQ;c0R$AS1&qh?1vMTQ4NxjC2ye0paHCVVZft!7jsamhg^SRWBD=uJ#Lm+`Ju zQ(c`X@cB0oA}81>hh3-^6qOu%jQ3GW!#zd2h@t}r<86c87R*PzXO$VTfsI^uBRE1i z<th(Dke3X^g@TLd(x%sj20Ju0tHK8@#L6U*Guw-|61Rv#iJ$|usGE3;T-W=0^vEm| z#6UYpOETU1V&C(Lhp<c1<A)&=F0cj94i^slzw&c3Nrc@{rXAVj>C5V6OrTN|H*qdJ z;i2J|XItN{SEzVn3h5`2d`Gv)OL@`n3YR1@hCYvO>R?8%rw@49s%H}l4p;e}*nIH> z6g=2o&@9eg*Y`QtBebiKlnL%el1>h>k^IO{_S%0L9EKprbq%UDSZ+an|K|L%m>Qw( z7h_1_q0Xm^#Wmfwvyprh)0~ClwBbjfT^j@1wIR8ngSFpqu?4qp{v`IKT6`P$J_mI6 zxSb_YfBC1;J5!6p^-X_rrb21M+rbfnjBfBl1|=MV<7gxE>*Dvv_s^Et-$?YcJksII z5)f-b%KW^RAM?V(?x1lM5p1^rX~lZlr?d`0UDPJf`boZ0fptOM)}X|VNTbUm$G#XI zGurC>`d!%}={N@)5igQ~eX+@t@T{F5EXGe{F#s&a10*KRH|sM;uDrSP?lcm1hJ*ul z9o6VWW)_=0l#zv|?G1wFcHQNlN)^{^S!B9^IT@`Azwj)XBwr7@Pv@ERNJjF-RUGFU zU!j>ebb4J`<?Lmps?n^{>5_%d>|u~CKx!J{k(66w*@WWg1`BW(*2&5zEO0O?`H+6n zV%o|(ul2`w3Ars-PI$#*J(B5?Gm&nLVfzPyDY#hWLid>og6~ff<+e#F2Q1zoT{Y)% zy0K<>%@q;d*Y(?Sf9A+_mcbDQH{R~+y}TtZBT-AjrPK~!KR$|3`tdQlJe=pO$l<6Y zmGLeRHkHr4QoS&!Iq}6^!z&qku3S^{*gozH>3F=Aa6!dsx$L|%pUf<00|G788{}_Y zMO9wnSP7UjJXYuTOWC;3Q6tR{KcTJJ06O=dw}X3KN54ahP85|f4<ns3Jr)a2OR;d# z`}B1&eH4v<LWP{EoKcgh_Kfp5Z~jTm)wYI~uiKf}jV&J8n`I{<&>!bVO(b9^nB;!f zHz%j!l*)ol4h^l>IBUY<rNI?Wd)=W3?84hW8R~B`fK^iBeY#6Cu{Mih$OGP|p-y}r z(T#G;=ZY)t;T7Lvw-2rkW+7+LB146qX1w9;w#kR5<Q)8E<@8c7*paR}#)x%3UOq~& zn=G$lAebyD+7Az=GaSqjIuBRv?5wC>U~WiP{f+&Y*c$60JXr5MJN>3Cmrdq&17E>+ zEuTBy+Ty?j#~udjr5?GEQ;Uz6dh-0d$mfYaU!R{kyDDaC-G3m1o-s6wHn@84Is|%^ z*HASau_OEGk&*s)i9tC&ofNIF9<2bmb(hNaAMDF5_`FAqX3OdwAIcuU@ZDgb+mP{! z619UW0u4=lcDEQ*PTH!-bOS6WBI>OeYGbPufa?z3Q(|5`O&boS9@k={0C;1OszK~_ zTlrFiAW%sNn|#Z?rgs2y_%k&Fdj^1s-rfX{$#t4cHCyEW@Jn*EVGwrhZ@bYTQ2>*K zqVb#z{9ydmAcTJdwxkO{mAU{7ibyhsteK1f_y@qI3ZG3Fhba&q+3Wm`fUGAo-m{h* z4|tXs8QK2k6@Ctzw-h0I8Uj_P2p$K|{11b5|3PBLQZs-yx^)%;Vk$KUhI`zPLlDPt z#{UJ_JbeF5AOi7;0c?G}B!(LDDS<$~Ho_g;!vMK0Eew(C(7_RlN1cwt#5+i$i_OF~ zbpZN8XfCj7jAe9ni2unr3vB4aL4T&&VTOP@igby|<hqQ^Ln+@`AkdS@b_9+MW~}Q& z0R+%sldDA^GtM*24wVqZ{Cq<cEbGF1;aX59d|}|$eE6vG8Q7t4SHluGKO)}W1r<=~ zNmkm+W}+&DL}*xXS8g&C6z+Pg?px1kfWEuPLOhy*HNuM+io;JKkxRWiR<w*D0Q8bE zg?T+DbW3_*8d$&vrLD9G;#&oP-^Fm?bG^vja1E~2|7bZIK@vE!I<Of4GFN7$4a12} z;ntK}|AGH@01(Fn3`*v}hbq(dpq*j{8ZLnkzBj0{VF~8H%tG{5riJnZcQYg=^wCq5 z7WxN``CSMJf}P0(AGVRH15%{926COmKOO|jAiE5Uqo3R&oPjQ!C<vX-*w&{U&AF%! zotl1s+H;-p^(fWm=Vrd1I^--<(aaPY%W)Ecpm1#hC`vxz5eD!t4*-|=eHIP|0I%aZ zI~7Z=8v=k!<bQxmI@<y>2g8&)WbY95Gq4)~D0%%f#M(hBVOfA*Vkn~nkx2v<WEfC+ zCjg0p4UR*NDQO!>mJeG@jQJ0(%z$sg08lvm1OvbYx*g1qc@<+9bQzG(ir?_D3`^F= zLj?dpgF!tl3h(-{$p*mGcwp@K=y2};2DArKk+k76ghwp^@rYNU72%a&szJ9g_KQa# zfS~f*<l$2~4P79r;GkNLS_W1+{=l{k)rEm|{}0xxlYzZMJP}S$7%seo!LYU(?ET$& zK<T;G0TnZ~Gs$f;FS=&8Gls>@F=@<YY%_-CGf5he{$2o>-vbO4UYv!z60sg{0EAbI zMe9h~fE!hois~`NU_QTlHX$5VoYTn%V7f?}6-$T1!}AR9=R=-Pu$szm)r>ZW?9;F% z!v1oLI{(q4_7jIPu~h)tEBwFsVHOYgrT-*d&O_}Y*HN~465fL&BS%LkI4|`5KS?KK z5`(s@uL_vRGgH&B9{gS!GCd5IrTv*+zHg;y@<T^Kg$tFi?jfevMD;PKL(eCM^XD?K z+aVDMZrJ14v^#7&h<O1?<dXNn&9~SEZHo4U?|=B|cZnGSGHncE+Jgo@Sc$VsoI+qk z9M*%gW0y%DZGp-8t3(WN+4*9q4jpxJREoDcfgWUh4|8EA0K-e9OZvE-hW5gOa3cS1 z+-mdQ+4WT>iM*;PEI4+p<EK15VI~1ZlDa(zr#-qzYCI+<hdi7$0M|9ZBwmQ(IDSv{ z>w|-5zKR?ckrzmMb>UE1R9D|f!<GH*e^k}5?Lw@_e#0D&9MDYl3bixQ;N9CP>7lFs zPXNOOJo?wUt`^A51A*UCju@7tVfHX^enhOQ9Yj0kBY+lYb`LxQxDwb>IgTW4&)bwE zd>1(Qw}UePEt8o?0(SyO)y^VGjpu-GN5qQSLA3Ln0ce?s_y;f#xP|gwtt8d72spvP zzkQqmXtB)v8t^;dz{*i1_0Q|Tg%R;!?I0Q(X8>9(B9;Qj0T0y9BB@vI1&(s?Z#QQE zIwCU{0>1!0RXdBM&Uy{_K}0OB9Yo{j3_wRj#67@V%JVo$nn+3cZkg-g-yO~XbWmoV z1N<D<21pve=YdNi;_=!+G_jlk=%A*d&!N02Fj6^=q;`6Ta(dq}4*uQb3_!<a=5ds* zgpaSCMN(_504|P*<+X!o@;C#~aS`z}<zS(!flZa;NE&V%fge%c>v!<)IA;KQBr^{N zt_RMmokh}6NnkPXlZbe^b{I_!3qTKL=2s}|1CFenMN)Nt1+I*UCu;}M)bbHP4@JZy zz_FCWh1OP%BdLy8flGmT4*vb*3_#Ci<^jM@feV3YmE%a7e4BwAf$Jk;W9=}i#{wV# zGII{42rR6fMbe~M0$dRhFVzmB`YZr?pUnI!@H61(+F2w`m=%=g{Jzhx_qYZ??-LOZ zQT7b@F5qflsoh=z&Ii8e;I9vI20$MvGp7UJ0j|Yug{3z6FJ&h0=7`u_JB)^t1wbDw zGxq{6r)(xPqjDTcA8kG5RM6`pVqNVp8g3Q<?X=9?2e=H2fHZ7I2mTu(;?3G&)D9K^ z?XrO)a22p`<v3EGIq+-DEC3p_%$x!I5V!)ESvii>C;tO(25yN6H}le%SO7F`nYjmW zE^rNSMCCYAm%Rr33b@IEU*lx~(1gj%-GDPGYXs(3jw5x+O5j%DwusnLJB+%)0-#Be znI{832F}9$CZw@?1h@%U5)oNDjJm}Fph=aPhf>xFTm<Y{IgZo@TY*0SH%7#=+F{gP z7646&%$x;$5BNT?f8{vRFj@`V2K+K2R@V-r?y~@BN;SI+o()_AoQi*g(sJN-U{OT8 zRXdFO!!KV|lbJ^V7f>D#>{mICG?mr@zXxuOh`-kkqkgggsJdpW;f0g~h)%}8OLbEM zj|0B}7DvRU%6Zgte$i^EWaez(Tfn8jXDY{$Cc-M<4&c`jv9fj;X_N&(L#f$Q;56Vo z;G4i+brVUuWIb>{un2fKBDPh|BYlVkKtr$DX>ha*oDEE`n@HNO5z2e}i-7wgVngLT z(hgYw)GC>|A8-z3>)}&?X>}8+=iUJx1?~p!jfgku#*ucO1wgHpnKOZ}Qx*^|z?lI} zjS=84z&*fSzO%2kvH++Pnv)5?L3u>50NAH)B6Z9<U@7nb@Sq3rs0%Cr>YU7+2Ao8h z9XJd4T-`)!seb_v0ZV|T5wW#$9%({Z0MvPzIR`kMvXJl;e4{|yw*hzz_%rawh<KrL z9%)ip0MskZR>bouj|ol#j>Uz9eKi6+4g85R=s)GJeD#S1K)sfkdjls@b|Cx`@MT;~ z*i|FI-+(89Cn)ddyJ}y(WdV=|G=*S3r4Y<(u1{7CrLkHAETgR0e}eK0e`DQ9((teV zNITH%NH~X51Ws)3p9glYnM)t?Ht-DpAMlp}|BQ&Nno1gC7654%W#;a{XMy7fuA_my zYv$^a4Z!ojvy`KBmjlZ^N>|!776562WadGX*@3wO_b=d{1Y@-Yc#-nU{@H>1bMCD# zjh_WTnnalyz#+ilz+ugO^z&g@4%SiLw_n*@FAjWO<rKa&c`N`@MVYxTr67D7nB9Dy z4IBg<0L*Hx-D+hVqiw+J&9xeM6?mn&{tdhgyb=*>swI?q&H^9}xn^g>Sp(NhV8(W? zJt;E^djOxHY<M)C@)pBjff)V&L2m(@2mZYcSPN_gHUgU{Q}XMZ&ua#*HwW&cgZ_V< crk94>yCtj*?HGE#$p8QV07*qoM6N<$g6?p}WdHyG literal 14947 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 U8Ag^%-T!3jY8pZ-?%9R^9~DfB8UO$Q diff --git a/background.ts b/background.ts index ff588b6..dce12f1 100644 --- a/background.ts +++ b/background.ts @@ -63,7 +63,7 @@ const ensureContextMenu = async () => { await chrome.contextMenus.removeAll(); chrome.contextMenus.create({ id: CONTEXT_MENU_ID, - title: "Open Image in BetterViewer", + title: "Open Image in OpenImage Viewer", contexts: ["image"], }); }; @@ -74,7 +74,7 @@ chrome.runtime.onInstalled.addListener(async (details) => { // When the extension is installed, open the welcome page if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) { chrome.tabs.create({ - url: "https://betterviewer.surge.sh/welcome.html", + url: chrome.runtime.getURL("docs/welcome.html"), }); } }); diff --git a/components/About.tsx b/components/About.tsx index 1c349ea..f250681 100644 --- a/components/About.tsx +++ b/components/About.tsx @@ -6,39 +6,41 @@ const About = () => { <div className="flex flex-col items-center justify-center h-full p-8"> <BetterViewerLogo width={150} height={150} /> <h1 className="text-4xl font-bold text-white text-center"> - BetterViewer <span className="text-blue-500 text-sm">v2.0.2</span> + OpenImage Viewer <span className="text-blue-500 text-sm">v2.0.4</span> </h1> <h3 className="text-lg text-white text-center"> - Fast, Simple & Easy Image Viewer + Fast advanced image viewer for Chrome & Edge </h3> <p className="text-white mt-4"> - BetterViewer makes image viewing faster, easier, and more fun. + OpenImage Viewer makes image viewing faster, easier, and more powerful. </p> <p className="text-white mt-2"> - Designed as a better alternative to the built-in image viewer in - Chrome-based browsers, BetterViewer lets you: + A community-maintained fork inspired by BetterViewer, designed as an + advanced replacement for built-in browser image tabs. OpenImage Viewer + lets you: <br />✅ Zoom & Pan with ease <br />✅ Edit & Enhance images instantly + <br />✅ Open image tabs automatically with MV3-compatible detection <br />✅ Use handy keyboard shortcuts for quick navigation <br />and much more! </p> <p className="text-white mt-2"> - ⭐️ If you find BetterViewer useful, don't forget to leave a star! + ⭐️ If you find OpenImage Viewer useful, please star and share the project. </p> - <a href="https://github.com/Ademking/BetterViewer" target="_blank"> + <a href="https://github.com/lscherub/BetterViewer" target="_blank"> <button className="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-1 px-4 rounded mt-2"> Star on GitHub 🌟 </button> </a> <p className="text-white mt-2"> - Created with ❤️🍪 by{" "} + Maintained with ❤️ by{" "} <a - href="https://github.com/Ademking" + href="https://github.com/lscherub" target="_blank" className="font-semibold underline" > - Adem Kouki + OpenImage Viewer Community </a> </p> </div> diff --git a/components/BetterViewerLogo.tsx b/components/BetterViewerLogo.tsx index ab09118..bae9b72 100644 --- a/components/BetterViewerLogo.tsx +++ b/components/BetterViewerLogo.tsx @@ -1,35 +1,11 @@ import * as React from "react"; const BetterViewerLogo = (props) => ( - <svg - xmlns="http://www.w3.org/2000/svg" - width={512} - height={512} - viewBox="0 0 24 24" - xmlSpace="preserve" - {...props} - > - <path - fill="#29b6f6" - d="M22.75 12a9 9 0 0 1-.07 1.15 10.743 10.743 0 0 1-21.42-.8c-.01-.11-.01-.23-.01-.35a10.75 10.75 0 0 1 21.5 0" - data-original="#29b6f6" - /> - <circle - cx={12.375} - cy={6.625} - r={2.375} - fill="#e1f5fe" - data-original="#e1f5fe" - /> - <path - fill="#1565c0" - d="M16.74 21.65a10.746 10.746 0 0 1-15.48-9.3 10.755 10.755 0 0 1 15.48 9.3" - data-original="#1565c0" - /> - <path - fill="#2196f3" - d="M22.68 13.15a10.746 10.746 0 0 1-14.42 8.93 10.285 10.285 0 0 1 10.24-9.83 10.1 10.1 0 0 1 4.18.9" - data-original="#2196f3" - /> - </svg> + <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="512" height="512" + + viewBox="0 0 512 512" fill="none" {...props}> +<path d="M0 0 C1.01790619 0.00215515 2.03581238 0.0043103 3.08456421 0.00653076 C17.69363523 0.05620146 32.02575853 0.30709809 46.375 3.3125 C47.34985352 3.51117676 48.32470703 3.70985352 49.32910156 3.91455078 C97.7109774 14.03517194 141.69928269 35.9516877 177.375 70.3125 C178.3640332 71.26068604 178.3640332 71.26068604 179.37304688 72.22802734 C188.86130305 81.37247479 197.6012044 90.66984009 205.375 101.3125 C206.23306152 102.46355017 207.09113451 103.61459177 207.94921875 104.765625 C213.98736829 112.95680614 219.34595521 121.47054105 224.375 130.3125 C224.73948242 130.94430176 225.10396484 131.57610352 225.47949219 132.22705078 C247.08534998 169.97532572 256.85198095 212.74189997 256.6875 255.9375 C256.68534485 256.95540619 256.6831897 257.97331238 256.68096924 259.02206421 C256.63129854 273.63113523 256.38040191 287.96325853 253.375 302.3125 C253.07698486 303.77478027 253.07698486 303.77478027 252.77294922 305.26660156 C242.65232806 353.6484774 220.7358123 397.63678269 186.375 433.3125 C185.74287598 433.97185547 185.11075195 434.63121094 184.45947266 435.31054688 C175.31502521 444.79880305 166.01765991 453.5387044 155.375 461.3125 C154.22394983 462.17056152 153.07290823 463.02863451 151.921875 463.88671875 C143.73224019 469.92427396 135.22961724 475.30707302 126.375 480.3125 C125.66778809 480.7146875 124.96057617 481.116875 124.23193359 481.53125 C101.09654164 494.5566741 75.92537591 503.30551461 49.9375 508.625 C49.21860596 508.77235596 48.49971191 508.91971191 47.7590332 509.0715332 C33.08339502 511.86090125 18.55831162 512.66142619 3.64770508 512.62817383 C0.70811513 512.6250221 -2.2304558 512.64854926 -5.16992188 512.67382812 C-18.54306192 512.71848737 -31.43916711 511.51301542 -44.625 509.3125 C-46.33055054 509.03031616 -46.33055054 509.03031616 -48.07055664 508.74243164 C-91.33802759 500.97044532 -132.38793216 480.98345309 -165.625 452.3125 C-166.37007813 451.67828125 -167.11515625 451.0440625 -167.8828125 450.390625 C-181.38779833 438.57948485 -194.05918743 425.82889772 -204.625 411.3125 C-205.48149066 410.16255169 -206.33826433 409.01281411 -207.1953125 407.86328125 C-213.23534209 399.67315742 -218.61867614 391.16870382 -223.625 382.3125 C-224.0271875 381.60528809 -224.429375 380.89807617 -224.84375 380.16943359 C-237.8691741 357.03404164 -246.61801461 331.86287591 -251.9375 305.875 C-252.08485596 305.15610596 -252.23221191 304.43721191 -252.3840332 303.6965332 C-255.35789088 288.05024391 -255.99800362 272.57681954 -255.9375 256.6875 C-255.93534485 255.66959381 -255.9331897 254.65168762 -255.93096924 253.60293579 C-255.88129854 238.99386477 -255.63040191 224.66174147 -252.625 210.3125 C-252.42632324 209.33764648 -252.22764648 208.36279297 -252.02294922 207.35839844 C-241.90232806 158.9765226 -219.9858123 114.98821731 -185.625 79.3125 C-184.99287598 78.65314453 -184.36075195 77.99378906 -183.70947266 77.31445312 C-174.56502521 67.82619695 -165.26765991 59.0862956 -154.625 51.3125 C-153.47394983 50.45443848 -152.32290823 49.59636549 -151.171875 48.73828125 C-142.98224019 42.70072604 -134.47961724 37.31792698 -125.625 32.3125 C-124.91778809 31.9103125 -124.21057617 31.508125 -123.48193359 31.09375 C-100.34654164 18.0683259 -75.17537591 9.31948539 -49.1875 4 C-48.46860596 3.85264404 -47.74971191 3.70528809 -47.0090332 3.5534668 C-31.36274391 0.57960912 -15.88931954 -0.06050362 0 0 Z " fill="#FEFEFE" transform="translate(255.625,-0.3125)"/> +<path d="M0 0 C18.57356357 10.8324843 25.35439975 32.36327397 33.375 51.125 C34.38560951 53.47272583 35.39676642 55.8202161 36.40844727 58.16748047 C44.85954976 77.80486369 53.20976759 97.48634439 61.47169495 117.20407104 C63.24059183 121.42520718 65.02027021 125.64126735 66.81884766 129.84985352 C67.18542984 130.71085663 67.55201202 131.57185974 67.92970276 132.45895386 C68.62408597 134.08890351 69.32142495 135.71759852 70.02232361 137.34475708 C75.97225554 151.34155559 76.94446426 168.17867382 71.5625 182.5625 C67.61406205 191.54011367 62.5232531 198.68954018 55.5625 205.5625 C55.02238281 206.12453125 54.48226563 206.6865625 53.92578125 207.265625 C40.08927919 220.50963201 21.87210721 222.01293328 3.82519531 221.95068359 C1.83808098 221.95475442 -0.14903109 221.96009916 -2.13613892 221.96661377 C-7.50828114 221.98023586 -12.8802496 221.97500889 -18.25239468 221.96547651 C-23.89346705 221.95784915 -29.53452515 221.96493444 -35.17559814 221.96963501 C-44.65094658 221.97508541 -54.12622475 221.96792159 -63.6015625 221.95361328 C-74.525475 221.93730705 -85.44921931 221.94256348 -96.3731277 221.9590925 C-105.77904081 221.97275032 -115.18490358 221.97460553 -124.59082341 221.96677649 C-130.19650985 221.9621211 -135.80211752 221.9614156 -141.40779877 221.97138596 C-146.68401749 221.98011537 -151.96002171 221.97392557 -157.2362175 221.95670319 C-159.16176626 221.95276923 -161.08733338 221.95381867 -163.0128746 221.96049118 C-183.56456365 222.02508713 -201.78173817 219.62293038 -217.3737793 204.89697266 C-229.31364701 192.94694682 -234.77531173 178.05221196 -234.875 161.4375 C-234.90787109 160.49390625 -234.94074219 159.5503125 -234.97460938 158.578125 C-235.09669804 142.10725483 -225.548175 127.18833751 -218.33642578 112.89379883 C-216.56390324 109.3777835 -214.80650039 105.85450902 -213.05078125 102.33007812 C-211.91234834 100.05944939 -210.77305436 97.78925212 -209.6328125 95.51953125 C-209.11590851 94.48278763 -208.59900452 93.44604401 -208.06643677 92.37788391 C-200.31384982 77.06786887 -192.4537991 64.67604608 -175.9375 58.1875 C-163.8936915 56.03681991 -153.59346705 58.91253283 -143.4375 65.5625 C-138.86273654 68.78765862 -135.48953537 72.63957204 -132 77 C-125.49577079 85.10002148 -118.63237102 92.17264987 -107.99609375 93.9765625 C-99.92981156 94.45624751 -93.56352137 91.28077945 -87.5625 86.0625 C-84.03488334 81.91236276 -80.91916938 77.90344331 -78.29296875 73.1171875 C-77.70596191 72.05322754 -77.11895508 70.98926758 -76.51416016 69.89306641 C-75.8907373 68.75272949 -75.26731445 67.61239258 -74.625 66.4375 C-73.96460408 65.23975488 -73.30362372 64.04233183 -72.64208984 62.84521484 C-69.88856333 57.85844881 -67.14776859 52.8647602 -64.41748047 47.86523438 C-41.31771611 5.57310033 -41.31771611 5.57310033 -25.328125 -1.6171875 C-16.8235772 -4.03064026 -8.0461757 -3.67883895 0 0 Z " fill="#54A6B2" transform="translate(335.4375,189.4375)"/> +<path d="M0 0 C10.08500951 7.90885609 18.52380848 18.90833512 20.42578125 31.90234375 C21.49582263 43.47948359 20.86904045 53.40258324 15.42578125 63.90234375 C14.9565625 64.81628906 14.48734375 65.73023438 14.00390625 66.671875 C7.02145467 79.19148576 -3.99661818 86.63196938 -17.57421875 90.90234375 C-32.22331687 93.86750972 -45.32818993 91.52795938 -57.94921875 83.65625 C-69.89889034 75.67202002 -76.95481428 64.0194374 -80.06640625 50.03515625 C-82.5916762 34.45618315 -78.18095867 21.61698027 -69.20703125 8.9765625 C-52.76859593 -11.96618984 -21.28651966 -14.91633155 0 0 Z " fill="#63AF7F" transform="translate(210.57421875,110.09765625)"/> +</svg> ); export default BetterViewerLogo; diff --git a/components/Help.tsx b/components/Help.tsx index 0dd81db..0ea0867 100644 --- a/components/Help.tsx +++ b/components/Help.tsx @@ -39,23 +39,23 @@ const Help = () => { const faqs = [ { - question: "Which browsers support BetterViewer?", + question: "Which browsers support OpenImage Viewer?", answer: - "BetterViewer works on all major modern browsers, including Chrome, Firefox, Safari, and Edge.", + "OpenImage Viewer is optimized for Chromium browsers, including Chrome and Microsoft Edge.", }, { - question: "Is BetterViewer available on mobile devices?", + question: "Is OpenImage Viewer available on mobile devices?", answer: - "Not yet. BetterViewer is currently designed for desktop browsers. However, some mobile browsers may support desktop extensions.", + "Not yet. OpenImage Viewer is currently designed for desktop browsers.", }, { - question: "How can I contribute to BetterViewer?", + question: "How can I contribute to OpenImage Viewer?", answer: ( <span> - You can support BetterViewer by reporting bugs, suggesting new + You can support OpenImage Viewer by reporting bugs, suggesting new features, or contributing code on GitHub. <a - href="https://github.com/Ademking/Betterviewer" + href="https://github.com/lscherub/BetterViewer" target="_blank" rel="noopener noreferrer" className="text-blue-400 hover:underline ml-1" @@ -68,12 +68,12 @@ const Help = () => { { question: "Why are some features from the old version missing?", answer: - "BetterViewer has been fully rebuilt to support Manifest V3, which resulted in some temporary feature removals. We’re working hard to restore them. If there's a feature you’d like back, let us know!", + "OpenImage Viewer includes MV3-compatible hybrid detection to restore automatic image-tab opening in modern Chromium browsers.", }, { - question: "Is BetterViewer free to use?", + question: "Is OpenImage Viewer free to use?", answer: - "Yes, BetterViewer is completely free to use with no hidden costs or subscription fees and It's open-source.", + "Yes. OpenImage Viewer is free and open-source under the MIT license.", }, ]; @@ -104,7 +104,7 @@ const Help = () => { <h1 className="text-3xl font-bold mt-6 mb-4 border-b border-gray-700 pb-2"> Features </h1> - <p className="mb-4 text-lg">What can you do with BetterViewer?</p> + <p className="mb-4 text-lg">What can you do with OpenImage Viewer?</p> <ul className="space-y-2 pl-5 list-disc text-gray-300"> {features.map((item, index) => ( diff --git a/config/ImageViewerConfig.ts b/config/ImageViewerConfig.ts index ca73743..71cfbf2 100644 --- a/config/ImageViewerConfig.ts +++ b/config/ImageViewerConfig.ts @@ -273,7 +273,7 @@ export const tipppyOptions = [ }, { selector: ".viewer-about", - text: "About BetterViewer", + text: "About OpenImage Viewer", }, { selector: ".viewer-qr", diff --git a/docs/STORE_LISTING.md b/docs/STORE_LISTING.md new file mode 100644 index 0000000..738bd0a --- /dev/null +++ b/docs/STORE_LISTING.md @@ -0,0 +1,86 @@ +# OpenImage Viewer — Store Listing Kit + +## Product Name +OpenImage Viewer + +## Subtitle +Fast advanced image viewer for Chrome & Edge + +## Short Description (Chrome/Edge) +Open images in a powerful viewer tab with zoom, rotate, crop, editor tools, and MV3-compatible auto-detection. + +## Long Description +OpenImage Viewer is a fast, advanced browser image viewer for Chrome and Microsoft Edge. It is a community-maintained fork inspired by BetterViewer, with a Manifest V3-compatible hybrid detection architecture that restores automatic image-viewing behavior for modern Chromium browsers. + +When you open an image in a new tab, OpenImage Viewer can automatically redirect it into a full-featured viewer experience using layered detection: + +- URL and extension checks +- MIME/content-type checks +- navigation event detection +- direct image-tab detection + +If automatic interception is unavailable on a site, fallback support remains available via context menu: + +Right-click image → Open Image in OpenImage Viewer + +Core tools include zoom controls, fullscreen mode, rotate/flip, crop, annotation, photo editing, color picker, QR scanning, EXIF details, reverse image search, Photopea integration, and keyboard shortcuts for productivity. + +OpenImage Viewer is lightweight, privacy-conscious, and built to preserve performance while improving image workflows for researchers, designers, developers, and everyday users. + +## SEO Keywords +- image viewer +- open image +- image tab viewer +- fullscreen image viewer +- advanced image viewer +- browser image viewer +- image zoom +- image tools +- photo viewer +- open image in new tab + +## Suggested Categories/Tags +- Chrome Web Store category: **Productivity** +- Edge Add-ons category: **Productivity** +- Tags: image viewer, photo tools, productivity, browser utility, image zoom + +## Store Asset Checklist + +### Screenshots +- [ ] Image opened in new tab auto-redirecting into viewer +- [ ] Zoom/rotate/flip toolbar +- [ ] Crop + editor workflow +- [ ] Color picker + image details panel +- [ ] Keyboard shortcuts/help panel + +### Promotional Art +- [ ] 128x128 icon (store icon) +- [ ] 440x280 small promo tile (Chrome) +- [ ] 920x680 marquee tile (Chrome, optional but recommended) +- [ ] Edge spotlight banner variants + +## Privacy Policy Template + +OpenImage Viewer processes image URLs and image-page context locally in your browser to provide image viewing features. + +What we collect: +- We do not collect personal data for sale. +- We do not run third-party trackers inside the extension runtime. + +What we store: +- Local extension settings (toolbar and viewer preferences). +- Temporary image URL state needed to open viewer tabs. + +Network behavior: +- The extension may open external tools only when user-invoked (for example, reverse image search or Photopea). + +Contact: +- Support URL: https://github.com/lscherub/BetterViewer/issues + +## Attribution Snippets + +### Store listing attribution +OpenImage Viewer is a community-maintained fork inspired by the original BetterViewer project, released under the MIT License. + +### Icon attribution +Icons made by Graphics Plazza from Flaticon. diff --git a/docs/welcome.html b/docs/welcome.html index 8769632..1a01d71 100644 --- a/docs/welcome.html +++ b/docs/welcome.html @@ -5,16 +5,7 @@ <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>Welcome to BetterViewer! - - - + Welcome to OpenImage Viewer! @@ -28,9 +19,11 @@ hero
-

Thank you for installing BetterViewer! 🎉

-

BetterViewer makes image viewing faster, easier, and more fun.

-

BetterViewer was designed as a replacement for the image viewing mode +

Thank you for installing OpenImage Viewer! 🎉

+

Fast advanced image viewing for Chrome and Edge.

+

OpenImage Viewer is a community-maintained fork inspired by BetterViewer, + with MV3-compatible automatic image-tab detection and redirect support.

+

It was designed as a replacement for the image viewing mode built into web browsers.

@@ -41,7 +34,7 @@

Thank you for installing Bet Right-click and select context-menu - Open Image in BetterViewer + Open Image in OpenImage Viewer

Thank you for installing Bet alt="hero" src="dog.jpg">

-
-