From a1e3e6852fb5070121611c11f0afc8787a7368af Mon Sep 17 00:00:00 2001 From: ShellDiablo33 Date: Mon, 15 Jun 2026 11:25:55 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20Phase=201.5=20=E2=80=94=20health=20prob?= =?UTF-8?q?er,=20Oracle's=20Memory,=20off-thread=20EPG,=20PWA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resilience + scale pass on top of the v1 core. Stream health prober: - New SSRF-validated /probe endpoint (HEAD -> ranged-GET fallback, 6s timeout, 5-min TTL cache, concurrency-capped, no-store) + orb_probe_total metrics - Front-end health.js: lazy bounded-concurrency probing (current + sampled channels, not the whole catalog), LIVE/DEGRADED/DEAD scoring, guide skull glyph, instant no-signal on zap to a known-dead channel Oracle's Memory (memory.js): - Session resurrection (last channel, volume, mute, theater/dim/ambient) - Exponential-decay per-channel uptime history; pinning; dead-channel auto-skip Off-thread XMLTV: - lib/xmltv-parse.js (pure, hand-rolled scanner, no DOMParser/regex backtracking) run in epg-worker.js module worker; wired into the iptv-org provider - Unit-tested in node: entity decode, TZ offsets, 20k programmes off-thread Service worker / PWA: - manifest.webmanifest + orb icons; sw.js (cache-first shell + hls.js, stale-while-revalidate for JSON-over-relay, never caches streams) - CSP gains worker-src + manifest-src; relay sends no-store on /relay + /probe so the SW is the sole metadata freshness authority; webmanifest MIME fix Docs: README de-emojified (title only) and reframed as a peer parallel build. Verified: SSRF probes blocked, legit probe + cache, new headers present, PWA assets served, parser tests 8/8, JS syntax clean, zero Rust warnings. Co-Authored-By: Claude Opus 4.8 --- README.md | 22 +++--- server/src/main.rs | 97 +++++++++++++++++++++++-- server/src/relay.rs | 95 +++++++++++++++++++++++++ web/app.js | 44 ++++++++---- web/epg-worker.js | 17 +++++ web/guide.js | 15 ++++ web/health.js | 118 +++++++++++++++++++++++++++++++ web/icons/apple-touch-icon.png | Bin 0 -> 13155 bytes web/icons/icon-192.png | Bin 0 -> 14251 bytes web/icons/icon-512.png | Bin 0 -> 54582 bytes web/icons/icon-maskable-512.png | Bin 0 -> 54582 bytes web/icons/orb.svg | 50 +++++++++++++ web/index.html | 6 ++ web/lib/xmltv-parse.js | 112 +++++++++++++++++++++++++++++ web/manifest.webmanifest | 17 +++++ web/memory.js | 78 ++++++++++++++++++++ web/player.js | 3 + web/providers/iptv-org.js | 69 +++++++++--------- web/providers/mock.js | 1 + web/providers/source-provider.js | 3 +- web/styles.css | 6 ++ web/sw.js | 86 ++++++++++++++++++++++ web/zapper.js | 20 ++++-- 23 files changed, 789 insertions(+), 70 deletions(-) create mode 100644 web/epg-worker.js create mode 100644 web/health.js create mode 100644 web/icons/apple-touch-icon.png create mode 100644 web/icons/icon-192.png create mode 100644 web/icons/icon-512.png create mode 100644 web/icons/icon-maskable-512.png create mode 100644 web/icons/orb.svg create mode 100644 web/lib/xmltv-parse.js create mode 100644 web/manifest.webmanifest create mode 100644 web/memory.js create mode 100644 web/sw.js diff --git a/README.md b/README.md index 148d457..e54e24c 100644 --- a/README.md +++ b/README.md @@ -23,18 +23,18 @@ It is built around one idea: **a channel is "a named thing on a guide that resol > **"Purple team"** here is a security *identity* (red offense + blue defense), not a color. The palette stays red/black; the wizard theme is naming and lore on top of clear, accessible function. -This is a side project built side-by-side with a mentor's reference design (a NAS + ErsatzTV + Raspberry Pi feeding a physical CRT). Same premise — *your media as 24/7 TV channels* — different architecture: portable, browser-based, and security-first. +It is developed as a parallel build to a peer project that takes the same premise — *your media as 24/7 TV channels* — through a different architecture (a NAS + ErsatzTV + Raspberry Pi feeding a physical CRT). This implementation is portable, browser-based, and security-first. ## Features -- 📺 **Authentic CRT presentation** — phosphor glow, scanlines, screen curvature, vignette breathing (all CSS, no WebGL). -- 🔢 **Cable-box channel zapping** — number entry with debounce + 7-segment OSD, channel up/down, last-channel toggle, auto-fading now-playing banner. -- 📡 **"Scrying Static" transitions** — procedural channel-change noise that clears the moment the new stream buffers (reduced-motion aware). -- 🗓️ **The Almanac** — a virtualized, 1994-style scrolling TV guide with now/next, a live current-time playhead, and keyboard navigation. Scales to tens of thousands of channels. -- 🎬 **Immersion stack** — Theater, Dim, and Ambient-backlight modes (à la YouTube), composable and keyboard-driven. -- 🌫️ **Graceful dead-stream handling** — "the orb clouds over" no-signal card, automatic fallback URLs, and auto-skip. -- 🧙 **The Lexicon** — optional in-world vocabulary (guide → *The Almanac*, search → *Scry*) with a one-click "mundane mode"; screen-reader labels always stay plain-English. -- ♿ **Accessible by default** — full keyboard map + help overlay, ARIA roles/live regions, visible focus rings, and a complete `prefers-reduced-motion` kill-switch. +- **Authentic CRT presentation** — phosphor glow, scanlines, screen curvature, vignette breathing (all CSS, no WebGL). +- **Cable-box channel zapping** — number entry with debounce + 7-segment OSD, channel up/down, last-channel toggle, auto-fading now-playing banner. +- **"Scrying Static" transitions** — procedural channel-change noise that clears the moment the new stream buffers (reduced-motion aware). +- **The Almanac** — a virtualized, 1994-style scrolling TV guide with now/next, a live current-time playhead, and keyboard navigation. Scales to tens of thousands of channels. +- **Immersion stack** — Theater, Dim, and Ambient-backlight modes (à la YouTube), composable and keyboard-driven. +- **Graceful dead-stream handling** — "the orb clouds over" no-signal card, automatic fallback URLs, and auto-skip. +- **The Lexicon** — optional in-world vocabulary (guide → *The Almanac*, search → *Scry*) with a one-click "mundane mode"; screen-reader labels always stay plain-English. +- **Accessible by default** — full keyboard map + help overlay, ARIA roles/live regions, visible focus rings, and a complete `prefers-reduced-motion` kill-switch. ## Security posture @@ -150,8 +150,8 @@ This project does **not** host, store, or transmit any media. It indexes **publi ## Acknowledgments -- Inspired by a mentor's NAS → CRT "your movies as 24/7 channels" build. -- Channel data and the public stream index come from the excellent [iptv-org](https://github.com/iptv-org/iptv) community project. +- Developed as a parallel exploration alongside a peer's NAS-to-CRT "media as 24/7 channels" project. +- Channel data and the public stream index come from the [iptv-org](https://github.com/iptv-org/iptv) community project. ## License diff --git a/server/src/main.rs b/server/src/main.rs index e02939c..ab7a9a4 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -7,12 +7,14 @@ mod relay; mod ssrf; +use std::collections::HashMap; use std::convert::Infallible; +use std::hash::{Hash, Hasher}; use std::net::SocketAddr; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicU64, Ordering}; -use std::sync::Arc; -use std::time::Instant; +use std::sync::{Arc, Mutex}; +use std::time::{Duration, Instant}; use bytes::Bytes; use http_body_util::Full; @@ -27,11 +29,13 @@ use tokio_rustls::TlsConnector; use url::Url; use relay::{ - build_tls_connector, fetch_validated, looks_like_manifest, max_for, rewrite_manifest, + build_tls_connector, fetch_validated, looks_like_manifest, max_for, probe, rewrite_manifest, RelayError, }; const MAX_INFLIGHT_RELAY: usize = 32; +const PROBE_TIMEOUT: Duration = Duration::from_secs(6); +const PROBE_TTL: Duration = Duration::from_secs(300); #[derive(Default)] struct Metrics { @@ -40,13 +44,19 @@ struct Metrics { relay_upstream_fail: AtomicU64, relay_ratelimit: AtomicU64, relay_bad_request: AtomicU64, + probe_total: AtomicU64, + probe_dead: AtomicU64, } +/// Cached probe result: (recorded_at, ok, status, latency_ms). +type ProbeCacheEntry = (Instant, bool, u16, u64); + struct AppState { web_root: PathBuf, tls: TlsConnector, metrics: Metrics, relay_gate: Semaphore, + probe_cache: Mutex>, } #[tokio::main] @@ -64,6 +74,7 @@ async fn main() { tls: build_tls_connector(), metrics: Metrics::default(), relay_gate: Semaphore::new(MAX_INFLIGHT_RELAY), + probe_cache: Mutex::new(HashMap::new()), }); let listener = TcpListener::bind(bind).await.expect("bind"); @@ -109,6 +120,7 @@ async fn handle( let path = req.uri().path().to_string(); let resp = match path.as_str() { "/relay" => serve_relay(&state, &req).await, + "/probe" => serve_probe(&state, &req).await, "/metrics" => serve_metrics(&state), "/healthz" => text(StatusCode::OK, "ok"), _ => serve_static(&state, &path).await, @@ -190,6 +202,58 @@ async fn serve_relay(state: &AppState, req: &Request) -> Response) -> Response> { + let query = req.uri().query().unwrap_or(""); + let raw = url::form_urlencoded::parse(query.as_bytes()) + .find(|(k, _)| k == "url") + .map(|(_, v)| v.into_owned()); + let Some(raw) = raw else { + return json(StatusCode::BAD_REQUEST, "{\"ok\":false,\"status\":0,\"latency_ms\":0}"); + }; + let parsed = match Url::parse(&raw) { + Ok(u) if u.scheme() == "https" => u, + _ => return json(StatusCode::BAD_REQUEST, "{\"ok\":false,\"status\":0,\"latency_ms\":0}"), + }; + + // hash the URL for the cache key (never store the raw URL — token hygiene) + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + raw.hash(&mut hasher); + let key = hasher.finish(); + + if let Ok(cache) = state.probe_cache.lock() { + if let Some((ts, ok, status, ms)) = cache.get(&key) { + if ts.elapsed() < PROBE_TTL { + return json(StatusCode::OK, &probe_json(*ok, *status, *ms)); + } + } + } + + let _permit = match state.relay_gate.try_acquire() { + Ok(p) => p, + Err(_) => { + state.metrics.relay_ratelimit.fetch_add(1, Ordering::Relaxed); + return json(StatusCode::SERVICE_UNAVAILABLE, "{\"ok\":false,\"status\":0,\"latency_ms\":0}"); + } + }; + + let outcome = probe(&state.tls, &parsed, PROBE_TIMEOUT).await; + state.metrics.probe_total.fetch_add(1, Ordering::Relaxed); + if !outcome.ok { + state.metrics.probe_dead.fetch_add(1, Ordering::Relaxed); + } + if let Ok(mut cache) = state.probe_cache.lock() { + cache.insert(key, (Instant::now(), outcome.ok, outcome.status, outcome.latency_ms)); + } + log_line("probe", if outcome.ok { "live" } else { "dead" }, parsed.host_str(), Some(outcome.latency_ms)); + json(StatusCode::OK, &probe_json(outcome.ok, outcome.status, outcome.latency_ms)) +} + +fn probe_json(ok: bool, status: u16, ms: u64) -> String { + format!("{{\"ok\":{ok},\"status\":{status},\"latency_ms\":{ms}}}") +} + // ----------------------------- /metrics ---------------------------------- fn serve_metrics(state: &AppState) -> Response> { @@ -201,12 +265,18 @@ fn serve_metrics(state: &AppState) -> Response> { orb_relay_total{{event=\"ssrf_block\"}} {}\n\ orb_relay_total{{event=\"upstream_fail\"}} {}\n\ orb_relay_total{{event=\"ratelimit\"}} {}\n\ - orb_relay_total{{event=\"bad_request\"}} {}\n", + orb_relay_total{{event=\"bad_request\"}} {}\n\ + # HELP orb_probe_total Health probes performed.\n\ + # TYPE orb_probe_total counter\n\ + orb_probe_total{{result=\"all\"}} {}\n\ + orb_probe_total{{result=\"dead\"}} {}\n", m.relay_ok.load(Ordering::Relaxed), m.relay_ssrf_block.load(Ordering::Relaxed), m.relay_upstream_fail.load(Ordering::Relaxed), m.relay_ratelimit.load(Ordering::Relaxed), m.relay_bad_request.load(Ordering::Relaxed), + m.probe_total.load(Ordering::Relaxed), + m.probe_dead.load(Ordering::Relaxed), ); bytes_resp(StatusCode::OK, "text/plain; version=0.0.4", Bytes::from(body)) } @@ -250,6 +320,7 @@ fn content_type_for(p: &Path) -> &'static str { Some("js") | Some("mjs") => "text/javascript; charset=utf-8", Some("css") => "text/css; charset=utf-8", Some("json") => "application/json", + Some("webmanifest") => "application/manifest+json", Some("svg") => "image/svg+xml", Some("png") => "image/png", Some("jpg") | Some("jpeg") => "image/jpeg", @@ -273,8 +344,9 @@ fn with_security_headers(mut resp: Response>, path: &str) -> Respons "Content-Security-Policy", hyper::header::HeaderValue::from_static( "default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' https: data:; \ - media-src 'self' blob:; connect-src 'self'; font-src 'self'; object-src 'none'; \ - base-uri 'none'; frame-src 'none'; form-action 'none'; frame-ancestors 'none'", + media-src 'self' blob:; connect-src 'self'; font-src 'self'; worker-src 'self'; \ + manifest-src 'self'; object-src 'none'; base-uri 'none'; frame-src 'none'; \ + form-action 'none'; frame-ancestors 'none'", ), ); h.insert("X-Content-Type-Options", hyper::header::HeaderValue::from_static("nosniff")); @@ -289,7 +361,14 @@ fn with_security_headers(mut resp: Response>, path: &str) -> Respons "Strict-Transport-Security", hyper::header::HeaderValue::from_static("max-age=31536000"), ); - let _ = path; + // Live stream + probe traffic is never cached: the service worker is the sole + // freshness authority, and it only caches static shell + JSON metadata. + if path == "/relay" || path == "/probe" { + h.insert( + hyper::header::CACHE_CONTROL, + hyper::header::HeaderValue::from_static("no-store"), + ); + } resp } @@ -305,6 +384,10 @@ fn text(status: StatusCode, msg: &str) -> Response> { bytes_resp(status, "text/plain; charset=utf-8", Bytes::from(msg.to_string())) } +fn json(status: StatusCode, body: &str) -> Response> { + bytes_resp(status, "application/json", Bytes::from(body.to_string())) +} + /// Structured one-line JSON log. We log host (not full URL) + outcome — query /// strings can carry stream tokens, so the raw URL is never recorded. fn log_line(event: &str, detail: &str, host: Option<&str>, latency_ms: Option) { diff --git a/server/src/relay.rs b/server/src/relay.rs index fd8a211..6a27a69 100644 --- a/server/src/relay.rs +++ b/server/src/relay.rs @@ -63,6 +63,13 @@ pub struct Upstream { pub redirects: u32, } +/// Lightweight liveness result for the health prober. +pub struct ProbeOutcome { + pub ok: bool, + pub status: u16, + pub latency_ms: u64, +} + /// Build the shared rustls/TLS connector (webpki roots, explicit ring provider). pub fn build_tls_connector() -> TlsConnector { let mut roots = rustls::RootCertStore::empty(); @@ -201,6 +208,94 @@ pub async fn fetch_validated( } } +/// Open an SSRF-validated HTTPS/1.1 connection and send one request, returning +/// the response status (body is not read — caller decides). Used by the prober. +async fn send_method( + connector: &TlsConnector, + url: &Url, + method: hyper::Method, + range: bool, +) -> Result { + if !is_https(url) { + return Err(RelayError::NotHttps); + } + let host = url.host_str().ok_or(RelayError::BadUrl)?.to_string(); + let port = url.port_or_known_default().unwrap_or(443); + let addr = resolve_and_validate(&host, port) + .await + .map_err(RelayError::Ssrf)?; + let tcp = TcpStream::connect(addr) + .await + .map_err(|e| RelayError::Connect(e.to_string()))?; + let _ = tcp.set_nodelay(true); + let server_name = rustls::pki_types::ServerName::try_from(host.clone()) + .map_err(|_| RelayError::Tls("invalid sni".into()))?; + let tls = connector + .connect(server_name, tcp) + .await + .map_err(|e| RelayError::Tls(e.to_string()))?; + let io = TokioIo::new(tls); + let (mut sender, conn) = http1::handshake(io) + .await + .map_err(|e| RelayError::Http(e.to_string()))?; + tokio::spawn(async move { + let _ = conn.await; + }); + + let mut pq = url.path().to_string(); + if let Some(q) = url.query() { + pq.push('?'); + pq.push_str(q); + } + let mut builder = Request::builder() + .method(method) + .uri(pq) + .header(hyper::header::HOST, host.as_str()) + .header(hyper::header::USER_AGENT, UA) + .header(hyper::header::ACCEPT, "*/*"); + if range { + builder = builder.header(hyper::header::RANGE, "bytes=0-1"); + } + let req = builder + .body(Empty::::new()) + .map_err(|e| RelayError::Http(e.to_string()))?; + let resp = sender + .send_request(req) + .await + .map_err(|e| RelayError::Http(e.to_string()))?; + Ok(resp.status()) +} + +/// Probe a stream URL for liveness: HEAD first, falling back to a ranged GET +/// (many CDNs reject HEAD). Whole thing is time-boxed. +pub async fn probe(connector: &TlsConnector, url: &Url, timeout: std::time::Duration) -> ProbeOutcome { + let started = std::time::Instant::now(); + let result = tokio::time::timeout(timeout, async { + // HEAD + if let Ok(status) = send_method(connector, url, hyper::Method::HEAD, false).await { + if status.is_success() || status.is_redirection() { + return Some(status); + } + } + // ranged GET fallback + if let Ok(status) = send_method(connector, url, hyper::Method::GET, true).await { + return Some(status); + } + None + }) + .await; + + let latency_ms = started.elapsed().as_millis() as u64; + match result { + Ok(Some(status)) => ProbeOutcome { + ok: status.is_success() || status.is_redirection(), + status: status.as_u16(), + latency_ms, + }, + Ok(None) | Err(_) => ProbeOutcome { ok: false, status: 0, latency_ms }, + } +} + /// Heuristic: is this an HLS manifest we should rewrite? pub fn looks_like_manifest(url: &Url, content_type: &str) -> bool { let ct = content_type.to_ascii_lowercase(); diff --git a/web/app.js b/web/app.js index e8718c2..db3ebee 100644 --- a/web/app.js +++ b/web/app.js @@ -7,6 +7,8 @@ import { Player } from './player.js'; import { Zapper } from './zapper.js'; import { Guide } from './guide.js'; import { Ambient } from './ambient.js'; +import { Health } from './health.js'; +import { memory } from './memory.js'; import { applyLexicon, setMundane, isMundane } from './lexicon.js'; const $ = (id) => document.getElementById(id); @@ -44,6 +46,7 @@ function setMode(name, on) { modes[name] = on; els.root.setAttribute(`data-mode-${name}`, String(on)); if (name === 'ambient') on ? ambient.start() : ambient.stop(); + memory.rememberModes(modes); } function toggleMode(name) { setMode(name, !modes[name]); } function collapseModes() { @@ -147,12 +150,27 @@ async function boot() { els.mundane.addEventListener('change', () => setMundane(els.mundane.checked)); els.helpClose.addEventListener('click', () => toggleHelp(false)); + const { agg, label } = pickProviders(); + const hasRelay = !!document.querySelector('meta[name="orb-relay"]'); + ambient = new Ambient(els.video, els.ambientCanvas); player = new Player(els, (msg) => console.warn('[orb] stream fatal:', msg)); - const { agg, label } = pickProviders(); - zapper = new Zapper(els, player, agg); + const health = new Health(agg, hasRelay); + zapper = new Zapper(els, player, agg, { memory, health }); guide = new Guide(els, agg, (ch) => zapper.tune(ch)); + // Health results → guide reliability glyphs (and the Oracle's history). + health.onResult = (id, state) => guide.setHealth(id, state !== 'dead'); + + // The Oracle's Memory: restore last session. + els.vol.value = Math.round((memory.settings.volume ?? 1) * 100); + player.video.volume = memory.settings.volume ?? 1; + player.video.muted = !!memory.settings.muted; + player._syncMute?.(); + for (const m of ['theater', 'dim', 'ambient']) { + if (memory.settings.modes?.[m]) setMode(m, true); + } + els.btnChup.addEventListener('click', () => zapper.tuneToIndexOffset(-1)); els.btnChdn.addEventListener('click', () => zapper.tuneToIndexOffset(+1)); els.btnGuide.addEventListener('click', () => guide.toggle()); @@ -163,22 +181,24 @@ async function boot() { try { const channels = await agg.listAllChannels(); console.info(`[orb] ${label} provider: ${channels.length} channels`); - if (channels.length) await zapper.tune(channels[0]); - runHealthPass(agg, guide); + if (channels.length) { + // resurrect last channel if it still exists, else first + const last = memory.lastChannelId && agg.getChannel(memory.lastChannelId); + await zapper.tune(last || channels[0]); + } + // probe a bounded sample so the guide gets reliability glyphs without a stampede + health.probeMany(channels.slice(0, 60)); } catch (e) { console.error('[orb] boot failed:', e); player._showNoSignal?.(); } } -// background health pass → guide skull glyphs (Oracle's Memory seed) -async function runHealthPass(agg, guide) { - for (const ch of agg.channels) { - const owner = agg.providers.get(ch.source); - if (!owner?.healthCheck) continue; - try { const r = await owner.healthCheck(ch.id); guide.setHealth(ch.id, r.ok); } - catch { guide.setHealth(ch.id, false); } - } +// Register the service worker (PWA / offline shell). Best-effort; never blocks boot. +if ('serviceWorker' in navigator) { + window.addEventListener('load', () => { + navigator.serviceWorker.register('/sw.js').catch((e) => console.warn('[orb] sw:', e)); + }); } boot(); diff --git a/web/epg-worker.js b/web/epg-worker.js new file mode 100644 index 0000000..a29437c --- /dev/null +++ b/web/epg-worker.js @@ -0,0 +1,17 @@ +// epg-worker.js — module worker that parses XMLTV off the main thread. +// +// Keeps the guide responsive when a 50MB+ EPG feed lands: the expensive parse +// happens here, the main thread only receives the finished program array. +// Launched as `new Worker('./epg-worker.js', { type: 'module' })`. + +import { parseXmltv } from './lib/xmltv-parse.js'; + +self.onmessage = (e) => { + const { id, xml } = e.data || {}; + try { + const programs = parseXmltv(xml); + self.postMessage({ id, ok: true, programs }); + } catch (err) { + self.postMessage({ id, ok: false, error: String(err) }); + } +}; diff --git a/web/guide.js b/web/guide.js index a5800d2..7eab78f 100644 --- a/web/guide.js +++ b/web/guide.js @@ -1,6 +1,8 @@ // guide.js — "The Almanac": 1994-style scrolling EPG overlay. // Virtualized rows (fixed height) so thousands of channels stay smooth. +import { memory } from './memory.js'; + const ROW_H = 46; const CH_COL = 150; const HOUR_W = 180; // px per hour @@ -126,6 +128,19 @@ export class Guide { const sk = document.createElement('span'); sk.className = 'skull'; sk.textContent = '☠'; sk.title = 'no signal'; cell.appendChild(sk); } + // pin (Oracle's Memory) — click the rune to inscribe/banish a channel + const pin = document.createElement('button'); + pin.className = 'pin' + (memory.isPinned(ch.id) ? ' on' : ''); + pin.textContent = memory.isPinned(ch.id) ? '★' : '☆'; + pin.setAttribute('aria-label', memory.isPinned(ch.id) ? 'Unpin channel' : 'Pin channel'); + pin.addEventListener('click', (e) => { + e.stopPropagation(); + const on = memory.togglePin(ch.id); + pin.classList.toggle('on', on); + pin.textContent = on ? '★' : '☆'; + pin.setAttribute('aria-label', on ? 'Unpin channel' : 'Pin channel'); + }); + cell.appendChild(pin); cell.addEventListener('click', () => { this.onTune(ch); this.hide(); }); const progs = document.createElement('div'); diff --git a/web/health.js b/web/health.js new file mode 100644 index 0000000..adab3a5 --- /dev/null +++ b/web/health.js @@ -0,0 +1,118 @@ +// health.js — stream health prober + scoring (upgrade #4). +// +// Lazy + bounded: we probe the current channel and whatever guide rows are +// visible, never the whole catalog (respects upstreams, scales to ~39k). Results +// are cached in-memory (short TTL) and folded into the Oracle's Memory uptime +// history. Uses the relay's /probe endpoint when available; falls back to the +// provider's own healthCheck on a plain static server. + +import { memory } from './memory.js'; + +const TTL_MS = 5 * 60 * 1000; // re-probe a channel at most this often +const SLOW_MS = 4000; // 2xx but slower than this → "degraded" +const POOL = 6; // max concurrent probes + +/** @typedef {'live'|'degraded'|'dead'} HealthState */ + +export class Health { + /** + * @param {import('./providers/source-provider.js').ChannelAggregator} agg + * @param {boolean} hasRelay is the same-origin /probe endpoint available? + */ + constructor(agg, hasRelay) { + this.agg = agg; + this.hasRelay = hasRelay; + this._cache = new Map(); // id -> { state, ts } + this._inflight = new Map(); // id -> Promise + this._queue = []; + this._active = 0; + /** @type {(id:string, state:HealthState)=>void} */ + this.onResult = () => {}; + } + + /** Cached state without triggering a probe (for instant render / auto-skip). */ + cached(id) { + const c = this._cache.get(id); + if (c) return c.state; + return memory.reliability(id)?.last ?? null; + } + + isKnownDead(id) { return this.cached(id) === 'dead'; } + + /** Probe one channel (deduped, TTL-cached). */ + async probe(channel) { + const id = channel.id; + const c = this._cache.get(id); + if (c && Date.now() - c.ts < TTL_MS) return c.state; + if (this._inflight.has(id)) return this._inflight.get(id); + + const p = this._enqueue(channel).then((state) => { + this._cache.set(id, { state, ts: Date.now() }); + this._inflight.delete(id); + memory.recordHealth(id, state); + this.onResult(id, state); + return state; + }); + this._inflight.set(id, p); + return p; + } + + /** Probe many with bounded concurrency (fire-and-forget UI updates). */ + probeMany(channels) { + for (const ch of channels) { + if (!ch) continue; + const c = this._cache.get(ch.id); + if (c && Date.now() - c.ts < TTL_MS) continue; + this.probe(ch); + } + } + + // ---- internal pool ---- + _enqueue(channel) { + return new Promise((resolve) => { + this._queue.push({ channel, resolve }); + this._pump(); + }); + } + _pump() { + while (this._active < POOL && this._queue.length) { + const { channel, resolve } = this._queue.shift(); + this._active++; + this._runOne(channel).then((state) => { + this._active--; + resolve(state); + this._pump(); + }); + } + } + + /** @returns {Promise} */ + async _runOne(channel) { + const raw = channel.probeUrls && channel.probeUrls[0]; + if (this.hasRelay && raw) { + try { + const t0 = performance.now(); + const r = await fetch('/probe?url=' + encodeURIComponent(raw), { + credentials: 'omit', referrerPolicy: 'no-referrer', + }); + if (r.ok) { + const j = await r.json(); + if (!j.ok) return 'dead'; + const ms = j.latency_ms ?? (performance.now() - t0); + return ms >= SLOW_MS ? 'degraded' : 'live'; + } + // 4xx/5xx from /probe means policy block or upstream fail + return 'dead'; + } catch { + return 'dead'; + } + } + // fallback: provider-native check (mock / static server) + const owner = this.agg.providers.get(channel.source); + if (owner?.healthCheck) { + try { const r = await owner.healthCheck(channel.id); return r.ok ? 'live' : 'dead'; } + catch { return 'dead'; } + } + return 'live'; + } +} diff --git a/web/icons/apple-touch-icon.png b/web/icons/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..86f908b50bfe7b57de40743950109e8c20fe81b0 GIT binary patch literal 13155 zcmb7r^-~+p^LG*g1TC%sLa-n$?he5zUJ3ZoPft9`wo|M!)R(?B$+TEHz}ime&M=G}e(iENrDiT)28>2M zZ(Id@Qj=M43}y;bKu0?-D%u&tLc_cx611(fuB1?)g%3oc?aK(+_@L0DNYy+h@?RR^ zabP|W3n=ol0X%}yWtd=u7ZZExC){0x6~_n$LfXBPJFdd{lb#p}V{sQxBofWN5^-Oa zVW55+^DJs+g$g4|FYFUdcrs%tpI*d#EERnI<|uQG=@%Z9*G#YL$;@tdYH=c$ScZV! z7aSem%R*fEuT;5MJdqkKYGSSr(Ab$;R9t#i+Mrg6m~tS5AU>p@w}XL7lPY zvZmw?zGR(XHvt zWZq%ED#LqKxUTdY2NSZx_*F#*owTlCLKYUG||>A;kdj%ViJMZm4rv zd(nPlsfmFA{0ajL=_g9Lgo@uJ)qYkN4lV7`!8G`RFhp{q2?@R?p2?VCnk5S&SIb@w zCj>HWyYW(MbykD*pRrRo-)^Y4mjCs4t~ig>KV4Kjm8;|B?ukv7WWQBqFAUWA`Z-Gu z(({9;&QK`NijJL|vX``bg%Yd#7gq2X;Z2r~>~hH5H^ZX>)P)uaoZcGNTo`0wW**yD z*%(XtSEQ^u5CHz7<<2X%;xOa;c{(Z@w0auT?t8ns>08rMVy$Ae-adVl>mhD zs#zOnroSWv!;mj0>{oLo9D*zC~tW zWrTLj&AN@%#e4SSzp-=gG_jnDg+t{pGyjc~h!gSJizFjn2bTeot86W2O%5*nTwO0m zhkeVZZ|_G(-|g??uUc;RXdt-D^^SQqw7Q687-Mz&K$yNvg$?4Tci5WT9k%Wlznwh4 zO*Z{GpwQ`a2yek!?D?hu*^dfF?{Qce_Uz#1M|h6y??-KI@mE(=OPEn_eP^`!ufbb$MLyW-l!`FX{{ z*Ras#)P4%m{u&&_i#57fTU(~SaHQ|b@NiaYT89|4{oii$7W#^;5JA_2mA)KKs8L(# z|6}N7e{MV@+!BH;*aI%s)*MN{$X;4lxF4RIJG4nA#zEo3Fo*zOw?`?vaPHze7MAIsR{w>|Uo!U4F`eCXr|=+rc4Y^ELGo8Z zaIPt24f@cA_L%MUSgWh;P6Fra+`UgkFs9X-qvj?0K`I!ZQJ!L0??=zF%-=z3nD2mJ z_kMg|Kmc>8@N=p07yaIElpIX`YHpL$r709cjtl1F1Zws;C;>7pCp&5; zuD;`KX%CKlt%@oBj3nSYQ*hD`=-%Jgto|xh>%6veU|;_OgUP@%o56mW zhgbtka0z=rYsy18hm=N)fxR;M1teHuxq0{gT=9~VxlyisaSv)1GpVQ8(=`8V*z3jGg%GU*o&UR+x zwmUuK|7^dv?+s@>db-`q=MY+h%KDU+gbeU3*O(d;slNB; zo02`lYUks%kNi1*mF?VAFdOUgWfAp{a(IdM(uFq?|w zdB@{nN(upchX7S+=GBpi{Lll+!X5OJbHL&zY6FS6C(-WYupP=*4!<0|}DMx^M`9TG_)s=NN(-Pc&b zpB0(>Kx26tCZY*ezdSdw{8sTAtcAu@vul(v=mISV{c1y# zEMJdoioe!hbh{o*!wT+!WXG6#S!Vrle0u?e#tM-vFE>~W;^dI7%6lxGpG{5a8W{nF zJ?mExUE#5Hf*^nZHjD;y+@GbzO44a&INjC}1k=HS=0nK51}Y+Xe^{~#XxLKqR&(t? zQvA^2d?zma7#4c%=(johltY=Wkb`4R;N_X>`d?Bgru@ia;)t$-^UFN(%irn}zSp(g zA=d1^;yRlW1{z!#GGH=L-aT%t&Lo=9YsyTdT-IMWL%NE z=ESck?ua`7d#yhexhna3DseplfQ_1SJZUt{V=9gGUIXFtE`9gh6{n<-a^Ap2kc*|y zpVq7=M8DIbS^~M6k(rU#?T~71^M@{`R|J+gpsetd&gpG3XF~3ZRM@&-B`%0>MBR6J za6LbWzgab19+iD~*Oi8K{X^k?5mcDkj20kko zDHD^L99XhJ57r%ibcH4Flnx8c-eq^={h(D(jBDtdj56(t8d{A*=TZ?awlv=)EG+El zcrSr)pkT$~yWy<(EYL55Ib}rz2&QxwgGc$o-qB=kfqXvbXq+hw{STclW7@M^fZP^Q zNCv907TSa!hs%s7MAaeRxN2h;=JF;-zYKz7_TqR3-AMw7eugFE9^0#_bu@fG7&e_Z z0wzGyB>rc=nFh4%lSa|ezTkZ|CrC^rzZ}zdjlUI1V|isXz>uMU!T+M&aN?>4OMz#T z#~~6UtT%imj>bU7REl*C2Xe7N1e4;0wmbX#L(VWi8V^oMd!D5GS8>g?*-IzY%apc| zdTywu-fs^M{^EYuXG$hTMRgkW7HkCX)&dEf?EeWecuR76Iy3xjHi%1}MMVXn_~+oa zLwNH-ZB->_d9cAa;ZrRPVBYx>dLg9;1_9!ewUEg7CKX2iK1AWlG*0Lt%@*X%=oACX z&}T0T_fj07aHN3GluhKehmi1+&*pI6!Qor(;x0}j_m6XikJSf|NPRcW*LC>fP6R9obQ~4B@A>4mG_svE4tSYQ{zqmy zMa)_hgZ+Mv`-33EzfaLAp)QiLI83i?**ru$z{IlXzNmkWQdczD_M!bmgw#KywE2M< z05c2Z3mjR3oJ}Ym}oo3o{EQ(-sIWWn!)%H=h+F z3LuPc!gt_4hH|NziLj>N%L)!@CN61dCcRZ4=Lw_mY24}=2fokv-YyqM^N+tsi+);w zao@uJIYzr@&7gc@eyt0`D~=y*06Fnm`FKX(?)mv}G4VSWlpj-dvEIg8t2di9o@YmU zuY)vcxj%k?``6*|{=$8AN@YQ2(L^}}G8>8)b9;!9MAOg*qT@r!0-GG*nZvcptT6d* z7V6E*HY8UzZc;f-Kq^P;h%rjKc8vS`F7_O$DO9r&E`qtjEiV3Sc(}FjAVKNX$6qPB z{mFz%PKE=6%i}&8+|ob33;yQJWwVieO9n`{u1f15<4ek`y~cTIoY|tTGsN2whS?o> zv|K1IC2zMr8+ADC4mRd{Zh_Umm8F9N(7r7K42F8}f=CqHYxS{^0gF4WAH76vE(Uxo zt81;DLY7AMjcau{w@&WP>+0g{?F$}n_ZZ;@MOz-mof*^so_b&>0=YC2CWD9Y` zFTP4p1AvPX!j}_!(^C;43`MvUNJ1yB>S?&=icBFpAoldBwpJQ5+wXNt5p-No9ya;z*&- z2Km7ST?|yQs1Dt9a5aA@8OkE$l6DFpLh~aDl(0adZ98h!a!LqnH(2afkXwuQJf=Mp#J_9@y;Ji8Cks}0ZKKKo>@ZOJTck6 zM;o(ZSNgQbRpZ>Y`oB+^Ql>ItvPK4+s=8FMPXK*onNrVADCTIA9^mcqdd65Eg67Dt zv7>@pii=a{Dgls3#@d$7T=4g%JZ3O>Wi@WTpE3aBz@NRE3A&QjXBtc*; zEToKFqD&pT7GzTz$X5u`W@@kTu_wTzO`>#<6Jq~ahYZ}|eQhv-k+{9`_FvU!4L@5y z$=UmU8~6yEbZF5p7WW5gd#m6+$kEWivv3j!c!^6Ie5%ZB9447L?+}pFNQVHL4{Iu}ihZuEBT@vuY zL<4a^2!I>61TnYGe1_Jah7G9ot}+E~7VG#~{86s8dV)xEPW&K(%QN@Cb9JVZw#(lX zRLIR(Jf#Cp+^Ylo(>3e9gO6-F9yP7scP`Lfc!F?=%~{hVQ5IZ;iJ#m2-8Vl}Q$pnc z!e2!uD476o0_^TFf11byEC128ROQZU52cacEcJ^OZGROp&etvS^)R36y2`drF{_hz zVqLFoyy~T|=4NLz-!lZK4_J=9FF6brvEJ7Buo5i=g{`9a_f zXJp#jm{e4smYic)vGQ7{tuznJC zZmG$|hLdI3wR__>H`i%wnj6t%IPt-(B_al^5Tql6Sq_>g{aJ4~;aXgrd%5Ab*;2Uy z^8l7;Y?|XAyu32%)Hp$vC6QQ{#-6NB7ELsajGo*G@Kv_Iw(MMArcxt0)&_gN%??ZPmK{+xtk`D|EQlf?P>Qz}jmUCEip zJ~`3hcYOe0g-+d)^{$Qu^XD=Kk<2bd?MDoVY&^A-aGp{=N;x=KnM3$r_H*4Dn`Qd4 zZaA

V%PxUF(jG?blW?hS~1;_d**um(^^TA5Q$o>w&0qzN#@|O5QWOe;)*dB0+@= zn(eFPvp%D(t|CU;4y3$XknzI=ncW9$z=0GD!S!x-i#v<;iwp@B+8{59%ecQzWHX5D zSnV9915EzJbQQ*mg*)9O2iOa3ZJC%Ek7BWpBf?X0z@m0KQL}GCATryAU}pXoQ&S?AR40fv1D;1(6cd(eq#B7r z7za95uJ`fl(5i2$U##H6hzw(D8;Xg%fO)ib(1o@6H@+(#Z7?G@9G+0I?qg5E3@6!X za|+SMz+;vRg+M^EjDV(dwsK!04Ae8i-cH7<0$w6B6eMMPrFh__^gy!o*qVb0{P2^Rt$F6K^$@OS<(PfLKPEbh+qSK_@_)W4*`fHYhoL?0EtbH%6kOaD~{akfy zqflKJl0JjL04d<&Oem_!aP16GGL=lTmRua$4hU+n4#?g_p*cAX75geqjAQN-?}18* z5}9aL7pTv|MF`mIBt4Wifscb2B_{si9$%}hj*&WuZ(SBN_=-J$h4@8*qU{k-wct-X zn$IYikaxPT5>ONMEO%aK*5(1{TSbASDGzH{e!ZX!Ah9gtCNk?%s2;jZ`y~s_cd?aW zCCE7$F`ww_q0Ft!wwD0e%g@*8<4p(}_sVDCdg_D)rgN4b7XUaqc^yQH<4CMl$$DGC z4OlAI9TOs?!v|${xDC}auo8Smg4p{+3~+d^sUSP-leTmLN;(Vm3JwrsBf}|aKkn)R zsc4m=i1^08RYd3}Hw`6hiFVGX-!VE${pYyM%W14Bi$K+o!F z5TmpNf#!h=WV$cZvXF#CP2@%T=Bo9Hom}y zCcB7-A?4zVZthm(3<=TWzE|skKS-*a8FzA{L5HW&>;q?HX7aSfonagkuF5f*G*pzd zRWr*|0EOz;TFlg}txolsYJC_iP1EziR={t5a(1fJ22EY;>gwPGi zM*(oOiQhvKX9|5llHB7}R_3RWp}ejzwS6N8Dv?IKLUeH=V7((=?S_>5)A|=XrwWEe z9oR1RS@PJWbGRocxJ1#j9XU(RIfzw%xUD=9mPkIr;66)MOX)MgKrj5$v0 z^lR$%mHhITheaN%%Lncimmp_#Jada z6mv4e;gssaf}OGTuy$M=d%uO_a+!RXn_#xYYqHO$5=U$t7J5U7d7KR%?kIJ}!r|dI zQw+No8fJUXAo5e3pRHz4q1I|iaSiVMTKJp=u9+@sCW+m&2FLd#Ryoi1&_u`Hhb;z4 zo{VF8bg@B%sv0fo6u$=PJ9$N|w^ug`(-rJ?*@_e#O3~(e^=tO6w>g@-k*1n39x_IB z2=iK`P6oLfHQ_zCWgDSOn$5h6Hx_AyO$i2Fe2i2V zhq+cF`yRmnKJ0zY0Cn70RRmGSozACvShEhh||VIDKO5~U^qUWU@wBDE*Rf@!Fk&*0nM=&s>TnGpb{K4E7qZ*p#bKf zvdXQK5StM-gz(Y)nGFX3%eeaOwj#&Vu_F~bug|%0HCKH^Hhh9+eV0i7JuMT zcE>!@gf*e<8Y;W=`WV}A>+IAWFSH*3AjSV57vR1tOMg?blCf5gha{}>)whT!&xmn) zg%)(FZz>bKnT?KUN88`@i>pUh=Nq2Umw!8)Md&)N`q67?Na8jgZYm%d9TBk3jn_KsSFdcY&a)s=s<_iYz#HiUU@9^o^W zWVt*}{d;<3^ebg=tWNUH^H;rXgZ}B{eE*(x=Fr`G@EG<|#rTH-qt z#})#-Z*mq_St1X$j<`o>>g10py~3epSFbm;)s`!6G(Hygr~aI>Ykt-7-hDG^VKGEx zhLbgWUsRrkNHOIlutIwN-@B)HQ(MVxmEC+~PO3-?25=>5hgJK60C}JwG+@w>B2Oq< zdVP|o4D#P0*~9NvS5ohZ_Jvl>Bfgy&zoo6gbHi3 zCNMO0FEb?d#7OVn#v!y$PK(UaRMC3lST8#n9HqY3RQzFZ6Jz8`7p6hcbJbih`v`H` zW;a(RS8cJ~b-8an`EKBrRfCUJ7ozfUb>vhd6T@Uj<5XDJV(eII-oJE)yUS}vW zp+e6FL>E>Af1WjtanKQNsq>5%JFm6S*&6iZV!O%)O%7eqm!sek;mu?Y2IikvA(IoTSyq zt|)pA_Yg_<(LVq5t9D=pj+83WW(1{AFCuCT`Lh07_Wn|%n)6LdqQOiv^#O;5(^6g^ zleM9MA+FNSvLa=Axc;$tl3KA%usND- z%*<29%uxH2AR)z+xU+XWl|mHOA%<)=ZXM-La^h+FP+{fP-r?H#OO<9=ELDxKrk|aB z=zEC3Wf({@0sDNr0L+I0*f+=Qd}0|q-2bfrx}LrxuEX?DyJVi^$5!w*#?kjGo@M|_ z@rd8rR8zhmOcHg$3yrpJz8Xr%{>rOO{`pE)m8yzI2GDXvLajY4$II22lrUInJ%uIO z`v8vjzTpRuASAa!WE6{JUR2!P%o^exWxSQASX!4A&mYs06D8ungcifIy|{M z=U=pTc(kp}F1Q&dF@N6vz-axWV2qRc1`Dv{zWax*d0`N&SSjL|uy+x^g<$4~N>r?j zQfD2R&c>3ow6dn$Ei(za%`X1qT=AGmc$f`xpxFU9$ligxjayUXHqI}E1+f}5G{lj^iSF1%~2nF0;kGm zP_ON!$EjZ3fXM@$WPsbO&V}FxCn3fhRThwXkK=r)swlA;Ae}1JZ`8_TmNcYO5pCCpaM?}|LbCPb%jgYvuiMy8GMn!{|PsCao5X8qX z6m|8Zq&M%)JBHqN%$8-2$4}mijVew@Z#}MGKz5nNCFb`6oO!MmCqD;l^$`>-g|5Ek zgnm}iB_f7Ww08puIoF_smz;z5Uh{INK=FsS|X z*4Emr^`)e#8i6-6|3M;E#w^5|zJ&f!ae(wQnNpfupYBaR++mJABA?hnP7upPsmz(R z2#If`<#+huqebA;cAk_Kna9(kFIJQpaekqGqjhP%5dEP4T~ z{_O6y#acE;5~e6fx4-l*;@ilcV(Q*~zs-zPUCuNwe!%*d^O2m%jjfyrS zW|7GL_;WbYjjJ>6joLUfDC3EA(4rshzjG54BD(@phHsYIVqD-o)ir6pZ)KU^JW(Jn zM<<6cJNe~L#h|!|p3qwDeHuO`L3{9e*KE84f_l9HGa_jxlsLncehbuE;iW5C+LNZpVF6rr#7|YlG~PUaF=Tl zF%ZJfGAco!aaL$0`WtITS!g9QN2U91Phn|@U-U_bKIg@CYj_x*PRKcR-5ULhd%QR8NQV5`MoA&laW<(f zSMy#)BwJx81{osvh1_viFD0dmZonA2p`Jd*vR(@IN$oZ5eTm1CwF3{scZZN^Vf2pW znzR-C(X2FKQB%k*_>>ga=)j=fbN;lY9}xQwsz^@hBN^bi7$LX(0anHJ7 zs~hsO(e#d|q(!-g5zIoI%SNQj=_s4*(5|5Cf-rg!eYn`SfoIrwpnGLhp121EdeQG% zRa*)j8OVegRNT&8>$u$cCKr8=$o$`BhDq(pRIC+qvt3w-CY^ zJZq6kK*hV^+NHMBQSN6q9W6~b%auAk)TsU?857y3NW?rGS?$x0{%K(?E5d3=DYjYj z{%5cp4Rx#*IktZ zaaEPAl?yiyTQ9zr#IGIJUiJlZ>I)QamrXdvX~MRg()b8UFllCetmjJN6EbyKWIoq6&{8m zhymlS?C=hVG``1J#SN1r98HOK2G7CWjXE9TMV zV&3|u?b5`AJ6nyHkQ(Pf1Q1+k6_99ZdwjaxDVj%~6H9aJ{(Jo0;r?jh)e1i+Wz@uE zcLFm4pa{T>U&zmQp`FG2@DjyVa&uAu!vOps6C@tPnb-PY!);N_onnKu`~>*IObq{rlk~Z0X!sFuJm)rWL*;A9^O^0FhX@}bn*JFHl!Cq=?@g$xZzCKa@%!JSea9nH zh4twA>=yRDnG+sJr6t3Ins}JWfkcvzgYZzP*X7k0az=eVXOj#SF-)12j^An>VQ)c@ zo(AscewVAO9Y#jCNuz|}AY?!Kx(HVQn-LqI5F)D;7uVRRPZlt@<9oZh>ha=*zZK6u z#~|^-l+19bHVyi7h!%u_mIAx$+qsM31YWJ3hUwCXw%nQC#wVt%-tQc`T@aNM}%f4>)fQD8(AY`K?!Kg26-VIpah3?gw$wID(rZ z*eDo=qAVG5oIY!50{g)Ao~b33f#<_{SwY?;-EdQP95#N~*d(q?5zxA|AS=I8q9 zRhY_8_!DQt1+k2ZI0n)q(K+`!{*Q5DIl?1jZGK)}Mqk(zFXdRP?12n)v0_Sr z_|Gvrn{~LyPU#Azf-!-<3;X-rdD6mg@97QBfWHSWG^nzF74gI(#n^+?ZwQ&+;4q_A zJv)C|P^i;|Zf^^Zjoh!#{9nwr&;CF_1P--- zOgVx+wqj+SrxQqib);yc+shNaGChoUEEyG5yx!gRApbCg5o`RQQg=M({;_G|YI$?2 zG+8i&7{&y(3r3(Nxhy*wub>4-kdi{Gyni7EBk^V28}AvVrJ!^fPoN;J_ydMtleA|! zf;B`ztLQ^iI8!(wVHp_7f&^ht$*nI+ba0MIiHXc-_w~3Ken}H_fj7!pWtJ0CJ7?}G zCji6W>ks}reHm891OGZBCy^ELBj-o-g**j#F>7m2^*oN&mdBQ<689LX{Yg)hfC_*v zdsfey;^RHJE+eWgYUgA_OblC1$0VjCS`wLDWT8P;@m&P?UKHtG)^*tFwf(UMpeMoqF;X;<||uU6NDq^Y4CULM`W#=Kdjrt z15^25`KHxO84mZ{@G6@?iaFD8qiyL5WO%3JYk2 zLs*C~dhas&a8@2%f`nEj_il@c11;k48(BIFN^s#?QHkDGnmSgx`81?XLqFw)o?{TQ zy>d`8XHa+7+<7JF{P>C{t^Yq1fcn>BLs_EHGw2&0kZcV57hc4qNbzu^UPd}VpaIHN zKVQD=L{bDUZ;hd`>|qjZ|7@uL8Zl6_LD3tMWJC{rV;&6pOBCoFLab)eX^xAt=29`_ ztdh4>eDp#V0F!$g4Vq&Y<6g&4rD(|kbZrO$vC{yE%w17fBOXYW<@TLEYZ*)2f3FHySux)6?b$G7FYdO_x_g=LI28)?q}tH6}+*WlsMr1zf{mw zo&o@X0W#tu>Yh2Lxjv4jD|(v&JuV$O*3BhJ9Lf7uK3xq74{*!y#KgwgOzx-@Tu7J^ z0jTgMWaz*(Wf}P@5(rGCau9CfAT=!>2?GzVguJ{8YM-t;v$jdEE#(6mBUj0-ZRWVmch7p5=+bBa2F#I&}n;)e?CD(2|rBn8Zj6~ zikCa*BP1=qPw%s%O2i_t3n|$Z0de*eIWYnK>9uO2fN(kt&qzIQAfh>9&jwx0175O~ z9Lmcm?+m(G4u%b3;eZn5XP&kc1d>70NV=t;&>Z+EcsTuha>e!UD~qxi5E zbCpiU5cryM+e^jTV+1;DB2Uvhn=W2cvpv26m7P{K{&bSW+EbOg69Yo`jh<_Oq=ccK z!K&f#-~SCSa#mdb$?ZIVtR=xm7Mpym(u#03-In-pAA8u3EP($ojk@1?m2Qs^8xMhY zPccZ1+=O7HTnp&a3Y()(sj+Lhi4u_dCAi}PoqfN;$+GfE#G@Lf%KKvyvqX?jda-U_ z`ox39q|m_#xHq1`nEwq23*h;lDO>qo=zg%C>YYRpFowV`&NNcNCNc{M(U|bDy=hZf zTp2O%Q*dG(?75Q(((^F@@Q@QQQZ|stRJUeeo-}@|o%O$vz2~I0vxKX)UxN}bAmRIn zvNK75$Rn4%mEY3;IRm6|#giyz9Z%c~ZMt)94_ zpD|9)1AOaGdv|%54@#2>DwL+M5Ton~p%SK%An$@ex~(Y+DR+a~yIhy1dIyd?wdz`r z4(_{qZob@F#d12BP5rajb(h$~97QB(0wR zlIQdNrRZQNEMc+~6ZH>H053@-WgfireqnFYN2wX%to(PnYZnW~v|rE9Hnoe*?)-{s zh(pk=5mtGhUf!@Q>QV2Kv!uv5QGpKq0Q=%g&fBL_{i_~#_qT?H&ZH8NgFSy)E6_QU zZ2iH-=?B0dFGSqp-#vgHl-?e-GBI`5==Zes1Xy`^_yriqB5{2>v`b_Awzi(my9y)k zU!qCnqKc=AH`rlrewLrx`dR5YpqKkS{)gEs3Hm2FN&d*qIK)JG*<0l5HynoDymmcIdJH+ z@jsicKTn+2DxG!^@Lo^KMkW=y*;9x`AS?3WW>SaWROn=aRmW|sVr~C&=URG|{P>7JH6i%>^zA9GHlcOxQ$cCk0E=X6 zR^b3lMQEP0)G(viR_%3XW#xTc-MU__P-B;$k%yLSX6;lP(y_87P7*tAYQCA?DY>CR8nlH*bL4tl7Q=esOQLNDfh&b zaC_5r>8Txk=^x3!xPovbTP$bXpXua~S+a&A@|~)R&;F`&)45oG7(aZ_=i+~+^YQ8F zY-~>|6N&8~B%ui}vb?|=WR*viOxTLANzFUY%JzA0Z<>;P`Fnd?UHbu3LL3C1b)W>m zCK<*g-Jb|g`+vGD=|7^k%*Ntg;6g)kES!6Md3%#HH-B5Xx-!oa_#Jn>vllx@@#VZ& zD{yvb0C>oP8;QUjbY~bp{#~p1a5G=%Hn_5Kgo~S*GaDKA?_iSziil2xCrmIfkyQ3z z)1UeAPqNs!PUfU~ed20XDySs#eqy}S-|4c^{+{&j5?4EJ+-_&ioyb}cBj(c;dn#2^ z>0#RK6T)PE_2A`zjSV+{ZY1PSk?1aR><5ZDwIb+O*i}2S=-V`sa&k`?=Vq3oZ%Neo zzt?<>y55TEl!R7~^c9nR;S8e3pK+P^m`T5rGC@}|x8y^e>k6n~o(IJN4m!HN=f`6> zYikJ`ZH2yHi$)4k)QtI=Llk=_@Y)-c(dOKAUOPXxV4yNNu6ozvZlRpIXCGQJAk`|y`_jLG`R#-yb)Nx-|Gv|Iq2DrR>SFi2$p?TL$~6bM1#u3#(-qQ{O@dEEz@v=CG;kHNou=iQ!YkU?v{Z+^z&^jszy!ti2D5<_^ zRmqxLex51wm?tjvb-_k4$Mf;zM5kW=^~OJ<8U+_Ap;%D2$n{-hIS7JDHwx%VZ$%t6_b0kd4kq2ztS4h6de<)IIXqNMQn(Z7emFq9#hHpM zv~YSC`Mdqc(~#o*k^U5{>iz{t2Q@cD3^|+@BXK7g1i+KVT4w1ovcFqW%=b4n**VH3 z^&j)vPfIZ^H^GwYrfd;qp}IDqZ;~u%?=PEQ z&DtL0?tv{-89lZT1_(Lq94ke%_3rlZKkKTl#;C8aKR-qK#7@Sl*dag~gS@)!xxO|j zbm++`2G}wU)hNfUtnT_fME!X1>sPwZX!?%l=WVC;MG?G)Jh|l9hzUs|C)D? ze;Kh#?{sCMg8k}>Aw6J5i*K8|qDun=dv&ZepHzHUo~=QKT@Lpp{8%hSfNl{5Y?cxVaeJD!4>vH zi6Dj$6t70*`SFrr9Ab$0$Pt|;2)r1;DYGgr+|~Iq)75p#fkyf&nuqSHY-?;K@Imd5 z>d=Rv*U?JI)2l^pfV0PaRP9I8AHgkJqIBPkMt#Zp4&}*kaaNGD#0^{8_q7R?HiKNh z%0r>afsy#m>mnXKLRFsKNPccx4d z4D}wa>4O2^R(WR-AT}e7o5@3tM4_li&fr0Qz`Pc`|*b?tMFYO~OEsOVeSD^yp3DuJNZdh=^+rwr*w^T`_ z{vu?Ae~=mX6gfo^d0!MUsypMj!qQ%xijb|T;GMVn;Gx#8bVc`7$=|ZIy?lS)xt@ft zQ2j!nTLDmTHBASRTleZZKgoog3I1rttN6<@id2ylhjjq28y@>YkbL9vHceR)7Gaej ziO_s#7+5I!=p@Y`yK0w5auUf*sT;Y|QC6lexb{$Nj+28yS|%tYxdYcG@V|JybPgeMJy3W zFOuSsrRsGydNC6JSqWoSh@BCf7>0h#U<9A|bnrLPdw(qH9(BI~6yr_@928fe57^zE zMeuMp+5Z{nAlY;GfEsseBUnMMe4+d1c`#aPpDeIpEpbP~bBLN2QD&D>q0LVkF40By z@nd8dj`17pVtJ$HfHfQg7BzhdQVG)Oxk?j_PRIA9asOiaciH4IQz)i1Xg)3#KvST6 zL>LT621tW3OOzjpdO|}W{Bz=i$FY(<>0K!8g1!enk`uAq+ImlLEuQA54AN)4cOB;fkm5g8ctNB^5wmxrI=#>OZ* zWhR}na>^NnI223`q85QdLj$28jj{Z_3vul~3Z{6@k>A)bRH{%UW?ieYD4tWqJ<9gc zP9wbY-+wgUo-HiAZ`f9Dd-vPMUq-Y07nJyxBQ^dc6K{n@Jl5rlJTd_+oZ^)-K~zPIl12=b zj--Ynr-EpTa1qlG4-ObDCZkLD^eu#=I~qqQj}E@N zh88<1)!sckJ+T>!<5FmTK2$@36T@TXQl*gFo3}pwYY=*C#rXQc9b{I;1HuA?{{Gx# z_DineCeHc#%hg~ySRu-FPZ?WAMinYcO;Z}Iij*uZjSZ#81_!~4Ql=*BHXFvEEBUe- zX$+b+Ou~X`!kB%F7M>!muQwMheO(Q_Xe8yqC3aO6Gbw$;@;KQd(HC>tp$f=lB686X*o0w1_VHL-sL z@h+GF)IRNV5ISt-WNpci^huH5ISX zoH&z$C>C1m>~zvLF^VxkoeE7@KV`PhE=;v$bk ze5EZ;M70gd;!L!{NTCcUuYtk);r#KZ+Jz(ivviZ&=KOrj-?^=86|le~r3bFqDg=;L zxSS2~bse<+7SE+VuS5tqXq zHB~~u(05&3fr)8%I+BD6g-9`h@CJg3YC|4VpMKjsVgP$r%i2Y5*G!g?E2te6j-BUp z7&J5I>B`lu939y8)OAfqwz1Z+e4547B}xro_+d^Uz10-~)y>H^i6Dk*L?x-mG0CZv zjAvj2W*Za%kr1Ffn?o$L>Iw|Rl0KAQ*kSTXPaI>aR*H(0R^`&05m4V&@nbuZ1*_;2 z&Nlaj(mmF&{9L;K6<$WU)hVO@mAVacB!6`?VBlokVY4%esZq6mASR+r#2YT<1;eHo zfcwG)_^dkkJn`g^ll?k==Pp#3jtHOx01^Rs{=#=#a6iSd0a(e>rZ8$>(&AW}?3yr_ zbSj?19&MUw0HNS{Tor0CR66vqkcfbrm&Jb4f{({qR+n+y-ct4B!La&v_z?%W06-Iq*OSlA-G+vih$1Cy8H>Fk%;~08dzYR& ziOopNFj@)z67!<*T0=BOH8H4H!=>I9f@QexeUn(_tnalg6_cV&HHlt%L!H9GurUa7%UYlhc~7mB1i92k4ekrf_wJn?~ce$ z-=qz2kPPC_(^Fk9)ZX~50(6{js%22U*hv`Dl$5{W8d#Rxwba$qHMJ~8%K3W4o{c4Q zC)JI9MN)jZ=NY*Y@1&v>Dh;fuXlTkR7aC;Pz}~+W7R)VcEXzO!HO|o8tF-CzeIW%p zvpZySAxSdL>e=`$PDxBekfj6upE?{;gx}g-A2Sm59U_}h;JBsK46qNtyD@xOpLmtu z$c5JJd))209M_-nYLb#4ksyihmtJCO0cEOQip}2b8=nM7V95UAys0`mNBi*a886HV z?EHn^i1JgGl0YVUliS|TP&5F*MyYAVG_NY?thI$F;n#W>%E!CY(B#P%$HMDls?%4W zss**Aw3zm66$YT#iX*^Fsz&LPIZ?g+xbCSt|5J3^8$!kB?;2X?*ZJwEf;M<>0RVaz zm5fp`?=oYuXc$VpN91Om6>Y*ub(>rQyp~4)b1qlk3zyqLp+|>@{&1>Ot)vv1Ig(B(sXKBtJBHSD?NtZsm|YFm8tXzY z8H+8NQm}p~s=KTpBg8CD>W<%qZYWcB&pNpRXWR7XvohM)>{AE~snesQVn{D;l)db_1L5p_}49wnAW zv(jzgJe+v57d9f$bhUG(!=1+J49Y-HlPr#8hNcnq6}tok_mc}iS$Q8>!zdne$a+Yv zUpixe`n9BqFri8WOi@o$C6#?Rs(&sqH>agjE2=3=9J1EtQX~@4Ft^3LA*?Y#tv7uu z)+0awRG*(07pyU=4YA~d15)m#5wdH-(d%~y{!K3$l5l!b|K1Sk(zL>9Y_F$M0G0Qd zw=%JbaBl^l0s8c;cE&6sh|uk7}vvND?~*xh1eC1&q$qO(zI z9OGwZ%)nGEimaV^x0Dg{9Kac6aHl-&o6vBPjPylsumV))U%24K0@c|A)e%YjfI~6)5 zJp~P?t2G?=3$KTvsZfd?InXKbMDXfEpAV;FBy!vK`TmW-#^0{08AnYaL}o4^z9xDK zfJdY97Jh? zvBkFTh{}Ap;Vl3IA||g3cmB83h{YS+b8y6r7s_KPK9G2(1%N zHlv*H`%lb;MUFcx`Ev9A%BV`{MitpSSs2TG<{bp{@qED^+n&g>s7~A9P>7uW9)~@; zo!Vv*;qf#W$s!nttpcsGKcoUs2ZNKN$wW1$rZ|{7vLbK=E8`<>2CgjYY*4~vzGxwP zENMGYl%|!P zIU!jqDZ6z_Wn>55Nkfy2V1uC`q`=s`&L>*{XtvdYt>(}(GE5w7cGiQO^Ci$fK3=Rt~Kl9`!u7GcyR!y3T4L0LL8}%TP#fKuR>?fnX(h0m; zzB9exNS5r+S$>$=ze~&KvTZ<*dttgkHw0Fil3U0n*xZ=ZG=Rh(W|4{F8Gda0b+TU2 zWa`l(ilAT#HTc~no(R4H{C_}ii6H6B6F87}&}vWy4>iVCJP@ATv$~3W7#SW2*Y|DS z1V0pVD-nK1E(=Np!%7cfS&?gE-dDKP6_IBG#k0U;A(2dLV=S__dzY1(qk+80AyGh001O?pj)sj8VHNID?a_G^6N$G>)xJ+`JRlnCP^|Xk&HQK zK9aju95BiWLa)PaA+!nirixKPE7^193FUVTG-O$z(1Y&BRFL;Sij~SU#7_cn$`Io+ z4o9E0OntqaF3{ZcWegO5T;s~O=73;*DPwuvb0Phvfu4I-Dl_NcJ5$X6-l- zAMvfwCoNuE*hjgH2JR0>O@a$7?SnNQ1=;5?$*0m%EmaJVH~S1 z?={d_g5xk+6>M%+EghMG-99%qp5Fkg@7*kZs|B{=R}eiIOe6{L{O3@+%Y}4jJNC{u3(!C!5fUo`^7oc6-$~7mv zfl$@V93TorBy55JVZqv2Da|<{SrNtJfTw%SSgH^vM@6@p_QQ0~2bqr#6lp~g?`Jtt zO>833=49VBM0XPoG^^Lx!h)O#72?8SBOw{D$z-@clV)x7Pig3iq!A14Ww;E(!vt8^ zRGKybhGHX;1<7o|0%xPNndUIW`*&(9PeRY;3>p0rM%1t05~;`L`wOL3SSMncI zk9{7~Ge4A?6chbX#np@Vd5oH)gE+v#lu#6x72;V!9)W?k)H0F##gCP77yn@~*luCW-L>PucP$mGI3$8Zh*Qg>IVz?XJN-VT8Ng-~@9O@&t6Y+7coI3To z8*kiT6Z!nTWygQwp;{uZG}yK9<&-g3F={~6uVh-2RL&m&WlRZC{3QJ}9b>zk5~r7e zO^I7}xmZ!frFz-z9=cJ&mtK#XN}X`8V_A)Sbu;Yv#~ONp4S5>Z)1OoE-HGIC$ankj#$^8AEb*^vt>d%!aY8>@~*}Jpx5ZBbS zZnW1df-T&zqXgDsgjl&&Ac( z8(x#@6Yp2t73s{|^SXsM$JV1_7VUR99Hb%?;x9#HN3Q!t5J~xx-CMEkc^}utne`4K z5VQq!>_aWNkC5d?o4+9*eOufu#SQ?Q3!`Qu>D-;fo9<2(ia^NvFmc=1B{4+&@vPp| zm=ZM*H53(X^^10!$?JbZg7k)J)@JL-v%c)5V*U~p_|}6_3Sv*HuzVnh{ImrKAgYb0@Sl@Z!jE~Pj2F&LrbA*@w{7QTi#_Fz}lG<2mBSQ7~tN9%4n*R z7Bp181Imdk^08^|S+;q$pzw7cmhLm8{1oeIi;EZ%sZQo9sK7kf>6r@>GRkLuF=^`g%e40YPw(sOnwm?n^+cen80vys*_$ToFT) zm1&1vot&uv#Q-9(1gR*O=gX<&;Uc9X!5|gIU)z8-FiX!kqXN~@#My&) zkTqttN{_oG8&tEM#USZ{S^To{KM%(1KEKDuE$;4KRE-Q%aY2WPr~RQ;?5z^x7BXu| zL0|I>i7@W^_SPLO`XnNkA88R{W<5U{l!prAFtb}S8GKEMF}u31WoK6!>M9>+9!(b& zvxRHWB3PGHFKBo_MwmN4KkF`Iy}s0pNkuBrv{JWtCzHA|qeoG&F;BbfytMx8mn_wJy;rE%)mH zLka0prKkM}eY)KMV|;=sb%v?zJpY4c8+5ez+0Ydtnl~W9byX}X5v{-nu@-!)z*F`A z&=-66J28HKU)TX=JV{ihK89%R+{CoJq+b|}6ns}|`Vt)cW<+BS&X1#Rmc6b_1XMnK zi7CZar$M+fpsQ~b*M6zkRphh>aEIpxpC3#+y3)pC6B6IQeGqG3Zs799)cYi`tp$9$ zzMH@h`uigFrPe(Q-o?!r?VEwdCN(K|{E@+Z$l7`0}Q$gYo*HB%( zWHHDEd_4=~)J|&tnhzg+o@3YfIF=@=`y?}Ci5mCTv`O0m^qcf7CvU8BilyQ|dZH;Iv8DEMSBAG1O)=dz#edb$>^P9pAkx?DU` zRU5%~N~x@vpuL-^)$Mh1M&j^=2Mg&XuGa2CgitF|v-N!L zY(09IYmO7$jZACH)z3M;GJu_>KwdUS+{nFa!$?$8GlS5!_iuqsBiaZf5D&-QLBT<3 zkn^q-cbT&9)XRELn|m%85WRwBQx^SEf@&=kSGqMO6k&x=D`l56ZdespaOSj1@fzK$ zSlu7$G(5#!q|-BVweyhMX;%WLa?IJT>BK}5cd0?wK;UfjHT=;(jy`(tC#w8lOY{}$ zy8_+5l4g;??{$s>Q>jtkzc)p^;+WoKeUb=>vIJLrx8$a$e`T(U>C)ed7G!;0*WFz5 zep-p`xAcda3LW2z@?T(>9w~me?2VYp z_co8<;K4*t3D1Va@*|EW%Jzj->W0RKm;UDa5XKa7(Ej7Q7&$p7<-_)nM9>2xw|yX; za3_HZwM3Z<2eFMTqlnNa_);f~l>j)vd3*QeTa$&*w~h{)QWpF??^4l17^2^rOjkp; z{e>xBjR;Up2@cKVVVK=cKB>*>FE8izc1V6J zPRIY)L}hm&wt0oZr_+PKDvUrMcn)|CdIUkwpDkWnTvC6`sq!#49>HrL=9xBEl**NCa!>C8;>&d6a>7NRTl6T?)H` zFkE#BwRDC|yfXR$c9Uz#)2;aOM|u8TYePL^(ChI}E=^R}(ix>q_lQHutWGs2P~;-pm1R#tSXQ zeDCw&;Z64+@!ubk)#k|#<{63c!4Socv9+p8Pwuy`nVI$ZnUC4-{60zS9L`sG(Z!`o zc=yaTBMZr3?&@Un+WV{LUl?<1SJ{ zu8a1~1L50!9?#`HQCzET*D6;uTjz^BG=SFA&i8^a$HHAEF{+Jw?xuWkX)|E|L~Y}& zR6hX#i&c?dGw&Si9f8$PWsp2^=D6>$Yn1rgP|R`W>|yHd1by_$1&9(C@8pfxkCe_- zIx>23o}Kj+H5AsWucx+CW_E)LRy0{1#6^5U!ocPK#@JO7{IFj-q;zt6yG%?(&!!){ zT;!%Ic2)dDs^`?1L8UeOR_*u^OSDh9onMXn^!vt#utS-yHoE5DutcDM*YTsx?)K}5 ziLwDHK$fa@*0@alpJ}bT(9K9XsX}-C_U+6TeLB!X?)3q5)?uS9DC6LwqKVzKU2wH& zG}>C2_IfPoG<^W(S^o+LW~=P->yAm*Zi&h6j96GdPGlCZAUy#1`loV%=#NgFuEK;A z3)@wueWC{1IG?`{+ksy&z=qDB81C0d)kThKp0wfRfV<53rWF|DryC}0){ z93J6C|8;L{_{=sfxaX53yoMvN9-*Z;J|mJ?05|%TkWIeen66ST%xiL}ItCH@u(_$} zoX_hDp-%r*mIOi2%BTfz^#N&>I>geX&ox(S;*N18*!$>9vTxm-*ZuLB){dv3%=|}= z)bqv!IFNVwTzqluZpHWL!elH0Sn=8Ep&#PqP2s<{Rie zMm68|tZtHrW^}7^i0~5x_7+k7#CecDx+|q_&$@Zr8ygGb={6@YCg7z`lEOY1h_V{T|h5P}vBA!Zs*B$QW<+Xj~zNV)0`Dyswii^}6ynDzPy4Qhuo8ZSm~}4( zCQ!A*QLg5EuUP3!qJF_=Wfd zfM^1XB1wP%KEOvA0aaSDgpha~Hg@ms^T8-`9bM1o)u)lwQ&FaHS5utUsM5=`=ckp9 z-0cIqt_%xR+sl8L|GBWweu~fO=E`rb!HOs4_;>~EHZ<|jPctDK`p(LmV!s#y>$9pr zP_^VR^ozhBh`Hkw-F{X_XxA-X376%?nJ?g?U2%9QlN?T{o`G8wEQz=JfMy@F6M(|7nkFmugcOFpQ4pjc^@ zyf~uxD8MfI@;7bopT$7l>8vrK`mr#AIs9mbnKY498q;nCpu)cV&&3E>R-D7&&aThR z_A#`-n^Cl2PeT&H7!SFD@rD%)&M1(YhKU4X7NB1!=d25edjkp(8tC`@(kdjr(^X1g z!cYSQZ{_Ey*kX`GM6IQ^&MH@X^z=?aFBhw;Y1Eg3T3CW%@h1Q_W_tvTX~X|kL>IFw z!Z_u!f&6albXF@fi1KMaxkg5Q_Adv33@M_?WM&zU`ut!}?D7lH939kGD57s^wW*39 z5q;fzek^ek^)!6D+V1Mg?{N21g74qP_8v1i4rzjMHCjPjjTo0bXJWgA-R1K~LTY9-6^_qUj5J2n2xIvdZo?7!lhTWgcsO^tOKd z)Ma7zIQN`OZlL2cIBtVJyVJ``ARl28fr1%(*eTE4=;kes(YzM$+rG!h|7}7p2KGXI zJsb2H_u;Z_Nr31EA_w3q@in43{zol-zZraC&gG-Q3~;u44LCb%p~qwvV;LZlj7A?p z9}P1jUu3qv%hhVbGdZ%>s8 z{75fMes4S!I+DWlwMfUf6%`CYPw}gw99&u~=NC`EA*DW77YnqIGDg09Kl7OFj*tEL zn<4wfx1dkqv>m|G6nujMYxr0XHwgbHWaGDrd>yTwmg-~fTr=F@#8tZxUs-pvJ0nn) zHf_9OQ+Qg;5MV9&g;v6i;tr$wyZ0{z&w8~{0<~C+pO-4a}U_RM%usQ zDo}NMR<#gG{M3ZJUl$75a1bBIeyz8)j#`?#Vc%#oDKIKMrm~d61)FuUnf{B$>7vkR zFaUM1cM=eh9oa0lo5IN-$fvxHORbLDKMYhjeh(X2PJ)-tR5J|4l-yz;e1HUvI$+r2 zTBqEPUk3sNx%kSi4~vUWxB!TvWN5a=xQs$#i%l+m(iNx7e3C;k|E$_gq-hhiy^0x? zJMH)lG5|gCiWi<&UE%chhkx2CJ#PP}J$^?nK$WZQ`j{NRd)h}w%Yyg~y#wnr$#T+$ zzWXzdT0Ab?@j3wZDI?&y@l@Y%ckcj|)QCGr_k$s&7MMuKdxvNvEORK4xr3^3+kF>ajn4i>yvV8{ z3oQ#TTz;o;K1@*TWD+4VJ0LzO-+_|g8#d{Qm*fgN3V1U-Z_5am;hv`=TXj7AWP5v+X4j?0;C|)OO82mr^^7H`! literal 0 HcmV?d00001 diff --git a/web/icons/icon-512.png b/web/icons/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..a9c1ee74692da27039ccccdb0458679ef97f9fb7 GIT binary patch literal 54582 zcmdS9g;$jC6E}P>-7O#?AP6X3(j7{t(xG&hw6F_^v>@FnB1(5JAV_z2cf-=`?z7+D z`#gWddv?#+J@>hqj1Yb#C!07gJrK~~Q<>!{7IQmFqOgKzZ-V#ak9nlcrDUkhVp>ZjzLQ_39X zw-_S$O5OS>D-vUSl;%c2{*8&?Lnbbo%|}MJA&i(#wX~{U-ZU<((D*MT3q}V@Wku7` z{&&~gfv0T`E2e)u5Wfb764Tjgst;xYPup(}V8=JsITGo~$?vWnvLy`h9jkC0N{Uj9 z97O$f3c*};Q#ymB$r-@^o_+f@g`uU2dgh@}#0oL`?-}zeA<&c#>KUDO32q*0S;=;U ziaLN=rpon3&jIb%|40?+kjwo4meer(1jW1_tCMDZ*NqiN-BdO9f5*XAw)t`!f6#P$ z;`-xfxDio2N;ZQbDmVtCf46xSeg@xKU1dCRFjV_bEMX+lN0eyWcbFk>>3p2O1vopX z{IVwffs*0%8wuX*=(So<<^vgI0bm0pd|s{Pf5{+rn5X)0Wg9tJK0a?S`o@jTvHmIx zI`PIKtiu`IRa+ga?kN4gE$NC#HXhd7*$4Co@xnr+JJR-#!nM(SI2=o?pZ&+@baZUY zothTO$<5s1=(35%W3MVM!VjnsMCmB`KYa@6P{T+!MysD`b$NJKRf+h#oRh~*BbKnz z3XgOsF)@gqCPtstF-sH1$0UVz1q9oaCaZ{MUCnwVAILsWBsQ6LWc_7L`5&|VWKj=( zdFJponFppO_9H&VXea((>3J!BZ&4OOK_Y#!I1*%G(pPvxm0X{t*p*+;ev;^4`(8#9 z-+}d4QSE=swDZ0(nxw#hduZp8gg!kSLCY&DM!UNN?5Xt^YWy{shLuNPVZ~FEabQx~VUl_ipn0e1J~gtH_CDgy2%eZ-E&OTD){jfKEO9PkstHdg&t=&|I|z@+P$2j zYvAK~?wT<|UQn>zSWRnEhO1->!%g7@#{FM+sNmk|V4KWkyu%4HJ(%DkJ@03*5oZbR znw_%t(v4nKjZ~NH6GW5JR}3_ zTPcc8TG*FUl2mBrgE{8j=rhaIzQ6r4_sGt+Y=rWYp2a)lds0$WE?OKi&OxgJ!U6m9TY18Br#u zZ%7MBBdr}J)U<-gv_`SMC7{@)wh9_MjiTAM!FQy5NQ`evh>rZ(xs-zp0p3Wlm`-+R z$D>YOKZFB+At#wUF2lRQvvVv{v-BuW5w^T%?-(Kh=Vkq6zlMWSDYk(VT?OSm{wn@f zpB(8}#gSw${oMqp~TGSwPiFVdpzfflTG)NAw?bLe=cD$-a~$J!`xmog?32BjXY{Jm%^*n zTn$xwfjvukddH(l3YwuvN=&h_Z{v02MPYYXirhD3RvuLFM4trnH*A0P%xK$U&~VUQ zKkmHweBR?fi`3fO7vf@a%a0-^(uq z#1PkFAj6D5-HTUq6vH&b%}$RfIgoU64SiEbP|9se&xn6^%JfjH6c*Id#3ag^!l;xX zJGng-ho$BRH%XFG+Ub^k0StYYR`s5B>_YbxB%c^Kp_pa*q0$S^&%xoqyiZmLzE;KS z2BRgf=m&(*-tQOqt(+VFUt&m|^i64e7?t~-Z8w}G)*M{P^7&bO;mbjcCi0NBykP%V zmGL^{9YHGG-%>+^ppu5O)+A|PC6Im#SbJm&$yFaN<+WLC|zajJP}A)PVD^@xLHA?#}R&@==?(iJ;5@ zPTJL3?DqLXK3Hjq7<=2KadnmVJ8=`9j$D;8Bo&u39?Rp;6kR0`iXXFR`~gq*rKx~F zzON~CUa*;tlYjU@J*86{=65NJqao`2t3^WI2xoXC7VF}!<8Zd+_tbh`U}^?%t%vqk z>YXU!MIPAPEf*tDvxkh`yjBI5sExKR9O-~N@7{e}z< zd_F`;3p0HelCePCANDFWxP+K7)Q$C54A$=e1V=c*f!i2DSse&qVaW(r3Rv39joW`G z1I1p#Uk_s38$Ed#4J8{;boGdiN{}UiZ5|B?l6<6;dV)iMJxy0Bj5^Sg^}ou|7`|Mx zF@}wc(U6DryxdhM!>YrP5RouOaXmv)^4mf&UUb4QnwY4qx=_A*`9wN{%Ik4Z7P^{K zddPqFgAmvKT3)b;_CnCBl$734FiyDO1!b8MDNxHiV@Uv{7)&WFXL_^`k^|IkQW_$F z6I(yG=IaeB=A4yi@_^{%9;Frn zVoR)uRWhfK6UO97%E7)Ru*oDjA|%{;e;yv{Kr}~-at!XSQYaZ5{jXG$h#AhkBrRSE zS`fs$@$rS7%&W{8$vM;>E|LrT5)-JeORn>4dQ-On5#_J$5-JJG2{DOZ&{?uHMX@3F z3Eg{_v4sCJw3A$fKN0|9+EY;lE)-t0vEF*OG)+?3LCzA01v}XE_-)wvZO^#~5rQZt zmsUj$M`cWggaKpq7@f$#=N-!~p%C_vJStQh;G_`|-H-myTWU6gd@1bO#(i5C16vpU zelG?XH%#I~mbDXLY>9|Z&64S`;>k`cew766gqRKAK2hSJfDG(Y5t(iSwkWY!rH1i6 zg>jvlrWvPl!A!^D9fv>DgnPS;%7~95_e*YPVV!5`<8~b1jz_-O*?d6B-r|{Va2~E~ z8w;;3Dzi{w0=1dU6_fRXSH?~|?`3EjryL}g52ePBCFc*N##{nMdPI~@)LCf@$J@?* z1H_Isi^UWBS@=?IJx!ecF%sj2LSpzzocQV&9Lip29+u5SzCW~T2`rd)Xf|X5`MOI4 z+325F<{*HN%eNTAHjix zxWPClK81Ux%O?-1sVmUd$CUSjRYH53#k8B}ZR2|@cC~!zPMWNpt~xmXbhC-^FxV$B zewRPtt6y=-acY=cE%6Q*ric1lOCaV>PI`U3r3I*C@PbH((!B}v?7m=Q_M%uaUXDdR zBdSz&OxH$fL`ec-<~(Ps)Ct{1= zzLvam=^CbbKc-*lB!%X5RfLo1b%DpfKpqzz1xG%KQ8h1LE}zVMx5$>65+`n@kMAXl zw}4w~E;oFgZlvwVNO+lW3W6mY&sUwzJv(wxNb=Pn^LDD5vHpt3ium$`^p)h3ykq)44G+lR&lC?7u&8}} z-m;zZV9|DP^+EFqxNE7f`sOP?M7Yj~!O#>wb};al@&t9@dkZ&bpPPk~lao)s-wolP zESe6tT{Jzh=~wKhn-$_2u|z0dbJKJreyy{)9By053}}1sZ%diJtN5k_on5`lK0cmh zODsr);MwIxl|XoCZPcn&he0){jC{L@?miX&VQa&eX%8DuM^#=L-A>?|esBH|d}T;3RtUBG4lNR0v~UL^nV12nM8)nioqT43 z`N;Zh^W_@mA-RsPZ_3JoRu2{;ZO|K@dInkg+|*@fbHEXLOQrUs)DbyDtU-1H)mTXZ zWD2h>XL27f^rA-K<~(=0f?fh(Ywhnbn?^szg#=D0o?h}PJw>%g@!9rIzB|qh= z1yu6FqbIrf&u;U5<+MUjs;rC2LKta(0$1G3U0k5IJ)2Bl^9)^wt}Z+-AGf>XzYM;8 zGSTtb<&l^vCIkI9Dtp8mZ;_zW{>19Ygb5R~rq2@gBkE685<6OFuW%u2( z$V$ZK%iX^s?aeipN>FJ9o;NkdHR7AW2$J__Cf8D{tB!Ge^mMlyK1gTlpA9>NEQO5` zKd2OmIk_aOTU!_G1gVYV3Ur5UQma}fZ>61F;kmRoEoZO7xbTd^&sU2J%7!G zu=P->2}PpZ|CPZDdZf-6*!<5GbMFik>|92rXsqmk!ZkMKuDk5@vw@S7;ZA_=9PY7a z9*Kc6UCvb8E_<2D7Ah=A23}w7P|oS6XJ%$Wy2a#t^<;|08N+q#G@ginMY#FGoUgq^ z`4_A%RQcw#UU$PNZm;Vp^A1&!g3{^Xm$tyAA16Tfj(|4xV&ClMlujCPJUB?OW=6Lf zwfP}|VB@wf2Eks}@x**)Y z?M-T`K27XvOB4&_u~@+4_{a#4tJ7x}UQRW1#piO~$&3tOl=V3h{X!LoI8UhVcOR}4 z$E10Wbi2+|-*q|iL7=U*uuV42_QF5Q1wlR{j|)3HwD9&%ckb(D+85;TD92|(kl|y(4z9I*gTXL6{xoV*R2I1E1 zE3Zvt44sV844u|n)b0rhd%3$Ki4yA-&tpw(WIC;=-D5#YI8*|NY6V+w$)$PZ(BbO4@%P#1f5(T^AJr-7Rr9s`us{J zq)vd=!U^_c2jYM#Ki>qXaINENE-pRdS0@ zxO zH8uzDUU+=jFa?jDBL5gSRHzkW+A;dR`mbzE$N;i7(FEautaPfQh6hP+tWHyc4d}lG59{k1}zk8PiH(Y z8~|EnkrG6_Lcn3{zlU%1e+7BpCYUcSJ%+W=w(JFxiKb~(0+Jt9%wKoOFKl^0-Z$(( zcuR00DUveC&#BVt6u1u*9*@ir;)-&_O|eGKn_LdRz<`Il*jR+`(V{NAeAtZ!=%lmS zRaV!o;_)iVcR9FWdCSVKj;_!p{RD^Tp4KgHmh9}*>d)12?>EV>8v*)1Cv%&;9&S)t zq;*BCZK-3bxB*)6&T~_AylkkQ%8aO%aumQQ9`=)=7L}a zdkk432%k8HRP3N67W1Zno1$TL7unY1i*TLPD<}Q83ri&yOclD-^v7OJWhiwJrB)S+S{0)%Qac8W#A>P0bIuP*uFy! z-*w0#tQcAQzNTpKcaF(Ylt6P;F9BP-v;98XXigL3M=9K09%mOR@J;z=cVliCRac;9 z$WTItTNRHh751DJNf!oeHRKfDKweFn0d&xwxm&cU@}w8`%mvKOASM*gH-N++h$^6TCy9BdR%pFcopS7*UXrxt7#!W8 zXRJ8+ApH{1fcHz6U`F82)F_C%trJAIwr+Onnk7>8>bab;`=j(~(#nGLPGUCaux{kWPUo4c z7k{&#{v7qt1wH(Jt&OWKM*^b-?_REe6M+sYn6Qd^W&s@p*2aE6ve~=Z)XLerr|IK^ z+>gx^?%qTbWq$oP0pdFJSA?;zbO%szKm!c)U_SSQAL1~1A*UvWcl!dxvthOk0_mR- zGi8}AEw8)7<-p%xfVkEhuO@T3n1X1u40P`mWlkcXKZl~P-_nKvBx0M-iSuadA|?Q$ zHNf@28+zCssrxa~PW&5kzHAX%({{{2S452SU$v}-ik>9**cr!E_ly5Hv|*zfxrmiI z&W%w~@cK#{D&BP~7pzOk91K3>uWnxic;m5;v9V!TQC_IP^?CMVY3!+<-gdl25E|TK z3KLRmY3wPMqhpl?D((gd%v~WS}RHkU7rd!1RY!-)1ObcN|~`i_}r$WhQ(pz&6(MSGJMcu!;n`kvgmvI_CmLmgute=%K2j`?v~o zWb17Q#1p8AIo(V$@4|5SL}&L$yK|P2HVhp(YJC&Z=`c3Av#+!XmIRwgEr~~N zj;^-D|6SKd27XJ6OOY`HkE9LV8b#>s+$mO)tgdRTiOQbnb$DMU=XmT26`g$Dd_J)% zOyIFfNVRbq0Q(Ps$~SvkHYBxkpAiH-E_ltV7uclWVGm0YpFI^Z!mkp|@c3j4yvv8$ zzo&zna+4Vl`Y(L0o`nmia!ay2JBJF;p;pz2hX!}Uk8DM+hTNLJ%YGAh#vks+LcPmv z3C_GGMoZe~6`LO!_Pp*K5N%8WJF~(H?Vq{Wn8hl+%vbQ&e4-n2CCr*=>*K>yYt);m z4xnmd_|^0@Pt4cZV% zY!-&wi$+1oZs3KFHROy9qap zCiJ~+V74RS?;)Q+tRoRlO5t08sW`+r(USMCpVOl40HhbKIR-wJE+FlFq2N!~t9)TQ zTLEpZv)-^QH?Nos#qW-cYL4AM+Eo|%ZHnH}_tCb$7W|CTBPsh$FT>3Z27I~5yXI?- zUDT_K{g*FxACu2-lgIbIyEM=%68>us^t)3po5>}@N?f{8Xc7gM3RQ%+d70l7?zw-8 z8D~l@Y{Vi7Qdt*hgxyi#FtEtnW{RykAzXJy+u9b}gtE;tH5yQoc3pj@QB1u9@Ka#X zBlN_l9O3F}3Y{j%ZQHpP#)Kp}#hgaxx1`xJJZN1-pT5v6Ys)7Y$%6kH(5#i(>>KDY za+VFdw^(kGg*Z-k!q3iB3eVRqdq?VwiZh2Vhj;Xq3K?3w;j#TJ!V#J)GztbIZoJW+K zVKH09zv>SNkl_)^3al1V`ii((uI2Jf-Xgw8+EVJ*?&*yXJfjWG84(Q9oNTtm((k@j zQmhtoB$aiHiU%a?sXYuycs1}=i$iCYNohnCryc3wIYc~!KnygTp7z+e#{(X9l6 zyMQe=(3@yLjtF`5dV2^+|IW2`gsuNRXuazW%aSLq7cLU?!Sk{Q72xwS(cv|c%?r*IA3Ps70RrQ(AZb^(RovZpVI|y#-}TO`x(RRGW8A@PdK);WM~uklV;@S z&GU){;E7YpbpPDGyrPjHFuZe9TGqyw-U^X=jxl90+yx37vS|<%^Y|hs^DdjNUi}+r znnH^$t5_%tUPaD^81E;y_onX6ZT0uE6y#rz!+ZE87=|!`bXQQw_*@@PeMr-@#ItzlIuTDr>$Z|IxbSg6u2N-RIa6 z=@?yUzpM~`?I9=3tIOFpX*4dPNsq6xjWY~*bV|~}-+60}nO~Rn&uQjJ!EZF^G;1<9 z&wI;F<|&E&p6+QPm*O11Hyrv7y=^*bl=m7i7=Z>%a)ew#E%OG!xF^2 zMw87-2+0MhcJps|pf6eE<$nTMX&sGavLhyj{0h)Z6~=i?M3AKCa!A_HPPTGW+QIk+0b2_6~;tgR7EL7;fW6@-DuuLK)Ca&l{*><5>a~(GglABQEWfTq25vDZX z^-VUNzI)rkLl;?Ov&wsfti_N*QK|x7pruia`Ka4_s5tYs7}ObYbOv! zP10_T9c4q+pikx1{u0aV)0{BNvTCBaj|CB9;!zU*RM~Sk;-a)nr+A73)NAvd7N)I& z8yTUWIgb6xqTUeP+(^z zxxY-oxEPndk+r@dc8b*?j!$JA!S?Ak*WFS4;^DIS5(k#^yf_HU@??y5VCrc4{8obw zTDKTWZ5&+yt*^dd6Boa+*#s=XrdW+71+RZ>(a_O|ZeeKMa^`C-PQM-ZmXR(ZxMf62 z&AA{KilS{%vE{7@vgUBM0`|a)7S;6n{0}#~!u{3$Z^-GB{N{RK#r(@Ed0d>-Q9C4whatZyGK3StX@NQS0mUR+QJ4%{ubd(os zA70^XK}=?|n3!|z+ov!i4r>SQ~9EJwtRVR zStz)I?!IMpDA9Pf#?EQZH{-?2;BuWa>~EYin}u0m6&Vu3y!R!RWehI7D$$;hfT}tB z(+Mggf-@dcPl)m4{@~`hcuGn}442|~xc+-70qUi+2|C6%|DJIpwHaxu?#Vw{^+Vsh zB>9wv+u>!BoeF;}jDHbOD?7H{h4ASGON+a~_86JWt#(6I$6W&+ER{7!Dd)foeAgAW z&5j1qrUR=<92CJz-?YU%zfTQEh&G%UxYN$kXEjxX%?&Qfbbe>|hK*NE3VL^84u3TM ziIx4d$^Vy$`D>Ey<>}KG{j*>H`fzg9J$2-}4o*%UHL8f_MI`+Fh{(SDSONVm|1vxm zP{|d3m;E^}SEgwXX;6I0LB(AvNCWW3Y{r?kH7n;!Q`6-8fHu?)K{7I6+(8lssEouw zGbzrJp&JVx{l{c3S{Rj)jlV*b+>-z+-4>mr9*T(W#KkC z2+DbJerCB<&Gh2O_rF}>i9nyFAuOg!bJ);{u{8UQcs4lTyvx531cZtp_Gn#Uy_V!V zCJ=-D?7Y&on$Bw|VH^|eCut%tC;gKDP+7gsD2yP<*XPo=W1wJD3fnhkz+hy01^ zm3qT))Pt=Q+&8^8Rh`RXPD8Xhf9O^4Yj_TIW%2p5&ukrQ7W|4Jx`mkOHA3Er&RoCe zFI#v#fEM?uuSBckCmsy!`RD3SD)-OaOZpf6xh72$Zz}u%jHK?-OOFQNBTg%{X3Pi8 z;~7q$X#^1wM*71a$BFL^aRK9@8f@&Et5SPb-yKsR(Q2Xdmg1fNf>cL8foghO5+tN) zis;5-|KsBEeB`7pgl?_6UpfRcuA*t2nFL2{2xCp`OOC+HErpl`XLe z-*XwopJo-?4qUTRXE_?Bqiv(b9re_kfVlES-T2;lQ4yu3sy0ktKLt4kk4ckI`b}67 zTSHMN_slTh^f8w1y{Hq$nka5m&I`^C#s<=}g}&}4n@c2_W7H%GsIyw(R z1zn>Txz>(?O@Qc?r^`oAyY z+)<%98O6XS!Y(yo{_#?W0h?IowW-+EyOD?>bZOY43L1v;k7KCY!6#g8F@@(Zcl5Y(VrBY7{X>lk)zx_Yi02SYb4@ZFI`uC+l{ld27!g zB{|kW?$6;#8G2Uyjo~loA|2XMqlCYIJa5zA_y1G#ity9%-{j^Ul;JDXq_13@trQjM zvspe$u0IYA1lA>xO*obF*}LIvosmESUsHo^g|)yhXICWD+x{1sHtsIf{{d?|7H1{2 z!dA?8(C6&L&jP^OE+y6^*5X86^w>Z14E^u(L~p52h7~O+U;XmSre#$B)81Eb1mM0P zAxGPEvuv~9yjWTuvzp>R(90Y393>n~xVfXq#rUyGj+k(}P0`rZtLX>Yo&D}6(NCkF z!(=}Zu)8ZK#HL}hj{;o;M8D|1#&yw-9f{+15dej3cfzyqo1AZ{#$~ImpPQ(vsCqX8 zHqVP)m!mdCxT4N}dii3~dxD-6`OBl{D7E5Z0sfBHX1s?1n)@z;(n{HC{er6RQtgMe z^r`*E4OfbxEJL%QM7b+qGtjS6T53_3bdQwW6;4l9&-_J)%0h32~^=Vy3{O0x>vze_sm;Z zwQaAWeoqD*r{uC=uUy6lpp!6V6YNcbtDtdNfmnSXh>b8$M>}L>SBQ@aCvYP*qZ1k(AIrWJ)ttp-v8F>6lHA8mpQ#? zb+2bRa2LIKZn=CCe~DkV6OfV;aG-}y|di0OnR+xab^Ex{d{we}yrz=v5 zQ8axXJXVZQ9{>+>G!*S7kF7yITV2Ecv*<5T*AZWuow`LbHl5Ap@2Ojq zmb%jfOaH=jh)g=jcLBA3Xx(q!-ezlXZ_3G`XBG1f*5Lp|w`sBowTk?Da{K)_xLWt! zACB}{%~bU>BMXPSt@q0uT`?WMxSf;w(0DkQ~e5dU^4sbDq;>zMVo@!aW8 zEwenEneNt~8jN{!G8V0s85N z8{R?D1T$JbmeJ~4dG&;&ZT>hVor6BIg-5&g&D|zxJ!wvR8&T=gBtr}(GpNyivPN6R z(;xnPY#k~o+9?*VzLs9qjJQ#CXge(Uatl}YS)U4B4-r)B{PvH0xR><8jjda*&DQVT z+>HIV?M(};Kx<*UA7#^0Oc-*Tc|HHwVclD6OnIp>6BW=|pfRp5`n~q0zm!2IVZ@o5 z-;@OdBFlD<2Sw42s9v5^OmA+ZJ90itH>*>}<-#_s7S_%hk~!CEGnEx;L?cZl9)yv^|s&>@QKj-|a(Vx}5P z^~FZ_tU=p)O@^r6qj)3WggHj%otJN(OUb@eER$=k$F$_zPv|Et*dlYR`W~3}BHXA+ z3dM3lA1BFcRWTr9mJ(14lRvHQ^-ra8WtZ$;iz50?9ucn$(UkZ4cTOofr+(|WIo^_z zLT!n{W76GR9|PyL?T3m+Mkn9!>YN9&2c(D|YZbLG#lO23pxiGKF3#D2`Y>B;Q7eZD+lTMptLmNgkNh~JP( z6H>{mxo;5-gPK!uyuxHi>cY!Y{VbgNnWunmh~>iT3LbL z%}^Q!1`ihdPCPFmA?M+SxNt>bQO+!U_S zf)+9aA-x@5!4FB4@^m7iz8Dq^a#Xh)%s*b19eg5X=dC1!@bktX7X}8TMZNgz9xsg> zsz+PD1Zow{z42Ea#$~K<3R=+V_Jy~Eq(`i&IEKjdPd(294>_+=UX6y})sl^c4WfXJ*9 z;v(#F8C4pmHZ_`BCi9Vm9 zzV5Sw{~;B6d-6oH%rW}uZabH&WB9mb?|*%Qs>9ib#7Oea<%XcIpTpZO z7K1S|CP&(FZ@T_7{1_8#tg;k2u=0~I%3$kN>bLKKapB=fs*~1l4>)`3UN<54ZHFU5xcegQB zi;ev|X&H}roDPW;wOjiSx8>GtFaYhO@3~to4>HG20eRomW7Z9<4Q6H@w2w;MtcLCP zoRE6Jqw=NYJ~Qu~P8dgn@a_d@*HaHUFfLfNFHiDHji)34Eu*x2c9M&YbigqY_Xqzp zWRFh_(~7yPt9j*8B#&f9944^5OTKrSNGSGNo4-4^7w?zgUI^IhdT6o56hI9N=C-tF z{Nw$#XhIK@p{^R3RzvLSe>_3CA~PjAG3amYe#YFu+Yw!*Br>=Fpf>qAP|$yNV#0&M zi`lz*{89e!8{-o86xIg|lbZY2=t+nJY;Q6*3!DzXFfH>z^F8*bDM>7XwZ)Va#CeHs z$u^tI(i}~kGj!#j`|N=8zNl>bi!X)J--ZmB7@he5$;)jcf{sSbRth6PvYjL8gC+w- z7_;*~n4=ZtX0d_xVf`~SC9kP^qCsPh(DF2kXy;5OFv((f= zYef-(-VL~_v7Q>5*#M{^!_hdU)ikwQA|o*2Id$5=)2GiX*rH!z#{q92r>lF;B`d|Y zo|Y<&Bi+xt94J5?s>a6V)6y3%y|6&FwOMRV*4@V=aj9{Kvabk&)DUY3JvjKPAPNf} z^%|BJpGNoVx#e_2$8+8tbSQB8>3OG-4 z&wscN_P6Xdk$+Trs3|7|);e3B^x9?&!%Xuvul{=bRVgzok42< zQ6n$Ue3&J|%i=P2tYa=Fx`WY2#`oBsbWac{0PkUt`rCgnU85A6)k=NIG z%NX&Jng(j}c zg9~NDHoHb&jGO<&>{3Cu=%9(U^Gh!)tu%}CS}2{g&L(nfV2U!R!6nF>Mg!6`fq0uEFJzw^czs=w$g?D3dvQk>7u6l}85^v=v5ygKw^ikboh z_AxkI(~1P+zk@6#wIj}*csE+$RsjO@t-TEmpsg{(v3?ON#t=0fdfmJTHxYTiM63y{ z#=e44<(Cn*`{BR%rPk)RD@0^SLVp$AhVkuUmriL|+8WB$AM?=4%N*$H^{~B)+}!82 zz+O@&=;Fj)qJMJyoY>ex_3zqbOAE@Kf{Ys$EsoeUvhOP@Ox!o5?(Gbo3f>4{xJdev zM{{CBfKOw~jyJirwb4@5&G!lw_yF#1Zi^>2C+AG{jPMdJt!b!iLWh5ERtGEk7*!Bo zJ4ar4>5vk*zI90=fK|*(%*cGSD?CkLi&v%F!ox&JWz60DN!9i`21_rnwnrY)(n@=sm?T#Da9v4NR$pMl zgW934Pe5C;pI;UYJgZgi02!dirwz)G0`mUVNtL8j5W;Q5LA-t&l_J!4{m}@89G97y z6;}_`5wX7{+pyxP;1$i4hkzL0XG=mI4>n zE9>QMsTsAe7L%DF#{2Zw=#kLSMa-()IN*;{OIVv6_FM{|$}cc@gNA zuDx*5dH1mP7&wWTSv!~>k3E!#d{^@5B(6{MuFv}WW25*RaIojQjJocg-E}{klzF%E z1COUnarp|&RuQQ2j7m>qNmQdfDa&_AM$d{U$Muy8Q9oF*i4P^{rPl12@aSyqa z{4IE|yx!N+^rpn?!#~&DdG3y!u=F2`ASV9(lRTfnMs@ai@gvyIj2GXM_;gC51JR?|^=-A{J`{tpy!jA8pjr|tv*}8rCP|aiWqS12y zk`u}V0o+3>FR^UhVt*>0s$YD|`?etJuLm@=Xzze7y%%W*Hr|xKYSZ48GMouab8ZFom@Tw#{ zh-Y(Ko}OF& z{`Vp`R}^m0@Ni(|;luBTSdnxh**AaB=VoFpe=-d^ZUX6NR!`M;7m>WoQ_yBid44ny zN?Z=zq(7c4E>My$D2zl5DS+b%Ln5}<&_iNs%zlAi?9sL*ZH^9^PuVeuueA6^3T2*a z=q35RINK^ur8mmZU;;YWi^+ z7V|wDs}gptwb-0AVnDP{sX|S_lS-iJb+**Rz96;uq659FAVR?ZwShA^-0Kyb})QeUe6m_63qv^ihWFQUHI z(){AjUB#2Pb*?P4pp zVp+aHlsBqjGeUy64)N$L*Q{u-SWjG76lrINP1K8+GYquzFxI|n?B?c(CO+Fb4LZJp zrD%E0g;{%BZTo$khv0aRPb*p%tJBbanxihl=fIaluOwa4)4|cmdt6#Vg59r&GL5-_ zThtKn_OLqI61_cxa{P5?9O1(%S4OZe-u)hEdG9uIBvG^Wq$N&>Hr>-I4?49rZsh{A zbqL5Xynjrcif+K=8-Ir5f%jOY#4P5{FXkR~deY&`LK)oi6Vy|mCYIwXR#>t3TtMBG z9mKyo!;T4HEtPaqEt;&(@?<-5aR@4f%Hl(}-v{EqR{U6$-zpi)Q)fhF#D(QnKL40~ zEM>3~;{IfEz;Hw2gW&+R8*Vlh7b%M?E;786Bcts+}j(fiH!tlRX<0axQ zr3R3^MF*U$i>|KOXl|r2o;$rT6K1J@vBLj@{f#(H zy%C2P%urU+Mb2t`fsFe~k0tsjkx=;L_leU$l~?M8^wOf52sQ*Y*cD{kVCf_$zF1O5 zo>DVU@w-~9x={cSO+tI8^?rIo`v1)W%$Tao-4@CVG$N%vPmYS-;{#>~H|9$V39~;Y z4;xx<$2jl&AiS~l9(fkrs+HT@CzF~&+-4AVGW1SrKtb)u*@!qvIQs;gWUVU@gYdAj z_9A(wtBVOYEIy|IjS?JXyThwf3hS=y;25jz*pnrDqSx?kC&oj;wZJiAAzfV6{$ri* zW5C#q!8iZ;n=4wP#`}hlyyO7t2z!5s zRLqUmHkAiwtJpZB*OGT>IT+T?sX84(I5Bxn2mm_lf4OA?N>`FL-Y;5u= zmfZT=@F4UXzP&;hf$;dh-7~XBr@s7RK?K^-FnG^b>KZc(+u~zCU~Q#9$5}5K>r*V9 zIfdf$wt$U1V;&;+>?b?8O4gE3-f8FXoZ53q)AM>&8ow5V`nd|Ut={u+akV*?*a}8y z1lUmA)jUCuNH!HT)Iu9m8s3Mu4%Dj#0ZUKAGSW&?|m9FweBkkBLM443J}6{>iQUi`G=X_Vq(J%#cetzxX=cR z@++O{GF$`SZ2lhrzCc00^f@Z#gLufm{RpLHhp~Z}QYbP&`z88~G|EN}i`;+WU@0X< zo8O-r#Jr&7X{?nC6TahUIWNc1d3NBrm8`J40ceCfi|JxHMi(bN^HfV}K*yK$S zT&0U63rYY|LJpok>$AzD7FRp(Us`%vy!hccJ^JswNURq#gkHB)#iFPI*ezwyeADI5 zrbMn%+_BLw^Z-2>PYV4+!@`RnLBrTO@X(lpsI zY4cn6Hm95ez*D{Mdwazu0m>$CiZD9_EwU^w0aQ5dr4OV_`43N?Of_HI-rku`$wu<8 zx;zigd65UcN=SGAg#~L|xY+)tZ^|5AP`Iov23d!RO9aClDA?C7An8P>CQRU;;rN3B zM^R7UzU*!!T2Kg0{qQ6~e};fD#v;~u;KAtB8Hw*%2O?A}-E4%L6iUPa+34bEk4%79 zBS%*4yBtQ) z%|^MOta;{i=N)fXUJo821Z-L2r{xkurAw=nh!n3P8?T!VTb{y`-IoD<$*+r8DB>-k6h^*zpYgyfeH(PL&>J1YceM_tL zZOhAP`YT&o;68nGE;+}_nCHr*K>_lg8<4oxdHkKM)5iO$rI}J1V2&mS2)ndI25mm{ z7l+4$ei<=QF1EfW5O(cY8bS!CzTfxxd|Z)^bk*(qeK$ zb}4~2{!*$liz5q10NRlGr&oE|5>;|r_|fCX(;<6pclX|SJmVFmU7YTF<3g`|vZ9Dp zv>v#>apHuqlQ^Ud03=wW1ZqgMo)szj%|U;Or`XMx=qmkpeRIUaz<59PB3xZF5dW#7yB*?M*vX8(K52kkuBQ7iDu)wS65Q~m(usX*%&=@ zEY(+~#3Dh8ah*=1m7f~Tm3W(HXuJXa9FCMwFhvN7SKi|+?mxG#E; zE3$QpNQB?cSmWY-(C#RR*TX>?2Z;SO!#=nWQJN}(0K_L|32N^>hd#>&_yn%BS*6se zYotTAOQuU0do;hdy`3h$cWw1}Ba%h?f)#<;1(8K004cr^v}SZAO6fy_V9#jbht}7- zQ3L?DN243Vp>0N|i{DLQH{~?*HZE`*T8}=$T1{ag5l9S$#BO9DT2ZdI3S%(6NFrSz z`UCQ*WpyT@Q9wKSsw3;iB0yvy+K~gn1lBhijr-ng`2JvX03Z+-^dWn!YoraRJ(Z)0 zMu3P5spEuLz>CPlp?9ZCtU{GbS6q?YUv+{K7i_Be@^JXlcnko&DEhC~k2$Y>cNB=} zr9=y}lrFF=76Its6*{J~XPG05l^w=@a6S9x`(NCafe zz2?P>Cal|OCjWqP|0Q5y3w2Fet}$rXm(@Vjk|Cmo{sJSJh}xS&z??t4^MX16Z-R+^ zWGp&!F6wl}A_2t#z|iKv5%y67Ym|yj=O8}Fj$?9lAKd(Npx}LI)uscX9MBn_DTCL6 z>8y6z!XIpHrP;rIEc4PzU+L9n7dQ&ESOj28^@qga-~&~PZ9crZa;nh)fc|v)>h3PM z&)RCzrPct=A_f4^ymX00OjCh`W8IV?1JKfz`;W(psn*=+pK%I?{z!*@h1UXwwIyEz z{ZR{&4ALz}VA4R=fryCl#6tJl8a!7wL#^P=XpB3-PsinES{QMR`vYR-CR5 z%EPzrsX|&ZfKLwwx8oQ9PBt1JSXnlV&GX#VATtg~{?-d+7f=?C09;h*V${N=rLqj* zZ?0wT|ChJ6k~uGq(dpoOw?SYv06@f=moF)J0t@%iB_be;a{nc)16C?%L+G!1qXDb2 zITY|g(2wz*2}H*Pe3C4^;9v5wt1h+y^6v&k( z&jcfF)}8H^o1b+-fxg_{)b{E;0M;$P28^}i?5rarH*dzyDSg^7$8pT_bGdS zyZwZC_rr_Z+Xb#4-6rrt%}txzl_|qLWGq@+i+Vlsk|KuK>HafKhv5$}oN0iYkN!+O z86f<9frkQTS!B8X@)v1vGw4RSf)6FWPxcr(NUp8G-fCF=&X{gnkG04c5ks^DO# z%Z}UtUCID{aD6RRzPh_Rh+|w7o-RNedFdbsU;qHo@e>BVP8G2kZ^*=K`fZY_J)}&kP1>{`=Neoq)iIhKzp_{a z;2KJUOZ`k+;lWF@Eyn)F%4(|ls&xO0Uq1zmOI_hw#{{-EP9D>6$M*4=qln3*Op)7@ zjd)u|STFr@QN$#0r_i67qS%hj0GiK^j4+X?ZbXWQqSbX-q=$V3;)8^KrU805;xjP@ z*;cf=n!PA;Vm-|Fg=>|c!xb9ndIFbi%}4wFH1S`qt+%U&a&e%Fl?Kwoe#xQ`fFHzZ zv%SiG=gP{7W&;4WCzEU94YV%f$}hPBxS-7~G6yqSS|+a>4upFkVb8ww~=7tgnqZ|LSP;{MOd%Ns=1S-{VD#cqz4N-{VCeeAimgUkFTV@Kz*# zQfY-M901@-FM^L z?p$n3`x&*wr``ee)A+_csUh}`F}X*owRG^QT1NKYY;641m6b<3ogY|V`~7|&pA<}< zBa9LEGU=r%Ym^3Li<<4DEXoW3f-&7^RyO{_+}ZnDt#|i&cjGwW{8jPVsa#wt2YpGMevPgMGL4X1pOImT7Ah2)Fglw5L|@3c+s-lsN5Z3 z0MKY=-@rk4A2Cgn>9CKlOz2Ih7BqW(A4QR>Av4A(=O1OJrvXC!>yWMZm8Dw<--Q3N z^&5O{Fi1Gxh~xJxEu~*l5 zF&Yig@~>^5JD+7x@*e79=r0wh8bW&w#PXYzRDjVCH>`m>h*?9L#aM4^F!~D{{mB4^ z_uTl2HWU*`8jxk^79-Jp#u-Q4fX0f9;|nxL1E}?x;TF*N7!XgPJ3bKf>8HeTl90+= z%+0M>x`lFm2&om`$h|mzVKTWJ#}U9sR#sf?7`|d9VB)8Tg~EL)3lRb;2l0Vs_)0C& z$VXOJ0N}As=jy$Cm!gQtNQ?fVcJf2;uCK%A7;_#8=a!+UkyZ=Ei0sw?MBIh3-gL@Z zO#yIB#L4An-({RfmV$KKH9as$pRZKDv)PXHwekJ+nO^zJDDE#40%z5cGAAqA0pi*} zX_}+I03u?Lg?~gW132g7_`+&8i}uK{Pa2j8rLS)rXN{zIDG-)=wDZUewH zNnRTajM7}+hwf%x9|~JmrVA6pKnw5q(H}48 zid>|YgykD>@t4*F%YF0;Qb z-u?ON?(Q^6T#f9(1yIJAF#t$*b|{qB73oQB6Nmv^dKGIJQ3=LnOaVFQuMk#%IRgo| zOrkuZ8o>mJ1~7jx*(0@y(MTgFjQAO4Sg@}4$^>q?i>e590FM*{)CZi!6|G@5$3M?t zp%9#ua^}kcA)Yo19$9>i7On;G!Ig{v zUf$X9RQLC4PE6ozR?j4x8=Br;05H%;BA!kUCccA-bUHrjdPD|!=&wUR17M7aulQ;c z0JKmHVup}y1p&9%x?C`3yuX>%uzh^I+h~@6dMHf@h*x8!k__qb;93>+AxEZKx-{;S zGVfY*x?VyW{M2stMA(Of4_6pKteII*tz5GJde}?Ze*%zF3B(7s7Si~mV*WTulGnu( zhPK)4m|kHmrvCv3$=yxD+#~^aM$v!>vcde|3PAOet5J?oaL^&#<2!B+RlyKN;WD)!C0xE1;zO%u z6v);1ULwze$U+c6&)$H{TFZKJb>J@rG71q*#iSzi4tD2<)r_3g) zrU_)k1E-KtZ;Y8r6j5Rb{WFaW-D@8R!{`rKBl;qy0t#rE+?>GcyEilB!oeB&pa8Qg zIv`$gj8q!~tXC|SHOJ3Rmr$0gRj&O^%8`x#tPbwXr*^W3_GKW~zQ#kAb6t9$*}+)` zSO@~hWNr%pC3ybLt=3ywEy#=iC}qGy?SZZqSxW-~e=UR27)-CcLELfXWmne%fK^>@ z#ij>r&2(hMEvqa-e~kOm-%o!L=)@pf$~0CZ>Hj>rebYjG48C|ypzpYDNsKn5vOs3@ z@qgY3USU%+F$5_TC6s9Vnc;AhZ~%C)-AYNOqRapSuBI~jobh$s9mD{>Rh%)eQEz|qG(PW3G`AKx z0+SbCfOzVxL^SFHDQgqVsG+sN1cu6XBsycgwgxLKzd8s-9*$j6L1$rWzyuvoBKM3e-nUX8CA5dHEFzyK`G~l$x06 zX~duhjDWZZqko3%0?EZZK*s+Cf-_uQ0Xn9cOp+T{*kpn+-8jJw78tPXJO1Vf0+9zq{A#MG*jO zOeWjYsmp9}mDD~@UwI|Dd)L{DEO5I<`4^DOWj1|etAyz_gzqn*Jazh&@2`SI*7~jL zr)rY#Z1Y?Z-Z zT%Tg&YxzvGA08F|SpfIHGU0su+?V)d9Ar$7j^QRdTv=u+sAjZ9TcsENz69_L`auMP zn7qG}SsZ{HL+K<=Ui~_7uFe>*5AMy*hX0Of6E&Q*XySKTJR&Cne|g!A0=e2K0NkaQ z0RrG|Z)726097$O= zar$DohuZD)P2%OpbMi8cvohCyzvN)w2AZQUb$jU3y)0IEbu@}+xZQJMCBAuc{FN_* zdMmA4=6$xBhet<1~1G7`~~c61#CW7@P;ad{hC7dP+kzR+=n}z)kXsr#@}CrdBFY? zfRw6yeBs-hvsa*}vWd{GGIb574q$(=^7Ea%f#ULHU5xnz60!VA#AbS}Mh zF1PN$Ob(_QhxBW`${_s|tRe^wgI)g0^Ze>JvSPG%-fmHwE|7JOwtqW*S%9;symCRr z=o^j#9c6#tmi_!FeC~+MYv|qYhj_Bv+f9-e$KyZS*}0M=>2f1OUtq_-NHik9+Yb7- z-OVbT%PO)Kt^)ek-pMU8yisF|a;G=|a0URJGcJ}+835;u0dVm~1@-ND#%|q(yPxWv zKezJGBT=W#V)V85^ly4AW|X=@Oq8Y>oRx3z5iSq|bl(mG*@(EgQzWuSz0^y57^(vL z16hhcIFF~hS6>_5yq0~IU4GIXKz*5A=+p0ti_eGaA9e@z-FETuckyBQ?3?fMtM204 z@tSc)OI+1W+sq8mm*Pd;B>Q5$_yE0PJ^PoSqC^0kXb-^nggRASHlBo4!5dA)D1!cl zce4s(WYPX+2Hv)mUUbr~pFmEfp z%YHU}xWQayKM6oeNhT=00_?DFGWN}#c0Wk~;P!kL065h*QaMv~L*>ls1)LABT^rrH zv-IXSEnU7ZYBvoN4#50G zJW;@2xITffdQIwSdw#wdbK+e3`M^FHa@_u*3N~JDmn&Q_hRRt`FaJ=J4Bx z8|;nj4*_TxQe-uJuG6sx+U;Hx-HPL#I3C0?s~ndrl}g$-82}heCp#~{Gqp&Km@!#UGqFOiifWZ+Zk z+sdiVK}B^^?2H&=GTIZK<#6>ixOt^<>U87$#puMzbTipon`LlDyqs?iNs-I@-qN>%km(q7jQBFfZ-0mdlT;6f+XQ9oeYp=kS9$f98lOt6(z!0hIF#f zhA>ll5zI-btc)7vWkqW&%d%{vJdIgI8OLz|xk!S4iIp&wBAlX>D8P~_88fS+0EI_?1 zA^M=@x%BugA3sZThC@l2WjUEgPYU(9(73s5zcC&^-Rl9sBc1l| zY*!4^zKW#+M0+NSLI6@q0C!alJ|b=ryW?E|;3+Zb2bD8seyOntZR8q+;=W1=MOc<| z#+a2AZS&pT_|;e9*S-<;mZCGK+3^$6`Z3mM7~SG1ev`d@Q)WR0_W^`Hh4_>zB)|M`ct~$Xsy0U?=xW_Kg5axXJ#Cp$)pDLyrmqkTZaa z-T5%uz&5$HvTadbhS?7TtV#D=E6}qXfI%|c<*&a6S6*jP#8%g$_4R0N9hO&Eucv}F z_Wom_XMzj3yil?*2;&KiM#*RwcKfiq4a42cE!RH$l5K*^mK77|;UIzB$m=Kh0Ni{a zaNk1@ssXKHPS!YB_OYX6UqC-sinVWDecYbpr<1_YRzth}4RKLRKhG8C$!+Q|5yt+{ z07?RSb+-Vea;y=ZX*2*}nk4t8)2aeKv%2%;3`AtvlSLJb*?>rJ0H)W(6*=eIn{j_D zx%LJy2F)nyEwiO1*6p!Q8`>S#?yydqGsapiU;xb)0EcM|3?P{T0H01^GJ$vk(+Nz5 zd_08Fh(V&g>Nx{`1+eB06O#bJ3LL>V84d!954eD1QRJZq;8a%r%MCT|ww}+_$>C5T5{~v07*naRAZ4`>17aUYsI<-fU#_HBN|R8J93(%?Q{m*BF#Ynx*ZPE zH4^T#x;h`2DX}rzdADv4G7}E3pBq_DmD*{W5^Q)Cht95rZOYV|2dNaSm1jnmNNvpd z8fXbS*n7`Z+;6g>p34cM7IIE6^r7tqh`wx-Gkp5&njIm-KI;8&KbmD^MyGnc(w2Y#U4E`!3Q-Ut+KurIPO-vlO# zy>DoprDe+CQY(vwZHlkJA28h4IUxH-2O0z79f+?7+!d}1twk7S039PHM+R5}$a9yq zFl47bzPvpjdH0eDIM1d9vNW9;=uKhJ_l1KLPLq6K4V2;H>meNj)T;*hdC=z!~=8I*6;OK<4J7$dCA0@gLEke6|ad zN`5#m1&uz_{_IRMkqczC@#r-+Zhz}IvOYj9J zu)4xNS!trBO&Y*qAK9Ro7H~0FP;^2q253|vQ69Vhb~wo71H4~y0s&~pLE3PApwwvK zF|_F+{U_ukai&n12G0)V zGjc%o4;NXkd8HQO>s16uxe!0IHzxrS=uu1td(m3h2c+*W_&{cr3oqXD!mXctK@5U^ z6-NSu?_grRoa@M)^@oGhJ^~s9Wh_Y(4>cNA*HJL&p@QR{bMiQ7LsORZW6BwjLc%wZ z<#`5{+>pxvEg}kZSOfhY*=GXS$4D7&`J#;fh{r=_$Ni$luFKeUN#h&C<%P<%%R>MQ zhAl7=+(LY-U`)_WMDwnPv7NW&oGO*|4QA0N77pk;+PpbJC0n;0dg&{s3_Gk{)h9(k13o zoC7fN_=C}a)Kq)IRcD>uD1W%~l@Dz!LL$C~>Bb}g0EK-xhb+h=8|5M%IXWctx!-pzSKXA`2rlWb#2)NWBBDJS!M!cTirn zUzRo?z@QMvc-ka2fd*Si`te{m9+?DiG$TTb`#R{ooGTm`?!c}%Kd_XBZx?n4rNv}Z zwdvp+aAidxok08yn@PmS5S<(L5!@n4#tQp@#Qjv6ZBttY0MtJ@IgtBo?j)$|Omt0V zbjSvT@;L26e@{3_SYkBiG~7G*00=%1G^OpC2KR16CRt$?hA2%N`HhsN3Rm5t22!;p zJiKF#%I<$T(9E%@Gl251fk18KwJGz`9T+4DhVQCe`0&_~-yTrkz)_UWR8*GdA%5o4 z%dk)C(Sx=U0Oi9zs50Z|yE8`UpK}iBiZOour!nWUMUEMl|CV12P@oS6Hz54B!$BVR zA8Z5M0>?Y$$8l8@jL5kRVWiDL4Nw37?7eBUEy-0L_(h)i+~Ljj-m5`UNgxS{l0Zmk zunYn%K+WI=?8dBK#()JZH()I=#()_XtCziO19n>&8krUt+TAwLjT>wXSnUQ?NhO4! z3Zc1#sw7eMrh4_}JDn+`f8>eC81{~cJj1=`-j{pbcV5Jf9Xlc;Grt|NW5_B?fGSx6 zQa&OeLs{EC%0ang&1u))(&; z=>?i9lw}v*nxIAL=!Z5Iw%f-V1OO4YPkB*g$DeThJC$@?|Ee|sOuvwIRVEqerF#BF zbQ-oh{+dts{avQkU>XV799Wu(?!PiihCNWVl-fS1ptt^qjFL&N*c_gmg@hMkHej?C zp+Uk+jC1a&9^UaRJB%Kih10i{9qYINs@l*;RQ>blxa$O1?=KnI) z0T*hYh52E3C{>vbs}IdXhgB|Jw3}qq%1<(*&Y#%K_waY7eDEv3&1(BMKRyY6r z+LlEdO{)IXodG29f!*B)TCIDV&5cImR`t)qXo}j8`33fYR&*!ue$w$q6Tn!?L7tO6 zl#^zMyY=ks!hY?kks>T8{njT-!M~+B(2o+q{Hr3tNN9I zJAG5N*z`*P>PR2&A`7UUuHG@+@wTKPpn+Qp8=x%J^=rNolWtR#tyKcaG~IFs@!fx= zS!dBTHtvwqXAj@>fFu_VXeh(XxPc>5Phx$-1ywCQkyAvsC;3E50LQZ${Z`2U?1L|e z6gb()08FGT{6E}dT`A1zF{RN}<-|RF>qm`iK4JFzr zXv9~|TsD)_T(V4bptHPC%KQ^|Ik<7m&xKf0#B#*;sil-l5~*Znj!{GD2yDrGEG2*w z)I9J(q0m85?E=Dv$N)UpZeubzpJk>C#dO_h_f8q+Wc;uYNn(jfejWU%Q6kFKmD;x> zrfwf0gwSpu>m!a+SC0@PbG$wJYmRm<;fN_0kmC;0&L!;{Dt$z1PxAB?5k{CN!;-20 zEi6Vk3NcWA8r7a0+ayToG0T%GO6QM+b>KuMWiC{bfRMB|o=7a4vfK6{D=v_#M z&;TrYflynG1jnUM1k#X+g#BH+#tKep7w2TxNxm4Aa@`%bJ>YiK*tOtXpoCghBLFF< z+k&~dUz96%rn`2hv%$JX(}1@IRN5Pk>BAnRvFcxG)Jy(Fu@tC~Rf~nZrZGtxL9LR8 zekI{{{NVvTgZ@gtVKB5#gJa1k2ICHr#_fZFS?2Xcq6v#c=_F>tdH=#`rvORmaco`A zB|zFyEo*Q`D%@HGl328=OML=#2o1oZ2U+?#m^e62hP@>{;6Xf!`)-oA_8(+M=3F2+ zl~Ir56qk#j0&NKx_zu8a?c;0$FgT_CFpPn*;#1X!S@kc=!AODozQt1cqr^5^gyyAa4_WGs`6{=O^hjUHU( zd~o9&<;=$pyd9&O`$l$z16WA3c*i zF-+{QH8m5;?>}usfvKm;xpI$e&{sjj;R6r)VWT{ZFopiG zm}ai1J4n?=TL=JEy8rri`!Yn9nBxdk)WmUw#r#%J3Hz?3gnep$iKI-7BYl~X9s$(L zKx+dafHq1403Uz(E_pSqN3x6Gk9t$VFrMkeK>!q{mbuF$)9s@<#Wf1gD#UDnan5td z^)Hp-oSF$`3Dl5;zDSd7@KDfRM9c7;lL6k~zzC><4I^O`O}m3iNHYIQCgZVjIo`ej z8mSW;M|4u~EQbYH1t*-g2iSpg*Fs2-W84r;|qBdFj`U9agFeNJGMKzC%Gd3}`O>GlqOB`lC#Rw8gZgF*v$-6Qt~ZJqh{&OTY<4 zqG>pu1o6z~wfU`rv{QUo#~hro;;xzt=s@U*8-NrFxPXv|^$L#T;O_f&C>KAGm+al! zxwP?cRhdj#(e0zG0)Y8k|7B%^Gr)R=pln%nz5eTL_wJ+;b8sIv^aCY`!$x^nh)<%w z@oS`lG7_alDTe|jvXg!D1SV@35+{>=uujJDIK=yFkYe^Gpw?ARh)FJEfK$4FY6DOk z0H5MmkJ2Yo)e98PsH5R^{hIti04HfB8BU%;%L3d!ao2w_hv2&Yt>Zu48DIeR!fJn( zW6ChBgNgeJ`CaIT!f|+R9~fZ@{oS6v=?*fzKnCI)8O=Joe`J!+oZhk&pbuJ(P~PC) z^2%1ht5sBnR7i5Tj8RTa1=R+i>=87kTT(+CyTF+QFDk)$fnYq5aaWI_EjkF$wS|*p z4p0J)pn2Rrmg|4YWnKR;>r#XaO8`KBV$vk?JvJNI$9?$FkEw;QRsqd88DN5bS0ZY0ffLoN0yP0(Kf)~Z2Q7poW%P)DD1DW8 z9UXB4V1hMAr2+5}yiyEnx6chTPU`DERX(qXd&!NAI^_Dxx2$;?v z@6Ws-i|=`LG&7K0KLZf~&lH7$I}Z1WhZj{S$bBhvgn)j^Md-a4kU&FS@kshP?m9Z+ z1|Uij7^-KaVZ3kgK7N`rhs;<)RlqRB*Y#T&-R#uGS~8Z~hg=m}3Lt0$G}c?Lf9o4# zFg`3Pbf%)qZ?6TKN;;<7?IKd3puz_3qnrbnG8Z}-K%l?n4zh;`<;A!NUI1~(5_o)z zGv6eE8;$vY0@&?}Ropm6BDf3mB}baf^o)Ad-_RXq+>La%8vxiYAZa6VzzYOUG9e=& z&wKNIj>9Ae5YDkA!eEvVUb=mxnd)@;%Wghn1BkF{M{6h`3k=fVAu}s7EoOScgxj({ z{_BRYQ(WAi#tKOS`k??Cp4$gTIE4OXPv3P18Db95a|mu>F=Z#_**5?`nuzrY{-0E< z;7C#I>TmjBly0MrHmwhIXAHLH3^gMOOH$y*oq`6J#e{qc4ER!tl- zy(Xk#5M@uloD3)cGR+1|@m^uQ9$RRjr(FM1U6*kE{?c6jUrqvZ*JqNn-en8-O?x0M zjus;)1E!9f3X=iufB+u)Q-824&ZUxk)}jPCA;S=xB#34ta|M!Ug?77?GLmA_9Lb3_ z)r&EtJ^+4zbRg#F01SY%v1tZ@#nMnUd}en~DmimP!ig^av_Sxw*LMxUupa@M+JNcG zdyVo?4G^{gh3ntqgLM5*EroLUn6I-`4u54HLX*HGnN4fpiZnR^=r3fHBgl38z(xEj z?jY+HnP6@GkWdOEJVHRJ9lF0?h)KN-SQ!Jd;mTSQ9O>lJu7BM$B=i?N zWdkfgMGX<`<$pq8EkFy4YF zI?pe#nsf*afRz5bR9S}sDS9N>G*ZL+cwt)wF16$=VO>A%;qi!UDSK-ej7v;&`>4LZ zwg>R1e0|ryR0heK0X8gwoOV>Fbu+47c@kJLOPi>Bi5mJ9JX@0i$pD9G05=8n z{uPnJstKqufs>J97I|HcFTiY&j z3g}1Fw-W(Cw=*I|l8#D(DM`uX?25CYCV_9R*c`xt&yc^$K)QWs8(@c1UH{e$u;J>_mOx#h0+5tR-~yms zM%h@>XwU%kL&1HSI{Rb*jrctJJAdY-q^HidZ$Lk^oPZUb!*P@-=~gT#34O(glQXMB^L6hH6{dyrFR3BeVf2J}*6|1zXRMpl(=pToP^2f{oj=>l`XQ1TaJ~Vo$M8gs&zB4A6 zDwb}NEUkrU9?VPz#yJ4(L$(BRqmCue8#+y`%0#_>8+z zL;WRpGYVCc+%7TqODCb#N=3*Y8x7Ugx8tgc5_} zJV2s)QxxyHRe^G0==8;&jtQo&9jP)Z86{XAI(s&A;ir*Ck5^{I(P#>lR3{gvknIhJ)K(M#$^T~6>6nMI(LYM30mF}9(poOp%IF_kok~W~&Dpnp7q8R(1agGr+u1b5YCz zdr)*>2Eaw3k5&>zp?!XV<JSuXiEXMhXU%b5h8#$*|t3OHK<0DGyA7N8agQHz2!zJLN*5{~11Uf8^J zUxT`TOW!w8Y56}G{SNtshWOIwOI8?=z^0x7o{as}FwHNpg0$ZTULt`>z~&S(Qm+LvqR?kSt1Bj3&}|Wu zSpvJsQS#ceuaqmCFR{e%=a>**2?BNQ*G+zGV2eW=Sv$Ug7BlaD8$BOMq6;gdFGyz;MdXZy2Tm{NzDE!^QEmJ8+!Z z3${<|`aL~lYLVTaH;!Vxhxci=L7mcI;l9)>K>>3pAd3Uupf~qgWLY>q&kCu68bgA?)W>C0ZJ?#{dJ83fX*Q`$n3r`U}U(YCG8uq zE;ez;nRCNTz6{7G@r}4V*K8HRXGW|Gh<@pmhKN8^gD-HP(*uXk1>}%igync3bb0X}$B;XEIqesB=eiJ~dxB`#P)0a^CnjZMQazW}Tn+BE~p;iEQ+ znU-J*_iF7=;VQB#suv!SmXUnvr+{s9%BX?tT2@Yzw6NFlS4s@G4{X%7qBfe-NxXbO zk9nc=2@~GbF$cs1UXvKTpu>gK+d^0lu5_+M=(}O@Wk9~*oNG=;0MCraenEb@a|*0J z9k2nAbHn#Sihf3q0Gdq&J5!k{@lJn}N#i^3$#Ef#^vu{y{T8MBb{xL&szJzmNz=p+gurZ~ReUvVvFbTXjq_`}0T z4z)QzPyI^=`T&l5K#WADt-%+gWx)EE;AipfEma5UB+*$IRRx`E=@G!t)yq>VNdooa3U$fzPXa5Q<7}F*P9_5>J3{octS!Wl{DxQZk{-_4;!iD*v%%WEU}&t;-%k^s z!3GpiEM%7H|2DgW48{2lTS3V-!$g7HSEnuMtY<{!31b8WRwDJVzE+VkD`e|EJ*hvur)f z0PN-Y^_jK-M{#^+pr1M8oU~dafZ5=C{)`g1I2t|JZUZ>pYCSs~&akA1WWqr9xz_o3 z^$A^6RR>Wt304P34+Tn;56l1qgcnEyz48K~92ppbF#e}%C&`clT_~~J@cV0IS6MXl z1LS0Yh4K`>m(iG0h=A9$F@beQNO=YU1F0c?mF~Zb`_!<5E>YicMxkOSnERPzPXGWQ z07*naR0=P_ls~V#|7rq&dE(=={~4D=D`5cSto{1R86~?$=$Y}jFaXCIjVl2BX@Dw& zfB+vz>dX3)>4O8o3ET3*DLw2{qJ{#H#TGH+?M<8k)&eL$Dp`&UbTNv}5{U%GeVI)aco4&Cg-_mxk zF#_;q!j$wTav4{6dSE3+01nCO@NMz=Zhj!+r&OolY`b0D5*qjCSl7?pX?j2~hkxJU zyFGm*0KJzaJ>z7isYbEQ0APT=_6tFKe#+%Q8f(jXDc4c-1@Rlc#3xmvmeJ^|@!fF> z$x_S#YqH~ChAGcDiP{|B2lP}v3G{Xgk$;>3%TMV3li6Xko?pG<9=NHJ&_g~7Ws>_; zx>;V-o{j)MH5`(vJRN>DS%KJNdcZ)>(JFove%~^h{3iy3B5;oyCr+Pueh?7h2mAXL z=vP|LvnU&YsokOrRvsk3-DF_}p%wud36>d<@V`ogqFE)pkxw#`H=Eyf}1MIj0S7^ zI21l!7%#h<*)3-lie_ARiSy7wj{uC`dJ0U_Ix1!)`JWh0*9G6xY-(Vn@jYQ(zciSo zh`}^ng;$i_*L`N_M!Gu$kuK@(4(XJTMro;`rMtUB5R~o#RJujFq@}xOzIlIZeQP~` zz+Ly==iGDl*=KK0H}CRjiwSA|RGh47>K_>I`Lrg0L!t=S?gW<$HbQ^QBAW*3jHx{d zLy|jYint*3n>Zd-cu>A$WOE$WiFZn2vTX3)KP9PFCgm?sO`55Zchwz5OcnEQK|Iu3 z%hIU2`sTkf_Bn9q3)UTpsVviIR%x4>N+mkmqMmrr0U8kaE0~RypfdVcDV3R zQf4)J6KXmQomrDA2)wjS7eTxHjWNov=5o=zwR+k(lib}6;XFXSA68)@KFT&5N_9|u( zz(6;FI=C!hOSM1eZ%M|EsJx@(j>AKOI+1#lCwW?X6PLfX&AWG2*nIvpbt>0P*4M=I zdr+95c|e&%QhK3{P}Pu;|F8!Xh&HBXliLQy7==IYwORHwY&`^jW|cUW-wH3uwx4Jd z6S;c#Ya{*ounLvQiLk8^UXO?~07v<|qmc5kJ0 ztx(H83SpEcM||u`dk5a%{%8YWk&I=BNL3d=Feqk7z6JWskla#BG=L~D83fkTKDe)J zXI96`1fOvA-6Pew_F!ic{jKzZ56{#!SxSc!a4k+&u>ulSYQO>tfl5EW$FI3!eI9`S z``G5*CNel+RX}*&b)YjAe1lx{7CkaL3%TVgOUqTBd_O8`nsX5Sy|~1>rq|D!B1x_3Yg$vh5#@{#(hfJN z44=X7&ODh*!6ons-|ntJK@@4tPwGOdgtoyNc1bqI>kj?EubGOkK9NxkYU&R?`hiiz ziz^~0s?&=$9v{JDHqH+sh4NRo_DvwmLe&?|QU!`iOZkDS*lX7Ge3ZW#f?e>~HNdh$ zJx$~@glAxig0g|KGivw8>!6~4X;N&uAKqyFzNRJdR`H}rtu4zHIqV7Xl@=^h6WJ=c*TjwL^jjPKP8k17q4b+THndYV z`m#F@@=DSv*n;;-io{GdI|b`33jDT|XR+K3`)XW21Jc9xy{aH~h2V)#T7O-Up8k;IgAo>iU(eq#(${CITjke{!S*|!IEg5Gocy40g>glO!&6BRX< zy1iX}Olx>ZP2Ra>$Ky(XWfsp0`aDUfy*&{WVdRQM3lnAS4* z)mM}m5Z|0;iuteKW$k+yK-TkX4J2&k@2+1_gVq7R-2Dz^#gXsi1%d}(zR#+LM0Mnc z-uCrb_AeCl`d;cjHHav12zO=iECF2>bE%RVL< z(VJbc7Jhy2MV8V(j0Lsp7@IgsIVkwX!4 zbIaFZJ-pqkL2)&%cQEQ(O~I`EWdqBEHc#kB45n~(Igi#eMr`$qKkyATx>)=jMW;Lt zRP-EuhV*Tl=rqvT;n>c&xN^0|0waHFUGYb0;xe7`cVsI$WSQ;B0usDrU0t(&&OY-& z$e}|$YC#=P9f$wkwbxj;gm;OjCm2OsKm3~Qw56PzRo_UMfh;bkb+WTUVxv|;Pz5!?pwYU&D|tw7}dW0Vzyl){g3dR39lr* zmlf6cMVpjq@{!aPkfO;O0!giWpl8lk=1keq(b{y?OTY_y*xM68rExd4#CaNoM&N(@2M` zKK8%O;I}FcyQb?*=2PiCUM9$=R8Z^LUN z(}P_sn4xBIzHx41)-JG&^muK(Wmv#Ll`&SjsQnPUBIy)e*+itGv^k`TQS7l3F6i)f zL%(~C^y(8JAxO4T{MK7|8fov8weFY3MtFo2fAFrKr5lA58qNBu|A$VTjr-%9%G;YK zeg4h4!mkYmuQY^f!iO62a4cZ`>R))O2P?HQ{Hxe^`pMrKq8~-@ADWA4 zX{eB-2XTFA6GE~QAV?KO-;uYs)bw8okGv`%w||QlVDwNJ-1y!vMkS;vY`csH>1koD zfU8=jc<+r?wn|_?Y%f?9(tybb3AJHfDa@tC_YZKp%}sOx`vz6&cHJKw20UF7*!8_v zFigUWDIO$1M+)?O#=~E{9nA$*J6a30eMh$A99{+%NJn#YVwgzncEg9?-&2OecvZY+ zydXb(Sm#L5nP1y4a|20Ild>LjdNOPN4kKOP#x15X0pF_S*Wg4}O@JxpbzU#rb4V~$ zAL05CmUcwDko}d=w_(npcCeo5nm7QH;f2kO-$slz ziWym=q&OAA^Qtw%SGw}Dx?3C#Qyoz64vt+|p)AB0WJ#6w zp&J0!l^7R)>g|?zi$x5i#8yyaf!dxwNoqN`HKdEYdLWeR71_}rOy_e7NAF_sA%pA> zWg3;0E(~dGmwe0mgALsEySBbYh9J_&(X}Y(%7tG~+`hRJUV)xxfC95}QB#61k>SGPWxnHyhnq?cIg|`$lUZ^K%a- z#ys}|fh!v##uDeHizO7j=mu(eB9b@XV{ne;Beze0?%}M zCF9amN8&>myH}S}W4XFAProk_qskCB?;1YJ3_5uaJ=5=cOAb+N@!5ZZMU+K@=rW^N zY%Su+Eo+C+i|E>sgD0F9B^x?Ts4zV>zj&1_c4@~^bq6)g1}3Zz*%T(;q(|)`eQvt{ z0}r47N2E_+#cW670kKtMQ|&pm*jKlJZ>3RgD6v{{%?TkL)%$FR5zblLq-6hNy|4a? zeef|GwDW3$@J@XsL8j_venFiyr|8F=f*O_+#sT{JyyM!uBY0ul!vh1~APHL`Gyhp? zpH2}#VHO}fbxAyXx39L=7?KuTOOrWy?A>0;_q00(e*n#i`fM_>%$;_maN@}cuKi&hmo-+_6?pULQTYomIEncAE;>L%jd?Z-th^y^ zvh4Qn7Sz?W{Jd3H$JRU3bX@DvMU#7j4`-~7vzZRr@4tW4jPfV1`h61dZ&Z9>8gYArsDQH)SA#+f5ON?#j7ol-u5E}Q zuu-^SsbAje)HlglO>WleGMaBbqdBK7sTFx#ZBRE+<5E@PE#TZz)^A!AcY!5kRmv@9 z!wQaDMiVT{QJ#5w!pqhZHjVquNJ&a)i7<{E>xbO1o-MeA-s-s5gr|mgmE#fI3|uAG zxqOw`e6MtLrU`67aUk-;qvB@Rn6W>{kgAUxOSQj|H8K8B{nVXEp(vZH`XPWNFL&hb zc6>(n<K`g29&cnCdZo1A>*FV1@^v&Lg!axG7HZtC#We&V>G2gWM2 zGshIdwUPN#9jR;#IVmOm512S!%PKoH1J69v)$fMAW?cZ;3YS!&#?KizlbS7FBMSjP=|+KMhgc47yZuUS+R^Hb>H7@5?i+)r9ofES zZXJ=2w=FGgpHOLtVPFyt?}jEBRH$OON)V0x;5$Q;mYGQDJp3NAk?kEkf1bR zpH78L^>spyM7t~{6ZIVJhi$QGEZSQ#9>8O(FJuiRa`c$f&!Uj$qbsWZ@*kQREGf!; zQkuz^+~m+rxKU*G^=%Ueqg6u1&5XjH>bJD@|SBL-~`;N*%IaZ&e1`h9}D3 zuk>zDgYwTl3m9s_vxyN>p_5T5-}*yR>4}y^z@`d(v0=Hmg{gR#&wp-~a{M}&C^tQ) z^-ExC#)L9%0IXZoXCaEdZH9viCz?8i8bGOw0loYTd=9Vr`_|+*Rp(D-)Bxf^%k&gc zr;5TRZgtM_GvKx7mPoUKwZa`8GnE3KoqRaMx> zQ2N_6pOzXB_!Re{+^Bnh8iXq;0mfGp5I*^Q{wkP&S0wnGm1vRwn~8PG`9Cp88xkU9 z0e1Whg~%7=O7Sde)E>IyfgHuB=c@wB8hq_S%=}tec=gbz; zAISO-hFaVkhbjsKVo&V|*zo0p?~K@=U;nw*47_|*z+)xSS6M#=qjh`6BWJ$D;Dogi zNOoAmXlwhaAexQM8)68hGWrmBZDbPHv3H_CZmgevT%CyW1s|)tE*ofO%dH>+Us#|| zT)$t7#w^p}<4h$;cymAR$JJ7VKXzVf#MBtaN3Y9^Ots4; z)|!vEkMy^4DkSYnYpcNSQlOg#LUqU01s^1j@~}=XAy7iAA}&rR0}(Op-7Jh9pfHqb zCMuk+uLcIzXJVY^G&jR2^7KIKa6e;2&<$A!diK;!8jtZY~STVi$q(|b57hhD7d|(B76A3I> z$GzoDm|h%mM{iop1s5bhs*xrP{o{m0 z_57{=bZ>dkIQaQ|z9Spd<~H-rFXevP(C@jZv<#mLo_QQSmK5T$2-hW5X~GpGR}Q(_OV%q}}NoQVrWDduBi;Lf4vl{t#I=PT!3$x9Us; zf2G3dyu+IVPldjaEm|Iop7@9I&}`D$dwh4E=_SJD&??#0=wZ*xLoIwlJAlSI z*%qxk|$hQpbmb~rgL z>w0tyvu%32yN_kI&xdtbF<1sElYiY>>&xec!$PC`Fb3s2qq6WbUJ;RUx6{~OLZdB{ z1ZpQt&<4CGzvHP;4X4z*{C!&R|K6d{)$N}}kA#7a!U2d{d9K@4_Orq5W3c-k?uLlF z%3s{eO+iq&en^mwY?rZ6Tcj(u zrSOKxpiDR9Cyfr`-94{yJsCUKt0+f?US(pEM($(5R?=dajb7chIV}L4cdjMfhqHG2 zhiuW_NV0GC*nW|HWdmS-lpfha`doXH?e$uVjy(i^cvEL^+X3|01U_%p)phN&jWuCF zg24T>zE(O+9<{wTbOm~x+M6rEtMV7NPyVdp?*LH)ZFUFL014%l=5Jh;pa&KU76sBa zl9yfhL-_7@DCV71uL<4pSU6||Ojw#C4clSQaqiM9lni67XN6BrQUL?I3fd3#>peRw z5*$p%tMDyBtN}?WYTH@l?Aps(`Mz z-s+xm9IQE(d(kZOw=?ngmDJz%@d~tcBZ%Yx>E=ND*e@RY7k?FHQ?+6I^cMr?dASS+ zkrcO{eUlgiLhH%DDV9zZuTC<9ulgit!h(gWnY#P}kN-nymuxN`9pR+s45#&Q*3BB+ zEQ)v)tdLC2@GnbSNcc60y-9jx`RZm>sX0jE$=zSqk=$#heGA)PEey%r=B&nUF9)#E#_1HzFZNAb`kMl59GTu>x2L2%O{3*Ce`^|q7mh9(iE`&+SnJ4`^}Y+QHsW4 z*vm3HA8I}+f=?Gy8spAC2)`SL9u!7=1OM)*7_z9HFKiML-XY;r<}2#GE@B}nTTg`k zaAT`nV?K1V+rw)-Z5_J%XMXz=!2@3vgWtBg8tZdA{qTX8=c~NWV)cq}AXWsX%p6L; zXk6{5>SB8U%vXmxA$ zR1JpHZiUSK7N1K3cbKm9h&M`X+Mrr{HC7f9=c9NpR^Ge6)+&z46-?@&drYa*BS;{B ziN|_RIAoiv%k82<_QZ6hDKoT?kVGr&@elSE3tGS0^K8-DlJ9TzN0Ng1)SnqAdYZU+ zt^m2f?e!G4Q3(a?cszGK;K>lRt7}<&+0l$=g5s*u@j4=@u?_r0^*vcWDNzG~Y;17! ze&bBdrn=b~Ncl6)`#nwDE?T?KYl$T2z}u1GzMmJrV#6G5s7gUI=TwpK5BS4nw{h4& zYsr|1wqjkb&oBAHGu9xaJM(|VZksC;w9#lLb$`$HqSJamg`L1s$5gaW`aU}uTEX$& zx+4QMjG8xtq{4FU6(A_y3)h|d(T;r5=4CJ<_-=NKcmA6by|$_hE)t!*YE}jrNAvJ( zeEHZnaY&JxvueNUJrZ@<59E_8=`03T@v>s~@8i|5LB8{yV6~}L=(@>=Q3sQKcD@*W z|C0@*Sot{U$Ln(CllocmRxnapEQ=!B`R+uQ)ndf~$#?$dCb-ROxntfAWj7nPql-9U zi8n!ObHxKZXd6u|8HDO-_dAqAm=jJ9&s*`RcLp!dyxULD)PmsIlG6Hq!ZkMdd;#8jZ6BR+&Vvh=i+dLE~SnAysz;c3<;r z10f$hC09FY>d3q1?C)2s}PV(IaqDQfqwM6XDB?nqEvvM-jw;1Sq2uFDb6copHjAQ>|@b3 zv?%*KwST&rz&{^6cJG1E)>pLGAVt5CHTWv#LIpco`MclPn#2)3onE3Z1Z-G|@T6O^ zV80mCliZpuopyTcel)35`<%c-h~RBrvYc1*GIQ-Kqs(B-9mT^x=O%b*ypH(EWH@=& z?@o?HIvOGo^{DatK|PQ7v$W*PEW~Ux(%^QkpS?mb#ouiC!dX;hQ5*)~Z`o4yKe9l0 zb?VRg2iSX`TMLU`bGv3tv_%{)TkBWCiR@RTO(m$n=J(zU}LR10cPvpf#BQ<+LN`-GS-@g^z^dd!rop+X%vp=-NO3= zR)gQ#y;&=sD^3>#3=;|mQ#R>oq<0VpWpL|{*JLd7`73^~D+ikKm@q^oU4cF7Q-o9- zD=tnz7Xj_={`XM4RyTz9IY^EhrT;VS)UJXb;-$9Xhdkz$CEmSFJG~2&cI2bVCZKDi zvmwJIiH5OY<~HCeYWmK>sSYJ#p_0OZ7ak%!-x@0Zp9??@;GG_IF^)gd`mvL+56BzD zh^6|XyS1s@!#wk=(;xepOB&O&j2Gf8j7|h#3 zD}|*tmD^=KL2q8t`l|o!CE7$Dr|UMJY0t-Y>)Ul6yjr!|FilA&mCG2}VCgST0QalU zm5+YARLEkYG`%Iue$t(Ul&7Ww?LS%j+Ho!65(jI;nf84SEPCzxTeuk8S+Zh=A!W2os@Ne=cWsP z_%LgfiHy@^-8C!G^S-032%+uSyTUSl4ZvOeA2Z!n_(yr&revNT*?7~x*AmsOXjn!u z(fzI;z*c5n&1Ggn2qnGwR5*Ja;OJJg6CS)JAF$4qkK9nL zV17VOR*jui+L!5xS%Q++rBIqYqRwneR+B#Tm%s%u8s=8i3CPS&xO)(C2{R0kkgEQx zqs~0dWI)Hw0VGAjYNXMx(8~WvyYHD-{cbz709*V%3{dXHqeEK@I_~gDd=mZ1`|9Dg zUGXLUj>VFGaXJmi@;<2G4I0RRHFdAqnCsXR5Sw!C_3Yc7x!v-BLay246 z3m3oaJOvKy{+f4j1{NkRPkTHaM2~*paSyD*Jyr2jjXsF*qZZxeTd}vL8C}s8-K|bs zs(qfn^#^F2Th}|g#Z$_WSKF*8@u43o+%)X)#Dj-vyzQm%LxUtOCps@EhCV%L3FHDs zCWPnIjEeo@)bTDks)%01zw5(QNOwGh8wgUV6w8TYX&r-fv}karrr;i3$p`Ot+VYSH1L1ww;P&Y76-<%JK#*Isq~Gt zbafBtfVrgj@7TdUY%mM7aqE2E#Wk)>Z2EnGGxx%$IiCwwZn%z zM=k1L#ezmO-O(3Grih^K#W+>yj7IQW7mLia-TwBnQzK7!^*@4e(Dq1UArZ1CLXCIZnYH+dbe)kXr_gFg4^$V(DZl73Ip?_*7GZ{(stY2!L0SMu@|XWe#i0G@qcm4sncf>Jp(FLTkD1Em2sNB) z!u}hzdLyBO&pgTUHR$k$dhcxt zM3wb*@uLMVp2;n3)F@!-fN$Z255;&IK3SW0sdW>iaH0Rxcof#zsqh?;QEDQFvNM49 z$9f)K#V((Cz6lQbDQJmb7=B8GX~V=$Wm-UllhuZYH@>(|ca=FE-Yiw-_Yy~T!v;NK zbhkgiSWTpQZi;qR=jBRaMdVGu8^|-G{X{@eE7C^4?^BCvW>iRd;h3?`UZ$E(`RiX| zR3st+r~sM-`Uc7`ogh2m2d7+0faZNG;zHIZ44%mA(PA1_i;bw7K>zxGn#tt;_wkJ? z{&!G;cmu98dWm2Ng+8*%PQ?pr3U2CWQ2*%ZP+P;qGR7-M&6}B!?bqO@IFA0AOtt~e z@4EdwSFEIgB^;p&!I$3eUFr|75lQ24C_FHeQ_{%xWIm94_s4Ba>OfQ|ZafGojSYTc z`hhGVO3~f0`sqU@(uPOp>aDYj`crJyAgV8zsV7z3Rfofz$_*nR{{^L#10#0WdG)_u4vmWGYu z5@=U-ec)^&YN){D-@OmmafQexz3@)fo#ucG;=@D0e8Dw1fV)lNTNKDR&+YN=PnN8V zgrek^cRaeA{UoI^16q|%R6{$mdqL1qB87Po^0SXjJ^Z}pSX*G}QH0Doy z$a2%Bwq3GWvcy%d)M+f z*tOVeiN79;UPc*;Yf1FQe%fv?sz+W=f2Gk5X2FLBDn^FG(%xB@cNc%+w4>e z`I#*slWE;qpYXZY?%i`8s|Jy>r032^;pKAAn8`aGl#n-P`C~zC`)A}pncqKM4!LA9 zGURZSBINy#AqXrPA&8LaB?_4TIS#V4w~q=m{(DmNcjxvox1fT34;B?$s^Y^TEkL;; zcmGpz2F6&khkmBQK>Blj5vPnAi-+<`v;K4PHx4DEpd$F*ee1_M_I3^>>cEKz95>rcn5`eZ4H8}<&<#l)ALrQ?u1@i_oVL65w-zWt+8JsVcZeNwvssX zu$@K!6Srm{z?=Vp#(z2UF#t7Ra)zYnXURz^_hpg~{DTq>kg>IgfejW0Er4OCN+Wou z$IsW}<7%IE$9LsMSbx_{O{L49Mo$OhiH9CM233Qk7YGc=t4G|ebkf6c8(&m1IftWP z2`La;twiBb=?gBR6!pgax_4>C5eONPuLXK75kresR4$@Bv;`v4$XB?xYY`L`A{ zKGMMz5-cAAt~>M-Q1^qh;Ql zjZ2W7&!hYP*O|Q`>Oh{{sZa!S2*ks$x9vLB+kJ*eFKsv znBwCYLoup8>R78!{m+hsUV3RLo? zRq@g3-s2IBL$WDgSbNvm58(XO{(~aC#-C&>J|!eYlN}^OFJ`5%QO0{9KjYp!_Z9WV zOvJ)S2BqK(2sO#;`pLpWI|STlW&p zqh?w8yZ)(GARGCT@?|^^UqjHDi4XD!gvmW*W;N#;AEW+5&Tx0#6h)QTW$90m_6 zCYDUFJ{{B4#P`-hNgoRYw))ri$%oT?>Qz$YBPSpE1GSGN+dBpU#Jac~_%K@We4~QcxSq=vr`P$} zB|kk}Q6g>!5?k-q-||W9u&;3bJv>%A7m%@Y!tmyRyy6d_D5lUpQUWGJC2jC4mC_Gp z>*Vxbd~(~luS6T*r!4a1?#FFI6N4dhGcREe5FiKaY;wDxW_=Q&BOpN^x*NM{KzR^5 z5!LSXGveS=QH}~CPA}ueILwjd#J{MBaJagiUWsQZ>UI38bCD}3)O-BnJQPl7P!HR@ z@kZAv-6#P5yx@8K!WAA_I`ceeB?MIc{e@BL5d+b{dlMR}BJo|Qt#|IBO9KtM=hI2M zxZJ5tMcA}Z3^3S1Nm(jg1n#A1xlt1cmSPt2_7Bs*x7ztB^;wj5c8%@c?xg{lg?Hse z>$P=w`wi5>2@NfT<^)@8)|CM`PTz#DG6f$HmHhMIZQgJ=aCX@03SYTCEN;PMsPAxB zwiDWZA5zt)q%7j;*@O+$-1~t`kqdkA74adrM@LU{L2&2BY>ab6pH$Pwr}c70|3#;@ zG6vx!1E1u94Ug3;Oh4!LuGH1wU}4XKORv9acWNb{u=mlx{3p6NN?ZONPF3NS{d-$- z&G`+fI;#>Q8(g>iDP2{q^YhUu`@slE>;7`@&v$HS)XmMB_x*)%@j=_JKu*-8dEm!| zc_}vGTF-qPpavUEfP(Lh>`Np(}RDMVUCAeVKA8u@F+rxavb4`ZM=tR&vvEI2)7$KZR&^ z=)3dP`p|cuJjvjmIb?Si-upjTq;9)@RnsYb;^6ZxZ46dsOe#(hD%yxd9TmJl`oMre zrMt!CitV}Xllm2(b;A+F}*h3}7G!R6J5rQnjg756qBm@QQ#$lrxkI#J+6|5_#h!#=|r|=vYAF zVL0?bcUK3Kr%klZttK*0$5^BYQX!UA6O%F2iIZGK0MTX3H`-{J)g}W$4vJa5H^1DR z%m1aLd+FgI1{-s~YR;uJqvxg95X_}rUS{Nq=`<8#5eAX6g|BYz6ui?_CcA$6gcxr6 zo6DP4@pf2G^l7xaQ{>U5j=9@jAwbilH>NSvc;P{&yR zLxz(L_ZjrGn#yXvdMGjF=psk~KO1Spb30`!kyO>6S|1@Ll*)n9mor)eNpTZwU=i`v z7~$TA^rT({i-T3_+spUjqfBQ9n@L?&(CZGKHSD%UmjGlpypl=91u_W8qL*&?jF2r! zyxh}**ZC$u;zhh))YB1SF=@mC*tSvx$~pEiKc_9!?>~BR$H#}k-~+q626gp?PJ)_3 zxsul_%@&0=rm;xP@ab^dWuvXQ{_ zMau9Q=(}RCfYFZG1_ zf>y2Y5hWm1@<7hZWV^^%nTSR%< z8Y$Mwd!rRSzw=u!%0tNyyK2+I@Xg&ipPB)QdpkBa)repGLGdIzKM8h&60!GlJv|kG zvyL;><1JB@Aq%D!eO8{f0tYV(T{cJ({?5Wq@J$a*la9;(qhPQ z$mTy5a*dHM%*VZQR)v%D!>URh-h32dW?n)2T-iTtPWeTxfU?1F;44mx*Bg=LO!u4* znx%i1rnnAn;r7k@m&y70!R|XoCtXpP`;uQSS!)H^z4`Z*$N^zUkFa7=?za@ip;Vrq zA2(K)Mcs@K3ta{I=*?G8;XmEoy~J3~b4{P$sDC8SApb1URu0%=l#o+rL(vR{T@Etn z)ba=p=C~c3%JLDK#%*|*T>DHk4+td=wS!S)QJ5*g){U}U@Y^_P`23B(WZ;dnDmp+* zi`|0=^4(`S&uJ1qo|bu=}Ot98AB?}OrtIB-MBDO6SSH%Mg>L0Xi|>^O!`fzci9uXrM36tyFk8C3YjiD zm%0@uwNRg(T!p&`rG3^C3Vy;!lnGVJ&!M4qAH_AVxV}@pJm)2xE|kPzWTrU2Xzaz1 zDCA8?^CZ^N(jdoRI8wi#u|j>eSV08#dyhjz0WstI)LPK)?qHoCF=XZ|EKodcy+QLT zXY6Cz{!2;#d9xGTQ#mx|g4A;HgxA^%?~IRc=5RvLK7!zgvb{A{y}yM8DFYKC7H znvQ(R)(YY1BP&}X4%=Fe^!uz!Ca6SzRrxii5#QMpW9pR0NKFXrI=G(sVSwntpVuyh zKh=D}v3sk>Khc&P;*>hvYT9;}S(>~q_ve(r6wV(y+2L_FH1&cXFl=H(=Q%P@!)Z(3 zJ6&CT{&yYk$|54uRk0rI?BnyL36$_1Kaug8-vkMK@*+{}A&%#a??L-(sz4$$y3H*@ z9vbyo#RALne#T}3_xYFp8R5?ZYIsq@Pn(K>I_^Xm0_s0)yL}o~K>Dx#MC{1fwmVt- zSwvB=&gI)>a(AZJebf9v)j#wS8+J+z1=K1_q_65Mh=tt$yS{eK@M=8rdWJ=zhM5rV zErU2WI&8J%#C!TN6kdnWW<{#ME5e^mR^~?%8NQDlLDu__`A)uC)qQ&wiJ~xIsKtf^ z<(ZD;^wBSH*qv_UO2|g7M}QN7re7!cPZlBslbv_&TP?co&ijhk9|)V0hBwpBr8y8O z^0W}31UZdBI}etCvfL18RGE01lU{uX~4AknjPJMAJl$B z0svFW@!*mIa!c!bU7rgiUii^^Gzg3p-exMtuD>aD&29*G_{h+PM;qz9a+?w= zrBIJn-iWr1@mXj^qAaU=yotwnSHJsYc{2Ysu3wKp_EUZ=DcqUs@4d3|ReRO?(*3)s z7jJOVN>ToH*4qe*zg@N7-IhPTfd|0@Z}}+z1s&Lt$K>OjE#!$UI6jX& z->xn@gR_+G6AtIs8@s7F@_nQ*Dr)plsvtbZL~9XRRyro?R!iw0bCKCTiB}CY3Ermk zd(tf)zvDK$f-l8i(~1XnupvXRw$586JT?)0SO%N07kt{HOqS^SDebw_w2EsedPx!2 zqdr%;ydV&nHHgxkZ*sl4`5M7i9Hfj#0Qpys;Jdpux~`1%J`?3~cf3|L^fq7DA5_gL z_|23V?D!utut*Ed@gLqf zAT+7XLSb!`3VC{Wqh>oRyDOg`86hw}lh2H@J`o@&_Ja7W&1t_2)HtL2 zd1X?}P-^lKsr((yCzx zmclhH+};(2NOO*^YO2g=kC2=3X<}M%my;HM}0L5eT6}&40 zoy(Dx!2QI|A1HcSzfsF5qj`;|QQd{V`~-hOT)C4!H_^4{F$g4Be0=xIWA~tsw`%Z* znf#{kl}gjLfC~X7KcOZyRkLTBvms0Vs_8;j4AYTIGzueCbWjuDw|BQw#}?N4n&dkV z7pM!&((HPh*W+Wo>0+#(GkD*P$6h`-)NYB?TS&_VAlcZC zM(5~9B?_VP^|iOB+o6021UU;*1lzhC6NVKx%R|}=Z}^TeKV;A`ZSg$&v@y$lxbw&D zvghtHD-DkO1@-WQJt<^hB!gT+sI7y6!xP2dzz-2vWLflec;$Zj>IwW4Y^A%71;Jjd z-uwDI*6g%<4?A-Nmx6mB#Okua9}V1bP7XXt$pMa8RAgx2H$ec3sLc_0Z*M@|I#Efk zt(&n4r78l+E2m2;^2b$<_kFBA@ZsAEkao%-Oy>v#Aw zHgUni>-Gz>KAINzE&pfOC8K{ljAhje72w-=RMVjOLonuul(%1gekZx!ektF*)^0}# z#acS%`sW1?aC6IjoKQHDa8ji+!>t<+&K3}WBz*c>kiAVy^?@?W$@-w(^sDXSxf-yK z!2`tbr43AJGM)RE_EQIIxfXhi?@ktoK1K%hR&6Vyg}DXp_On(aNv!Tu?Q3qU`dLX7NBK78>d63nqvp94D|&`kK%xrXtJsUlPPw++|P`(gWC|K=ye zOVR7|Z`&?Iynb$J==*v{;ND=p`D!`IQycNtXQ-(9`m7aOmza~OOs=z*)1bx{($2M`&5|8+0pjz8*v zw#=^_r4;CnSa0w2d#q$oZgyKnrbU!xNMdM^&>T7b88tjK96$J-$0g#3Xx;b`=(SMz z-T4=T^`PU2&lYF83b$C#uTOtH?EnB#sj{53Ud^;*{D}?{M1BDx=bjjo{4@QU-x;X9 zEDh@$_%DC9@HhV=ka5xT_OLvEq7rq0`t-N#Upw7f3)I_*U1)IK| z<~Mw_>JWR@S$Sz3dcp5Uk!iasl(-L@Qex>p!-IY%+x=n)s93z~o2`U7_68%UZPK03 zD>fI@q+BqosRIiIzpK4}R8?mT)N%q3NNu8KQaL2HNT!|%>YJPcsOTFujpy|f`Tl|R z24_BHPwQVTf_EoqX|az8(cvA02EZ8t4wm%%=P8-Hc8ox^df*p32s{~>vcQN$CUX&Z@bJ7%05C=P z1%b~RSf{%et#0e>>3j93w-g8hkgr)UT&nZBxVzh`mesXeuYZe4OY`&Bjx@Y@mcqK} z;15mAJ7mI@q$r@y8F>YQgN3Tr--9ob{zKI7via8i{`w;7212%A*spln?u#SbotqD( zYg3I1@VT-jV4;^yQJm2RY2?TQG2v!M=Zq8sL52mmohIk6B5*-O<$!>Rn%CO?1UvEv zcstX7{O2)AiNv=;Vy$lWqjE4cv0?pnm4iY@!Ds?LYa=!^2VXW?9GFcAh>lZ6r7PZo zYqdUJ?oITlP@kRscE3Xaok4pOB<+)v z8>3}ppDBcPl#tu{o4NN0J{zbZ z@z?cZ3-%|$Nlk(8{Zn7h{&e1T6;?2s z$@Q|72JDGi{hX6kadS5c+Dv0x1`GEvmT5RG!B~0o>|B zQ;33O>u+x^_srK%N$~~|`S>lD1*|+*Xn0N{XahP`2)ZJV`?0Ff49c2uTmmFxkgceF z9fhBcms=%UXZ?b{pa>8NFFOZ0bCacUeR=dUOu4gBA)*DyRm6D7j_2Iwc-hdt zZeRGtE9lZ8{RwXy=D_^U^E+QP>_I;5qq}ry>A>{(r|G>52V~Ps#3CXAW0|Y)w&dAWKf04kwxIQ{mYW+7 zds>~SPir}9uwg`^IQwPNW%&*ZPuyM#{(sF~=U)?B6W%0BS4t3(5~=16cwZ+NGO^}$50bU-o5|DyI;?5&)G9O&+N?E znP-6N8dJ^RQs-}0Ag{cJ{OdmE4dflyb3tx`MXpHS*~>q?iD1FPkidfK5hGQrs8f(@ zeQC*P_Laz2L6HFiCmn5!nvhd1nm(m8ogK*9iqD2n*s|GYwk8+~lv`%gSKpP+(t6$2 z4|d_bQ7;ymc5gPK$yKSCw)WHO`#lLBnz_7=;xuCx)-<#KcrLrnLVZrV!?b+oh=q_72?D|Gz$OB>^TTZyI(fS|~9oq8Yxcs~G9p~FF&KZt(F zGuQg|Kn29+%L%VqRYqsz%J`mR+hJu)gPq)k$0JB75v|pvk-n6R(&N{M96I3nl3#g2 zf)zKIwbYe5i`Tj1o0g?)(T+9Ldo^fGKxYjBsUy@urKR_Vg_&O4u*n8+T?a-L;qJ?5 zZG>V$NtOsqOe}rxJ{wJX6HK~gwJ4&^gxV=YFxS_SZ)r2K;0G?cVQ)*5vK#OV%o|QM z!dSZ;<&%%*}$4J=MZHJ@n8}My9ZO2_oJ82nzj-4YIxY ze3!s_*!|PL#)t{4ddcIr-W>T+G<%=o9=YA(2RM#;9-(V2h}VjixJZA7DJ42#YYujH zTMUM`uh`JbXw5qnOg+%CyFJY+%#$Y%W#?oz;%=Sc0JAW~GDYb`8`+7mOQpvUV2m6# z;m03^F`K8RH`MEH?XP!lMjmD3PnE(8!fo1bXaub<9rX6*%%}n2U$ME+!^sIeUZGPo zlzLdC?#C!xQD-UcndSBu#prj<%a&qja%DzLS8!$h4^!AA>D!d|Onw&?z(iL_W5oU4 z+Gw4hW=ma3;(M;cbM_+{Qv1J~@_XU8ADr}lnNU1KcWw?;7! z9#DUvMVK2C6FVTuX)JxWs3dazZGBE3REtpyrMS!oYjyWeP)f{RLz0I2rvZz>7w>fV zlUN*Qd@&n!IexZI6N61pGrj$oC2xG!%>RyfPJJ^rT11Zy#NJHP#ZQGtcrEwSx5JhD zUin>aIY=)o^tqSYOAighEH4L%nfveAL8=$IS>nC6kp|a=u^Ru3vAD+sY?B}Lq0Xec z2IS*cLx~%sb?QQ27cy7ZiPY)W3l5PFo^*CH`UgzDdrdcz)s+G0{;o}ptmoj z0v${LTC}&mJ~QE|Gvw)jNRQo`etkEY^4gy0r}1L0eynmJ=P>wLqbszlcX!wE=ZeoI zq0F`QqaKA@vGcTag-^VVoPYKcy4~}{wudEC{-hPv4r3&)X9Ct9M#4NfQXw)N^k`*3 z%QW&lGJ;vtofyIoIMClJa7r8D85? z0YX=`HS^a8C;Nj6$kXLHZ}Pjg&QUwQf91otH(l7ydwM^eaicC2azoNr1SM4!5zg1X zTb8Z&u?%aQw;A1ay7`BjFi2AQ4s$6YLszx7daNAcuadW?E)1oxHx(zRdUo8rFPF7S zm4|WR65@8A$~#F-CS$=#b8FRr+`1oB%yl z6JeT>y%qkf!)Q&h5xEr}-go$LX-csjM_#TJ2RIXAky#WlF*W5y#X}lzQMxDWf|g-+ z42v*|8WF}LE0(q0^WYO`9w^OPJF*CFk4 zRoXWYB>AZi2oPuI7>h7VaZ`=bI*AV}T5AgxSn%#l05opi&>F((ANGLwUVTl5^M&bO ztnE~nc~Chmc66~3$yoYjB27QF3KD6TL`ZK?QjRf>S+oc{yg_0Z-Lv^cEFx>|w1-I5 zDmnigcdNC*@{r_io?QKW*e@mai72S@qXht|e2mf!2UTfG4?SW30vzH|(znrncWnMT zNPry<5#DMmQMMzm54)rS)pX~z#^B0zCJ8a{Mn7=-a~sSKT3sBfE9eZ-gu ziueb==QY;M-;cGi4Yk(s)_Qw*)Y0)rL;USx<~a*yt-pDYwaR&G8=-5cT4Mqmn|xJ# zNKwC0)zcSV8>zg}@)92urW>J0z1BpG2GKqNV{Td5Os$rU3UU&w>qnj$_64BjQQYuBuPT|R~jF`CH^z-D1E!80|jUVpf zyQTUS5xMeCn73}}49=QqKoM;FUV!Rl9c_(^y4JkXsaxGx9U~LdI&?>-Togk+kUc&l zr|SFC;|wSxSF5hVgV%%=Qw)*@Xp5Y88SBKc-UDbb*!Ix!V@@E>G znfS}9Q&6=L2*`BZhMfG|6XE4~M+k((TmBH=K+&_N#iwiQs$sIB$51+C`71x$QVD+7 zm0%8#`c=3 zL4t+PvwcC=SNB0=YhH)->RG3xB1sk#l@FJrRj*)Mlc!+S}(h zU=s-D80ZT(2zR{Oqq>JXq*x97#C&sT-{-FHuOj=L)j%o38$wku1tlZZoevf zbvC+tbELV7-QN{)v)nS%@V%Tt;&CZnj$bLK$dP_Ig-?#;@R=`V9hd&iVH5dsYAB^Qkk`flFQC1cWHA+P!9g}gIt3$fxJ5<}eI$UVtp z&GDdq_vqy&LhH=5=v*#}@A>=(!D_b2Z?aRH8H1~D3cm0i^A}^kjedNP@E|8Yq?b8l z?E{>IH)fo1u1J#>znq(&Tt^)!yngDVbcK@E1OQhF&vIwvq*+0YGEb)Z-%gJB3h^jU!aIR*B&X2ke{r4D1 z2j@BWWJmGknT@GI;17j-|NRi!WPAuCSf>U&&VT00qJ3gsaad079x5eZ(EYpq(&am) zl5%w$-x`E)Z|Eg0Mzx8I_7rgTR{7a_6~Y;|B*O{`i};I4GB=*sD*iLc`ILpGE8EAV zc!Jg^G#;D;qQE%r_a)etzc-3xtPu2MO|QI5*Tz+er_(vu<$<%r52z;v`5hEl#gzdS z7|D&T-0BJ3Ei%)UcCYOntET8*wmy z&*%Go*AF|clyY0nzC+Z-{^gVa+gR`=aA_tcYVVbZI-3C`_<28*8TcyoUgoh`EaGMf z!344xuD6pLkyh-X$Rfo2x!(Vr#+|5F5!0@&9k&SAvHDHa^?ZXAL~=g$Dj>2STGQ(J z0CbBKi@pQhO~-f~qwFx8JrzNuT0E+|QTpIk<(Aj9_o{GaFZR3B6Cj*;GxwXwUfTI1 zd@I+?8plZuy-50-iLsbTjF`&iXC@85&Du-VhL)zRUM|@dgJ>ZMDl#*OKMp(D7?yJ+ ziF(vQA>`=gU?K!94R{u4uNTbj%+9>maX%stMu;?I+I(X)JwDpS_AQoa7Xxz3OH$#k z?@NafV*an@AC+Dm&TOuwbMXLGCq(w_1Gj@V{K?ZhB{x*G>_mdA zqGW5QBz$q`2w(rezcSc2t$@fYkRG>mQG$aHh!!%9pY8tgtmD(hnjMu|Y!gbJp_F{Z z#t~3!kY!yLD0V~Nl-VT3*3$e#JyI!B;eJhUq7z&#T)@4)Dn`G#@C?5!FnJ0cze|ey zfQn8(NlK`p3{!}qhi01Z0hq8y^(AW3(Gr zPvi^SAf)KZ@&F?4%ZF%Xz6GY$c>JT%$*6k^T0Q?h1W4KhdY5{X!jiAY$xa!wkK{X0 ztXBh)8T8u>(Z>JG9IAl>NCE<}+!R-*i7o#}H)VqbplU7YP^1u3uD zTC)IBwOZ-7O#?AP6X3(j7{t(xG&hw6F_^v>@FnB1(5JAV_z2cf-=`?z7+D z`#gWddv?#+J@>hqj1Yb#C!07gJrK~~Q<>!{7IQmFqOgKzZ-V#ak9nlcrDUkhVp>ZjzLQ_39X zw-_S$O5OS>D-vUSl;%c2{*8&?Lnbbo%|}MJA&i(#wX~{U-ZU<((D*MT3q}V@Wku7` z{&&~gfv0T`E2e)u5Wfb764Tjgst;xYPup(}V8=JsITGo~$?vWnvLy`h9jkC0N{Uj9 z97O$f3c*};Q#ymB$r-@^o_+f@g`uU2dgh@}#0oL`?-}zeA<&c#>KUDO32q*0S;=;U ziaLN=rpon3&jIb%|40?+kjwo4meer(1jW1_tCMDZ*NqiN-BdO9f5*XAw)t`!f6#P$ z;`-xfxDio2N;ZQbDmVtCf46xSeg@xKU1dCRFjV_bEMX+lN0eyWcbFk>>3p2O1vopX z{IVwffs*0%8wuX*=(So<<^vgI0bm0pd|s{Pf5{+rn5X)0Wg9tJK0a?S`o@jTvHmIx zI`PIKtiu`IRa+ga?kN4gE$NC#HXhd7*$4Co@xnr+JJR-#!nM(SI2=o?pZ&+@baZUY zothTO$<5s1=(35%W3MVM!VjnsMCmB`KYa@6P{T+!MysD`b$NJKRf+h#oRh~*BbKnz z3XgOsF)@gqCPtstF-sH1$0UVz1q9oaCaZ{MUCnwVAILsWBsQ6LWc_7L`5&|VWKj=( zdFJponFppO_9H&VXea((>3J!BZ&4OOK_Y#!I1*%G(pPvxm0X{t*p*+;ev;^4`(8#9 z-+}d4QSE=swDZ0(nxw#hduZp8gg!kSLCY&DM!UNN?5Xt^YWy{shLuNPVZ~FEabQx~VUl_ipn0e1J~gtH_CDgy2%eZ-E&OTD){jfKEO9PkstHdg&t=&|I|z@+P$2j zYvAK~?wT<|UQn>zSWRnEhO1->!%g7@#{FM+sNmk|V4KWkyu%4HJ(%DkJ@03*5oZbR znw_%t(v4nKjZ~NH6GW5JR}3_ zTPcc8TG*FUl2mBrgE{8j=rhaIzQ6r4_sGt+Y=rWYp2a)lds0$WE?OKi&OxgJ!U6m9TY18Br#u zZ%7MBBdr}J)U<-gv_`SMC7{@)wh9_MjiTAM!FQy5NQ`evh>rZ(xs-zp0p3Wlm`-+R z$D>YOKZFB+At#wUF2lRQvvVv{v-BuW5w^T%?-(Kh=Vkq6zlMWSDYk(VT?OSm{wn@f zpB(8}#gSw${oMqp~TGSwPiFVdpzfflTG)NAw?bLe=cD$-a~$J!`xmog?32BjXY{Jm%^*n zTn$xwfjvukddH(l3YwuvN=&h_Z{v02MPYYXirhD3RvuLFM4trnH*A0P%xK$U&~VUQ zKkmHweBR?fi`3fO7vf@a%a0-^(uq z#1PkFAj6D5-HTUq6vH&b%}$RfIgoU64SiEbP|9se&xn6^%JfjH6c*Id#3ag^!l;xX zJGng-ho$BRH%XFG+Ub^k0StYYR`s5B>_YbxB%c^Kp_pa*q0$S^&%xoqyiZmLzE;KS z2BRgf=m&(*-tQOqt(+VFUt&m|^i64e7?t~-Z8w}G)*M{P^7&bO;mbjcCi0NBykP%V zmGL^{9YHGG-%>+^ppu5O)+A|PC6Im#SbJm&$yFaN<+WLC|zajJP}A)PVD^@xLHA?#}R&@==?(iJ;5@ zPTJL3?DqLXK3Hjq7<=2KadnmVJ8=`9j$D;8Bo&u39?Rp;6kR0`iXXFR`~gq*rKx~F zzON~CUa*;tlYjU@J*86{=65NJqao`2t3^WI2xoXC7VF}!<8Zd+_tbh`U}^?%t%vqk z>YXU!MIPAPEf*tDvxkh`yjBI5sExKR9O-~N@7{e}z< zd_F`;3p0HelCePCANDFWxP+K7)Q$C54A$=e1V=c*f!i2DSse&qVaW(r3Rv39joW`G z1I1p#Uk_s38$Ed#4J8{;boGdiN{}UiZ5|B?l6<6;dV)iMJxy0Bj5^Sg^}ou|7`|Mx zF@}wc(U6DryxdhM!>YrP5RouOaXmv)^4mf&UUb4QnwY4qx=_A*`9wN{%Ik4Z7P^{K zddPqFgAmvKT3)b;_CnCBl$734FiyDO1!b8MDNxHiV@Uv{7)&WFXL_^`k^|IkQW_$F z6I(yG=IaeB=A4yi@_^{%9;Frn zVoR)uRWhfK6UO97%E7)Ru*oDjA|%{;e;yv{Kr}~-at!XSQYaZ5{jXG$h#AhkBrRSE zS`fs$@$rS7%&W{8$vM;>E|LrT5)-JeORn>4dQ-On5#_J$5-JJG2{DOZ&{?uHMX@3F z3Eg{_v4sCJw3A$fKN0|9+EY;lE)-t0vEF*OG)+?3LCzA01v}XE_-)wvZO^#~5rQZt zmsUj$M`cWggaKpq7@f$#=N-!~p%C_vJStQh;G_`|-H-myTWU6gd@1bO#(i5C16vpU zelG?XH%#I~mbDXLY>9|Z&64S`;>k`cew766gqRKAK2hSJfDG(Y5t(iSwkWY!rH1i6 zg>jvlrWvPl!A!^D9fv>DgnPS;%7~95_e*YPVV!5`<8~b1jz_-O*?d6B-r|{Va2~E~ z8w;;3Dzi{w0=1dU6_fRXSH?~|?`3EjryL}g52ePBCFc*N##{nMdPI~@)LCf@$J@?* z1H_Isi^UWBS@=?IJx!ecF%sj2LSpzzocQV&9Lip29+u5SzCW~T2`rd)Xf|X5`MOI4 z+325F<{*HN%eNTAHjix zxWPClK81Ux%O?-1sVmUd$CUSjRYH53#k8B}ZR2|@cC~!zPMWNpt~xmXbhC-^FxV$B zewRPtt6y=-acY=cE%6Q*ric1lOCaV>PI`U3r3I*C@PbH((!B}v?7m=Q_M%uaUXDdR zBdSz&OxH$fL`ec-<~(Ps)Ct{1= zzLvam=^CbbKc-*lB!%X5RfLo1b%DpfKpqzz1xG%KQ8h1LE}zVMx5$>65+`n@kMAXl zw}4w~E;oFgZlvwVNO+lW3W6mY&sUwzJv(wxNb=Pn^LDD5vHpt3ium$`^p)h3ykq)44G+lR&lC?7u&8}} z-m;zZV9|DP^+EFqxNE7f`sOP?M7Yj~!O#>wb};al@&t9@dkZ&bpPPk~lao)s-wolP zESe6tT{Jzh=~wKhn-$_2u|z0dbJKJreyy{)9By053}}1sZ%diJtN5k_on5`lK0cmh zODsr);MwIxl|XoCZPcn&he0){jC{L@?miX&VQa&eX%8DuM^#=L-A>?|esBH|d}T;3RtUBG4lNR0v~UL^nV12nM8)nioqT43 z`N;Zh^W_@mA-RsPZ_3JoRu2{;ZO|K@dInkg+|*@fbHEXLOQrUs)DbyDtU-1H)mTXZ zWD2h>XL27f^rA-K<~(=0f?fh(Ywhnbn?^szg#=D0o?h}PJw>%g@!9rIzB|qh= z1yu6FqbIrf&u;U5<+MUjs;rC2LKta(0$1G3U0k5IJ)2Bl^9)^wt}Z+-AGf>XzYM;8 zGSTtb<&l^vCIkI9Dtp8mZ;_zW{>19Ygb5R~rq2@gBkE685<6OFuW%u2( z$V$ZK%iX^s?aeipN>FJ9o;NkdHR7AW2$J__Cf8D{tB!Ge^mMlyK1gTlpA9>NEQO5` zKd2OmIk_aOTU!_G1gVYV3Ur5UQma}fZ>61F;kmRoEoZO7xbTd^&sU2J%7!G zu=P->2}PpZ|CPZDdZf-6*!<5GbMFik>|92rXsqmk!ZkMKuDk5@vw@S7;ZA_=9PY7a z9*Kc6UCvb8E_<2D7Ah=A23}w7P|oS6XJ%$Wy2a#t^<;|08N+q#G@ginMY#FGoUgq^ z`4_A%RQcw#UU$PNZm;Vp^A1&!g3{^Xm$tyAA16Tfj(|4xV&ClMlujCPJUB?OW=6Lf zwfP}|VB@wf2Eks}@x**)Y z?M-T`K27XvOB4&_u~@+4_{a#4tJ7x}UQRW1#piO~$&3tOl=V3h{X!LoI8UhVcOR}4 z$E10Wbi2+|-*q|iL7=U*uuV42_QF5Q1wlR{j|)3HwD9&%ckb(D+85;TD92|(kl|y(4z9I*gTXL6{xoV*R2I1E1 zE3Zvt44sV844u|n)b0rhd%3$Ki4yA-&tpw(WIC;=-D5#YI8*|NY6V+w$)$PZ(BbO4@%P#1f5(T^AJr-7Rr9s`us{J zq)vd=!U^_c2jYM#Ki>qXaINENE-pRdS0@ zxO zH8uzDUU+=jFa?jDBL5gSRHzkW+A;dR`mbzE$N;i7(FEautaPfQh6hP+tWHyc4d}lG59{k1}zk8PiH(Y z8~|EnkrG6_Lcn3{zlU%1e+7BpCYUcSJ%+W=w(JFxiKb~(0+Jt9%wKoOFKl^0-Z$(( zcuR00DUveC&#BVt6u1u*9*@ir;)-&_O|eGKn_LdRz<`Il*jR+`(V{NAeAtZ!=%lmS zRaV!o;_)iVcR9FWdCSVKj;_!p{RD^Tp4KgHmh9}*>d)12?>EV>8v*)1Cv%&;9&S)t zq;*BCZK-3bxB*)6&T~_AylkkQ%8aO%aumQQ9`=)=7L}a zdkk432%k8HRP3N67W1Zno1$TL7unY1i*TLPD<}Q83ri&yOclD-^v7OJWhiwJrB)S+S{0)%Qac8W#A>P0bIuP*uFy! z-*w0#tQcAQzNTpKcaF(Ylt6P;F9BP-v;98XXigL3M=9K09%mOR@J;z=cVliCRac;9 z$WTItTNRHh751DJNf!oeHRKfDKweFn0d&xwxm&cU@}w8`%mvKOASM*gH-N++h$^6TCy9BdR%pFcopS7*UXrxt7#!W8 zXRJ8+ApH{1fcHz6U`F82)F_C%trJAIwr+Onnk7>8>bab;`=j(~(#nGLPGUCaux{kWPUo4c z7k{&#{v7qt1wH(Jt&OWKM*^b-?_REe6M+sYn6Qd^W&s@p*2aE6ve~=Z)XLerr|IK^ z+>gx^?%qTbWq$oP0pdFJSA?;zbO%szKm!c)U_SSQAL1~1A*UvWcl!dxvthOk0_mR- zGi8}AEw8)7<-p%xfVkEhuO@T3n1X1u40P`mWlkcXKZl~P-_nKvBx0M-iSuadA|?Q$ zHNf@28+zCssrxa~PW&5kzHAX%({{{2S452SU$v}-ik>9**cr!E_ly5Hv|*zfxrmiI z&W%w~@cK#{D&BP~7pzOk91K3>uWnxic;m5;v9V!TQC_IP^?CMVY3!+<-gdl25E|TK z3KLRmY3wPMqhpl?D((gd%v~WS}RHkU7rd!1RY!-)1ObcN|~`i_}r$WhQ(pz&6(MSGJMcu!;n`kvgmvI_CmLmgute=%K2j`?v~o zWb17Q#1p8AIo(V$@4|5SL}&L$yK|P2HVhp(YJC&Z=`c3Av#+!XmIRwgEr~~N zj;^-D|6SKd27XJ6OOY`HkE9LV8b#>s+$mO)tgdRTiOQbnb$DMU=XmT26`g$Dd_J)% zOyIFfNVRbq0Q(Ps$~SvkHYBxkpAiH-E_ltV7uclWVGm0YpFI^Z!mkp|@c3j4yvv8$ zzo&zna+4Vl`Y(L0o`nmia!ay2JBJF;p;pz2hX!}Uk8DM+hTNLJ%YGAh#vks+LcPmv z3C_GGMoZe~6`LO!_Pp*K5N%8WJF~(H?Vq{Wn8hl+%vbQ&e4-n2CCr*=>*K>yYt);m z4xnmd_|^0@Pt4cZV% zY!-&wi$+1oZs3KFHROy9qap zCiJ~+V74RS?;)Q+tRoRlO5t08sW`+r(USMCpVOl40HhbKIR-wJE+FlFq2N!~t9)TQ zTLEpZv)-^QH?Nos#qW-cYL4AM+Eo|%ZHnH}_tCb$7W|CTBPsh$FT>3Z27I~5yXI?- zUDT_K{g*FxACu2-lgIbIyEM=%68>us^t)3po5>}@N?f{8Xc7gM3RQ%+d70l7?zw-8 z8D~l@Y{Vi7Qdt*hgxyi#FtEtnW{RykAzXJy+u9b}gtE;tH5yQoc3pj@QB1u9@Ka#X zBlN_l9O3F}3Y{j%ZQHpP#)Kp}#hgaxx1`xJJZN1-pT5v6Ys)7Y$%6kH(5#i(>>KDY za+VFdw^(kGg*Z-k!q3iB3eVRqdq?VwiZh2Vhj;Xq3K?3w;j#TJ!V#J)GztbIZoJW+K zVKH09zv>SNkl_)^3al1V`ii((uI2Jf-Xgw8+EVJ*?&*yXJfjWG84(Q9oNTtm((k@j zQmhtoB$aiHiU%a?sXYuycs1}=i$iCYNohnCryc3wIYc~!KnygTp7z+e#{(X9l6 zyMQe=(3@yLjtF`5dV2^+|IW2`gsuNRXuazW%aSLq7cLU?!Sk{Q72xwS(cv|c%?r*IA3Ps70RrQ(AZb^(RovZpVI|y#-}TO`x(RRGW8A@PdK);WM~uklV;@S z&GU){;E7YpbpPDGyrPjHFuZe9TGqyw-U^X=jxl90+yx37vS|<%^Y|hs^DdjNUi}+r znnH^$t5_%tUPaD^81E;y_onX6ZT0uE6y#rz!+ZE87=|!`bXQQw_*@@PeMr-@#ItzlIuTDr>$Z|IxbSg6u2N-RIa6 z=@?yUzpM~`?I9=3tIOFpX*4dPNsq6xjWY~*bV|~}-+60}nO~Rn&uQjJ!EZF^G;1<9 z&wI;F<|&E&p6+QPm*O11Hyrv7y=^*bl=m7i7=Z>%a)ew#E%OG!xF^2 zMw87-2+0MhcJps|pf6eE<$nTMX&sGavLhyj{0h)Z6~=i?M3AKCa!A_HPPTGW+QIk+0b2_6~;tgR7EL7;fW6@-DuuLK)Ca&l{*><5>a~(GglABQEWfTq25vDZX z^-VUNzI)rkLl;?Ov&wsfti_N*QK|x7pruia`Ka4_s5tYs7}ObYbOv! zP10_T9c4q+pikx1{u0aV)0{BNvTCBaj|CB9;!zU*RM~Sk;-a)nr+A73)NAvd7N)I& z8yTUWIgb6xqTUeP+(^z zxxY-oxEPndk+r@dc8b*?j!$JA!S?Ak*WFS4;^DIS5(k#^yf_HU@??y5VCrc4{8obw zTDKTWZ5&+yt*^dd6Boa+*#s=XrdW+71+RZ>(a_O|ZeeKMa^`C-PQM-ZmXR(ZxMf62 z&AA{KilS{%vE{7@vgUBM0`|a)7S;6n{0}#~!u{3$Z^-GB{N{RK#r(@Ed0d>-Q9C4whatZyGK3StX@NQS0mUR+QJ4%{ubd(os zA70^XK}=?|n3!|z+ov!i4r>SQ~9EJwtRVR zStz)I?!IMpDA9Pf#?EQZH{-?2;BuWa>~EYin}u0m6&Vu3y!R!RWehI7D$$;hfT}tB z(+Mggf-@dcPl)m4{@~`hcuGn}442|~xc+-70qUi+2|C6%|DJIpwHaxu?#Vw{^+Vsh zB>9wv+u>!BoeF;}jDHbOD?7H{h4ASGON+a~_86JWt#(6I$6W&+ER{7!Dd)foeAgAW z&5j1qrUR=<92CJz-?YU%zfTQEh&G%UxYN$kXEjxX%?&Qfbbe>|hK*NE3VL^84u3TM ziIx4d$^Vy$`D>Ey<>}KG{j*>H`fzg9J$2-}4o*%UHL8f_MI`+Fh{(SDSONVm|1vxm zP{|d3m;E^}SEgwXX;6I0LB(AvNCWW3Y{r?kH7n;!Q`6-8fHu?)K{7I6+(8lssEouw zGbzrJp&JVx{l{c3S{Rj)jlV*b+>-z+-4>mr9*T(W#KkC z2+DbJerCB<&Gh2O_rF}>i9nyFAuOg!bJ);{u{8UQcs4lTyvx531cZtp_Gn#Uy_V!V zCJ=-D?7Y&on$Bw|VH^|eCut%tC;gKDP+7gsD2yP<*XPo=W1wJD3fnhkz+hy01^ zm3qT))Pt=Q+&8^8Rh`RXPD8Xhf9O^4Yj_TIW%2p5&ukrQ7W|4Jx`mkOHA3Er&RoCe zFI#v#fEM?uuSBckCmsy!`RD3SD)-OaOZpf6xh72$Zz}u%jHK?-OOFQNBTg%{X3Pi8 z;~7q$X#^1wM*71a$BFL^aRK9@8f@&Et5SPb-yKsR(Q2Xdmg1fNf>cL8foghO5+tN) zis;5-|KsBEeB`7pgl?_6UpfRcuA*t2nFL2{2xCp`OOC+HErpl`XLe z-*XwopJo-?4qUTRXE_?Bqiv(b9re_kfVlES-T2;lQ4yu3sy0ktKLt4kk4ckI`b}67 zTSHMN_slTh^f8w1y{Hq$nka5m&I`^C#s<=}g}&}4n@c2_W7H%GsIyw(R z1zn>Txz>(?O@Qc?r^`oAyY z+)<%98O6XS!Y(yo{_#?W0h?IowW-+EyOD?>bZOY43L1v;k7KCY!6#g8F@@(Zcl5Y(VrBY7{X>lk)zx_Yi02SYb4@ZFI`uC+l{ld27!g zB{|kW?$6;#8G2Uyjo~loA|2XMqlCYIJa5zA_y1G#ity9%-{j^Ul;JDXq_13@trQjM zvspe$u0IYA1lA>xO*obF*}LIvosmESUsHo^g|)yhXICWD+x{1sHtsIf{{d?|7H1{2 z!dA?8(C6&L&jP^OE+y6^*5X86^w>Z14E^u(L~p52h7~O+U;XmSre#$B)81Eb1mM0P zAxGPEvuv~9yjWTuvzp>R(90Y393>n~xVfXq#rUyGj+k(}P0`rZtLX>Yo&D}6(NCkF z!(=}Zu)8ZK#HL}hj{;o;M8D|1#&yw-9f{+15dej3cfzyqo1AZ{#$~ImpPQ(vsCqX8 zHqVP)m!mdCxT4N}dii3~dxD-6`OBl{D7E5Z0sfBHX1s?1n)@z;(n{HC{er6RQtgMe z^r`*E4OfbxEJL%QM7b+qGtjS6T53_3bdQwW6;4l9&-_J)%0h32~^=Vy3{O0x>vze_sm;Z zwQaAWeoqD*r{uC=uUy6lpp!6V6YNcbtDtdNfmnSXh>b8$M>}L>SBQ@aCvYP*qZ1k(AIrWJ)ttp-v8F>6lHA8mpQ#? zb+2bRa2LIKZn=CCe~DkV6OfV;aG-}y|di0OnR+xab^Ex{d{we}yrz=v5 zQ8axXJXVZQ9{>+>G!*S7kF7yITV2Ecv*<5T*AZWuow`LbHl5Ap@2Ojq zmb%jfOaH=jh)g=jcLBA3Xx(q!-ezlXZ_3G`XBG1f*5Lp|w`sBowTk?Da{K)_xLWt! zACB}{%~bU>BMXPSt@q0uT`?WMxSf;w(0DkQ~e5dU^4sbDq;>zMVo@!aW8 zEwenEneNt~8jN{!G8V0s85N z8{R?D1T$JbmeJ~4dG&;&ZT>hVor6BIg-5&g&D|zxJ!wvR8&T=gBtr}(GpNyivPN6R z(;xnPY#k~o+9?*VzLs9qjJQ#CXge(Uatl}YS)U4B4-r)B{PvH0xR><8jjda*&DQVT z+>HIV?M(};Kx<*UA7#^0Oc-*Tc|HHwVclD6OnIp>6BW=|pfRp5`n~q0zm!2IVZ@o5 z-;@OdBFlD<2Sw42s9v5^OmA+ZJ90itH>*>}<-#_s7S_%hk~!CEGnEx;L?cZl9)yv^|s&>@QKj-|a(Vx}5P z^~FZ_tU=p)O@^r6qj)3WggHj%otJN(OUb@eER$=k$F$_zPv|Et*dlYR`W~3}BHXA+ z3dM3lA1BFcRWTr9mJ(14lRvHQ^-ra8WtZ$;iz50?9ucn$(UkZ4cTOofr+(|WIo^_z zLT!n{W76GR9|PyL?T3m+Mkn9!>YN9&2c(D|YZbLG#lO23pxiGKF3#D2`Y>B;Q7eZD+lTMptLmNgkNh~JP( z6H>{mxo;5-gPK!uyuxHi>cY!Y{VbgNnWunmh~>iT3LbL z%}^Q!1`ihdPCPFmA?M+SxNt>bQO+!U_S zf)+9aA-x@5!4FB4@^m7iz8Dq^a#Xh)%s*b19eg5X=dC1!@bktX7X}8TMZNgz9xsg> zsz+PD1Zow{z42Ea#$~K<3R=+V_Jy~Eq(`i&IEKjdPd(294>_+=UX6y})sl^c4WfXJ*9 z;v(#F8C4pmHZ_`BCi9Vm9 zzV5Sw{~;B6d-6oH%rW}uZabH&WB9mb?|*%Qs>9ib#7Oea<%XcIpTpZO z7K1S|CP&(FZ@T_7{1_8#tg;k2u=0~I%3$kN>bLKKapB=fs*~1l4>)`3UN<54ZHFU5xcegQB zi;ev|X&H}roDPW;wOjiSx8>GtFaYhO@3~to4>HG20eRomW7Z9<4Q6H@w2w;MtcLCP zoRE6Jqw=NYJ~Qu~P8dgn@a_d@*HaHUFfLfNFHiDHji)34Eu*x2c9M&YbigqY_Xqzp zWRFh_(~7yPt9j*8B#&f9944^5OTKrSNGSGNo4-4^7w?zgUI^IhdT6o56hI9N=C-tF z{Nw$#XhIK@p{^R3RzvLSe>_3CA~PjAG3amYe#YFu+Yw!*Br>=Fpf>qAP|$yNV#0&M zi`lz*{89e!8{-o86xIg|lbZY2=t+nJY;Q6*3!DzXFfH>z^F8*bDM>7XwZ)Va#CeHs z$u^tI(i}~kGj!#j`|N=8zNl>bi!X)J--ZmB7@he5$;)jcf{sSbRth6PvYjL8gC+w- z7_;*~n4=ZtX0d_xVf`~SC9kP^qCsPh(DF2kXy;5OFv((f= zYef-(-VL~_v7Q>5*#M{^!_hdU)ikwQA|o*2Id$5=)2GiX*rH!z#{q92r>lF;B`d|Y zo|Y<&Bi+xt94J5?s>a6V)6y3%y|6&FwOMRV*4@V=aj9{Kvabk&)DUY3JvjKPAPNf} z^%|BJpGNoVx#e_2$8+8tbSQB8>3OG-4 z&wscN_P6Xdk$+Trs3|7|);e3B^x9?&!%Xuvul{=bRVgzok42< zQ6n$Ue3&J|%i=P2tYa=Fx`WY2#`oBsbWac{0PkUt`rCgnU85A6)k=NIG z%NX&Jng(j}c zg9~NDHoHb&jGO<&>{3Cu=%9(U^Gh!)tu%}CS}2{g&L(nfV2U!R!6nF>Mg!6`fq0uEFJzw^czs=w$g?D3dvQk>7u6l}85^v=v5ygKw^ikboh z_AxkI(~1P+zk@6#wIj}*csE+$RsjO@t-TEmpsg{(v3?ON#t=0fdfmJTHxYTiM63y{ z#=e44<(Cn*`{BR%rPk)RD@0^SLVp$AhVkuUmriL|+8WB$AM?=4%N*$H^{~B)+}!82 zz+O@&=;Fj)qJMJyoY>ex_3zqbOAE@Kf{Ys$EsoeUvhOP@Ox!o5?(Gbo3f>4{xJdev zM{{CBfKOw~jyJirwb4@5&G!lw_yF#1Zi^>2C+AG{jPMdJt!b!iLWh5ERtGEk7*!Bo zJ4ar4>5vk*zI90=fK|*(%*cGSD?CkLi&v%F!ox&JWz60DN!9i`21_rnwnrY)(n@=sm?T#Da9v4NR$pMl zgW934Pe5C;pI;UYJgZgi02!dirwz)G0`mUVNtL8j5W;Q5LA-t&l_J!4{m}@89G97y z6;}_`5wX7{+pyxP;1$i4hkzL0XG=mI4>n zE9>QMsTsAe7L%DF#{2Zw=#kLSMa-()IN*;{OIVv6_FM{|$}cc@gNA zuDx*5dH1mP7&wWTSv!~>k3E!#d{^@5B(6{MuFv}WW25*RaIojQjJocg-E}{klzF%E z1COUnarp|&RuQQ2j7m>qNmQdfDa&_AM$d{U$Muy8Q9oF*i4P^{rPl12@aSyqa z{4IE|yx!N+^rpn?!#~&DdG3y!u=F2`ASV9(lRTfnMs@ai@gvyIj2GXM_;gC51JR?|^=-A{J`{tpy!jA8pjr|tv*}8rCP|aiWqS12y zk`u}V0o+3>FR^UhVt*>0s$YD|`?etJuLm@=Xzze7y%%W*Hr|xKYSZ48GMouab8ZFom@Tw#{ zh-Y(Ko}OF& z{`Vp`R}^m0@Ni(|;luBTSdnxh**AaB=VoFpe=-d^ZUX6NR!`M;7m>WoQ_yBid44ny zN?Z=zq(7c4E>My$D2zl5DS+b%Ln5}<&_iNs%zlAi?9sL*ZH^9^PuVeuueA6^3T2*a z=q35RINK^ur8mmZU;;YWi^+ z7V|wDs}gptwb-0AVnDP{sX|S_lS-iJb+**Rz96;uq659FAVR?ZwShA^-0Kyb})QeUe6m_63qv^ihWFQUHI z(){AjUB#2Pb*?P4pp zVp+aHlsBqjGeUy64)N$L*Q{u-SWjG76lrINP1K8+GYquzFxI|n?B?c(CO+Fb4LZJp zrD%E0g;{%BZTo$khv0aRPb*p%tJBbanxihl=fIaluOwa4)4|cmdt6#Vg59r&GL5-_ zThtKn_OLqI61_cxa{P5?9O1(%S4OZe-u)hEdG9uIBvG^Wq$N&>Hr>-I4?49rZsh{A zbqL5Xynjrcif+K=8-Ir5f%jOY#4P5{FXkR~deY&`LK)oi6Vy|mCYIwXR#>t3TtMBG z9mKyo!;T4HEtPaqEt;&(@?<-5aR@4f%Hl(}-v{EqR{U6$-zpi)Q)fhF#D(QnKL40~ zEM>3~;{IfEz;Hw2gW&+R8*Vlh7b%M?E;786Bcts+}j(fiH!tlRX<0axQ zr3R3^MF*U$i>|KOXl|r2o;$rT6K1J@vBLj@{f#(H zy%C2P%urU+Mb2t`fsFe~k0tsjkx=;L_leU$l~?M8^wOf52sQ*Y*cD{kVCf_$zF1O5 zo>DVU@w-~9x={cSO+tI8^?rIo`v1)W%$Tao-4@CVG$N%vPmYS-;{#>~H|9$V39~;Y z4;xx<$2jl&AiS~l9(fkrs+HT@CzF~&+-4AVGW1SrKtb)u*@!qvIQs;gWUVU@gYdAj z_9A(wtBVOYEIy|IjS?JXyThwf3hS=y;25jz*pnrDqSx?kC&oj;wZJiAAzfV6{$ri* zW5C#q!8iZ;n=4wP#`}hlyyO7t2z!5s zRLqUmHkAiwtJpZB*OGT>IT+T?sX84(I5Bxn2mm_lf4OA?N>`FL-Y;5u= zmfZT=@F4UXzP&;hf$;dh-7~XBr@s7RK?K^-FnG^b>KZc(+u~zCU~Q#9$5}5K>r*V9 zIfdf$wt$U1V;&;+>?b?8O4gE3-f8FXoZ53q)AM>&8ow5V`nd|Ut={u+akV*?*a}8y z1lUmA)jUCuNH!HT)Iu9m8s3Mu4%Dj#0ZUKAGSW&?|m9FweBkkBLM443J}6{>iQUi`G=X_Vq(J%#cetzxX=cR z@++O{GF$`SZ2lhrzCc00^f@Z#gLufm{RpLHhp~Z}QYbP&`z88~G|EN}i`;+WU@0X< zo8O-r#Jr&7X{?nC6TahUIWNc1d3NBrm8`J40ceCfi|JxHMi(bN^HfV}K*yK$S zT&0U63rYY|LJpok>$AzD7FRp(Us`%vy!hccJ^JswNURq#gkHB)#iFPI*ezwyeADI5 zrbMn%+_BLw^Z-2>PYV4+!@`RnLBrTO@X(lpsI zY4cn6Hm95ez*D{Mdwazu0m>$CiZD9_EwU^w0aQ5dr4OV_`43N?Of_HI-rku`$wu<8 zx;zigd65UcN=SGAg#~L|xY+)tZ^|5AP`Iov23d!RO9aClDA?C7An8P>CQRU;;rN3B zM^R7UzU*!!T2Kg0{qQ6~e};fD#v;~u;KAtB8Hw*%2O?A}-E4%L6iUPa+34bEk4%79 zBS%*4yBtQ) z%|^MOta;{i=N)fXUJo821Z-L2r{xkurAw=nh!n3P8?T!VTb{y`-IoD<$*+r8DB>-k6h^*zpYgyfeH(PL&>J1YceM_tL zZOhAP`YT&o;68nGE;+}_nCHr*K>_lg8<4oxdHkKM)5iO$rI}J1V2&mS2)ndI25mm{ z7l+4$ei<=QF1EfW5O(cY8bS!CzTfxxd|Z)^bk*(qeK$ zb}4~2{!*$liz5q10NRlGr&oE|5>;|r_|fCX(;<6pclX|SJmVFmU7YTF<3g`|vZ9Dp zv>v#>apHuqlQ^Ud03=wW1ZqgMo)szj%|U;Or`XMx=qmkpeRIUaz<59PB3xZF5dW#7yB*?M*vX8(K52kkuBQ7iDu)wS65Q~m(usX*%&=@ zEY(+~#3Dh8ah*=1m7f~Tm3W(HXuJXa9FCMwFhvN7SKi|+?mxG#E; zE3$QpNQB?cSmWY-(C#RR*TX>?2Z;SO!#=nWQJN}(0K_L|32N^>hd#>&_yn%BS*6se zYotTAOQuU0do;hdy`3h$cWw1}Ba%h?f)#<;1(8K004cr^v}SZAO6fy_V9#jbht}7- zQ3L?DN243Vp>0N|i{DLQH{~?*HZE`*T8}=$T1{ag5l9S$#BO9DT2ZdI3S%(6NFrSz z`UCQ*WpyT@Q9wKSsw3;iB0yvy+K~gn1lBhijr-ng`2JvX03Z+-^dWn!YoraRJ(Z)0 zMu3P5spEuLz>CPlp?9ZCtU{GbS6q?YUv+{K7i_Be@^JXlcnko&DEhC~k2$Y>cNB=} zr9=y}lrFF=76Its6*{J~XPG05l^w=@a6S9x`(NCafe zz2?P>Cal|OCjWqP|0Q5y3w2Fet}$rXm(@Vjk|Cmo{sJSJh}xS&z??t4^MX16Z-R+^ zWGp&!F6wl}A_2t#z|iKv5%y67Ym|yj=O8}Fj$?9lAKd(Npx}LI)uscX9MBn_DTCL6 z>8y6z!XIpHrP;rIEc4PzU+L9n7dQ&ESOj28^@qga-~&~PZ9crZa;nh)fc|v)>h3PM z&)RCzrPct=A_f4^ymX00OjCh`W8IV?1JKfz`;W(psn*=+pK%I?{z!*@h1UXwwIyEz z{ZR{&4ALz}VA4R=fryCl#6tJl8a!7wL#^P=XpB3-PsinES{QMR`vYR-CR5 z%EPzrsX|&ZfKLwwx8oQ9PBt1JSXnlV&GX#VATtg~{?-d+7f=?C09;h*V${N=rLqj* zZ?0wT|ChJ6k~uGq(dpoOw?SYv06@f=moF)J0t@%iB_be;a{nc)16C?%L+G!1qXDb2 zITY|g(2wz*2}H*Pe3C4^;9v5wt1h+y^6v&k( z&jcfF)}8H^o1b+-fxg_{)b{E;0M;$P28^}i?5rarH*dzyDSg^7$8pT_bGdS zyZwZC_rr_Z+Xb#4-6rrt%}txzl_|qLWGq@+i+Vlsk|KuK>HafKhv5$}oN0iYkN!+O z86f<9frkQTS!B8X@)v1vGw4RSf)6FWPxcr(NUp8G-fCF=&X{gnkG04c5ks^DO# z%Z}UtUCID{aD6RRzPh_Rh+|w7o-RNedFdbsU;qHo@e>BVP8G2kZ^*=K`fZY_J)}&kP1>{`=Neoq)iIhKzp_{a z;2KJUOZ`k+;lWF@Eyn)F%4(|ls&xO0Uq1zmOI_hw#{{-EP9D>6$M*4=qln3*Op)7@ zjd)u|STFr@QN$#0r_i67qS%hj0GiK^j4+X?ZbXWQqSbX-q=$V3;)8^KrU805;xjP@ z*;cf=n!PA;Vm-|Fg=>|c!xb9ndIFbi%}4wFH1S`qt+%U&a&e%Fl?Kwoe#xQ`fFHzZ zv%SiG=gP{7W&;4WCzEU94YV%f$}hPBxS-7~G6yqSS|+a>4upFkVb8ww~=7tgnqZ|LSP;{MOd%Ns=1S-{VD#cqz4N-{VCeeAimgUkFTV@Kz*# zQfY-M901@-FM^L z?p$n3`x&*wr``ee)A+_csUh}`F}X*owRG^QT1NKYY;641m6b<3ogY|V`~7|&pA<}< zBa9LEGU=r%Ym^3Li<<4DEXoW3f-&7^RyO{_+}ZnDt#|i&cjGwW{8jPVsa#wt2YpGMevPgMGL4X1pOImT7Ah2)Fglw5L|@3c+s-lsN5Z3 z0MKY=-@rk4A2Cgn>9CKlOz2Ih7BqW(A4QR>Av4A(=O1OJrvXC!>yWMZm8Dw<--Q3N z^&5O{Fi1Gxh~xJxEu~*l5 zF&Yig@~>^5JD+7x@*e79=r0wh8bW&w#PXYzRDjVCH>`m>h*?9L#aM4^F!~D{{mB4^ z_uTl2HWU*`8jxk^79-Jp#u-Q4fX0f9;|nxL1E}?x;TF*N7!XgPJ3bKf>8HeTl90+= z%+0M>x`lFm2&om`$h|mzVKTWJ#}U9sR#sf?7`|d9VB)8Tg~EL)3lRb;2l0Vs_)0C& z$VXOJ0N}As=jy$Cm!gQtNQ?fVcJf2;uCK%A7;_#8=a!+UkyZ=Ei0sw?MBIh3-gL@Z zO#yIB#L4An-({RfmV$KKH9as$pRZKDv)PXHwekJ+nO^zJDDE#40%z5cGAAqA0pi*} zX_}+I03u?Lg?~gW132g7_`+&8i}uK{Pa2j8rLS)rXN{zIDG-)=wDZUewH zNnRTajM7}+hwf%x9|~JmrVA6pKnw5q(H}48 zid>|YgykD>@t4*F%YF0;Qb z-u?ON?(Q^6T#f9(1yIJAF#t$*b|{qB73oQB6Nmv^dKGIJQ3=LnOaVFQuMk#%IRgo| zOrkuZ8o>mJ1~7jx*(0@y(MTgFjQAO4Sg@}4$^>q?i>e590FM*{)CZi!6|G@5$3M?t zp%9#ua^}kcA)Yo19$9>i7On;G!Ig{v zUf$X9RQLC4PE6ozR?j4x8=Br;05H%;BA!kUCccA-bUHrjdPD|!=&wUR17M7aulQ;c z0JKmHVup}y1p&9%x?C`3yuX>%uzh^I+h~@6dMHf@h*x8!k__qb;93>+AxEZKx-{;S zGVfY*x?VyW{M2stMA(Of4_6pKteII*tz5GJde}?Ze*%zF3B(7s7Si~mV*WTulGnu( zhPK)4m|kHmrvCv3$=yxD+#~^aM$v!>vcde|3PAOet5J?oaL^&#<2!B+RlyKN;WD)!C0xE1;zO%u z6v);1ULwze$U+c6&)$H{TFZKJb>J@rG71q*#iSzi4tD2<)r_3g) zrU_)k1E-KtZ;Y8r6j5Rb{WFaW-D@8R!{`rKBl;qy0t#rE+?>GcyEilB!oeB&pa8Qg zIv`$gj8q!~tXC|SHOJ3Rmr$0gRj&O^%8`x#tPbwXr*^W3_GKW~zQ#kAb6t9$*}+)` zSO@~hWNr%pC3ybLt=3ywEy#=iC}qGy?SZZqSxW-~e=UR27)-CcLELfXWmne%fK^>@ z#ij>r&2(hMEvqa-e~kOm-%o!L=)@pf$~0CZ>Hj>rebYjG48C|ypzpYDNsKn5vOs3@ z@qgY3USU%+F$5_TC6s9Vnc;AhZ~%C)-AYNOqRapSuBI~jobh$s9mD{>Rh%)eQEz|qG(PW3G`AKx z0+SbCfOzVxL^SFHDQgqVsG+sN1cu6XBsycgwgxLKzd8s-9*$j6L1$rWzyuvoBKM3e-nUX8CA5dHEFzyK`G~l$x06 zX~duhjDWZZqko3%0?EZZK*s+Cf-_uQ0Xn9cOp+T{*kpn+-8jJw78tPXJO1Vf0+9zq{A#MG*jO zOeWjYsmp9}mDD~@UwI|Dd)L{DEO5I<`4^DOWj1|etAyz_gzqn*Jazh&@2`SI*7~jL zr)rY#Z1Y?Z-Z zT%Tg&YxzvGA08F|SpfIHGU0su+?V)d9Ar$7j^QRdTv=u+sAjZ9TcsENz69_L`auMP zn7qG}SsZ{HL+K<=Ui~_7uFe>*5AMy*hX0Of6E&Q*XySKTJR&Cne|g!A0=e2K0NkaQ z0RrG|Z)726097$O= zar$DohuZD)P2%OpbMi8cvohCyzvN)w2AZQUb$jU3y)0IEbu@}+xZQJMCBAuc{FN_* zdMmA4=6$xBhet<1~1G7`~~c61#CW7@P;ad{hC7dP+kzR+=n}z)kXsr#@}CrdBFY? zfRw6yeBs-hvsa*}vWd{GGIb574q$(=^7Ea%f#ULHU5xnz60!VA#AbS}Mh zF1PN$Ob(_QhxBW`${_s|tRe^wgI)g0^Ze>JvSPG%-fmHwE|7JOwtqW*S%9;symCRr z=o^j#9c6#tmi_!FeC~+MYv|qYhj_Bv+f9-e$KyZS*}0M=>2f1OUtq_-NHik9+Yb7- z-OVbT%PO)Kt^)ek-pMU8yisF|a;G=|a0URJGcJ}+835;u0dVm~1@-ND#%|q(yPxWv zKezJGBT=W#V)V85^ly4AW|X=@Oq8Y>oRx3z5iSq|bl(mG*@(EgQzWuSz0^y57^(vL z16hhcIFF~hS6>_5yq0~IU4GIXKz*5A=+p0ti_eGaA9e@z-FETuckyBQ?3?fMtM204 z@tSc)OI+1W+sq8mm*Pd;B>Q5$_yE0PJ^PoSqC^0kXb-^nggRASHlBo4!5dA)D1!cl zce4s(WYPX+2Hv)mUUbr~pFmEfp z%YHU}xWQayKM6oeNhT=00_?DFGWN}#c0Wk~;P!kL065h*QaMv~L*>ls1)LABT^rrH zv-IXSEnU7ZYBvoN4#50G zJW;@2xITffdQIwSdw#wdbK+e3`M^FHa@_u*3N~JDmn&Q_hRRt`FaJ=J4Bx z8|;nj4*_TxQe-uJuG6sx+U;Hx-HPL#I3C0?s~ndrl}g$-82}heCp#~{Gqp&Km@!#UGqFOiifWZ+Zk z+sdiVK}B^^?2H&=GTIZK<#6>ixOt^<>U87$#puMzbTipon`LlDyqs?iNs-I@-qN>%km(q7jQBFfZ-0mdlT;6f+XQ9oeYp=kS9$f98lOt6(z!0hIF#f zhA>ll5zI-btc)7vWkqW&%d%{vJdIgI8OLz|xk!S4iIp&wBAlX>D8P~_88fS+0EI_?1 zA^M=@x%BugA3sZThC@l2WjUEgPYU(9(73s5zcC&^-Rl9sBc1l| zY*!4^zKW#+M0+NSLI6@q0C!alJ|b=ryW?E|;3+Zb2bD8seyOntZR8q+;=W1=MOc<| z#+a2AZS&pT_|;e9*S-<;mZCGK+3^$6`Z3mM7~SG1ev`d@Q)WR0_W^`Hh4_>zB)|M`ct~$Xsy0U?=xW_Kg5axXJ#Cp$)pDLyrmqkTZaa z-T5%uz&5$HvTadbhS?7TtV#D=E6}qXfI%|c<*&a6S6*jP#8%g$_4R0N9hO&Eucv}F z_Wom_XMzj3yil?*2;&KiM#*RwcKfiq4a42cE!RH$l5K*^mK77|;UIzB$m=Kh0Ni{a zaNk1@ssXKHPS!YB_OYX6UqC-sinVWDecYbpr<1_YRzth}4RKLRKhG8C$!+Q|5yt+{ z07?RSb+-Vea;y=ZX*2*}nk4t8)2aeKv%2%;3`AtvlSLJb*?>rJ0H)W(6*=eIn{j_D zx%LJy2F)nyEwiO1*6p!Q8`>S#?yydqGsapiU;xb)0EcM|3?P{T0H01^GJ$vk(+Nz5 zd_08Fh(V&g>Nx{`1+eB06O#bJ3LL>V84d!954eD1QRJZq;8a%r%MCT|ww}+_$>C5T5{~v07*naRAZ4`>17aUYsI<-fU#_HBN|R8J93(%?Q{m*BF#Ynx*ZPE zH4^T#x;h`2DX}rzdADv4G7}E3pBq_DmD*{W5^Q)Cht95rZOYV|2dNaSm1jnmNNvpd z8fXbS*n7`Z+;6g>p34cM7IIE6^r7tqh`wx-Gkp5&njIm-KI;8&KbmD^MyGnc(w2Y#U4E`!3Q-Ut+KurIPO-vlO# zy>DoprDe+CQY(vwZHlkJA28h4IUxH-2O0z79f+?7+!d}1twk7S039PHM+R5}$a9yq zFl47bzPvpjdH0eDIM1d9vNW9;=uKhJ_l1KLPLq6K4V2;H>meNj)T;*hdC=z!~=8I*6;OK<4J7$dCA0@gLEke6|ad zN`5#m1&uz_{_IRMkqczC@#r-+Zhz}IvOYj9J zu)4xNS!trBO&Y*qAK9Ro7H~0FP;^2q253|vQ69Vhb~wo71H4~y0s&~pLE3PApwwvK zF|_F+{U_ukai&n12G0)V zGjc%o4;NXkd8HQO>s16uxe!0IHzxrS=uu1td(m3h2c+*W_&{cr3oqXD!mXctK@5U^ z6-NSu?_grRoa@M)^@oGhJ^~s9Wh_Y(4>cNA*HJL&p@QR{bMiQ7LsORZW6BwjLc%wZ z<#`5{+>pxvEg}kZSOfhY*=GXS$4D7&`J#;fh{r=_$Ni$luFKeUN#h&C<%P<%%R>MQ zhAl7=+(LY-U`)_WMDwnPv7NW&oGO*|4QA0N77pk;+PpbJC0n;0dg&{s3_Gk{)h9(k13o zoC7fN_=C}a)Kq)IRcD>uD1W%~l@Dz!LL$C~>Bb}g0EK-xhb+h=8|5M%IXWctx!-pzSKXA`2rlWb#2)NWBBDJS!M!cTirn zUzRo?z@QMvc-ka2fd*Si`te{m9+?DiG$TTb`#R{ooGTm`?!c}%Kd_XBZx?n4rNv}Z zwdvp+aAidxok08yn@PmS5S<(L5!@n4#tQp@#Qjv6ZBttY0MtJ@IgtBo?j)$|Omt0V zbjSvT@;L26e@{3_SYkBiG~7G*00=%1G^OpC2KR16CRt$?hA2%N`HhsN3Rm5t22!;p zJiKF#%I<$T(9E%@Gl251fk18KwJGz`9T+4DhVQCe`0&_~-yTrkz)_UWR8*GdA%5o4 z%dk)C(Sx=U0Oi9zs50Z|yE8`UpK}iBiZOour!nWUMUEMl|CV12P@oS6Hz54B!$BVR zA8Z5M0>?Y$$8l8@jL5kRVWiDL4Nw37?7eBUEy-0L_(h)i+~Ljj-m5`UNgxS{l0Zmk zunYn%K+WI=?8dBK#()JZH()I=#()_XtCziO19n>&8krUt+TAwLjT>wXSnUQ?NhO4! z3Zc1#sw7eMrh4_}JDn+`f8>eC81{~cJj1=`-j{pbcV5Jf9Xlc;Grt|NW5_B?fGSx6 zQa&OeLs{EC%0ang&1u))(&; z=>?i9lw}v*nxIAL=!Z5Iw%f-V1OO4YPkB*g$DeThJC$@?|Ee|sOuvwIRVEqerF#BF zbQ-oh{+dts{avQkU>XV799Wu(?!PiihCNWVl-fS1ptt^qjFL&N*c_gmg@hMkHej?C zp+Uk+jC1a&9^UaRJB%Kih10i{9qYINs@l*;RQ>blxa$O1?=KnI) z0T*hYh52E3C{>vbs}IdXhgB|Jw3}qq%1<(*&Y#%K_waY7eDEv3&1(BMKRyY6r z+LlEdO{)IXodG29f!*B)TCIDV&5cImR`t)qXo}j8`33fYR&*!ue$w$q6Tn!?L7tO6 zl#^zMyY=ks!hY?kks>T8{njT-!M~+B(2o+q{Hr3tNN9I zJAG5N*z`*P>PR2&A`7UUuHG@+@wTKPpn+Qp8=x%J^=rNolWtR#tyKcaG~IFs@!fx= zS!dBTHtvwqXAj@>fFu_VXeh(XxPc>5Phx$-1ywCQkyAvsC;3E50LQZ${Z`2U?1L|e z6gb()08FGT{6E}dT`A1zF{RN}<-|RF>qm`iK4JFzr zXv9~|TsD)_T(V4bptHPC%KQ^|Ik<7m&xKf0#B#*;sil-l5~*Znj!{GD2yDrGEG2*w z)I9J(q0m85?E=Dv$N)UpZeubzpJk>C#dO_h_f8q+Wc;uYNn(jfejWU%Q6kFKmD;x> zrfwf0gwSpu>m!a+SC0@PbG$wJYmRm<;fN_0kmC;0&L!;{Dt$z1PxAB?5k{CN!;-20 zEi6Vk3NcWA8r7a0+ayToG0T%GO6QM+b>KuMWiC{bfRMB|o=7a4vfK6{D=v_#M z&;TrYflynG1jnUM1k#X+g#BH+#tKep7w2TxNxm4Aa@`%bJ>YiK*tOtXpoCghBLFF< z+k&~dUz96%rn`2hv%$JX(}1@IRN5Pk>BAnRvFcxG)Jy(Fu@tC~Rf~nZrZGtxL9LR8 zekI{{{NVvTgZ@gtVKB5#gJa1k2ICHr#_fZFS?2Xcq6v#c=_F>tdH=#`rvORmaco`A zB|zFyEo*Q`D%@HGl328=OML=#2o1oZ2U+?#m^e62hP@>{;6Xf!`)-oA_8(+M=3F2+ zl~Ir56qk#j0&NKx_zu8a?c;0$FgT_CFpPn*;#1X!S@kc=!AODozQt1cqr^5^gyyAa4_WGs`6{=O^hjUHU( zd~o9&<;=$pyd9&O`$l$z16WA3c*i zF-+{QH8m5;?>}usfvKm;xpI$e&{sjj;R6r)VWT{ZFopiG zm}ai1J4n?=TL=JEy8rri`!Yn9nBxdk)WmUw#r#%J3Hz?3gnep$iKI-7BYl~X9s$(L zKx+dafHq1403Uz(E_pSqN3x6Gk9t$VFrMkeK>!q{mbuF$)9s@<#Wf1gD#UDnan5td z^)Hp-oSF$`3Dl5;zDSd7@KDfRM9c7;lL6k~zzC><4I^O`O}m3iNHYIQCgZVjIo`ej z8mSW;M|4u~EQbYH1t*-g2iSpg*Fs2-W84r;|qBdFj`U9agFeNJGMKzC%Gd3}`O>GlqOB`lC#Rw8gZgF*v$-6Qt~ZJqh{&OTY<4 zqG>pu1o6z~wfU`rv{QUo#~hro;;xzt=s@U*8-NrFxPXv|^$L#T;O_f&C>KAGm+al! zxwP?cRhdj#(e0zG0)Y8k|7B%^Gr)R=pln%nz5eTL_wJ+;b8sIv^aCY`!$x^nh)<%w z@oS`lG7_alDTe|jvXg!D1SV@35+{>=uujJDIK=yFkYe^Gpw?ARh)FJEfK$4FY6DOk z0H5MmkJ2Yo)e98PsH5R^{hIti04HfB8BU%;%L3d!ao2w_hv2&Yt>Zu48DIeR!fJn( zW6ChBgNgeJ`CaIT!f|+R9~fZ@{oS6v=?*fzKnCI)8O=Joe`J!+oZhk&pbuJ(P~PC) z^2%1ht5sBnR7i5Tj8RTa1=R+i>=87kTT(+CyTF+QFDk)$fnYq5aaWI_EjkF$wS|*p z4p0J)pn2Rrmg|4YWnKR;>r#XaO8`KBV$vk?JvJNI$9?$FkEw;QRsqd88DN5bS0ZY0ffLoN0yP0(Kf)~Z2Q7poW%P)DD1DW8 z9UXB4V1hMAr2+5}yiyEnx6chTPU`DERX(qXd&!NAI^_Dxx2$;?v z@6Ws-i|=`LG&7K0KLZf~&lH7$I}Z1WhZj{S$bBhvgn)j^Md-a4kU&FS@kshP?m9Z+ z1|Uij7^-KaVZ3kgK7N`rhs;<)RlqRB*Y#T&-R#uGS~8Z~hg=m}3Lt0$G}c?Lf9o4# zFg`3Pbf%)qZ?6TKN;;<7?IKd3puz_3qnrbnG8Z}-K%l?n4zh;`<;A!NUI1~(5_o)z zGv6eE8;$vY0@&?}Ropm6BDf3mB}baf^o)Ad-_RXq+>La%8vxiYAZa6VzzYOUG9e=& z&wKNIj>9Ae5YDkA!eEvVUb=mxnd)@;%Wghn1BkF{M{6h`3k=fVAu}s7EoOScgxj({ z{_BRYQ(WAi#tKOS`k??Cp4$gTIE4OXPv3P18Db95a|mu>F=Z#_**5?`nuzrY{-0E< z;7C#I>TmjBly0MrHmwhIXAHLH3^gMOOH$y*oq`6J#e{qc4ER!tl- zy(Xk#5M@uloD3)cGR+1|@m^uQ9$RRjr(FM1U6*kE{?c6jUrqvZ*JqNn-en8-O?x0M zjus;)1E!9f3X=iufB+u)Q-824&ZUxk)}jPCA;S=xB#34ta|M!Ug?77?GLmA_9Lb3_ z)r&EtJ^+4zbRg#F01SY%v1tZ@#nMnUd}en~DmimP!ig^av_Sxw*LMxUupa@M+JNcG zdyVo?4G^{gh3ntqgLM5*EroLUn6I-`4u54HLX*HGnN4fpiZnR^=r3fHBgl38z(xEj z?jY+HnP6@GkWdOEJVHRJ9lF0?h)KN-SQ!Jd;mTSQ9O>lJu7BM$B=i?N zWdkfgMGX<`<$pq8EkFy4YF zI?pe#nsf*afRz5bR9S}sDS9N>G*ZL+cwt)wF16$=VO>A%;qi!UDSK-ej7v;&`>4LZ zwg>R1e0|ryR0heK0X8gwoOV>Fbu+47c@kJLOPi>Bi5mJ9JX@0i$pD9G05=8n z{uPnJstKqufs>J97I|HcFTiY&j z3g}1Fw-W(Cw=*I|l8#D(DM`uX?25CYCV_9R*c`xt&yc^$K)QWs8(@c1UH{e$u;J>_mOx#h0+5tR-~yms zM%h@>XwU%kL&1HSI{Rb*jrctJJAdY-q^HidZ$Lk^oPZUb!*P@-=~gT#34O(glQXMB^L6hH6{dyrFR3BeVf2J}*6|1zXRMpl(=pToP^2f{oj=>l`XQ1TaJ~Vo$M8gs&zB4A6 zDwb}NEUkrU9?VPz#yJ4(L$(BRqmCue8#+y`%0#_>8+z zL;WRpGYVCc+%7TqODCb#N=3*Y8x7Ugx8tgc5_} zJV2s)QxxyHRe^G0==8;&jtQo&9jP)Z86{XAI(s&A;ir*Ck5^{I(P#>lR3{gvknIhJ)K(M#$^T~6>6nMI(LYM30mF}9(poOp%IF_kok~W~&Dpnp7q8R(1agGr+u1b5YCz zdr)*>2Eaw3k5&>zp?!XV<JSuXiEXMhXU%b5h8#$*|t3OHK<0DGyA7N8agQHz2!zJLN*5{~11Uf8^J zUxT`TOW!w8Y56}G{SNtshWOIwOI8?=z^0x7o{as}FwHNpg0$ZTULt`>z~&S(Qm+LvqR?kSt1Bj3&}|Wu zSpvJsQS#ceuaqmCFR{e%=a>**2?BNQ*G+zGV2eW=Sv$Ug7BlaD8$BOMq6;gdFGyz;MdXZy2Tm{NzDE!^QEmJ8+!Z z3${<|`aL~lYLVTaH;!Vxhxci=L7mcI;l9)>K>>3pAd3Uupf~qgWLY>q&kCu68bgA?)W>C0ZJ?#{dJ83fX*Q`$n3r`U}U(YCG8uq zE;ez;nRCNTz6{7G@r}4V*K8HRXGW|Gh<@pmhKN8^gD-HP(*uXk1>}%igync3bb0X}$B;XEIqesB=eiJ~dxB`#P)0a^CnjZMQazW}Tn+BE~p;iEQ+ znU-J*_iF7=;VQB#suv!SmXUnvr+{s9%BX?tT2@Yzw6NFlS4s@G4{X%7qBfe-NxXbO zk9nc=2@~GbF$cs1UXvKTpu>gK+d^0lu5_+M=(}O@Wk9~*oNG=;0MCraenEb@a|*0J z9k2nAbHn#Sihf3q0Gdq&J5!k{@lJn}N#i^3$#Ef#^vu{y{T8MBb{xL&szJzmNz=p+gurZ~ReUvVvFbTXjq_`}0T z4z)QzPyI^=`T&l5K#WADt-%+gWx)EE;AipfEma5UB+*$IRRx`E=@G!t)yq>VNdooa3U$fzPXa5Q<7}F*P9_5>J3{octS!Wl{DxQZk{-_4;!iD*v%%WEU}&t;-%k^s z!3GpiEM%7H|2DgW48{2lTS3V-!$g7HSEnuMtY<{!31b8WRwDJVzE+VkD`e|EJ*hvur)f z0PN-Y^_jK-M{#^+pr1M8oU~dafZ5=C{)`g1I2t|JZUZ>pYCSs~&akA1WWqr9xz_o3 z^$A^6RR>Wt304P34+Tn;56l1qgcnEyz48K~92ppbF#e}%C&`clT_~~J@cV0IS6MXl z1LS0Yh4K`>m(iG0h=A9$F@beQNO=YU1F0c?mF~Zb`_!<5E>YicMxkOSnERPzPXGWQ z07*naR0=P_ls~V#|7rq&dE(=={~4D=D`5cSto{1R86~?$=$Y}jFaXCIjVl2BX@Dw& zfB+vz>dX3)>4O8o3ET3*DLw2{qJ{#H#TGH+?M<8k)&eL$Dp`&UbTNv}5{U%GeVI)aco4&Cg-_mxk zF#_;q!j$wTav4{6dSE3+01nCO@NMz=Zhj!+r&OolY`b0D5*qjCSl7?pX?j2~hkxJU zyFGm*0KJzaJ>z7isYbEQ0APT=_6tFKe#+%Q8f(jXDc4c-1@Rlc#3xmvmeJ^|@!fF> z$x_S#YqH~ChAGcDiP{|B2lP}v3G{Xgk$;>3%TMV3li6Xko?pG<9=NHJ&_g~7Ws>_; zx>;V-o{j)MH5`(vJRN>DS%KJNdcZ)>(JFove%~^h{3iy3B5;oyCr+Pueh?7h2mAXL z=vP|LvnU&YsokOrRvsk3-DF_}p%wud36>d<@V`ogqFE)pkxw#`H=Eyf}1MIj0S7^ zI21l!7%#h<*)3-lie_ARiSy7wj{uC`dJ0U_Ix1!)`JWh0*9G6xY-(Vn@jYQ(zciSo zh`}^ng;$i_*L`N_M!Gu$kuK@(4(XJTMro;`rMtUB5R~o#RJujFq@}xOzIlIZeQP~` zz+Ly==iGDl*=KK0H}CRjiwSA|RGh47>K_>I`Lrg0L!t=S?gW<$HbQ^QBAW*3jHx{d zLy|jYint*3n>Zd-cu>A$WOE$WiFZn2vTX3)KP9PFCgm?sO`55Zchwz5OcnEQK|Iu3 z%hIU2`sTkf_Bn9q3)UTpsVviIR%x4>N+mkmqMmrr0U8kaE0~RypfdVcDV3R zQf4)J6KXmQomrDA2)wjS7eTxHjWNov=5o=zwR+k(lib}6;XFXSA68)@KFT&5N_9|u( zz(6;FI=C!hOSM1eZ%M|EsJx@(j>AKOI+1#lCwW?X6PLfX&AWG2*nIvpbt>0P*4M=I zdr+95c|e&%QhK3{P}Pu;|F8!Xh&HBXliLQy7==IYwORHwY&`^jW|cUW-wH3uwx4Jd z6S;c#Ya{*ounLvQiLk8^UXO?~07v<|qmc5kJ0 ztx(H83SpEcM||u`dk5a%{%8YWk&I=BNL3d=Feqk7z6JWskla#BG=L~D83fkTKDe)J zXI96`1fOvA-6Pew_F!ic{jKzZ56{#!SxSc!a4k+&u>ulSYQO>tfl5EW$FI3!eI9`S z``G5*CNel+RX}*&b)YjAe1lx{7CkaL3%TVgOUqTBd_O8`nsX5Sy|~1>rq|D!B1x_3Yg$vh5#@{#(hfJN z44=X7&ODh*!6ons-|ntJK@@4tPwGOdgtoyNc1bqI>kj?EubGOkK9NxkYU&R?`hiiz ziz^~0s?&=$9v{JDHqH+sh4NRo_DvwmLe&?|QU!`iOZkDS*lX7Ge3ZW#f?e>~HNdh$ zJx$~@glAxig0g|KGivw8>!6~4X;N&uAKqyFzNRJdR`H}rtu4zHIqV7Xl@=^h6WJ=c*TjwL^jjPKP8k17q4b+THndYV z`m#F@@=DSv*n;;-io{GdI|b`33jDT|XR+K3`)XW21Jc9xy{aH~h2V)#T7O-Up8k;IgAo>iU(eq#(${CITjke{!S*|!IEg5Gocy40g>glO!&6BRX< zy1iX}Olx>ZP2Ra>$Ky(XWfsp0`aDUfy*&{WVdRQM3lnAS4* z)mM}m5Z|0;iuteKW$k+yK-TkX4J2&k@2+1_gVq7R-2Dz^#gXsi1%d}(zR#+LM0Mnc z-uCrb_AeCl`d;cjHHav12zO=iECF2>bE%RVL< z(VJbc7Jhy2MV8V(j0Lsp7@IgsIVkwX!4 zbIaFZJ-pqkL2)&%cQEQ(O~I`EWdqBEHc#kB45n~(Igi#eMr`$qKkyATx>)=jMW;Lt zRP-EuhV*Tl=rqvT;n>c&xN^0|0waHFUGYb0;xe7`cVsI$WSQ;B0usDrU0t(&&OY-& z$e}|$YC#=P9f$wkwbxj;gm;OjCm2OsKm3~Qw56PzRo_UMfh;bkb+WTUVxv|;Pz5!?pwYU&D|tw7}dW0Vzyl){g3dR39lr* zmlf6cMVpjq@{!aPkfO;O0!giWpl8lk=1keq(b{y?OTY_y*xM68rExd4#CaNoM&N(@2M` zKK8%O;I}FcyQb?*=2PiCUM9$=R8Z^LUN z(}P_sn4xBIzHx41)-JG&^muK(Wmv#Ll`&SjsQnPUBIy)e*+itGv^k`TQS7l3F6i)f zL%(~C^y(8JAxO4T{MK7|8fov8weFY3MtFo2fAFrKr5lA58qNBu|A$VTjr-%9%G;YK zeg4h4!mkYmuQY^f!iO62a4cZ`>R))O2P?HQ{Hxe^`pMrKq8~-@ADWA4 zX{eB-2XTFA6GE~QAV?KO-;uYs)bw8okGv`%w||QlVDwNJ-1y!vMkS;vY`csH>1koD zfU8=jc<+r?wn|_?Y%f?9(tybb3AJHfDa@tC_YZKp%}sOx`vz6&cHJKw20UF7*!8_v zFigUWDIO$1M+)?O#=~E{9nA$*J6a30eMh$A99{+%NJn#YVwgzncEg9?-&2OecvZY+ zydXb(Sm#L5nP1y4a|20Ild>LjdNOPN4kKOP#x15X0pF_S*Wg4}O@JxpbzU#rb4V~$ zAL05CmUcwDko}d=w_(npcCeo5nm7QH;f2kO-$slz ziWym=q&OAA^Qtw%SGw}Dx?3C#Qyoz64vt+|p)AB0WJ#6w zp&J0!l^7R)>g|?zi$x5i#8yyaf!dxwNoqN`HKdEYdLWeR71_}rOy_e7NAF_sA%pA> zWg3;0E(~dGmwe0mgALsEySBbYh9J_&(X}Y(%7tG~+`hRJUV)xxfC95}QB#61k>SGPWxnHyhnq?cIg|`$lUZ^K%a- z#ys}|fh!v##uDeHizO7j=mu(eB9b@XV{ne;Beze0?%}M zCF9amN8&>myH}S}W4XFAProk_qskCB?;1YJ3_5uaJ=5=cOAb+N@!5ZZMU+K@=rW^N zY%Su+Eo+C+i|E>sgD0F9B^x?Ts4zV>zj&1_c4@~^bq6)g1}3Zz*%T(;q(|)`eQvt{ z0}r47N2E_+#cW670kKtMQ|&pm*jKlJZ>3RgD6v{{%?TkL)%$FR5zblLq-6hNy|4a? zeef|GwDW3$@J@XsL8j_venFiyr|8F=f*O_+#sT{JyyM!uBY0ul!vh1~APHL`Gyhp? zpH2}#VHO}fbxAyXx39L=7?KuTOOrWy?A>0;_q00(e*n#i`fM_>%$;_maN@}cuKi&hmo-+_6?pULQTYomIEncAE;>L%jd?Z-th^y^ zvh4Qn7Sz?W{Jd3H$JRU3bX@DvMU#7j4`-~7vzZRr@4tW4jPfV1`h61dZ&Z9>8gYArsDQH)SA#+f5ON?#j7ol-u5E}Q zuu-^SsbAje)HlglO>WleGMaBbqdBK7sTFx#ZBRE+<5E@PE#TZz)^A!AcY!5kRmv@9 z!wQaDMiVT{QJ#5w!pqhZHjVquNJ&a)i7<{E>xbO1o-MeA-s-s5gr|mgmE#fI3|uAG zxqOw`e6MtLrU`67aUk-;qvB@Rn6W>{kgAUxOSQj|H8K8B{nVXEp(vZH`XPWNFL&hb zc6>(n<K`g29&cnCdZo1A>*FV1@^v&Lg!axG7HZtC#We&V>G2gWM2 zGshIdwUPN#9jR;#IVmOm512S!%PKoH1J69v)$fMAW?cZ;3YS!&#?KizlbS7FBMSjP=|+KMhgc47yZuUS+R^Hb>H7@5?i+)r9ofES zZXJ=2w=FGgpHOLtVPFyt?}jEBRH$OON)V0x;5$Q;mYGQDJp3NAk?kEkf1bR zpH78L^>spyM7t~{6ZIVJhi$QGEZSQ#9>8O(FJuiRa`c$f&!Uj$qbsWZ@*kQREGf!; zQkuz^+~m+rxKU*G^=%Ueqg6u1&5XjH>bJD@|SBL-~`;N*%IaZ&e1`h9}D3 zuk>zDgYwTl3m9s_vxyN>p_5T5-}*yR>4}y^z@`d(v0=Hmg{gR#&wp-~a{M}&C^tQ) z^-ExC#)L9%0IXZoXCaEdZH9viCz?8i8bGOw0loYTd=9Vr`_|+*Rp(D-)Bxf^%k&gc zr;5TRZgtM_GvKx7mPoUKwZa`8GnE3KoqRaMx> zQ2N_6pOzXB_!Re{+^Bnh8iXq;0mfGp5I*^Q{wkP&S0wnGm1vRwn~8PG`9Cp88xkU9 z0e1Whg~%7=O7Sde)E>IyfgHuB=c@wB8hq_S%=}tec=gbz; zAISO-hFaVkhbjsKVo&V|*zo0p?~K@=U;nw*47_|*z+)xSS6M#=qjh`6BWJ$D;Dogi zNOoAmXlwhaAexQM8)68hGWrmBZDbPHv3H_CZmgevT%CyW1s|)tE*ofO%dH>+Us#|| zT)$t7#w^p}<4h$;cymAR$JJ7VKXzVf#MBtaN3Y9^Ots4; z)|!vEkMy^4DkSYnYpcNSQlOg#LUqU01s^1j@~}=XAy7iAA}&rR0}(Op-7Jh9pfHqb zCMuk+uLcIzXJVY^G&jR2^7KIKa6e;2&<$A!diK;!8jtZY~STVi$q(|b57hhD7d|(B76A3I> z$GzoDm|h%mM{iop1s5bhs*xrP{o{m0 z_57{=bZ>dkIQaQ|z9Spd<~H-rFXevP(C@jZv<#mLo_QQSmK5T$2-hW5X~GpGR}Q(_OV%q}}NoQVrWDduBi;Lf4vl{t#I=PT!3$x9Us; zf2G3dyu+IVPldjaEm|Iop7@9I&}`D$dwh4E=_SJD&??#0=wZ*xLoIwlJAlSI z*%qxk|$hQpbmb~rgL z>w0tyvu%32yN_kI&xdtbF<1sElYiY>>&xec!$PC`Fb3s2qq6WbUJ;RUx6{~OLZdB{ z1ZpQt&<4CGzvHP;4X4z*{C!&R|K6d{)$N}}kA#7a!U2d{d9K@4_Orq5W3c-k?uLlF z%3s{eO+iq&en^mwY?rZ6Tcj(u zrSOKxpiDR9Cyfr`-94{yJsCUKt0+f?US(pEM($(5R?=dajb7chIV}L4cdjMfhqHG2 zhiuW_NV0GC*nW|HWdmS-lpfha`doXH?e$uVjy(i^cvEL^+X3|01U_%p)phN&jWuCF zg24T>zE(O+9<{wTbOm~x+M6rEtMV7NPyVdp?*LH)ZFUFL014%l=5Jh;pa&KU76sBa zl9yfhL-_7@DCV71uL<4pSU6||Ojw#C4clSQaqiM9lni67XN6BrQUL?I3fd3#>peRw z5*$p%tMDyBtN}?WYTH@l?Aps(`Mz z-s+xm9IQE(d(kZOw=?ngmDJz%@d~tcBZ%Yx>E=ND*e@RY7k?FHQ?+6I^cMr?dASS+ zkrcO{eUlgiLhH%DDV9zZuTC<9ulgit!h(gWnY#P}kN-nymuxN`9pR+s45#&Q*3BB+ zEQ)v)tdLC2@GnbSNcc60y-9jx`RZm>sX0jE$=zSqk=$#heGA)PEey%r=B&nUF9)#E#_1HzFZNAb`kMl59GTu>x2L2%O{3*Ce`^|q7mh9(iE`&+SnJ4`^}Y+QHsW4 z*vm3HA8I}+f=?Gy8spAC2)`SL9u!7=1OM)*7_z9HFKiML-XY;r<}2#GE@B}nTTg`k zaAT`nV?K1V+rw)-Z5_J%XMXz=!2@3vgWtBg8tZdA{qTX8=c~NWV)cq}AXWsX%p6L; zXk6{5>SB8U%vXmxA$ zR1JpHZiUSK7N1K3cbKm9h&M`X+Mrr{HC7f9=c9NpR^Ge6)+&z46-?@&drYa*BS;{B ziN|_RIAoiv%k82<_QZ6hDKoT?kVGr&@elSE3tGS0^K8-DlJ9TzN0Ng1)SnqAdYZU+ zt^m2f?e!G4Q3(a?cszGK;K>lRt7}<&+0l$=g5s*u@j4=@u?_r0^*vcWDNzG~Y;17! ze&bBdrn=b~Ncl6)`#nwDE?T?KYl$T2z}u1GzMmJrV#6G5s7gUI=TwpK5BS4nw{h4& zYsr|1wqjkb&oBAHGu9xaJM(|VZksC;w9#lLb$`$HqSJamg`L1s$5gaW`aU}uTEX$& zx+4QMjG8xtq{4FU6(A_y3)h|d(T;r5=4CJ<_-=NKcmA6by|$_hE)t!*YE}jrNAvJ( zeEHZnaY&JxvueNUJrZ@<59E_8=`03T@v>s~@8i|5LB8{yV6~}L=(@>=Q3sQKcD@*W z|C0@*Sot{U$Ln(CllocmRxnapEQ=!B`R+uQ)ndf~$#?$dCb-ROxntfAWj7nPql-9U zi8n!ObHxKZXd6u|8HDO-_dAqAm=jJ9&s*`RcLp!dyxULD)PmsIlG6Hq!ZkMdd;#8jZ6BR+&Vvh=i+dLE~SnAysz;c3<;r z10f$hC09FY>d3q1?C)2s}PV(IaqDQfqwM6XDB?nqEvvM-jw;1Sq2uFDb6copHjAQ>|@b3 zv?%*KwST&rz&{^6cJG1E)>pLGAVt5CHTWv#LIpco`MclPn#2)3onE3Z1Z-G|@T6O^ zV80mCliZpuopyTcel)35`<%c-h~RBrvYc1*GIQ-Kqs(B-9mT^x=O%b*ypH(EWH@=& z?@o?HIvOGo^{DatK|PQ7v$W*PEW~Ux(%^QkpS?mb#ouiC!dX;hQ5*)~Z`o4yKe9l0 zb?VRg2iSX`TMLU`bGv3tv_%{)TkBWCiR@RTO(m$n=J(zU}LR10cPvpf#BQ<+LN`-GS-@g^z^dd!rop+X%vp=-NO3= zR)gQ#y;&=sD^3>#3=;|mQ#R>oq<0VpWpL|{*JLd7`73^~D+ikKm@q^oU4cF7Q-o9- zD=tnz7Xj_={`XM4RyTz9IY^EhrT;VS)UJXb;-$9Xhdkz$CEmSFJG~2&cI2bVCZKDi zvmwJIiH5OY<~HCeYWmK>sSYJ#p_0OZ7ak%!-x@0Zp9??@;GG_IF^)gd`mvL+56BzD zh^6|XyS1s@!#wk=(;xepOB&O&j2Gf8j7|h#3 zD}|*tmD^=KL2q8t`l|o!CE7$Dr|UMJY0t-Y>)Ul6yjr!|FilA&mCG2}VCgST0QalU zm5+YARLEkYG`%Iue$t(Ul&7Ww?LS%j+Ho!65(jI;nf84SEPCzxTeuk8S+Zh=A!W2os@Ne=cWsP z_%LgfiHy@^-8C!G^S-032%+uSyTUSl4ZvOeA2Z!n_(yr&revNT*?7~x*AmsOXjn!u z(fzI;z*c5n&1Ggn2qnGwR5*Ja;OJJg6CS)JAF$4qkK9nL zV17VOR*jui+L!5xS%Q++rBIqYqRwneR+B#Tm%s%u8s=8i3CPS&xO)(C2{R0kkgEQx zqs~0dWI)Hw0VGAjYNXMx(8~WvyYHD-{cbz709*V%3{dXHqeEK@I_~gDd=mZ1`|9Dg zUGXLUj>VFGaXJmi@;<2G4I0RRHFdAqnCsXR5Sw!C_3Yc7x!v-BLay246 z3m3oaJOvKy{+f4j1{NkRPkTHaM2~*paSyD*Jyr2jjXsF*qZZxeTd}vL8C}s8-K|bs zs(qfn^#^F2Th}|g#Z$_WSKF*8@u43o+%)X)#Dj-vyzQm%LxUtOCps@EhCV%L3FHDs zCWPnIjEeo@)bTDks)%01zw5(QNOwGh8wgUV6w8TYX&r-fv}karrr;i3$p`Ot+VYSH1L1ww;P&Y76-<%JK#*Isq~Gt zbafBtfVrgj@7TdUY%mM7aqE2E#Wk)>Z2EnGGxx%$IiCwwZn%z zM=k1L#ezmO-O(3Grih^K#W+>yj7IQW7mLia-TwBnQzK7!^*@4e(Dq1UArZ1CLXCIZnYH+dbe)kXr_gFg4^$V(DZl73Ip?_*7GZ{(stY2!L0SMu@|XWe#i0G@qcm4sncf>Jp(FLTkD1Em2sNB) z!u}hzdLyBO&pgTUHR$k$dhcxt zM3wb*@uLMVp2;n3)F@!-fN$Z255;&IK3SW0sdW>iaH0Rxcof#zsqh?;QEDQFvNM49 z$9f)K#V((Cz6lQbDQJmb7=B8GX~V=$Wm-UllhuZYH@>(|ca=FE-Yiw-_Yy~T!v;NK zbhkgiSWTpQZi;qR=jBRaMdVGu8^|-G{X{@eE7C^4?^BCvW>iRd;h3?`UZ$E(`RiX| zR3st+r~sM-`Uc7`ogh2m2d7+0faZNG;zHIZ44%mA(PA1_i;bw7K>zxGn#tt;_wkJ? z{&!G;cmu98dWm2Ng+8*%PQ?pr3U2CWQ2*%ZP+P;qGR7-M&6}B!?bqO@IFA0AOtt~e z@4EdwSFEIgB^;p&!I$3eUFr|75lQ24C_FHeQ_{%xWIm94_s4Ba>OfQ|ZafGojSYTc z`hhGVO3~f0`sqU@(uPOp>aDYj`crJyAgV8zsV7z3Rfofz$_*nR{{^L#10#0WdG)_u4vmWGYu z5@=U-ec)^&YN){D-@OmmafQexz3@)fo#ucG;=@D0e8Dw1fV)lNTNKDR&+YN=PnN8V zgrek^cRaeA{UoI^16q|%R6{$mdqL1qB87Po^0SXjJ^Z}pSX*G}QH0Doy z$a2%Bwq3GWvcy%d)M+f z*tOVeiN79;UPc*;Yf1FQe%fv?sz+W=f2Gk5X2FLBDn^FG(%xB@cNc%+w4>e z`I#*slWE;qpYXZY?%i`8s|Jy>r032^;pKAAn8`aGl#n-P`C~zC`)A}pncqKM4!LA9 zGURZSBINy#AqXrPA&8LaB?_4TIS#V4w~q=m{(DmNcjxvox1fT34;B?$s^Y^TEkL;; zcmGpz2F6&khkmBQK>Blj5vPnAi-+<`v;K4PHx4DEpd$F*ee1_M_I3^>>cEKz95>rcn5`eZ4H8}<&<#l)ALrQ?u1@i_oVL65w-zWt+8JsVcZeNwvssX zu$@K!6Srm{z?=Vp#(z2UF#t7Ra)zYnXURz^_hpg~{DTq>kg>IgfejW0Er4OCN+Wou z$IsW}<7%IE$9LsMSbx_{O{L49Mo$OhiH9CM233Qk7YGc=t4G|ebkf6c8(&m1IftWP z2`La;twiBb=?gBR6!pgax_4>C5eONPuLXK75kresR4$@Bv;`v4$XB?xYY`L`A{ zKGMMz5-cAAt~>M-Q1^qh;Ql zjZ2W7&!hYP*O|Q`>Oh{{sZa!S2*ks$x9vLB+kJ*eFKsv znBwCYLoup8>R78!{m+hsUV3RLo? zRq@g3-s2IBL$WDgSbNvm58(XO{(~aC#-C&>J|!eYlN}^OFJ`5%QO0{9KjYp!_Z9WV zOvJ)S2BqK(2sO#;`pLpWI|STlW&p zqh?w8yZ)(GARGCT@?|^^UqjHDi4XD!gvmW*W;N#;AEW+5&Tx0#6h)QTW$90m_6 zCYDUFJ{{B4#P`-hNgoRYw))ri$%oT?>Qz$YBPSpE1GSGN+dBpU#Jac~_%K@We4~QcxSq=vr`P$} zB|kk}Q6g>!5?k-q-||W9u&;3bJv>%A7m%@Y!tmyRyy6d_D5lUpQUWGJC2jC4mC_Gp z>*Vxbd~(~luS6T*r!4a1?#FFI6N4dhGcREe5FiKaY;wDxW_=Q&BOpN^x*NM{KzR^5 z5!LSXGveS=QH}~CPA}ueILwjd#J{MBaJagiUWsQZ>UI38bCD}3)O-BnJQPl7P!HR@ z@kZAv-6#P5yx@8K!WAA_I`ceeB?MIc{e@BL5d+b{dlMR}BJo|Qt#|IBO9KtM=hI2M zxZJ5tMcA}Z3^3S1Nm(jg1n#A1xlt1cmSPt2_7Bs*x7ztB^;wj5c8%@c?xg{lg?Hse z>$P=w`wi5>2@NfT<^)@8)|CM`PTz#DG6f$HmHhMIZQgJ=aCX@03SYTCEN;PMsPAxB zwiDWZA5zt)q%7j;*@O+$-1~t`kqdkA74adrM@LU{L2&2BY>ab6pH$Pwr}c70|3#;@ zG6vx!1E1u94Ug3;Oh4!LuGH1wU}4XKORv9acWNb{u=mlx{3p6NN?ZONPF3NS{d-$- z&G`+fI;#>Q8(g>iDP2{q^YhUu`@slE>;7`@&v$HS)XmMB_x*)%@j=_JKu*-8dEm!| zc_}vGTF-qPpavUEfP(Lh>`Np(}RDMVUCAeVKA8u@F+rxavb4`ZM=tR&vvEI2)7$KZR&^ z=)3dP`p|cuJjvjmIb?Si-upjTq;9)@RnsYb;^6ZxZ46dsOe#(hD%yxd9TmJl`oMre zrMt!CitV}Xllm2(b;A+F}*h3}7G!R6J5rQnjg756qBm@QQ#$lrxkI#J+6|5_#h!#=|r|=vYAF zVL0?bcUK3Kr%klZttK*0$5^BYQX!UA6O%F2iIZGK0MTX3H`-{J)g}W$4vJa5H^1DR z%m1aLd+FgI1{-s~YR;uJqvxg95X_}rUS{Nq=`<8#5eAX6g|BYz6ui?_CcA$6gcxr6 zo6DP4@pf2G^l7xaQ{>U5j=9@jAwbilH>NSvc;P{&yR zLxz(L_ZjrGn#yXvdMGjF=psk~KO1Spb30`!kyO>6S|1@Ll*)n9mor)eNpTZwU=i`v z7~$TA^rT({i-T3_+spUjqfBQ9n@L?&(CZGKHSD%UmjGlpypl=91u_W8qL*&?jF2r! zyxh}**ZC$u;zhh))YB1SF=@mC*tSvx$~pEiKc_9!?>~BR$H#}k-~+q626gp?PJ)_3 zxsul_%@&0=rm;xP@ab^dWuvXQ{_ zMau9Q=(}RCfYFZG1_ zf>y2Y5hWm1@<7hZWV^^%nTSR%< z8Y$Mwd!rRSzw=u!%0tNyyK2+I@Xg&ipPB)QdpkBa)repGLGdIzKM8h&60!GlJv|kG zvyL;><1JB@Aq%D!eO8{f0tYV(T{cJ({?5Wq@J$a*la9;(qhPQ z$mTy5a*dHM%*VZQR)v%D!>URh-h32dW?n)2T-iTtPWeTxfU?1F;44mx*Bg=LO!u4* znx%i1rnnAn;r7k@m&y70!R|XoCtXpP`;uQSS!)H^z4`Z*$N^zUkFa7=?za@ip;Vrq zA2(K)Mcs@K3ta{I=*?G8;XmEoy~J3~b4{P$sDC8SApb1URu0%=l#o+rL(vR{T@Etn z)ba=p=C~c3%JLDK#%*|*T>DHk4+td=wS!S)QJ5*g){U}U@Y^_P`23B(WZ;dnDmp+* zi`|0=^4(`S&uJ1qo|bu=}Ot98AB?}OrtIB-MBDO6SSH%Mg>L0Xi|>^O!`fzci9uXrM36tyFk8C3YjiD zm%0@uwNRg(T!p&`rG3^C3Vy;!lnGVJ&!M4qAH_AVxV}@pJm)2xE|kPzWTrU2Xzaz1 zDCA8?^CZ^N(jdoRI8wi#u|j>eSV08#dyhjz0WstI)LPK)?qHoCF=XZ|EKodcy+QLT zXY6Cz{!2;#d9xGTQ#mx|g4A;HgxA^%?~IRc=5RvLK7!zgvb{A{y}yM8DFYKC7H znvQ(R)(YY1BP&}X4%=Fe^!uz!Ca6SzRrxii5#QMpW9pR0NKFXrI=G(sVSwntpVuyh zKh=D}v3sk>Khc&P;*>hvYT9;}S(>~q_ve(r6wV(y+2L_FH1&cXFl=H(=Q%P@!)Z(3 zJ6&CT{&yYk$|54uRk0rI?BnyL36$_1Kaug8-vkMK@*+{}A&%#a??L-(sz4$$y3H*@ z9vbyo#RALne#T}3_xYFp8R5?ZYIsq@Pn(K>I_^Xm0_s0)yL}o~K>Dx#MC{1fwmVt- zSwvB=&gI)>a(AZJebf9v)j#wS8+J+z1=K1_q_65Mh=tt$yS{eK@M=8rdWJ=zhM5rV zErU2WI&8J%#C!TN6kdnWW<{#ME5e^mR^~?%8NQDlLDu__`A)uC)qQ&wiJ~xIsKtf^ z<(ZD;^wBSH*qv_UO2|g7M}QN7re7!cPZlBslbv_&TP?co&ijhk9|)V0hBwpBr8y8O z^0W}31UZdBI}etCvfL18RGE01lU{uX~4AknjPJMAJl$B z0svFW@!*mIa!c!bU7rgiUii^^Gzg3p-exMtuD>aD&29*G_{h+PM;qz9a+?w= zrBIJn-iWr1@mXj^qAaU=yotwnSHJsYc{2Ysu3wKp_EUZ=DcqUs@4d3|ReRO?(*3)s z7jJOVN>ToH*4qe*zg@N7-IhPTfd|0@Z}}+z1s&Lt$K>OjE#!$UI6jX& z->xn@gR_+G6AtIs8@s7F@_nQ*Dr)plsvtbZL~9XRRyro?R!iw0bCKCTiB}CY3Ermk zd(tf)zvDK$f-l8i(~1XnupvXRw$586JT?)0SO%N07kt{HOqS^SDebw_w2EsedPx!2 zqdr%;ydV&nHHgxkZ*sl4`5M7i9Hfj#0Qpys;Jdpux~`1%J`?3~cf3|L^fq7DA5_gL z_|23V?D!utut*Ed@gLqf zAT+7XLSb!`3VC{Wqh>oRyDOg`86hw}lh2H@J`o@&_Ja7W&1t_2)HtL2 zd1X?}P-^lKsr((yCzx zmclhH+};(2NOO*^YO2g=kC2=3X<}M%my;HM}0L5eT6}&40 zoy(Dx!2QI|A1HcSzfsF5qj`;|QQd{V`~-hOT)C4!H_^4{F$g4Be0=xIWA~tsw`%Z* znf#{kl}gjLfC~X7KcOZyRkLTBvms0Vs_8;j4AYTIGzueCbWjuDw|BQw#}?N4n&dkV z7pM!&((HPh*W+Wo>0+#(GkD*P$6h`-)NYB?TS&_VAlcZC zM(5~9B?_VP^|iOB+o6021UU;*1lzhC6NVKx%R|}=Z}^TeKV;A`ZSg$&v@y$lxbw&D zvghtHD-DkO1@-WQJt<^hB!gT+sI7y6!xP2dzz-2vWLflec;$Zj>IwW4Y^A%71;Jjd z-uwDI*6g%<4?A-Nmx6mB#Okua9}V1bP7XXt$pMa8RAgx2H$ec3sLc_0Z*M@|I#Efk zt(&n4r78l+E2m2;^2b$<_kFBA@ZsAEkao%-Oy>v#Aw zHgUni>-Gz>KAINzE&pfOC8K{ljAhje72w-=RMVjOLonuul(%1gekZx!ektF*)^0}# z#acS%`sW1?aC6IjoKQHDa8ji+!>t<+&K3}WBz*c>kiAVy^?@?W$@-w(^sDXSxf-yK z!2`tbr43AJGM)RE_EQIIxfXhi?@ktoK1K%hR&6Vyg}DXp_On(aNv!Tu?Q3qU`dLX7NBK78>d63nqvp94D|&`kK%xrXtJsUlPPw++|P`(gWC|K=ye zOVR7|Z`&?Iynb$J==*v{;ND=p`D!`IQycNtXQ-(9`m7aOmza~OOs=z*)1bx{($2M`&5|8+0pjz8*v zw#=^_r4;CnSa0w2d#q$oZgyKnrbU!xNMdM^&>T7b88tjK96$J-$0g#3Xx;b`=(SMz z-T4=T^`PU2&lYF83b$C#uTOtH?EnB#sj{53Ud^;*{D}?{M1BDx=bjjo{4@QU-x;X9 zEDh@$_%DC9@HhV=ka5xT_OLvEq7rq0`t-N#Upw7f3)I_*U1)IK| z<~Mw_>JWR@S$Sz3dcp5Uk!iasl(-L@Qex>p!-IY%+x=n)s93z~o2`U7_68%UZPK03 zD>fI@q+BqosRIiIzpK4}R8?mT)N%q3NNu8KQaL2HNT!|%>YJPcsOTFujpy|f`Tl|R z24_BHPwQVTf_EoqX|az8(cvA02EZ8t4wm%%=P8-Hc8ox^df*p32s{~>vcQN$CUX&Z@bJ7%05C=P z1%b~RSf{%et#0e>>3j93w-g8hkgr)UT&nZBxVzh`mesXeuYZe4OY`&Bjx@Y@mcqK} z;15mAJ7mI@q$r@y8F>YQgN3Tr--9ob{zKI7via8i{`w;7212%A*spln?u#SbotqD( zYg3I1@VT-jV4;^yQJm2RY2?TQG2v!M=Zq8sL52mmohIk6B5*-O<$!>Rn%CO?1UvEv zcstX7{O2)AiNv=;Vy$lWqjE4cv0?pnm4iY@!Ds?LYa=!^2VXW?9GFcAh>lZ6r7PZo zYqdUJ?oITlP@kRscE3Xaok4pOB<+)v z8>3}ppDBcPl#tu{o4NN0J{zbZ z@z?cZ3-%|$Nlk(8{Zn7h{&e1T6;?2s z$@Q|72JDGi{hX6kadS5c+Dv0x1`GEvmT5RG!B~0o>|B zQ;33O>u+x^_srK%N$~~|`S>lD1*|+*Xn0N{XahP`2)ZJV`?0Ff49c2uTmmFxkgceF z9fhBcms=%UXZ?b{pa>8NFFOZ0bCacUeR=dUOu4gBA)*DyRm6D7j_2Iwc-hdt zZeRGtE9lZ8{RwXy=D_^U^E+QP>_I;5qq}ry>A>{(r|G>52V~Ps#3CXAW0|Y)w&dAWKf04kwxIQ{mYW+7 zds>~SPir}9uwg`^IQwPNW%&*ZPuyM#{(sF~=U)?B6W%0BS4t3(5~=16cwZ+NGO^}$50bU-o5|DyI;?5&)G9O&+N?E znP-6N8dJ^RQs-}0Ag{cJ{OdmE4dflyb3tx`MXpHS*~>q?iD1FPkidfK5hGQrs8f(@ zeQC*P_Laz2L6HFiCmn5!nvhd1nm(m8ogK*9iqD2n*s|GYwk8+~lv`%gSKpP+(t6$2 z4|d_bQ7;ymc5gPK$yKSCw)WHO`#lLBnz_7=;xuCx)-<#KcrLrnLVZrV!?b+oh=q_72?D|Gz$OB>^TTZyI(fS|~9oq8Yxcs~G9p~FF&KZt(F zGuQg|Kn29+%L%VqRYqsz%J`mR+hJu)gPq)k$0JB75v|pvk-n6R(&N{M96I3nl3#g2 zf)zKIwbYe5i`Tj1o0g?)(T+9Ldo^fGKxYjBsUy@urKR_Vg_&O4u*n8+T?a-L;qJ?5 zZG>V$NtOsqOe}rxJ{wJX6HK~gwJ4&^gxV=YFxS_SZ)r2K;0G?cVQ)*5vK#OV%o|QM z!dSZ;<&%%*}$4J=MZHJ@n8}My9ZO2_oJ82nzj-4YIxY ze3!s_*!|PL#)t{4ddcIr-W>T+G<%=o9=YA(2RM#;9-(V2h}VjixJZA7DJ42#YYujH zTMUM`uh`JbXw5qnOg+%CyFJY+%#$Y%W#?oz;%=Sc0JAW~GDYb`8`+7mOQpvUV2m6# z;m03^F`K8RH`MEH?XP!lMjmD3PnE(8!fo1bXaub<9rX6*%%}n2U$ME+!^sIeUZGPo zlzLdC?#C!xQD-UcndSBu#prj<%a&qja%DzLS8!$h4^!AA>D!d|Onw&?z(iL_W5oU4 z+Gw4hW=ma3;(M;cbM_+{Qv1J~@_XU8ADr}lnNU1KcWw?;7! z9#DUvMVK2C6FVTuX)JxWs3dazZGBE3REtpyrMS!oYjyWeP)f{RLz0I2rvZz>7w>fV zlUN*Qd@&n!IexZI6N61pGrj$oC2xG!%>RyfPJJ^rT11Zy#NJHP#ZQGtcrEwSx5JhD zUin>aIY=)o^tqSYOAighEH4L%nfveAL8=$IS>nC6kp|a=u^Ru3vAD+sY?B}Lq0Xec z2IS*cLx~%sb?QQ27cy7ZiPY)W3l5PFo^*CH`UgzDdrdcz)s+G0{;o}ptmoj z0v${LTC}&mJ~QE|Gvw)jNRQo`etkEY^4gy0r}1L0eynmJ=P>wLqbszlcX!wE=ZeoI zq0F`QqaKA@vGcTag-^VVoPYKcy4~}{wudEC{-hPv4r3&)X9Ct9M#4NfQXw)N^k`*3 z%QW&lGJ;vtofyIoIMClJa7r8D85? z0YX=`HS^a8C;Nj6$kXLHZ}Pjg&QUwQf91otH(l7ydwM^eaicC2azoNr1SM4!5zg1X zTb8Z&u?%aQw;A1ay7`BjFi2AQ4s$6YLszx7daNAcuadW?E)1oxHx(zRdUo8rFPF7S zm4|WR65@8A$~#F-CS$=#b8FRr+`1oB%yl z6JeT>y%qkf!)Q&h5xEr}-go$LX-csjM_#TJ2RIXAky#WlF*W5y#X}lzQMxDWf|g-+ z42v*|8WF}LE0(q0^WYO`9w^OPJF*CFk4 zRoXWYB>AZi2oPuI7>h7VaZ`=bI*AV}T5AgxSn%#l05opi&>F((ANGLwUVTl5^M&bO ztnE~nc~Chmc66~3$yoYjB27QF3KD6TL`ZK?QjRf>S+oc{yg_0Z-Lv^cEFx>|w1-I5 zDmnigcdNC*@{r_io?QKW*e@mai72S@qXht|e2mf!2UTfG4?SW30vzH|(znrncWnMT zNPry<5#DMmQMMzm54)rS)pX~z#^B0zCJ8a{Mn7=-a~sSKT3sBfE9eZ-gu ziueb==QY;M-;cGi4Yk(s)_Qw*)Y0)rL;USx<~a*yt-pDYwaR&G8=-5cT4Mqmn|xJ# zNKwC0)zcSV8>zg}@)92urW>J0z1BpG2GKqNV{Td5Os$rU3UU&w>qnj$_64BjQQYuBuPT|R~jF`CH^z-D1E!80|jUVpf zyQTUS5xMeCn73}}49=QqKoM;FUV!Rl9c_(^y4JkXsaxGx9U~LdI&?>-Togk+kUc&l zr|SFC;|wSxSF5hVgV%%=Qw)*@Xp5Y88SBKc-UDbb*!Ix!V@@E>G znfS}9Q&6=L2*`BZhMfG|6XE4~M+k((TmBH=K+&_N#iwiQs$sIB$51+C`71x$QVD+7 zm0%8#`c=3 zL4t+PvwcC=SNB0=YhH)->RG3xB1sk#l@FJrRj*)Mlc!+S}(h zU=s-D80ZT(2zR{Oqq>JXq*x97#C&sT-{-FHuOj=L)j%o38$wku1tlZZoevf zbvC+tbELV7-QN{)v)nS%@V%Tt;&CZnj$bLK$dP_Ig-?#;@R=`V9hd&iVH5dsYAB^Qkk`flFQC1cWHA+P!9g}gIt3$fxJ5<}eI$UVtp z&GDdq_vqy&LhH=5=v*#}@A>=(!D_b2Z?aRH8H1~D3cm0i^A}^kjedNP@E|8Yq?b8l z?E{>IH)fo1u1J#>znq(&Tt^)!yngDVbcK@E1OQhF&vIwvq*+0YGEb)Z-%gJB3h^jU!aIR*B&X2ke{r4D1 z2j@BWWJmGknT@GI;17j-|NRi!WPAuCSf>U&&VT00qJ3gsaad079x5eZ(EYpq(&am) zl5%w$-x`E)Z|Eg0Mzx8I_7rgTR{7a_6~Y;|B*O{`i};I4GB=*sD*iLc`ILpGE8EAV zc!Jg^G#;D;qQE%r_a)etzc-3xtPu2MO|QI5*Tz+er_(vu<$<%r52z;v`5hEl#gzdS z7|D&T-0BJ3Ei%)UcCYOntET8*wmy z&*%Go*AF|clyY0nzC+Z-{^gVa+gR`=aA_tcYVVbZI-3C`_<28*8TcyoUgoh`EaGMf z!344xuD6pLkyh-X$Rfo2x!(Vr#+|5F5!0@&9k&SAvHDHa^?ZXAL~=g$Dj>2STGQ(J z0CbBKi@pQhO~-f~qwFx8JrzNuT0E+|QTpIk<(Aj9_o{GaFZR3B6Cj*;GxwXwUfTI1 zd@I+?8plZuy-50-iLsbTjF`&iXC@85&Du-VhL)zRUM|@dgJ>ZMDl#*OKMp(D7?yJ+ ziF(vQA>`=gU?K!94R{u4uNTbj%+9>maX%stMu;?I+I(X)JwDpS_AQoa7Xxz3OH$#k z?@NafV*an@AC+Dm&TOuwbMXLGCq(w_1Gj@V{K?ZhB{x*G>_mdA zqGW5QBz$q`2w(rezcSc2t$@fYkRG>mQG$aHh!!%9pY8tgtmD(hnjMu|Y!gbJp_F{Z z#t~3!kY!yLD0V~Nl-VT3*3$e#JyI!B;eJhUq7z&#T)@4)Dn`G#@C?5!FnJ0cze|ey zfQn8(NlK`p3{!}qhi01Z0hq8y^(AW3(Gr zPvi^SAf)KZ@&F?4%ZF%Xz6GY$c>JT%$*6k^T0Q?h1W4KhdY5{X!jiAY$xa!wkK{X0 ztXBh)8T8u>(Z>JG9IAl>NCE<}+!R-*i7o#}H)VqbplU7YP^1u3uD zTC)IBwOZ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/index.html b/web/index.html index 61a56f3..66dcbf7 100644 --- a/web/index.html +++ b/web/index.html @@ -17,13 +17,19 @@ media-src 'self' blob: https:; connect-src 'self' https:; font-src 'self'; + worker-src 'self'; + manifest-src 'self'; object-src 'none'; base-uri 'none'; frame-src 'none'; form-action 'none'"> + + + + diff --git a/web/lib/xmltv-parse.js b/web/lib/xmltv-parse.js new file mode 100644 index 0000000..83a7efb --- /dev/null +++ b/web/lib/xmltv-parse.js @@ -0,0 +1,112 @@ +// xmltv-parse.js — pure XMLTV parser (no DOM, node-testable). +// +// XMLTV is regular enough to scan linearly for blocks. +// A manual indexOf scan avoids both DOMParser (unavailable in Workers) and +// regex backtracking on 50MB+ feeds. Exported standalone so it can be unit +// tested in node and reused by the EPG worker. + +/** Decode the handful of XML entities XMLTV actually uses. */ +function decodeEntities(s) { + if (s.indexOf('&') === -1) return s; + return s.replace(/&(#x?[0-9a-fA-F]+|amp|lt|gt|quot|apos);/g, (m, e) => { + switch (e) { + case 'amp': return '&'; + case 'lt': return '<'; + case 'gt': return '>'; + case 'quot': return '"'; + case 'apos': return "'"; + default: + if (e[0] === '#') { + const code = e[1] === 'x' || e[1] === 'X' + ? parseInt(e.slice(2), 16) + : parseInt(e.slice(1), 10); + return Number.isFinite(code) ? String.fromCodePoint(code) : m; + } + return m; + } + }); +} + +/** XMLTV time: "20260615013000 +0000" → epoch ms (0 if unparseable). */ +export function parseXmltvTime(s) { + if (!s) return 0; + const m = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})?\s*([+-]\d{4})?/.exec(s.trim()); + if (!m) return 0; + const [, Y, Mo, D, H, Mi, S, tz] = m; + let ms = Date.UTC(+Y, +Mo - 1, +D, +H, +Mi, +(S || 0)); + if (tz) { + const sign = tz[0] === '-' ? -1 : 1; + ms -= sign * ((+tz.slice(1, 3)) * 60 + (+tz.slice(3, 5))) * 60000; + } + return ms; +} + +/** Read attr value from an opening-tag string, e.g. attr(`channel`, '… within `block`. */ +function inner(tag, block) { + const open = '<' + tag; + let i = block.indexOf(open); + if (i === -1) return ''; + const gt = block.indexOf('>', i); + if (gt === -1) return ''; + if (block[gt - 1] === '/') return ''; // self-closing + const close = block.indexOf('', gt); + if (close === -1) return ''; + return decodeEntities(block.slice(gt + 1, close)).trim(); +} + +/** + * Parse an XMLTV document into program records. + * @param {string} text + * @param {number} [cap] optional max programmes (DoS guard) + * @returns {{channel:string,start:number,stop:number,title:string,desc:string}[]} + */ +export function parseXmltv(text, cap = 2_000_000) { + const out = []; + let pos = 0; + const OPEN = '', start); + if (tagEnd === -1) break; + const openTag = text.slice(start, tagEnd + 1); + + // self-closing (rare, no title) — skip the body search + let blockEnd, block; + if (openTag.endsWith('/>')) { + block = openTag; + blockEnd = tagEnd + 1; + } else { + const close = text.indexOf(CLOSE, tagEnd); + if (close === -1) break; + block = text.slice(start, close + CLOSE.length); + blockEnd = close + CLOSE.length; + } + pos = blockEnd; + + const channel = attr('channel', openTag); + const startMs = parseXmltvTime(attr('start', openTag)); + const stopMs = parseXmltvTime(attr('stop', openTag)); + if (!channel || !startMs || !stopMs) continue; + + out.push({ + channel, + start: startMs, + stop: stopMs, + title: inner('title', block) || 'Program', + desc: inner('desc', block), + }); + } + return out; +} diff --git a/web/manifest.webmanifest b/web/manifest.webmanifest new file mode 100644 index 0000000..fed1f09 --- /dev/null +++ b/web/manifest.webmanifest @@ -0,0 +1,17 @@ +{ + "name": "The Pondering Orb", + "short_name": "Pondering Orb", + "description": "A retro CRT-themed web TV — channel-surf live streams through a security-hardened relay.", + "id": "/", + "start_url": "/", + "scope": "/", + "display": "standalone", + "orientation": "landscape", + "background_color": "#050102", + "theme_color": "#e10000", + "icons": [ + { "src": "icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" }, + { "src": "icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" }, + { "src": "icons/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" } + ] +} diff --git a/web/memory.js b/web/memory.js new file mode 100644 index 0000000..54226cf --- /dev/null +++ b/web/memory.js @@ -0,0 +1,78 @@ +// memory.js — "The Oracle's Memory" (upgrade #5). +// +// Local-first persistence: session resurrection (last channel / volume / modes), +// per-channel rolling uptime history (feeds the guide reliability glyphs and +// auto-skip), and pinned channels. Everything in localStorage, namespaced. + +const NS = 'orb.'; +const K = { + settings: NS + 'settings', + health: NS + 'health', + pins: NS + 'pins', +}; +const HISTORY_DECAY = 0.85; // exponential weighting toward recent samples + +function read(key, fallback) { + try { const v = localStorage.getItem(key); return v ? JSON.parse(v) : fallback; } + catch { return fallback; } +} +function write(key, val) { + try { localStorage.setItem(key, JSON.stringify(val)); } catch { /* quota / private mode */ } +} + +class OracleMemory { + constructor() { + this.settings = read(K.settings, { + lastChannelId: null, + volume: 1, + muted: false, + modes: { theater: false, dim: false, ambient: false }, + }); + /** @type {Object} */ + this.health = read(K.health, {}); + this.pins = new Set(read(K.pins, [])); + } + + // ---- session resurrection ---- + get lastChannelId() { return this.settings.lastChannelId; } + rememberChannel(id) { this.settings.lastChannelId = id; this._saveSettings(); } + rememberVolume(volume, muted) { + this.settings.volume = volume; this.settings.muted = muted; this._saveSettings(); + } + rememberModes(modes) { this.settings.modes = { ...modes }; this._saveSettings(); } + _saveSettings() { write(K.settings, this.settings); } + + // ---- uptime history (fed by health probes) ---- + /** @param {string} id @param {'live'|'degraded'|'dead'} state */ + recordHealth(id, state) { + const ok = state === 'live' ? 1 : state === 'degraded' ? 0.5 : 0; + const prev = this.health[id]; + const score = prev ? prev.score * HISTORY_DECAY + ok * (1 - HISTORY_DECAY) : ok; + this.health[id] = { + score, + samples: (prev?.samples || 0) + 1, + last: state, + ts: Date.now(), + }; + this._healthDirty = true; + this._scheduleHealthSave(); + } + _scheduleHealthSave() { + if (this._healthT) return; + this._healthT = setTimeout(() => { this._healthT = 0; write(K.health, this.health); }, 1500); + } + /** @returns {{score:number,samples:number,last:string,ts:number}|null} */ + reliability(id) { return this.health[id] || null; } + isKnownDead(id) { return this.health[id]?.last === 'dead'; } + + // ---- pins ---- + isPinned(id) { return this.pins.has(id); } + togglePin(id) { + this.pins.has(id) ? this.pins.delete(id) : this.pins.add(id); + write(K.pins, [...this.pins]); + return this.pins.has(id); + } + pinned() { return [...this.pins]; } +} + +export const memory = new OracleMemory(); diff --git a/web/player.js b/web/player.js index 800924d..3b6784c 100644 --- a/web/player.js +++ b/web/player.js @@ -1,5 +1,7 @@ // player.js — HLS.js wiring, live-aware ghost controls, dead-stream handling. +import { memory } from './memory.js'; + const HLS_CONFIG = { enableWorker: true, lowLatencyMode: false, @@ -171,6 +173,7 @@ export class Player { const m = this.video.muted || this.video.volume === 0; this.els.btnMute.textContent = m ? '🔇' : '🔊'; this.els.btnMute.setAttribute('aria-pressed', String(m)); + memory.rememberVolume(this.video.volume, this.video.muted); } setVolume(delta) { this.video.muted = false; diff --git a/web/providers/iptv-org.js b/web/providers/iptv-org.js index 235ab8a..9941311 100644 --- a/web/providers/iptv-org.js +++ b/web/providers/iptv-org.js @@ -100,6 +100,7 @@ export class IptvOrgProvider extends SourceProvider { language: clip((c.languages && c.languages[0]) || ''), kind: 'live', streamUrls: playable, + probeUrls: urls, // raw https upstreams for the /probe endpoint guideId: c.id, }); } @@ -124,10 +125,9 @@ export class IptvOrgProvider extends SourceProvider { } /** - * EPG. Parses XMLTV with DOMParser (never innerHTML) into Program[]. - * Phase-1 stub: returns cached programs if an XMLTV feed has been provided via - * setEpgXml(); otherwise empty (guide still renders channel rows + now/next is - * simply blank until an EPG source is wired in Phase 1.5). + * EPG. Returns cached programs (populated by loadEpgXml via the off-thread + * worker). Empty until an XMLTV feed is loaded — the guide still renders + * channel rows; now/next is simply blank. */ async getPrograms(channelId, window) { const cached = this._epgCache.get(channelId); @@ -135,42 +135,41 @@ export class IptvOrgProvider extends SourceProvider { return cached.filter((p) => p.stop > window.from && p.start < window.to); } - /** Parse a raw XMLTV string and populate the EPG cache (safe: DOMParser). */ - setEpgXml(xmlString) { - const doc = new DOMParser().parseFromString(xmlString, 'application/xml'); - if (doc.querySelector('parsererror')) return; - // map xmltv channel id -> our namespaced id + /** + * Parse an XMLTV feed OFF the main thread and populate the EPG cache. + * @param {string} xmlString + * @returns {Promise} number of programmes indexed + */ + async loadEpgXml(xmlString) { + const programs = await this._parseInWorker(xmlString); const idMap = new Map((this._channels || []).map((c) => [c.guideId, c.id])); - for (const prog of doc.getElementsByTagName('programme')) { - const xmlCh = prog.getAttribute('channel'); - const cid = idMap.get(xmlCh); + let n = 0; + for (const p of programs) { + const cid = idMap.get(p.channel); if (!cid) continue; - const start = parseXmltvTime(prog.getAttribute('start')); - const stop = parseXmltvTime(prog.getAttribute('stop')); - if (!start || !stop) continue; - const titleEl = prog.getElementsByTagName('title')[0]; - const descEl = prog.getElementsByTagName('desc')[0]; const arr = this._epgCache.get(cid) || this._epgCache.set(cid, []).get(cid); - arr.push({ - channelId: cid, - title: clip(titleEl ? titleEl.textContent : 'Program'), - desc: clip(descEl ? descEl.textContent : ''), - start, stop, - }); + arr.push({ channelId: cid, title: clip(p.title), desc: clip(p.desc), start: p.start, stop: p.stop }); + n++; } + return n; } -} -/** XMLTV time: "20260615013000 +0000" → epoch ms. */ -function parseXmltvTime(s) { - if (!s) return 0; - const m = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})?\s*([+-]\d{4})?/.exec(s.trim()); - if (!m) return 0; - const [, Y, Mo, D, H, Mi, S, tz] = m; - let ms = Date.UTC(+Y, +Mo - 1, +D, +H, +Mi, +(S || 0)); - if (tz) { - const sign = tz[0] === '-' ? -1 : 1; - ms -= sign * ((+tz.slice(1, 3)) * 60 + (+tz.slice(3, 5))) * 60000; + _parseInWorker(xmlString) { + return new Promise((resolve, reject) => { + let worker; + try { + worker = new Worker(new URL('../epg-worker.js', import.meta.url), { type: 'module' }); + } catch (e) { + return reject(e); + } + const id = Math.random().toString(36).slice(2); + worker.onmessage = (e) => { + if (e.data?.id !== id) return; + worker.terminate(); + e.data.ok ? resolve(e.data.programs) : reject(new Error(e.data.error)); + }; + worker.onerror = (e) => { worker.terminate(); reject(e); }; + worker.postMessage({ id, xml: xmlString }); + }); } - return ms; } diff --git a/web/providers/mock.js b/web/providers/mock.js index c21ed29..f8e15e4 100644 --- a/web/providers/mock.js +++ b/web/providers/mock.js @@ -91,6 +91,7 @@ export class MockProvider extends SourceProvider { language: 'eng', kind: 'live', streamUrls: [TEST_STREAMS[c.stream]], + probeUrls: [TEST_STREAMS[c.stream]], guideId: `mock:${c.n}`, })); } diff --git a/web/providers/source-provider.js b/web/providers/source-provider.js index 4deeed8..ecd47ff 100644 --- a/web/providers/source-provider.js +++ b/web/providers/source-provider.js @@ -16,7 +16,8 @@ * @property {string} [country] * @property {string} [language] * @property {'live'|'vod'} kind Always 'live' for Phase 1; self-hosted "channels" are also 'live'. - * @property {string[]} streamUrls One or more upstream HLS URLs (primary + fallbacks). + * @property {string[]} streamUrls Playable HLS URLs (relay-wrapped where needed), primary + fallbacks. + * @property {string[]} [probeUrls] Raw upstream https URLs for the health prober (pre-relay). * @property {string} [guideId] Key used to match EPG/program data. */ diff --git a/web/styles.css b/web/styles.css index 228f642..7343bd7 100644 --- a/web/styles.css +++ b/web/styles.css @@ -158,6 +158,12 @@ img{display:block} .guide-chcell .num{color:var(--red);font-weight:bold;font-variant-numeric:tabular-nums;min-width:24px} .guide-chcell .nm{font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} .guide-chcell .skull{margin-left:auto;opacity:.55;font-size:12px} +.guide-chcell .pin{background:none;border:0;cursor:pointer;font-size:14px;line-height:1;padding:0 2px; + color:var(--ink-dim);margin-left:6px;flex:0 0 auto} +.guide-chcell .skull + .pin{margin-left:6px} +.guide-chcell .pin:not(.skull + .pin){margin-left:auto} +.guide-chcell .pin.on{color:var(--red);text-shadow:0 0 8px var(--red-glow)} +.guide-chcell .pin:hover{color:#fff} .guide-progs{position:relative;flex:1} .guide-prog{position:absolute;top:3px;bottom:3px;background:var(--panel-2);border:1px solid var(--line); border-radius:4px;padding:5px 8px;font-size:12px;overflow:hidden;cursor:pointer;white-space:nowrap;text-overflow:ellipsis} diff --git a/web/sw.js b/web/sw.js new file mode 100644 index 0000000..091ccb8 --- /dev/null +++ b/web/sw.js @@ -0,0 +1,86 @@ +// sw.js — service worker (upgrade #7). +// +// Two strategies: +// - app shell (html/css/js/hls.js/icons): cache-first → instant repeat loads, offline guide UI +// - iptv-org JSON proxied via the relay (…/relay?url=…/*.json): stale-while-revalidate +// → instant paint from cache, silent refresh in the background +// +// Live stream manifests + segments (the rest of /relay) and /probe, /metrics are +// NEVER cached — the relay marks them no-store and we bypass them here, so the SW +// is the sole freshness authority for metadata only. + +const SHELL = 'orb-shell-v1'; +const DATA = 'orb-data-v1'; + +const SHELL_ASSETS = [ + '/', '/index.html', '/styles.css', + '/app.js', '/player.js', '/zapper.js', '/guide.js', '/ambient.js', + '/lexicon.js', '/memory.js', '/health.js', '/epg-worker.js', + '/lib/hls.min.js', '/lib/xmltv-parse.js', + '/providers/source-provider.js', '/providers/mock.js', '/providers/iptv-org.js', + '/manifest.webmanifest', '/icons/icon-192.png', '/icons/icon-512.png', +]; + +self.addEventListener('install', (e) => { + e.waitUntil(caches.open(SHELL).then((c) => c.addAll(SHELL_ASSETS)).then(() => self.skipWaiting())); +}); + +self.addEventListener('activate', (e) => { + e.waitUntil( + caches.keys() + .then((keys) => Promise.all(keys.filter((k) => ![SHELL, DATA].includes(k)).map((k) => caches.delete(k)))) + .then(() => self.clients.claim()), + ); +}); + +self.addEventListener('fetch', (e) => { + const req = e.request; + if (req.method !== 'GET') return; + const url = new URL(req.url); + if (url.origin !== self.location.origin) return; // same-origin only + + if (url.pathname === '/probe' || url.pathname === '/metrics') return; + + if (url.pathname === '/relay') { + const upstream = url.searchParams.get('url') || ''; + // Only the JSON metadata is cacheable; stream manifests/segments are not. + if (/\.json(\?|$)/i.test(upstream)) { + e.respondWith(staleWhileRevalidate(req, DATA)); + } + return; // streams/segments → straight to the relay, uncached + } + + // App shell / static assets → cache-first. + if (SHELL_ASSETS.includes(url.pathname) + || url.pathname.startsWith('/icons/') + || url.pathname.startsWith('/providers/') + || url.pathname.startsWith('/lib/')) { + e.respondWith(cacheFirst(req, SHELL)); + } +}); + +async function cacheFirst(req, cacheName) { + const cache = await caches.open(cacheName); + const hit = await cache.match(req); + if (hit) return hit; + try { + const res = await fetch(req); + if (res.ok) cache.put(req, res.clone()); + return res; + } catch { + if (req.mode === 'navigate') { + const idx = await cache.match('/index.html'); + if (idx) return idx; + } + return new Response('offline', { status: 503, statusText: 'offline' }); + } +} + +async function staleWhileRevalidate(req, cacheName) { + const cache = await caches.open(cacheName); + const hit = await cache.match(req); + const network = fetch(req) + .then((res) => { if (res.ok) cache.put(req, res.clone()); return res; }) + .catch(() => hit || new Response('offline', { status: 503 })); + return hit || network; +} diff --git a/web/zapper.js b/web/zapper.js index 5e97efe..e520e93 100644 --- a/web/zapper.js +++ b/web/zapper.js @@ -11,11 +11,14 @@ export class Zapper { * @param {object} els * @param {import('./player.js').Player} player * @param {import('./providers/source-provider.js').ChannelAggregator} agg + * @param {{memory?:any, health?:import('./health.js').Health}} [opts] */ - constructor(els, player, agg) { + constructor(els, player, agg, opts = {}) { this.els = els; this.player = player; this.agg = agg; + this.memory = opts.memory || null; + this.health = opts.health || null; this.current = null; // current Channel this.previous = null; // for last-channel toggle this._entry = ''; @@ -38,9 +41,16 @@ export class Zapper { async tuneToIndexOffset(delta) { const list = this.agg.channels; if (!list.length) return; - let idx = this.current ? list.findIndex((c) => c.id === this.current.id) : -1; - idx = (idx + delta + list.length) % list.length; - return this.tune(list[idx]); + const start = this.current ? list.findIndex((c) => c.id === this.current.id) : -1; + let idx = start; + // Step in the requested direction, skipping channels the Oracle knows are dead. + for (let n = 0; n < list.length; n++) { + idx = (idx + delta + list.length) % list.length; + const ch = list[idx]; + if (!this.health || !this.health.isKnownDead(ch.id)) return this.tune(ch); + } + // everything known-dead → just tune the immediate neighbour + return this.tune(list[(start + delta + list.length) % list.length]); } async tuneLast() { if (this.previous) return this.tune(this.previous); } @@ -50,6 +60,8 @@ export class Zapper { if (!ch) return; if (this.current && this.current.id !== ch.id) this.previous = this.current; this.current = ch; + if (this.memory) this.memory.rememberChannel(ch.id); + if (this.health) this.health.probe(ch); // refresh this channel's reliability this._showStatic(); this._safetyClear = setTimeout(() => this._clearStatic(), STATIC_MAX);