From d59397d4146ffa23adbbe6dc99c64ebb22a93b2d Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Sat, 1 Aug 2026 22:44:19 -0300 Subject: add vanilla DOM web backend --- build.zig | 308 +++---- build/snap.zig | 12 +- docs/design.pdf | 1556 +++++++++++++++++---------------- docs/design.typ | 34 +- docs/ideas.typ | 2 - docs/web.md | 49 ++ src/dump.zig | 6 +- src/web.zig | 481 ++++++++++ src/web/app.mjs | 436 +++++++++ src/web/index.html | 17 + src/web/libc.c | 152 ++++ src/web/libc/include/assert.h | 14 + src/web/libc/include/ctype.h | 7 + src/web/libc/include/endian.h | 21 + src/web/libc/include/inttypes.h | 8 + src/web/libc/include/limits.h | 9 + src/web/libc/include/stdio.h | 19 + src/web/libc/include/stdlib.h | 16 + src/web/libc/include/string.h | 17 + src/web/libc/include/wchar.h | 9 + src/web/libc/include/wctype.h | 18 + src/web/pardes.css | 91 ++ src/web/zstbi.zig | 30 + test/web-snapshots/README.md | 7 +- test/web-snapshots/source-list.golden | 306 +++---- test/web_harness.mjs | 136 +++ test/web_snapshot.mjs | 41 +- 27 files changed, 2634 insertions(+), 1168 deletions(-) create mode 100644 docs/web.md create mode 100644 src/web.zig create mode 100644 src/web/app.mjs create mode 100644 src/web/index.html create mode 100644 src/web/libc.c create mode 100644 src/web/libc/include/assert.h create mode 100644 src/web/libc/include/ctype.h create mode 100644 src/web/libc/include/endian.h create mode 100644 src/web/libc/include/inttypes.h create mode 100644 src/web/libc/include/limits.h create mode 100644 src/web/libc/include/stdio.h create mode 100644 src/web/libc/include/stdlib.h create mode 100644 src/web/libc/include/string.h create mode 100644 src/web/libc/include/wchar.h create mode 100644 src/web/libc/include/wctype.h create mode 100644 src/web/pardes.css create mode 100644 src/web/zstbi.zig create mode 100644 test/web_harness.mjs diff --git a/build.zig b/build.zig index 781cc848..b089a9c9 100644 --- a/build.zig +++ b/build.zig @@ -9,7 +9,6 @@ pub const Platform = enum { tty, gui, web }; /// which fails on a fetched package that has no .git) and to `SPC l i`. const zls_version = "0.16.1-dev+3e0d0820"; pub const TreeSitterGrammars = enum { disabled, zig, minimal, full }; -const GhosttyArtifact = enum { ghostty, lib }; pub fn build(b: *std.Build) void { // Default target is the Steam Deck (deckcap's trick): x86_64 linux-gnu @@ -27,10 +26,10 @@ pub fn build(b: *std.Build) void { const platform = b.option(Platform, "platform", "which shell to build (tty, gui, web)") orelse .tty; const static = b.option(bool, "static", "statically link") orelse false; const dump_path = b.option([]const u8, "dump", "dump .zon embedded into the web shell (-Dplatform=web)"); - const emcc_path = b.option([]const u8, "emcc", "emcc for the web shell's final link") orelse "/usr/lib/emscripten/emcc"; - const is_emscripten = target.result.os.tag == .emscripten; + const is_web = platform == .web; + const is_web_target = target.result.cpu.arch == .wasm32 and target.result.os.tag == .freestanding; // wasm: size is the budget - const optimize = if (is_emscripten) .ReleaseSmall else requested_optimize; + const optimize = if (is_web) .ReleaseSmall else requested_optimize; // The vendored C is never what we are debugging, and at -O0 it dominates // the app: 90% of a Debug startup is tree-sitter's query analyser // (perf: ts_query__perform_analysis + ts_lookahead_iterator__next), and @@ -38,12 +37,16 @@ pub fn build(b: *std.Build) void { // mode takes a Debug boot from ~710ms to ~210ms — the same treatment // ghostty's simdutf/highway already get here. Zig code keeps its mode. const c_optimize: std.builtin.OptimizeMode = if (optimize == .Debug) .ReleaseFast else optimize; - const default_grammars: TreeSitterGrammars = if (is_emscripten) .zig else .full; + // The browser keeps its useful default grammar without acquiring a host + // libc contract: Tree-sitter and the generated Zig parser are linked into + // the freestanding module against src/web/libc's tiny in-module shim. + const default_grammars: TreeSitterGrammars = if (is_web) .zig else .full; const tree_sitter_grammars = b.option(TreeSitterGrammars, "tree-sitter", "tree-sitter grammar set: disabled, zig, minimal (c/c++/zig), full") orelse default_grammars; const tracy = b.option([]const u8, "tracy", "enable Tracy profiling; supply the path to a Tracy source checkout"); - // the browser shell: zig object + emcc link + html, installed to zig-out/web - const web_step = b.step("web", "build the browser shell into zig-out/web (-Dplatform=web -Dtarget=wasm32-emscripten -Ddump=)"); + // The browser shell is a freestanding wasm core plus ordinary web files. + // JavaScript owns the loop and IO; HTML/CSS own rendering. + const web_step = b.step("web", "build the DOM browser shell into zig-out/web (-Dplatform=web -Dtarget=wasm32-freestanding -Ddump=)"); // Web LOOK has a tiny read-only source filesystem. Generate one Zig module // on the host from every tracked .zig path + its current working-tree @@ -68,30 +71,9 @@ pub fn build(b: *std.Build) void { snap_build.addWeb(b); - const emscripten_sysroot = if (is_emscripten) detectEmscriptenSysroot(b) else null; - if (platform == .web and !is_emscripten) return failBuild(b, web_step, "-Dplatform=web requires -Dtarget=wasm32-emscripten"); - if (platform != .web and is_emscripten) return failBuild(b, web_step, "-Dtarget=wasm32-emscripten requires -Dplatform=web"); + if (is_web and !is_web_target) return failBuild(b, web_step, "-Dplatform=web requires -Dtarget=wasm32-freestanding"); + if (!is_web and (is_web_target or target.result.os.tag == .emscripten)) return failBuild(b, web_step, "wasm browser targets require -Dplatform=web"); if (platform == .web and dump_path == null) return failBuild(b, web_step, "-Dplatform=web requires -Ddump= (the browser has no ptys; state replays from an embedded dump)"); - if (platform == .web and emscripten_sysroot == null) return failBuild(b, web_step, "no emscripten sysroot found; pass --sysroot /sysroot or set EM_CACHE/EMSDK"); - - // emscripten "libc": point zig at the sysroot headers/crt via a libc.txt - // (the prototype's WriteFiles trick) — applied to EVERY compile step. - const libc_file: ?std.Build.LazyPath = if (emscripten_sysroot) |sysroot| blk: { - const files = b.addWriteFiles(); - break :blk files.add("emscripten-libc.txt", b.fmt( - \\include_dir={s}/include - \\sys_include_dir={s}/include - \\crt_dir={s}/lib/wasm32-emscripten - \\msvc_lib_dir= - \\kernel32_lib_dir= - \\gcc_dir= - \\ - , .{ sysroot, sysroot, sysroot })); - } else null; - const emscripten_include: ?std.Build.LazyPath = if (emscripten_sysroot) |sysroot| - .{ .cwd_relative = b.pathJoin(&.{ sysroot, "include" }) } - else - null; // build-time IO: slurps the grammars' highlights.scm queries, and reads // vendor/themes to find the theme sources @@ -102,8 +84,8 @@ pub fn build(b: *std.Build) void { const root_mod = b.createModule(.{ .target = target, .optimize = optimize, - .root_source_file = b.path("src/main.zig"), - .link_libc = true, + .root_source_file = b.path(if (is_web) "src/web.zig" else "src/main.zig"), + .link_libc = !is_web, }); // helix differential harness (test/hxdiff.zig): a second compilation of // the sans-IO core, driven headlessly. Mirrors root_mod's wiring for @@ -150,19 +132,16 @@ pub fn build(b: *std.Build) void { root_mod.addImport("generated_themes", themes_mod); hx_core_mod.addImport("generated_themes", themes_mod); - // static archives the emcc link needs beyond the zig object (grammars, SDL) - var wasm_libs: std.ArrayList(std.Build.LazyPath) = .empty; - // forkpty: in libc proper on glibc>=2.34 and darwin; the BSDs keep it in libutil if (target.result.os.tag == .freebsd or target.result.os.tag == .netbsd or target.result.os.tag == .openbsd) root_mod.linkSystemLibrary("util", .{}); // The language backend (src/lsp/lsp_zls.zig) links ZLS as a MODULE — no zls // binary, no JSON-RPC, no protocol. Everything except the browser gets it; - // emscripten does not, because the web shell has no threads and no-ops the + // the web shell does not, because it has no threads and no-ops the // lsp effect anyway, so paying to compile an analyser it can never call // would be pure wasm. - const zls_backend = !is_emscripten; + const zls_backend = !is_web; const opts = b.addOptions(); opts.addOption(Platform, "platform", platform); @@ -236,16 +215,26 @@ pub fn build(b: *std.Build) void { // ts_queries options module (codegen consumed by comptime in syntax.zig). if (tree_sitter_grammars != .disabled) { const tree_sitter_mod = b.dependency("tree_sitter", .{ .target = target, .optimize = c_optimize }).module("tree_sitter"); - // the C runtime rides the module as a static lib; give it the wasm - // libc and hand its archive to the emcc link - if (is_emscripten) { + if (is_web) { + // zig-tree-sitter carries its C runtime as a linked static library. + // Retarget that library away from libc and put the compatibility + // headers before any unavailable freestanding system headers. + const web_libc_include: std.Build.LazyPath = .{ + .cwd_relative = b.path("src/web/libc/include").getPath(b), + }; for (tree_sitter_mod.link_objects.items) |link_object| switch (link_object) { .other_step => |lib| { - lib.setLibCFile(libc_file.?); - wasm_libs.append(b.allocator, lib.getEmittedBin()) catch @panic("OOM"); + lib.root_module.link_libc = false; + lib.root_module.addIncludePath(web_libc_include); + lib.root_module.addCMacro("NDEBUG", "1"); }, else => {}, }; + root_mod.addIncludePath(b.path("src/web/libc/include")); + root_mod.addCSourceFile(.{ + .file = b.path("src/web/libc.c"), + .flags = &.{ "-std=c11", "-DNDEBUG=1" }, + }); } root_mod.addImport("tree-sitter", tree_sitter_mod); hx_core_mod.addImport("tree-sitter", tree_sitter_mod); @@ -299,10 +288,9 @@ pub fn build(b: *std.Build) void { const lib = b.addLibrary(.{ .name = "tree-sitter-" ++ g.name, - .root_module = b.createModule(.{ .target = target, .optimize = c_optimize, .link_libc = true }), + .root_module = b.createModule(.{ .target = target, .optimize = c_optimize, .link_libc = !is_web }), .linkage = .static, }); - if (libc_file) |f| lib.setLibCFile(f); // grammars declare external_scanner_create() with EMPTY PARENS // (a K&R non-prototype, not (void)): under clang's // -fsanitize=function the callee's type hash differs from the @@ -315,19 +303,26 @@ pub fn build(b: *std.Build) void { lib.root_module.addCSourceFile(.{ .file = dep.path(g.src ++ "/parser.c"), .flags = &ts_cflags }); if (g.scanner) lib.root_module.addCSourceFile(.{ .file = dep.path(g.src ++ "/scanner.c"), .flags = &ts_cflags }); lib.root_module.addIncludePath(dep.path(g.src)); + if (is_web) lib.root_module.addIncludePath(b.path("src/web/libc/include")); root_mod.linkLibrary(lib); hx_core_mod.linkLibrary(lib); - if (is_emscripten) wasm_libs.append(b.allocator, lib.getEmittedBin()) catch @panic("OOM"); } } root_mod.addOptions("ts_queries", ts_queries); hx_core_mod.addOptions("ts_queries", ts_queries); } - // zstbi (C stb_image): image pane decode. zigimg crashes the 0.16 compiler. - const zstbi_dep = b.dependency("zstbi", .{ .target = target, .optimize = c_optimize }); - root_mod.addImport("zstbi", zstbi_dep.module("root")); - hx_core_mod.addImport("zstbi", zstbi_dep.module("root")); + // zstbi (C stb_image): image pane decode. The freestanding core has no C + // allocator ABI, so its module is a compatible no-decode shim; browser IO + // can grow native image decoding independently of the core. + const zstbi_dep = if (!is_web) b.dependency("zstbi", .{ .target = target, .optimize = c_optimize }) else null; + const zstbi_mod = if (zstbi_dep) |dep| dep.module("root") else b.createModule(.{ + .target = target, + .optimize = optimize, + .root_source_file = b.path("src/web/zstbi.zig"), + }); + root_mod.addImport("zstbi", zstbi_mod); + hx_core_mod.addImport("zstbi", zstbi_mod); // mvzr: the regex engine behind `s` / `S` (helix select/split on a regex). // A bytecode VM that compiles a RUNTIME pattern into a fixed-size struct @@ -353,11 +348,11 @@ pub fn build(b: *std.Build) void { .tables_path = uucode_tables, }).module("uucode"); - const vaxis_mod = b.dependency("vaxis", .{ + const vaxis_mod: ?*std.Build.Module = if (!is_web) b.dependency("vaxis", .{ .target = target, .optimize = optimize, .external_uucode = true, - }).module("vaxis"); + }).module("vaxis") else null; var ghostty_vt_for_snap: ?*std.Build.Module = null; // ghostty's simd libs (simdutf/highway, C++) locate the Apple SDK via @@ -379,7 +374,7 @@ pub fn build(b: *std.Build) void { // without it); gate that block on `b.graph.host.result.os.tag == .linux`. // Ghostty's pinned translate-c tarball also 404s now (codeberg dropped // the archive endpoint) — seed zig-pkg/ from a machine that has it. - const ghostty_simd = !target.result.os.tag.isDarwin() or b.graph.host.result.os.tag.isDarwin(); + const ghostty_simd = !is_web and (!target.result.os.tag.isDarwin() or b.graph.host.result.os.tag.isDarwin()); // app-runtime none + emit-xcframework off: only the ghostty-vt module is // consumed, and the defaults otherwise drag ghostty's app graph into the // build — gtk4 header translation via host pkg-config for linux targets, @@ -394,39 +389,19 @@ pub fn build(b: *std.Build) void { // own safety checks come from OUR optimize mode and are unaffected, since // ghostty-vt is a module compiled into this binary. See reflow.snap. const ghostty_optimize: std.builtin.OptimizeMode = if (optimize == .Debug) .ReleaseSafe else optimize; - const ghostty_dep = if (is_emscripten) - b.lazyDependency("ghostty", .{ .simd = false }) - else - b.lazyDependency("ghostty", .{ .target = target, .optimize = ghostty_optimize, .simd = ghostty_simd, .@"app-runtime" = .none, .@"emit-xcframework" = false }); + const ghostty_dep = b.lazyDependency("ghostty", .{ .target = target, .optimize = ghostty_optimize, .simd = ghostty_simd, .@"app-runtime" = .none, .@"emit-xcframework" = false }); if (ghostty_dep) |dep| { const ghostty_vt = dep.module("ghostty-vt"); ghostty_vt_for_snap = ghostty_vt; ghostty_vt.addImport("uucode", uucode_mod); - // emscripten: hand ghostty-vt the terminal_options module its build() - // would otherwise provide (copied verbatim from the prototype build) - if (is_emscripten) { - const term_opts = b.addOptions(); - term_opts.addOption(GhosttyArtifact, "artifact", .lib); - term_opts.addOption(bool, "c_abi", false); - term_opts.addOption(bool, "oniguruma", false); - term_opts.addOption(bool, "simd", false); - term_opts.addOption(bool, "slow_runtime_safety", false); - term_opts.addOption(bool, "kitty_graphics", false); - term_opts.addOption(bool, "tmux_control_mode", false); - term_opts.addOption([]const u8, "version_string", "0.0.0"); - term_opts.addOption(usize, "version_major", 0); - term_opts.addOption(usize, "version_minor", 0); - term_opts.addOption(usize, "version_patch", 0); - term_opts.addOption(?[]const u8, "version_pre", null); - term_opts.addOption(?[]const u8, "version_build", null); - ghostty_vt.addOptions("terminal_options", term_opts); - } root_mod.addImport("ghostty-vt", ghostty_vt); hx_core_mod.addImport("ghostty-vt", ghostty_vt); } // override uucode on vaxis LAST so it wins over ghostty's build() wiring. - vaxis_mod.addImport("uucode", uucode_mod); - root_mod.addImport("vaxis", vaxis_mod); + if (vaxis_mod) |vaxis| { + vaxis.addImport("uucode", uucode_mod); + root_mod.addImport("vaxis", vaxis); + } root_mod.addImport("uucode", uucode_mod); hx_core_mod.addImport("uucode", uucode_mod); @@ -467,29 +442,22 @@ pub fn build(b: *std.Build) void { root_mod.addOptions("pardes_config", opts); hx_core_mod.addOptions("pardes_config", opts); - // SDL3 shell wiring (-Dplatform=gui and web). The sdl package builds SDL3 + // SDL3 shell wiring (-Dplatform=gui). The sdl package builds SDL3 // from source as a static lib + emits the SDL3/ headers; gui.zig @cImports // those, plus a small stb_truetype C shim for the glyph atlas, and embeds - // the SPIR-V compiled at build time from shaders/*.glsl — or, on web, the - // GL ES shader sources compiled at runtime by WebGL. - if (platform == .gui or platform == .web) { + // the SPIR-V compiled at build time from shaders/*.glsl. + if (platform == .gui) { // sanitize_c MUST stay off: zig cc's UBSan (on for C in Debug AND // ReleaseSafe) traps hidapi's mismatched fn-pointer calls the moment // a HID gamepad is enumerated — SDL_Init SIGILLs on the deck itself // (ud2 in SDL_hid_set_nonblocking_REAL); headless boxes never see it. // SDL3 always statically linked (like deckcap): the gui binary must // only need system libc/libm — never a shared libSDL3. - const sdl_dep = if (emscripten_include) |include| - b.lazyDependency("sdl", .{ .target = target, .optimize = optimize, .sanitize_c = .off, .preferred_linkage = .static, .system_include_path = include }) - else - b.lazyDependency("sdl", .{ .target = target, .optimize = optimize, .sanitize_c = .off, .preferred_linkage = .static }); + const sdl_dep = b.lazyDependency("sdl", .{ .target = target, .optimize = optimize, .sanitize_c = .off, .preferred_linkage = .static }); if (sdl_dep) |dep| { const sdl_lib = dep.artifact("SDL3"); - if (libc_file) |f| sdl_lib.setLibCFile(f); root_mod.linkLibrary(sdl_lib); root_mod.addIncludePath(dep.path("include")); - if (emscripten_include) |include| root_mod.addSystemIncludePath(include); - if (is_emscripten) wasm_libs.append(b.allocator, sdl_lib.getEmittedBin()) catch @panic("OOM"); } // darwin: SDL_GPU only speaks SPIRV here (shaders/*.glsl -> glslc), so // it must pick its vulkan backend via the Vulkan SDK's loader + @@ -505,71 +473,56 @@ pub fn build(b: *std.Build) void { root_mod.addAnonymousImport("AdwaitaMono-Regular.ttf", .{ .root_source_file = b.path("assets/AdwaitaMono-Regular.ttf"), }); - if (platform == .web) { - root_mod.addAnonymousImport("ui.vert.es.glsl", .{ .root_source_file = b.path("shaders/ui.vert.es.glsl") }); - root_mod.addAnonymousImport("ui.frag.es.glsl", .{ .root_source_file = b.path("shaders/ui.frag.es.glsl") }); - root_mod.addAnonymousImport("overlay.vert.es.glsl", .{ .root_source_file = b.path("shaders/overlay.vert.es.glsl") }); - root_mod.addAnonymousImport("overlay.frag.es.glsl", .{ .root_source_file = b.path("shaders/overlay.frag.es.glsl") }); - const dp = dump_path.?; - root_mod.addAnonymousImport("embedded.dump.zon", .{ - .root_source_file = if (std.fs.path.isAbsolute(dp)) .{ .cwd_relative = dp } else b.path(dp), - }); - root_mod.addAnonymousImport("embedded_sources", .{ .root_source_file = embedded_sources }); - } else { - root_mod.addAnonymousImport("ui.vert.spv", .{ - .root_source_file = compileGlsl(b, "shaders/ui.vert.glsl", "vertex", "ui.vert.spv"), - }); - root_mod.addAnonymousImport("ui.frag.spv", .{ - .root_source_file = compileGlsl(b, "shaders/ui.frag.glsl", "fragment", "ui.frag.spv"), - }); - root_mod.addAnonymousImport("overlay.vert.spv", .{ - .root_source_file = compileGlsl(b, "shaders/overlay.vert.glsl", "vertex", "overlay.vert.spv"), - }); - root_mod.addAnonymousImport("overlay.frag.spv", .{ - .root_source_file = compileGlsl(b, "shaders/overlay.frag.glsl", "fragment", "overlay.frag.spv"), - }); - root_mod.addAnonymousImport("crt.vert.spv", .{ - .root_source_file = compileGlsl(b, "shaders/crt.vert.glsl", "vertex", "crt.vert.spv"), - }); - root_mod.addAnonymousImport("crt.frag.spv", .{ - .root_source_file = compileGlsl(b, "shaders/crt.frag.glsl", "fragment", "crt.frag.spv"), - }); - } + root_mod.addAnonymousImport("ui.vert.spv", .{ + .root_source_file = compileGlsl(b, "shaders/ui.vert.glsl", "vertex", "ui.vert.spv"), + }); + root_mod.addAnonymousImport("ui.frag.spv", .{ + .root_source_file = compileGlsl(b, "shaders/ui.frag.glsl", "fragment", "ui.frag.spv"), + }); + root_mod.addAnonymousImport("overlay.vert.spv", .{ + .root_source_file = compileGlsl(b, "shaders/overlay.vert.glsl", "vertex", "overlay.vert.spv"), + }); + root_mod.addAnonymousImport("overlay.frag.spv", .{ + .root_source_file = compileGlsl(b, "shaders/overlay.frag.glsl", "fragment", "overlay.frag.spv"), + }); + root_mod.addAnonymousImport("crt.vert.spv", .{ + .root_source_file = compileGlsl(b, "shaders/crt.vert.glsl", "vertex", "crt.vert.spv"), + }); + root_mod.addAnonymousImport("crt.frag.spv", .{ + .root_source_file = compileGlsl(b, "shaders/crt.frag.glsl", "fragment", "crt.frag.spv"), + }); } - if (platform == .web) { - // zig emits an object; emcc does the final link (wasm + js glue), - // compiling the C shims itself and pulling in every static archive. - const obj = b.addObject(.{ .name = "pardes", .root_module = root_mod }); - obj.setLibCFile(libc_file.?); - - const emcc = b.addSystemCommand(&.{emcc_path}); - emcc.addFileArg(obj.getEmittedBinDirectory().path(b, "pardes_zcu.o")); - emcc.addFileArg(obj.getEmittedBin()); - emcc.addFileArg(b.path("vendor/stb/stb_truetype_impl.c")); - emcc.addFileArg(b.path("vendor/stb/font.c")); - emcc.addFileArg(zstbi_dep.path("src/zstbi.c")); - for (wasm_libs.items) |lib| emcc.addFileArg(lib); - emcc.addPrefixedDirectoryArg("-I", b.path("vendor/stb")); - emcc.addPrefixedDirectoryArg("-I", zstbi_dep.path("libs/stbi")); - emcc.addArgs(&.{ - "-std=c99", - "-fno-sanitize=undefined", - "-Oz", - "-sINITIAL_MEMORY=1073741824", // the 512 MiB web heap + code/stack - "-sEXIT_RUNTIME=0", // run() returns; the rAF loop keeps living - "-sFULL_ES3=1", - "-sMIN_WEBGL_VERSION=2", - "-sMAX_WEBGL_VERSION=2", - "-sINCOMING_MODULE_JS_API=canvas", - "-sEXPORTED_FUNCTIONS=['_main','_pardes_web_test_cols','_pardes_web_test_rows','_pardes_web_test_cursor_x','_pardes_web_test_cursor_y','_pardes_web_test_cell','_pardes_web_test_cell_fg','_pardes_web_test_cell_bg','_pardes_web_test_cell_attrs','_pardes_web_test_cell_x','_pardes_web_test_cell_y']", - "-o", + if (is_web) { + const dp = dump_path.?; + root_mod.addAnonymousImport("embedded.dump.zon", .{ + .root_source_file = if (std.fs.path.isAbsolute(dp)) .{ .cwd_relative = dp } else b.path(dp), }); - const js = emcc.addOutputFileArg("pardes.js"); - web_step.dependOn(&b.addInstallFileWithDir(js, .{ .custom = "web" }, "pardes.js").step); - web_step.dependOn(&b.addInstallFileWithDir(js.dirname().path(b, "pardes.wasm"), .{ .custom = "web" }, "pardes.wasm").step); - const html = b.addWriteFiles().add("index.html", html_shell); - web_step.dependOn(&b.addInstallFileWithDir(html, .{ .custom = "web" }, "index.html").step); + root_mod.addAnonymousImport("embedded_sources", .{ .root_source_file = embedded_sources }); + } + + if (platform == .web) { + const wasm = b.addExecutable(.{ .name = "pardes", .root_module = root_mod }); + wasm.entry = .disabled; + wasm.rdynamic = true; + wasm.export_memory = true; + // The full grammar tier carries ~48 MiB of generated parse tables. + // Keep the compact default at 32 MiB, but leave enough static address + // space for an explicitly requested all-language build to link. + wasm.initial_memory = @as(u64, if (tree_sitter_grammars == .full) 64 else 32) * 1024 * 1024; + wasm.max_memory = 512 * 1024 * 1024; + web_step.dependOn(&b.addInstallFileWithDir(wasm.getEmittedBin(), .{ .custom = "web" }, "pardes.wasm").step); + inline for (.{ + .{ "src/web/index.html", "index.html" }, + .{ "src/web/app.mjs", "app.mjs" }, + .{ "src/web/pardes.css", "pardes.css" }, + .{ "assets/AdwaitaMono-Regular.ttf", "AdwaitaMono-Regular.ttf" }, + }) |file| web_step.dependOn(&b.addInstallFileWithDir(b.path(file[0]), .{ .custom = "web" }, file[1]).step); + + const run_web_harness = b.addSystemCommand(&.{ "node", "test/web_harness.mjs" }); + run_web_harness.addArg(b.getInstallPath(.{ .custom = "web" }, "")); + run_web_harness.step.dependOn(web_step); + b.step("web-harness", "run the dependency-free JS/WASM DOM harness").dependOn(&run_web_harness.step); b.getInstallStep().dependOn(web_step); } else { // binary name: the native-shaped linux-x86_64 tty build stays `pardes` @@ -587,7 +540,7 @@ pub fn build(b: *std.Build) void { b.installArtifact(exe); const run = b.addRunArtifact(exe); b.step("run", "descend to the pardes").dependOn(&run.step); - web_step.dependOn(&b.addFail("web needs -Dplatform=web -Dtarget=wasm32-emscripten -Ddump=").step); + web_step.dependOn(&b.addFail("web needs -Dplatform=web -Dtarget=wasm32-freestanding -Ddump=").step); // snapshot parity suite: scripted input traces in a pty, captured grids // diffed against the goldens in snapshots/ — the frozen record of parity @@ -736,45 +689,6 @@ pub fn build(b: *std.Build) void { } } -// the html shell: a full-viewport canvas wired into Module (from the prototype) -const html_shell = - \\ - \\ - \\ - \\ - \\ - \\ pardes - \\ - \\ - \\ - \\ - \\ - \\ - \\ - \\ -; - // a bad -D combination: fail both `zig build` and `zig build web` with the why fn failBuild(b: *std.Build, web_step: *std.Build.Step, msg: []const u8) void { const fail = &b.addFail(msg).step; @@ -812,17 +726,3 @@ fn vendoredThemes(b: *std.Build, io: std.Io) []const []const u8 { }.lt); return names.items; } - -fn detectEmscriptenSysroot(b: *std.Build) ?[]const u8 { - if (b.option([]const u8, "emscripten-sysroot", "path to the Emscripten sysroot")) |path| return path; - if (b.sysroot) |path| return path; - if (envPath(b, "EMSCRIPTEN_SYSROOT")) |path| return path; - if (envPath(b, "EM_CACHE")) |cache| return b.pathJoin(&.{ cache, "sysroot" }); - if (envPath(b, "EMSDK")) |emsdk| return b.pathJoin(&.{ emsdk, "upstream", "emscripten", "cache", "sysroot" }); - if (envPath(b, "HOME")) |home| return b.pathJoin(&.{ home, ".cache", "emscripten", "sysroot" }); - return null; -} - -fn envPath(b: *std.Build, name: []const u8) ?[]const u8 { - return b.graph.environ_map.get(name); -} diff --git a/build/snap.zig b/build/snap.zig index a721f483..2c135fef 100644 --- a/build/snap.zig +++ b/build/snap.zig @@ -39,18 +39,17 @@ pub fn addTty(b: *std.Build, opts: struct { b.step("snap", "run the snapshot parity suite (-- --update regenerates goldens)").dependOn(&run_snap.step); } -/// Browser regression suite: make an isolated web build from the real TTY dump -/// captured after running `git ls-files '*.zig'`, with the Zig-only tree-sitter -/// tier. The dependency-free CDP harness then drives its .snap script through -/// real Chromium touch events. This recursive build selects `web`, not -/// `web-snap`, so it bottoms out after one level. +/// Browser regression suite: make an isolated freestanding web build from the +/// real TTY dump captured after running `git ls-files '*.zig'`. The +/// dependency-free Chrome/CDP driver then exercises real DOM pointer events. +/// This recursive build selects `web`, not `web-snap`, so it bottoms out. pub fn addWeb(b: *std.Build) void { const build_web_snap = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "web", "-Dplatform=web", - "-Dtarget=wasm32-emscripten", + "-Dtarget=wasm32-freestanding", "-Dtree-sitter=zig", "-Ddump=test/web-snapshots/source-list.dump.zon", "-p", @@ -67,4 +66,5 @@ pub fn addWeb(b: *std.Build) void { run_web_snap.step.dependOn(&build_web_snap.step); if (b.args) |args| run_web_snap.addArgs(args); b.step("web-snap", "run browser touch/LOOK snapshots (-- --update regenerates goldens)").dependOn(&run_web_snap.step); + b.step("web-e2e", "run the Chrome-driven DOM end-to-end suite").dependOn(&run_web_snap.step); } diff --git a/docs/design.pdf b/docs/design.pdf index 0022972b..83f97dc2 100644 --- a/docs/design.pdf +++ b/docs/design.pdf @@ -2,340 +2,340 @@ %€€€€ 1 0 obj -<> +<> endobj 2 0 obj -<> +<> endobj 3 0 obj -<> +<> endobj 4 0 obj -<> +<> endobj 5 0 obj -<> +<> endobj 6 0 obj -<> +<> endobj 7 0 obj -<> +<> endobj 8 0 obj -<> +<> endobj 9 0 obj -<> +<> endobj 10 0 obj -<> +<> endobj 11 0 obj -<> +<>/K[225 0 R]/ParentTree<>/ParentTreeNextKey 5>> endobj 12 0 obj -<>/K[214 0 R]/ParentTree<>/ParentTreeNextKey 4>> +[17 0 R 19 0 R 20 0 R 21 0 R 21 0 R 21 0 R 21 0 R 22 0 R 22 0 R 22 0 R 22 0 R 23 0 R 25 0 R 24 0 R 25 0 R 25 0 R 25 0 R 26 0 R 30 0 R 28 0 R 30 0 R 29 0 R 30 0 R 32 0 R 34 0 R 34 0 R 34 0 R 40 0 R 37 0 R 40 0 R 40 0 R 40 0 R 38 0 R 40 0 R 40 0 R 40 0 R 39 0 R 40 0 R 41 0 R 42 0 R 50 0 R 43 0 R 50 0 R 44 0 R 50 0 R 45 0 R 50 0 R 46 0 R 50 0 R 47 0 R 50 0 R 48 0 R 50 0 R 49 0 R 50 0 R 50 0 R 50 0 R 50 0 R 51 0 R 53 0 R 53 0 R 52 0 R 53 0 R 53 0 R 53 0 R 53 0 R 53 0 R 54 0 R 64 0 R 55 0 R 64 0 R 56 0 R 64 0 R 57 0 R 64 0 R 58 0 R 64 0 R 59 0 R 64 0 R 60 0 R 64 0 R 61 0 R 64 0 R 62 0 R 64 0 R 64 0 R 63 0 R 64 0 R 64 0 R 66 0 R 65 0 R 66 0 R] endobj 13 0 obj -[17 0 R 19 0 R 20 0 R 21 0 R 21 0 R 21 0 R 21 0 R 22 0 R 22 0 R 22 0 R 23 0 R 25 0 R 24 0 R 25 0 R 25 0 R 25 0 R 26 0 R 30 0 R 28 0 R 30 0 R 29 0 R 30 0 R 32 0 R 34 0 R 34 0 R 34 0 R 40 0 R 37 0 R 40 0 R 40 0 R 40 0 R 38 0 R 40 0 R 40 0 R 40 0 R 39 0 R 40 0 R 41 0 R 42 0 R 50 0 R 43 0 R 50 0 R 44 0 R 50 0 R 45 0 R 50 0 R 46 0 R 50 0 R 47 0 R 50 0 R 48 0 R 50 0 R 49 0 R 50 0 R 50 0 R 50 0 R 51 0 R 53 0 R 53 0 R 52 0 R 53 0 R 53 0 R 53 0 R 53 0 R 54 0 R 64 0 R 55 0 R 64 0 R 56 0 R 64 0 R 57 0 R 64 0 R 58 0 R 64 0 R 59 0 R 64 0 R 60 0 R 64 0 R 61 0 R 64 0 R 62 0 R 64 0 R 64 0 R 63 0 R 64 0 R 64 0 R 66 0 R 65 0 R 66 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 68 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R] +[67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 67 0 R 68 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 69 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 70 0 R 76 0 R 72 0 R 76 0 R 73 0 R 76 0 R 76 0 R 74 0 R 76 0 R 75 0 R 76 0 R 76 0 R 77 0 R 78 0 R 79 0 R 80 0 R 80 0 R 80 0 R 80 0 R 80 0 R 80 0 R 80 0 R 81 0 R 81 0 R 81 0 R 81 0 R 81 0 R 81 0 R 81 0 R 82 0 R 82 0 R 82 0 R 82 0 R 82 0 R 83 0 R 83 0 R 83 0 R 83 0 R 83 0 R 83 0 R 83 0 R 84 0 R 84 0 R 84 0 R 84 0 R 84 0 R 84 0 R 84 0 R 85 0 R 85 0 R 85 0 R 85 0 R 85 0 R 86 0 R 86 0 R 86 0 R 86 0 R 86 0 R 86 0 R 86 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 89 0 R 90 0 R 90 0 R 90 0 R 90 0 R 90 0 R 90 0 R 90 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 92 0 R 92 0 R 92 0 R 92 0 R 92 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 96 0 R 96 0 R 96 0 R 96 0 R 96 0 R 96 0 R 96 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 105 0 R 103 0 R 105 0 R 104 0 R 105 0 R 105 0 R 105 0 R 106 0 R 109 0 R 107 0 R 109 0 R 109 0 R 108 0 R 108 0 R 109 0 R 109 0 R 110 0 R 112 0 R 116 0 R 117 0 R 118 0 R 118 0 R 118 0 R 120 0 R 121 0 R 122 0 R 124 0 R 125 0 R 126 0 R 128 0 R 129 0 R 130 0 R 130 0 R] endobj 14 0 obj -[76 0 R 72 0 R 76 0 R 73 0 R 76 0 R 76 0 R 74 0 R 76 0 R 75 0 R 76 0 R 76 0 R 77 0 R 78 0 R 79 0 R 80 0 R 80 0 R 80 0 R 80 0 R 80 0 R 80 0 R 80 0 R 81 0 R 81 0 R 81 0 R 81 0 R 81 0 R 81 0 R 81 0 R 82 0 R 82 0 R 82 0 R 82 0 R 82 0 R 83 0 R 83 0 R 83 0 R 83 0 R 83 0 R 83 0 R 83 0 R 84 0 R 84 0 R 84 0 R 84 0 R 84 0 R 84 0 R 84 0 R 85 0 R 85 0 R 85 0 R 85 0 R 85 0 R 86 0 R 86 0 R 86 0 R 86 0 R 86 0 R 86 0 R 86 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 87 0 R 89 0 R 90 0 R 90 0 R 90 0 R 90 0 R 90 0 R 90 0 R 90 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 91 0 R 92 0 R 92 0 R 92 0 R 92 0 R 92 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 93 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 94 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 95 0 R 96 0 R 96 0 R 96 0 R 96 0 R 96 0 R 96 0 R 96 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 97 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 99 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 100 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 101 0 R 105 0 R 103 0 R 105 0 R 104 0 R 105 0 R 105 0 R 105 0 R 106 0 R 109 0 R 107 0 R 109 0 R 109 0 R 108 0 R 108 0 R 109 0 R 109 0 R 110 0 R 112 0 R 116 0 R 117 0 R 118 0 R 120 0 R 121 0 R 122 0 R 124 0 R 125 0 R 126 0 R 128 0 R 129 0 R 130 0 R 132 0 R 134 0 R 136 0 R 136 0 R 138 0 R 139 0 R 140 0 R] +[132 0 R 134 0 R 136 0 R 136 0 R 136 0 R 138 0 R 139 0 R 140 0 R 143 0 R 152 0 R 144 0 R 152 0 R 145 0 R 152 0 R 152 0 R 146 0 R 152 0 R 152 0 R 152 0 R 147 0 R 152 0 R 152 0 R 148 0 R 152 0 R 152 0 R 152 0 R 149 0 R 152 0 R 150 0 R 152 0 R 151 0 R 152 0 R 154 0 R 153 0 R 154 0 R 154 0 R 154 0 R 154 0 R 154 0 R 155 0 R 155 0 R 156 0 R 157 0 R 164 0 R 158 0 R 164 0 R 159 0 R 164 0 R 160 0 R 164 0 R 164 0 R 164 0 R 161 0 R 161 0 R 164 0 R 162 0 R 164 0 R 163 0 R 164 0 R 164 0 R 164 0 R 165 0 R 169 0 R 166 0 R 169 0 R 169 0 R 169 0 R 169 0 R 167 0 R 169 0 R 168 0 R 169 0 R 170 0 R 172 0 R 171 0 R 171 0 R 172 0 R 172 0 R 173 0 R 178 0 R 178 0 R 178 0 R 178 0 R 178 0 R 178 0 R 174 0 R 178 0 R 178 0 R 178 0 R 175 0 R 178 0 R 176 0 R 178 0 R 178 0 R 177 0 R 178 0 R] endobj 15 0 obj -[143 0 R 152 0 R 144 0 R 152 0 R 145 0 R 152 0 R 152 0 R 146 0 R 152 0 R 152 0 R 152 0 R 147 0 R 152 0 R 152 0 R 148 0 R 152 0 R 152 0 R 152 0 R 149 0 R 152 0 R 150 0 R 152 0 R 151 0 R 152 0 R 154 0 R 153 0 R 154 0 R 154 0 R 154 0 R 154 0 R 154 0 R 155 0 R 155 0 R 156 0 R 157 0 R 164 0 R 158 0 R 164 0 R 159 0 R 164 0 R 160 0 R 164 0 R 164 0 R 164 0 R 161 0 R 164 0 R 162 0 R 164 0 R 164 0 R 163 0 R 164 0 R 164 0 R 164 0 R 165 0 R 169 0 R 166 0 R 169 0 R 169 0 R 169 0 R 169 0 R 167 0 R 169 0 R 168 0 R 169 0 R 170 0 R 172 0 R 171 0 R 171 0 R 172 0 R 172 0 R 173 0 R 178 0 R 178 0 R 178 0 R 178 0 R 178 0 R 178 0 R 174 0 R 178 0 R 178 0 R 178 0 R 175 0 R 178 0 R 176 0 R 178 0 R 178 0 R 177 0 R 178 0 R 179 0 R 184 0 R 184 0 R 184 0 R 180 0 R 184 0 R 184 0 R 181 0 R 184 0 R 182 0 R 184 0 R 184 0 R 183 0 R 184 0 R 184 0 R] +[179 0 R 186 0 R 186 0 R 186 0 R 180 0 R 186 0 R 186 0 R 181 0 R 186 0 R 182 0 R 186 0 R 186 0 R 186 0 R 186 0 R 183 0 R 186 0 R 186 0 R 186 0 R 184 0 R 186 0 R 185 0 R 186 0 R 186 0 R 186 0 R 186 0 R 187 0 R 197 0 R 188 0 R 197 0 R 189 0 R 197 0 R 190 0 R 197 0 R 197 0 R 191 0 R 197 0 R 192 0 R 197 0 R 193 0 R 197 0 R 194 0 R 197 0 R 197 0 R 197 0 R 195 0 R 197 0 R 197 0 R 196 0 R 197 0 R 197 0 R 198 0 R 204 0 R 199 0 R 204 0 R 200 0 R 204 0 R 201 0 R 204 0 R 202 0 R 202 0 R 204 0 R 203 0 R 204 0 R 204 0 R 205 0 R 207 0 R 207 0 R 206 0 R 207 0 R 207 0 R 207 0 R 207 0 R 207 0 R 208 0 R 218 0 R 209 0 R 218 0 R 218 0 R 218 0 R 210 0 R 218 0 R 218 0 R 211 0 R 218 0 R 212 0 R 218 0 R 213 0 R 218 0 R 218 0 R 218 0 R 218 0 R 214 0 R 218 0 R 215 0 R 215 0 R 218 0 R 216 0 R 218 0 R 217 0 R 218 0 R 218 0 R 218 0 R 219 0 R 224 0 R 224 0 R 224 0 R 224 0 R 224 0 R 220 0 R 224 0 R 224 0 R 221 0 R 224 0 R 224 0 R 224 0 R 224 0 R 224 0 R] endobj 16 0 obj -[184 0 R 184 0 R 185 0 R 195 0 R 186 0 R 195 0 R 187 0 R 195 0 R 188 0 R 195 0 R 195 0 R 189 0 R 195 0 R 190 0 R 195 0 R 191 0 R 195 0 R 192 0 R 195 0 R 195 0 R 195 0 R 193 0 R 195 0 R 195 0 R 194 0 R 195 0 R 195 0 R 196 0 R 201 0 R 197 0 R 201 0 R 198 0 R 201 0 R 199 0 R 201 0 R 200 0 R 200 0 R 200 0 R 201 0 R 202 0 R 204 0 R 204 0 R 203 0 R 204 0 R 204 0 R 204 0 R 204 0 R 204 0 R 205 0 R 206 0 R 206 0 R 207 0 R 208 0 R 208 0 R 208 0 R 208 0 R 210 0 R 209 0 R 210 0 R 210 0 R 210 0 R 211 0 R 213 0 R 212 0 R 213 0 R 213 0 R] +[224 0 R 224 0 R 224 0 R 224 0 R 222 0 R 224 0 R 224 0 R 223 0 R 224 0 R 224 0 R] endobj 17 0 obj -<> +<> endobj 18 0 obj -<> +<> endobj 19 0 obj -<> +<> endobj 20 0 obj -<> +<> endobj 21 0 obj -<> +<> endobj 22 0 obj -<> +<> endobj 23 0 obj -<> +<> endobj 24 0 obj -<> +<> endobj 25 0 obj -<> +<> endobj 26 0 obj -<> +<> endobj 27 0 obj <><>]/K[26 0 R]>> endobj 28 0 obj -<> +<> endobj 29 0 obj -<> +<> endobj 30 0 obj -<><>]/K[17 28 0 R 19 29 0 R 21]/Pg 245 0 R>> +<><>]/K[18 28 0 R 20 29 0 R 22]/Pg 253 0 R>> endobj 31 0 obj <> endobj 32 0 obj -<> +<> endobj 33 0 obj <><>]/K[32 0 R]>> endobj 34 0 obj -<><>]/K[23 24 25]/Pg 245 0 R>> +<><>]/K[24 25 26]/Pg 253 0 R>> endobj 35 0 obj <> endobj 36 0 obj -<>]/K[31 0 R 35 0 R]>> +<>]/K[31 0 R 35 0 R]>> endobj 37 0 obj -<> +<> endobj 38 0 obj -<> +<> endobj 39 0 obj -<> +<> endobj 40 0 obj -<> +<> endobj 41 0 obj -<> +<> endobj 42 0 obj -<> +<> endobj 43 0 obj -<> +<> endobj 44 0 obj -<> +<> endobj 45 0 obj -<> +<> endobj 46 0 obj -<> +<> endobj 47 0 obj -<> +<> endobj 48 0 obj -<> +<> endobj 49 0 obj -<> +<> endobj 50 0 obj -<> +<> endobj 51 0 obj -<> +<> endobj 52 0 obj -<> +<> endobj 53 0 obj -<> +<> endobj 54 0 obj -<> +<> endobj 55 0 obj -<> +<> endobj 56 0 obj -<> +<> endobj 57 0 obj -<> +<> endobj 58 0 obj -<> +<> endobj 59 0 obj -<> +<> endobj 60 0 obj -<> +<> endobj 61 0 obj -<> +<> endobj 62 0 obj -<> +<> endobj 63 0 obj -<> +<> endobj 64 0 obj -<> +<> endobj 65 0 obj -<> +<> endobj 66 0 obj -<> +<> endobj 67 0 obj -<> +<> endobj 68 0 obj -<> +<> endobj 69 0 obj -<> +<> endobj 70 0 obj -<> +<> endobj 71 0 obj -<>]/K[67 0 R 68 0 R 69 0 R 70 0 R]>> +<>]/K[67 0 R 68 0 R 69 0 R 70 0 R]>> endobj 72 0 obj -<> +<> endobj 73 0 obj -<> +<> endobj 74 0 obj -<> +<> endobj 75 0 obj -<> +<> endobj 76 0 obj -<> +<> endobj 77 0 obj -<> +<> endobj 78 0 obj -<> +<> endobj 79 0 obj -<> +<> endobj 80 0 obj -<> +<> endobj 81 0 obj -<> +<> endobj 82 0 obj -<> +<> endobj 83 0 obj -<> +<> endobj 84 0 obj -<> +<> endobj 85 0 obj -<> +<> endobj 86 0 obj -<> +<> endobj 87 0 obj -<> +<> endobj 88 0 obj <> endobj 89 0 obj -<> +<> endobj 90 0 obj -<> +<> endobj 91 0 obj -<> +<> endobj 92 0 obj -<> +<> endobj 93 0 obj -<> +<> endobj 94 0 obj -<> +<> endobj 95 0 obj -<> +<> endobj 96 0 obj -<> +<> endobj 97 0 obj -<> +<> endobj 98 0 obj <> endobj 99 0 obj -<> +<> endobj 100 0 obj -<> +<> endobj 101 0 obj -<> +<> endobj 102 0 obj -<>]/K[79 0 R 80 0 R 81 0 R 82 0 R 83 0 R 84 0 R 85 0 R 86 0 R 87 0 R 88 0 R 89 0 R 90 0 R 91 0 R 92 0 R 93 0 R 94 0 R 95 0 R 96 0 R 97 0 R 98 0 R 99 0 R 100 0 R 101 0 R]>> +<>]/K[79 0 R 80 0 R 81 0 R 82 0 R 83 0 R 84 0 R 85 0 R 86 0 R 87 0 R 88 0 R 89 0 R 90 0 R 91 0 R 92 0 R 93 0 R 94 0 R 95 0 R 96 0 R 97 0 R 98 0 R 99 0 R 100 0 R 101 0 R]>> endobj 103 0 obj -<> +<> endobj 104 0 obj -<> +<> endobj 105 0 obj -<> +<> endobj 106 0 obj -<> +<> endobj 107 0 obj -<> +<> endobj 108 0 obj -<> +<> endobj 109 0 obj -<> +<> endobj 110 0 obj -<> +<> endobj 111 0 obj <><>]/K[110 0 R]>> endobj 112 0 obj -<> +<> endobj 113 0 obj <><>]/K[112 0 R]>> @@ -347,565 +347,614 @@ endobj <> endobj 116 0 obj -<><>]/K[259]/Pg 246 0 R>> +<><>]/K[314]/Pg 254 0 R>> endobj 117 0 obj -<><>]/K[260]/Pg 246 0 R>> +<><>]/K[315]/Pg 254 0 R>> endobj 118 0 obj -<><>]/K[261]/Pg 246 0 R>> +<><>]/K[316 317 318]/Pg 254 0 R>> endobj 119 0 obj <> endobj 120 0 obj -<><>]/K[262]/Pg 246 0 R>> +<><>]/K[319]/Pg 254 0 R>> endobj 121 0 obj -<><>]/K[263]/Pg 246 0 R>> +<><>]/K[320]/Pg 254 0 R>> endobj 122 0 obj -<><>]/K[264]/Pg 246 0 R>> +<><>]/K[321]/Pg 254 0 R>> endobj 123 0 obj <> endobj 124 0 obj -<><>]/K[265]/Pg 246 0 R>> +<><>]/K[322]/Pg 254 0 R>> endobj 125 0 obj -<><>]/K[266]/Pg 246 0 R>> +<><>]/K[323]/Pg 254 0 R>> endobj 126 0 obj -<><>]/K[267]/Pg 246 0 R>> +<><>]/K[324]/Pg 254 0 R>> endobj 127 0 obj <> endobj 128 0 obj -<><>]/K[268]/Pg 246 0 R>> +<><>]/K[325]/Pg 254 0 R>> endobj 129 0 obj -<><>]/K[269]/Pg 246 0 R>> +<><>]/K[326]/Pg 254 0 R>> endobj 130 0 obj -<><>]/K[270]/Pg 246 0 R>> +<><>]/K[327 328]/Pg 254 0 R>> endobj 131 0 obj <> endobj 132 0 obj -<> +<> endobj 133 0 obj <><>]/K[132 0 R]>> endobj 134 0 obj -<> +<> endobj 135 0 obj <><>]/K[134 0 R]>> endobj 136 0 obj -<><>]/K[273 274]/Pg 246 0 R>> +<><>]/K[2 3 4]/Pg 255 0 R>> endobj 137 0 obj <> endobj 138 0 obj -<><>]/K[275]/Pg 246 0 R>> +<><>]/K[5]/Pg 255 0 R>> endobj 139 0 obj -<><>]/K[276]/Pg 246 0 R>> +<><>]/K[6]/Pg 255 0 R>> endobj 140 0 obj -<><>]/K[277]/Pg 246 0 R>> +<><>]/K[7]/Pg 255 0 R>> endobj 141 0 obj <> endobj 142 0 obj -<>]/K[115 0 R 119 0 R 123 0 R 127 0 R 131 0 R 137 0 R 141 0 R]>> +<>]/K[115 0 R 119 0 R 123 0 R 127 0 R 131 0 R 137 0 R 141 0 R]>> endobj 143 0 obj -<> +<> endobj 144 0 obj -<> +<> endobj 145 0 obj -<> +<> endobj 146 0 obj -<> +<> endobj 147 0 obj -<> +<> endobj 148 0 obj -<> +<> endobj 149 0 obj -<> +<> endobj 150 0 obj -<> +<> endobj 151 0 obj -<> +<> endobj 152 0 obj -<> +<> endobj 153 0 obj -<> +<> endobj 154 0 obj -<> +<> endobj 155 0 obj -<> +<> endobj 156 0 obj -<> +<> endobj 157 0 obj -<> +<> endobj 158 0 obj -<> +<> endobj 159 0 obj -<> +<> endobj 160 0 obj -<> +<> endobj 161 0 obj -<> +<> endobj 162 0 obj -<> +<> endobj 163 0 obj -<> +<> endobj 164 0 obj -<> +<> endobj 165 0 obj -<> +<> endobj 166 0 obj -<> +<> endobj 167 0 obj -<> +<> endobj 168 0 obj -<> +<> endobj 169 0 obj -<> +<> endobj 170 0 obj -<> +<> endobj 171 0 obj -<> +<> endobj 172 0 obj -<> +<> endobj 173 0 obj -<> +<> endobj 174 0 obj -<> +<> endobj 175 0 obj -<> +<> endobj 176 0 obj -<> +<> endobj 177 0 obj -<> +<> endobj 178 0 obj -<> +<> endobj 179 0 obj -<> +<> endobj 180 0 obj -<> +<> endobj 181 0 obj -<> +<> endobj 182 0 obj -<> +<> endobj 183 0 obj -<> +<> endobj 184 0 obj -<><>]/Pg 247 0 R>> +<> endobj 185 0 obj -<> +<> endobj 186 0 obj -<> +<> endobj 187 0 obj -<> +<> endobj 188 0 obj -<> +<> endobj 189 0 obj -<> +<> endobj 190 0 obj -<> +<> endobj 191 0 obj -<> +<> endobj 192 0 obj -<> +<> endobj 193 0 obj -<> +<> endobj 194 0 obj -<> +<> endobj 195 0 obj -<> +<> endobj 196 0 obj -<> +<> endobj 197 0 obj -<> +<> endobj 198 0 obj -<> +<> endobj 199 0 obj -<> +<> endobj 200 0 obj -<> +<> endobj 201 0 obj -<> +<> endobj 202 0 obj -<> +<> endobj 203 0 obj -<> +<> endobj 204 0 obj -<> +<> endobj 205 0 obj -<> +<> endobj 206 0 obj -<> +<> endobj 207 0 obj -<> +<> endobj 208 0 obj -<> +<> endobj 209 0 obj -<> +<> endobj 210 0 obj -<> +<> endobj 211 0 obj -<> +<> endobj 212 0 obj -<> +<> endobj 213 0 obj -<> +<> endobj 214 0 obj -<> +<> endobj 215 0 obj -[/ICCBased 268 0 R] +<> endobj 216 0 obj -[/ICCBased 269 0 R] +<> endobj 217 0 obj -[245 0 R/XYZ 62.362206 729.37256 0] +<> endobj 218 0 obj -[245 0 R/XYZ 62.362206 590.0229 0] +<> endobj 219 0 obj -[246 0 R/XYZ 62.362206 733.7516 0] +<> endobj 220 0 obj -[246 0 R/XYZ 62.362206 342.88815 0] +<> endobj 221 0 obj -[247 0 R/XYZ 62.362206 789.5276 0] +<> endobj 222 0 obj -[247 0 R/XYZ 62.362206 546.3959 0] +<> endobj 223 0 obj -[247 0 R/XYZ 62.362206 426.81766 0] +<> endobj 224 0 obj -[247 0 R/XYZ 62.362206 335.20096 0] +<><><><>222 0 R<><>223 0 R<><>]/Pg 256 0 R>> endobj 225 0 obj -[248 0 R/XYZ 62.362206 411.61353 0] +<> endobj 226 0 obj -<>/Font<>>> +[/ICCBased 275 0 R] endobj 227 0 obj -<>/Font<>>> +[/ICCBased 276 0 R] endobj 228 0 obj -<>/Font<>>> +[253 0 R/XYZ 62.362206 729.37256 0] endobj 229 0 obj -<>/Font<>>> +[253 0 R/XYZ 62.362206 576.02637 0] endobj 230 0 obj -<> +[254 0 R/XYZ 62.362206 679.2434 0] endobj 231 0 obj -<>/FontDescriptor 232 0 R/DW 0/W[0 0 280 1 1 786 2 2 559 3 3 474 4 4 639 5 5 527 6 6 454 7 7 319 8 8 383 9 9 869 10 10 800 11 11 607 12 12 447 13 13 756 14 14 639 15 15 607 16 16 319 17 17 575 18 18 958 19 19 1189 20 21 639 22 22 319 23 23 639 24 24 607 25 25 510.99997 26 26 831 27 28 639 29 29 351 30 30 671 31 31 607 32 32 882 33 33 575 34 34 319 35 37 575 38 38 818 39 39 692 40 40 319 41 41 1092 42 42 831 43 44 447 45 45 383]>> +[254 0 R/XYZ 62.362206 288.38 0] endobj 232 0 obj -<> +[255 0 R/XYZ 62.362206 706.6116 0] endobj 233 0 obj -<> +[255 0 R/XYZ 62.362206 463.47986 0] endobj 234 0 obj -<>/FontDescriptor 235 0 R/DW 0/W[0 0 500 1 1 556 2 2 444 3 3 394 4 4 278 5 5 500 6 6 556 7 7 333 8 8 306 9 9 500 10 10 392 11 11 389 12 12 556 13 13 722 14 14 1000 15 17 500 18 18 333 19 20 500 21 21 681 22 22 500 23 24 528 25 25 833 26 26 444 27 28 278 29 30 556 31 31 278 32 32 556 33 33 528 34 34 278 35 35 556 36 36 278 37 37 722 38 38 686 39 39 528 40 40 681 41 41 528 42 42 361 43 44 389 45 45 556 46 46 764 47 47 625 48 48 500 49 49 778 50 50 444 51 52 750 53 53 778 54 54 278 55 55 583 56 56 500 57 57 750 58 58 500 59 59 750 60 60 306 61 61 736 62 62 785 63 63 708 64 64 917 65 65 556 66 66 500 67 67 611 68 69 500 70 70 778 71 71 750 72 72 722 73 73 1000 74 74 653 75 75 1028 76 76 514]>> +[255 0 R/XYZ 62.362206 343.90167 0] endobj 235 0 obj -<> +[255 0 R/XYZ 62.362206 252.28497 0] endobj 236 0 obj -<> +<>/Font<>>> endobj 237 0 obj -<>/FontDescriptor 238 0 R/DW 0/CIDToGIDMap/Identity/W[0 78 602.0508]>> +<>/Font<>>> endobj 238 0 obj -<> +<>/Font<>>> endobj 239 0 obj -<> +<>/Font<>>> endobj 240 0 obj -<>/FontDescriptor 241 0 R/DW 0/W[0 0 500 1 1 527]>> +<>/Font<>>> endobj 241 0 obj -<> +<> endobj 242 0 obj -<> +<>/FontDescriptor 243 0 R/DW 0/W[0 0 280 1 1 786 2 2 559 3 3 474 4 4 639 5 5 527 6 6 454 7 7 319 8 8 383 9 9 869 10 10 800 11 11 607 12 12 447 13 13 756 14 14 639 15 15 607 16 16 319 17 17 575 18 18 958 19 19 1189 20 21 639 22 22 319 23 23 639 24 24 607 25 25 510.99997 26 26 831 27 28 639 29 29 351 30 30 671 31 31 607 32 32 882 33 33 575 34 34 319 35 37 575 38 38 818 39 39 692 40 40 319 41 41 1092 42 42 831 43 44 447]>> endobj 243 0 obj -<>/FontDescriptor 244 0 R/DW 0/CIDToGIDMap/Identity/W[0 8 602.0508]>> +<> endobj 244 0 obj -<> +<> endobj 245 0 obj -<> +<>/FontDescriptor 246 0 R/DW 0/W[0 0 500 1 1 556 2 2 444 3 3 394 4 4 278 5 5 500 6 6 556 7 7 333 8 8 306 9 9 500 10 10 392 11 11 389 12 12 556 13 13 722 14 14 1000 15 17 500 18 18 333 19 20 500 21 21 681 22 22 500 23 24 528 25 25 833 26 26 444 27 28 278 29 30 556 31 31 278 32 32 556 33 33 528 34 34 278 35 35 556 36 36 278 37 37 722 38 38 686 39 39 528 40 40 681 41 41 528 42 42 361 43 44 389 45 45 556 46 46 764 47 47 625 48 48 500 49 49 514 50 50 750 51 51 917 52 52 500 53 53 722 54 54 444 55 56 750 57 57 778 58 58 278 59 59 583 60 60 500 61 61 750 62 62 778 63 63 750 64 64 306 65 65 736 66 66 785 67 67 708 68 68 556 69 69 500 70 70 611 71 71 778 72 73 500 74 74 778 75 75 750 76 76 1000 77 77 653 78 78 1028 79 80 750]>> endobj 246 0 obj -<> +<> endobj 247 0 obj -<> +<> endobj 248 0 obj -<> +<>/FontDescriptor 249 0 R/DW 0/CIDToGIDMap/Identity/W[0 79 602.0508]>> endobj 249 0 obj +<> +endobj +250 0 obj +<> +endobj +251 0 obj +<>/FontDescriptor 252 0 R/DW 0/W[0 0 500 1 1 527]>> +endobj +252 0 obj +<> +endobj +253 0 obj +<> +endobj +254 0 obj +<> +endobj +255 0 obj +<> +endobj +256 0 obj +<> +endobj +257 0 obj +<> +endobj +258 0 obj <> stream -xœûÿÿÿÿÿîø +xœûÿÿÿÿÿ?êô endstream endobj -250 0 obj -<> +259 0 obj +<> stream -xœm”ËŽ£0E÷|EÍ)½ÈæÕE‘¤,ú¡NkfMp%ƒ â±Èß�ð­$­Ñ,]WÙ·NÙÆýñq˜¯usäyøÓ§Oî›±+yž½­ãºÛ¦k6óf}‹ö j»¦ìy l¿Ý›jp\woÊ˨ù–ó¿” Ÿ+óH˜<(û¡©×ýª† /h†²5Ñ^³ªáJþ“㺿¸ë«Æ,(p\wgtÖÔSq½ã‰y]Sx Set'Ntœ|�@‘®ÊA”}—uÑÚɇk?p½7§†Bd鱕L""ï“ÏU?tWšÙžHó ‘÷NsW™3ÍnÅ~ ƶ½ðT$ùv”�¶_o‚+j&O€ï£BIÁcèëÚ²,àý~môM(±l4÷mQrW˜3;Kß÷ý-ó<ÏW“ã?ñ(Æ´ã©üSt6=XÑÒ÷ce•²*  B«R!AÅP1T‚Ì*µ*\C=[¥ÄáŪHÖp—57Xå*ƒ’ØóÄo÷TŽÌĪ`j€ï'/PàKr(áÛB�/N¡„îøRT€/É À— /øRñ_‚NàKÅ|±Ä„Døa¾ä1Ædc•c„Þ(0†pQ`T¨U�1Ä* -Œ!*W²‡2Œ‘ÄÀÉ*²‡è·’=D#P)0*tQ�Q¡7 -Œë­=šr§C:ÝÅû­(Ç®c3Ø«h¯ÀtÞ+Ã÷;Ý6í4Ë>ögpû¯Lê=ÿ ˆÚBÎ +xœm”O�¢@Åï|ŠÚ‰sp�q4ÆDQó'ãd÷Œté’HC8øí7ô+ÇÉfj^WU¿úUwëÿx?N7º9ñ4þÒwÍ`Kžf/Eëùþ®)‡šMÿʬYߣݒZÛ”÷”vSõžïLy4ßsþ—²åKe £eC×7µçûŸUå%M°@®':h6}Õß(|ò|ÿÛ®jÌ’"Ï÷÷FgM=6×y�xPðn›òÈ=�+£­8Ñiôõ"Eº*{Q‹Öo]ÏõÁœŠ‘¥‡V2‰ˆ‚¾T]oo4q�=‘æ3"oV³­Ì…&÷f¿�CÛ^yl’B·ÊF»ß`„-j¦@€¿V…’¢ÇÒç­eÙ øýÒ軈ÐbÙhîÚ¢d[˜ {«0 Ã5­ò<Ï×£ã?ñ$AÙé\þ)¬K�Ö´ +ÃY¸vJ9•FP±Ss• –@Í fP)2c¨¹SñêÙ)% §qØÀ]öÜb—g¨ Jb;Ô‰ßî{¨™©SÑ8€0LPàKs(áÛA�o6‡>¸Gà›£ë|i¾s‰À7?ð¥˜D¾¹8€o&1áQ¾T„/}¬€1Ý:¥À˜`6 +Œ1\zU`Œ±‹cŒÎ•œ¡Ô�1‘ÙEÎóVr†˜¢c*F…)*0ª…»ŒrëÆk9¾¾¯wPÖ²éÝãs—~¼á•á¯WÜ6íXå>îùßÿIFõ–ÿ¨s?ô endstream endobj -251 0 obj -<> +260 0 obj +<> stream -xœ�XiX×¶­¦­ªƒ�FºlL”T£ApBpºIŒFEÁ!jb4N4 +xœ�XiX×¶­¦©ªƒ�FºlLÔTƒApBpºIŒÆ¢&FâØ(((eZ¡±›Ý4ó$3ŠA@ZQJŒc4Æ!1×›è�I®C5&!<ýv‘Cî}_ãðrÍ}ï{ª¿>çô9{ïZk�µ[ÁØÛ3 +…ÂiahÂÌc}½gDm± øËƒå!à(Ê/+Ä~ŒàñÓ‘òÛÙÞƒCø¬!öÛØ—Fáâl{Ƹ¼Ì0ÿú—ãPÛ—•޶�ÅŽÃ¥BÁ©ê§‡D­ �›4|æ·q¾c_÷ç;î/nÓ#c£"ÃcÜb¢6Dm � �ãã–áãº!48&4Ä-.2$4Ú-6,Ômö{‹Üü£"cÝæ‡¯ �Œ uóövs‹ u ‹�Ý4ÉÇ'6ný˜¨èõ>ë¢"cc|6<^ãcû�·ÿÛ ¼çÏ�é·p±ß˜ØÄX·uQÑn!¡±ÁábÆ0Œ£`FÁùŸ}¡üN>®ª*(äÄ~öQŽÙŽýÀñ©_£Åb6gf™ss‘{AÊ9TœShÉËÊtt2;ª”Œ‚aÆÛVÅf³­j/3 3ÅVW5ãm;ÞYË‹¢ìsú‚ÃKRß:‹ÅlÎÊ6çå98 ÷’”ÛRœ[dÉÏÎrp4;¨”Œ‚af´­ŠýÍf[Õ^ef²­(.jf´íŒ>Ìjæ±b©âs»Ùv¨ôQŽSV(»ú¬ï#±ƒØTöïœ'—Ê;óõ¤ÙIÎÛO·—úºö=ôRÄKF:\s\ëxZ5IïÔ×)­_b¿ßœ':/wFõvõ?„7„yôN²Æüfl—艮؀^ÊîP9UƒvÃþA'Š=tÈôÜ¥ŒŽk°<„Vh…‡Ð`$e0ýxÔ"ù+Úk©—Ë x›Žé@lÇAŽ€)Óµª÷ Öõ¾[ƒ£¬ê}hÿ6:ãxä„xùØMU -¤ˆóÍP U#ø»3.ÒáïSÕöq+ë÷ÕÔV¶ˆp ±Ô˜õQn­y�/냧hÃyAša¤yÛ€…‘Ø/é ø¤æÝ-Dˆ_�ÿ%å*vÀ- D^#H#½S¢—®®?,28¶ä˜…¨¨»å0vJQVõcd(Ó�ö¨êäùr͉ö/ý`õ²Ø¹�e…‹tbèØóy¢šéy�j ÛÀj$ÒxœÎ_Ù‹ª_ 19rUmÂ~qme“VUiKZVZq�”Ÿ nÀþ˜ƒœ)?t‘øyéШù+´R¿ç›Ó%ü²Æ%¹¡CÆÑÁôåGá0í§ptOÍ^²œGEŸ”¤U‹¦U #\�£p²ºq‹TXg )bw$QùšpnN´ªk±?¦=XÞ.<’·¡½¦,2Äd0e6ż1œ‰¯|¬ÅSÜîBا…õeÇÖX—ù¡ãÇ»Sg:ð—8A‹c[—jyÔÐ4.«ÑÜRYWÝÔ´c?´‡,:ÀFTô ƒUT«n¸:ã(æJÁW…»ò8tÓ@kB}ØG!û#r'¯É›Sœ¿å@„{_BCdÎ"ófsF%�=�S¥ýš/‡‚$q;˜ $qcqXîjXt4«+6T$7…5®o!Â5«áËx¦zC †�×R[3J2` �0Äj©‚O„mebdAåNR]ʶE‡ - 58ÐC«¢Ç}ðeôQÜD%n•í4­aõAAaaAAõa­­õõ­"mîó§1MUa6Hè!)º?w‘Fð´ ›eõÕ©� Q°=-=‰PsÏϬa³1m -�x‡ö¶NÃ!#‘x ÅÚìÇÐ+áõ c, šàÔ ½ŽéšÈa «Â9–Ãò IÑ"a:Á4IÙm’ý5ñhø}ÄSƒl²…7ÑÈõžÔKÇ�´ ÎÂY@%œ´‘ÔK¾ñ�¯Aá[…”#*=HØ%)äo\¤<�„h�.lqInÞ·@@ò6º[@Ç–ÀÓŽôí0mßN^÷Ž|€D�Ôκ«€>t.@=Ùäĵt?ZºŒ ±I‰9¹ZÈÊË'¨@;ê C «¢S Mø/IgUw!§“°¯$\“ÕØOsB·”Ÿµ.T‰¸=$^¸H=p¡Žš3=—f$k¿¡ûx·ÛqWÅ¯Žœ¹¦U¡ÖKXØ«ZCp‚¤ì^‹û4:.ŽŠQcé< tÖŸâ~* š¦•ð Ž›¶-h„¸ q‡ Úwu$¬CÃï -[ˆ @Ï·”Ðu«�UU‚ôD$�CŽr]�œP'SÉwð�>hôGÂâ÷7.%€ŒM(¦þ¡@µ$ eQq«ý³ƒ•ñSDZõTETúÒxy¨¤�¯Ëƒ5mŠÌŒâc{åû�i¶:š2¶J¨… -X}Òö -ú)gÝÀé=ìŽèb(†R(´Vœˆ2›[’�wˆ â¶øó~Fõ7èCUÈÍØè"Í“=yáõµ…{¶WzzƒUYX¡ø ¹óߘ Ú`¯UšdÁª°‰JöWÊ�©Á�Þ�ôuú†ÏPú -íwÇßÂI·;ÑI¤ý‹4ã�2T  s[„#ðqéÁòC-•íÐ-›v‡U†Ã" *¼÷b‘×!‡ÁÈ õ¿½õ¤Ð]K›ÝEX²lc`Â=oK(Œ‡÷WDØÔ™a…Ë,zë,úíöów'¼ý¼èÿç$«’?/Žï$)\û˜»�ÄoÈ 3­€P˜k-DÇï…£°_OèÔž…ÔO^ñ€Ä†½ B`„Yˆîß<˜ºÒGÿë4¦ÿ®`s7eoÝ {!»0wA_y1úö,~at“|ŸÍ-5gÕX*²*a$Ÿß)È!ƒk�n¾É¥ âBI&Þㄎ?\/=Çþ_€¬¤‹%l•RD“ú1r˜ƒý…›rÆhðŸûÔ]œ -‹×Å&hgÿ°¨¶ÇüÂþóÙÖ°Ã[›�àˆ_¿G­–öw¡ƒý–Ì·€VœÔƒÊ †ñPn6—”áfSóñÜÝ@.ŸžOÕ½-Éw{3%ȇ°ÍEòïÄ _ü)+'[à«Üÿii#ƒEˆÛë>*ú²ȘØöÇÀC´=¿«¼´lWy~Zûw�àð®§ñ‚m ‰\¨�?9¹u'Ál~_ýÑý§UÔüˆJOuVùI±yåS"ǘÖ?'2H�ªÍH¥<ͤV½Àáw{ǰq3gÀ0™Ó,ÙU%POêbö„GE&†,•V�¯Ã'ç÷�!!²y%–^~»šd§&…ÍZø¢³RŽF{MÉØ*&A¦)#eã܀ĥ@¨гí4  j´õPj,6&m2ÅÃ6òÌaÝ¢$w�9�ò”ÐWî�ÂÑø—HòD†?Q§î¶Þ¤bMë3c€Œ´%UО©×‚ÑhÈ4’!´€rXwÚ–gdƒ!8k“™èÎò•ËÀÛ{WM¢‹†`Qï"'#UX@wЫ§/›—ü óy¥ä1îxLwüûºãc6§8;ÿ¬�zIþg«úBÇI¶ë˜Ø.Ü“¯âJ  râMŸrB‡Ö°« „O¡õ£ó¿î~ �áUÔ5;LÏl¾óÄg¤Af¦~+Y±’]Ð6§ è(˜>†ÀœºÀʸöåÓQs'±Ô¸;ž×wnÞ»!`£ÿk0訊4žY9qÏ<Çœ'ž£²²òóH[{iù=ƒ ÿožG¶ó©%ìUä^±Ã ä��»Ï !à -uô�ÿ1„ ù7—.ö}Û¸÷¤(¸Þaz ïv3îg±þ -m7Èd^E+,‡±K VÚ#s�”òl¹[Ó²öÈäá” ¦¬è1U÷%íú“‡íB^¢Ž�<Ú}U°WÌ�È3mÖ§%B" ªO¬>P[Ù,ªNôÛî6~­AætRv§ÈÝšÖ5‡'‹a° C·>¸~!Ä¡*úZ(í«õ|~ž“�ž*C® ]þ¶;÷…0ì%êÔÉ#ÿ]v™˜Ù™¹™/†A¯4kŒ¦ ›a $çÅ—¥’ÁtÝCþ»K ?ˆ5°ÛP´ý™ÃÁ%O¥@¸.ç"%óA`ÌNÙEèd\‹.�lIQAÞe ¿Á �PÞì*°óÓ]@‡ƒÈ -÷þ$6t|šˆÀî¯ÊÏ­(!�TͤîJ#Ù–)¢Ž?�uÛœÄ -3šˆ -K{Ŭ·¿’ §²ûü^ƒèÔÐåb�ï³KžÎá2�Nø¡–zš5@©‹#VÌ·i¾­3�ï¢w ¾Ml÷«_š?FUPa¼¼�kÔ¤TIBg¡C>Õý²†q±@=s¶dÇgg˜ -‰XáQÍ“€-üª¸8;«(÷&”ÁÉ\R\b|RÜHÚg:tñ; ¹»¤œKbG-Gó¤‚Ë•gë› zã,¶°² ¾×aôèÉJ´Ôh>?³ p]XÐê}¡‹µPQj±¤QÅœÅñI† £ dkÑÖü��n¡VTé[±ËŠËÕGQÄùè솮Â#¹ -ƒ5èæq�:Šq°‚§�r�«lÍÛ¹G:iýÊà ±*–òÚŒ¤ °ž„WE56î©n8ü™íÎ}sÍaRÁ[ÍþÒ”¯b®AíOßà@­ðˆºfi<`š‡¸64¦íÚT × Œ óI锸¦zjUA€Îr‚¤>ƒîè�¢NîÉ%­ÑqÆ„mïlIצÂ& Ô““�·©#B'rß]�àAþµ¿ÑÁÔÑkÞ˜÷ŽnÞSÛ´û˜ǃwmÎÞ¿§¡È -· m&LÿЙ~3 ¤ÁlJ*˜ �$ÉÓxU ´â¨Ž+V|£s•U]{k*G·ãTfÝò»%tUʧäÁšªäú@q3èŒ+Èð@Ÿ´#¸rPwX4ü`UŪÚX"üª� -3|ñDxt6g/oŠH1úÆÃ\²ôÔTÔ¡ß�³WD8�öÙ¬ƒ ?zF‚MÏ2ÌDøµrež¾Ê 0{gn~[ÌǦ½€îpê\)ºnó®»*³ŠÌÄ”aÚ]šT-V—–ïÑÒˆQš0kœ(<Ð�ƒËGŽÀå;w`Ö -­p÷²=Žšµ!Pê°¼­íÜgP"¢=Wƒ,ÌÓªP±b©¤FO€'qåÑSxÔmÀùøiÂeúRddÊ/žƒëäÇñ_Ó b�ÿsž„p8ñ»;µÔojÞ˜7B¤>XŠs¸Î²I�ZáÑ>úµ&hê.Ò¹xs ÁÁ R AOT³1òð“ÞᜤìÐÛ;¤ù'Ó±t&wù.’¸•Fª€å°< ÔBžŸ~…Ž~[ûxãÏÝ£JŽ|Jùa'äßÑYù›ÕE¢Œ|‰näã@úhBÓ{ªiº\Íê÷ê{u3ÚvÄ9â23£Œ1FD‰¶ýïr¡ŽC³‘HÑ|$›“²"-™fØMdÉÌãÞž‡lAÂŽŒ"¨€ü�Ùkej°Åkk2­–{Ð Ípߦµ* ×Kòo’úzÉi'mXïÎÃMEº9YL�m�™œNRÇù0^ß³äSÝ™Ô/á{8mAæ³K/Ý.:6ü3ð`Ên*Xͦ* Õæ¬j­p#žÜ®ÛÀdJK'³ßcç›U6Í¢^t8 ¦ÁèE‡c–ßE��תèd:”²š¦jrŒ9 Fî›ói0ößø÷Ôáà²�q Ú¡rçN³r h«% ’!xMR2¡>Ô;–Î…Á@�ë¨�ôÆ%Êÿ0«H~¡¥¨wcC‡@‹ÐùC´Ó};yŸË‰�[� ‡ 0•nB5í�útÙR:†ÚQ%Ù¼932@_ḣRh9TVŠ>è]…sá1QÑTôíPã'J¼Š¾šúÉ^õß9øgË + +j +koojji›ýŸÆT4E…Y ¡§¤èùÔUÉÓü–Õצ@2DÁ®Ô´$Bͽ?³†­ÆÔ©@âu:XØ8 �Dâak³ŠŽ¡VÁ9ê9@Ç6[îC;´Âmh2z Ó44�ÃzV…ó,‡åë’â�„i8S%e�Iö×Ä£á÷‰O °ùÈÜ@ ×z¯SowÒ‚J8 g•pÒFRoùú—<¾oPލô a·¤�¿v•fñt2®Dte‹Krr¿’�ÑÃ:¶ŠLEi» `Úµ‹¼ê=ùV‰:©�tŸúÒùt õb“×ÃJ  ûÁÒm‰MJÌÎÑ@fny€ +´£®!:t´°*:ÕЊÿ’tVu7r: ûIÂUY�ý5'tËøÙ1Q‹àB�ˆuè)ñÂEꉋuœÐ–áµbøp#Yÿ5Ýǻ݊û\üòÈ™«ZŠ a“„}ª5'JÊžõ¸O£ãâ¨5Ž.BGcÓ)îÇ‚ éZ è¸é;ƒFŠX€£9œµ3J©‘`~WØBdz¿¡ €®G ¬ª +¤Ç"�r”ëÆä„F™ºJþXÄ?|¯ÅKKÞݼŒ26¡˜ö„ÕF�ü0”EÅÍÎOTÅOiÍQéËâåa’B¾&»k$>Ú™ Ä×ö*ꌩ¶:šÒwJ¨… +X{Òö +ú)gÝÀ™½ŽlQt1CX +ªNB™Í)ÉʽÄq[üy ?£¯úkô¥*d„6lq•È^¼p•ΰ…{¶Ozú‚UYX¡ø3¹ëߘ Ú`¯UZeÁª°‰J.PÊ-©ÁA>]ôUúšï0úíÛ ßÀÉ·ºÐY¤ +5€2T  sK„#ðaÙ�Šƒ‡ª:áÚRV°’¨ðîóEÞ€#'4ýöÆãBw/kó}aéòÍ� w},¡0Þ]aSg†.ÿ±èíÿ±è·:ϨNxóYÑÿÏIV%Zß3XR ±7÷‰ß”fZ¡°Ö[ˆŽß G¡NOè´ÞÅÔO^õ#€Ä†½!B`2„Yˆî&ßæN‡Ð‡ÿë4¦ý®`s¶díØ {!« §”à y Îè]òÜèù›Sfά·TfVA)$ŸÝ)È!ƒë�n<Ée‹âBIÞ儸^z�ý¿YE—Hèn•RD«úr˜�„òŒÑàK¾÷¨‡8 –lˆM"ÐÉþaÿPm¯ù¹ý²ía‡w´Á‘¿~‡Z-àJÝý–η�V�Ôƒ*†ñPa6—”áFkÛñœj —O/¤ê>‰–ä;}™d„ƒØá*ù÷ æ…Ïþ”•³-pƒUð¤4��ÁÂ?Äí}�gÀòȘØñÇÀC´½$¾´¢¬¼´"/µó½;@pD÷“xA›C"×ê#ÀBNîØM0‹ß×t´î  +€:�Qé©Î*$)ª‘W>!rŒiã3"ƒ)ÚôÊÓ *`Ís~»×=v%·2bö,Ø&sª%?«¦šHcÌžð¨ÈÄ�eÒšsâ5øèü¾3#ä@6·ÄÒÇo7C«ìܪ°Y‹袔£ÑAS² vˆI�aJß¾yþÊÄe@¨Ыã4 +j´MPf,6&m1ÅÃNòÔaݤ$g�=�ò”Зî�Æ1ø—ýHrE†?V§žŽ¾¤bM3b€Œ²%•ß™¡×‚ÑhÈ0’¡4ŸrØxÚ–gdƒ!8s‹™èÎòUËÁ»úVM¦C±°o‘³‘*, ; èÝÛ�ÍM~ŠùÜ2ò‹Ñ¢C|Äfgå�µ1@/ÉÿlW_x0R’íLêîÊŸãj  rÒ ß +B‡Õ³kó€�¡ýƒó¿î|]á5tHV ˜žÚ |ë±ÏH…Œ ý²j5»¨c^þJ £aæ( +ó«â:WHCEÌíÄ2cu<®íÞºw3ÂÊÍþ¯ÀT £+SqDF9dÇ=õó{Ž|ÈÌÌË%ì¥w 6ü¿~Ù®'–°O‘ûă�t6î>5„ +4Ò·þÇ.æ__¶dƛƽ'Eaà½ç¦·ñn7â~ká¯Ðq�LáU´Òr»%ÜdU 2wÐY)Ï•{4‡Ö™2‚2Á”=§é¾ Ýò°ÝÈKÔ©‹G»/ó÷ŠÙ� ¹¦­úÔDH$AM‰µûªÚDÕ‰>ã`ÛÝÆ¯uÈ|�ÎÊžír�¦}Ýá)b,J×m nZ q@¨Š¾Jûi½ž�çlAç'ÊÐ�ëh·¿íÎ}. ‰:wñÈ›U.æAVFNÆóaÐ+m£iÓVXɹñå)Ä�nø‰ÿöRó÷b=T +w=u8¸ô‰×äo]¥d>ŒYÛK �‚ëѵ‹-)ÌϽ Dâ7£a3ÊÛ€]c^*¡‹è�YáîŸÄÆÑ‚NOغš¼œÊÒEÕl~JiÉÎ$Ø.êøý™·ÌÙ@¬p 〉¨°¬OÌúú+y z){>Âï4¸‰ŽD ]!öÎxÚaÉ39\Ž#Ñß×R/³¨"eIĪ•³ÇoYhë ä;èÉ]‚o;ýš–å͆1DT/ïC—†õ)E’ÐEx ŸêyQCƒ¸X ^ÙÛ²â³2òMD¬ð0ŒæJÀ|Y\œ•Y˜sÊ€à.).1>)nµŸINüNCN©”}Iìàá¨åh®”¹êlSAœÃB&4õ9Œ>=E‰–zͧágn Z»/ôC±*Ë,–Tª˜·$>É�n4‚�ì(Ü‘·ûáMÔŠª };v[qE‹ú(Џ]ÜpˆðP®Á` ºy^¥Nb,†à©¤‚äªÚswï‘NZ?†r8`¬‰%‚¼>=il$á5Q--{j›Ïb»s_ŸH³E˜œÿF›¿4õ˘+@Pûã×8H+<¤C25ž0ÝS\ +›ZRK·4ÀU('èrR:%Þ‡i^ZU ‹œ ©Ï ú£¨“„»r Fktœ1aç[ÛÒô†i°õ⤖ãíG‰Ð…Ü·$¸O�åoÔ�:y/ûÎÑ­{Z«�‰p<¸tkVÝžæB+Ü„ŽÙ0 üCgûÍ"4�³ÛSÀ $IžÎ«‚h G?¸bÅ׺ÖXÕ 7 rL'nBeæM¿›Bw•|Jv×Ô$7Š[Ag\F„ûú¤¢àªé@= ` +øÁšÊ5 ±DøUfxâ‰ððlÍZѱÝ8#æ“e§¦¡ý®Ÿ½"ÂþÔOæXüÁÛ0 +lz–n&¯U«sõÍPY»sò:b>4íô€S×á +HÑ�[K÷—Veš‰)Ý´ $º,©V¬-«Ø£¥£5«`ÎxQ¸¯—��Ë·oÜUZáÎ d{�4ëCÞ£®ÔqEGǹO DD®YX U¡$ô �&4­·–¦Éµ¬~¯¾O7£mGœã .##Êc4A�hÛÿ.g Áqh3)šO‚dsRf¤%à ÕD–Ì<îíý‰ÍO(J/„JÈÛ�•O°A¦f[¼¶&Ój¹ mÐ÷lZ«Âp½$ÿ&©/ ·œzÒ†õž\LÐT¦™“Åí°2’Óè ê´Ð¦À«{–~¬;“ò|§-È|réâ¥[…ÇÁ†îO­¦‚%ÑlªRkÎ¬Õ +w1âñíºL¦Ô42÷vÁ±9å³�ÐLêMGÐ`ŒÞtfjñmdÑy­ŠNEæ�RVÓM¶1ÄÈ}ó>Æ›ÿžòÜ\þ!ŽE;TîÞm6C6î°¤B2¯KJ&Ô—úÄÒùàÔ¥‘ÚI¯]¢ü÷s*€äX +û66> +261 0 obj +<> stream -xœûÿ -~6Ì ð +xœûÿAJ +w endstream endobj -253 0 obj -<> +262 0 obj +<> stream -xœm•Ënâ@E÷þŠš…¥d‘¡_¶“!ˆ%y(D3kbŒ¥Ð¶üXð÷£î[�h4 ‚nW¹ëž*SI¼no–uûÁ7ö§¢7Ú©¯øfõ´ë’4]·Õtd?>3×\Ÿ£Ã=u}[ <Òj³ÞøfLÒtã«Ï©æsÎÿRøÐø¯„PƒVÓ0¶Ç$Mß›ñ“ïé -=Ѧf?6ã‰Ôu’¦¿¸šÖß“NÒôÑ׫öÌ ÉLjÐìµo«-�´o|ÝK%úum¨nªQTü[w]|x{F>nü¾%‹¬zê$“ˆhöƇfû]Ec×Tó‘—¾æ¾ñº:›ýÜN]÷ÉÁ$©xʾŽß³ÿ¼;2Íør*”¤¿ŽÞO˳ßOm}«¶æ¡ÛUÜïü�“¹RJ-h^–e¹ÿ‰9ûØWv}L× š+•»ET*ƒ²QÊ!v•AP9Ô#T•QP·ˆåPwP%Ô Ô”xY!ój�˜Ô{\ÐÜ(-™eŒYÜ¢C”²¨®ÁgQ]ƒÏ¬¡Àgq§Ÿ»_&·Ÿ†_g|…T>©¾Ôà³K(á[A ŸT|JR|™|9h ø -LÅ€Ï>@�/Ï/S3`4˜“FtÑc~™€g.·�ÓÁ¡g�Žp:©Nƒþp‰�3CG 8�Ô§§•9"Ó‚ÓÀ‹g�NZpfpfÁèÀhÁèð¾ÙÀhÂ�¢*¾úƒéY0Z8·`Ì$F#7�Ñ�ßÊ,Å�0bBVñ–YaDÌ�Ñámqò[ ~Ð'óD'œ¨âä}Eï8-Èfiå^pfpîdŽè« ŒF߉™#ˆ38w`t˸Xdƒ„6ée§USß³ã"� ,l«Æóe#wmžŠŸ¸ÊÏÿ‚z)ÿ¦~™® +xœm•Ioâ@…ïþ=KÉ!Co¶BH,±Ä!‹B4s&Ú–—ÿ~Ôý +ˆFsH¢ç*WÕ÷Šé�·ÝÃÒ5Ÿô`~JñN}3v=¬Ÿ÷m’¦›¦Oä‡"Gîíg¢íšª§A¬·›­¯‡$M·¾ú]rþ—²¢cío ¡‡X�ýМ’4ý¨‡/š‰;<q&±uä‡z8 yŸ¤é/êúºñ3¡’4}ònÝœÂp}2ábòÖ5ÕŽq¨½ë¸“ø }¥…««�Uü]�öm|ywî:mý¡Ynl9S!&ït¬û¡;‹»8ؽpt@äµsÔÕþ(î.Ã~ îÆ¶ý¢0¤�ñ)yÿNüËþDbÂÀ×§L)ÔíÑǹ%.0ùýܸ‹P±jõí¾¢nï�”Ì¥”r!æeY–‹ÐñŸø£ÄkŸ‡êϾ‹éj!æRæv•†Ê LT…�²ˆM¡2¨*‡z‚*¢Òê±j +UB-ÑAC­ x–52¡6ˆq¿§…˜k©8³Œ1ƒ** ¥Aw>ƒî +|z>ƒš +|ì +|Wa>¾“)ðÜ�ù¸ør8¨Àg–PÌ·†b>îø¤,¸;ø425ørÐjðØŠŸYA�/ϯ[Ó`ÔØ“fF¸¨™1¿n@ƒ3çjà´˜Pƒ³€#œ–»€Sà NÍ1pfpDƒÓr?pZpÞ#2 8-¼3à´è`Àiá¹aF| -WcÁUÀ—�È0¼1à³\%ðé°Ü¨V7_±uFÃó0#ǘ.f„o–w‰y,3lÖ2#>�–9foÀ- NÃuÁ™q]þÄœž[p�YìÑÀI Î ØÀ¨Õ”'££cƳ‚1ƒ³i> +263 0 obj +<> stream -xœ}zwtÇ÷ïȲ´‹,D À® ½— @0¡w½cŒ� ÂÝØcË]Ò•ä^qÁEË0˜¡) :I @€Z SgÍî;k¾ß÷~ç½sžÿŸ]ÍÎܹwæÞÏýÜQWW¢P(>šî1fÚ �ý¾õY®÷ -‘ß�—:H¡… uRnDøÐ¶à:²ôw«;ª­]ëT�QXZÉí“Ö�Alñ©üp¥EWùßÏ-º¥ Q5Ñ(„Ñ«WúLZåæÕsL`P”ÞÇ7¬—Çà�ƒ†õ>~aaA¡_ Ñu@xÿÀ�ÕôþÞ>¡>¡Véûùz÷÷ [§ï2>0 l\¤·OP˜`€‡ÛXÿаÿ•áMOÿç}ϱãzÉ3{­Zå³ÊÃ?Àc¶�wÓC<}=&LŸÛO ¿Çl�©æñðõ×ûx„ùy…yx®ó õˆðóóp óñXõ?çôm’ß70 ,´?!²ž¦HÆ6 �tá¥Ò˜B�“^ªÜ\ç¶h–Þ Z4w¸•Z¬«Õ’aµ¶hq±yE�-Ýšn³ÙÒZ´T!„L“Mׯ`‘MÕ‰ò•l‰tw2MžàSrHÑÛÅ×å†ë×]_¨¨Î¨Çªwr››uhÖ§s›äö›Û“æûZx·¸Õ2 UÈG#Z“ÖúÖe­ïº/Ó*µóÚ|Úf·®�îgÝßmgµ}ýñÎv½Û�jïÑþÎ'_v¨èèÚq~§N�¼;]Æ WÅîâZ�):Ïî¼õÓ¬._uíØõ^7}÷fÝOõ˜Úã—ž#{íÕ½×—½NöîÛûdŸ×}Ëá°4é°âðaê<¬<ÜVê*Õ4vUnܨ“&Qgã$NÓßPjpHíKiZ„{Í-ºù¢ö5taïY‹…Ÿ”Êi£�Š9Áæ0¨¿�ËÙ#J’™Kd ês¹#q¾" ãÖìY¶e1ð¬M_F˜›ˆ¿ð’}± ò$!W‚öPF©Î‚ BË×쎮…»`·ß²¯ôÀášÃpêÖU,âY"—¾|Â(à5Ì+ÎNõ[¨g™¢ò6�?§”ÚQN·vÀÈøPðƒÐ¼ð"¯Çà&_@ws›­¶BÊMþƒ©™æ Ö’ oúSŽº}O[Ò�éñb"¤¤¤Äò¬ýYWŸÇÚz‹F—ÁeÒv¿Õì‘gËŒ+“>+qß~hqµÙCi¢IcuŒã6™RâbMé9ÉO™bØÚÕ«XYY�¤¿ôñù£x$í85ÅÇ1û£yí=$£¶ÄÇgœHº¬ ˆç¾ð„Ù0Ñçö,ÿÍA•ˆwÎNA¼�k.Ä J7ö#¾ã€G|»jbã�eH”~ùHZ+R‘CÒOÛ�(É�lA{1�¸dvD|÷X‰ÄEñµî]æj$͵D¼3x!’–¾/ŸÛŠÄcY€¤\Ï$$c®Áy8à€Sp`MÅŠ|Ä{õ­�ð -´zŽD=p•W9¯}´¦xÝv8Îí—iø*cË6Ú+�(÷{Ú�pœÀ§§™£EM#IU•A;¿t¿újÜ9í/ÛÛ:¸Ÿ -‘�‰žHºîsŠ´†CÒ7ÅÓ€Déœ*€C¥­£9Ðè¦B¼Ñ¨.@DåÛc‚ž ƒ¶UÀûÁBc(ðO¤S:mžcK©£&¨(88xƒ_HA`­¨a+ËéÌS·Ê(”JÝ·�ømf]þÛŽ£ËOh¤qÒBÝjXÈk_‚Kü7/�^0õ +¶¬-äµ6„Ä�æîÐgyí?NÄÝG¢ŒŠA|>:ñÊ�/ñO–ÊOº;�v@’4ÕÉü=N$Ë«‘Œóš+ÀîMް²‡†YF?C­ý{‹>رK„ÂŒÂìûÆm›¾ƒ‡pùÜ€›vÙ‘´nü§éB×!ùøÏnHºý½Ò Ý ÀÇãa#¿1?6¿$;³€ÄýØçˆ/bŸ!FžEüÝà.°�Ø`,HŽX³!6äE"@|:É”ÞH´/áH†½dK~~qî6@2ye$ q+2"Ö¶ú/×÷àµ÷œÔ¥ÑM·xú¦4bï)î¨Ú›ÉS^ýý³„¯EMÙ¾Ž˜rwêr‘ú\Ôî—–Òcºú%»£aÉÂÐ9<¼Ri¯±ÎÐç�êg â³�ñ·YDd%œ—Á"ø -Ñ¥›+³kjÖT®¦€÷üÈYkWF}«³#Ü©âõ»¤ý£µËQñ½k/’Å�ØôGúº– ^yÞËÜNò,�C¼ý•³ñý Ï‚ž …om+ -Æcdµ qqmH4Oþþ<Åà‘ $$š†F$¤‘ôšó™H£¹¡Û"þ<‚ ÖüH–0•À&qˆ¿(*3ß½_tYÐs10ÊËa�1Lžá×ÔÔïD©˜ÛoȘØäÞnÒ®9Àê- Ú÷ÉÒ‰«k/$íµC€×ü"u­VH¾ÕJÉרëL¿ÿ”P!¾;èDl8DÆz"¾K‘á]@|³6‰"p)bc–I³´ržµ—x⛂KH>Ú€øØgÅ)Î[–(~2À.øÁV¼žÓ!²)Áˆ÷êRMOY•Eü“&Eɳһ%HÚºŽø´“å˜î+åï ÍMPGm[åïo«Î#>˜ü ‘5»„øxÃï" 6¶¾‰„܈Cd‰QHWŽ#¾½¯àëYí#Z B¢x¡@¢Úø yê@¢Z3�¨†tã‘´tñï¶ÕHÚ4\Fü£™Cpp9€dLGƒIë¿ à€rk�…×s+ñžÂñ¯½žˆ¯Þ;ÿœìäY+öDÖ\à'ˆÒµ^ˆ¯Ó ¾ïqÕ$k.Å__+G¢ðo@|·¥uÇkèKšUª Y®o£KßG«5ð;}ý¢Þá~ø]þ0Ø®}% kk+® ø5@ÌиDDöp%â»Îâ¿íŠÙ-Þx6~:©BR^üIñèb$^^nH>wÞ$Ñï “C…nY1’è÷-�|RºÉ@Å+��j¢ûkÇã»T ìãás�µgÍFyß  »H§ŸTäÐbe�®£Å'Y±Z#�ù}{„â˜=Ý~æ�ò^ÃP]…:u­è2àé'jX�ˆc7 ¾+9‡H&#¾ZñÏÚ³*ÄãµNDÇsOÄçÓ=“Ý ®jtòˆçÒˆñNY†xwa/Ä+¯"iÝó(’nWG €Äßc:’OÏ­C’~ù’eƒ3‘$·¸Ï¿¤=*Ä…“«ñß½s!)±þ_OÄ¿WË'ü#'¢3Æ ˆø‰'o¶p–ítÈÚ¦®OèÔ2Úö–ûá§K«hä}íÚNRéè|®2~[ÊVàéÇgg¥™ÒÄxX°v �¥Ž À'™RâEv�‹IMÎ2 Õ’–™‘S{òO¨‚ªˆÂ5žika|·xõêÐððhà™|^™3ÒLHÔw €ÄU4¯}k¯(¨·…—…Çx�ÿ�¹Ò¶ô£o(O›ù·‹0V†ðšjpÐZ;=S­ ïÒÃ/•R7zQG[¼@2û�ÉòfžÔ�i.1¥ÈÆ›  ¯ÕÉC ØXÃyÅ¿6éÕ5pÆvNÀãnà~Ü×Ñ;Eš|—;h×±t«º:×V-÷<8¸ó/:*ƒ×°–MØCA+h–nd½|4¿¹�ÄM5ñ}f$ʆɞï$š•$­.OE·õ@¢�_‡„<¿Ã;¸`Xbô_ð·†Ënï ùøöD|8ÉÇnˆwÛU#éµ®ñ̺R$=ë–#ž©[ޤ×-‚xæá—ÍRÍ› æ„DÄ{³ß#><ƒøËvÄÇ_Æ/3ÉÞœ¸¯&HH0AÒ#ó%—T‚¤£ª% qÿ¢� øª±±�!ùØó”:{÷’ÛO~DBÏ‘(šmCB\ÛÈÑŸMÛ„Äeb6â«ëW�¸-˜H>ú´�´ðx‚D=õ$­|×#Ñ@’Ö{?â/Þ~ÀZª�(a#"›´‰K·Ä·Û‡ÉŽûŸù<â¿%~ˆ÷;]FlˆÙ�H�ô\%·•Á.Øm,•£Ô·€Xߟ"qéR‰øðR3$âÍEˆ¿<|�dX† þ:Œd¨ÍñÊçÓ‘ ¹%ñמ¨�|ñƒɘÁIÿ¯ 2Ä$56ÞÁE™×˜ÖÀð±†ÉúG¢™ý1".œ‰Dóúâk×€ø4ê¡|ªãœˆ»÷µF,®<'ï9®S¨QÒQÑ!¾iN�´Ûo@âþš i>Á°_–:¦ƒ -[B¬¼>�ÛHZ�1!²'w�4;�ø¨�O{7ªTH\n}„(½ø‰²s=bC˳¹�HÔÑ#q9ç@âšð1’æƒçñ´ýK…¤Ù¾�HÚuêŠD7q’nwož”§�4›×A4LµÅË!}·l¤· Þqi‰øJÕñÏw/ù.,O¥¡S›v³¡Ô�º\¢Þ—éÊKm:joJíè)ÛÄ!^w�o@|˪õê<¸f+…mpÊX¼c·Ð�¶K¤3¹Î�¾xоf´Àâ9oCÊú^²Á>øÑX& µ "Mæ^ÌÛ1LKVÌŠ;»¸úð„¥^ÓxxÙ”Y¨®¤Ç/Yç·Ñ¸T¦NÚŠá;8Þ4%7)öˉÄã³g. ‡Ë×~%~àªì´»o¿Mç?ÚT¦•hšAGÝwQuaz²-^L“É”9cÕÒo`& ; -´/Ü,:¸³®´´,·öÃÞM¥áü*SB DóA…Uö⢪ó#v�fºÁLÍܦ¸ÅÜhGA΂_ÓÀ׊?_+éI£ÛZPºm[yù6�ýîúÿ¼kÊ�M€WyN{‘Ž»¦[ža’áe,±yƒ7,3†È«;ŸcÛ%JÛ¸ïí³›àå.Ú5G¥éWë�\«×îu§ŠKÔ÷‚¶¯TÝ–u5À}ÕúÅÞ^€gí#‘L8ê‰dœ§S¤K¹“IÙ3…‡Z[H{ä»§Z˜µâ’1Á$Cl$Ã~v"ñúÜS Ó¹ÚÈÌ¥‚¶¯Ü½cS÷·ª•™±§„lµ¦?›ç }ˤvŽh»û«K´à¶öŸ­RWÝ¥Ìä%bãÎ;Æ<¹)ïûÍ–EpÍX$/d¢ˆt,W°ú¨ÿ1�‡�¬ó1 Yø¼9›æµ¨½I›!–}áùÑzÆ)¬‚… ógñpN¥ý‡u5¨hö‡ŽÆpÚ›åûöïü øÓ—ƳvˆëY›aˆ‡]ÿ™!Žß+)ż¬à— -:±LI]Ù\]îu$Ó¿;€$xÒ„½qgçún  ÏÓï‹ ?#+‹Oâ`DÀÌåKß77 ¾{å”bcsO0ñ)ÖÄLAÖyÖziH)õ«Ê�puŽßÖv§žRK½dæ�é ‰Àë󸦼¤ÔPK -l´°ïx3;c‡�§Uû¦ ù,„Å#éjUOÕ”<¦miÛžO™«ˆxÝOF?çzÆ/žÍÓ�]tˆ/¼Ä_º¤û ùÜD¥ N$nÛ=é~O$ngœPÈÓ0™%Š?€dÐÐ`$ã7M@2ãT*’O_#™çÞÜ› `¹ÉsåÒ°àµaËeÞ«%v[ -w(Jn*¥öô�®+Ke­V™­f¤òùy9ß ²»cLðþ“B1äûÉÞI¹Lµn\Є) QYñYå¶‚ÍPÊW‡æDm Ž[ãµkÕ1á Ô/?ÁÓ1ÒUÑw»ËwÉÛ Á¼Ôka¹-RöDµP¤�ÑËæbžëéÜÿÿIŠlTê1ò’çXÄ«gfâ³UA|bZJZΕ”ßfúu®_TPppaÐNIëVž€„¯w¦e¦óÈ ™¬êøp{©û«ótÚÃIçµ·¶¶up²­u"½>Âq�ª8êBÝŽü�dêj'’Ïó<—Ï^Y\)@–uç~ âë²êï9ïßs"iÛÁs1ð“†zõ™’väZŽ¥Öeð�.ÜŠ ã‡#½Ü¶VÂ2c°¬í—2­ûDZÎØ”¾D`½™§šõåVdš. z.¸©3¿–Ê4X“{ù çÿ«Í/à�˜C±ÃN3ïÑL»²ÍPúuÛÝð‡í<„‹Æ­À;"9Ö,>³V”*¹[ÚÂ5í¹Þù¬?o‡ÞH!‚…ÛA•OæÖÒ>ÀoQ;S“ýÅÆJÎ'>�5"Õš]†ŠM2AÓJݩ빇w÷]üÀ 6гÒëDyõ_îlP‰±)Q1‡mލÜVPR¾Ëwû¼q_Îë,0N¦Y®qË 0Q=UÛT{à{Øc”ղɰ^=Ú”³S¤¿ÑP¶�c­Åî¼¼õòÏÂ�!s¸Ñë||íÃDxP(Ríâ`]èÔÎ<,´#M[º‰*¡ÁŽœ÷×ç´×¤L‡n%D¤­ÛÀ>¦SãósóÎØ·ëPIÓ^Œ5™õ ‡Å–5V^ŸÊ˜²â`Ä$Ç )Fÿu>kùqÓ@ -SiÉžU¯:^jZ"6nã| F™Ùª€ý¶=°ö+äáÆ&Z÷‰ðüçcϘ¨BÂÿú+â˼©Hš÷îƒøÏê:0ð±†øùKËÖZØ NS–ù–>å 5U -Úá>]d§½íV»RNƒuvZ¬fü:3k!,¦)ê�¹–�m¯¦�a×üö)_�4¼ñ€^uw³y¹ØXÁùšº zé7n/Í U›¸t ë<ÓªçÓ¶‹´ô G›;LŒe?0ÏAû•J=íŠí·iÁ%¥4—µÐI'Ã9ßÁfsø¾ÆÊÙsÀ:°^´åÈ»â%ؽsÛ.žMáüãQzµØê öí²*Æ%Øöˆ“h¶î[Ķ;Ç#ží‰¸«¯ñäO$Ëš— xå…$H¿É׆íHæg~‹äÛØ9ÂeØ1µ`&¯auMARA;ÞSÒÓ]¹^ío�j™ ³ašÙßÄ;ìÜu[ÎNh!ÐBU�1÷+!Ô¡®2�3ƒ*xn)µòúPîëÄx_X!°BÕj›á¦ ayÿžTÒAÔ¦úå*^|ŽÄ½Ò€¤CA¢[h@Ò>€”—!i9ž i±ß€øæ{‚Ä}‚!,jéjÄë� ˆWæ{"Þ¹k@<»Í9£çZÖ -˜L¨f­Nõ䑈�LòO·d!wÿôÀê²($ÍÆ»ÉCY_x#Z†øX }A|ºð?¢àA¢EâKZ"ÞħHÌøè—27Ǭy -yJI7|X„Ç?�ܺ¾"´,&/«¨,êÀêÚeާzVÿW¨µ¬ÕŒž¼~�ϲ¥«Ã¢â‹òòÊ˶To½ø|›Fí^Ý0°Òý˜=ø,=v^…öÚqºJ×™æ -)“5ÅjJ‡Th*™Y²òs‹ø-5ªïVœ -º H‚}Î’Ù_"YnQ’ PO§Üüz bc’ yáD\¿Á€¤sKÏ$+â…­IH>êƒøë‚�Húß�‡ÓpõìdpY;� Ÿ¾P>kŽD¡¹‰H{�(žwEl|?- 2 ÕjMåi$—ŸhMRñÝnÏ�ñD|?M㇜ƔÕ3L&Þ¬ö¯öÛÕmdfhÏxgOˆ Ÿˆdšó"âéß–#ùrÔ@Äg‡%Ò6�‰Hú.Ê@üwY3$=íˆç¿Û ˆŸ,DçÝŸ¯ÎÛƒXÛi(byÕ4à™ŸO -xí#s‘ -C† i&y 2ëi$.Ü�à æÄXQC? @íô—ä^¯ÜáÐé%5GGÑvô :ŽNeé—lŒÈF› °Vu­Âì/6äb’ ô·¶_¨—™²ªDé gÏIs¯Ôôës¬=›ÒcóbQúŸá;ܧwìJé:ÍÑ…¨7²áóf°ÎÀW¯‰·í¥ -nwfÖa›C½Ê4Á< fÁT‹¿•××p§²6­k9¿ä¸ÑB¨^*Rk·^¥JÚ­œòõ§+Üë¨rh=þÐóEŽhUHWuÕ‡/äî„8¹>‡1AcD"¾híD|{Á€øò™'"4¬1">ü»ñÝ…µˆoÚz#q˜ Ñ�bII5ñVón(“¹ÃÍ]cû°.#×ûˆËaô–µÇRÍ6°ï¨(­ÙVæï¶úóã©’’Wר›WgÝ`в§.à þ�ÏŽ÷éçöfî|,8¸ 0Òk`š-TUÿ¤¯ôÙ3Žuë6jà”{éXAúˆÛaÍþS(p¨ýM3Ìsa.Ìl2t>÷§-Î_llË1-uaÍhgÚêÅê!hêÿ»�ª¤¡Û”Rƒô‹®ñ·)%%^�Éiìs‰¢¿±ñ—¯�¸\ÊŠÏlü\j ߸™Ó[–=o3‹m+`,þ€|þIß³C”2¸jSª§ì 3Õ‰™±t$³ðt"+i¤jGÒžÞ‚ƒ³ÃAãwð´Ùåu3/Ó‹ª ·7 ­P{!­x¡”Ú…ëèx:€¢ÞÔ› ¤Ùx6ž d™7ó¦ƒØ :^´»vgmÑ\Cu÷ÿý—ê±–ËÚôï.×/&G(î4´Ñ2½ö [ ++?Ç£W¢×FŸ ÿÈÐØdH€äŒÄ4H…ô´œþ ³âœçÏíõ^ºNÐLúßu§WçéêsÊ6é�mËáPSm戱J^ö@|ÛΉ+n—ùœ;Hz�9<ý�òÖ\ÆœÉȾ‚‰xå®P9)Ƙ” › ”7"!.—¼‘ô{7 ¼°È¾geÕRa¬Ž -__éS0 ø®]§YKX]å–Ìÿ-}ÇMÈdR¬œ{]¥¾ì:çkœ$ü.eé˜+ó§÷àÖ�SBìL.Ý´>9zCXAl^Š)ÁœØÄ'omhUá^w8|?-ß~D{‘ž¦ïu?Tœ?7ùºÙmø7ýxÆw{8¿eSBŠŠµ�’4‚ø/¯NÛ<£ŠË´¥ßmØ¿v;Vî¿ÅË·nÖͪUõÿ)"Žð'Îì»,h¯ýòó‚oD˜½löœ ~Ô,íÞO¥ý±:¬ÄüøQ_/9ôë àÜzhÿμÊB^SßàQ­ t�RúSº­cÓ7°¹R†*±Ø¸å/ ïàÖ˜g™AL´ùË{è,”˜r×ðÔðN¥²Å§'çC.¤Ùl™<�’êU¹Õ;+OȺŠ�iÆpˆ€™6?ù«C暀?^âֿ�ŽPÐæ{”OX˜Ž>~;\…Äõ§$-ÛôA¢2Ië'¿FfDf 6üTƒø¬MD6d6â‹'¿òìñûáªä˜¤¨âÄâÄô¢´<^>at¡CZ¡ R­²a¥C7Nf˜.|ŽÄeV=â«�g‘tÜñÏB>V!6n÷DÒ,ˉøj¶‰b­g$â+NNWwÄFIÎ gžéßU”Ÿ~Ã"Ÿ WÃaÛ^¡Nš*̼ƒ›^Y!’f WD’R¹…§ Fâîÿñ´±I·¼_ó¢Êõ§‰-yćú­ˆ¿uz.Sv±ˆ·o�âõêë�–ÃpŽÉ�åÑ\ W×R²‹*vQÂ[L*HN�ÍNóö„y•I×9´ó+÷ׯ&ž×þRȾÖYÍ¥±ÕÀ)9\”>çv†eþ÷–@ßhLP}>uò7ˆ5l âíHzï2 éÞÝI;‹Ië�‹‘´)4 éôô>aÊgH4§!>*w">ºjd•v”uÖ`@|êGByº ¡RWf_'hóü#C‚Ê‚«jJ¶Vˆš»áef=ZF�:Ü©ð'Ýñò‰]#M¤�tW -Ÿ…ø¿¹Çú ì¼¾Z}2÷?tv´qt�mýÉ"ÓÙ{Í»M2�=Ř¿M4Ó¬ó úR ×t n·oÖ2[,X,Óa -Xm›x푒δUJ1œ�ê#Ö“|®)-Î`LŽ]´ÂGð‡è2ÃÑøÚøÇñ[ø˜ãóvÍ/ä/Ñ¡:˜ë». ñ¼£ÚWF%ƒ±¦¤ ð3i©ÚRfÍ8 üy5í‡(Ý•Y˼ûrÕÿú�'¼†v wä®§I©»ÃýØKé‹ûk«´‡>m˜«“!T£÷>Ä÷߯G|[8 Qgæç�R�»öM¦|Ïg6ëÃF³oÙB:€ §óÄ?àÚ¶ªymtVÔÞ¥yÀ§¦YóE:‰Ûf-Ø%TU«™Æ¨šmoõµðúï¹K™±!â*C¢)�×~Ÿ°pꊡÀû±õ›éyꤋvœ©~g­r™›5Ìù�6°Zyí!k*¤mËÓV\¡É'hNB5=[JwW»Sá6ýñé˜z­$-£ º'%—NÂ5þaÿëìS�½Ö«/ÔÀZ±ñ4—²1>ÞøMzºRM#`Û¨ªðümø�‡›#n1uÏbi¥./'«T =Ôç~œ:rÄØ‰ÃEÖOÍ~r¥»é·Ü�F9}t?‘µSoL-5tËâ¤XEMj»©l˜ÒÐE×xž[�`!ó•›á’í gS4ˆæ¾J´¥|noZæ-¡ÀÁÆ«£ÁhLÚȳÀÆ“l­tXg7YC�g_ëóÕ׳“|ÄÆLnî¼Ø…²g·´4F³ÝÄ;¸Ås³�‹Ò>î¶ú&óýƒ­¶%d¤¤C:¤§Ú2ÿCz8èæˆ,ù�þ`Ò9íuI+gìk¨RýìöÞs‚öqTÂÖx^{3>ecóÚë•]˜Ä³ù®ì�ÿ;Ûýþd»ÚÇ ½[—,×aCŠ1óÄwVoDÔ?0¯½ž$Ÿ>eÿBÄC�—�ïÇZ,`."SÉÑê:÷Ÿ« åÿI÷ý7y´~'ÒkœÒ.ÇÏ -ô«RÒV®7£åâE¼'âÛD‚ÄÕW®©ôýØÉKç¸\cšAˆW¯ Zá˲ï–ó’¿ßB¢õ^�Ä­û§H¸Â|¾±€“Yµ‡r†'×Ý œˆI124Ýääõ\)<³Ùá4\7î^ã5ÒûjÅE»4µB)UÓ]…ÚlÜȲÁȧ4®àÖ'A¾yHRWù¶Á+$*î&޵àélzœ.¢gÙg b}Áû›DÖ² †KKd˜” B"æü€È¾IFdþ£¥ÃøÆOßÑá ¢#aû´¯m_-­�PУW”Ô)�Ó56cFNÈ踑¦ì]âÝ=¤U\^JªAˆÄ÷�5ˆ¸ì$â›´ÙˆÏK¿âÙ‰F_ÐÓb€ÏTþ¦ØÑÂz½ºNÙ>xqÈ׃ۥRW»{ÝýÉrÕWûBRHÃt]=†©€v8{ÌB»ÑÂØî_¸ŒÏ]›:–òLCM:íÛ.½º1Žiou¡¼xv,9ÊoäXVgï¹Â*X™aç3ÔUåeeKõ�";ÓÖÆ|ÚýFGüm¤ùlµŒóè'{hÿ=Šc´^qÉ™É<½¬¦çä-–Tkzš5�ÏçRÒ“Smü»–jCJRÄñlž+Äe$fù†–ê [Zjj:ŸÏ™Ò’S“m&‹ØàÙeu|Jb2xM=슆x&èìïâƒ9Í/áÕ }Šc/¥ð -¥ôy¶ŽvºK9ªÈ„ì¼\HŠ“Y¦éÂÚÏ–²^ԓΡÓi/:ŽÎ•¤KÃùmuª‚²üb«ÕfI…T°™­&« ²�õÖrM)&“Éü&0Ù̹1´åpêÆZSëñ5°<`¨®mc–¯*”®§QuÞu4*Â];ð횪‹K7¤Æ¥ øaÖ�ˆzÞ[�;üÀ—'¥'¥%g¤ðZÏw)fUl´)JÔzD˜r­³!ŬÚ¹~c¤×Bý”¸ÉüuIý‰à³ÓrR³ÓyM*8è÷úýòiŽ�~jWÒ×mWY'XšÒÁ&¢%Ÿûµ@N é¨ÌŒCâF+f"!Êf¼¿\t‚C:[Yx¨¢¨vŒõ¾‡zF<øŠ,ëîéžÔ'b¡�o–ÇX¹ ñææ}HÈŽˆù«&!Q4tçç²Tõê͉ׄj�ÔJx �ÔM‡¤`7AÅÍvNù•›—rIõ«Î<’ON$ ÞŠpAÒþa♫œààJà´± -vî&ˆó‡E›6-çÙüÆ'ª”Xcr,l’ƒ]ôb$-zNEd v$-¯Öñlˆldc‘Êœ’”’q–d«)ƒgÞ UbYtÆ|àcj;5„ƒpÜZcáõrQìÌ�GˆÿÞî�X_?ñÙÃWdû!!›g 6Ö D¢˜V‚ØèÃÓ/ T”FÇÖª¢Nز=��s¨7›o˜*áülÙ*KŒxTýñ鞈/»½@üGúC“Ý[‚„ì¹…ÈNßB¢Èè‚ÈS^Ã:„—ýH•RDµ¢ŽºÒ^w•uÔE—Ï¥Û ‹·_Sª_æ/¦¨‘¸>­C|Ó5Iç£}/ÞðC2avg™y5ë0’;Æ ™œO�x®&¢äËÕÆeöꦫMÜÚm[!ðú�œW¤ÉOlôáãWy"B³4ÄK›�ˆGß ˆµ#ddbüIŸ½sÙW#�,˜¼�×ü/€;]º +xœ}zw\××÷]`wFÔ5²®%ê ÆÞ5ͱkì±k,ˆ èJP„¥ïîÙ]z•‹²ˆˆb‹ 5jì-‰Æ®±E£Áz/zÞÏ`~Ïû|Þçù¼üqùÌìmsî¹ç|Ï÷qr" +…â³iž!c¦Ð÷Ï•Á:÷µò»ñR{©4¤Ž +Á™ˆŸÚf\–üae•¥ƒS�²#! +s ¹}Ö²#!ˆÍ¾�®4ë"ÿ;Ó¬+qt +¢"j…0j…ßrÏI+<}ƒ|‚ÂzŒñóÓyzõtýrÀÀ!}¿ðå·®£|ƒü|}]gúéüÖøùösužííèâ·vµ«O ëZO�§{ ç +×`ßžk]ƒ¼=]'̘òUïñã\ûöu ôôtõ +òÚ¿HHH¿•¾ÁýüÖ®ì¯óñðô ô ì¿Ò_××Ë= ŸwÐ]çñ~¾AãB=<ýƒ|ü|]�Çú­õYÜøôß÷;®§¼²ûŠž+\}|]gyz4þ0ÈÕÏËu´9}å ôs�åéé:åÓ:®^>:O× o÷ W¿5ž�®!>AÞ®ÎAž®+þû~^�û÷òó +ìGˆ,§é’¡U}Gmp‘4&—úf$©g§Ù~Íš$7s†fMíÎEf‹Ùb1§X,Íš]lZZcM¶$[­Ö¤f͉‚BfÊG×Ê `–�ª#!d¨|É.d¦¼À䀢—ƒ—à § Nÿ8½RÎWžV�UUq›š´oÒ» sžäü»ó³¦{šy4»ÝÜ·ÅÚφ·$-u-‹[ÞwY¢qÔÌmõE«ÚVÚ3Ú¿ZÏlý¶MUÛ^mO¶smw÷óoÛ—vpê0¯cÇŽg±¹è.Þp�ìz°ÓôNù�þüâXç%�Ït)íšÜmP÷vÝïõðéÙ½çÖ^_÷ZßëÏÞž½Ïö¾ÙgtŸ›ýšö2 ”&Tˆ˜S6ÉÚ+ +As ¥Hë9�%«v„WÃ}°™�î)Úw°ò †š5¥ yËÅ/�0x5s�²Q]!u+V”Ý¡Ñ祶”Ó®î?":¼!0+8Ï}[ÈQ¸ÉçÐÜ&‹5—rßßb*¦þÆ•5g»~”£Î?QEa²!9ZŒ…„„„Hžõ¥g´uY¬µ‡h`Q)\*mû{åNyµÔ¨bé«—­•R«-ð€æú§4VË8n£1!*Ò˜œ‘ÿœ)†¬^¹B€å•¡åÑHúIï_>‰FÒ–S!Q´‰ØÎk YHŸž®EÒyA<÷�Ì‚‰ž£Ùg°|6ù—!Þ=;ñ®F¬¿�(ÝØ‹øNŒñýŠùˆ w— qôÎFÒòÀX‘Š’–xÊŠÄ‘ J4S‰CjÄO‘8è ¾Õ~H]‰¤éÂæˆw¿\€¤¹×kħç6#qIæ#éÕ#I‡ˆkpöÙá$ì[Uº,ñA] $ü…\Ä}-^"Q Xá^Âkž¬Ê_³öAíÖË´솲Èâ ¶R$Ž{ݬH¸ µÀ''™ÂEuvIYžB;½v¹úfÜ9ͯ[[Û¹_r‘�‰nHºì©i%‡¤O‚›‰*´vŠv¥¦†ºf@ƒ³ñFƒ*ßt\,³®Þ�&�Ôj²ì…EöJÿ¼€€€õÞksüªE5[^Bgœ¼]L¡X_ä²ùpÈï3ÊéÒß·^z\óT/�“hW²Ð?^óJPà³éGè SFÃ(XV¸ºÄ�×ü¥_¿6Òt0g›.ÍÀkþ®EÜq( ñÑÈÄ—£¯üüï±D~Òýi´=’¸)nHæí¬E2,¿É8÷9ìØh*ž`ˆyðÓUš¿ +uöí"ä¦ä¦gØ6lÙ¸Ãåsp¶m¬ò·!i!Üø·éL× is¯+’®í…$H6ðцØhØÀoÈŽÌ.HÏÞ$ q9ú5â«ÈH„gÿлì3ö¥æÇ„¬ �XéòG"î2G|8 ÉäGHú·ËáPŠ­ 0;;?s ù~y( qÎ3 V·ø/×uç5j©Cƒ³vÑ´ÙL1pø®“ìßV¾+•§¼ê§1߉ê~òùÚ#J\¨ÃEêyQ³WZL�jë~ÜÑ_?.œÍÃ¥æë¤](Ϙ_TÄßg‘pîzÓDAÇÃYk äÁ-CðvnR$s<’n�ëE:�Óì­»xâܾ͈÷*Ü÷Ì.X‡xm`m$âÇón“ä9ÌG-{ ®³L¼=Œ›‡¤i‹ÞHÚÖý&ªÙE5{Ö¨‹4©XAÎ?¹çHÇ_ÖÒ[TegMhîþÁý;‹²bAH0D�Ž�J\µcó¦<ÛN�ò£†þÐM`üpÝuvƒ[aX „ëT%ð“uì�ær#oßÈ�ѧlÕQ6©_‘l–¶Üq¤ÖlítX\v@oOØgàLꮲJ$Ú!�|þÓ6$]Ot@ÒnÜ»`ì Êó-óIu‡Éx@ÔÒVÝß²æ¬e/¦`-™öuoÚ„6¯{N5‚š¥7ž�¾Èåí¹·÷4{ßþ¦]eœ è8ìmÜá)C�,Ö^�tH¼ÌÁH7§æÐnײ‹! ¬�dÚ !¼axѦ²ôÊÊUeË…Éà1/t&ÔA>?ñÓù0dW™ãatåÕ,+Ê&µ*ªpyuim)ý¼T³•ž¤jí‰ÒÜ(Ä»‡jg nk�hûqíogZÊiÎ~[¤úÓºó±ù9_ªÒle“içÕœ¦†u–ª¸yy²5º²O@20jMùùÐ'=k[L½*ÒC\¨âõ¾¤ù£4KQñ“SO-’EOØøGú8 ^yÙ‹�Oð,†C¼3´¶ñãq·ã‚Ž „¬Ë Æ"d± qpj +H4K‰â™ðH†u}R�HzÎþJ¤áÜ�À­ Ï 'ˆ•?“™R`“8Ä_e)ˆ>.¼,è¸i ƒ¥0ß$¯ð[bânQÊçöêS&6š·›´K°:3(÷\�øÔ³?ÅIÎCÞQ&übÈ�ípÄZ ¼ŽÓù#²Éˆj�ÏY¹Y¼GãÂäUéý$­\G|Þщã˜nËåñ¹¦ýÆR(†ÃÖÍòxÄ;Êóˆ�¾�Èš\B|ºþZÞDBnD!²Ø0$Š+Çß?Tðu¬ú ÍQ"Q¼R Qnøˆ„<·#Q®šH”ƒºòHÚ=Ù�øWë +$­ê/#Þjbì\ ÓAo@ÒòO=ءĒcæuÜ2@| pCüs—â›�µˆ÷¾¯åY öL–œßçˆÒµžˆo“!~ì~Õ(K.Á ß^+A¢ð©GüP؉*ƒãÕô5M+RÐ4§÷áEÃUjøƒ¾}Ugw9ø†.}`Ó¼‘†´¶æ—ÒþüZ@Äà¨XDöx9â‡Nâ?móÙmÞ x6~9¡DR’ÿIþ¨|$îîÎH¾®½HÂ?èyêŒXì0û*¢ñÃV¦õe¿eå‘Å6[~¥=°Ð_ˆ‡xˆ7U>ºœQ¼F¢\.b”×:ÄÙ&YÀ[ö&"žè;qÛéBÄ—«w…_âÙ6O‰(-@¤™ˆ›¼WA0¯.®oS¤Øq—&Ýu¤jzMK¿±Ð¯¨ u1³¯Ø7ìû–¹0#ý–~# nÍzÚÙ:‘N´Ó´'í©£sØD6QÇæ°ž‚:x³ôEÑ�ÇÕ6—šGÔëá÷5 ôx}+­Œ + +üÌ ÀGzÇ/÷-X_fÙmÞweÖöѬkÎz³Eì<ý2ð ¨yO[ÝxK›ÑÏ¿`ÎâlX¾ÊoŸÊ¡B»$IøÇfH>/ZŽd€â�ÀF6 Òþ¹íé}ê¬Í°9ÀÚ±&#=nÐö‚š]¤ÓN(2h¾c�¦¥ù'X¾J-�þckˆâ¨-Ùvú‘ãƒúÁÚRUâj;Ð%ÀÓÏU°Ç®GüPp‘î�G|³ì+žµcÓ•ˆÇªkí/Ý_NsCŒw!€¸¢¡–G<—DLˆwýÉÄû z"þSvIˇ‘t½:J$>®Ó�|qn ’äËç�,ù2I|³‡ükÚƒñ D\ð} þ³kÄÅ Öýã†ø×Jù†V‹XQ ˆø¹o +0sæ­tÈÒ¦NÏè”bÚú¶ËÁç‹ËièCÍ;ÚVRjé<®,zKÂfài›ÓOÓ’ŒÉ1b4Ì_=Ábûzà㌠Ñ"»ÀE$Ƨ)�hNJMɨ>qÊ¡<$wU¾WÒj˜C£­\î =øÚQêJ/ji³WHf½«E²´‰ufêKÌQdc€} «å‰ ½ŸØPɹG¾6êT•pÚzŽÃÃàíÞÜwá)U"�¿Ïí·iY{ºYU‘i­©èWÐiá�ÀûJTGÓвG{‹].?¢ƒ/N?u¥TóAr¥Û´P“Pí»Åk»GáàgZ1ZÔå­ß¼9/oKÉúB¡¤|ï¦*à�]6T\αµqSûÃDô,胣[ŠŽ›C7M9|ù¡¢+âÏkàæé#CÂ²Ž ã÷i¿ú~ùÜÙ>Hzµ¯EÒû�›û«þ¤#Sx5kÞˆ=´”¦iGÔÉWsôC$ÎÊ ˆSÛ#q<2D¶| Q/×#iqy +¾µ+ͼ$äå]ÞÎÀ�/ðK°löö’6wÞ!âã9HÚ¸:#Þo[�¤çš"ÄÓkŠ�ô¨YŠxºf)’ž· âéÛ„_2S9÷{0ÅÄ">˜õññ©Ä_·: >ý6z‰Q¶æÄe%AB’‘8$$”͉Ë75€¤ÿÐ:Ćz†¤�ÛIÙuöê)·ŸÿŒ„(^"Q4Ù‚„8µ’½+¾˜º‰ÃÄtÄ7ׯ qž?�|öE iæú ‰jÊçHZx­C¢† $-w}Æ_¼óˆ5W"q„ ˆlÒB$]}ßo"î¿çñˆÿx#>ìx±>b"8NÐqepÌZ Ûa‡¡HöR?b]?ŠÄ¡sâãKM�ˆ7"þúø-’!)2Løó ’ÁVÄ+_OC2è¶Ä_{¦DòÍ=’1_$ý¾ÓË“TZy;fZe\«ÀÓ$ˉzVD\0‰úí5Ä·NÃñyØcùVGÕ îØÓ1¿ìœ¬²_§PéHGJD‹ø®)AÒv¯‰Ë[‚¤éý^y×0Õàa°È¼ÖÂë’¹½€¤Å#"{vI“!ˆOZ¹ò´WƒR‰ÄáögˆÒ«¯‘8vªC¬o~6Ò‰*ü/$çìHœbÚ iúå\ž¶§*‘4ÙS…¤mÇ.H´g"ézÿæ yÙPc€i „Ãk´ìÒwȇôþâ]‡æˆo”�ï}xÍwfYJ5�Ò¨Íú"êp‰z\¦Ë/µê ¹)µ¥'µl#‡xÝižñ=+Ÿ/lЩ²àšµ¶ÀIC ðöõÜ}Òv‘Îàþ>wêâ~ÛªQ‹æ<ô ÿö½d̓=ð³¡XÞÔ|°‹4ž{5wÛaü¸ÂwfÔÙE£Á »ûNåáucd¡¼’½Ddåœ÷Ãbyš8a͇Ýp¬qInR$앉§gO_–¬*~â*UÙ\¶Þ¡óžl,ÖH4I¯¥.Û©*79Þ-Æ€ÑhŒ �¾bñh˜Cí7óöWÕgVÂ^ص±(˜_aŒñƒpÞ?7¤Ü–ŸW~~øŽQLû%S1g�)n3gÚA�£à·Ôï­âÞ[G:[Rk·–øúúú–nÙRR²E`8ý�w�±s½¢ð:žÓ\¤ã®i—¦ex¹~´z€,1¬•¿î|†u»(má~ +¶Ìj„—Ûi— ¥º_Tq¤]rªX½Ë…*.Q¯ š>REkÖE•ëy¸Ožµ E2á°’qnµ"]Ì�ˆKŸ!DØUš\Ú=Øå‚´e×�Œ Ð#dÕ#r¦‰û×n�ÆU‡¦.4}äW.O�<)¤«ÔýØ\;íS,µµ‡Û\Þ\¢9w4o–ºh/¥Æÿ(6¬â<"Lß7Æ}¿[³!®ò䙨‡}"Ëå¬<ìsTFàksôHÖxê‘,xÙ‰UýVÔܤM‹¿q{�h9]+¬€1ófòpN©ù›uÑ+iwvKK#8ÍÍ’={«~þÔ¥ñ¬-â:ÖjâA§¿§‹ÃÁëJB>/ øµ‚N,v¤NlŽ6ó:’i»÷! ˜4aWÔÙ9^|ƒ³t;Ä<ÈNIKãã8î;cébÄ�MõˆÞÔÊ�±¡©ùKlª ËcV\b 96˜ÙnÞÄNÛ ê”rÏd$_­eÑHºX”ÀS%OikÚºÇsæ$"^÷–Á™L·èE³xúYƒƒññ…�€øÛ‡dO$_ ¢4¡‰óV7Dº× ‰óéZÈåi�ÌEïC2pp’ñ' ™~2Iÿço‘ÌuiêÁú °Ôè¶|qPÀê ¥2ïÕœ ¹#Û7¥vô‘¶ Kd­Pš,&+$òÙY»Ù\�1Ä€'x|òIû!²½eë¤]¢\3ÎÂd…°´è´kÎ&(â+3Â6D­rß¾â¨pjŽ•çéi¸2o÷Ž’í²Ę#`5,µ†Ê–¨òt:ù¸˜Û::çÿ“Bµ€zÉm,âÕÓ3ñÅ +>6)!)ãÊ Êo1þ6Ç;Ì? ׿J@Ò²… áëj“R“ùOd†LVux¼µÈåÍy:õñ¤óšÛ›[Û¹ é–‘^n¿N•u Î‡þB2ee-’¯³Ü–ÎZš_&@š¥j¯ñm{Yôj>¨EÒº½Û"à' vï!2GÚ�Ûo>šX“Â78pËR Ÿ®ôRërXK ²4·.¥Zöˆ´„Û·1ùG�õbn*Ö‡[–j¼$踀ÆÎürX,Ó`�æå“Djÿ§@Ô¿‚]bvÅ6M}@SmŽ­ÓïZï€[ÖKð.6oåX“èÔjQ*ã*­IG„Bí ™Ù¬oƒÜ@!„Û@™MdVÓÞÀªjã}Ć2Î3:†5BUêíúÒ�2A“Š\¨Ó¹Ç÷÷\üÄ ÔÓ³Ò-ëHyÕŸû÷ï¬�9±‘ a°–ÚR¶%§ d»×Ö¹ã¾�ÛI`œL³\ã–èa¢:ª²*wÂO°Ó ‹e£~�j”1£J¤¿Ó@¶…c-žDV]Þ|ùŒðóÚÙܨ5ž^‚æ�~"<Ê©�v¶³ÎtÊZÎ4$°+#�*ÝH•Ð{FˆËÛsškRª]»B’Öì`mè”èì̬sÇöl?PШ‹‘F“t°È¼ÊÂë¹cZl„ˆøh½>Áà³Æs5?n*HAJÍÙ²ê”ÇŠŒ?Š [8/½Af¶Ja¯u'ì„=†Ryº±±–="¼R½Vi>b©†MPkL3}ÂÒ'í´²\AÛ?¤ m´—Íbs”†Ñ­�樿ÆÄš ‹h‚ª*Ó\%Ðv*Ú ¶ÏËa_ð¥àGƒNè”÷7™–Š ¥œ—)¦« “~çvÑŒPú³‰‹dÝ€gÕ\CÒV‘íçhS»‘q¢læÚiß"©‡M±õ͹ä(ÍaÍ´Ò‰`ÀëK“)xϲ}cåh�9ôgíYOÚ|Ä}ñì¨Ú²�g“9ŸèØùB˜Neƒ}Ö¨�½›,Šq1Ö�â$š®ýñÈÖÚñˆg¹!nïS‹x⊒%M �ø¾qGâ¯Û†ä;ýV$óR@òCälá2l›’3ƒW³šF'© 8ÒSvm‰Nåc™bž³`ªÉÇÈÛmÜukF•4h®²Ò�9T´«Ê�çLG¡^š‹,¼.�û.6ÚK– ,W¹Òª¿)¨YÖ?'é@jÕýv/¾DâR¦GÒ>… Ñ.Ð#içKJŠ‘4O�4Û«G|÷Aâ2A¶x%âõŽzÄ+óÜïÞ×#žÝR;½ÇjÖ˜L¨`-Nöà‘ˆ�òO·e"wÿbßÊâ0$MÆ;ËS™_í{'OXŒøTÞ@;_‚ø|Á¿[ÁýDƒÄ‹4G¼‰Ï‘˜ð5ÐoenŽY²4ô¤#]ÿé#¼©8þeèæu¥�ÅYiyÅaûVV/±Ï?Ù£â?›ZÍZLïÁëæ{.Y¼2(,:/+«¤¸°4óÅ—Û¨Ø8k¿àŠúe.Gmgéù³sK5׎ÑÚN0'H0- c2$BcêÌœ–�™ÇV*w/;é�xž$³r¾E²Ô¬$þ� žO¾ù]!bCœ yU‹¸n½I§ænqÄ ›ã�|Ö1ñ·ù�ô» §àêÙ#dpZ=� ›¶w`6kŠD¡¾‰H;‘(^vAlø85 R ÑbIäi(—k‰ñÃÏ�qCü8Uvãj +§�¼IåSá½½ Z÷ÉÌÐÎñµ=` ‚n"’©µOý¾É·# ¾8¸ /–¶òˉEÒga +â?Kš éaóE<¿{ îö# ÖÞÿñêÜ�ˆÕ#–”Ož©áËó1´¯ybÊS"âÚAHšH®ˆÌr +‰w7x½)6RTÓOPA;þ)¹Ô9n³ku’Š£#i[ú G§°ô[6Fd#€ÍX­¼Vjòös¾q_ +ô÷Öߨ–ÓÊEi?gËH² oTô»s¬›Ü}#sgzQøïôíÒ»6Gé:ÍЮUm`ÃæNg�€¦ZmÝ%J¥ÜŽÔ´G»j…q‚i&Ì„)f ¯«äN¦m\'6TsÞñQ£„@�”§Ro¾Ji×Ê×�*u©¡Žƒëè°Çn¯ZqDSO¨Bºª­8x!³ +*áÄ:øÆø�™Šøªe-âû zÄ×/Üq€~•ññ_yˆ.¬F|×Ú‰Ó€t‡sB¢‘·˜v@±ÌEèonÛ›u±ÎS\ +£ +WM4YÁ +¼½´¨rkP±�wHÐʯ�§Ž”¼¹F�E¸:óSß(=ynð·¾:Ö»ÓØÉcW¬+¯Ì+Þ"”F–,Ô¬}pñÏÔQ +©PÔP'Úó¾c uÐfsɶÜü­ÀWêVùˆ *$NÏkßuÉBÒépoÄ‹7¼‘L˜ÕIÖБ3"é¾m ’ï³ ·•D”¼¸ê¨Ô>‚¯]µÍxµÑݱæ¯ÛÀ¹‡½ÅO1z…"4IB¼´©ñð;±zx= VÎ é½k6":Éüï·òê:°ÓSvZi—­ =üÉ5È^2‡f9ÜJƒ~¸°N§ª´ül>ÇษÒ({ýÆ>@í@S”[¬Y7…|»*ØØË´fÃ4ó ¯ËçnZ#}DÉÓîÿÛç?Öó]‹SÓ•M,§F;µÞt¬Ÿ\ßYÛpž›c.Çl›à’õ4…ZC9ðöpnh¬õ�(es»’Ro 9v6^CÜžù5œ`«¥ƒÊ(›Ñ<ûN—­ºžç)6¤rsæF.�S–ýæÝ°ö›lòò‹æ¤¥=Ü-¶ò&óºÅVZcR’!’­©¼š…­{¢ Mw:>cAZúôý0%§_*‘4oÕ‰jÐ,$-Ÿýšš‚XÿK%â‹V½Ù Yˆ¯žýƳ§‡)ã#âÂòcóc“ó’²xõ¯Áõ}슣¯¥àRG©Gý-›Î¾a_±ẽbé4:ðmK›gArdÄD��Êz³o#‘ F*Èßt=͢ݯQ…Hð`@ëfÙ†là7�µP¤Q\.¤è…H€˜H~Á(¥WÕüƒ½Óã`“Z+jlôt©ãæ,-$#qr_‹DuÔ‰S¾‰jÄ žVHÍYSP²&;;n¿2è7ô&(7YâcDH0MÆ>rÞ^Û‡µâ©«YùÄ\z"¹Ž/… l:{ʈ„Ä4Q]l¯oóÉŒ¼/w”êi°–¾äv¥V=ìÜza‚U0Õ(ƒù¿“—{‹ìǺv9`r÷]t¬ }Æm³¤ßrì*ãtÓ˜3 L6wÏå#6´æ˜†:°&´mñêud�ÿd¸Ê¥Á[¥zéWmÃQncBB´ 'E°÷ $Š~:Ć_‡"q¸”�ÚðµTf¾a§3/yÙ¢Y—Á2Xô qÿ�¼s›(¥pÆD7!ÀNg¨RbS#éfæéD– Ò嶸�½;gƒý†FÕ²Úä/êjZ¢ÕTl«\ª8úJZöÊQj¬¥ãi:�zP6€`ãÙx6€ `̃déxÑæÔ�µzB3iÕ>üçªÈ"X&kÕ¯›œ7¯ÿ>Dq·¾•VŸê¾W(„´´ì K˜ î±î<ý}B#ã!âSb“ ’“22øýµ¥'á<Ú—ÇêàÀ5‚zÒå;ßœ§+Ï9¶ê@n]s‚‡o×ß·uEâ„[eñ.’îd6Oÿ ¼�5•c‚dDÁŽD¼r_È�Œ„CDÂú�È�‡KHú~è_’›gÛ¹¼|±°V†ø¯+óÌ™ |—.SЬ¹ è¯rKô¦ÿ$%?ÁÀFD<)RŽù¯R/v�óˆ4Lþ�Ҵ̉ùPŽ{t{ßI¡ªâ‹6®‹ß”™•`Œ1Å6æ16×·(u©9¼—–ì >¤¹HOÑ�Ú#¥çÁMþïnGt6º¯N{m æ 7Æ$(YëÉqÁŸÿöú×´Õ ª¸L› °{ýÞÕ[ù ŸBw¸I;³ZÙï—� 8Ä?½ç² ¹öë™ù£E˜µdÖl~äL-íÖW©ù¹"¨À¼ù‘ßÍ1ø»ã +P»ùÀުܬ²\^]WïZ¡ t§£tOº£eSÖ³9RŠ26ßPø§™·s«L3� Á&Z}d: ÆÌU<ÕP*­ÑÉñÙ� IVk*Oä:efEUÙqYV0Õ !0Ãê-�:`ªô�ðæÕTû_~Ü‘þEQ &${»vÀ�ÿ´ G¢¸þ±áIlr”5by½)ôAÇ•›�[A!Ü3fš©Ò I«öçþ1íÏ”t¨€N¤£ÒR +s÷T]ø–Ï6z�;¸[üä@Kî†õ"„GGGGÇÆ±£¬Æ`äMF —•ÕÉ©·þ·Û|71z¥ØPÀ-ŒIÚÈì[N˜�À8Ùè"¹¯MHš¬™ƒ¤{J…HGq�Žm�]Z¢ Rµcýr»vœL¯^ø‰ÃÌ:Ä7Î"é°í3žÖ·Q"6luCÒ$­ñͬZ$ŠÕnqˆo8™«ÙN$™™Ax¦û@”aÞºõ �|ŒN­»„8a,•…17¸¬T$M,Ø�$¡¬�§ Bââóñ”!I׬_³ÂÈÉ׉ÍyÄǺ͈¿w|)óÕ‘ˆw?yÁƒpŽÊ·�eÑL- VUS²�*¶S›�JˆOŽ~ËNñjöŒ¹K×í!´Ó—·o&ž×üšË¾ÓZLE‘À*8L”¾æª‚RÿS"Ó'b”_Où~4b%+D¼óÈI¯íz$ݺ¹!ik®EÒrÀ"$­rõH:>ˆD˜üõþ©ˆOJjŸ\Õ ²H;È2«×#>÷&�±<�__¦- ²­4Y>!~ký‹Ê+ 6—ŠêûÁÅ&;=\LÛ]¨p�n{ý̦‰�&Ò'Ú+¹/ÃßüŸŒ<`}v^W¡:‘ùo.'Ü0êÓ‰ÿb–s9»L;Œr.g²!{‹h¢içAù+$@¦q_Ô¯´%ÖH0›§Ád°X7òšC�h‹„|8 ‡,'øLcR”Þ¹Ô™§àáÅúÃÑÕÑO£ ùˆcs·ÏËå/ÑÁZ˜éµ&ñ¼½ÂK†ä_ÊЩ 3ð3h‘Ê\lI9üyí‹(Ý—)û¬‡rÉËõAÏx5ílÏ\GãìR7»ËÑ×Ò7W—kÔQ?G+Ç {?þ´ñ}î$Diœ‰Ÿ;R9îÚèT¹ÈmëÍF±ØÚŸ £sÅ[pmKùϼ&<-l×â,à“,Ù"�Äm±älÊ+TLmPÎ2�·x™yÝOÜ¥Ôȵâ +A¬1†×ü³`ʲÁÀ{³u›èyZKn;.R-üÁZd2gK$˜²! ¬`±ðš–DHÚš§-¸\£5JPŸ€ +z¶ˆî¨p¡Âúóó1uIZBëµÏ +.�€küã~×Ù{«S]¨„ÕbÃ).aCt´ðut¹Š†ÀzÈ·Reîù;ð7‡ßfª žEÒ2mVFZ‘@»«Îýoø@‡�’Ž€­·RhoÙÑÐ ;’r§£¤¤´¬š N�OOOO*h5­æŠ’ÒÓÓãÓƒEVM«UEQIQQQñÁ«–{ÆGEE%E‰j°ÓvÒº=|Å‘ÖJç´ M˜�“°ùZûzn„1}»xÿ{wi—•�¨"ñ£_%".9�ø.iâË¢¡<;Þà:šð•ÒÇ9J:Já¤õ“¹µƒŒ¶?ºS$u±¹Ô<ü^®Mм’Òm—Eß�aJ íÏ5Ó®´™°¶úä.á3W'N�Årº¸ìÒ>ØÌ‚ׂ2ŒŠAGY/໫¦Gƒ—ÈÒŽpÏw&>sm,/`“<Çòùùˆ77íAB¶ GÌ^1 ‰¢¾?‡%ªVnн&lS©¥2üª÷£ÎZ$9;*n¶­•k»¨Ü¼–íC;ñH>?ƒx;ÄI»Ç刧¯r‚�+€S†rØÛ©AÎnܸ”góž)" ñ‘°Qöá‹�4ë1‘ÅØ�4¿ZóA° yJSB\B D™ã-ÆžyÔ«•±Åá)ó€�°«lpذöÃ1K¥™×É©ÒÓƒž þs§b]ÝÄ�?NùõEB6MGl¨€D1µ±Á)‚§ß4è©(�ЬV†·¦»eWm2Ý0–Á8cÞ,ïñ°ê5âó�Í_w}…ø·tKž“=ø Ùy‘�º�D‘Ò‘}Iù>–´¶s¿’ÞÆj$mŸ~DÒaÝt$½´<DãØLº]‰øO»±HÚyšï?:€Ä!'hš hípÔpªà‚e› WˤéUˆu£Ž#i¹j&âÃCÃxÚ†ÍWZ¬TEG ÑÄu`%âíIåH:�ŸµL6¾[L‡Œrˆò“µD6¡²ï¾1ñæÌŽˆEýŒx{ÛŸr�ÎêÅ®(‘´ö1 Þz³Éç¡r~.ýŒ> +264 0 obj +<> stream -xœûÿ -þ6Ò ö +xœûÿ6Ó ÷ endstream endobj -256 0 obj -<> +265 0 obj +<> stream -xœm•MOã0†ïùÞC$8°Ml'„*Ñ–H=ð!ŠvÏ%q»‘håãп²Ÿ) Õ½™×3óŒ­!þñ²½º¯Úwwe~&êÕ íÔ—îjõ¸ë¢8^·åttÍøä\åªst¸U]ß–ƒÕj³Þ4õÅñ¦)?¦Ê�=ÿ³,Ý¡n¾ ¾†ZMÃØ£8~«Çw«.ø BOjS¹f¬Ç“J.£8þåú¡n›[•FqüÐT«ö蛢™ÔP³—¾-·nTûº©z©¤Þ}Ý(ÕªªËQTø]w]8¼= £;nš}« ®jêÄ©”R³Ww¨‡±?©‹ÐØ¥ªÜžÈs_¹¾nêâÜì·àvêºç›TIøêš*ü�yø§ÝÑ©™~J•~}z;uNÌ~?¶ÕY¤´X¶•º]éú]spÑ]’$ÉBÝEQ,|Åâók޽ïË?»>ØÓ…ºK’y¶J£” *·(‹JQN‰åÄ$Ë<(}�ºÆ™£np> îqÞ –8 j…Ò¨5ç$ËJœYè:õH½FÁ—¯Pðiª§ðÍïQÂW „o޾% -¾9]§Âm*|R¾\bðårNø$'|Zú„o.YàË™„†/£O-÷Ç­hørºÖðeÌEÃgÈ©á3T×ðiÉ Ÿa.¾Lœðe’>Ë=hø´8á³Ðjø,ïE ´>Ÿ>rø,÷nà³¼3#|ä4ðYrá“,ðeR>Ë” |VbðYæiàˤ:|™œƒÏð– |†Yø´tŸåXø,³¶ÂÇ<-|†ê>M=ëùtf©g=ŸÎ„ÖÂg©nå}ŠSøDÉûän­ðILø˜®>Ø­ðAdá³Ë°dd›øuã·êç~+§¾wÍ–jXf~sÕ�ûÜÎ]ÛùSá'¬õ󯞋¿xBœx +xœm•MOã0†ïùÞC$8°Ml'„*•–H=ð!ŠvÏ%q»‘håãп²Ÿ) Õ½™ñ¼óŒ­!þñ²½ZVí»»2?õê†vêKwµzÜuQ¯Ûr:ºf|r®rÕ9:ܪ®oËÁ�jµYošzŒâxÓ”SåÎ9ÿK¹w‡ºùJðj5 c{Œâø­?Ü­ºàƒ +=©Måš±O*¹Œâø—뇺mnUÅñCS­Ú£onˆfâ¡f/}[nݨöuSõâ¤Þ½o”jUÕå(*ü.�».Þž†Ñ7;U†¬jê$S)¥f¯îPcR¡±KU¹=‘ç¾r}ÝÔŹÙoÁíÔuÎ7©’ðÕ5Uø;óðO»£S3þü*”*ýúôvꜘý~l«³Hi±l+7t»Òõ»æà¢»$I’…º+Š¢XxÇâó޽ïË?»>¤§ u—$ól”F%(TnQ•¢22%–“*ó ô5êšÌuCæjIæ êžLƒZ¡4jÍ9©ò€’Ì‚*t�ú$‰^£àËW(ø4î)|ó%Jø +”ðÍQÂw�‚oNשðA› +Ÿ¸Ã—K ¾\Î ŸÔ„OKŸðÍ¥ +|9“Ððeô©åþ¸ _N×¾Œ¹hø 55|w Ÿ–šðæ¢áË$¾LªÀg¹ Ÿ–Lø,´>Ë{Ñ­†ÏÀgà3ÌÌÀ—á`à³¼ŸåÕø2 |Ÿ‘*ðeâŸef>+1ácº¾LÜáËä|†—eà3LÞÈû¤3 Ÿ…ÏÂg™¼>¦ká3¸[ø4~ÖóéÌâg=ŸÎ„ÖÂgq·ò>%SøDÉû䦭ðILø˜®>q€ÏrÓVø–aåÈnñËÇïØÏmWN}ïš1¬Ø°Úü«÷¹«»¶ó§ÂOXòçÿ^=góŸU endstream endobj -257 0 obj -<> +266 0 obj +<> stream -xœÝ| xTÕõïÚ¯sÎ<2™™Ìdò~2 1äAB€„@†@€ðÊ;„ðA ¤�?&-HxµFjS*1¡!¨ˆŠ©­–ªÛ¢¹6 Âds¿½Ïä>Úïþïýþßw&çÌ9û¬½Öo­½^û( 0Áj �:sé’¨«ÕªŽàÔ¢…³KÆó>ÀͰöüåEï~ÐúÙð@añ¬é…ÝÊ~3 É =‹‹gM×ê0Hî]ŠK–<9=¢'@rÔÌ/�9}÷‘Æ$ßßK¦?¶�Ý 9)Û jÁô’YŸt%~)õÎÍ K/ùÙ#?Èï/\4kaÖ›'T€AAj(ÔÃYù©EOC=@=¬Ç«·ÿÖÃ)8 XŽ«GgÑFôœ…½à…³°¾AFò&êk¡ -h4œ…*Ø-Ÿ¬"ÿ€2r .ÀøÊÈ?P&y ΢ �>�zØØ1 i€�pŠ4@9i (•Àóè%(‡zT -«p9Ôã1PïÒóð.¬‡õ°ž‡RxWr¶= —à0T@ lÇWa†×à4�}Ô7a®Å}qTÀi¨‚�°­…&XL�Ãg¬ 'ÂópvÀ ØÍšØv�kbMì:<áJ½âPcщÛ^t uÇ#á2B9Œ#��GÉÇh�¥ËÈU¨Â@¦Á\8ÇšT©±P¥¡åtšü-òáetª…«ŠC�AnA9ކӰ[J p�a#ÙHzŠ`7ì–«ô¿ŠÞ%·a-<�9B‘¨‚r:¶Ãˆ‡R(%0J¡œmÒ¡j!‰m"Ûp¹ŽJÇ}a7.BP…o»PJB/(‚pv ֡Ê@] ‹Y€^UF FÐ-Êz»ó z,ˆzkbtR·û¾FYÕ¨ƒ0ú ßò¨ú»wGÐP6ñ ;HÜÚAêŽýìÇn~–ÔmØè‚¨zäÊè#›7m`R·ac b·ø6pbttR·¼�òž˜õ sdîüi£fG=i}26ëI묬$ÀPÌ·Ñbö<P!òPä9ê�ÆÖb -)�›»ƒõbóÅæÔ[´Ím‹.¦à]LB½ŸómªåÖ7‹”§î^¦¡t -@7O�ÁB€ ¥Ò¶ÃˆNšý Ši(V`�ÃÚÒìmNë)WÒZšm®ÌÌÔ[ºÍ˜žÖ3Ön‹Í° Ø˜¸Sõó>þä‘#Ý_|tÿ>´×µ­Þüêoñò;{öM/üL̇¡��§ãh9X! Ò=a !•G¥Ö`Ù�N‘“á6»i°‹‚‚…[[šÓÒ¼B’+W®´4[¯Ù23SݶX[º³JO³Û¬86&õˆ‹�Qœ’´ìÈ‘ä…gÿñÏ·‹v ëë×=ñä“O¬[¿©õŒb¬;�¿Á¿à_ó3Ð�?~ôqÓÅ¿|¤óT~÷2µ+ÉSª'¤�§–´‹HnÛì¦!‚#osš¢¹�!Ô¶Yíéi�HÇE²E&Õ× †®~ñö¬�ÜúuëÖm çñ€ïš7��€ú '²¡^¸é�ýåbÓÇ ~ÖݽLci9˜ x0ªeòW¡.H­´GWD¯ìÒ`ß䇂h°Å¨˜FQÅÙïkKs£`Ж™ÙR¯´x—‚O[¦=ÓfÏLõ„§F¦F¥F§ÆÔ@ ªÁ5ÆÓžÀWMPMpMˆe2jDzWF¯6ÅfôèÙe$‹{j†€>Ð�pCßç~½bþö—Б#}^^ýÛwîüë[ôÄ–)'.:ZPqºo\Ntᬅ^KÞºfoáÔ×÷=þÄòž=êããÇŒIÛ¢ÛßZª±_At÷Y˜æOêÀ†NjuFÍdÀ«Ýâ°^Ìnôf7¦I±š[²›…ˆ©È팶9û §àÒ�mÃEhŸ2¥ìÜgçjyJd¿â'«Zk~6cËÞ³xZêçÓw-'„Až' 2V6)�uH©ôC¯W4øí'8ÌjT ?Ìnõé¾Ñfº¦¢¾¾û¾Å¿}Q¸\'Pëz:mß´™Â!ôÿ†Ä·aª -LUdÒ ˆÚMëE¯4,¦é�v§«±=í=0zDâY³níZÅÞ̳?ùŒg7ÿ½qù -zCØqÓÝËT¡åe�Ÿ[L®ÈÍ€U£+"2"7<"ÈhŠˆ¤N¨@'¨£Ây"¨ÒF+Ý ¶]Ã�¦ÈPF…*–|UqÄäuµ¶46{›¯ck37+¿qÍzãšÝ%—±Äßò•Í•©Ê¿c�S›Ó‰"�Ó¡ÄÆÄÅgD éŠRp2ÊèÑ3=-�¼;ªfìÊòG^ºqSócëæÎ>6nÅ7´¼gñÑÛ“öÒÌÃÉÉŽ64Ö²{åÞ£±± 3'®îŽ-‘[V=w Zb8€®¥å`ƒQžE5°‘jKƒá¤jTÐìÖ‹�z´hi¾øŽð=©·¬Èj‹‚(eK…T”nMµyÀƒX=¶Ñ0�¶Ž¶Ù'#]ˆ�ºèÚ>+ò÷×9’||íÀ¥=ÉòäþôNë:íãe«bºøb�W=MêQ((¦ááW¼ïè~Ö+üK*ºÇ¿âUOüðêo^áFŸ m?ûùî‹'ÉwOBWðç¨;°ÖÁŒÂbÉŠ…d‹EW½^Ô�Ÿ“¸� V: Pà #.US5&8W«ƒ“¤Ži(Ê%Ï(Ö�/˜5·4wxémzkMö8{’ÞZªM Ú,2W+#+4ãä€h§�<E_&I­+ñZïQ¼¶õ:cŸ÷/Ûj‰[Æý�w/Ó!2κ Ö TÚ¡Ò,âªÁî?�Ø�ý‚¤Ó÷©îZ*jÓRF�¸x_þ!‚>.®|ê©ÊMO=µéê·7¿¸zó&ùä£?6}üqÓ?ÚÍ?àãŸñ ( ‰…™,äzžN3²yòL˜`£ÁH6šŒ”QcT˜0eš¦ -Ÿl3r�9×È0ш'MšÙd4hzÖjR!åéš³[²m.Ý=Üë�U+;£Z5߇�™sÈß(¼u¥É@M‘‰Âq £Á,Ìj 1Ešã %à8– $¨±Z7s&îÉ2•L5]Ë6çiù†A¦¡æñZ�a‚i¢¹Ï!Et›k˜eZŠW°Ç´Ÿ™’ü�Á8’DÒ`iŒ4&âDÖ÷cÙÆ!Ɖƹx+6–ãUd9]EW°ŸWƒ&£É¶ôP$þ¡XŠ­;UóË=§êøíƒ/:H§y—áÜÖ²ñN .jÝ©¯ÁfzHq€ N{²4—Ac -S]ŠÂ .‚5—ªÌ\ -ÃS6Æ0!'a—QÑ%Š)Ê@È3[[š›Ól:ˆÍW\÷F8í+•úPÔ„åiª°¼1 -Ö´@Ä‚´ ܃õÔá"\†—2³�hZ0qÑ ¬„¨AZWϺª}HÚ‹eª½´¡$_�¨LTç‘9tŽ2G]NcË•åjØd˜�nCé‹T[lsºü)Œøg|ÆÆÅá-Gçù¤ÖA8w ÏÅ|<]C§�j/D ‡è@ÅðƒdO°VæFã.8©à:J†›�†Ã0£j±^̾ÒìÍ–.íŠÈ%RQ´¨G2¢mÑ(Ý‹}ˆJ¼ P ÿ EÖ×ÓiÞ”ª*’‹\r]â‡H‹â€.PäÉöwš·!Äê 7±¨h¦:Ô¡7 o:ë^q› FÖ%0Â�,; *¸¯ÑŸ¹;Ò›¬íäG¦®2ZÙ]¢äk¿™ÊD ï‹zÄék°/E�žù85…‹º•´x¾{q^e¿~›æ¾ø�gPåC/(�ôPeÃS[/}]½¤jѶ뗶TMØ|ë—›ƒC7ï¾U5^æƒ[øgø” ‚<&òkØ£ŠÂAˆwÚ’i'‰ @7½§wÎD)çø´J·õæzzEºCÍþZ¨ÉìOY�àºP¨‹}#ôMÿ:Û+î°à§?¢ …8cíB"�}­`¢‰4o¶,Î~ yчGªË@¯dÔŽH  ‘Dtià¦ñ“J<<~ÓÀ~ßí›·ÉãÙ4oßwý -6ÝÚ½94xó/om*¨Úréú¶EUKª¿¾´Uï%¼.jK�d/!Èl •þ†Jçÿ†Ð]Á`·2+JH§îFç^Bç^F§G¼3Ö–N¶mÐûZ/wÛUôö?¯ž-Ü‘\_�S|Í üؘ~†Í¿ä§'ŒÝ$Z\€‡Óó¼ø¿õˆNyÇ—:£3èù;)¼dôh�÷�| �¤Ë$ïéž°vÞüw„ž ->.9 v{¿ŽNHçÞLçÎêÔqeˆ pøúuë6n\·n=IÚ1ëÌÕ¾]¸#ùÈœ(Øoúø£Ö'ÇND½� ¢¬ c«¾»©÷føj÷õB†xâƒÍ¡ñb¯4TFVú“Ê. þ§ºž| >ó`Ån�ò€^@ùøkÔ› Ö¦kºÜ‹s€w”J}ñ½l“Ië׬ß\µaÕúúkÿ¾w쌚Ïlè¶½¤ñ‹/çoK©Ç™ç>üðܹ?Ä/y¹7,´.¹ÛžƒÚÊ)� ,¤" e�Ÿô´ŽíiZÆš@ƒHô¡j+T6Ø­F S`i~½maHwX½Â“é!©Eôï�Í©;:�:4ÙbQÕ•¿Ü½‰G‡o#ÌïÞùâm–Òznëºu[ö^þøÒßZ÷és it9Ù#û„¡3­Qp hL¬ ¹dÚ{„¢ô‰vFÐè;Ÿˆ6ïǹµ‚†¾¶i<00€Û íQäßo$‘®­½½r�ûÜ \êD¨\.w?¯×·âÉ›ü¼°É¢»¹´k"ü† EŽ ¢`��Ë–ÆT‘’å ÞkÇYÓw%€õú‚ÆûdñÃ{`?Ý£0® #ëMQ#ˆbÃæ+8¼^ÏÏóLYvBçø7d™â"<þ´Ny×Á+C¤¯ á•€x%‘h±àœÑèÚwý:/PUßy«$�Iü‚Ûh�:ô*4 ¯‚©f½¨z: [´0û ‚yÁõëŠãÖ_«*i@ÅÝË´;»Á�ì ~V¿—͇¬Õ†m¢lL3Cw%5DØ‚¯ø|ó‡ÊFÝT{ö¢ÝGìy˜ÆO¡þðžCkÇŸnl<]ðb~FBÚ†¢hGB¹¾þ>—¿Çß÷ô•¼À£t9Ý&ˆ÷8à9ªaϩČC(„i!FÅ,À•qÎwâëºÉJÙ†�¡?ðûø@tŒnákÅI-:ÎP…5�IX�WÃ�V+ õ"*ô2˜EÿJï)7§µ4§µÛ ŸgH_þ&ÊôžB™üMÖT{gUm-]ãóQtŒ\G6èêq*Õ† Pí¯€¿A%iæîj„5Õn•y�Þ;‘FáŽêi³ÆEÇÚ$z ȆÃÝ·ÏÜ…i…h<È�ñZ~~ï4 »sgKá[ùjþ8Fl lçá¸A öW¼B�b½¸µzß‘™nد„ßM°¶ÐXvÂàAO„¹™Â‚‚Cˆ+Ô­(,×j{Á¯Ú±�B5«#c„+ÆJº„[½�Þæ'ô|M€ÒòN[>*smö•+mbŒ[`ÔzõCºŸÕ²ÔéPT Beø%oÙQ”Q8hËê‡ßZ8ûÍé#ÓÄÂÞMµµµ§Qr¿Õ£VnÎðN÷´«˜vbIÿ¿·ÙãPvâá¿<}eïÊák^¹###reç -9_v¼TmC/à ´Ú½Í¶£k„Þ¸Š Í´tw¨™1©]­^Ñ€¾§q¥›n[UêkZéQJaQ;ˆ -©˜¨‰Zá¾VíÜÊŠKA¢—ÕEô²Z92¥joÉ3s?8Áoyç\œ·øÝâµeOÏÿòûd|ÛónŸìu�Î,Ž êþÁ+MŸ&%}˜?pcùÂ¥QÁ) 5oý¯x@p€°&0@O€RM…¥Òßk uWIô0J‡Ü¨Û‘õZ»™Úb¯’ÒÖGð¬Ö]gYS-RÛÚKê^øù‘Òî<�>zZ5ý½1ƒ$™nÖIJš÷�vFŸ&K[ÇáÍ­‹ðqï2AyPmëeáŠA -ÝÚ@…0�E‘œ¢,YLm‘K´/¥X[t -]Ì“ÎòDÖT{»‰%ê4> b×Käjf�Dé=«·Y¸Òœ�.ùð,>ï-dM·›jÅs¢WÒ‹]‡®0Ø“ÕNc…a¯_µYµ7¬:v›²ÃùbB`GpDœ5‚ÄD: ‘ Voc£·ù¢ЬÍíæ`½–™úºÕSÓû ›h[vó/oÌþãì¢7fì=thûÎ�»Ÿ~bbCñò?䄨Fÿæ3ï}×åLF�m›ß±wEÉâò®]_‹Šúø•r±¹)vmEÏ…5A„Á\Ooƒ¦£â&”07¥$W¡à$ÔYmpTûm0Qf 4(ÄHlf!Æà4jëî0F˜SÃuÝ yl¢Ž²é]—æ‹ÍöLñÛQ@¶µe#�+ –$#·m2„+í!ß¹`ÌÙ?Q>óõ³¨æ&Ržk}ÿÒÓ›«ŸÂ¯;J÷òb´ü¹É­YÓ_?ØzOl½öøk6Êøy™Žf×!²=ÑÁ!HBªÃî‰!¡Áfè�¦dDoØ(LØ·ùE‘Ù2"šØb3¢éèÏ.åWx#ò ð)ûG?X;õôéão ˜•ðg´³|ØT�JEPÉèynD>?ÇßãgxSd4zz/Ø @õùé(èë‰ †j£¡Ú¾Ui3Gh˜�%"�¥…u7@„=5ZO~¤µè®[Z‹ÜbÓ#�’¡@áò¤ % ôè×·ýjß×_þbíš­|(zíó[k×ny�ßäßñAøLë¥òM¿Øˆ‹x¿…+-ÜûÆ+åΚî $1޿Іۉd™W¬ÓØD—Óe @´Ç.vҀїÐïTw¥¯Z½ÙÍÂ-Š}µÔ€ äDH¦àd y½ŽOÙ˧¼Šú‘ûÁÃÙu½O�Œžòƒ½:Â\´-bGgD¨ ¡1þÑ‘]„¿Øl½ÖÖ³¾x-ÕóÇHA)X€’ÂR”5EK1¤SL9�ƒr°€)‡å(9jŽ–cÈ1æ˜FÁ(4 -�2Ž2M…©h*žjœjzžEÏâgɳôYö¬ò¬ú¬ö¬áY㳦pÀÈz€P¨´†Æ¦ãpÇÇÉqzœWŽ«Çµã†ãÆã¦A?ÆŒo*2•NeS•©êTmªALüc„ºLF“‘ÜÓÒ7»|ÞK”Ì�›óèòˆž½G�Êì=lÝ¦ŠŠM›+*6}ãÆ×_·´àk½F�îÕ{äp¼›¿ÏÏð·ùû(õD½Pj Œ¯á�óÇÐôs´ -m�>­�_ “(à)PèÉÔºv5!ˆº)VWrWtÙÙµ*ÂQ°UY¢#¬Té¢uc`RBX×( 5ÂåOÔTëEWv³+Í›Ýlõ^¹ÖRÞHk”añ�›ºs¶ù6ú�M&zñ6 r:e$áÒe“z½2Ò]Høîx›ÜôSñá?[ø×â²’‹…¨è̌³3ßzûÂñB4jϸ‡žýÞŸ®ÃùH²¤pòìóè—tá”ñ…wN $–œp¸_.FoGÖmûåQË—_²ˆ�ß%¦Pþ`äÉ�;ß3蹃Ƚ‡ÈÜ&ÎãЪñï)l0**‰`Ý (RõÌF&õÙbMf¢³EÛb7žÅ g϶~x–5µîÆ…·ñ›­™zl.»{™>ÒfßžCµ?©vnóßiæžJš=#Hfôû0mºMO³t:'×ïܱ~ýŽ�ë/|ÛÚzó[oë·ø*ÊG!üïüU^ÏÿŽ‚Q>_ÁW£Ÿ£ h=ZÍWK¹ÆÐåÒ­ótÓ0ÁªØ�A0F¹FÐ61ƒ&vÃ�ŠBSŒ -¤úé…†o× ­ÝWɽêûtÚkéÂ4£Á…‚ˆK 2Ä¡§%z¢LÒSëm°ø«þª¿‘ˆýòhŠE¶ØñÈ‚0¢Èÿ(¿¹ƒßx�5µjøÖíDïýŠÜþ3 ¸ @±&0 -½‘s² *T´X%‚@,2Y/Š´ÜWV\lNuGÛX†[¦yÈ‚²øKhôÛ¨§÷­ZZ6¼~¨ÌøDÝc%µ¸AÖé¢îÙЩ{^bM­âå2¡GÄOàzåuY£ƒx/†ØÒm8¨¦¦†Ì'y{gçݯë<Ï¥Ï�@}l@F´3=#Ú™�®/G×ñÜýû÷ï ¡üuº“-ô€…žî]»„¸ˆÅlíA¸ ̶ø.]º'fÄû)]Í $: Ä/ÙìˆN4'%gXÿÒìm´òìF«\T¢°²6^—›EêëÊcü|­î€ÕŽÕNEø–N=¢Žad_HÜÒ§ž½\Y”ÝI-«çÍ[³fÞ¼Õ•O¹×ŽyîÂ…çF?ÑåàÓ7ù%4Ù{ÎÏLÍ)Ïâ»ødôÊ>G¯ÙµkÍã»vñ–æ üæØ±oõÍÙÝÀ×ð#üU¾Âá\„>@•è ô¿ù©ˆ)¨™.'f…8�™¨?XhM°jLa`‰³ÊDï¢7ûbsš.o¤ÄÄÇÅßóþN KÈE—«5éÑ@ÓˆÙé£6å�üÅØŒÂ¡fç’Ƀ6óK}z¥itPŸœ—²{F2c¯¾¢VôÙšJ¹é-þüõœ>YY}ú�Ö×f[¾]Dæ®FW#«­ÆßRT›iuà6ëwLÄùŨJ -ˆt‹´Ã{¥£Yõ¹Žfª^Êc¹ÿ"^¦‰�Âz½Ñy+�|’³yĉ7Rküé«–KÜû ŠEŽ¡[ù¥5[·®ybÃvø5w<ÿ„ÿ£pÿö_ß𛨠=�V M‘­ó_{þù×~ÿ»—J¾‹Ä¾™Ìåý ׉üˆ◠ĤV3D6�ÙUüÍ],V¯WØ€,ᮈ³¶t½ÍkP4I ›]øž€>ŒþâÍ7Ï´®gáÞ/É»ÞôçùnTx¼-6ž‘±±Ú­¹õ}h·Âô g8ìÛoF�Òz¢-pܓ⊦kc¸Ê™K‹cqZO<?„'h†B¼‚-×Ê LU(XƒâY7%Q�Ó²H>¬ V&X�R NÐæ‘ä1ÕußÎòƳxÙW­Gñø¼SDäb¼½õWÞM¸ùùÖziÓxJý¥×ÚêŸ}"õÖÖç­?ïÕv¼³¡±- 4Àò¶|N-áᢸ³á®ƒ5èÕA§DÏC1œ‚(‡u°ÊQ-Â)ô4¡¹pJì÷¡B¨AWá¬Àš¡†C œ‚Cp m�Kð:l„r8 h ¡«èšPg`#¶Ãv¨€«pRàCØ(ß+Þ nQA¬ñFvŒ‡›ØŠƒ B¡*à5[`É9ã` -ìƒë¨Õ …‹ð¯ðÛÄC6�FªQ�FСt}ž~ÊžP¨²B¹®.U_Rÿ¦ ÑŠ´÷ �†n†¥†�ŒcOã4ã -ãncƒñSSœiŒéç¦zÓûæ®æ½æ÷Ì^¿¿,¿�°Œ±ìõ·øñ¿èËzÌ–m+¶í³kööáöö%vÐ/ 2à­€/©ŽJÇÛÎ4‰è(Üa(€Á -;Dç‘M@6`@å[ûODEÚ&Þ_×ÏDAƒïƒõ�“N×i§sAðwß¹aÀ}çÄ ß¹ ²P¶ïÜ/ -õ�[ Ø±@),„å°æÀl(†%]a&$@¤A*¤B:DÁ XQ� s` ,†%°fÁt(�nù°fB2DA˜ó! -Æ´ÓZ,¿Í‚Å0 ÁR˜…� F³`.L‡ñPQ0Ša:,€ÙrdL—ô£`,€(Xe0æÃ˜ QP¥PÓå½û錕T…P -  r¡JaŒ—ó/†9òº�,Ò¡×=Ï·=Ýöì½´‹äU]¢%>é…„K`!dAЍ5|ã—B$Ãb(…2X3a–|v‘”.À,Xƒ:Qk“¶ õï£,î Ũ0 æC),ƒ‰ùÿ$…NŒ?8³ŽÜtˆº‡çï[�’þ¿böÿ KŒú72Ïñ¡(t.® ÌÁ<ˆ‚R(ú·¼ÉFKz%’Z‡ ê´‹å½Y>¹fËYÊ‚?A§HÞ�Õ>›®aÝšÄý%P*9\ Ÿ_è³s}†R˜K|ŸÙ>Yfú�n£¹Drq¯�O‡™r\ ,ôQo£ Fë¼ë–4K®Ý‚c:YIŒÔœx¶P…ì¥0æÀtŸ|º ΄2(‘T¯KÚñ)‚90ßgÇ]Ûyì˜A¬wÁÿXæ³s1c&âÊBX¥Pe’Ïn -¥Bcs`”I~:pøñu�ÃL˜e’ŠŽÉ2iÅrÍ/ñ!#ô}¯Dmô;,|q;·eÃn�´#Î.ºîX¿‹¡X^ù!9ºµË™"ýN”¤¬¯�öª÷jÿ§¥nCNçV·3]Â{­®C¢e�’ÿh†¶ÕP$}柄º�èÔ„¥IJ%7‹%saÌ”ôô1�íx¾ÏK¶iHH.$˜Ó®�Å�%Wç8ßSÓa”JÏСƒÎ¾¨�ï{/]ae‹ïÛ¶Vþ èüœ�J¬m]SÂÏßkk:º'Ÿþú”u!t_"�þã?ÑÅX.ù-’^@ÐN¾©ŸzV`²¼�1»À\¬å6�&xvº¨ýŠÎ©À´MJ¡ÏÎV׿Ä,:^e0_~ë�H<+��í³B]ÞÙ0_JSì»¶¨“Òéœ,nŸã~|ÿ[™:û¸Â{,LHúÃü4'÷Îw?.?Ä£Žâ9“�äǽº®%ñWðWrݶ+‹Û-³mÝÜEfùü�à¸c¦eRªBù|ÌÄŘv¹ïBŒo‹º1�¬M_;Ãï‹3=6µñ*¬a~'M,…R˜óˆÍ‚Ç$κõN‡…°ÐÅÄêѦí‰Îú×yþé#ô(î‰ãb�bžŸ²]ºòáân™u/Â1?™¯ÄÜ£ÃÿÓ5+|ìüö˜Ý±êÚV”È ôµ'â’_î§(ž™ ó`º#(ëqQXÕ÷ó�ÿëÇ¥Ò3-E‹Ú‘yržQ0ÆÉyFÁ  ?Œ‘÷òa,DÁh£`<äÃ@ȃ�R/ýåq?F®Æ �/)Ž‚‡$-�Æè/iO„(I[dª#å·a�#a |6 -äy0VRc$í0†C¾œSÏ1GÂÁ@y>Xf£ú|#a”<Šñ#$/:§ã`T§YïåJPÛÎÙȃ10†øîö‡\È—ôÿbþAò|d;Ÿƒ|œö— Ê‚æx†ËoâêC0FÃ(+ñ”ú¸)ec|²äItMè €Q0&ʃaŒ“\ˆ™ÆùFŠïã¤-‹ó*¢sê|üÇ·ÏÛVÞÈûðm[Gmãþß¡Ój›û^ -<N:‡º'ùÑÕ}W<&ýÞB_\[ü½ÈÝ9{ìÈJ;çŸÝ:ùÚΙ€î…˱%÷�븪ûg=fuÔ<�s¸Š\mUr·û²ß¶ìC÷ÝzmÔ9û-”yºž .nÏJôøQÚž™ˆì_ÏÚªQ Šøro½·XΫK¦Ïõ}Zz~)Æé³-þ4*BÝ_! -^F‚ò2y.zIzÆ0]ŽcÅõ÷Uź ÿ¹Údùwø‹«‹e¹è‰°È'“}tµ×g˜ôîVÉ}Zï°>A-ë{y¨À`v'ÎE}§ç"¯sÿýµ‰÷<˜)’Gñìc�,³ð…�r_F)ö%äÏÝ?Á$_gýÞŸQ²3=Ã@é·L03Œ‡‡ ‰ÿ¢F� &Ø#áxFÃ0SÀ¦AäÂ8*;X`‡pèˆ tƒx˜ -Nè ÐzA -B<nè™�Ñ*$ʘĆ7�X˜Ý¥7í Áà‚dµlÁœ´Œy¾ã€#x5rÚ:™õCNØ9aµüPp (@þµƒ²És«üë;� ‹<÷;ôå`Öß�ü`%d7d‚4 È(éä( ,@�*Ï9†És*¯yË+È3‘ÎIëJâåä'·ÓÈwGÉ­•äÛ›•ì[N¾=AoÞ˜ÈnV’›«é�–8vc"¹á¡-qä_ߤ°Ý&ߤ�ÿÅÉuN¾N#×ä«m¤ùËÁ¬™“æú»ç=wé—ƒÉW ÙÛÈÕBòONþñ÷PöNþJ>çäÊ»M> &Ÿl#åä'ùØÉþÂÉÇNòÑ6òç?9ÙŸ9ùÓ&û““|¸’ü1‹4m2±¦,r‘“ ÙN>0’óœ¼Ïɹ'mì\y/�¼ËÉ;ÛÈÙ -7;ËÉÛœœYIÞâäMNÞàäôN?ÖÈÉ)NNrò:''6™Ø 9n& 8Ê8ùñÉìGÉVÓcGÝìØdrÌC�ºÉkœÙFê«ú³W9©«êÏên“Wvú±Ãœ¼\H’ß[ÈA;9ÀÉKÜÓJ~ÇÉ~N~k'µœ¼¸ÏÂ^L#û,ä…½6öBW²×F~ó|ûÍJò|ù5'{8yŽ“šgƒYM!yöWVöl0ù••üÒHvs²k§ÛÅÉN?²c{2ÛÁÉödR]ÕŸUo#Ûž9ʶqòÌÖÉ왣ä™ÕtëSn¶u2Ùê¡[8ù'O?åfO%O¹IU…›Uõ'›7™ØfÙd"•nVYH*ž´± -7yÒF6r²�“õœ<±ÎÆžàd��ü'k9yÜ–ËKÖp²ú1²êç+Ù*N~¾’¬Œ ?ã¤ÜBVp²Œ“¥œ”-1³2RV�Àó]b&KNÐÅv²ØCqò(' 9)]0–•n# Jº²cIIW2Ÿ“yid.'sÒHñm2û()âd'…œÌœÁfr2¬lF™ÎÉ4N¦r2e’‰M±�É…ä‘·ÈÓLìa™d"9)p� œŒçä¡Ð`öPÇÉXNÆpòàJ2š“Q2’“(‰�àdøQ2¬+šĆö"ùì,?ˆ É bC8<ÀÎ’AyAlÐQ’D°³�½È€\`'ê±Çc ¹ýýY®�äÖcðh�…õ÷'ýëÑ ��zrÌÌc!žz´Úc 9fË1“œzäñÒ~œôEI¬ïm’ÍIŸ®$‹“L[.Ë,$½»‡°ÞÃH/Nz&9XON2†‘©!¬Ç0’žÂÒ9I³å²4Nº'9X÷’BR’,%ˆ$YòQ’Ô-€%9HR=Óv³ÚX·ÒM°»�&>àf‰œ<`d¸IÎb œtå$ž“8âÌeî<ÒÅŸÄrãïÏb8‰ŽJbÑ+IT‰F"l¹,‚“pNÂBƒY'¡`e¡Á$„“`N‚8qæ2× èLb�¹Äé°2gqXIXY€ƒØm¹ÌΉ %1[.±úû3«�Xuìü-fæïOüuì,~Ff1‹Ž�ŸÙÀüŒÄ¯yS³�˜…mõ¢&NŒ†@fäÄH4+Q9QPS8aBp#· FI gV†’X ªG…ë6¡Äÿ~àš�ÿæO8üo[¬·ˆ +xœÝ¼ TTW¶?¼Ïtï­�¢nQE1C�dDQJç¨Q4qFÄ1**ÒFmŸQJÒ&à”H|iÛÐv´�!m4ŠIÔ¤�Q’î �äiºÛ„_žšD‹ã�{‹A3t¯ï}ßú¯õAŠºu‡}öþíyŸ2€Àk€@ʬeK£®ÖÊf8€SŠÍ)yÏÿ·Àþ9 Ê‹þûØ¢ÁdÀ­Å³gö(ûíT€¤ÿ€ÞÅųg( ˜$€nÅ%KW¸žÛ�ôìYP:kÆË§_ +�,îßS2cÅ"v‹æ¤t€¨…3JfÚ�ø¤ plYTºdé¨9«€¼¿À{‹Ï^”õæ `ð~9áœöªGOA#@#lÀ«wü6Â)8X»¯�C›Ðkpö‚ÎÁ:øÉ›(ÖAPœƒjØ¥=YMþeä\„3𔑠LòœCÁ…>…FØÔ¹ +i‚MpŠ4Ai"(•À è%¨€FT +«q4â±P ïÐ ðl€ °^€RxGãlz +>�ÃP 7`¾ +“á0¼§© 8Xô5P ܂ո÷ÃEP §¡vÀ´Z` dŸ³œ/ÀaØ3akaÛ¬…µ°ëð„K�’]ŽA5Üö¢c¨'‘*`Bëi ]N®B52æÁyÖ"Ù¡ZŽ�j©•ÓéÚo…�/§ÓQ=\•ìòLò=T`œ†]šÄ‡ñX6Š�¢ vÁ.íoµþW²Â;ä6¬ƒ§0GCé`’ÕPAGÀ6ØqP +¥$æA)T°Íú/ÔC=$²Í¤Wèh 4Üvá"T Õø¼¥dd@„³k°–ìò*XÂZìðª,1J0‚QÖƒØ�_xÐó`AÔ[“\‰=îûe•£˜ƒ~åQ�wïŽ) ¡lÒAv�¸•ƒÔóùÏ]ü<±Çð1Q�È™7ÈG6oú ÄÃÇÄnñiÐ$—+±GÞ íšXõ sdîüé£fG=a}"&ë ëì¬DÀPÌkh1{Èy (²€„ì Haë0…äæK­=Áz©õRkJ€êRÝ.ÕULÁ»„„z¿à5²åûoKñNݽLCéT€ž ƒ…AR•ºÝˆNšý ’i–`°Ýz£ÕÛšÚ’¯¤ÞhU�™™)jšjLKí�®¦©1é{ªqþ¢_?qäHÏÝ¿íà mÃj·¼ú{\~gϾ…Ÿ‹õ04ñ t<­+„Aš'Œ�=¤Êb¯Rš,ÛÑ)r2\µ™†8)Hxp¸õFkjªWHråÊ•­ÖkjffŠ[�QÓýQZªMµâ˜èXÔ+6&ZrhÌ åGŽ$m/<÷�ž-ÚŽ®oXÿøO<¾~Ãæ¶3’±zÜDþÿ’ÃÏLD7ßÿð£–K¨óTq÷2µIv�§OHOÛ-Mh'Ѹ¢ÚLCGÞÖTDkC¨¬Zmi©�HÇEc‹Lnl ]ýòììÜãúõ••ë×o$ðÀZ7�›ˆú"RQÆDnzÿÃ�/µ|ô¡àgýÝË4†V€ âa¡ç£ !Qæ ‚ä*›«2êxxU·&Ûö ?Dƒ-FÉ<(ŠJŽþXo´6 ÕÌÌž�Ü|å†Wp)øT3m™ª-3Åž™•âJ‰®ƒ:T‡ëŒu¦=�uκ ºàºËÔ�eFzF»bÓ{õî‹Ò“Ä59]@èŒ@¸©ßóÿ¹rÁ¶—Б#}_^óû·ïüÏwèñ­SO<\t´ òt¿Ø(œöè¢Ù‹.¾?¢míÞÂi¯ï9z2üñòÞ½ãâÆŽMݪÛß:ª°ç zz‚,Lñ'  ¢“JƒQ10Éj³Ø­—²›½ÙÍ©šX­7²›[…ˆ)Hu9\ª=°/r.UWºKÅEhŸ:µìüççëy J`Ïñ“Õmu¿š¹uï9<½õ÷黀V€ Ï �+ ›¥À$Uù¡×ƒ«šü¶‡f5J�f³út߬ÚÖ+7Z¯`­7®Ù2ÕÌäpùPsXPL¨VHKµÉ:d´À{ùøK'Jæžz˜ßᢨëï×HŸÚ¸~¿O�,½úVŸÌWP& +@fäá;½çŃ»¡zþ-)“là‘iì´øÉ@l-ÖK­©­šž­ÞÖ$a‡Ý按Åé½l¤lýºuëëjŸ~ºV²]á}ÿþÏúû5tê³OQs+ ( %t:H0ÛOœ”QìD˜‰7‚%��@ÊÅN2‰Œ͇<Ùz£Õ)ð¿’š™2|\�le_ËVÅ÷b_OŠ>‡LñXd�‘BJvc<M H3 4Sxå¡ÁÇùâ¯étïx²ÿN�ˆ?4”VÜšÌ'�K0LÄ -þh� 9ûŠ/þ 5FÕ¿#ÒÐ#ó][ÙØØsß’ß¿(Ân¨m�¾oú,€z„KâÚ1•¦22)Dm&‹õ’W3,¦i�6‡Ë1½mé½0zDónýºu’­•gú9Ïný'zãòô†°ã–»—©D+ Ê<?3¶˜œ‘ŠËFgDdDnxD�ÑIP‰NP{¥ãDP•J«ÜMêöîáFSd¨ £C%K¾,Ù£óº[o4·z[¯ck77+¿yÍzóšÍ©¹±†¿åkÕ™)k'E#‡fl{`$Š@»—�´P”Œ“Pz¯Þi©�ä�ÑuãVU<òê°M›[ß×0oαñ+¿©äíþ͇g'陵‡“’7|XŒ%dת½GcbšÒÓgMZÓ["·®~þ€KÃp]G+@…ÑžI6PI­¥ÉpR6J(6ë¥f=[Üh½ô¶ˆ=)·¬ÈªFAŠRS ¥YSTxÐ@«GcÐëÕ6éBtêÔI×õ]™¿¿áÈ‘¤ãë-ëMÊ“øËÛméô�–¯ŽîæËa4N²Côò„0+2+ ª‚�é¤È``’Ÿ¿éÞ(r%ÕÛj½–j¶äˆ‰–‘ˆ%1"†¤hÜ…Y#ÑZ¾ºQ‘_–ìÛœ3«Ú›L.T�j|©3wºiC²'Ä\éw +•Á'«ˆµÊÐD¶‡ØÌ ±ÞhNmm×â ¡Åw{”p¥:;4'âu{v,÷ò��ÑwŒÊß:å¯Ý?}ۀ̄ÔÙ‘õy Çë²>{÷üç}û }¢OI ^Ԩõ^jÖ*€!*ƶïðºA5J‘౞cƒù4i`D¢ ™FD\ñ¾­ÇY¯ˆ/)èžøŠW?<郫¿}…ÿ}Šj~õØ®K'ÉOBWð¨'°6ÀŒÂÂe…#©1èª×‹zòón稕ÎxˆSVdʼn ÎUà$i` +ŠòAÊ3 +?ð%³Ö­�QG‹6}„¦x½I%� S&’e6™§”‘•ŠqJ€Ë!$OG®Ë$±m^ç=Š×µ=Cgîó~\SOÜZÞßt÷2ªåY'Äx¤*T™E^5Øü›£�ô}ª»–‚Úµ”Þ+6ÎWˆ¤�‹«ž|²jó“On¾úÝ­/¯ÞºE>ýðý–�>jyÿÃ]ü=þ_üs~%"á˜IB~ èt0#Õ“g FB°Ñd¤Œ£’À„9)SYÄd3˜‘̹F†‰B$8iRÌ&£AÑ«V“ Éok¡9ûFv³êÔÃýÑY¶²3²Uñ½Ø™Iчü�"ZW™ Ô ‘(‡�0Ì ¡ÆS¤9bQ<ŽeñR¼£ô0gâÞ,SʔӔlsž’olfž &š&™‹ð\RDç²y†Ù¦ex%[¡üʰؔèo Æ‘$’³Hc¤1'°þ¸?Ë65N2ÎÃsY±±¯&åt5]É~e\m š‚¦¨i¡Hü‡bL(¦áTݳ{N5ðÛ_>t�N÷.ǹmMdÓ�:\Ô¶C÷ÁVzH²ƒ N{²§Aa“�’Ä N‚§¬ÌœÃS'6Æ0!'a§QR%’IÒ È3[o´¶¦ª:ˆ­Wœ÷f8åk™úPT„å)²°¼±V”@Ä‚”tÜ‹õVã"\†—1³�(J0qÒ ,…ÈAJwǺË}I_šÁ2å eÉ—'I“äùd.�+Í•ËÉ +V.•ËaS`J@šŠÒ (ÉjLkºü‚øç|æ¦&Éî­@øä¶Á8w-ÏÅ|]K§ƒ êj¾šo›ägœS�$cÙ‚PºrBÂ429iȬè¤'yºäÁG†ðѧÐ4ä*.;οÏ5jÇÔf:Êû4Y ëy]O§ƒ ^ô eNI–¨“PY¼1Š0"NŒ‘É ŒNƒ‰7“QVdƒSQä\£LUà$þ#œ¯HBëÍ^]Þäì+©ÎŸ•õ¾:GÖ<'€$¹Í•—¡rY’‘,KF‡1‹ö2N¦ŒÊ4Å€c (Æ ¤¥Sy)jlá�üH jä¥o£xG§·ý³­½ÎsðPÄç£gtYKh)­€høOO\�Íß@e•d‡¹*Š4…ž ¶Ê ú+#¥QêHÿQaA#Còb¬7†4�~PÿpÁ¹{¢Ï$o¶WÄp›&^ö•Ù"–ª™™"Bx†¤Ð–"¥È)JŠ!ŘbÊ Ìqæåç„䄿„å„çD¬!kè¶FZ#¯QÖÖטª«�ÕAÕÁÕ!Õ¡ÕaÕáÕ1h +Òu0êR�Ý_™á¢çÛPº/}ð˜¾û2‡ågþîw®Y9#f“kCó.ðOÛ–ãµ_/©ø¢m5^{}‘x§Ó§gç nÏí¡Zn¿·>ÜùÓõaëOև꿨%{Û Z�ˆá$ÙÁ~�ä VÀÜlÜ '%Ü@É’Øn”-ÖKÙWZ½ÙZ†K½"j‰äýHºKu¡4G ô*ñ.D%üsÙØH§{“««I.xUÈõ ?DnHvèEžô`‡IrB¬Žp‹r05 ½axÓÑðŠÛl0²n�ÁndØQÁýŒþÌÝYΨZo§½´ÒUËV6§hù:.¦0‘Ãû¡^±ºöC¢©Ó+»$G pÑ·’ž^œ_Õ¿ÿæy/þà\õÐà K'?TÕôäÓŸ|S»´zqÍõO¶VOÜòý³[‚C·ìú¾z‚VnåŸãoQ20ò˜È‰P’˜@¼Ý^L;HLºå=½cJ>Ï×¢Õº­wâ0Ï“é 4û+¡&G°?eQ‚B¡!æ�Ð7ýÔWÜaÁ!DA qÄØ(„D:úYÁD5$R½ÙZsösXh'}x¤8}d$¡D�ˆ$ Omž0¹táÃ6êÿþù›=žÍó÷ýп©`ó÷»¶„oyöûÍÕ[?¹^³¸zií7Ÿ<­Ï^½¥–�´YB�Ù@ªü UŽíþM¡;ƒÁfd–¤�.Ó�®³„®³Œ.3Ž8GŒšFj6êóŒ�m—{ì,:ûÏ«ç +·'56âdß0¯[ÀÏðoøWüôÄq›Åˆ ðpz�—ÿW QÀÉoû*C‡+�^¸“ÌKÆŒÑyßÄÇÒHº\ã=ÍÖÁ{“ÿöÐSÁ'Ã5·€ÍÖ¿sÒu6Óuò�ºLDœé¢±aýúM›Ö¯ß€C·Ï>sõŸg ·'9‚û-}ØöĸI(©(eMWýÃ-}6ÇR›o2ÔlŽ�3[e@ ¡*"°ÊŸTukŠð?ÕýäqÁ ™‡H6›kèzåã¯Y‚X[®éFp/ÎvÜÙ*õÃ÷²M&oX»aKõÆÕ¯ýcÄÞq3ë>³±Ç¶’æ/¿l^P“܈3ÏðÁùóý�âåްІ¤{*«¦>‚²�Œ”5aòS:¶§hk Á„j­PkØh³L�¥úõQ!Â�f·zE$ÓSÒ 1¿CªR·+•:ì4©1¨ú˪gwmæ#ÐáÛó»w¾<Ë’ÛÎ?½~ýÖ½—?úä¿Úöék é´œìÑæ„¡3­“p(Lx�æ23BÑú¸®êºó©xaó~œ[/hè¾Mã€�Üže�¤9ø~#¡ŽäpÉh½ä½äÕüÜ5W'Båš»ûy½>�'oò Â&‹îæÒ ÖDÄ )ŠADà .o4§ˆ�”7y¯g-?”Öû ç“Åï�ýt�ÄP¸.ŒÖoŠA4ª¯áðzi¿À3µ¶:Ï¿%Ë%;Èáñ§ Ò«¸^Q"ý ¯ˆW#âçp¡óhßõë¼@²Wÿà­ÖhLæßÜNƒ4 W™ ý$Lë%½ÑÓi¨.aöéó‚ë×%û÷«–¨F*ï^¦=Ùu†$OHðËp(°–ø½l>d­5Ôˆ¶1Õ =¥”a ¾æCXð­ŸjuSí�A{ŽÜó0ÿœŸB9(üá=#‡ÕO8ÝÜ|ºàÅüôøxTƒ¡…h{|üù~þ.‡ÿ™¿ëé§ñR�ÒrºLç±ÃóTÇž—‰‡PSBŒ’Y€«å9ß�oê¦uÊ*>†þÄîãƒÐ1º•ªõè 8@%Ö&a5F\ Z+1”A"dÈ0˜ÅüJŸ)·¦ÞhMí°A‘>Ï�~üM”é=…2ù›¬¥þÎêúzºÖ£èXÍ�TèîqHµ†�Pë/�¿A&©æžr„5ÅfÕê}v¢…;ª·j�uŨzñHE‡áîÙ3waz!š€ñc¼ž_Ø{ EÃïÜYÎ’ùÓ| ÿ5Fl lãá¸I +¶W¼B�b½¹µzßÖ* Ü´_ +ÿÁ" Ø@cØuƒ=ñæf +!ÎP·$±\«ú;¿Z{ …Z V#FÆg´•t ·z›½­'NèõšåÆÛíõ¨Vk³¯�©“¢Ý£Þ�ÑéqVÈR‡]’-•á—¼eGQPzáà­k~kÑœ7g|„L“ +û´Ô×ןFIýWÖŽ^µ%wàÛ=S¯þiú‰¥þ@`ÝÝËt»&ˆ�dèq™¡6Nª�H¬µÕDl�{1%ÈÜí�G·C„#4šDø»"S¬ÞæVo³o¾,’­žÇ¬×D€íÒ)»ÛgO‚G1š¢1ÑÝÒ{õè’-pñ†­Ï¬ß¸õ~víSß¾{áÛ§ÖÖìæüÊ~w÷È5å+׬®(_ƒO×>ñÄöÚªMÛÆ»¯>tá¡Շ]®·vŸ½rùLÝ4sÅc�­X¹F³Ýdž±ëÿáé§Íãܾ�œ;22"W›Æ!ÇËößÕªèeø­uרۻGèøØÐLKO»œ�ÒÝêCõ{†qº;¶wÚ¾Aœþ&ÚC,ú!ÑU!#ÑÿÜ7ž£]Çs±ÉH`ÔMÌçn´¾-CÃRä®Qš/Ç{}ô”ZúG#b�dšY'©Ñ¼�¨Ëá:M–µ�Ç[ÚããÞå‚òàú¶Ë"½‚dº‡µ€ a‹¤qвHd1EŒ¢D}ÔbTW2]ÂÏñÖR»…%è4> b'OÔŸf�Dé ½$«·U¸Òš�&ùà¾à-d-·[êÅsbþ“Á®Cw≇€Z‡±Ò°×¯VЬŒÚVS#mw¼Äk� Ñ‘vCd¼ÕÛÜìm½¤'iÍèus°^ËLù ÝêåöýÎJ”­»øW7ç¼?§è�™{Ú¶cGå®§ŸÔT\þ§üÛD"ãÞ|æÏ_Åv;“Þ«fó¯·ï]Y²¤¢{÷×¢¢>z¥BlØŠ�h1Gb-a0ÏÓÇ ÈÄ(¹ %ÌM)É•(8uÔìµ~M”©�‰‰ +ab N¥jO»1œ®ëNÈ£ŠÞPÕ'I­—Zm™â·³)n5G g@ IB¢Qµ²Dê(Sð÷£Ž=÷×C#+f½~ÕÝBÒómï~òÔ–Ú'ñëöÒ½¼•??¥mkùÛ{Oœڮýúñµ›´šà2îC8d{\Á!HBjÃîÉ‹¡Áfè�*¥Gˆß,LØç�ü’¨íÔÌ_È�jLº‹ŽyðÜ2~…7# +Ÿº̃õÓNŸ>þÆÀÙñE;*†�Dµ¨T$ÊôÞçGæóóüÏü o‰t¡§ö‚ˆ“{裾Üý<1ÁPk4ÔÚ6¢Zã#USpd€‚X"YjXODØR\zA§Y‹žŽ4kѶ uÀH—¯3DÆ#ôè7kžÛ÷ÍW¿Y·öi> ½öÅ÷ëÖmý¿Åàƒñ™¶O*6ÿf.âý­z´pï¯lzÎx¾îÜyÀà ûY `0Â6Ïp#{¢uë#Zw—íáŸÑz~D«�fe}R;)úP�AÀ8UŒP#�É$™&sHícœŒ'3“Ó‹ núë®$ܦXs:Î"é4‹õU² ½L½Íãa<šŒ ÈD:�=,=,�U& +LSÌs”bs9YFË ËL1S cæJÄÌõtuýÅýÕ§?=~îìqÖrg‰ö~L›n'�å^á§°™–Óå �Ëc»ƒÀèK貄»Sˆ“­ÞìVÅ^aJ@:r t¤µd,y½�OÝ˧¾ŠúÑö¸Gh5‡b�ÑB~k°ÕF˜kƒj"¶wsD„J.�ö�pEvQüR«õZûþÒµÏûÉ�Œ’±%™%KÉr²’lH6&›r å`SË‘rä%Ç�cÌ1�†Ñh4mmšÓÐ4<Í8Í´v£Ýx7ÙMw³ÝÒny·²Û°Û¸Ût ø9@°Òù€rÀpÀxÀtŽ£ãø89N�³ãÒqù¸rÜpÜxÜ4øç˜ñ-E¦Ñilš4Mž¦L3ˆ…ŽP·)h +j¯•b¢c|ÑKŒºn8 Ë#{÷3:³Ïðõ›++7o©¬ÜòÍÍ›ß|sã¾–1fLFŸQ#ð.þ.?ÃÏòwQ +ê�2PJ_Á×ò_óh#z ­Fµ˜ÖÄ/ÒÉ’$ðƒd(ôd*Ý»�DÝöd«3¹+»m‰ì^a¯ Ø‚ª-®+•º)=˜¤ÐÖ=ÊB@Žpú9ÅzÉ™ÝêLõf·Z½W®õ„ä7R›µ´øÆ-=8«¾ÍK¤jÅkœjA{ –IDºtªZ¡˜‘žæŒ@"vÇ©ÚF¦Œ/üÕ¢¿—•\*DEgfž›õÖÙ‹Ç Ñè=ãz~ÌŸÿrõÄG‘¥…Sæ\@ÏÒES'Þ9�YRüáþ¹��l¨yö¨å«¯XDÈ’)0òäŽ6赃è'†jµM¬Ç®Ôâ?RØh”dÁzP¤è•�Ö¨d‹=C­’ ¦êRc6�Ãñçε}p޵´íÂ…·ð›m™zn.»{™>ÒnßžC­?©uÔøo‚Tso)Õ–¤u)�{KíºMKµt9&›6ìØ¾aÃö.~×Övë;oÛwø*ÊG!üïüUÞÈÿŽ‚Q>_É× ÇÐF´­ák4¹&Ðr-~­÷ôP0Á²ØaB0F¹FP61ƒ"vø�’D“�¤øéÍ“o'$µ#ViûGÔ÷ê²Ô�)Fƒ§dˆEñ$V‰7ôF™¤·ÒÇ`ñ—ýe#ßp�¨àP Rc& ˆ"ÿ£üÖv~ó5ÖÒ¦àïo'°8ï×$àö_Á-:˜µ€Qè…ˆš“m”¡Ö ÄHb�ÉzI”å¾VéRkŠÛ¥²t·Væ! Êâ/¡1gQoï[õ´lDã0­â½œ•Ôã&mö z¹�]z91uÐz¹—XK›øÂœÐ#â'p£ôº6wñ]¢¦©8¨®®Ž, yg<ïݯë<Ï£Ï�@ýÞ€t—#-ÝåÈF×ËÑu~¾ñ}Àû‡$bK—¹Wç—{´Y—¸¤N½3œ�U”ÍA-kæÏ_»vþü5UOº×�}þâÅçÇ<ÞíàS·ø'h²õ^�™’S‘Åwò)hʾp»Öîܹö×;wò–æ úöرo÷ËÙÕÄ×ò#üU¾ÒîØ„ÞCUèqôg~ë3‘SP+-'f…X� ™¨?Xh]° êLa`‰ ³j…Þ%oö¥ÖT]0$¾ewÏw’�B.Z>¼zôäGM#ç¤�Þœ?ê7ãÒ ‡™K§ ÞDÌ/õÍH3RWPßœ—²{F2cF?Ñ+úlÍ%ž0a„%YÊ.rXa’±J{Ê*¤Û ºodúbû¢í±Œö÷;ÛkR²@¬]Öž“Kx¸¨áïl¼kgMzEßåÑ P §  *`=¬ƒ +T…p +=-hœûލêÐU8'ô ­P # NÁ!øm…OàuØp +ÐV(BWÑy4*¡ÎÀ&lƒm°*á*œ†dø6ißpÞ nÑÍ@¬ñÝð2˜·°A6„BTÂk0¶BlÝ&ÄÂTØ×QªC7p.ÂÏá³ÄC6’fªP…FÐat:}�~Æ—¨´Rº./“_’ÿKª)6z–>4Ú�½�Ó�+�»ŒMÆÏL±¦±¦ÇL�¦wÍÝÍ¿ñ³úõñ+òÛè÷‚…ZæYŽù[ýWø²ö·ÎTcÕ½ê{6›m±í9[ƒímÛߊöܲ§ÚÇÛwØO8º;–ùt4wƒ˜`°Âv1 e‘ + ¨ö¯žˆŠ’K|Ÿ^?FM¾c +üÍwLºœ§]ŽÁß}Ç„÷+�B|Ç&ÈBÙ¾c¿€X´Ìwl�bû.¥°Êa1Ì…9P K! +ºÃ,ˆ‡(H…H�4ˆ‚™PQ� sa),�¥°fà (�ù°fADÁX +ÆvÐZ¢}š K`6,†e0 +! Œ0fÃ<˜  ¢`à Xs´;£`†F? +æÂBˆ‚EP3aÌ…Y…P +%0C»v?�qAa$”ÂB(…\(…R˜´õ—À\í¼�, Ò ãžçÛŸnö^ÚEÚY]¢¥>é…„KadA²è|÷/ƒ2H‚%P +e°fÁlíÙÅštI°fÃRÜ…Z»´í¨ÿeqM (îš ³a”Ârˆ×0ÿI¡ãO®¬#7¢îáùÇVc„ÄÿůXýÿ†%Fý ™çúP:g„Žf‹a>DA)ýK^„dc4z%µNÔik×fû䚣­"Pü :EÚÕÙ«éÖ­I\_ +¥‡ µçùì\_¡fÂRŸ†ÅkŽO–Y>¤Ûi.Õ¸¸×ÆgÀ,í¾Xä£ÞNAÜ­ó®[ÒlÍkt Žîb%ÑšæÄ³…Ú»�½fÁ\˜á“O·ÁYP%ÁëÒ|Š`.,ðÙq÷;Wþ.ø_ +Ë}v.VìÄDœY‹¡ +¡L㳓›BM¡±¹0Ê4~:qøùu�Ã,Xe“åš k>¿Ô‡ŒÐ÷½µÓï´ð%Ü–iöè¢q,péÔu§ÿ.�bíÌOÉÑ£CÎd-îDi”uÐiÏõ¡z¯öYêvätnu;Ó%¼×ê:%Z®áQòo­Ðî EZÌ\è“P·�š°!I©ÆÍ ‰y0fiôô{ºÚñ_”l×��\H0·CK KóÎñ¾§fÀL(Õ"C§ºÆ¢N~ D¾t…•-¹çÞv_Yô“1 ësB*áÛº¦Dœ¿×Öt4ôH>ãô)(ëñBè¾D{ïŒÿŽ.–B¹Æo‘í¤{�ú¥g&åü‹ÕæÂ—Û#šà]ØéâŽ3:§Óv)…>»Z]{þ«èx•ÁíS§DâY�ìŸêòÎ�š4žs‹»ÄP!�ÎÉ’Ž5îÇgÉ¿”©kŒ+¼Ç„¤?ÍÁ/srïz÷ãòS<ê(.ÔV’ü|T×µ$þ +þJî¡Û~fI‡e¶ûÍýYd¶/Þ Ž;WZ®IU¨=ýy1ºCîûŸ÷·gÝè.Ö¦ûΈûòŒÀEÏMí¼ +kXÐEË æþb³a…†³n½3`,òe1áý"Û´?ÑUÿ:Ï¿ì1B�âšx_âãQ¬óKö¢K÷S1\\-Óîºáè_¬W¢ïÑáÿSŸ1vAGÎîôºv�„î{"/éùå~Šâ™Y0fh÷Êz^Võãúãÿ‹ˆõóRé•–Ž¢È‹EH …@¬©ó!ðŸÐ±ò8Mþ0BÃVÈ;N[!ÀȺí¶3D£ øÖÑxH“Oð—¯I(hˆkE�爎;ÇvÑŠÐéMo‚sñ¼�D 2î'%i§v¯v~Ê:ÚW´„ÞR#´»ÇÁȃ�%ýŒn�ùš¬}Øê4u»×mB¿WçIèg”¦Ùá!ß:½û¥Ð=Dðß)…®�¾¿»`Ö©}AQðÜÎ�°fae?FEøŸàDÜ%¬@|jGAؘВιî/úíz|ÈgŸíž7ê>|Ûý¨ý¾'vè´Ú×¾WƒO�“ΡIFý[tõØ•+´¸·È—×–ü(sw­;«Ò®õg�.±¶k% Gá!Ú½%÷Ý×yV�ÏzÎêìyºÖp?•¹Ú»ä÷U¿íÕ‡»õÞ¨kõ[¨Õéz-¸¤£*ÑóGiGe"ª½bhïZD7(ò˽ýÞm]]2}­ÓÒëKqŸ¾Ú’Ÿ@ó—2Ôý¢àE`$(/׎Å,I¯fh÷ˆ{Åù•÷uź ÿ¾ÚeùWø‹³K´,*jѹ¢žLòÑ]ÜÑŸub"Ч[%÷i½Óúµ¬Õ¡ƒ9]8ý�^cˆºB¬iü_Ì×’5¼çÃ\HÖxÏ®€$­ +_É÷U”bŸRû¹û˜ì›ÞÞû#þ1@Œƒ!0H‹[&˜‚&ÀC�ƒÅ¿ð„Ñ Â “a<Ã#`*øÃtȃ\ô VØ úƒbÁ= ¦�B¡7ÄCwÈ€d„txÜÐ 2! \2$h30;ˆíj10zjñ´DBøÉe 禦÷Êó½8‚× Ç¡§§°aÈ5@�Öhÿ_ hm`‚TíØªýõ‡@�E;ö;ôÕ6À�ü`d7d‚T ȨÑ3hw)`‚díXÒîaÚ1ÕÎí ÖÎ Ï$N8'm«ˆ—“;œÜN%?%߯"ßݪbßqòÝ zëæ$v«ŠÜZCoÞˆe7'‘›z#–üÏ·Éìn“o“Ésr�“oRÉ5;ùº†´~5„µrÒÚx÷‚ç.ýjùòj!û²†\-$ÿääeÿàäï¡ä N®Ì'—9ù¯£äóÏ‚Ùç·ÉgÁäÓò7N>áäã�ìcN>r�kÈ_ÿâ`åä/›Mì/òÁ*ò~iÙlb-Yä'ß3²‹œ¼g$8y—“óO¨ì|ùs y‡“·kȹJ7;ÇÉYNά"oqò&'oprz‡kæä''9y�“›Mì„�7“¦?eMœüéØö§£äOkè±£nvl +9æ¡GÝä5NŽÔ�ÆêìUNª°†Ûä•~ì0'/’C…ä�rÐFpò÷´‘?p²Ÿ“ßÛH='/î³°SÉ> ùÝ^•ý®;Ù«’ß¾�È~»Š¼�Hþ““=œ<ÏIÝî`VWHv?ge»ƒÉsVò¬‘ìâdç?¶““~dû¶$¶�“mI¤¶z«­!5Ïe5œ<óôöÌQòÌúô“nöôò´‡nåä7œ<õ¤›=u”<é&Õ•nV=€lÙlb[ìd³‰TUºYU!©|Be•nò„J6q²‘“ œ<¾^e�s²^%ÿÁÉ:N~­æ²_�#k9Y³‚¬~l[ÍÉc«Èªò+N*,d%'Ë9YÆIÙR3+ó'e�<Ò¥f²ô]b#K> stream xœ;ÁÁ endstream endobj -259 0 obj +268 0 obj <> stream xœmQ=kÃ0Ýõ+®ƒ RÛIéB ujð�âÐÎŽtv±$$yð¿/’夔’¸wïôÞÝѧSµxãꊋÕs @@ -914,7 +963,7 @@ g ë̳`l›1s4��-Ì&³¿’U¯õ ½IHŠ’‡7ñÍê!‰ ßÑØ%dè2hŒ$_{ŧ -2ÅÑêš¡©e‹d“¦iº…MQÅÖ+þÉǪkþkØÙ6ËåëK`GÜ×ùñÜ�²Þ”.L'¸ò„Äû˜µÒ¾*œ°ŸiÕ>:?”¢ÊW endstream endobj -260 0 obj +269 0 obj <> stream xœcd`aa`dd”ðÉLJ-*ÉÌ+-N-ÊLÓ JM/ÍI,ɹý�þ!ÓÍ#÷C–‡AŽ‹A¾»Bò°Ë<¯ý=EFBú×OVY†½ü² Œ\‚² ÿÿó(�„>ñ¨€¨W<ª ÌŒŒl|ÞŽ)ùI©ž)©y%™%•Îù•E™é% @@ -924,152 +973,128 @@ x býñ¾W}Ÿ–cý3�ýwÌ÷ý¢¿í¾Odýþ‚�¯`Ú.Æó?L™¿}Ÿ úýâwö3{VÖN”ü#õ[±©ª»zJ�ä©ßJ3'v­¬›)ùGû· è©]¤Øø¼»– endstream endobj -261 0 obj -<> -stream -xœû߀€ -endstream -endobj -262 0 obj -<> -stream -xœm’ÍnÂ0„ïyŠíÁh~Z„R �”-‚ª={¡–ˆmÙÎ�·¯ìMhUõ�Dßî83k›Ýí£'iŽ8šÜsØ£7­8Zok›1¶1¢mP‡WD‰²ïúXg„ÇëjSi2Æ*-.­Ä^óŸäÏJÿ¢¬[L“1ö®Â0 ¤LPIÔA…+ðaÆØ:¯Œ^@‘1ö¢åÚ41œÏòÎò�3â€NJK×9Á1úfŤ¡£ôMmÓâÃÕl*}20!•lm§È÷xV>¸+ R°!H> +270 0 obj +<> stream -xœÍY p\ÕyþÎýïÙ]­,iwµ–ä‡ä]=,?ôòú…Œ�•-ÙÉ’,ù%bKÚ•%¬•ÖZɶ0;à€Ç%IJÃË1œŽ‰!JÌx ¸Ó2„¶P§Ž“R dFõÐÔiE¾îœsî>$ Ã$í¤ÚÁ{ï=ç|ÿ÷ÿþóß @2‚PÖ¶§Ïs¦ú•^؃íá�¡ÝKÊï4?€ììh¿÷‚Û h£€þlG°%P¼ïùÀú€eÁ–¤aö)`= ¿#Ô·Ïò,ûÀú)wWO[ ï¶ü`÷¡–}aÝJÿØ<Ý-¡àǹÖï¶2`ú_‡{"}x•¥ÙW, ÷õëŸY äÌôÏÙb–ÇN³£x šù¹Ìê°ûéËc…,�Í`y̆­ú4–‡w±Õœµ{õô:Ëc‹q­,Ë“£­Q$}Z1¨O£ÑŠÃ8AïÒrä3í˜ö®v ŽCÃ8�Ÿâ$žÀëÂV€ãx‹°Exš•²<|�•²fgåh¥wш×p'ð7 ì³ ¢ƒ�à-|ˆ÷p™�ð'pœ�ðþv3@¶eØâ¶æá2ëÁ61Æð&~­h+}�ÝŽs–víIí-}‡üìpYÛªíמćúv -XÜ8Žð$z é.¼KËõZ|Ž …ÐpŠ–ò£êà -˜ ïñíì,ùg8F•¸€ÿ`=nIe¥Öûùe\@pŸüØjá:i EÇ�VPò¯ßâù»foqѤ[�ÃêBÃPÊ€gøÚµ†-ú,Þ<ÄgQ�mH/Èûð‹?,.ªiØâz£ªÒD­ÚQY\TÓ´eH+w•Í^oqQU¥F‡xÁ/¨Þ1äiëð<âx$oÅ#ŽàŠb@C‡1¨wð X1Ó?M?Ë9fã­šŽÒóï�.‚ãýÑ÷GËÒ�^g�×éíÐ1¡YãƒÖÔÏÓk™ Ç}?� é(òg²°ᤀ˦9ìàÞ”9N¤%Ív;ÆG}ã£ÎòòòòE(½"P™s±oÙÒ%só -¼}º[÷æ9½ìí�Çûû7v°?gKYšñŸÆ;ÝÆEý—Æ­­Ÿÿâw¿ûÅU* ^@â#Ð`Ç+þ›Á s]㺕ëÎuf';4Ù“Èn³“½dí`÷Q ‰'Ù¬¥$>Ëž•ì¸R3dkª²¯¿sËO`‡ÿ¦æÑLAsåG㣮ò²š¦-VÛÊß¶:loËKóV=iÎeþ¢4€A+ceZ™µÌfKÓt²ëKÙ -m…u©-ÂîÕ²cÚvVK݆mŒ¼Ì˼ä%¯Öñ(Ë4Þ`�ìÛÆÅ­Fÿ�ÆEýo¯>E»Ç²ÝÆ1áëa@¿ÀGàF6ÚýËìI6«žl!�¸®S�EGéaûôpj`šNäÊδ[ô´™ÉúL¯kÎô䴔܂óNWyf¹Sù'âà*Ÿ˜“þ¶3³¼9—å°L楹…s2§×éõdLw[b!£Â¢ŠR–j¼~Æ–R¿k»q‘�bžß^ýüÑ�ÎŽ{´7“*¶_ýw6à˜ýÒÕò‘Ÿ}òäkšÝè¼+Ú.cwÐûeÎ81Ï?]$ ;¢)“ƒ´¤\—c|4ž0£WÌ|q:ææ1¯Næ36Ôpú;ß9ma+Y7[eœ3¾eœ×ß¿í³2þsf7¾oôã9›ý>‚d,ðgÚÂ=¬ìaËAXós’x›=MJ´ò£E(ýhôʨãrÙ|é»úèwŒo§ãWk·]}SÛÏGŒqãœ1n €áе_雸g(DØkÆt-Ó]ˆÂÔ4‡ÓÅSÒ�‚tw!t{Ρìox¦ýPROJØÒ=³w^aºùޤyù™sÙ”;Ï1~~t|ô#§KyîøèŠdòß—�™f�RE€Ì¯æ\V–.É_ìËÈt–°¼\ËtwÆ–ÃÄ~Ê�[èÌa*b…Ìøài¦ÿjçßï:¿cWoÓƒ÷Ÿ9eüÖøMÏ{~ÙÚ×P«Ûxöéw>--1þuõšM ·®_T¶êç'ÿ탥KØ¢ �mÍ«ƒÙBGÙúãi¯âëL‡Vú3Y(ÊØtïRýÂïK�KçΉ=Êp' ïå#ªºX´°G1›ãýóãçe!ðÅ4ÖÆ�‹Æa=Û8¬¿Ç4ö mþä�ýú®´•¿Å›,Ò_½oyô{<4~‘_²mƒ š–­!#[ì™ñ�ñ9¿$‘ÿ˜~8/ã^Ä!@pE.¶ã}¶’ía'´™Z™Ö W&iùXˆ ,Ðà€6€^fùà'R2�éI„ÛêšÁƒsæµþż&,À'浞pÍ‘ÅæµsÙ<óÚ†\Vg^'c ›×)ésÙ)ó:îÄjô Œô¢;Ñ�>x0m˜|(CÃV ÀƒUèD"èC/‚hAEð ÝhC <¨@ºàAc +" ˆ^ìA”ÀŽJq7Z° ýð  hA7vÊ™´H|:Ñ ÂèG+ºÐ‰6x@Bh‘c“qš$Š@X‡t£«Ðƒ.¾tž'6s“dA§”`1–O@ˆ®�®.þ;ír\©Ðg*&TéC+PŠRÌù{Ð�DЃ~ô¢ A¹¶W*R‚nч5 hQ…¢‘º>2bL¨.fµ"ˆ.ô`/æË8ýï¨/âhŸÒ²Ò°ž œ¯Ï4;Šÿˆ�°þ§È^Ï—øÜiª(b.žˆ Íz± ô ýK¹Ï$^H¢Å³Qawȱ é×NiE¨,ø œv9ŒYSVÙ$ÆûdÆ‹5b}ØÌxe¡­è3#,þÛiúÒf*Åì“,&æx Úä¼Â&zAÌVÜU&åþQœ›�%¹2rbm@~ ß{ІN´˜þ©lC?BEpí‹éÓŽNt™yTíVïF‰Ýo@ö验ĺu~ôÄ:Ñý«Ž!úÖ"ÞÅù2ñ}/"í*Ï”­ë±T)æ)k‘)Ô¼Ñ 5ù Qp ä½òZü–¤:†9GÌÏï™ôV¬|øê1ˆúòeú‹§yŠŠ^´S*,úÉ·7ö~×D( ~Ý -MŠz<ûÚŠëúP¡ÁÎæâýNõ¢¯6íÄïk¥Rï]èD©ä(ÖîC‰ìÂÃ(�ÔQŠÿ!ÿ®ý³ü xòoÅ€øew1ò±…˜‡eX…åÃÚAß9ƒÎž¥Ÿž¥ŸŒÑ�ÇèµW×ò×ÎÒ«kéŒ�~4H?ôÑ+¤—O§ó—wÑétú«tú�A§^Já§Æè¥zñ…Çø‹½ø†þÂÉfþÂcôÂAýäósùÉf:éןŸK' ú¾�ŽO§çž]ËŸ3è¹ákü×ôgŸ©àÏ®¥g*èé§|üé]ô”�¾gÐ_ŽÑ“cô=á¢ïÐ`}Û oô¸Afб ƒ;@ß<êæßÌ £�9øQ7=æ GÛsø£>zdyø,?bÐÃm㟥‡ê}£€?´�òëß( Ã¦ñÃ3èÁ4z`�¾nС ƒòÑÁûÓùÁÝŸN÷ Ò�ÝÛDûÛsø~Ýtð{|4�EûÚsø¾í5h�A}‘I¡ÞÝ%¼× Ý%nÏááÔ“EÝ¡³¼Û P×6:K¡ƒzWgïÚF]~}×.º»³€ß}–:ý× -¨£=‡whg{ß ö ƒ·çPÐAƒÚ j5¨åí0h{€¶~ÍÍ·ô57Ý飿boΠ-´.¾Ù M>ÚhІ¦d¾ÁAMÉÔ¸>ƒ7Òú_ŸA ª7¨n]€× ÒºÕTcÐÕéüŽAªN§ÛÇhí­9@U•é¼êU¦Óê,ªH¥Û|t«“nY™Êo1håÍÉ|e*ÝœL+Ê3ùŠA*¿)™—gRùAý¦dºÉ¯/_–Å—/§eÅ.¾,‹–.ÉâKkhÉb7_’E‹Ýä[”Å}ZTì⋲¨¬4ËŸÁË*©4‹JŠ]¼$‡Š‹œ¼ØEÅÚߟ¤-LãEN*ÖàOÒ.Hå Óhá0{ߤ/°Øù‚TZ0Ìú7ëókh^ÖÐÜü,>7Ÿ -ò³xA åÃÅó³(ÏM¹³Ý<×G^Ï3�f*N3li|†“fN›õ,7eÖP\r:|Ü9F¸¸ÃGi©[xÚJ…‹§n¡[OÉ¡iÉi|Z%§‘.n³Nã¶4²)­;·N#«ð0I·ð$n±“e˜ùÏè<‰ø0ƒ†®i)œrHK!g9±a8|”-üý‡?¡íìÿÍãÌ +xœ½=Ë’¹qw~E‘;w–;¼6½¶–ÒÁ­#Ë›åÃ’¡qØámKT;ú{E÷t¡ +ùºªw.’$™‰D"_õøãŸ~:¼ÿøÃ‡þí¤ÿÓá?¿þãáþ»ï¾ÿí‡WžÌ¤'==˜É$¯´nJ1©CðÓçŸ?ëéó_&=ýåóáÕ÷'=}üòø¤'“¦�OËÜÓ��?ÿû×ÐZÿAksïìüw{ùé.?ýåg¸üŒ—ŸéüóÓùÏãêï‡û¿nç˜gXO«Q_.¿‰ËÊæ¢¶ºÅÀšyìåß@_`<ÝÿÇÇyõ»�¯þíÕï~øð¸&¤Aô³Æ(ë‹›’+ªYò™É‘|»Iwh~Ól�›š±vEÈC»âe>œYIXÿ H^ÿmZRÏ¿·ŽùÏÞ"ÂG«\´VÇ)é¢lÎN\¯$Ñ­Í´¶HÔf,©ÿÓ:ò˜;óX´r!If´ +æáÞæùï±á"'OéþÁX£l)e=ßr�Mý +ЉmÅ�\pÆ).Ø;Ý sXÉu•ygøùf`ÝM ³ÂÂY%öPÒ0§Í“;çwwÁä2Á]À¹ð›—e­Õ/¹Î¬9gH‘0—º|_ˆXù÷´}ÝMÒZ‡~aψ�íâ +¹0v²Xâ%’¢rQ»°U‰L÷3ŽË_/òùúôÇ›Š¡5Êk­sè›v` :¡—à�õ௠ûœ^”‹)RgpŒ€,TIöHø‡Qý +àk{ ÀmϯħÅ0ÇáŒÄ3ÿWC\¯Ð�Ìa&¶Šâ@™'ÄÅÆ¬�ôN% <Ù�‹A;¯òkžæ`߈áH V¨ìgP¦ý —�”L�”Ìù¯n‡¡­¸éY8�щ‰à“2Áiy @±xôDZ`êLŸ•R:ËêÛõÚwÜì¯Y½rXé5 "y‰Ð�@ _IÓhªJ8Û€õ+2`ÜÁ)è�™îЪ=ý-ØÞÚ}+ƒ4Z¯‡·!Ý8¼¡”*yÁzTš™‘0p€ :Ê·ˆÿ¬î‰’îñY¹˜üÝMì´ñÑÌ]aÆL�‹Ì¸¸¶z](,ïxb%‰X6«PÂfEý >UA¹ u¹ ?ÛCÐÁN ^_pHCtN�áiÐÚ†o3t‡ðHò‡¸ÑÔŸ¤eHÓr^j Œ±pÀPHc8�6nyB^£!¶¾`]ÕUç�…ºñ‡zÞï Ü XÜÜ — |;Ã>%P$ µŠÚæÍ¦ÖÊσxUÛò^ŸT4Þ›cv=®1I�ÍÜãU‚|Q.{ø +V ‰=ðÞ³/#è;À8Ï4’*„_:cÀ§©cp�eê·”Wu€¿-gÚ›üŽÄÙvµm'¶…ñÄj"È+p°¡;¯D<@‡ÉÇ1µ BŽ*ê¸ãÁu-Ç–Go\sÆHý�ž!W½„{�2c$І Š·ÆoQÎdk�\óÑšU8â6Ü?,!ù /…Wƒ‹ª¤b^8HiµJYk!F FŒRŒ2!L8m9ºþŽuwÇ3G4¸¹9ï¦pÆÑ´*1{æ¬½Ë É#7‚ÿ4ãK[»pÙ‹·QÀÒAúœK0G‘Ím ü<Ó …¶öü®Ü œ×•00üÄ(8ÓÛ·}øÖà¼íQb+=‚?!æØ¶ö8aÁÍaû›bž§„-Àd)¬U%Û¸ùù ÷¼Î‡pV•Cp´]]‘ìÀ±µ纻`Md5­Þìh?È3B$;È{Çòð)¸×Š?E:,µ��š$œ’—Úü–·ü¡Í0@¨ò™9ˆj²ëæ6Rcoôß.¯V¤àIÐY•MÞa ŒÄ<–+¨¡ze¶†<`O›Ã„RÏ0Ðóˆ}ÜaÞÕ´Á ìúß|9þ×ÓOŸ�ïß?~üëŸþøøûŸþú¿ÿw¨ìKT!G3çà|øqÒÓ�þuÒÊOÿ?ùé‡óœŸ'=¥¨’³aúŸW?^·Z‰J'cux‘ÕÂI.�ó/²X´Êœù¼5—£I½Õ|ÒªcÒ¤w­ƒ²&¿ÜzV+\ÌÛÖkŽ}âŸ21UÉÌ^™ìê7¼ejŠ�MzPâHƒÑ¦ +pöÊÅ\éRÕn¨-§� ‘—xÊÕ¶!'·#·Á0L‚Ûu`®Î¢óE%D!dOÆ»у d”‰S'}"§å8$1?ÌÁòvxdª1õ;˜�¯JÊÛ,2aà5‰©”ƒËä»®Þ³üÁ/âÁOºQ·øàÛ)+û*‰ùß­Ã x&…êì.51ªl‚‰›ê'¨Ì6‹YÅä �ñà÷AÕ¯8e]ˆñÌ©¨™•8�hÍ£l$;'mÈ*�nI{VW!P*Î’O?s#e� ð5¹öAL&9mx…1o“¡•6œÒ^· ÉY;øW5UõR}û1nøILF9®’ÝÄè”ÜfŸ!éñzšógMrAÚU,IhùÓ?kc•«=Ge�ó³Ð±þF0—„áL(0c}j›ß0‘ãç`ÝW ×PÒA»<ërä‘ùýp§ðgt¯5‰›ÅkMÃù�ﺔÄ÷Ð(ÍAJâË�ßPkÀtd¼ß/b3³@ÙÃq'sÙˆ6KƒêÈËàµK&¿”¨½ÐRÓ­JZïòo« Êûd’§úùâo  ¹”fª(R`¤äý¼N±@:iùL~�kïÌè?ÒÿýOÏ8C;ž;¡ >›Ð†á÷AÊó_©¸î°§�œÍùvL®ÓÀ_¸æ��4c18^¨òP¢ÜÀÇðx…!%é[ŸUÒ~{`cw‰# 4Øù^ÊHdShᶲϊƒT: l1Zü¶˜\ä®í�jd—ñëM›INàÏ�-x¹¾›&LoEi·$é&‚†ÞZ̸¡Ï9Ô–óà¡òœ•,F¡cu*mVE!!¼ß{�ä­²æÓ! M·f°ÆZí�ñ ­¼µNÛ•œlÇ‚£NíÔæ‚¿m™qŘóo!¼®ó—ÇÒŒb ìáN_“•7€ýÄ•éƒ�Óà8|t@ÊÕ¦½\ôWðû*c‡…‹Xk¶¾æ’÷.*�\É&ÌW†‘Y^wÌ*½";þÃ;RE‹5^å$5�þôÎ +—¬LNÎwËryœ ¯}‹VÙº”pn|5ãT? ?%¬éñÖ~º/Ê›3L‚^ç´Ìߣæ#áSϧv)¶Ü‚¡Že$Ñ{–Á |WÓ™µ½ïsµ@›ïja;aXéq¤wî{0³ÌëTt�Ô‘¥òðG…š‹Bé‡L›D:óUïèi”—¢… MMøên½çµøpþÜIz¶Z«œbÜü‘V±Ý‰W>äT?*=p¦?¥gPÁ ÄÃf½­»xS ÖUû4:í¹†°¾ÒÈr¯7c{⩵­ô,Öë?í¶� Ú&+7ñòä™ Jê‰ê))lcõ�¬ÜÂ!%|ø� lór¶`TuÒó �½î´„TóbrT9k³óë}ëOxk§b°|ßgb ,Õé Ç2�Âe^'�§JÑòËí²IWcøÓŽ íl‚³…Ø1A4m�EW|Rj#y¯ê¾Ì�™¿(*Ñ'„}×+ÊZ îVD¨\´Z˜)qLIßH1j“¬ÊÙíiÊÁ8„î¢#ß�:kàÓ²1q°?ΫÍç"ç +–@3’2=°«C +ÂÔy¡ ¿™éùýé�«¨TÓmãžå‡ÏÖÝã™PÁ^K/Âênéx ò�å¨(6ª?)€æJ‹éÐãö[Z”(†òŠE +`›�UΩ6�ßâ8ñž‚æ Ô@~PǦä�í¾8mØ¥qÒ�ï±o’IÛÚ�ºf¿Ãqõ„àÛš>¡%f¶¥�ÕPŽü© ”?m³€â»žÆuÕC•BæÊú–HDHR:}3 `o¡!%RlƒŒ™Xéþ!§¼M¹ªªùæƒÎD!7a7°�Nm‹»ïG’•Ñœ:ye¬Í#§b0Ë}¶BSg³›üóV«• +V0#ìÀ>\—´2.¥—cÑ-#k•ÎM2v³c8y|¥m+OæNÌéæGf>’ °H˜;;iÛÃ<ÆeÏ×N¼“ÅçÁ©KeN‚Ór8£½½|�k;mοnL0”\°î(¿Ì‘ˆKÔ{9§Lt.ìì6ÔÅ9;'¾šd�ÝO]p„ÚüÔXó©2CÊn±jÐSØ#¶¬ J;�ì‹Ñ™hijv`µ�‹ØP§ Ûÿoü[�Ó¯Éq–oà+Â�ý}½m‡´*WH§ÎR JÊY·'/¹ö7ØÐ*“’VÑ.�>H&@Ì•@µ…£�7ã9ºÒ¡'`!5Š2.d|QüV$0FùþâþåÞ¿#D·-ìIâ‰~,îWCÁ�=ÞÛþ uÃÀÆØm‹Ý7vøèSQ%§�wÐÙt÷ÿ».ü7йØ endstream endobj -264 0 obj -<> +271 0 obj +<> stream -xœÅ]Ý“¹m×_Ѻ[[·§[Š¿åR±ì‡¤|©r�Þì<œTÞ”]¹‰³ÞTÊÿ}ªGÓì& 9Ý=ë—�‘† ‚à øîÇ¿ützÿþÝþõ׃~÷ÛŸNÿùÍO÷ßÿ«_xõ?ƒô ‡3˜è”ÖÞ1D•‚÷nøüó»Ïzøü×Aý|zõ«�ƒ>>½{Ôƒ‰ÃÇǹîøññçßó­õ´6÷¦ïpù´—Owùô—ÏpùŒçÏOç¿Ï‹ï§û¾©ë˜/m=.J=]~ sÏæK‹tM˜©ìå߀ZŸÛx¼ÿ��ÿöê7_ýîÕo~øðnÉHÓðŒQಢÍ*{,ûÌ`ŒÈ¾Ý¬;U¿Ô ›Û�UYX0òT÷x©�k–#–—›šÕÓï`™ÿw<ã¡a|e€CÔYAJV\§$Ñ-M¼†FÔ&*©ÿÓ:ð”[�ò�µ²>dIf´òåþÒô=T³ÈÉS¼0`äœ'Ñs«E.mS?a1�ZüÈ'šÂL½Õ1§…\™·†¯o:Æ·:ˆf­°Œ°À�Ķ}Bœ4ÌjsäÈùÑ](¹T°—æ¬GôMݲ -Õ/ÙϤ9§–-`6®ÎûÌÄ2�ÛûÝ$­¥ˆç;vŒøÀ*­xúV«Cœ¤CbP6hë·*‘áþaš„çùëE>_�¾*‚QNk�üÚ²© ®wA¶Nè%\dÁ=üž>«geÁRÚ¨³ZFHŠ$»Fø»IýÑ kM¡Ýžï‰gNaŠa–Ùˆ;¦þ/ºf½´þÌ,¡b­(N”yBllLÿ�Þ)ŒÁ+ÛóbÑ!hç^~Éó�»™p@Ø*Tv€SS¦þÄ]HJÆKJæüÕî0T°u€= Gct¶LpQoµ»°X|iè‘´ PÕ‰? ¥t–Õ7˾ï¸Úß°zå´ÐkHEò‡ZGA|aM¥© -ã`½�V¿â"Æ®Ò,2³Z´hOw$!û´v_Ë MÖëîaH;/ÇO”R%7ØÓ—ZÍÌÈ*Ø1 /:ʇfþYÝ$Ýã’²!ºº›Øqã¡™Ûš6&n\dƆ¥ÕÓð…¢òŽgV”˜Iùì7+êo›Uõ`rR‚·•º-œ Îu úü…ÊT|çTQ[Üø|Öì#�Â!�.¹ÑHl[|K)�ay8¾÷XÛ”�´Rsß5j¦!¾:á©B$£S)gD£vÆ?jüónü£Ùþž¹Ø�¥¯§ÆõÏÜ$Í~‚!d:ÎGÕ7ײ¹Ýû%�UIRÆ)Ÿ³�›�„ ©n'�Ñ}÷A+kœqi15O >5/EÃUe૳�ńъšä¯ƒÊªú®¶Q_Ü) “´ ŠåFë…öXѶ±8¦7öyYü!®¡ˆ_•¸deU -k=Kk]k4¤Ì£iEà-µY1úÊìø0Cby$k`CŒ˜z¢k…^©°0·/Æe{XËó-Ol¨L­¢ÃÆ-˜1×ä÷¨kֹڛ廙ǚ l´°&|È*ÛÂf�ÐĶS˜$tZèh}€¿˜= ^ ÞHÄ{­rôñ…}B ULZ .!T¢·6 8ž�‡ìúˆõꈧÑh äÀ$-ÐÜ:ìÌH`H˜œ%˜Ç°ÕîµÒOq‡vÌl£*I§û<¶Ç0%”[àTûsRù#[õeØ&å(©�c],ýÃ嵊ä&ó*'{샄yÞá‘*;fmÇ£é©#FšÀ²sŒ‘Ï�nèÃ/mo"³þ_žžÿôøÓçç÷ïß}üÛ_þøî·?ýí¿ÿ÷YâòÈ—?ü8èáÇÿ>hå†ÿÜðùÎσbPÑ‚þëÕ�×õ–ƒÒÑ€ö/Ò›åÒX÷"�Pfdä—¡ÙåœÄöæ¢VÙ½§?³ã^®?ë”öÚÄmýUË>ð'™'Ét9)³|ð\YÿS@‚'Åódë2ÚL<ƘÍBK»¡´œ*0Æ#cÁ§hwD’5m&œèºf®ŽÉ £ó$BqËŽt(t’‡Ãu(§tÐÏzl¿þ–ÄhPT§5�»¨kKÚâÁ¼ãƒi«¤`aq:#œ˜J�Ltáâ8Ë/ü$.üä*uÛ.|’rÇǤOÿ®ñ2L -£jñn‚JÆ›Ð1¨u¼{²YÌÂÁê;ç¸]|Ìz‹Q‚± -¬á€É)¤™…8!‡j‰Z«'H`>W|RÑëx$ïY]Mxá(· -Í?kÍ\!€¯ÉNxßL3ɤ Ç §0ælÒÕÓ†Ãn×W€ÙºÌž•6f�ÙÓ`ê( „`E-8çìó‡õ¾Ü?8«œŸ’ÈÛ¤½—'©ø6çŽkÒ¯Å1üŒKn�dšñ®A2K„!ß·ÀÑ4+)l¶âÆ(™¦¤ÊèT‘¯Û°ôY`ì -j³{2 µy�Âì°‚À‰ëß[¥]سi q ÊD?î�«ì%–®\x·´L?ÉamK>ãö$ˆ²!œÕG8, æexv’ÂxñJSÛ¹8—abÕÉHšª�·hFç]L€wÙùãeeÅ�.HG˜ÑTÍÑR3N�ÊQˆ'¦(wÊÒëð3ƒ5€Í ´Å¥Ž8ôÕ°92P2©¤XggœÍfeU‡¶´¾W›ÄØ‹�,ßg®qš -)œ“ -îàx¸ªˆº{㉭£j/]Škô ‚„Kq�Nk^ïrµ­ßïu‰¼jÆÄ1\¢b08Œo‰m¶'½v’Q øê| ^¤�¦wL;ß¶÷ÅRïí"iH]–ÆòZ]¥7¸ëóÔ…:ÔÐBÔñOå¾$º5oÙ*´f;«�œµë\˜,<8‰.¢Ö†)³MÚëùô5u2+´ #¥C¶c~…5 Ø¯Ì Ÿ™CŠ!µ)(ðΤG·dö6×С~PÁmÁ‹µ‡;ìÂJÈ!;ÎÑÔTÁÁÕH 4�›eû^]ꓸuX‡–˳S9™Ø!@«Þ—i0®š„‰.4·&Þ£‚³ÊQM£ÜGm‘"^öì”\=ÓjŸ:ž7mÊ›µÒÖº#×ú2"¦¾/œˆ¨¹+€5&ãК]º€~>¤DD6‚o’­²ßðrÍûßT­ïúm½{ɵŽcu[ʯ¶ÔxÓó„ažCöM�*á¢yƨîiiÃ1û5 õœÙP¥KÂ7Rùž€wâ2«´F[ ºî‚sæðƒðVŽOrú©·%×&8Æì•/^yH±ÔÖ'aŒžÚœ�¨'L¾¾l¹v�«9ü ›î!ENÚH§t³@ÐìÆÞÓÆš@Ѳ¹P´Ã¦g›h¡T·mï"tÌtwÐB-‚STŽdO´¸©¯9�ü~\0[>´ÿ�9\ca¨äõ�ѧ(ÆVòÑõ -\”z�óf˶R* -k“r)‡ÍŽway/ŠÑÓ6ƒdópêK•ÄQx’Ñy?ÅaŽx ã^ê�×–É€“v�H�£ØëæÄÍ\Á¤’I4 ë0eV�‚$‰Ìâ`’ -)â°’OÙ^ã"ÏìUÙ[m (foŠBu='’c­Ê.Óö–š‡)sD‡.v-@a”ÏZ»Š×t1Öl ‘Òžt��*a^O<�kO”Æyå“3G°y‹"¯z¼JÆjÿbl!¢UÁz`K1Q‘«¢ìäBd–#ü²9© &ÜtÅ¡$UØü9þ¹½6ª -sU”ÝPÂØ¾âèEn¡ù¾mÛU�É=Xe¥Á®Ì(´Õ™x�<ÍÒ˜ßD�ÅŠ®+÷¤Òm÷ðÒÛZœ^Ÿƒ ]8Bý"0Gcu,8]$ïYȇ,¬.îHˆ¬v*d »±ÏË69­±‚ tµ›|Š*¸4âŽkdÂßnÛÙªœ¼5»3™~Ø72™ŸJÙ[98e!�IöeQT.&ß“’§–Øô½QZç`÷‹ÞÔü¥ü¿@!a$£¬‡œ`'fãÛ+ psÐüBo­=±¡ ¨Æüäe„ÍÏÍÍ n߀À@"Ý_ [3ܲ�£õ‹R…Ueÿq…8|É—Êš¾ÂÆ…#›#s‹ÈPÖÇŠ¸0æØl%ð M!G�*d»ÇƒQE6•S2_bWÞ_ä- V*]ì«Úk²ט4Nï�+SÏ5 "ìP®±Zéê`Às�‰‹-FÔ»UŒxÔïòœRPö’²ÞâÎk ½$F}£1J±)BÜ >¦âÊkÀ¯×RÓÊß9ïY¥­Mê|RÚgÓ±Ho—‹ µvªKVYçGàãíALOuY;=NëÀ=ž=~hR„ìhŒë´#6p `Õ¹X�§ ëÿ¯ü;„ù†«0`q¾Âé·>®7u‘Zå -a§IÊ!lLVÖ@Ø‘\«\MÜ�îŠWÑ0Á $ã¥m²6`'ë–;lÒ™|Mrèe[�m®‹Èô6nJºÍ<(?å�{“ó÷õ0°Ùnñ}bG$áaiïÙÚÓžsYç c ô18»e�'ï+�¼ö$8>—SôiÏ�¬A{ÿñÏLÏRÚ\£µ²V{îÙœ{VÉYc#„A�{އìÌø5�¿û�I ËM?žG¹=ƨ¼µ)!B¯™Âiç‹,‡r{üKcZ cÌí„ S¼/§ÖL\…ÕQ¥ÁÝ–_4hF?—s‘fØÈ!3âÞZ�¿¸8hÇO®a×ׇ«ñ¶§Š“%ŒAà �/z«lÈ·å ‘Ã'åܘ>þf"÷Žà‰"¼wgV�&·äq%$åƒÍ/¡¡*ƒ¬è)IlˆgöRQ½ÑÑvKF/áe«’×f¿Ö±ý­éÄ-:Ž@ü Gl4‘RW[•ƒó~GÏM’ŸâÞ!ԭ“•±X Ö \h5.€S&Û´½)ÿ[ 0B£ã�v/ÿ¿ÂP­Ä|ÂOâÜù®K¸1ó ïˆËÊÅ<šn7e>áÁðNyƈ’ÝÂ_¦#–(ü„+#dÇt‹·eB&Ãbð£ƒl÷ľgC<سJy·�õ ¡[éR@“(&Ÿ—»¡ó.k“úšDwÕføËEÚ)¿òô¿ÅÓ4!ÀùÁ¿´r^ïo!3 ?^ÇvÁ;+Kà2Ô'‰ÀVGPnŒvtˆÀƒ—�qüáhwÇZêØó§£íãóáQ&½1„ ã“)Ã�gˆ0c!)£ƒ¹¹ðÞ­ „†zÚ&õ2 «h ذñ�Ï?OÇ’›N(ñ`ó|.¹9ÓP–d�4›dU´>ÜX+G¡´Cí6|\�•c‹}7cÆ8ÁbßϘâç°ýB"зÉ€þ{+F lì¬|v͈ãô$ ƒ<�7Uõþ}î$L¦'§’v~G̉!í§À -âå¦b¢Ô$?…8ŠÐ)¸Ž ñfÐ ¦ÇOéa=C¼Í3ÛLÛiè–ˆWhf›é¥FïxÓh? ;Bx%š½°ãïž1I™ï.Ì;þÍÛ -tmˆ— -2z[v$Ý/={ "Åý ßífŒdÉêÁ:euÜÓñžäì†HZ?Ãi7•G ÇÅÈØ¯` ‹ÈHÁ©à ¤½=WÖÿIHë +xœå]Ý“Ü6r×_1VlË ñí(Îùd;¾+;U)ë-΃¤ò^%u·¹ìíUrÿ}г$H4MAŒ\•—i—C4ûã‡îFwóö§?¿½õêöÇ׿ûæ$¿úê·ß¼~öß'u’'yz©N„vÒ�¼×BkOïÿtû^žÞÿå$E0Ziî$€¶�þÎÿ¶§¿¼¿öÛ7'yzóp{'OA˜Ó›»ùÞÃÇ›?ýÛg?K)–ÆOõô©ýÍ¿¿ùý³oß<û×gßþøúvI§*èô^X­CÈÉTg2·Ñ1’¡üÍ›ÿ¤W…bÕÂF¥Twæ(÷ô æüù8þV�,³uVé‚h%½ÞƒéÉ+S.«@DmŒ'™5pGy70ëüãORøáSºKXõw#ŸF%’Oü’Òž?2.Þ�ЦêܳåcX-tˆ=¹çˆeƒ0&Ú~ªv¦êã*I¾$Éia¥óº''±lÖéxDrKcK¸Ä¨K,© AøÁõd’*q[E-‚•ªyYmêË–0¬bQz ]·b�ZD7,·{Ý$u›·•è +* +¥´[…¶u”ð +`„ŠÚØ®œ/ñ +°ÒÅVÎ?Gf¦¶—øÆ ]W¶— & +ã£íêx¨Áaµ Юð0)¼Ûàx•. +/CW½ƒàÀá�õíH£]}ÝáÀGb«÷ôI}Qà¼p§„–:ÛóŒ5QªèÐ?ƒo.Úò>M?iLv˜yœ>÷¯FOjþœüÔÑ™½¼ËÙÄ_Ôµ 4÷䃥9Õm·ô�!¯D]Âxç¬ÉÉ;Xû-î4.+™eïì]G{G9ê@ø§ …4!BWÙ*¡¤S½Uöã'‡½ÎÂÕA\ŘNÀå{Œ–\¨ÑO”Zq±Fg†�ú?ÅŒó£ËíA-¼¶®+ +iÍ7Íx0)ÈÂâŸç:Ãf9 çˆ72 ÎË9â­L™vÓ|f•ƒõŒ;*ëPÔ”ó…�æààÝŒ0š&<í`D²y?»¯gíØ°ö©höëóÄ�ò³Î£/$£èxñÝa"„øÈ�\ô0n0$hÎ-ÚMÂznÈÎ/ºÎ³[Æÿi¦`ŠxÒ±Å"YxÊ}Û¾Á1$;noo—®÷ÜæÞËÌVRÎ&0ï͞\^³Ys]+¹\+[_ÇÉm„–>É•Éç‘X\^¬£†XÍùͰZOHYÂÏuF8« ´.\ÏHY˹Ê‹ †»ÚªÃ‘£°UÙ’íµOpz�ÀÕß8)@{éòxIJ]¹âYTýNSŠjT@ 7òý}g!à¿ßåÊ:%TÈL�ФÚ�8HÆ;²å¾l”àC0]Te¦ª4ÝI8Sš|bozÒ¤1*Ѩõ®JÏ’·uL{Hö˜¡©ZWnÇF€R‹ b´ûy<¡lâ@�¥þæ¥lðzíÑñ…“Ù$Ó6×_T¾ûy.Ât£ŒÄ/·…#Š„–f +7žWLŒyÈ›òêãÃ(Æ®užî…—V…v™‘� )1d;KQ†l 3FXåM3{_p‡QŽrТR[}„ý”ìîRFêd“Ù)Ž8ÙåbÉ¶Ê ±O“Vœ¬ ))V€îæå™Ц kRÒéÑ‘²¾+á6áF±Þ#-”‘5Ó_+Îá‚5u-äv†lmö*á‹´»ÌBÍ™!唞Édô_ç Ê|c|£\«§ßÖä‹c²Y~O;#²F¡¯Ó +•¿›EV¨ З’o@Fñ­\w0äôE:f%uî§F6 +e#ÔõNÊ_Õ£áÖ&76£û=ë$Ð,™žøšŠb“ZÕÐsh†Ô–?4®�äöÀ„" O&�€g«rnÔ£ñ®÷8&FH•0ˆRt¼DÂÁÊÔ À¬,š—gúŒÝ8®Ã`šÙŒI“j�»Òb[Há&¿âÙ/¯þ”B®ÂÍN1A 0Öw¬Ÿ^æ&âM�ÎP9ÊeFêýé‡-'F^2e:í䕸spÌðÄ—�@„Á¿¶~?Aã^\­×.�úè…wàã‘bØòyþÒ Ã]?¨ÉH=X×ÿK’!Ñ0�Wfç¾sTo™¢iŠË]« +i+z�÷Èôçsä›Ùå—>Ïï�àžÄhTâXì´É?÷¨"íÔµ¿§ûOσӺèz®¾Ís®˜�^X§Ü'ó žÁÕvVdÅÁk¨CÝ~ºÖð•8$” H©ì¡i�Ö ëÐšÓØÕ�Ø�8 Šéyº;÷AkàúQH.÷ÅV”İ“àjéã!¿ù)­ýÉ +NúTU«Çž£– ¹êo¬ð›z"\à +¼›)Hñ *'9–B^†>ËbÎ^W�.8¦…ô@¹\ 'Ïe^VÁµÑj`‘ðæÊ4ÞY¯æÚκ9]o&a4ü V˜Sà(ëÒ~bV;*Æo8Pû=§è‰ïß//Á™ ´¶Ò^••°Üp›9Åòž›ùT3ÈÄ/‚Þý&�”7€n’Š ‘�­|%rèÌÑÝÂGïè4K:‘CN #Pî,Ä:R74OnR)ÇAm+É�À‡Ið ežAÀ½„­¡n`�˜ã²Ãö#·Í‚J™ÂÜ�žJ¥8A))™Ô˜ÖÎ\%‡¬ËG¸~_k§°WW=릈 .;ѸM?Ðâã2-vÏI‚ë0¶VýK}!QIÍab3 •$}¾9=‰a*ÖŸN|š©¡6^Ĩü~’WÐRIËtp´­ÊÏ�ŽÃåÂ=š±QÊtKŽ^Iî4×ê ´U½Õ:pjÝL„R˃ï‡Jv�ÝM"Òï%sM•©15©ê@ùl�5ºfVî%)ÇUê 3pæ&é¼<`ÿ§†åÌû?Áóžû?jíKáD^ð7GO(wšð 3à" ]îþ¸ä‚ÌÒ⚇ %ÍÛ`Q”̉Ép( +NXMßÜ”"æ -`´™†‘™tjñ1Ë+65º›ÎU õ�(¢-¢â`ä´ ¥SíaVÿ LÁ°"¦-ÒTmâbG©(`÷ž\Ò[T�á1inImåY½]±S�ì9a`ͯâäR±c‹L”"ݹæI±³‰ÚiÈ{V™L°"†/œ º…Ž5D$f¥óƒ#%°EžÙrZÖܬáå\&“Ÿ0nÒeÎ�à}Ð]8yÔ'÷L‘qçƒ�Þfj.5á)MŠi7n4—Lë+!ª@" + Êûv#©¶1sRà¦Rw4WŸ‡ÓWÄÈ …vVéÞ6{äÃMàëk%‘—ÓUFÔ”¦iPvûN’€¬ÅõùYPCœ¢1§;Ú +1©IK)† �áŠÕ¤¥JF‰áêàpü‹Ý2*Vk)t´p ·¬Y¸¢)ã¼€5ôõ؉IF‹à©•†wõqd²ùžÝd®ZT`Η]±¨X/ƒÈ>>�:»gQÝr¯‡`Ck…±B_í%†¿,´·™†zЇ£‰ þw“´¦©Ž þ¯$ 6øÏhøU¼GH<æSµFQñÖMÌ|X$ZWæâ~bÜpèúÈlλUCóîUæM6“I´Ô/¢ñf‘pﻑ\4ÞS&ž;v<>ó·š�Uêì®O´×ƒ2âûu•÷Æ©¾áÞ9Õ.‘‹^»E5³ÏpW.pöÛ%_Ÿüª<7bÿJû¨g#yjí[Ã�JŸÑÉZ:›g^Vœ¦¬Lu½–ŠYï~Å]´+ÖJ¹‹1›lƒÀbŒNYè|ØB´�/œßvòÑoY9÷¼Órô)®e?�k®0Ñ)¾ðCÛ–åq‹h®^„‹ÍÁ'¹HsžÕS²á +ÑŽ=Mõå–e†´s«2q‹µ)Çùb]¹á9_¬]wМcÜ…ªX¶œšýÕ _å@ ÜúÉѹ=5£õzuÑxÔCµsieçjjê,ê—QÝÊãÊ|‹]´¥š•1hçޅɦ™´Þkèœ$%zØ;m; E71G 0¥»IYÛS‰Þó9©u ²ÏÏ86pï>Ï) Ú©&kORH©#(ëâI +ýtú.`>mÐsÖ¶M8?ß0Ë:¦}�dÆÑ�6›4—K=52‡ÝZ#›z¢ØsØ{w>g¨âêä{òØ6çvk¾|ž7]Ë‹ä[W }Êð 8g°õðäÕ� +ˆ†ÞE)LW�á&v´ób=iÀq…-MéÊ®:¥ƒ_0ýžc†g^×Ô—lÞŠ2â®y+4…ø®ÒŇcå<{„ÞÈ�k¨S4…_®°2'¦6ür2ƒÚ÷Ðõï.÷�èJ^øÓ*Ѝ•ê›á¢GyáO7Ó°VÏÚÑ´<¤î&mÅ¿ªÓx‘+k[—7[¢cx‘.ËVîä<¢·”§w®lhÑ¢‘vv*Ôæ^ŸÜ£qÄIÁôÅS”š/¦¼çY‹;ª&¿Èlä(‹"4åŠ^§žïß�-¥ž#}k†ps„� B†¨LgŒå ·Ó�Ë5åV™Æ` š˜çÂn‚V‘52x~QP}É3¶‹¢ºÝq4q³9¥Áï7DÏñ¢ö¥]"yÔ‰§ˆçor)ÓšœY-È‹xð@]Ú±Y­É‹Í"£í*›ÕŠ…Úª€^�Þé¤wÚh*›n?AW­:�Ü6†žgí�q¸=4¿WNoú-§ \U±FiUÏÎèÍ�=@4”§×Îg”öƒf_ß“(^]á…Ü@t‡§k7W¶3;l¿Q¨ØÛé%…I@4'Ÿ¿«Ð†ôA�DòœfnUçw,Ÿh;žóº=5‡è<žOò?ädˆ‹Ç8q€Dõ/§üjWr±^W�®ŸPÑœ<7!v冯Ö}6o %ƒˆ^å9³Ü•±žXîiP"ãà{Ã[t€hlžÜ×7ìïD§3øáÍœM³™YT@4-C0"Ù$EiíÕò:M45k%…r®3Æ=ÍZÙ3|5È›sO^‚¬+´ö1ô}rWï5<È1H°Æe`ˆžfm¬°®3š½ÉÚJáÀôu¨Ù?[B(¢£Y{+¢’ÐàO.$ÔE44ë EtÞ4ì¸é`¿¯¿‘Wmà ÑÛl”Z M×�¼©Oª¢·yÕz¦uÈ.Ãdw4ãÑ=¶±Ý"[¢¿yŽl)~]#´%:žçÐv7_6 Ñæ¼Œm›ERŸßʼnÈ3e[}ÙÁÍí«L¼Aõ<§ÌpW~8.£Ð¬MîÑâ<Ï îË`Æ"}0%!�çR±¾ü0Lú¿]Kv”ÍQ Ìsº¢+/—¯h·˜Ýï7¢Áy²wåI`böf.‘iâìÊ¢­ynâìê±MÅYc£,Dô\²Ö—;ÀåHZWæ2Tsó44éGˆNq(Fõ<‡¡ºÅ›ÎvÃçó©þç4Åé/¾6¯Qrœs\B£«úz&£ÑÿYÌ…�ŽÔÎ!B@4V/Âú®ìŠ\\ÿaL¢�ØH'À0}h@Ot/z'…õk�i¼ZÒ{°ê=Ås_²éQ<Ñ2³.çiÒµª5"#›F€ +.ÆÑ)ŠBð“}Þ©ÿáóÛÊŒP9~âaAþRë¡LføüÝ ½Â!Wž¯ÿãîíûÇW¯nßüíÏ¿Üþðöoÿõ×GF‡ÔPåìÍ´­¿þé$O?½þ—¡òòô?'súñü•?�äI)3L�þøì§ËÓ.ˆ¨´¿ÆZC5«Q®±–Õ0<—¹ÆZ„fÏ‹yoRú¬ºšñRD«”?ɦõ¼Ö«ë­gœ0Ru­õ††!�Þ]Ò}9Bº¡ÿâ:ë)BTn×rù^·?¼½ÿÃg¿Üß” ú(CóóB_Èô.¿)Má!¨›—)Ë·–M™^¥ë$k¯GX:€b—ï)ß’d"ÆÚ.Øé¬0R2¯§^?õXžrCÃççÙ¾‰d2‘vv ð®�ÅnÿLn� Oè1U”\|³'>ªÇÖI ž»Kåȱ˜•@~�éÎÏ£¿àäm]l÷÷¹cò䈜KE~Ç‘Dä9•wÒv ¬ÄŒg‡Ù-”¶ª(]@çül&‡8Dˆ×¹„&|Ö2ǧOË´©…!#+çé._¿üëÛ?¾ùå_}÷íwßIùõ7_�ï¸Æõ„¢çjà_×è ŒÌ­Ê6áËe¾ÌþMçG©*‚ãZäÀP›å^½ ‰CR²ààr|£ˆŠ"[\J±q-Ðy6µ<-Ì‘©–"™¶Y\ÊH'‰p¬Á1 y†¹FA~»|â₩]\s�g�oW­<ëuOVQEIÛ k×Ä[žg*Å ŽYÀ¢ò™»'ó@†ðk æ ò\Ôž°ºnJ)‹”ó"Ï\¬[âï—ÿ9Ÿã‹E›*°¸àd7'¯(*<íÁ$ú.¦ú8'ò¬þ¡~`š¿fÌ¿]}Š L6²éG˜aPà²äka‚ºæI Ó$ÄYIX#ÿ> +272 0 obj +<> stream -xœå]Ý�7r×_1–eK[\²ø}Qw’œ � °Þ¢èÙnv³X¬îi6ÇäE³šé&«ëãǪbûöÇ?~zxóæö‡wÿüþ$ûÛ·ïß=ûÓI�äIž^«“¡€t'ïAh0îôÓ/·?ÉÓO>ÉÓŸzxööÃIž>|¾½—'%…=}¸Ÿï>>üòï¯>J)¿þùxþWJ8>dÿ“Òß8)@{éη|”ÒŒŸºrÅãø½[iAÛñn ¼ÊhB÷|9^hø¡OÓ8_T§Vh„éa¦‘mþz~Øÿøð/Ͼûðìßž}÷ûۥ¤T!)�AhpÖ%¥NA˜ª >J ƒ>Ga|˜xzþ|^§JjM>›õŠàøýR5’ü&)lாýþÓÃ^ýüpSîƒ0Ѩuºa�n=±1×°'êïn\”³¯²_‹ïµB‘Ó÷7Z‰ct£žKíé!&y+Gþ~Ÿ«©Ò™“n$¥†ll)]�í¦à¶Q^€ÁôP“™¦Òd'ÑÂvJæaï(£t2€Éä‹Dœ„ìr²dWå…Ø�I3N–�”àªÀ wózBKCÓJ5©èôèHUïJ¤M˜QÌ÷H edÍôkÅ\°¦î÷±.º1BkeÍ^-|™V–Yª97¤ôHXç‡yCƒkzB7ŒÊÕzú¶&`¤“È‚ðÚ ‘5 -}-à˜f¨ü~þÿ OmÐäP–QÜ•+Fƒü�îPtsžñ£GŠÓ#¥…s^³¾­¾ªG'¡MlF÷=zÖI jù«ÆLOnó€À< ‹Fxmƒ92˜�÷™‰A*"žlAÏVíܨHã¨8FX•PˆÒt¬} +P³³2©#@ab7è0œæV6ƒÒ¤[㺴XR$†É¯¸õË«¿¦`GkF35§™Þ -ou°gÍTgÍ�RÞ¹“ç?Œ?Iá‡Oé.q}¾Ìž -™^r&9Ò GºÓ"*v;½jÂ~ný+#Âxç¬9€‚É[5(0æxRÛúý�«ñ‡ÿªÌYzõÑ ïÀÇ#Űåó|Ó ÃžÒ•W:ˆRcÖõ¿Ã’dH,={eµÐàêìä>™üZé‚Ô":c-ÉecM”*:ôgpà�½äù¾^@`¢”´¢—ùE@&=ŸçxœRN~ÁO#$¼'Azº*%SÑR›\ôi4K&㪿§ñ§çÁÉ\t½f8gÌYÒE¿?™°Iƒ€ÃÕfVdÅÀ+hêvÓµ‚¯P®sJ‚ ¥²‡J¤ZÁ2ÐšÑØÕ�Ø�:"Yfƒ0&Zu5vî„VÏA+Å徨ŠR€v\-}<ä8?%µ¿ZÁÉó÷/È‹iÏQK†��ƒ8#€÷}.r×JA -h¦aŠ®–I$ÖF´d1g/�+H§Ë¥GI/‚÷pWöœ.W"A(éÒ”ÑÞ‚ÑJ{Œ @Ûä†?Ãùo{®�V‹Œ·dV,ÍÆw„Ö›®º® §ëÍ$Œ†ŸÁ -³û«-!í&fM±ã7(„E÷œ¢g$¼~¿¾L|Dg‚ÐÚJ{UVÀòÈ-æË{.æ�ÙNÆ/‚^ý&�”7€I†ÈÇVnɃ:st¿�p•]ŠÓ,iO91LÅ·â”Öè¾n…QÔ¶R�ܼ}‘ÏP î%lu�f�˜ãr¹íÃÁm³ Î¹e¦ç‚µþ|釩Æq˜º|²kÄGk -{u%ųn„È1\òPI#¼T®oŠÇ©ÚI¨äÎó5ãi!8å+C3‘šU^Ĩ|É+ f‰H ´�&Dh�õ,¢êÄŠƒ¨lâÃcŸ2“¹%un¹]VAûjµÕŒV·S0Èr?ús%ägÖbk˜0{7•kzL,9 -DÔÆø#…³AHŽQ쌒ƒ#y�øˆPÍia¥óº'ÛWe˜U™âxÏUù¾R–—àÍÑ Êe&`ÂÏ‘qŽŸžª� ³¦¸a‚CI)óúW”3RŠ|%¤ê¼ïã$Ÿ­Œ<øœI¦«2|r\–r7•+ð逃ÏㄳAHšƒÏ%%Ãgn £Á0”&WÔ&¨s]dUV–ÙÂïÉ!Ø¢à ¿ˆ…1è¡6͵*öLJ:·¸`ÄZ/´ÖöobãÐqÛFÖXa¢jhtÚd|ܾQ; ©^`- ëK¤^8t +èU=u$û×Åà�[2RVÚ¬ð\ b.mð€-Àû »ðñ¨Oæ‘ ç`Ròèš÷AídR»(H^z'É Å9¢TŽwÜqn ù’É´ËëójÑ¢4¯õ¦ËžP�Rڸπdá5ã,Êj!mfÃ}Ïõ�Y­…3±ïΦw·R�J…Q‘¡Ç3¹—œ5PõÄþu„9,^RÐ!M5:¥�HkWS‰�Èêi-”Ó:4ŠŠMêUOü·N«M}Zà–œŽ�«¹ U;Q«üÔÂ@V "„u:ºnˆpÄká@©Ø•ùTSjÎ� S_,"§ƒˆÒkh7 [ç›ë(ªö - Êûfè63í¬DÍ8DVºØÍ0"qn…6BË–¥k�÷‘8€BG¡�Uº³]¨’)!l6š#–ŒºeDÂ¥wF8« ë --ÙYíe8`ÅHn}Ö2ú|ƒˆ}íhDŒÆé~öQ‚¢–R Ýú]Á)– ¨¥JF‰ÀéààúÛ½Ò)ÑTk)t´pœ¬¹þRÉ•YP"Hotßf8É5ÓpwQ§G&›»ÙMæZ“œÔ\¿mZÖš”4õ²…|â㤳+`Wª‘”d#yET¨¯ò²¡|+ õt GÍï¥hUM¹pþ:’`ãù% =âù|—uò—¸~MâŒÅ~X“œx»&NMXä'f‚yEœf0'z>0›¸nTμþ9…ŒyZ’mÜ%úÑqv«<êž²"ÚÐ�vO�°†Í ™å=Qµy:ŽÑ-§Œ8‡w=ÅAÄô* -¥è¾â ‚z0BEml»8Š^bÄ©ð9ÆíÈ¢{y8¬ËèvpÒŽ™˜:V2 -㣠WZ9� Õ‰•³oñ3*PF›bikk>"²â#e%¼¨Q´TÊzÃ(n<]é¹_+¸.:ÿ7Ùwf‰‰A(˜ªú© wjÉ4ä¦e¥ÖóúÊÑ縶�ý®¹¾Dsõìx6N»Z�‰ Û%‚7a‘,æ4 ºäD+®Ü¢z“Sÿ~;·Š34&nq6Eu.'¬/7€ñÁÐt,°ªlôoßúTDKò즉�[?9Z ³¤æ´^¯tŸŽ0·ü\¶r5õA%ƨääqåHˆ]´¥r“1Lç$Çå”LpÃ9Ѻ³CF´}/VÚvŠ\Ž_¯ØÛOÊÚšJ´k§Ö‘BÈ>_qlˆÜR›Q4´’KÖž¤�RGPÖÅ“úi£!\À&&d$:‡SжQ8o˜iÓ[F2ãèV˜-šk˜tS+sØ¥Õpù&’=G¤"Ï„}ÃPÅUµ÷åW×ÞnÍ—‚­ˆvß9åÖWB_3|òœ3ØŽzøÔàõ�Šè¶�Ë[úê wÈE;/Ö“Üé�\ÑIW®X¦ò¤‡_0}Ï1ƒÈ_Y#¬v¡³ŠM³ ›2â®y+trï}¥ÑÇÊyöè±Ò4ˆÔûÐkG«Ô΋œÌ vºþn‡ÿH4 /üio„ѱs�ÑB¼p§[IX+eç­‡9ài7ekÎ5Õ¼H”5M»b²�K•-'îä7�SÞÒ>­ˆ>×ÙŸº/S2 ¢-xПó‚Q¹¿¥cÁ¸ž«Œâ£Õ‡k»¢Xu�XžèžcùžÜà_f¼jôÚâ] µÃ¹¹#œ�ê$N‘eW.qgô¶2éüäg° Ã?‘c€æâ×®àNçík6ŒCN4².â×®üàð=Àlp=0.–ÊÏ?—š5›úY?}yÄöÓÊ£çt×7džÈEo=A´°.¢·feI•ý¨sfîg¸Bô¹Î®ƒŽVë]½·Iž”¶JÜíˆöîÂù‹/¦?R9#Òléo°þXèˆY½blz@lÈ^~ž<T¼š6á'7ÙWéÈö¼ªôž?ݼŸóM>í4Mº.Å´ã»&r§œ8ª€ÜÌ$¨\÷9 ¨–‡¿Ÿ¯ÀOQ2c¾VËb䇭¹èê´"ú)øª@uíEpðÿ�—éÙxx”döÌ€hM_KPÂ8¥Ž2Ñ|»ÓƒÝó77 pÀ�J»þ+ÈxæÞëa³×{ëtî.ßSxöô/ -Áƒ ÷Ó?Iò‹úœU©Q—#÷ô†FX¿Ÿ7¸ç[”Š:sÆ㜷(ÕJ›S†(¿þù{Äë‹Ó(Ť%ûé~ŸP &œzÍÒ£ÆVKeËw1ñŪQ.nx€}P[·†Ç­æµÁ^FJN9²ÒÜy¾�ï3ÿ½â2BÚyaœa^�½®X“?3Á.:g ÷ -¥róZ;¹ÓÃ)G¸¯0hºS×çFÎ"wí&oƒš£T)|ÅÒ¤ - -Ý6µž]Îq¦‡|¥Fÿ®¢…©&5§,i-%?²-¿;r]œœê‹Tu´sœ!Î:6X˜u§„‰…o^—\ýù&½v³€�Ó–Ž8¸”u—_[°ƒ+ÓV ã‚Únð»ñ‹üæè1¿ ‘åjɺÍóÕ›ƒ� -p †»RØå,ù9j$4„ôg[xÁÉ‘{'«AÙ»šᤌðë…÷7:!�DLd]î�ÚZj<˜Ýjö]C¶4¼×£‘z%¬+SC.3ziƒBºŒW­–á{î)¹¦ë¡zz:¦’™q¢òa“A¸ú8ÅjA\SEêª(­/EC€èŸ«Ï~Ê¥(\A�rªªûQ\û{jÂçՑ뎮ֿ=d"|¡Eóµéí?ã÷,rqÇ£�·"ø¸û¥ê#¨!aâŒ:>iÂ?<‰€#«L½-¢·~ U+xú-JæD%”7:aâ}Õ÷€ê82?—�6Îõø²2Ç2a†Ÿ¤’@Hë¢_ï¢à@¬>7ËÅÕw”¯—ï -¾¨ÜûU-÷€é¡÷6˔ʄà9Ö°ºzëcÖÀGŒ<¦á–<ͨ®Îõì ~À%j§‘ÂZçÚ.žØnË9°àò©à”˜£ñÖ]Pœ¬øLî·-÷²|Á”\ƹýª5"#›Ž -AV\+D') -ÁOöyD€WàÀðù¶rˆ¨?ñ¡BþRë¡Lfø|‡HïxÈ•ç÷ŸÿóþÓO�oÞÜ~øë¾ýþÓ_ÿç/�œ /D -§êÐw?žäéÇwÿ:hžþ÷dN?œïùå$‡7/ÁžþûÙ�—M§Á e-\i¶s ¾ñ×™ÍjÚeÍufs Ô 8{ž¤DZu:㥈v¨ÿ•MóiJ·®7Ÿ2"Ê`ì•æSCá«vé­ÀÝç RXgÓûe»Ïç†S„t„kͧAØx5ù)+¤5)sá|ùªëo¿ÿôð‡W??Ü”3ú�ÚgA¦²ùåwŠ„AݼNÙl¼ˆnÊjÛP'Yká÷Š]¾â¥dæ„Z䨩bfð{vx–;ºE•ÔðùMæ!àP€Lž� JkøÓ )ášÉmáó=¦ -š‹{¢á‹z! Äs£T¶W‹Ó#țщåùÞû·Œ¼‰Ã�g]l÷ûÜ{r¹Î…Wßq$íV.ŽþB»V¢c$βŽ�MánÅ©®Í�÷ŒP”½LØM{>©’�ã(pF-![U÷5±³IV \n¨Ô®NQ!‹GÜ8Bš<Znñå&VËjLë®B¤ó:¸òVíU3öÚ*É·ËG~¿ø¸VpâèçÙ^P®ù{´gÅmB–ˆÄJK"�ý�Æ÷ÂÿÀ+ÈZºœX2ÒNKÍѹAZ@ÇÒçàØ®¶DÐÊ*¡¢d°�¦½÷)“Œ2ÊøUæãõèRéeNnÁ¡éšì¥Ùi>.Îõ°!o~ø/Ò -ùe²Î/9ª4c -V 0¾�d¹„±JÚW»’çx€¬¶¡üm“-÷ÝÑõmËÊãüŽ ->’ ÷’©j+kÂA1>¯Ò>K«íqâÖ6Ypmò{—\£GŒ|õ5ô{þºž<^½ã8Æú½ ³Ìà~¿·ð §è.ó‹éÂÚü¡Vö�(z?—g�¦Å(ûÿ?í}�úüœ3LœÅ?ƒg«LÏŽÃxÞr$pn/4«Õ¦mÌj›1]�ž­ë3F!P#ó~Íý5—þæÇäÇ +xœ½=Ûr\·‘ïúŠ!­Øf(‚¸_¼ªdcYÉfc§*e½Åû`ªÂ­MÅLVa*•¿O�™9 osÎH/¤¨ƒK£»Ñè÷¿úðü�?¾~ýúþÝ¿þö§ûoü×_ÿñü‹_|ýÍ›ÿ¿3;½Ó»;³‹V¹h­Ž»”ŠJ6¿{ÿÓý{½{óýNï¾óû�V~÷Ï�ß}·ïóÓNO�’‹»¿¼øþÅ^¼ýîÍýàd.fUŒKŸb.¯£òÆÙO1WpvZ—ÿsE«ÌD°°Ÿ,Ø—æòI«ŒI;½i:ç•‹NûO5ŸIʳryßÿíǧׯï¿{óÛovúþÛŸþ÷Ë?=ÝàéReÿéŸÖÏÓ½ÿûNïþþþéÅ×ïvz÷îÃý£Þ­ÂîÝã©÷ôëÝOüò­õZÛÃoÀïxü=µÑ?hgºö�ýW{üj½º6¦ý«ÎoþçÝ¿xûŽXºá—î’;nÆ�+¿š~\O?>›~¼Üÿ‹Éâ­jÌq«N�„hXHÌ Ü‹Ú§›;‚ÒÑe¿oóöˆÞtì�ú]ÿPICs ‰žzBÕ߸ß�ÌÚYÆùþ·N<>�€Ïà” %ĵÝõìì�Íû_ÌÿhV5cÅ`Ø •7Ùǹ�}f¬;ÈÚ`L<Ös‹?öûi&»ŒQ/`Ô•N®`Ѻ&´6ð=u[&Ás<ôArÖ¶2uô•ªÀÕSò±Å}¥*µ¢'†>sŸ®ïíV öÂ)& í¿é©1Ãcº¿·v!üü¯xŠFAvo$èëéÇ^ô½åçOÂ~ØÌP�Àl¶gOQ€ã#挛ÅÐU×í¹m|^@¦ÎWI϶ãxeA±Ž9Nzšãe†Þ¯�¤§›R%ç̬‘R'ÓÏ:dôDÏó½ÎQEÏQÈÿ7ôœ|h=O%¶íºÎÇq<8®ƒ žE"FL*”PÖ2웬ÌnÝ!Ÿ•·¹ä¸Àë¨e?Öš÷—ç;²üs�Â*%¡’1�4·KXÉ<Ûq <3»ØÅ›;¬^cY3¸åéPEßVGpœ[A ×X€;¯¼�Ö/3¤Ýeå—è¬çbÎH™¥Øuó~­z¯Ûÿ¾cðbJPÆØ’7ﮕLÇKvR£OÛ1pv2ÝÜÅ¢|ʺÀ5Í«¤�ö‹»rÄ–LØÅ*—}¹yÈ]È(ï‡�ÿª_39iE½$܃S!¦õëCòü ¼íSVÖã |ò“>1Ýw´9ÔÊ¢+~fhDá&–ÿÔh5³ô½ÉŽØ…}¿Ƥ%Œ>ÜVLsàÆF¼kãt)“@Zâˆe¯ÎQPštã,ü¿Xÿï@»\TI:¦¹é¬}UÃa¨Ga¡„úoü´¾˜¶s<&Ãí‚ÙŒÉ3ì(t!xn‹à�gÎ��%õˆã éôóžr Ü~7ýøzúñ+~-¦Ó±€®Œ� 8T]»hF iFãÙ&I‚Ò’qa«#`Æ$°±tº™,ol²ÍáqOªÒÁµ‡Gb‡å½)àT:IÀŽvAð€¬>Â!¨ý€Ï{?À :4Kf 'û-¤ð¨¯uN«±<]”~¼Ô˜µØÊ–õ£"d:Î +ñƒt­{83W¢uC™r<*ø¥À–ä¹n¸gœ¸¢“Ã’ÏJ»¼gZµ$>{u2äâM¢Yz¦’u­#¹_rÃ~ÝQn9¸³°3-ß²ºzàè=ë)FÈ8òÁc|kÙÖo[rØA-ÏS{û¾’��?.u.v™A·X{)f³ÒÚk».˜ò¸CÕ"õpij�ÂÑ:…vhø”÷f³xÕ w3ÂíòaYÀY# 8cTHÙ¥�±´1¦7YY“œ©^4sR‘ ŽÙT 2½+®=L ?â€%ˆ¦C#Fú; · ï%˜�r­nU»Šl´Ê‡`Ýñ—¤p<Ò�¬yu?/ „)ñdbг|.ˆµ*4 (MÏYйÈÏσC áÆòEÙÊöâ«þ¬¬íÎÙDÇF +Ü'‘Ý/Õtë•ýY?…‡ø€'ÌJž°P’ +Ùä ÞX³ÐI§0�hÎìyoWÌCQ�Õ,M¤Bƒ&C�9b9d–7Â''AÑŽN_^àH™dA'•mÊ«SH³êjŽß+ŠeirIsiù+yRv6ðáÚv…ØQ8‚‡šÈÜ™vìE>*ù·WÚP–ä”îýùœ•q}ÊÀݲM~8˜}QÚ:ï€]ÒÚ!�ÎP¸|ÖÏBÊ"¤Ì nw5V|Ïÿ¨ö±ÃKšše)§÷ 4hІrêÐVߘt,E¬}Ê«^&Ã~¦¯*ÖØ8°VÛþÇr‡ó™²1â_-E˜›ñ±-„Ù6# +@hI’$¯t(ëÏ'” ô,z� ¸„;cE¶Ò/i7Lß9Yôü–àoÎØCÉø“�vJÕ&�Ö1Î/¥†NžiWBŒk/øÎy Ñ`R<Ì[¯|ô&]<éyrPÅhkY‚å¤ga 8Ü`tR!Ùh–0âì·zÚ²Ö…/·fÂ:vÌÁÊ?°Û¢ èB´'ôŠ_*y=�Ú#†ƒv0ƒ*¤ÉL¦‚ñœ€£>NeLðàåíI©GRœ3ʇœüGáÔÛsÕƒ3Ò½ +êkE&¡æ•¨°­|LqC.tW>¤(ï£6ÕBlN˜J íD~¼=w•é‡ã§Q´¨ž·KVÑA�Ò}É«®¤w°1§—9Ýëw @}·äh D'ú.9ñ80íf(;œŒÛ\-’çnm);¶â�w/‡P{æÌ»ž¤Ë’’®îJT>™-ËÎ1Ö[7AÖ*ùlkð¤Æ�„÷à(}=<º’;‚�€¨Hµ9íOa1d&"Ì»ä:“N(j•P Ó1S•…D-+¸úN&GèåX\4SP©(Ay SVáùKߨ@0ü†]UïOƒ²8aAú1\»™Á'á2 B5“µ(îflà“¦Ûìi`3¯µoypœ$\²U>ù¸Z‹ƒ·ñk�™y€aÛ)'}v~®³êr… BNÎô0û%©Ów£®¶ð‹Ã†—qQŬ³ÛŽõá+ÛgK Äu“WKx�ên©éÇÕvb´{oÛj�ß +)Úý#pLµ¨ãì�§—Xz—37ΨRJ‰5à øÚˆ&õ Xà†›ŸØ$%Xã”�Å®~›å»šöÄ–j·FkŠ_¾o[^2ó ŽÍ]ú%Ÿa¹Ʊ²L¸–Gf½/€M(hÜM×làxT,ÎH]cW+gHQ}…w~È–—`>�«¼®Âò9ìB;=$Öí)9«v�ÒHg¤·$ì–œnAG›ìˆYL FQÿPÍ[€Krw™R”M6­O Øöráá»=Uëuª—î}€~ÈÝk§Ê™öX›ôÚ¤È<­kJÌã鯰’60£_èJ1=SlWFÈ,@9‚Â(t”ó‹Ö¿ÄØžGå +I Ö±®Æù2�aÙæå.Ü› ãsJ |w d³¦yRV +×qE„.ÔñÉÿN’‰lrP6E»¥0~ç'äý¸ü~f*©=FÔv'ÿ|ÅÌ�ýœËfXrôßñ“Ì`¼¡ª )óáÁ†l1(ŸœMkãƒs©xÛÚ§×tµööÔ—Ô„AUr±Ú@;ô,£Êz›Ü¡˜n÷Ö1*Z7ÓŽ¸ÒCéœ} ¢nȈ¦†Æ[ÉD�lí”Ñ® Ï-%ï6y/e°uVÑ¥‹PíÀFÄÍ€áåü²-ô›­âO@Gì¡p“ŠƒùÈtÄ–·›B¿%Çít|‹ˆyÍãDž‰Š†]uиŸÚ,€6f!0ò,âr6#¿®0z3pM'˜dƒ™dóF�>ÝW8þ³ô.Ž FùÓê㿹q3=´V +(?¢Eô}Å+<@SN¥ÄMç4»®”Ïõn‰{9*¬I¸4Oj5¸�qXPwëõþæõúBr*…’‹�ËÖ°‚˜¢G£Ô�~:é¥ò.™Hz^óƒÙ±ëA‹+DQá%Õ ëø1¹ë¸#´è )@0ÀÀqÇq�·8Æa(·êA€M¨Ö\¢0ð÷€üÊv'÷ÀCÇ~GêEþ#ê¦óhãe€T;ÓX§|v›j]œ+­¦÷ì³)Ùúå·¥a[&Õ{«‡’µpD´ß Wõ©EvøA%% ´}d,@ªÙpî8^eáJ2ò|D¼–U¬ÊÉÆ<ÂGœ.w° Xí–IªØR6qï~ZÏO‹í~79ÒØ´âbÍÏJ˜Ç:+ë’±Ù«$kti�Ýv'…Ò+I–m6#¡ 8(¤pcæàòŽ”>»,{=™Eé°-Ü�°Þ˜-R†�ÑEù<=Êó±jÈjzh2�IM¼0†¥lÊn¨ùÑUài®t�ì£Þ°ÝhŠ^×�ÒLkäÈØF¶Ÿ³´&M"wÔSBErî€H}[‰äsôV†ú ‹–Ëóï‰ë룛¾ÚÒ TfŒµç\#œ{ý,ì 5ýîn—"¹´JP¾è”××@Ñ ï dnY ²ÀWYl8“rí-„å­¶W1£�_ýïQ endstream endobj -266 0 obj -<> +273 0 obj +<> stream -xœÅ]Y“9~÷¯è™õ®=ŒGÖ},‹�õ.°<ø�åo0DÁÿÿ ª»K-åUªª¶y™£[G*•Je~™’^ÿùß{úæ›×|ûÃwýæÍ·ß½}öŸƒ9èƒ><˜C´ÊEku<¤X”÷ÎÅÃOÿzý“>üô߃>ü÷§§gß¾;èû¯õÁx•ï/Õ§_ïþõ——?j­|º+ñô—Öáü;?žþ³Ó'úGmŽŸ~y.’Ž¿ßw}×Ìé;mÍù÷©Q­}÷íÜ¥kKÙ¨íùKÛUÕµ+H�í:Hb¸ûë»ß?ûþݳ?=ûþ�o_·“a¤ÉZc²g'ÃŒV��Œ_vt�¨þxš¥žb�î\VÞæ’çÙ3®å€P²oëC÷™ïÚûs¶¡¯òÐõÓ¬�-ÍåÒF2÷öÔRr®]ÿ»³ùXúf®r÷pþDnû,;}«dÉ*7ø»Y[:g‰½ô>·ÍöqÏ ¤EéœWÞFëÒ²ò¼rÌœ'u&|fÊYಛ¬¶s¹ãï[~0¦eŒ-yÿêÚ(t,±ë­VÞDŸ®ÀyÀ³3‘éîaÒø)ëÇ4/¬N“^„ЍÊM.?䀇\¬rÙ—kL¹ -gò¡Î>®¡Wý˜É Jf4JÊÝEå³+›‡‡Ôù ¼êSVÖã zò‚Œ>1Õ`Z#VE7|Ï QÄò_Í›@£|ï²#a_ï=5Ø2$FáIfÉ�Ër�^ÿáoOÿxù÷§;$6¥K™ôÑ’@èEy?«I“ŸÅúÙiºßß=ä¢JÒ1½ìG2o½Õ†Ò�mõÈ�3cukü4¼˜öË;ž„ûNÝÀM�#Ï£P…ØÝ¹‚žåÖÍ“Ðé`¢‰w ³yE¹Y˜~¼™~ü‚‹é ,`)WEÈ.'h3ºvÐp�a‚Y©)’–´Vùœ\Ú!6®eä<#—)ŸÜol²Ä”í,^槪×n‰mé ÃS0›9@Œªøq>pƒ¬- -Â!©½üCuŠû=+à N>¡4†‹ó–SÒ"?ßZkåéªóÇ+�Ù‚­ò7ÿÝ‚™Žó@üà¼Ö%—%&Ž Sç)ÕöÏ?¸½²„|¬ îÃøvkD„Cgå‹ÞeW¶ãûHÛ•h–ζdÈÅ›DËô€‚ ‹Y+_RŽ;PØsà Q;úÑͺŒZ• �óKZt¶¶ -uIýæƒ4`ý['²¾ÈÏû ãÐ9ñ½³D7zËÕ›œ�{‚¸¬Ô>ñœ©§€žXeCî6*�£5�™¾ê€�Øf]}¨BB@³ý@ž†™ d”#öž—è›å9– øÄ·Ù2jXTFPx…’$…£:öº]¡4Ht°*¦h|"ƒ”Ôû* AKq�L5&«ä]0ƒ”wù75:ü«éǯ§B˜Æ`ˆÎx¯´-Ñ]ƒá˜ÑÄ@…À6‹}“´r.¿›mGep48¾­JímåçÑÌ)AYÝi7}+Љ=@«‹š òt –ެ#‹}#k‚Ê¡˜¸›WÇ™ûYõ&Jýì‚^üL »76Då̵™¸ó±EñW2ð9ƒ€Ð*85œ/hJPÀê~òFZ­×îžÞvëæìY+‹$†Ùr »Èñ�]T÷„ä솰4qÇ•K©è>.²—ö*U²e»ñû%‚b±©Ÿî¢U:««‰p•^Ä!Žé -øTð†!’MdèšBVÊK©:e�‡¡ÃÀ?öÎÛZg£Ëœ‹lf8(H+R:½¾¯Ú$t ¯ø­ °‡1c‘V^ªålQH cQO $Z8À2d à…ƒ“F½VIk£�ŠÕ,È2Dц~úì ¹Ô^Š 28ø8  wRšÉ ,'0¡»dÇSìA¡Zd†ô�àƒe0K�´ Ó€Þà,žõvô0Ø,ÒD64(2ž#†C&z#~r­(a÷åO‘Hùd¡è ”ßl},&ÔÁœ¿¯–•É5� ´Ü6Ф 5ð1Ûv„&áCÍe‡9îL9ö(•Ü[ møë¬^V´û<^ñ ÙÁg3øÑ‰l9ªl|ðW˜žÑÇ«oúò‰4ïœ-W˜”‹Â÷/e¨ø”+:n6î·¼iqGðÓ]œNøyKCO‹i—mõˆÃB�µsß9µ3¡¨+6æ M ‘µ+ôÆe� ŽÙn§n¹n!g¸L8"!ïÿ5Çë/" "bå’r%mG¬6„3#^Aô¨u<Ø~§u5Cë-¶½IñüÝì Å. ÝÉØ—¶Sn$¼¬ˆÏ#ÝÄÙû·\V�$ò@ -Œ”"t.'•’ö›íè~;=Þ=á›ã¶pýªÎOºñLIv§G}Œ^2IãoàA[Ç4p¿­»uÇè$Õ„«N‹Q¶¤œiñ®ÓËjˆÁ¾¬-Eyãý~YÞ7ÍWU|MLÓÛª[† ‰Zâ™�Í„@ä ZJÇ åÜš -í·“=3àÔé$šKN¥äÊfç²Ã©r1øÆÉnLpQ¢z(WZÈXÄÈ7$‚à9, -=,H¤qIÅͺ\­NÍYÅhƒHL[m ’ÏÅO"Û�a×pfðø‡FNxo=®#Žœ»Y,„=úœé.U^cH0  E¥”üfÓùû3GÏÑD•BJg¬÷'É´ñǾpÕë¿þ‰Øë±Á’àž�v’˜ 5QØ[ƒBÌŠæèüOTØÕܶŒÒš@C„«öž¡+ÌŸãõg�Ûð)Ž‘§pè#-Ÿ:ðË–ÅßµØ@¾ñiOf<yh"z*Ñ�Pq�κ9ÔôüÆ’{çJ¤2bw - ç�Ì‘2@­;f=’v/‡3x1Âi¬W:G[®ÂÈÅÔg�6Œ·Ÿ•ÖÁífŸí0‚ô,UÄ€ŠINÙb¼»"»Ýirï#%�J@Z°û.Nœ0ΆÆd J¨€Nß pVQ3½`Óv8k>É<ãI�€ êšiÞçÑv -µ{¼ {mˆ…LîþE5æÚ¥sï�—wMzðË™»)“²”+> -€7¢È¼ñ@Ln~¯N˜  L�-Q™ìæ;J~_S¤Ø›Ï­QÆšâ—asXòšYb°mîø,ùªÉ­ÐŽ•uÂ�0<2y|�l Díî:²Û£®�=R'±ØÑÊ©TT]áÙ²äûk“dµîÆâ5âBÃ’èŽeªJ-­È¶‰¡œr‘£MvD�,fW÷¨’º[ K¾l¶Ê䜶gí{ðô½D=uuêtý¸÷i€ú!àת�ƒ=ßóy½Sä¨Ö1%¦‰ñTYXi˜/T¥„ž¹»VhFÈ{@É„B+tHöE‹41^èÎV¹‹™˜ï…®núò<Ãäúå*Ü ã}J %|u`dצy¢^¹N¶Š ]¸cä¨J”œe³2ÅÚ=Íw0 �èò뙹’ìŒQË� ðé³<ö pàͰæè¿Çïƒö†.@Hš6Óæ³r¹ØÍ¡ÂùêuÛú—¿k‚[{é¥@5�#h£J.Vûj‡Nqùé—M.µÉŸ@‘Â\IêÆ€®ÊæìKWpŒXj¨áé’D\9­�2Ú•æ¹¥SX†=…•ˆ ¥uVÑ¥«ÌÚIŒðÈáåÄ´=ó7{ÅŸa‰,þÉÄŠÁ|âyÄž·›‚ÀÓõª»çñ[4™·<¯ALì#q7`wÑ -¨à§6 �^Œ<38�ÉŽ+ &.C©é“ì0“bޘї Q¶ÿ$½3c�W®X5?h9=[V -¸m}ÄŠ&æ÷Û¬úE9“�sîº[qnx‹B“£ÒÁš4ÀÛA‡ðbVƒã!§åž!s¡Ù?´ž�°Kh]TÑzï÷ˆ$}L¼¿Ò«ü¾�¥{ii1 pš42Fd{õÕï×>ª:(…DÁ±kÐáèÐýb]Àÿ@ÙÂP×C~™–ñüQD‰¨~±ÅÆ‹¯èÙX­\‰Ûñæíö”J.BV[# -bn?l�2wú¿{ºd çó–oÌŽ�'Z!Š/™ö¨x%“ôŽ+B�Þ� - €;Nh¾Å1 CYÐbB•æ’†Þ2-Û•Ü�ýnª …) ªÈ6VdéJ«£r¥ìA5×*«éuølJ¶~ù©fX–IuåÞ¼¡T-l-7âΊ¾N½¨†oT²Á@ÙGÆ¤Š §‘ãQvnárC^Œˆ‡§ŠU9Ù˜Ĉ³äŽt|Ǻm™ðûKRÅ–²Gv�½~Í÷Š�~7¡ i¨Wq¨ßó�®±Îʺdì5Ö))�/ZöÝ&A¦Lâ˸(qm"a8¨Ÿqcžà -Õ Ûöž]Ö;„‰Ì²tØ î[ØîÇf)¹À«¼v;`ì¥×²šW d¾@j‚a)w²kj~¿€ÌuÞ#Gû86,7š§×Õ£ŒÒ4úµÑëk†ÖäêC掂$ô¤H¸¨�,·�L^c²2‚ð;2K{^¼rÿÇÉýzúñMýëEý‹ŸeöíU»æ<�ëõ½¼g_yé_B@\²„f™”•×1mO ¨çç… ²¶¬DƒrRÑgç(N¥Üzayq€ÅÇݪ!¯r ^™�UÔNNÕ™qGF© +„xU&žnÕZY¦xÕ2�cñ*«ŒÑ¡œ‚¹¯[ηÅ:®4q’F÷‰“ }§ü  »Û5ŸçNËÔ\0UDðC�ÖR{1vj–sŸ O¦üÖ•hUIüXz9›¬3Œ Š3!¥põ#–¤«ÍyŠ÷úœŠÞqs‰$l¨rŸ´Æ"‘ÁáýV¸¶ªHðÁôšsÔÓs‰[õ€éç”5áb¯¯a"¬¼M(`+RÀ„íq9¿ -×ÝúÜ[‘ð%ñ¾ÕÎöOe ‹Æ=*è¾æÔ°}çE/Œ§6µu EèXJ~½6\ÊÐÊ9Ìnð¬s‘®2N«hôvØâWÌKЮ™…»…£ò&[3šy�{X¶©öø#ì¥;)³›�‰eMS -±Äbè½-À¤xUÊûEýÈuSø à -÷ŒcÔhgäJBˆaBç£ -Á&7 „‹N�m�žûjA5æoªù­@ �(椴™Îjí^%0 Ù±záÊ ~b…g¡Ð•C�ß«„s ›áÞ¨c"~8yé8•1QEã÷ä…òï7š¤¼7Ñ®Cž3 übtgt, ùÐD…îŒ8h‹<íib0ÒiµUA[í&F^î/*Ötú!�AÜc§g¦u!cÍ�®€…t\dœ!ÐÏr7^N‡ÒÆ`•·3LA!¥°/U£‚�Æî†ÞQžC"Ýùá¾Èe �N›ô‹¡žSž{(8åÈ›¤lšŠÙ-U¯¸™@Ú½ûš4�Ì.žÞ®*Mü�o`Éç™/%ÌmU4i;F9`É�ýíäUŽÚ›-™š±!‘€MúìUI>§ý<8oÔE9r} -€2>@‘•¹g ú†”™¶�{ù.ê ú®>™•DRØiB*/ ­%ܮѕûagý1ÕªPQa«§n?û<€‘ö�Î…©’0tÂ6mâ} ´øx•bð¹…Öe-$]å9ÝÑaÍžc«WãdV…ëKlB‚ ,*ÝÄËraj"”ÀRDP@Gz4k¬ÇÆ7¸Î�bèçž�â»dœçd!8=VXuMHžè—Íñऄ{W†� °žS¯�ÚAUGO×-„åìeÿØÑ{«mþޯΒ +xœ½=k�7rßý+FkYÑz%ŠïÇ�ÏòKñYg; ¢oq>œŒ(@€\tûÿôÌt«XUdw�»ò6Åb±Xo¾ú÷¿ÿõøÕW¯~ùþ§úÕÏ=þ÷óÿ:Þýõw?|ÿÙÿÌAôá¥9D«\´VÇCJV9ëãá÷¿½ú]~ÿÇAþñûñ³ïÞôáÝÇWôÁhï>\{O¿Þýí?žÿ¦µþíþôS[sþíüù·Ž—ßáôûùý¾{ûÙ›wŸýÛgo~ùþU ¦i 3Z+kƒÕ¾žé€§uºé­2F‡O{uù`§ßÏ.`;®õoZ»ºCµÄùÿ/¿ ;ÆÃôãz?Þ¿´ù2�³÷—ÿÓå©Í<›�sç'ܶó‡ËöæZú:_-ð²`mx0m¬°{épVeêçÎ ">ÜÜž°£ó޹à:÷x¬ÿ&îÄŒ†È¢ŽL�‰Y ÄÃyk^ “¨g(l¨³P µH`\i<°“ +Y9›õv6pþqÙ¨�Wà�sÊš`ýâÎÛh�ÂáOœÑ@p ±OMß¹M Ù#\þù÷�$…›co—s½ð 9ô#øë0i<€µ÷¹d3ÀB77„PÍü«¾‘<æÈð Çõîlg!¡ +13ÖñŒÚéë¿äae8ûyŸ.ÝYöà$öà½rο•=8´§3°LcÛ­IQy“­A˜°‰–ðÞטCC™ÈÏRß uw0Ýv9.s׈ðÁ¯Ñ0nð9�Èrx¦?pÓ|¼—éwx ®QÈœVaú4èt>ªlr4hYyAP�‘aõú³…_þ¸ð�?óð…¾œ”6:¸ýgäÄUîD#ζp t52Z³Ãp_ ’Åç“èjÒl¨]`çßÜÂ+^|•çà®ç…ݳ(ñ5§•sÁìP~£¨o¦\T‰e^Åûf ˜aaF øvôRt,„bôˆÄÔ¡f�x¬HmM„mIͶX�”NÆl‹|ÒO úéúƒ"·@ؤœÖ&Ý€6jù¢ïH’1–ØûíD£tÔ5žFçOèœR»ß—A Ø�@MöXwýCsØq$š™†<%”†¼ *»PöR#ÔÐ/¸µ3ß&”øëvÕÇù,Ú…]Ý®&RÉñ“Òus¹p´Š?‘âK»ïüŠ�ÄåMTÎå°ÇÆE"ÛEı•–pÙ½JÞ&—0Ðå +4 +Ôç2õ{¾<¾ó@[‚=ÞÓ+€T{¸O³BË2¾cm~k»> +üëÈOذ/NãÂýÖ°+ {³ÒGã¨Ï�¢#BÎ {†•@h† !ÿœ²³ð[ûл^`óo Xó©Zì�é46[Þ(Â3ÑB¦­r~²˜od"²«æ…m@†¥§ ´K¡¤ †¶Î´×4Ã"lwhÄßÁÕX÷ Rz4PÀ#ž¡=ˆ"¯ü£ÑzŠ.¿°Ë؈#¡VÈÔ´±ÜòI…ŒÆ=VÌÎÈÑëõ؇ ù„Y”gèKæ³ @âõJwim—ôÎÐ&„î¤zVžƒHF´˜³r~‡òž°ÙV,Úf•MÐÅ7ƒýWmã�Ì­Í™A‰éúÒî�ÙPm´Àm›»É +m�QäNhȪ °åÏ]¸DÓÕóÇbj­a6GU\È¡OL]cØeíFÒ#Z{—-Ié Ý~j·n€)c#ñdÇ\ˉb!x mùìåÛpèŸÇÈ�õØ„ÛvcŒÀ+zx„žÜ!mÉ(“WΗ¾HZ÷ÑÊåâõ?öÆ·ð£>6@m|B+d«@™=û"9šˆ0«.§§m>rmêl×1!dÃÕ§� JílKÀÀÖ\õSH9Tx + �^fäˆ{Jñ®Söj=·½ŒFqÜF†õ:YÅ©ö‚çBIâBQ+ìvwN寸$å©•õ©ØÐ5Æâ–�Kt”‚0¦Ì`#ÿ�ïPx—_Í‘QëˆYz×QÅ9y‚ üÑ+gÊ$ðt B¹N·f_¾Þã‰Nâ1­¡Ú–¢’)»Hö¡¿÷?LèPkPvÚOöÛx¼|ƒ°åŠ™Z“¯sZÙ’ßzáUÛœ"D¦iÃzÙ²û^l|˜çr 1KÖnŠú#Ï5†iòtóßTGÔ㈤!|„Ûº‘ ÂJÁè£r!î÷wíÞ—…då]0�ñݼ(ž’(Ð9ú Ž +ˆ@wÓdô*ç†X}Ó‚ù?Š´·ikúš»nÀy +ûrg^ÞaË$ù�Jñ¸ÒÆ�) g‘A¨ÕL{5¼,i@åµ¢iÐYåBÙeMAB ˆ•ÊØìÖýÁßW-w•Iþ)ÓoUTà�EC´øW.IÚùAVB=qç5²˜nu­!¶/w²èhÁ›Ê6 Çqö°Ií|ÊW†%‘äËTóžæ–b¥]þ +øÜT‘è½tèMV.ºíÅ•áÜ©> b˜ñ‘£‹‘Ã^sRÂï¹\@ø|¢éž +X #yW¡d¢Ö7H¼ºé,–ügº�½ì+Éô«�€qÈŠn&UÌ¥+{ÎxAQðpÆ4£`17ÀÀ†c!âµ,?h¬ò:Ä2€ÖžwdaÀ“á{òxLƧӷ·Ü‡ŠÄ©oFøøoóY¢¾Íl¿}Å}(ÜÇ}øšûðšûðîÃ]eDd¾J‹ºëmÍ]ÕY §Öôã�SAë|“c:b~²D¢ÕJ'çÝnšþ’ÊHœQuŽˆG‡g>üìª$Í™œR y¨UŠÚÄÿ/4ºÖ0äsRÎÙ4C×q:³+áÔÎmæßR�­"ج¬CÜHÂÁ N%í%d¯Bt{.1.µÈ#Hðv¾dëžw£á°—„ð.ÀÑ„kǵ�™ŒŽÉ�à¡{ëTä’�*ELjUVüéó÷?°C-±ÇøÓ·ÂºÛH“‹r>š°{ÿ×Ða+LY­•³Ö¹íø¿ØXó·£’‚r©„=«ïÝá�0ZE;4«¼ÖIêgç%\ &¨˜cÊ·8ëÔé½�>ÜÚ¶øL³ö¢²±¨lM´ûr-N¡Ó7;y¨ƒ™øãoùO†ùô³°zÂw2ÅwŸn°Ã qîôó±äí·£ Kpø/îóLQUßÛý‰£˜^)n3Zá©p,V]‹# /y4BšÔÒ´'3¤ŸtA ú7 ¤Ë�Gq„A«ð³Êû’q•ˆ¯Å.„°Û$±:v`l5BÓŽm›ŒXC g¥6ƒs˜a�Ö™c ½0ñ+]å΂�GìQ)Háó¤°#x¼_Å€œ«r�ɦhÛ‹ñ«Gçô6Ñ*Ï&Dq?D’Þá¬@+o^ºƒÊÁÇ‹p4Ù³x€k-ÌQÛi±eS›Ž'¸ºˆP2Ô¸õÙõÓ?Ã9ýtþ!-Ï,d¶ÜYÒÅÁËS¼ç¹9ÿ{6ZåQ +öè׌Ž4°Àà +q�¨<�’ʦø‚ïÚ 4²³ Î2 þ~VÕj»Ù…Å´ÊšwYÍ N/Á¡š£¬¿lzELÈPßÌŠæ³8†ˆBŠRÞª�üa)òNkèk CR•, &5'E”;Y9Qƒ®måÉU쮓ÓÐ(ãË…é;x˜ùˆ`)ÍË9;pœ2RùŸ)�ßmÂÆqÒûЉÅjÐAÇÀà�#³ÎðMO~ƒ—-6-ÞL?ôòãÅ`Õ!ßšV|ð*¦h}ÿŒuŒÚ²FOØûCQÉ9‹³ÍÓãJoôM·—”ž4²Ä…>r`}‘xžÍ*¤t3Áo!&.`¹¢þE´[!ä/ Á«æ@M+àNMØqïÔ0GÛ]OgC¨24TW4è¬Rò!möoïQ¥Å/z¾ìÐÚ�r˜ê%í:6S¯qÆ‚J¢�ÄQЧI�°•âT9­a¯‡q~ÚNÈäMö®¹B˜Ízˆd0ª!dðBæ½`zýÈ/º£’õ²hñxMMÆVæC]PÖ*b�ì ÿ„ ßÓʈD6„v»“Õ¶ÞñclÓ«Œ�pBꢂµy„ ɺÑKø/ÀÑ%‚õ*> ï¹î’ßå‹W)e�7¢Ã{"<"«àrΫI8ó´S:”äGÀî ²N *å`,g£Ú¬‰BÅ}Ų®ÌT4YéyÎ+c‚IŽ®DÈD]Q*éa4æè/ápèYèjL�£©¸wæe”>`m—ægQmWF< 1RtȯME“ ÊÍò…øb"î¡Y#=8¼LEòð“p“¯´-nà\Þ¢`¤tp¯ŒwÉïg 2^±¿2$@-jå&«’‹Þu-b7)8•¶+%ûÍe�à�m…5 ñC\åš:r‘*ªî-“òSf®Ù€‰Ý)ó¡–Ée�CõŒywfþQ'äÈ£e“#æÚà�ò9yöpV\†u9—W&H°!9bÿ–AÚ•ë»ÙK‡Ü¦ÏÚó tû]«œ> +�ŒhéøO¬Š aëñG~Jèl0*”’QD\KÀŒ³£ŽsÃc5‡�Š’ º¡0ª ¼ÀpÝe$õ̯ïG½Ñâp@±½)‰¶ó…8Tv¼ã ’'¦–-1nðµ€Æ(CzÏêi…¢Ô{w ïKê +!*¨ðk*ËMGQ\æÎ-1󙤇D\Ѫ”¸+�™v†œ–mF¶mP]¬§Ø×K¼×—cSP­êNƣ͙žîCh*¶8*,Uƒ�ê…4¿ŠÔñ§ªŠ‚Ñ@!0"öÍ�ˆ=4^IÄíFÑÑ4ä‰À·ç²6|ÚáÌÊr,Gf$`²Ê:„G«SÎÊÈŸ¯bo—tÚ¥t8—¢*¥ìRj8˜Ð>rê8¬¤ÓÆŽòûYpT ã17E `³ùW4ô "++©Ä5ž@t<$ž�ÛFu‹§NS*�Æòùïliô¡ +h ºû¼ I™Ãfû<ò÷-I(á²ÿš|"J è¤RpÉ €92åvØty¬e¬ACÎE<Òô¤øì@hB"b©ÊT"z?€�á'Kçú}'ÀCH˜®ƒ‹Ÿfw˜sd=ˆkÒj"£Ã{ueù�´þ¸–6ˆ–8– +&Cc“` +³C® +¤RÒ™| ¨eĆI/`ÄEöÛša çÃö¨Õ«ÈŸ©²»óNY­w˜ýZûЈaö!J Ÿi7IS +#64’|â»b9Ž®‰j¹¤GàL”±:p83BäÇdä!¾Ë Þ?òJZ7ÆÜŠˆ¦3 üg+ý:ekÑ$ ×J„®á@tâMV´1�ù›ßö‘[{E‘ ”¥Óo‹²Úm·ú5‘ýGÆíŒÒ>è„Ë.VLtY3†h™Â³€—ð7š€„ƒOrW~æ÷Œ(:ä¬ÊÆè4°gÝðIdׯè¹åÜÂ:„�µ1DZWNTÛ¥†…·L<³àœ*!܆n… ž™B-æGÖàf(œ§ÏNx1(5N/+ }Ø<>¦åûÕG‡hIæ¨Ö>¾Ê®@ ¢uÒeõŽò=ã÷`kPÉYÙ0ý×pT§y1j Y ¹�84S�O—ã Pw¢ŸUò¾¸‘‡¨`Û¸�5<$ƒ‰îV˜~‹øÙìØæ�¢ÊZUÜ”4üi�¼ê5@'Œƒ/- ÷„’í¢ +Ö¤ý¸‡‰^(h°Ï~¶öVÔêKN[ec¸Éáá ޡѽ y®’9ùv•6OÓmÏÒ7‹õ™lµB¶f(¯•È Á=q[SQeŒ¡ü¡×ëML*ìQÄŽ0a�ð0QP×FY£·›ßÉ×�*:¤¸Ä)c=*ž²רXhJñyB ¯iPÍÛøòn1dCl/+]ô\½óúKÊNúQj'l �iKI‡BÕÈÒÊ•�Ýî-"1Do’7¨5®¬V9¸è?É® +oJâ�Ÿ©‘)¡ìFYÞÈøé䇈òV™oä„Ó>zeb(v?_°äÙhàøzížNsæ�eAMÇÂ{G�;¶kì.` ,ÿ‘»᜵`Ž\P<Ûè‰jì≪dÒ¶ñ±”j´¨­;£¬ÍºìpqÉ2§@«JôQŽ5ì¸ñ@ÜøÒÑ÷SO¿˜ä‰6§Ÿÿrý牔Î�ý×?’ccu”ôì�>Â;+hl,¨3BvSe�ÔÀ�’_¡Ô^†ZHÖ~rOY…b‘†¡\(lð¼÷¨^6¡Ãeš^m”3ZT¬MRÖ™==ƒ–W×dÀ¬¨°µ¯öcïÚsB«‘—æÂYB`¨öR™fn�ÁP­ôÖx†¨ .wè9ók$60ÄQ0²Âw­ +ÓîHwI yO¿ÿyI|É�ü!£íH‘)Iy›CÙ^à˺ª`<|¹æýýK­¬×Sa8�¿¿`an�*Ih{-v1TµcUÉë½T5Ç ©“fžïÑeØ–½d(£[ÅÚê¢L(© à|H‘ÐÊêâ½5—e<¿MR\;ðµ¼Iÿw|ÏKJO®¨H•ÊB£Ônpˆòx~¥C‚]+Η—IÆþTa€Íõ֎ݱ¯¡v†Ñ’Mf*í�ÝnðÍt„Á™v¡¯O©dMJK%|IŠÂmé’à‘ÊW '>ýøšl¤„�øŠ·â²á|ä[ÂëæÀ5|X=®/K6ø¯éÖè~”{~âž°›1Ø|d[42ìa#I À‰¨–-jˆÌhl&qV*˜et�N},Ê»°Ý¦óù¨A>&e¢�È=�L!´6‰ºRîÜçZœóe£8ׯóÉ™ \ˆ õz@*БAB#?ÃÏ{xTaéµö`�¦o™¿Sìô®·3Ü%M –ÑOjõu|MïäòLà9B¦+ðD­FµCÝÉ7TˆºÂÆXš�ÑRµP‚ò®ì°©õ^÷™BxJHúZa²^QÓ€¿Çá8tlXÕëÎMÐ-uÄž2£½fþ>˜(…3bycˆ_Õ’¸Ö&ìn¨,:Þ($ÄòAÅŒ(�†cù¥» %È] �̇*Rý:]5VH ÅÇ¢ÊDÑ-åÔo”÷v‡e a�W>¥‹ê;’T¯Ä“¬ðšiOБ¡gšlݧ˜í´µÞ=ÝTèЄ´Ý¼@ˆÑ­ÓnRæ¢Í:Ý`Œö_,GÀ¡Û´ ¹�ÄžDØN�î1h£¡Ó°ß‡� +«­hƒçÆ×5Sc~Õž XìF¸E1n`à/†Ž|—8l +ìFnSiׯí—8ãO�‘ü‡Æ&å}ÔþExÓóýËh”qN ”BMšpPQˆ¤ä8`§`šHÖàÓ‘©†8b&Asla×p�/–ÿÚYʳõtÓú£ÜD az+O™P™ŽæØŽ„Z42Å)ìj£ÍòŽz?âFÂ÷ÎJ F8ÜDžb†|¡ l¦_U¡«ud\rå$£|Ô{žü®¹dðJg‘�®Ù”ÞcíP�|„fâ�`c–\hÏlp‚¤� “.ή�`–«Š“]Ù�¼ù‘+¨‡;l[[¸gSƒQ½ä–?nØ)úõÖe£êòzRêsƒ³ÍÌ.€�ÈwbÛÙÓ·\àŸo”XFTÕHë�)‡"—Á"žÿ›½zÜ endstream endobj -267 0 obj -<> +274 0 obj +<> stream -xœ½\Y�·~ׯ­${Ç«åòfS¶Cò!_‚è-ʃWÈ�A²ÖÿGÐ3M6YÉ9œ—™Ýéf±Š¬"«¾*òî¯ÿùm÷ÕWw¿¾ýñÛ�|ýúÍ·oŸüw£6r#7·jãµ0^ké7!haœW›�ÿ¾û(7ßÈÍïwOÞ¼ßÈÍûÇ»¹QR¸Íû‡µõüõþß»þ ¥ü �?|ëå[¦o=?_þ Û[¥„1“QÓ¾á7Ë»|«úÛØ’ -ùãgéÒè­^þ~Ø~Úî@†£ðyn¾ôµŠ©ØFGð' ^5œù�ÙBŠu„ Êi»Æoo‘,™€¿«>áÌ:ñÎÂî´°@Èô�ž;Žâ»ùãnþø¢ËØ®&fÒ7ѯS{`—ÕП ýYÛƒãuhªe6wåæö–m¿hîʯ‘H-wìþýýOO¾{ÿä/O¾ûõí]¹¨Öjà&a\tþ�Z>H‹ó÷¦~9é;²_ ás^<}÷Ëo»^ÿc·mÉi&áœçÅT1· ßj{ktš ôù Ô5Ï«A,*)…óJ÷9ìNÄ^£¬ˆÞë®+–ªÕ0YH^9(Í®é€9�†­ÏÁÒÛ§¡õ�åà†S‹ÆT+-¬t>öUo&a[Ê�Öå°½ÕAHg¦h÷Ï~äÊM=S�gŽ–¬ˆz–†?û’{0qXy¿æ¼æüÄ=¸ÊìÓ–PW½©¹ê uc±tH›¬2ÂI9]ÂD×µ�çÀc´2kÎÕç´©ºÒ¨Ó0iYaòeÔúÏcñ»i°“ÁKåÿOC8aŒþü%A§Eªa­é�ôÝz§5” âô$´uòü¡|9>žªPh+œ—òœ� :ˆµ·¼ÃޏuÂØ8isÝóö²ÇeQ®7Ì®–ÖÆ)9^(£ ÃâÒQ„sàW&âÕ4;ž¬n5‰Äv 6ðìÝTÏÊî>ëô€�l¥¥mCI!þÃX¨ñöõHqZO1¯ -ÅzŒp…A˜@W ^fî±Ó×: ŒºÂ»°GTS´HŸ£«<´Öòû}ôÂùpz"Žì.lo½“³>d8 žpú!À ¤ñ‚bØFݦæv°f @ÄË÷H W�(·êCé5õ›Œ§ÃH( ðA¡Qæƒç7ÑùúvŒ¿Y£ô÷@År]­) ¸÷5ïLbRÑè{8�hã—<øü¯• Y‚l¤oÈ‚#6;#Ò«óm—Xž�!T¸oÞµ¯ -éF¶ÑZç© -êôS­÷ å‡Ñ´–ÀI ä²'uª(¥++÷òÝ�OõÍÀ>º9g…S!¥žˆDcýBayº:Ý¥Z*ãâÖ›$“Lúh¶1݈ΠöŒp^¥P‰¡±ÝW™ç�|}ÇÇbk¥O ÙÌì·ÀW÷¶u[è"zãÍü!óÇËz7æ� £+6H¡'kl¬ƒrHÍ¢š@ûÃ|)§/aܼ ì: -7Ùùºç-¨9ƾµ�ùI¸`Ï( -9ðû´-ÔÊgZ»˜5í°jƒxŸõ‰B6fBC!æYý^» [°‡hJšWDCÕ=ͺŸ‘à - �»eÅÈ@%[tUÎw�!¤v`§]}¦ž•1p­4|ÉÃ{;‰”<=¿ÛÆ{ÑKºk sMNH%ƒ´ �X¹“B;eÔ¡2àh3½×mÀÖ¸¼ø å×ëV7ãë?îm[ ÆHÖ P®º–€ã,7O±’â^¬ušÈÆCᇢVlgݲé0ôêvDíjòHvüÐë»àÅ{:vâi© Œ9’Å´^ñ4N G  "u*£pZO#«P;–»ˆ¡jTü`Åi+|´îY{^õ‡Æ´ -¼±"ëì‰CSï2÷¸–CÍåÖåŽJ")�ÁLlw†²€ ½“œŠ`�„uSQ£Ú¢åÆÁDàåô©â1…o"ëey.9rCdhmÆ{¶v=£Ñ¯Œê¥…¤B½Û—Âü2ü:ˆù#IëË7Í:A#özo ŽxŒ×ÂÆÃùÊ â.0wkz,¹ŒåžWkßH2ÉÐ5SÁ¸éì ÿsÍF®Uâ'åXP’Фÿm—‚FPÁpI-úKYv�T]îÆ�c3BÓjFìÜy•_Pz S6b süàè5„ -!e.(yª¶¤H€Rö.üÁ�.*¥ØØŸkõKÿŸš…^’P®+ÂÎ*f(™¦Í\È�H@֞ƀǑ8ÑMA?Éprœ(¥Ú®•Ú)éå�­Ø¶Ø›±ó¹´Ïã@d¬ðÖÅ%ª-jNKW—‰¬š4(üüDc5(q•rði RÀuGo@–½PúSƒßáóàXÒ`žYÔ$äÙK/y^�B¶²B¬l…ŠˆZX<`. mQáJ‰IFõ|‡"wøuOD’d_žþªa|­HÅ…Ù÷WÎ�j~iq³c@£ƒ‡ÜG%½RN…ň›8a»(µ¦t3ZûðÃ@º&­XîŠAĺjåº*ŠªÃÝtŠ­Øq(·Râ›fA’æ’†Ìa—Ã÷«cÏôbY‘á¯è *‰,’‘&N—QR%¼aÉåh…ÔÑ Øe7Qž|óFeq”é¤Êš`Ï_Úã -ñ©: × oÓÚÖ‚æ¢átžËrÿ‘õJÁ -ã´H`òyÉByH•¦±ÕI<‰Õ«)3Ø@QS@æGù9Ó×O ^›Lº!&w¬µöÑÉ%ƨô[‘Ý"¼pXÀ!W°´öÜP¹âpÝ+ªs…1ÆßKcœƒÅ_3C¦ðHùP¿:à„æ‹­jd3ESº€XsôTÀny3®eüÖ‰¦Ó³Íš9“:ãN ãJs°3@gudÐBÆWÌÔU£H/RïÔÛWf÷-5,½~~äBÂÁºF}QÅýQ—À¡ìd½JFÚrJ­MU,‹Ë» ä¼îö5©ÀÐbù–ÚBˆûx™? \¥K×3ÒÏø„ü±øÆŠÑB�Q"Lút -Õ’5{d�CùB±±î‹ðL(‘Æ^²¤Ü_ËædÍEª×¶t"NÑÝ„xU¤V� - &èõªÊ&p;¢öH2žë(»C5è`µ­‹Ý�wÏ,´LNyÄŽ¡ÇGaC�ZY9}E¾] âÜÃ$-koAãN¦³"Ž%0�\,^ßã�+Øøi¯W€ -¬Ö‘^,ÀZ¦còžu. @¬d‡R_À:Z.<_> -Jß°gFùð;wü#Œ\ÉÒçí4ÎÛDœt#©×çAö(kƒS_Ë„¶Ðy\å¡dÁ™ ØÂçÃ$¼M�À þiÔÚV­Q}Í,CÕÛŠ¥².e4¬Òt+«Nn.±Ú­‘pýá×L�:;{¢üøž¼È­§®®âïx…©ÇDlY¨Á¢w8êUˆ<ë.ûýÑDNÅð:püí*­ev2"N^êSíU”\„y�‡k`�†Æ/åZ�«ÊW¬Š€}[Y饻œ±Ø©Ú%ÞÎ{.lgSpjhSðV¨É4‘nÆV›¢¶·>u¿½•B[9§«*Bz€ƒR¯YàeýÀ´ -<"-1i~Šæ v‹"“z‡S´�}€¼¼ìmpíZF¡\ q`ȇ68)´ŒÖjµHq}?^Ó…¤ö_ñ-h»àJP©O@�'€Õn…1¿²ÝãTœ¬g— aVªAàäüù®K{p3l ¡®u°Î:)ÔäÝÉ[�my×]æ«cדJ[ ËÑ¡ïCĬ¨µâÉÖB6�¢ÙS[S< ªsñØâIâL~EÿûÆX¨cît¥Î´×!Ú&t8ű(ç6'˜îÀ…ý+IÙH±:½¸*å!©khñ±«eàN¥Ž ÛàŽÍÉóKC+Kj�*Ji.{æ¶¶¿‘ûFö2x¡‚±~‘5ݨ‡ç³~¯¾–?/®¨œYL¨©¬]þ€}µïëEÅåÛìÚÞ±"WÌF† /@÷]œ4¥›´ƒ“m BÜ k£pRE}-§¦·¶=íΑ�kHA]Ÿëæë|Œ=GŠÃNÀÞ*á[ ç¬S”Êž\ñúÙð%›À5ñþJqÁŸÛVLcÌ$¢‘þ ˜‚º¹³Àaö@ -µŽ cÅ«Ùýe -å$«ÁëäÑÿ ž^„ +xœ­XKo1¾çW¸R* Žk{ƒJ}xô€È�rh#©+hóÿ…²±�õØ3qR.ëf;žç7ߨ;ûþç¾;?ŸÝ^}ºfâââòújô—I&˜`SɬâÚ*%,sNqm¬dËÇÙR°å3ìyÙ�.L°ÅÓl%˜ܰÅj·{³,œÝ !î„n¶«²ÕöïNÂwk/b¶«ÔÛU¸ÉT +Å­²FY¯GÈ~í‚6ÿÖoÄÖ¬lE7üî•Q”ÇÞ�VÏ×iVÂZRlxÿ}D“‰QÅý®1ªýtÒêbz´ŠåYQÁû¾ÚPKÿOXK ò‘S q v• eªå©W“:¤@HípSŒŠ‚R„IpCÄ"íÁ`øgì¾,�€Yÿöä€Ò 7ù¹ø<ºYŒ¾�nn¯fCn‘·˜–k37öxr!º±åfn�“½¤„ԧФ0™Ê¿Ë8,Wf#–öm�1¶ý´.’]Ú‘¶À±‘èéƒå›Çìe•wjÈËÁ"}Y³âù Ùæñ¥Ä)Ѿ·+uœ>¡ž“iEšò4CV""Z'hƒÖ:Üf-¬+Šxé½íóá0©C©×˜Ô›A— D?ú7 +§EÑ@ÓpmµhŽ¥�÷›Ç[Ð\­ãÆÌ[gèæJÅØ�øcÁžŠPî0%;ÊåX[ïï T�¥&4ÜåiŒìZ¸§„éÌàyÔ~ÇŽêdˆ°# Á1£‰Î=ÈjÉávC¾GÓU8]`²®`²×§¬XÉÙñ©^ON£õn‡6JO;£ä¡)òЂkk�>B˜HiS@ ¦å­›[GóG"u} q7YÜÒl¢�7jÜ’µ¼!NN*m˜@K±œ¸[&wËn�1æÅå($5dÝõ-q§15àIž–P%à¬[¨A6˜Aé}B7ÂíK¢þ§•¢¯k0ô.k`+ÅqU¹‰0,Ž5 © Éúè8Š&\UUõpEûÇRt&-׺}É•èª6\ +!CÌ\¡,>‹¹þŒ:ß<0£=Y™RÖüz·'šöüøôªÐúh ‡�ÒqY•LçÃɾï8Ñ[4Àò¢!]td©i™ÊB€,)‹5­ ~í¢úË;Þw¿Ï~u“¬Ñ#¹m[ÓT4šÚûí|‚ÔÄÌlsWœâÖ8QãJÍÐÄЪ’6F.½°àö`( ‘Ï)¶ŠëFó‹ÍÝÆGüUwóOòvðKX*žÂ[ˆ ÷ï€�vœÀNNëq’ó— +rÓ endstream endobj -268 0 obj +275 0 obj <> stream xœu�±JÃPFOŒµUªv¬DœD@¤`]\Ú @@ -1078,7 +1103,7 @@ F ̵Ò8+¤/<°ŠÀâa­RkpÂàØ´óA¾mWÓQ”Ihÿ㌠œ%–Álþ½E5VW~ªüdžµþX€ì)ôÏ´þ:׺öôŽb‘ˆ�k#�&¼_¤ 3÷0±÷ ØIì endstream endobj -269 0 obj +276 0 obj <> stream xœ}�¿KqÆ?×U–X 94%MQKS�†Nø#Ô¦óüQ vÝ÷BšË¡©hˆFk ¢ÙÆú‚ ! @@ -1086,295 +1111,302 @@ x ô’0l+ϽߣÈy7½®Ó;¯×«É¥º;QŽ?V.ø_îtFÀà3LËEÆK¶)y ðëz”80eÅIPö¤Ÿkñ‰äT‹/%[Ñp” å:8ÕÁ…ü¶¼+%¿÷dбÐŒ"ÂÿG¦·™ `d_¿{Ù¹ÙÖ–gzžçm\‡Ð8rœÏSÇiœ�úµ­öþfæë ´½Ô1\íÃÈCÛóU`¨ ÕS·ô¦¥]Ù ¨ŸÃ@†oÁ½ö ãâ_± endstream endobj -270 0 obj -<> +277 0 obj +<> endobj -271 0 obj +278 0 obj <> stream -Typst 0.15.0en2026-07-06T08:35:32-03:002026-07-06T08:35:32-03:004application/pdfryCwVs21NRYeVZORaVGmEw==ryCwVs21NRYeVZORaVGmEw==proof1.7 +Typst 0.15.1en2026-08-02T00:27:40-03:002026-08-02T00:27:40-03:005application/pdfod6Ce8g5ofbkk30tkgkhhg==od6Ce8g5ofbkk30tkgkhhg==proof1.7 endstream endobj -272 0 obj -<>/ViewerPreferences<>/Outlines 11 0 R>> +279 0 obj +<>/ViewerPreferences<>/Outlines 10 0 R>> endobj xref -0 273 +0 280 0000000000 65535 f 0000000016 00000 n -0000000093 00000 n -0000000169 00000 n -0000000255 00000 n -0000000347 00000 n -0000000429 00000 n -0000000544 00000 n -0000000626 00000 n -0000000730 00000 n -0000000844 00000 n -0000000980 00000 n -0000001047 00000 n -0000001241 00000 n -0000002267 00000 n -0000004312 00000 n -0000005154 00000 n -0000005700 00000 n -0000005771 00000 n -0000005832 00000 n -0000005899 00000 n -0000005981 00000 n -0000006054 00000 n -0000006125 00000 n -0000006207 00000 n -0000006279 00000 n -0000006363 00000 n +0000000101 00000 n +0000000177 00000 n +0000000263 00000 n +0000000355 00000 n +0000000437 00000 n +0000000552 00000 n +0000000634 00000 n +0000000738 00000 n +0000000840 00000 n +0000000906 00000 n +0000001109 00000 n +0000001771 00000 n +0000004169 00000 n +0000004955 00000 n +0000005909 00000 n +0000006007 00000 n +0000006078 00000 n +0000006139 00000 n +0000006206 00000 n +0000006288 00000 n +0000006361 00000 n 0000006435 00000 n -0000006553 00000 n -0000006623 00000 n -0000006693 00000 n -0000006838 00000 n -0000006906 00000 n -0000006978 00000 n -0000007096 00000 n -0000007227 00000 n -0000007295 00000 n -0000007423 00000 n -0000007495 00000 n -0000007565 00000 n -0000007635 00000 n -0000007745 00000 n -0000007813 00000 n -0000007885 00000 n -0000007955 00000 n -0000008025 00000 n -0000008095 00000 n -0000008165 00000 n -0000008235 00000 n -0000008305 00000 n -0000008375 00000 n -0000008526 00000 n -0000008598 00000 n -0000008670 00000 n -0000008767 00000 n +0000006517 00000 n +0000006589 00000 n +0000006673 00000 n +0000006745 00000 n +0000006863 00000 n +0000006933 00000 n +0000007003 00000 n +0000007148 00000 n +0000007216 00000 n +0000007288 00000 n +0000007406 00000 n +0000007537 00000 n +0000007605 00000 n +0000007733 00000 n +0000007805 00000 n +0000007875 00000 n +0000007945 00000 n +0000008055 00000 n +0000008123 00000 n +0000008195 00000 n +0000008265 00000 n +0000008335 00000 n +0000008405 00000 n +0000008475 00000 n +0000008545 00000 n +0000008615 00000 n +0000008685 00000 n 0000008839 00000 n -0000008909 00000 n -0000008979 00000 n -0000009049 00000 n -0000009119 00000 n -0000009189 00000 n -0000009259 00000 n -0000009329 00000 n -0000009399 00000 n -0000009469 00000 n -0000009640 00000 n -0000009710 00000 n -0000009788 00000 n -0000009929 00000 n -0000009997 00000 n -0000010129 00000 n -0000010253 00000 n -0000010371 00000 n -0000010440 00000 n -0000010511 00000 n -0000010580 00000 n -0000010649 00000 n -0000010757 00000 n +0000008911 00000 n +0000008983 00000 n +0000009083 00000 n +0000009155 00000 n +0000009225 00000 n +0000009295 00000 n +0000009365 00000 n +0000009435 00000 n +0000009505 00000 n +0000009575 00000 n +0000009645 00000 n +0000009715 00000 n +0000009785 00000 n +0000009956 00000 n +0000010026 00000 n +0000010104 00000 n +0000010224 00000 n +0000010291 00000 n +0000010406 00000 n +0000010515 00000 n +0000010633 00000 n +0000010703 00000 n +0000010775 00000 n 0000010845 00000 n -0000010913 00000 n -0000010981 00000 n -0000011067 00000 n -0000011153 00000 n -0000011233 00000 n -0000011319 00000 n -0000011405 00000 n -0000011485 00000 n -0000011571 00000 n -0000011660 00000 n -0000011715 00000 n -0000011783 00000 n -0000011869 00000 n +0000010915 00000 n +0000011029 00000 n +0000011117 00000 n +0000011185 00000 n +0000011253 00000 n +0000011339 00000 n +0000011425 00000 n +0000011505 00000 n +0000011591 00000 n +0000011679 00000 n +0000011764 00000 n +0000011857 00000 n +0000011954 00000 n 0000012009 00000 n -0000012094 00000 n -0000012235 00000 n -0000012344 00000 n -0000012485 00000 n -0000012578 00000 n -0000012679 00000 n -0000012734 00000 n -0000012907 00000 n -0000013089 00000 n -0000013215 00000 n -0000013469 00000 n +0000012078 00000 n +0000012171 00000 n +0000012336 00000 n +0000012421 00000 n +0000012562 00000 n +0000012671 00000 n +0000012812 00000 n +0000012905 00000 n +0000013006 00000 n +0000013061 00000 n +0000013234 00000 n +0000013416 00000 n 0000013542 00000 n -0000013615 00000 n -0000013717 00000 n -0000013797 00000 n -0000013870 00000 n -0000013947 00000 n -0000014049 00000 n +0000013796 00000 n +0000013869 00000 n +0000013942 00000 n +0000014044 00000 n 0000014124 00000 n -0000014245 00000 n -0000014320 00000 n -0000014441 00000 n -0000014555 00000 n -0000014635 00000 n -0000014763 00000 n -0000014891 00000 n -0000015019 00000 n -0000015099 00000 n -0000015227 00000 n -0000015355 00000 n -0000015483 00000 n -0000015563 00000 n -0000015691 00000 n -0000015819 00000 n -0000015947 00000 n -0000016027 00000 n -0000016155 00000 n -0000016283 00000 n -0000016411 00000 n -0000016491 00000 n -0000016566 00000 n -0000016687 00000 n -0000016762 00000 n -0000016883 00000 n -0000017015 00000 n -0000017095 00000 n -0000017223 00000 n -0000017351 00000 n -0000017479 00000 n -0000017559 00000 n -0000017730 00000 n -0000017841 00000 n -0000017912 00000 n -0000017983 00000 n -0000018056 00000 n -0000018128 00000 n -0000018200 00000 n -0000018272 00000 n -0000018344 00000 n -0000018416 00000 n -0000018585 00000 n -0000018657 00000 n -0000018749 00000 n -0000018821 00000 n -0000018900 00000 n -0000018972 00000 n -0000019044 00000 n -0000019116 00000 n -0000019188 00000 n -0000019260 00000 n -0000019332 00000 n -0000019404 00000 n -0000019562 00000 n -0000019663 00000 n -0000019737 00000 n -0000019809 00000 n -0000019881 00000 n -0000019992 00000 n -0000020102 00000 n -0000020177 00000 n -0000020260 00000 n -0000020334 00000 n -0000020406 00000 n -0000020478 00000 n -0000020550 00000 n -0000020622 00000 n -0000020767 00000 n -0000020841 00000 n -0000020913 00000 n -0000020985 00000 n -0000021057 00000 n -0000021130 00000 n -0000021330 00000 n -0000021403 00000 n -0000021474 00000 n -0000021545 00000 n -0000021616 00000 n -0000021688 00000 n -0000021760 00000 n -0000021832 00000 n -0000021904 00000 n -0000021976 00000 n -0000022048 00000 n -0000022235 00000 n -0000022309 00000 n -0000022381 00000 n -0000022453 00000 n -0000022525 00000 n -0000022603 00000 n -0000022724 00000 n -0000022798 00000 n -0000022870 00000 n -0000022973 00000 n -0000023047 00000 n -0000023127 00000 n -0000023201 00000 n -0000023287 00000 n -0000023359 00000 n -0000023519 00000 n -0000023591 00000 n -0000023665 00000 n -0000023756 00000 n -0000024135 00000 n -0000024172 00000 n -0000024209 00000 n -0000024262 00000 n -0000024314 00000 n -0000024366 00000 n -0000024419 00000 n -0000024471 00000 n -0000024523 00000 n -0000024576 00000 n -0000024629 00000 n -0000024682 00000 n -0000024816 00000 n -0000024950 00000 n -0000025084 00000 n -0000025218 00000 n -0000025367 00000 n -0000025944 00000 n -0000026152 00000 n -0000026304 00000 n -0000027149 00000 n -0000027360 00000 n -0000027500 00000 n -0000027716 00000 n -0000027955 00000 n -0000028115 00000 n -0000028321 00000 n -0000028534 00000 n -0000028679 00000 n -0000028899 00000 n -0000029144 00000 n -0000029272 00000 n -0000029400 00000 n -0000029528 00000 n -0000029656 00000 n -0000029739 00000 n -0000030381 00000 n -0000034852 00000 n -0000034934 00000 n -0000035714 00000 n -0000046346 00000 n -0000046428 00000 n -0000047197 00000 n -0000059607 00000 n -0000059684 00000 n -0000060115 00000 n -0000060587 00000 n -0000060666 00000 n -0000061134 00000 n -0000065576 00000 n -0000071392 00000 n -0000077480 00000 n -0000083396 00000 n -0000087336 00000 n -0000087679 00000 n -0000088086 00000 n -0000088199 00000 n -0000089272 00000 n +0000014197 00000 n +0000014274 00000 n +0000014376 00000 n +0000014451 00000 n +0000014572 00000 n +0000014647 00000 n +0000014768 00000 n +0000014882 00000 n +0000014962 00000 n +0000015090 00000 n +0000015218 00000 n +0000015354 00000 n +0000015434 00000 n +0000015562 00000 n +0000015690 00000 n +0000015818 00000 n +0000015898 00000 n +0000016026 00000 n +0000016154 00000 n +0000016282 00000 n +0000016362 00000 n +0000016490 00000 n +0000016618 00000 n +0000016750 00000 n +0000016830 00000 n +0000016903 00000 n +0000017024 00000 n +0000017097 00000 n +0000017218 00000 n +0000017348 00000 n +0000017428 00000 n +0000017554 00000 n +0000017680 00000 n +0000017806 00000 n +0000017886 00000 n +0000018057 00000 n +0000018168 00000 n +0000018240 00000 n +0000018312 00000 n +0000018386 00000 n +0000018458 00000 n +0000018530 00000 n +0000018602 00000 n +0000018674 00000 n +0000018746 00000 n +0000018920 00000 n +0000018992 00000 n +0000019084 00000 n +0000019156 00000 n +0000019235 00000 n +0000019307 00000 n +0000019379 00000 n +0000019451 00000 n +0000019523 00000 n +0000019598 00000 n +0000019670 00000 n +0000019742 00000 n +0000019897 00000 n +0000019998 00000 n +0000020072 00000 n +0000020144 00000 n +0000020216 00000 n +0000020327 00000 n +0000020437 00000 n +0000020512 00000 n +0000020595 00000 n +0000020669 00000 n +0000020741 00000 n +0000020813 00000 n +0000020885 00000 n +0000020957 00000 n +0000021102 00000 n +0000021175 00000 n +0000021246 00000 n +0000021317 00000 n +0000021388 00000 n +0000021460 00000 n +0000021532 00000 n +0000021604 00000 n +0000021774 00000 n +0000021848 00000 n +0000021920 00000 n +0000021992 00000 n +0000022064 00000 n +0000022136 00000 n +0000022208 00000 n +0000022280 00000 n +0000022352 00000 n +0000022424 00000 n +0000022496 00000 n +0000022687 00000 n +0000022761 00000 n +0000022833 00000 n +0000022905 00000 n +0000022977 00000 n +0000023052 00000 n +0000023124 00000 n +0000023259 00000 n +0000023333 00000 n +0000023405 00000 n +0000023508 00000 n +0000023582 00000 n +0000023654 00000 n +0000023726 00000 n +0000023798 00000 n +0000023870 00000 n +0000023942 00000 n +0000024014 00000 n +0000024089 00000 n +0000024161 00000 n +0000024233 00000 n +0000024435 00000 n +0000024510 00000 n +0000024583 00000 n +0000024656 00000 n +0000024727 00000 n +0000024800 00000 n +0000025200 00000 n +0000025563 00000 n +0000025600 00000 n +0000025637 00000 n +0000025690 00000 n +0000025743 00000 n +0000025795 00000 n +0000025845 00000 n +0000025897 00000 n +0000025950 00000 n +0000026003 00000 n +0000026056 00000 n +0000026179 00000 n +0000026313 00000 n +0000026447 00000 n +0000026570 00000 n +0000026693 00000 n +0000026842 00000 n +0000027409 00000 n +0000027617 00000 n +0000027769 00000 n +0000028644 00000 n +0000028855 00000 n +0000028995 00000 n +0000029211 00000 n +0000029450 00000 n +0000029610 00000 n +0000029816 00000 n +0000030029 00000 n +0000030157 00000 n +0000030285 00000 n +0000030413 00000 n +0000030541 00000 n +0000030669 00000 n +0000030752 00000 n +0000031389 00000 n +0000035839 00000 n +0000035920 00000 n +0000036713 00000 n +0000048023 00000 n +0000048103 00000 n +0000048878 00000 n +0000061414 00000 n +0000061491 00000 n +0000061922 00000 n +0000062394 00000 n +0000067750 00000 n +0000074317 00000 n +0000079777 00000 n +0000087012 00000 n +0000088036 00000 n +0000088379 00000 n +0000088786 00000 n +0000088899 00000 n +0000089972 00000 n trailer -<> +<> startxref -89459 +90159 %%EOF \ No newline at end of file diff --git a/docs/design.typ b/docs/design.typ index 763dcde4..9cc05cab 100644 --- a/docs/design.typ +++ b/docs/design.typ @@ -18,7 +18,8 @@ is text and all text is equally alive, whether the shell printed it or the user typed it. It runs in three places: the terminal (libvaxis), a native SDL3 window (the -steamdeck), and the browser (wasm + SDL3 + emscripten). The rewrite exists because +steamdeck), and the browser (a freestanding wasm core driven by vanilla +JavaScript and rendered as HTML/CSS). The rewrite exists because the prototype grew three parallel implementations of one program. The rewrite has exactly one program and three thin shells. @@ -59,8 +60,9 @@ input: one event vocabulary, three dialects translated at the door. *Surface* (out): a grid of cells — grapheme, fg, bg, attrs — plus a cursor and per-pane rectangles. This is the *canonical interface*: it is literally what the -tty shell hands to vaxis, cell by cell. The SDL shells rasterize the same grid -through a glyph atlas. If it cannot be expressed in the surface, it does not +tty shell hands to vaxis, cell by cell. SDL rasterizes the same grid through a +glyph atlas; the browser reads a packed copy and patches native DOM cells. If it +cannot be expressed in the surface, it does not exist in pardes. (Pixel images ride along as an attachment per pane: the SDL shells blit RGBA, the tty shell falls back to the petscii matcher, kitty graphics when available.) @@ -136,7 +138,7 @@ only goes down. As built, against the prototype's 12,072 lines of Zig: [*module*], [*lines*], [], [core (pardes.zig + look.zig + syntax + image + dump)], [4,289], [all semantics, all platforms], [modal.zig + petscii.zig (pure, unit-testable)], [1,410], [carried over, unchanged], - [shells (tty.zig; gui.zig = sdl native + web)], [2,768], [translate + rasterize only], + [shells (tty.zig; gui.zig = SDL native; web.zig + web/ = browser)], [2,768], [translate + render only], [main.zig + build.zig], [484], [three targets, codegen for queries], [*application total*], [*7,626*], [vs 12,072 — three full backends instead of one and a half], [snapshot harness (snapshot.zig + e2e_harness.zig)], [831], [the parity oracle, kept], @@ -170,8 +172,8 @@ test. = Build `zig build` produces three statically linked artifacts: `pardes` (vaxis), -`pardes-gui` (SDL3), `pardes.wasm` + shell page (emscripten). Same dependency -set as the prototype — ghostty, vaxis, uucode (shared config), zstbi, SDL +`pardes-gui` (SDL3), `pardes.wasm` + a vanilla DOM shell (wasm32-freestanding). +Same native dependency set as the prototype — ghostty, vaxis, uucode (shared config), zstbi, SDL (castholm, lazy), zig-tree-sitter + grammars — all via `zig fetch`, wired in `build.zig`. Codegen during build, consumed by comptime: tree-sitter `highlights.scm` → options module; tutor text → embedded pane content. Debug @@ -260,23 +262,23 @@ instead of looking it and stepping the list wears the themes. Colors toggles all recolor passes; Debug stats overlay; Dump writes state ZON. *Web (replay viewer parity).* Embedded dump; focus, border/move drags, wheel, -scrollbar, Colors/NextColor, pinch, render scale, and link-LOOK opening a new +scrollbar, Colors/NextColor, and link-LOOK opening a new tab (new — the prototype has no web link handling). One-finger touch is deliberately complete by itself: tap = LOOK; drag past a small slop = natural scroll, with no LOOK on release. A build-generated read-only archive lets LOOK open the current contents of Git-tracked Pardes `.zig` files despite the web shell having no host filesystem. The published launcher dump is captured from a running Pardes TTY after `git ls-files '*.zig'`, so its complete terminal -listing is the set the user can open; the published web build carries only the -Zig tree-sitter grammar and colors opened source panes without shipping unused -C/C++ parsers. A body gesture retains tap-LOOK/drag-scroll, but finger-down on +listing is the set the user can open. The freestanding module carries no host +libc, SDL, or WebGL; Tree-sitter's C runtime and the selected parsers link into +the module through a tiny local ABI shim (Zig is the compact web default). A body gesture retains +tap-LOOK/drag-scroll, but finger-down on a tagline or a one-cell-tolerant pane separator latches to a left-mouse gesture for its lifetime, keeping layout drags out of the scroll heuristic. Touch -circles, trails, and click flashes render only while Debug is enabled. SDL -shells use an -stb_truetype atlas over the SDL GPU API (SPIR-V on native, GLES3 on web), -letterboxed web scaling, pinch, and a touch debug overlay. `PARDES_TEST` -provides PPM and text-grid capture; the browser `.snap` harness drives real -Chromium touch input and reads both text and per-cell styles from the rendered +input translation and scroll/tap state live entirely in the JavaScript shell. +The native SDL shell uses an stb_truetype atlas over the SDL GPU API (SPIR-V). +The browser exposes each cell as selectable, inspectable text and applies the +surface styles with CSS. The browser `.snap` harness drives real Chromium touch +input and reads both text and per-cell styles from the DOM renderer's packed surface. Joystick cursor for the steamdeck is *new* scope — the prototype ships no gamepad input. diff --git a/docs/ideas.typ b/docs/ideas.typ index c954dbbd..3493f758 100644 --- a/docs/ideas.typ +++ b/docs/ideas.typ @@ -7,5 +7,3 @@ - clickable things for the mouse should be navigatable with the keyboard - like if I get some search results I can just use tab to navigate them, the editor should know: - semantic boundaries (maybe just jump to the next clickable thing?) - -|- web: native web client (DOM-rendered, not canvas/WASM). Use WASM only for text logic (parsing, grep, treesitter analysis, look internals) — rendering stays in native DOM/CSS for accessibility, performance, and browser-native text selection. Send structured display commands (layout tree, styled spans, cursor, scroll pos) from WASM to JS via a flat buffer or JSON. diff --git a/docs/web.md b/docs/web.md new file mode 100644 index 00000000..339509d2 --- /dev/null +++ b/docs/web.md @@ -0,0 +1,49 @@ +# DOM web backend + +The web backend keeps the existing Pardes core and replaces the old +Emscripten/SDL/WebGL shell. Zig produces a `wasm32-freestanding` module with no +imports. Vanilla JavaScript owns `requestAnimationFrame`, browser input, window +sizing, and effect/IO dispatch; HTML and CSS render selectable, accessible text. +There is no canvas. + +The default web build links Tree-sitter's C runtime and the Zig grammar inside +that same import-free module. A small freestanding compatibility layer supplies +the C ABI locally, so source panes retain the core's Tree-sitter highlighting +without Emscripten, WASI, or browser libc imports. Other grammar tiers remain +selectable with `-Dtree-sitter=minimal` or `-Dtree-sitter=full`. + +`src/web.zig` is the narrow WASM ABI. Events enter through exported functions, +and `pardes_frame` writes the canonical `Surface` into a packed 20-byte cell +array. `src/web/app.mjs` reads that array in one linear pass and patches stable +DOM nodes. Core effects become browser operations (links, downloads, clipboard) +or `pardes-io` custom events for a process-capable embedding host. + +Build a replay from a dump: + +```sh +zig build web \ + -Dplatform=web \ + -Dtarget=wasm32-freestanding \ + -Dtree-sitter=zig \ + -Ddump=test/web-snapshots/source-list.dump.zon +``` + +The output is in `zig-out/web`. Serve that directory over HTTP; browsers do not +allow a useful WASM module load from `file:` URLs. + +Two dependency-free test layers cover the boundary: + +```sh +# Real WASM in Node plus a small DOM double. +zig build web-harness \ + -Dplatform=web \ + -Dtarget=wasm32-freestanding \ + -Dtree-sitter=zig \ + -Ddump=test/web-snapshots/source-list.dump.zon + +# Real headless Chrome, DOM rendering, and browser touch input. +zig build web-e2e +``` + +Set `PARDES_CHROME` when Chrome/Chromium is not on `PATH` or in a normal +Playwright/Puppeteer cache. diff --git a/src/dump.zig b/src/dump.zig index 0f8cb810..44f61cf4 100644 --- a/src/dump.zig +++ b/src/dump.zig @@ -31,8 +31,8 @@ pub fn outPath(buf: *[1024:0]u8) ?[:0]const u8 { const md = yd.calculateMonthDay(); const ds = es.getDaySeconds(); return std.fmt.bufPrintSentinel(buf, "{s}/pardes-{d:0>4}{d:0>2}{d:0>2}-{d:0>2}{d:0>2}{d:0>2}.zon", .{ - dir, yd.year, md.month.numeric(), - @as(u8, md.day_index) + 1, ds.getHoursIntoDay(), ds.getMinutesIntoHour(), + dir, yd.year, md.month.numeric(), + @as(u8, md.day_index) + 1, ds.getHoursIntoDay(), ds.getMinutesIntoHour(), ds.getSecondsIntoMinute(), }, 0) catch null; } @@ -156,7 +156,7 @@ pub fn readZon(gpa: std.mem.Allocator, bytes: []const u8, label: []const u8) !St } pub fn readZonZ(gpa: std.mem.Allocator, source: [:0]const u8, label: []const u8) !State { - if (builtin.os.tag == .emscripten) { + if (builtin.os.tag == .emscripten or builtin.os.tag == .freestanding) { const state = std.zon.parse.fromSliceAlloc(State, gpa, source, null, .{}) catch |err| { log.err("parse dump {s}: {s}", .{ label, @errorName(err) }); return err; diff --git a/src/web.zig b/src/web.zig new file mode 100644 index 00000000..cebbeebf --- /dev/null +++ b/src/web.zig @@ -0,0 +1,481 @@ +//! Freestanding WebAssembly boundary for the DOM backend. +//! +//! This file deliberately contains no browser imports. JavaScript owns the +//! clock and every IO operation, feeds events through this ABI, and reads one +//! packed cell buffer after `pardes_frame`. Keeping that boundary flat makes +//! the same module directly instantiable by the dependency-free Node harness. + +const std = @import("std"); +const pardes = @import("pardes.zig"); + +const gpa = std.heap.wasm_allocator; +const embedded_dump = @embedFile("embedded.dump.zon"); +const input_capacity = 64 * 1024; +const c_alloc_header_size = 16; + +comptime { + if (c_alloc_header_size < @sizeOf(usize)) @compileError("C allocation header is too small"); +} + +/// Tree-sitter's C runtime is linked into this module. Its conventional +/// allocation symbols share the same wasm allocator as the Zig core and keep +/// the original allocation size in a 16-byte, max-aligned prefix. +export fn malloc(size_arg: usize) callconv(.c) ?*anyopaque { + const size = @max(size_arg, 1); + const total = std.math.add(usize, c_alloc_header_size, size) catch return null; + const bytes = gpa.alignedAlloc(u8, .@"16", total) catch return null; + const header: *align(16) usize = @ptrCast(bytes.ptr); + header.* = total; + return @ptrCast(bytes.ptr + c_alloc_header_size); +} + +export fn calloc(count: usize, size: usize) callconv(.c) ?*anyopaque { + const len = std.math.mul(usize, count, size) catch return null; + const ptr = malloc(len) orelse return null; + if (len != 0) { + const bytes: [*]u8 = @ptrCast(ptr); + @memset(bytes[0..len], 0); + } + return ptr; +} + +export fn free(ptr: ?*anyopaque) callconv(.c) void { + const data = ptr orelse return; + const data_bytes: [*]u8 = @ptrCast(data); + const base: [*]align(16) u8 = @ptrCast(@alignCast(data_bytes - c_alloc_header_size)); + const header: *align(16) usize = @ptrCast(base); + gpa.free(base[0..header.*]); +} + +export fn realloc(ptr: ?*anyopaque, size: usize) callconv(.c) ?*anyopaque { + if (ptr == null) return malloc(size); + if (size == 0) { + free(ptr); + return null; + } + const data_bytes: [*]u8 = @ptrCast(ptr.?); + const base: [*]align(16) u8 = @ptrCast(@alignCast(data_bytes - c_alloc_header_size)); + const header: *align(16) usize = @ptrCast(base); + const old_size = header.* - c_alloc_header_size; + const replacement = malloc(size) orelse return null; + const replacement_bytes: [*]u8 = @ptrCast(replacement); + @memcpy(replacement_bytes[0..@min(old_size, size)], data_bytes[0..@min(old_size, size)]); + free(ptr); + return replacement; +} + +pub const std_options: std.Options = .{ .logFn = logFn }; +pub const panic = std.debug.FullPanic(panicImpl); + +fn logFn( + comptime _: std.log.Level, + comptime _: @EnumLiteral(), + comptime _: []const u8, + _: anytype, +) void {} + +fn panicImpl(_: []const u8, _: ?usize) noreturn { + @trap(); +} + +const WebCell = extern struct { + // UTF-8 graphemes in the core are at most seven bytes. The eighth byte is + // always zero, which also makes a debugger's memory view pleasant. + text: [8]u8, + fg: u32, + bg: u32, + attrs: u16, + len: u8, + flags: u8, +}; + +comptime { + if (@sizeOf(WebCell) != 20) @compileError("the JS frame ABI changed"); +} + +const State = struct { + core: *pardes.Pardes, + arena: std.heap.ArenaAllocator, + cells: std.ArrayList(WebCell) = .empty, + effect_data: std.ArrayList(u8) = .empty, + + fn deinit(s: *State) void { + s.core.deinit(); + s.arena.deinit(); + s.cells.deinit(gpa); + s.effect_data.deinit(gpa); + } +}; + +var state: ?State = null; +var input: [input_capacity]u8 = undefined; +var last_error: u32 = 0; +var effect_aux0: u32 = 0; +var effect_aux1: u32 = 0; + +export fn pardes_init(cols_arg: u32, rows_arg: u32) u32 { + if (state) |*old| old.deinit(); + state = null; + last_error = 0; + + const cols: u16 = @intCast(std.math.clamp(cols_arg, 1, std.math.maxInt(u16))); + const rows: u16 = @intCast(std.math.clamp(rows_arg, 1, std.math.maxInt(u16))); + const core = pardes.Pardes.initFromDump(gpa, .{ .cols = cols, .rows = rows }, embedded_dump) catch |err| { + last_error = @intFromError(err); + return last_error; + }; + state = .{ .core = core, .arena = .init(gpa) }; + core.update(.{ .resize = .{ .cols = cols, .rows = rows } }); + return 0; +} + +export fn pardes_deinit() void { + if (state) |*s| s.deinit(); + state = null; +} + +export fn pardes_last_error() u32 { + return last_error; +} + +export fn pardes_input_ptr() u32 { + return @intCast(@intFromPtr(&input)); +} + +export fn pardes_input_capacity() u32 { + return input_capacity; +} + +export fn pardes_resize(cols_arg: u32, rows_arg: u32) void { + const s = &(state orelse return); + const cols: u16 = @intCast(std.math.clamp(cols_arg, 1, std.math.maxInt(u16))); + const rows: u16 = @intCast(std.math.clamp(rows_arg, 1, std.math.maxInt(u16))); + if (s.core.screen_w == cols and s.core.screen_h == rows) return; + s.core.update(.{ .resize = .{ .cols = cols, .rows = rows } }); +} + +/// `mods`: bit 0 ctrl, bit 1 alt, bit 2 shift. `len` bytes at input are the +/// browser's composed text for printable keys and zero for functional keys. +export fn pardes_key(cp_arg: u32, len_arg: u32, mods: u32) void { + const s = &(state orelse return); + if (cp_arg > std.math.maxInt(u21)) return; + const len: usize = @min(len_arg, input.len); + s.core.update(.{ .key = .{ + .cp = @intCast(cp_arg), + .text = input[0..len], + .ctrl = mods & 1 != 0, + .alt = mods & 2 != 0, + .shift = mods & 4 != 0, + } }); +} + +export fn pardes_paste(len_arg: u32) void { + const s = &(state orelse return); + const len: usize = @min(len_arg, input.len); + s.core.update(.{ .paste = input[0..len] }); +} + +export fn pardes_output(pane: u32, len_arg: u32) void { + const s = &(state orelse return); + if (pane >= pardes.MAX_PANES) return; + const len: usize = @min(len_arg, input.len); + s.core.update(.{ .output = .{ .pane = @intCast(pane), .bytes = input[0..len] } }); +} + +export fn pardes_lsp_response(id: u32, len_arg: u32) void { + const s = &(state orelse return); + const len: usize = @min(len_arg, input.len); + s.core.update(.{ .lsp_resp = .{ .id = id, .rows = input[0..len] } }); +} + +export fn pardes_file_changed(pane: u32, len_arg: u32) void { + const s = &(state orelse return); + if (pane >= pardes.MAX_PANES) return; + const len: usize = @min(len_arg, input.len); + s.core.update(.{ .file_changed = .{ .pane = @intCast(pane), .bytes = input[0..len] } }); +} + +export fn pardes_set_cwd(pane: u32, len_arg: u32) void { + const s = &(state orelse return); + if (pane >= pardes.MAX_PANES) return; + const len: usize = @min(len_arg, input.len); + s.core.setCwd(@intCast(pane), input[0..len]); +} + +export fn pardes_eof(pane: u32) void { + const s = &(state orelse return); + if (pane < pardes.MAX_PANES) s.core.update(.{ .eof = .{ .pane = @intCast(pane) } }); +} + +/// Buttons and kinds are their boundary enum ordinals. Invalid values are +/// ignored rather than reaching an unchecked enum cast inside wasm. +export fn pardes_mouse(button_arg: u32, kind_arg: u32, col_arg: u32, row_arg: u32, mods: u32) void { + const s = &(state orelse return); + const button: pardes.Mouse.Button = switch (button_arg) { + 0 => .left, + 1 => .middle, + 2 => .right, + 3 => .wheel_up, + 4 => .wheel_down, + 5 => .wheel_left, + 6 => .wheel_right, + 7 => .none, + else => return, + }; + const kind: pardes.Mouse.Kind = switch (kind_arg) { + 0 => .press, + 1 => .release, + 2 => .motion, + 3 => .drag, + else => return, + }; + s.core.update(.{ .mouse = .{ + .button = button, + .kind = kind, + .col = @intCast(@min(col_arg, std.math.maxInt(u16))), + .row = @intCast(@min(row_arg, std.math.maxInt(u16))), + .ctrl = mods & 1 != 0, + } }); +} + +export fn pardes_touch_scroll(delta: f32) void { + const s = &(state orelse return); + s.core.update(.{ .touch_scroll = delta }); +} + +export fn pardes_tick() void { + const s = &(state orelse return); + s.core.update(.tick); +} + +/// Render the canonical Surface into a stable, packed JS-facing buffer. +/// Returns the number of cells, or zero if initialization/rendering failed. +export fn pardes_frame() u32 { + const s = &(state orelse return 0); + _ = s.arena.reset(.retain_capacity); + const surface = s.core.render(s.arena.allocator()) catch |err| { + last_error = @intFromError(err); + return 0; + }; + const count: usize = @as(usize, surface.cols) * surface.rows; + s.cells.resize(gpa, count) catch |err| { + last_error = @intFromError(err); + return 0; + }; + for (surface.cells, s.cells.items) |cell, *out| { + out.* = .{ + .text = @splat(0), + .fg = encodeColor(cell.style.fg), + .bg = encodeColor(cell.style.bg), + .attrs = encodeAttrs(cell.style), + .len = if (cell.default) 1 else cell.len, + .flags = @intFromBool(cell.default), + }; + if (cell.default) out.text[0] = ' ' else @memcpy(out.text[0..cell.len], cell.grapheme()); + } + return @intCast(count); +} + +export fn pardes_frame_ptr() u32 { + const s = &(state orelse return 0); + return if (s.cells.items.len == 0) 0 else @intCast(@intFromPtr(s.cells.items.ptr)); +} + +export fn pardes_frame_cols() u32 { + const s = &(state orelse return 0); + return s.core.screen_w; +} + +export fn pardes_frame_rows() u32 { + const s = &(state orelse return 0); + return s.core.screen_h; +} + +export fn pardes_cursor_x() i32 { + const s = &(state orelse return -1); + return if (s.core.surface.cursor) |cursor| cursor.x else -1; +} + +export fn pardes_cursor_y() i32 { + const s = &(state orelse return -1); + return if (s.core.surface.cursor) |cursor| cursor.y else -1; +} + +export fn pardes_cursor_bar() u32 { + const s = &(state orelse return 0); + return @intFromBool(if (s.core.surface.cursor) |cursor| cursor.bar else false); +} + +/// The browser's touch policy asks whether a gesture began on layout chrome. +/// A hit returns row:col packed into u32, including snapping near a separator; +/// 0xffffffff means body text and therefore one-finger scroll/tap-as-LOOK. +export fn pardes_chrome_target(col_arg: u32, row_arg: u32) u32 { + const s = &(state orelse return std.math.maxInt(u32)); + const col: u16 = @intCast(@min(col_arg, std.math.maxInt(u16))); + const row: u16 = @intCast(@min(row_arg, std.math.maxInt(u16))); + const target = chromeTarget(s.core, col, row) orelse return std.math.maxInt(u32); + return (@as(u32, target.row) << 16) | target.col; +} + +// Effect codes consumed by app.mjs. Unknown/host-specific effects are still +// surfaced as `pardes-io` CustomEvents, so embedding the static shell in a +// process-capable host does not require another wasm boundary. +export fn pardes_effect_next() u32 { + const s = &(state orelse return 0); + s.effect_data.clearRetainingCapacity(); + effect_aux0 = 0; + effect_aux1 = 0; + const effect = s.core.nextEffect() orelse return 0; + return switch (effect) { + .spawn => |e| blk: { + effect_aux0 = e.pane; + putEffect(s, e.cwd.slice()); + break :blk 1; + }, + .write => |e| blk: { + effect_aux0 = e.pane; + putEffect(s, e.bytes.slice()); + break :blk 2; + }, + .resize_pty => |e| blk: { + effect_aux0 = e.pane; + effect_aux1 = (@as(u32, e.cols) << 16) | e.rows; + break :blk 3; + }, + .open_link => |e| blk: { + putEffect(s, e.slice()); + break :blk 4; + }, + .save_file => |e| blk: { + effect_aux0 = e.pane; + if (s.core.panes[e.pane]) |pane| if (pane.file) |file| { + putU32(s, @intCast(file.path.len)); + appendEffect(s, file.path); + appendEffect(s, file.content); + }; + break :blk 5; + }, + .write_dump => blk: { + if (s.core.dump_out) |bytes| putEffect(s, bytes); + break :blk 6; + }, + .set_clipboard => blk: { + if (s.core.yank) |bytes| putEffect(s, bytes); + break :blk 7; + }, + .lsp => |e| blk: { + effect_aux0 = e.id; + effect_aux1 = e.pane; + putEffect(s, e.arg.slice()); + break :blk 8; + }, + .watch => |e| blk: { + effect_aux0 = e.pane; + effect_aux1 = @intFromBool(e.on); + if (e.on) if (s.core.panes[e.pane]) |pane| if (pane.file) |file| putEffect(s, file.path); + break :blk 9; + }, + .quit => 10, + }; +} + +export fn pardes_effect_ptr() u32 { + const s = &(state orelse return 0); + return if (s.effect_data.items.len == 0) 0 else @intCast(@intFromPtr(s.effect_data.items.ptr)); +} + +export fn pardes_effect_len() u32 { + const s = &(state orelse return 0); + return @intCast(s.effect_data.items.len); +} + +export fn pardes_effect_aux0() u32 { + return effect_aux0; +} + +export fn pardes_effect_aux1() u32 { + return effect_aux1; +} + +fn encodeColor(color: pardes.Color) u32 { + return switch (color) { + .default => 0x01000000, + .index => |index| 0x02000000 | @as(u32, index), + .rgb => |rgb| (@as(u32, rgb[0]) << 16) | (@as(u32, rgb[1]) << 8) | rgb[2], + }; +} + +fn encodeAttrs(style: pardes.CellStyle) u16 { + var attrs: u16 = 0; + attrs |= @as(u16, @intFromBool(style.bold)) << 0; + attrs |= @as(u16, @intFromBool(style.dim)) << 1; + attrs |= @as(u16, @intFromBool(style.italic)) << 2; + attrs |= @as(u16, @intFromBool(style.blink)) << 3; + attrs |= @as(u16, @intFromBool(style.reverse)) << 4; + attrs |= @as(u16, @intFromBool(style.invisible)) << 5; + attrs |= @as(u16, @intFromBool(style.strikethrough)) << 6; + attrs |= @as(u16, @intFromEnum(style.ul)) << 8; + return attrs; +} + +fn putEffect(s: *State, bytes: []const u8) void { + s.effect_data.clearRetainingCapacity(); + appendEffect(s, bytes); +} + +fn appendEffect(s: *State, bytes: []const u8) void { + s.effect_data.appendSlice(gpa, bytes) catch {}; +} + +fn putU32(s: *State, value: u32) void { + var bytes: [4]u8 = undefined; + std.mem.writeInt(u32, &bytes, value, .little); + appendEffect(s, &bytes); +} + +const Target = struct { col: u16, row: u16 }; + +fn chromeTarget(core: *const pardes.Pardes, col: u16, row: u16) ?Target { + if (row < pardes.TOPBAR_H) return .{ .col = col, .row = row }; + for (core.panes, 0..) |slot, id| { + if (slot == null) continue; + const rect = core.rects[id]; + if (row == rect.y and col >= rect.x and col < rect.x + rect.w and col < rect.x + pardes.config.GUTTER) + return .{ .col = col, .row = rect.y }; + } + for (0..core.ncol -| 1) |column| { + const handle = core.col_x[column] + core.col_w[column] -| 1; + if (col == handle) return .{ .col = handle, .row = row }; + } + for (0..core.ncol) |column| { + if (col < core.col_x[column] or col >= core.col_x[column] + core.col_w[column]) continue; + for (0..core.col_n[column] -| 1) |index| { + const rect = core.rects[core.col_terms[column][index]]; + const handle = rect.y + rect.h -| 1; + if (row == handle) return .{ .col = col, .row = handle }; + } + } + for (core.panes, 0..) |slot, id| { + if (slot == null) continue; + const rect = core.rects[id]; + if (row == rect.y and col >= rect.x and col < rect.x + rect.w) + return .{ .col = col, .row = rect.y }; + } + for (0..core.ncol -| 1) |column| { + const handle = core.col_x[column] + core.col_w[column] -| 1; + if (distance(col, handle) == 1) return .{ .col = handle, .row = row }; + } + for (0..core.ncol) |column| { + if (col < core.col_x[column] or col >= core.col_x[column] + core.col_w[column]) continue; + for (0..core.col_n[column] -| 1) |index| { + const rect = core.rects[core.col_terms[column][index]]; + const handle = rect.y + rect.h -| 1; + if (distance(row, handle) == 1) return .{ .col = col, .row = handle }; + } + } + return null; +} + +fn distance(a: u16, b: u16) u16 { + return if (a > b) a - b else b - a; +} diff --git a/src/web/app.mjs b/src/web/app.mjs new file mode 100644 index 00000000..3d32a16b --- /dev/null +++ b/src/web/app.mjs @@ -0,0 +1,436 @@ +const CELL_SIZE = 20; +const DEFAULT_FG = "#cccccc"; +const DEFAULT_BG = "#121212"; +const decoder = new TextDecoder(); +const encoder = new TextEncoder(); + +const BUTTON = Object.freeze({ left: 0, middle: 1, right: 2, wheelUp: 3, wheelDown: 4, wheelLeft: 5, wheelRight: 6, none: 7 }); +const MOUSE = Object.freeze({ press: 0, release: 1, motion: 2, drag: 3 }); +const SPECIAL_KEYS = Object.freeze({ + Enter: 0x0d, + Backspace: 0x7f, + Tab: 0x09, + Escape: 0x1b, + ArrowUp: 0xf0001, + ArrowDown: 0xf0002, + ArrowLeft: 0xf0003, + ArrowRight: 0xf0004, + Home: 0xf0005, + End: 0xf0006, + PageUp: 0xf0007, + PageDown: 0xf0008, + Delete: 0xf0009, +}); + +export class DomRenderer { + constructor(root, wasm) { + this.root = root; + this.wasm = wasm; + this.rows = []; + this.cells = []; + this.cols = 0; + this.rowCount = 0; + this.snapshot = null; + } + + render() { + const count = this.wasm.pardes_frame(); + const cols = this.wasm.pardes_frame_cols(); + const rows = this.wasm.pardes_frame_rows(); + if (count !== cols * rows) throw new Error(`bad frame: ${count} cells for ${cols}x${rows}`); + this.ensureGrid(cols, rows); + + const ptr = this.wasm.pardes_frame_ptr(); + const view = new DataView(this.wasm.memory.buffer, ptr, count * CELL_SIZE); + const bytes = new Uint8Array(this.wasm.memory.buffer); + const cursorX = this.wasm.pardes_cursor_x(); + const cursorY = this.wasm.pardes_cursor_y(); + const cursorBar = this.wasm.pardes_cursor_bar() !== 0; + const raw = new Array(count); + + for (let index = 0; index < count; index += 1) { + const off = index * CELL_SIZE; + const len = view.getUint8(off + 18); + const fg = view.getUint32(off + 8, true); + const bg = view.getUint32(off + 12, true); + const attrs = view.getUint16(off + 16, true); + const text = decoder.decode(bytes.subarray(ptr + off, ptr + off + len)) || " "; + const x = index % cols; + const y = Math.floor(index / cols); + const cursor = x === cursorX && y === cursorY; + const cell = this.cells[index]; + if (cell.textContent !== text) cell.textContent = text; + const styleKey = `${fg}:${bg}:${attrs}:${cursor ? 1 : 0}:${cursorBar ? 1 : 0}`; + if (cell.pardesStyle !== styleKey) { + applyStyle(cell, fg, bg, attrs, cursor, cursorBar); + cell.pardesStyle = styleKey; + } + raw[index] = { text, fg, bg, attrs }; + } + this.snapshot = { cols, rows, cells: raw, cursorX, cursorY, cursorBar }; + return this.snapshot; + } + + ensureGrid(cols, rows) { + if (cols === this.cols && rows === this.rowCount) return; + const document = this.root.ownerDocument; + const rowNodes = []; + const cells = []; + for (let y = 0; y < rows; y += 1) { + const row = document.createElement("div"); + row.className = "pardes-row"; + row.setAttribute("role", "row"); + row.dataset.row = String(y); + const rowCells = []; + for (let x = 0; x < cols; x += 1) { + const cell = document.createElement("span"); + cell.className = "pardes-cell"; + cell.setAttribute("role", "gridcell"); + cell.dataset.col = String(x); + cell.dataset.row = String(y); + cell.textContent = " "; + rowCells.push(cell); + cells.push(cell); + } + row.replaceChildren(...rowCells); + rowNodes.push(row); + } + this.root.replaceChildren(...rowNodes); + this.root.setAttribute("aria-colcount", String(cols)); + this.root.setAttribute("aria-rowcount", String(rows)); + this.rows = rowNodes; + this.cells = cells; + this.cols = cols; + this.rowCount = rows; + } +} + +export class PardesRuntime { + constructor(root, wasm) { + this.root = root; + this.wasm = wasm; + this.renderer = new DomRenderer(root, wasm); + this.inputPtr = wasm.pardes_input_ptr(); + this.inputCapacity = wasm.pardes_input_capacity(); + this.cellWidth = 1; + this.cellHeight = 1; + this.running = false; + this.pointer = null; + this.frameHandle = 0; + this.bindEvents(); + } + + start() { + this.measure(); + const { cols, rows } = this.gridSize(); + const error = this.wasm.pardes_init(cols, rows); + if (error) throw new Error(`Pardes wasm init failed (${error})`); + this.inputPtr = this.wasm.pardes_input_ptr(); + this.resize(); + this.renderer.render(); + this.drainEffects(); + this.running = true; + this.frameHandle = requestAnimationFrame(() => this.frame()); + this.root.focus({ preventScroll: true }); + } + + stop() { + this.running = false; + if (this.frameHandle) cancelAnimationFrame(this.frameHandle); + this.wasm.pardes_deinit(); + } + + frame() { + if (!this.running) return; + this.wasm.pardes_tick(); + this.renderer.render(); + this.drainEffects(); + this.frameHandle = requestAnimationFrame(() => this.frame()); + } + + measure() { + const probe = this.root.ownerDocument.createElement("span"); + probe.className = "pardes-probe"; + probe.textContent = "M"; + this.root.ownerDocument.body.append(probe); + const rect = probe.getBoundingClientRect(); + probe.remove(); + this.cellWidth = Math.max(1, rect.width); + this.cellHeight = Math.max(1, rect.height); + } + + gridSize() { + return { + cols: Math.max(1, Math.floor(this.root.clientWidth / this.cellWidth)), + rows: Math.max(1, Math.floor(this.root.clientHeight / this.cellHeight)), + }; + } + + resize() { + this.measure(); + const { cols, rows } = this.gridSize(); + this.wasm.pardes_resize(cols, rows); + } + + writeInput(text) { + const data = encoder.encode(text); + if (data.length > this.inputCapacity) throw new Error("browser input exceeds wasm transfer buffer"); + new Uint8Array(this.wasm.memory.buffer, this.inputPtr, data.length).set(data); + return data.length; + } + + key(event) { + const mods = modifiers(event); + let cp = SPECIAL_KEYS[event.key]; + let text = ""; + if (cp === undefined && event.key.length > 0 && [...event.key].length === 1) { + text = mods & 3 ? "" : event.key; + const shortcut = event.code?.match(/^Key([A-Z])$/); + cp = shortcut && (mods & 3) ? shortcut[1].toLowerCase().codePointAt(0) : event.key.codePointAt(0); + } + if (cp === undefined) return; + event.preventDefault(); + this.wasm.pardes_key(cp, this.writeInput(text), mods); + } + + point(event) { + const rect = this.root.getBoundingClientRect(); + return { + col: clamp(Math.floor((event.clientX - rect.left) / this.cellWidth), 0, Math.max(0, this.wasm.pardes_frame_cols() - 1)), + row: clamp(Math.floor((event.clientY - rect.top) / this.cellHeight), 0, Math.max(0, this.wasm.pardes_frame_rows() - 1)), + }; + } + + cellPoint(col, row) { + const rect = this.root.getBoundingClientRect(); + return { x: rect.left + (col + 0.5) * this.cellWidth, y: rect.top + (row + 0.5) * this.cellHeight }; + } + + pointerDown(event) { + event.preventDefault(); + this.root.focus({ preventScroll: true }); + this.root.setPointerCapture?.(event.pointerId); + const point = this.point(event); + if (event.pointerType === "touch") { + const packed = this.wasm.pardes_chrome_target(point.col, point.row) >>> 0; + const chrome = packed !== 0xffffffff; + const snapped = chrome ? { col: packed & 0xffff, row: packed >>> 16 } : point; + this.pointer = { id: event.pointerId, touch: true, chrome, startX: event.clientX, startY: event.clientY, lastX: event.clientX, lastY: event.clientY, point: snapped, scrolling: false, accum: 0 }; + if (chrome) this.wasm.pardes_mouse(BUTTON.left, MOUSE.press, snapped.col, snapped.row, modifiers(event)); + return; + } + const button = pointerButton(event.button); + this.pointer = { id: event.pointerId, touch: false, button }; + this.wasm.pardes_mouse(button, MOUSE.press, point.col, point.row, modifiers(event)); + } + + pointerMove(event) { + const point = this.point(event); + const active = this.pointer?.id === event.pointerId ? this.pointer : null; + if (!active) { + if (event.pointerType !== "touch") this.wasm.pardes_mouse(BUTTON.none, MOUSE.motion, point.col, point.row, modifiers(event)); + return; + } + event.preventDefault(); + if (!active.touch) { + this.wasm.pardes_mouse(active.button, MOUSE.drag, point.col, point.row, modifiers(event)); + return; + } + if (active.chrome) { + this.wasm.pardes_mouse(BUTTON.left, MOUSE.drag, point.col, point.row, modifiers(event)); + return; + } + const travel = Math.hypot(event.clientX - active.startX, event.clientY - active.startY); + if (travel > 8) active.scrolling = true; + if (active.scrolling) { + const dy = event.clientY - active.lastY; + active.accum += dy / this.cellHeight; + while (active.accum <= -1) { + this.wasm.pardes_mouse(BUTTON.wheelDown, MOUSE.press, point.col, point.row, 0); + active.accum += 1; + } + while (active.accum >= 1) { + this.wasm.pardes_mouse(BUTTON.wheelUp, MOUSE.press, point.col, point.row, 0); + active.accum -= 1; + } + this.wasm.pardes_touch_scroll(dy / this.cellHeight); + } + active.lastX = event.clientX; + active.lastY = event.clientY; + } + + pointerUp(event) { + const active = this.pointer?.id === event.pointerId ? this.pointer : null; + if (!active) return; + event.preventDefault(); + const point = this.point(event); + if (active.touch) { + if (active.chrome) this.wasm.pardes_mouse(BUTTON.left, MOUSE.release, point.col, point.row, modifiers(event)); + else if (!active.scrolling) { + this.wasm.pardes_mouse(BUTTON.right, MOUSE.press, point.col, point.row, 0); + this.wasm.pardes_mouse(BUTTON.right, MOUSE.release, point.col, point.row, 0); + } + } else { + this.wasm.pardes_mouse(active.button, MOUSE.release, point.col, point.row, modifiers(event)); + } + if (this.root.hasPointerCapture?.(event.pointerId)) this.root.releasePointerCapture(event.pointerId); + this.pointer = null; + } + + wheel(event) { + event.preventDefault(); + const point = this.point(event); + if (event.deltaY) this.wasm.pardes_mouse(event.deltaY < 0 ? BUTTON.wheelUp : BUTTON.wheelDown, MOUSE.press, point.col, point.row, modifiers(event)); + if (event.deltaX) this.wasm.pardes_mouse(event.deltaX < 0 ? BUTTON.wheelLeft : BUTTON.wheelRight, MOUSE.press, point.col, point.row, modifiers(event)); + } + + paste(event) { + const text = event.clipboardData?.getData("text/plain"); + if (text === undefined) return; + event.preventDefault(); + this.wasm.pardes_paste(this.writeInput(text)); + } + + bindEvents() { + this.root.addEventListener("keydown", (event) => this.key(event)); + this.root.addEventListener("paste", (event) => this.paste(event)); + this.root.addEventListener("contextmenu", (event) => event.preventDefault()); + this.root.addEventListener("pointerdown", (event) => this.pointerDown(event)); + this.root.addEventListener("pointermove", (event) => this.pointerMove(event)); + this.root.addEventListener("pointerup", (event) => this.pointerUp(event)); + this.root.addEventListener("pointercancel", (event) => this.pointerUp(event)); + this.root.addEventListener("wheel", (event) => this.wheel(event), { passive: false }); + globalThis.addEventListener?.("resize", () => this.resize()); + } + + drainEffects() { + for (;;) { + const kind = this.wasm.pardes_effect_next(); + if (!kind) return; + const ptr = this.wasm.pardes_effect_ptr(); + const len = this.wasm.pardes_effect_len(); + const data = new Uint8Array(len); + if (len) data.set(new Uint8Array(this.wasm.memory.buffer, ptr, len)); + const aux0 = this.wasm.pardes_effect_aux0(); + const aux1 = this.wasm.pardes_effect_aux1(); + this.handleEffect(kind, data, aux0, aux1); + } + } + + handleEffect(kind, data, aux0, aux1) { + if (kind === 4) { + globalThis.open?.(decoder.decode(data), "_blank", "noopener,noreferrer"); + } else if (kind === 5) { + const view = new DataView(data.buffer, data.byteOffset, data.byteLength); + const pathLength = data.length >= 4 ? view.getUint32(0, true) : 0; + const path = decoder.decode(data.subarray(4, 4 + pathLength)); + download(data.subarray(4 + pathLength), path.split("/").pop() || "pardes.txt", "text/plain;charset=utf-8"); + } else if (kind === 6) { + download(data, "pardes-dump.zon", "text/plain;charset=utf-8"); + } else if (kind === 7) { + navigator.clipboard?.writeText(decoder.decode(data)).catch(() => {}); + } else if (kind === 10) { + this.running = false; + } else { + this.root.dispatchEvent(new CustomEvent("pardes-io", { detail: { kind, data, aux0, aux1 } })); + } + } +} + +export async function instantiate(url = "./pardes.wasm") { + const response = await fetch(url); + if (!response.ok) throw new Error(`fetch ${url}: HTTP ${response.status}`); + if (WebAssembly.instantiateStreaming) { + try { + return (await WebAssembly.instantiateStreaming(response.clone(), {})).instance.exports; + } catch (error) { + if (!/mime|content-type/i.test(String(error))) throw error; + } + } + return (await WebAssembly.instantiate(await response.arrayBuffer(), {})).instance.exports; +} + +export async function boot(root, url = "./pardes.wasm") { + if (!root) throw new Error("Pardes DOM root is missing"); + const wasm = await instantiate(url); + const runtime = new PardesRuntime(root, wasm); + runtime.start(); + const test = { + grid: () => runtime.renderer.snapshot, + cellPoint: (col, row) => runtime.cellPoint(col, row), + }; + globalThis.pardes = { runtime, wasm, test }; + return runtime; +} + +function applyStyle(cell, fgCode, bgCode, attrs, cursor, cursorBar) { + let fg = color(fgCode, DEFAULT_FG); + let bg = color(bgCode, DEFAULT_BG); + if (attrs & (1 << 4)) [fg, bg] = [bg, fg]; + if (attrs & (1 << 5)) fg = bg; + if (attrs & (1 << 1)) fg = dim(fg); + cell.style.color = fg; + cell.style.backgroundColor = bg; + cell.style.fontWeight = attrs & 1 ? "700" : "400"; + cell.style.fontStyle = attrs & (1 << 2) ? "italic" : "normal"; + const underline = (attrs >>> 8) & 7; + cell.style.textDecorationLine = `${underline ? "underline " : ""}${attrs & (1 << 6) ? "line-through" : ""}`.trim() || "none"; + cell.style.textDecorationStyle = ["solid", "solid", "double", "wavy", "dotted", "dashed"][underline] || "solid"; + cell.style.setProperty("--cell-fg", fg); + cell.style.setProperty("--cell-bg", bg); + cell.classList.toggle("is-cursor", cursor); + cell.classList.toggle("is-bar", cursor && cursorBar); + cell.classList.toggle("is-blinking", Boolean(attrs & (1 << 3))); +} + +function color(encoded, fallback) { + if (encoded === 0x01000000) return fallback; + if ((encoded & 0xff000000) === 0x02000000) return indexedColor(encoded & 0xff); + return `#${(encoded & 0xffffff).toString(16).padStart(6, "0")}`; +} + +function indexedColor(index) { + const ansi = [ + "#000000", "#cc0000", "#4e9a06", "#c4a000", "#3465a4", "#75507b", "#06989a", "#d3d7cf", + "#555753", "#ef2929", "#8ae234", "#fce94f", "#729fcf", "#ad7fa8", "#34e2e2", "#eeeeec", + ]; + if (index < 16) return ansi[index]; + if (index >= 232) { + const level = 8 + (index - 232) * 10; + return rgb(level, level, level); + } + const n = index - 16; + const level = (part) => part === 0 ? 0 : 55 + part * 40; + return rgb(level(Math.floor(n / 36)), level(Math.floor(n / 6) % 6), level(n % 6)); +} + +function dim(value) { + const n = Number.parseInt(value.slice(1), 16); + return rgb(((n >>> 16) & 0xff) * 0.6, ((n >>> 8) & 0xff) * 0.6, (n & 0xff) * 0.6); +} + +function rgb(r, g, b) { + return `#${[r, g, b].map((part) => Math.round(part).toString(16).padStart(2, "0")).join("")}`; +} + +function modifiers(event) { + return (event.ctrlKey ? 1 : 0) | (event.altKey ? 2 : 0) | (event.shiftKey ? 4 : 0); +} + +function pointerButton(button) { + return button === 1 ? BUTTON.middle : button === 2 ? BUTTON.right : BUTTON.left; +} + +function clamp(value, low, high) { + return Math.max(low, Math.min(high, value)); +} + +function download(bytes, name, type) { + if (typeof document === "undefined") return; + const url = URL.createObjectURL(new Blob([bytes], { type })); + const anchor = document.createElement("a"); + anchor.href = url; + anchor.download = name; + anchor.click(); + setTimeout(() => URL.revokeObjectURL(url), 0); +} diff --git a/src/web/index.html b/src/web/index.html new file mode 100644 index 00000000..4012c313 --- /dev/null +++ b/src/web/index.html @@ -0,0 +1,17 @@ + + + + + + Pardes + + + +
+ + + + diff --git a/src/web/libc.c b/src/web/libc.c new file mode 100644 index 00000000..c49fa03e --- /dev/null +++ b/src/web/libc.c @@ -0,0 +1,152 @@ +/* Minimal libc-shaped surface used by Tree-sitter inside the freestanding + * browser module. Allocation lives in web.zig so it shares Zig's wasm heap; + * these routines neither import browser functions nor perform IO. */ +#include +#include +#include +#include +#include +#include +#include + +_Noreturn void abort(void) { + __builtin_trap(); +} + +size_t strlen(const char *str) { + const char *end = str; + while (*end) end++; + return (size_t)(end - str); +} + +char *strchr(const char *str, int character) { + const unsigned char needle = (unsigned char)character; + do { + if ((unsigned char)*str == needle) return (char *)str; + } while (*str++); + return (char *)0; +} + +void *memchr(const void *ptr, int value, size_t count) { + const unsigned char *bytes = (const unsigned char *)ptr; + const unsigned char needle = (unsigned char)value; + for (size_t index = 0; index < count; index++) { + if (bytes[index] == needle) return (void *)(bytes + index); + } + return (void *)0; +} + +int strcmp(const char *lhs, const char *rhs) { + while (*lhs && (unsigned char)*lhs == (unsigned char)*rhs) { + lhs++; + rhs++; + } + return (int)(unsigned char)*lhs - (int)(unsigned char)*rhs; +} + +int strncmp(const char *lhs, const char *rhs, size_t count) { + while (count && *lhs && (unsigned char)*lhs == (unsigned char)*rhs) { + lhs++; + rhs++; + count--; + } + return count ? (int)(unsigned char)*lhs - (int)(unsigned char)*rhs : 0; +} + +char *strncpy(char *restrict dest, const char *restrict src, size_t count) { + char *result = dest; + while (count && *src) { + *dest++ = *src++; + count--; + } + while (count--) *dest++ = '\0'; + return result; +} + +int isprint(int character) { + return character >= 0x20 && character <= 0x7e; +} + +int isdigit(int character) { + return character >= '0' && character <= '9'; +} + +int iswspace(wint_t character) { + return character == ' ' || (character >= '\t' && character <= '\r'); +} + +int iswalnum(wint_t character) { + return iswdigit(character) || iswalpha(character); +} + +int iswalpha(wint_t character) { + return (character >= 'A' && character <= 'Z') || + (character >= 'a' && character <= 'z') || character >= 0x80; +} + +int iswblank(wint_t character) { + return character == ' ' || character == '\t'; +} + +int iswdigit(wint_t character) { + return character >= '0' && character <= '9'; +} + +int iswlower(wint_t character) { + return character >= 'a' && character <= 'z'; +} + +int iswupper(wint_t character) { + return character >= 'A' && character <= 'Z'; +} + +int iswxdigit(wint_t character) { + return iswdigit(character) || (character >= 'A' && character <= 'F') || + (character >= 'a' && character <= 'f'); +} + +wint_t towupper(wint_t character) { + return iswlower(character) ? character - ('a' - 'A') : character; +} + +int vsnprintf(char *restrict buffer, size_t size, const char *restrict format, va_list args) { + (void)format; + (void)args; + if (size) buffer[0] = '\0'; + return 0; +} + +int snprintf(char *restrict buffer, size_t size, const char *restrict format, ...) { + va_list args; + va_start(args, format); + int result = vsnprintf(buffer, size, format, args); + va_end(args); + return result; +} + +int fprintf(FILE *stream, const char *format, ...) { + (void)stream; + (void)format; + return 0; +} + +int fclose(FILE *stream) { + (void)stream; + return 0; +} + +FILE *fdopen(int descriptor, const char *mode) { + (void)descriptor; + (void)mode; + return (FILE *)0; +} + +int fputc(int character, FILE *stream) { + (void)stream; + return character; +} + +int fputs(const char *string, FILE *stream) { + (void)stream; + return (int)strlen(string); +} diff --git a/src/web/libc/include/assert.h b/src/web/libc/include/assert.h new file mode 100644 index 00000000..fd018947 --- /dev/null +++ b/src/web/libc/include/assert.h @@ -0,0 +1,14 @@ +#ifndef PARDES_WEB_ASSERT_H +#define PARDES_WEB_ASSERT_H + +#ifndef static_assert +#define static_assert _Static_assert +#endif + +#ifdef NDEBUG +#define assert(expression) ((void)0) +#else +#define assert(expression) ((expression) ? (void)0 : __builtin_trap()) +#endif + +#endif diff --git a/src/web/libc/include/ctype.h b/src/web/libc/include/ctype.h new file mode 100644 index 00000000..985c8759 --- /dev/null +++ b/src/web/libc/include/ctype.h @@ -0,0 +1,7 @@ +#ifndef PARDES_WEB_CTYPE_H +#define PARDES_WEB_CTYPE_H + +int isprint(int character); +int isdigit(int character); + +#endif diff --git a/src/web/libc/include/endian.h b/src/web/libc/include/endian.h new file mode 100644 index 00000000..a047c88f --- /dev/null +++ b/src/web/libc/include/endian.h @@ -0,0 +1,21 @@ +#ifndef PARDES_WEB_ENDIAN_H +#define PARDES_WEB_ENDIAN_H + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __BYTE_ORDER __LITTLE_ENDIAN + +#define htole16(value) (value) +#define le16toh(value) (value) +#define htole32(value) (value) +#define le32toh(value) (value) +#define htole64(value) (value) +#define le64toh(value) (value) +#define htobe16(value) __builtin_bswap16(value) +#define be16toh(value) __builtin_bswap16(value) +#define htobe32(value) __builtin_bswap32(value) +#define be32toh(value) __builtin_bswap32(value) +#define htobe64(value) __builtin_bswap64(value) +#define be64toh(value) __builtin_bswap64(value) + +#endif diff --git a/src/web/libc/include/inttypes.h b/src/web/libc/include/inttypes.h new file mode 100644 index 00000000..7e795746 --- /dev/null +++ b/src/web/libc/include/inttypes.h @@ -0,0 +1,8 @@ +#ifndef PARDES_WEB_INTTYPES_H +#define PARDES_WEB_INTTYPES_H + +#include + +#define PRId32 "d" + +#endif diff --git a/src/web/libc/include/limits.h b/src/web/libc/include/limits.h new file mode 100644 index 00000000..6ba31375 --- /dev/null +++ b/src/web/libc/include/limits.h @@ -0,0 +1,9 @@ +#ifndef PARDES_WEB_LIMITS_H +#define PARDES_WEB_LIMITS_H + +#define CHAR_BIT __CHAR_BIT__ +#define INT_MAX __INT_MAX__ +#define UINT_MAX (__INT_MAX__ * 2U + 1U) +#define USHRT_MAX (__SHRT_MAX__ * 2U + 1U) + +#endif diff --git a/src/web/libc/include/stdio.h b/src/web/libc/include/stdio.h new file mode 100644 index 00000000..92895054 --- /dev/null +++ b/src/web/libc/include/stdio.h @@ -0,0 +1,19 @@ +#ifndef PARDES_WEB_STDIO_H +#define PARDES_WEB_STDIO_H + +#include +#include + +typedef struct PardesWebFile FILE; + +#define stderr ((FILE *)0) + +int fprintf(FILE *stream, const char *format, ...); +int fclose(FILE *stream); +FILE *fdopen(int descriptor, const char *mode); +int fputc(int character, FILE *stream); +int fputs(const char *string, FILE *stream); +int snprintf(char *restrict buffer, size_t size, const char *restrict format, ...); +int vsnprintf(char *restrict buffer, size_t size, const char *restrict format, va_list args); + +#endif diff --git a/src/web/libc/include/stdlib.h b/src/web/libc/include/stdlib.h new file mode 100644 index 00000000..cb280904 --- /dev/null +++ b/src/web/libc/include/stdlib.h @@ -0,0 +1,16 @@ +#ifndef PARDES_WEB_STDLIB_H +#define PARDES_WEB_STDLIB_H + +#include + +#ifndef NULL +#define NULL ((void *)0) +#endif + +void *malloc(size_t size); +void *calloc(size_t count, size_t size); +void *realloc(void *ptr, size_t size); +void free(void *ptr); +_Noreturn void abort(void); + +#endif diff --git a/src/web/libc/include/string.h b/src/web/libc/include/string.h new file mode 100644 index 00000000..7e5b8783 --- /dev/null +++ b/src/web/libc/include/string.h @@ -0,0 +1,17 @@ +#ifndef PARDES_WEB_STRING_H +#define PARDES_WEB_STRING_H + +#include + +void *memchr(const void *ptr, int value, size_t count); +int memcmp(const void *lhs, const void *rhs, size_t count); +void *memcpy(void *restrict dest, const void *restrict src, size_t count); +void *memmove(void *dest, const void *src, size_t count); +void *memset(void *dest, int value, size_t count); +size_t strlen(const char *str); +char *strchr(const char *str, int character); +int strcmp(const char *lhs, const char *rhs); +int strncmp(const char *lhs, const char *rhs, size_t count); +char *strncpy(char *restrict dest, const char *restrict src, size_t count); + +#endif diff --git a/src/web/libc/include/wchar.h b/src/web/libc/include/wchar.h new file mode 100644 index 00000000..4888631e --- /dev/null +++ b/src/web/libc/include/wchar.h @@ -0,0 +1,9 @@ +#ifndef PARDES_WEB_WCHAR_H +#define PARDES_WEB_WCHAR_H + +#include +#include + +typedef __WCHAR_TYPE__ wchar_t; + +#endif diff --git a/src/web/libc/include/wctype.h b/src/web/libc/include/wctype.h new file mode 100644 index 00000000..77bbabe9 --- /dev/null +++ b/src/web/libc/include/wctype.h @@ -0,0 +1,18 @@ +#ifndef PARDES_WEB_WCTYPE_H +#define PARDES_WEB_WCTYPE_H + +#include + +typedef unsigned int wint_t; + +int iswalnum(wint_t character); +int iswalpha(wint_t character); +int iswblank(wint_t character); +int iswdigit(wint_t character); +int iswlower(wint_t character); +int iswspace(wint_t character); +int iswupper(wint_t character); +int iswxdigit(wint_t character); +wint_t towupper(wint_t character); + +#endif diff --git a/src/web/pardes.css b/src/web/pardes.css new file mode 100644 index 00000000..a959e6c3 --- /dev/null +++ b/src/web/pardes.css @@ -0,0 +1,91 @@ +@font-face { + font-family: "Pardes Mono"; + src: url("./AdwaitaMono-Regular.ttf") format("truetype"); + font-display: swap; +} + +:root { + color-scheme: dark; + --pardes-bg: #121212; + --pardes-fg: #cccccc; + --pardes-font-size: 18px; + --pardes-cell-width: 9.333333px; + --pardes-cell-height: 19.459459px; +} + +html, +body { + width: 100%; + height: 100%; + margin: 0; + overflow: hidden; + background: var(--pardes-bg); +} + +.pardes { + box-sizing: border-box; + width: 100vw; + height: 100vh; + overflow: hidden; + color: var(--pardes-fg); + background: var(--pardes-bg); + font-family: "Pardes Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: var(--pardes-font-size); + font-variant-ligatures: none; + line-height: 1; + outline: none; + touch-action: none; + user-select: text; + cursor: text; +} + +.pardes-row { + display: flex; + width: max-content; + height: var(--pardes-cell-height); + line-height: var(--pardes-cell-height); + white-space: pre; +} + +.pardes-cell { + box-sizing: border-box; + display: inline-block; + flex: 0 0 var(--pardes-cell-width); + width: var(--pardes-cell-width); + height: var(--pardes-cell-height); + overflow: hidden; + text-align: left; + white-space: pre; +} + +.pardes-cell.is-cursor { + color: var(--cell-bg) !important; + background: var(--cell-fg) !important; +} + +.pardes-cell.is-cursor.is-bar { + color: var(--cell-fg) !important; + background: var(--cell-bg) !important; + box-shadow: inset 2px 0 var(--cell-fg); +} + +.pardes-cell.is-blinking { + animation: pardes-blink 1s step-end infinite; +} + +.pardes-probe { + position: fixed; + left: -10000px; + top: -10000px; + width: var(--pardes-cell-width); + height: var(--pardes-cell-height); + visibility: hidden; +} + +@keyframes pardes-blink { + 50% { opacity: 0; } +} + +@media (prefers-reduced-motion: reduce) { + .pardes-cell.is-blinking { animation: none; } +} diff --git a/src/web/zstbi.zig b/src/web/zstbi.zig new file mode 100644 index 00000000..76b144f7 --- /dev/null +++ b/src/web/zstbi.zig @@ -0,0 +1,30 @@ +//! Freestanding image-decoder shim. +//! +//! The browser core has no libc or C allocator ABI. Image bytes still survive +//! dumps, but decoding belongs in the JavaScript IO layer rather than pulling +//! stb_image and an Emscripten runtime into the state machine. + +const std = @import("std"); + +pub fn init(_: std.Io, _: std.mem.Allocator) void {} +pub fn deinit() void {} + +pub const Image = struct { + data: []u8 = &.{}, + width: u32 = 0, + height: u32 = 0, + num_components: u32 = 4, + bytes_per_component: u32 = 1, + bytes_per_row: u32 = 0, + is_hdr: bool = false, + + pub fn loadFromMemory(_: []const u8, _: u32) !Image { + return error.ImageDecodeUnavailable; + } + + pub fn resize(_: *const Image, _: u32, _: u32) Image { + return .{}; + } + + pub fn deinit(_: *Image) void {} +}; diff --git a/test/web-snapshots/README.md b/test/web-snapshots/README.md index d2ea84f8..c6564ba0 100644 --- a/test/web-snapshots/README.md +++ b/test/web-snapshots/README.md @@ -13,6 +13,7 @@ To recapture it: The visible `.body` must exactly match the command plus every path reported by Git (and the final prompt). The base64 PTY stream must contain the command -itself. `source-list.snap` then drives that dump through Chromium: it checks the -full listing, taps `build.zig`, snapshots tree-sitter style runs, resizes the -pane separator, and finally verifies body scrolling. +itself. `source-list.snap` then drives the freestanding WASM + DOM build through +Chromium: it checks the full listing, taps `build.zig`, snapshots packed cell +styles (including Tree-sitter's Zig highlighting), resizes the pane separator, +and finally verifies body scrolling. diff --git a/test/web-snapshots/source-list.golden b/test/web-snapshots/source-list.golden index d4321fbb..35f86de6 100644 --- a/test/web-snapshots/source-list.golden +++ b/test/web-snapshots/source-list.golden @@ -1,6 +1,6 @@ == snap launcher grid=120x37 cursor=4,23 -|Kill Newcol Tutor Debug Colors NextColor Crt Dump -| TTY /home/goblin/00-projects/0x4200.cafe/02-pardes-code Del +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +|$ /home/goblin/00-projects/0x4200.cafe/02-pardes-code Del | $ git ls-files '*.zig' | build.zig | src/crt.zig @@ -36,155 +36,155 @@ | | | -== snap source-open grid=120x37 cursor=7,25 -|Kill Newcol Tutor Debug Colors NextColor Crt Dump -| TTY /home/goblin/00-projects/0x4200.cafe/02-pardes-code Del -| $ git ls-files '*.zig' -| build.zig -| src/crt.zig -| src/deck.zig -| src/dump.zig -| src/gui.zig -| src/image.zig -| src/look.zig -| src/main.zig -| src/modal.zig -| src/pardes.zig -| src/petscii.zig -| src/syntax.zig -| src/tracy.zig -| src/tty.zig -| test/deck/replay.zig -| test/deck/schema.zig -| test/e2e_harness.zig -| test/hxdiff.zig -| test/snapshot.zig -| uucode_config.zig -| -| NOR build.zig Save Del -| 1 const std = @import("std"); -| 2 -| 3 pub const Platform = enum { tty, gui, web }; -| 4 pub const TreeSitterGrammars = enum { disabled, zig, minimal, full }; -| 5 const GhosttyArtifact = enum { ghostty, lib }; -| 6 -| 7 pub fn build(b: *std.Build) void { -| 8 // Default target is the Steam Deck (deckcap's trick): x86_64 linux-gnu -| 9 // with the glibc version pinned low, so a binary built on a rolling- -| 10 // release host runs on SteamOS — a native build references the host's -| 11 // newer versioned libm/libc symbols and dies with "GLIBC_2.4x not found" -| 12 // on the deck. Override with -Dtarget= as usual. +== snap source-open grid=120x37 cursor=7,2 +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +| build.zig Save Del $ /home/goblin/00-projects/0x4200.cafe/02-pardes-code Del +| 1 const std = @import("std"); $ git ls-files '*.zig' +| 2 const snap_build = @import("build/snap.zig"); build.zig +| 3 src/crt.zig +| 4 pub const Platform = enum { tty, gui, web }; src/deck.zig +| 5 src/dump.zig +| 6 /// The ZLS the language backend links, spelled once. src/gui.zig +| 7 /// build.zig.zon pins (0.16.x branch) and is passed src/image.zig +| 8 /// `-Dversion-string` (its build.zig otherwise shell src/look.zig +| 9 /// which fails on a fetched package that has no .git src/main.zig +| 10 const zls_version = "0.16.1-dev+3e0d0820"; src/modal.zig +| 11 pub const TreeSitterGrammars = enum { disabled, zig, src/pardes.zig +| 12 src/petscii.zig +| 13 pub fn build(b: *std.Build) void { src/syntax.zig +| 14 // Default target is the Steam Deck (deckcap's tr src/tracy.zig +| 15 // with the glibc version pinned low, so a binary src/tty.zig +| 16 // release host runs on SteamOS — a native build test/deck/replay.zig +| 17 // newer versioned libm/libc symbols and dies wit test/deck/schema.zig +| 18 // on the deck. Override with -Dtarget= as usual. test/e2e_harness.zig +| 19 const target = b.standardTargetOptions(.{ .defaul test/hxdiff.zig +| 20 .cpu_arch = .x86_64, test/snapshot.zig +| 21 .os_tag = .linux, uucode_config.zig +| 22 .abi = .gnu, +| 23 .glibc_version = .{ .major = 2, .minor = 38, +| 24 } }); +| 25 const requested_optimize = b.standardOptimizeOpti +| 26 const platform = b.option(Platform, "platform", " +| 27 const static = b.option(bool, "static", "statical +| 28 const dump_path = b.option([]const u8, "dump", "d +| 29 const is_web = platform == .web; +| 30 const is_web_target = target.result.cpu.arch == . +| 31 // wasm: size is the budget +| 32 const optimize = if (is_web) .ReleaseSmall else r +| 33 // The vendored C is never what we are debugging, +| 34 // the app: 90% of a Debug startup is tree-sitter +| 35 // (perf: ts_query__perform_analysis + ts_lookahe == style source-open -|0: 0-48 #969696,#2c2a3e, 49-119 d,#2c2a3e, -|1: 0-1 d,#383c54, 2-60 #969696,#2c2a3e, 61-119 d,#2c2a3e, -|2: 0-1 d,#525252, 2-119 d,d, -|3: 0-1 d,#525252, 2-119 d,d, -|4: 0-1 d,#525252, 2-119 d,d, -|5: 0-1 d,#525252, 2-119 d,d, -|6: 0-1 d,#525252, 2-119 d,d, -|7: 0-1 d,#525252, 2-119 d,d, -|8: 0-1 d,#525252, 2-119 d,d, -|9: 0-1 d,#525252, 2-119 d,d, -|10: 0-1 d,#525252, 2-119 d,d, -|11: 0-1 d,#525252, 2-119 d,d, -|12: 0-1 d,#525252, 2-119 d,d, -|13: 0-1 d,#525252, 2-119 d,d, -|14: 0-1 d,#525252, 2-119 d,d, -|15: 0-1 d,#525252, 2-119 d,d, -|16: 0-1 d,#525252, 2-119 d,d, -|17: 0-1 d,#525252, 2-119 d,d, -|18: 0-1 d,#525252, 2-119 d,d, -|19: 0-1 d,#525252, 2-119 d,d, -|20: 0-1 d,#525252, 2-119 d,d, -|21: 0-1 d,#525252, 2-119 d,d, -|22: 0-1 d,#525252, 2-119 d,d, -|23: 0-1 d,#525252, 2-119 d,d, -|24: 0-1 d,#6e4fd0, 2-23 #969696,#2c2a3e, 24-119 d,#2c2a3e, -|25: 0-1 d,#525252, 2-6 #969696,#2c2a3e, 7-18 d,d, 19-25 #cc70d8,d,b 26-26 d,d, 27-31 #8ab87a,d, 32-119 d,d, -|26: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-119 d,d, -|27: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-27 d,d, 28-31 #cc70d8,d,b 32-119 d,d, -|28: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-37 d,d, 38-41 #cc70d8,d,b 42-119 d,d, -|29: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-30 d,d, 31-34 #cc70d8,d,b 35-119 d,d, -|30: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-119 d,d, -|31: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-10 d,d, 11-12 #cc70d8,d,b 13-119 d,d, -|32: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-10 d,d, 11-81 #f0f0f0,d,b 82-119 d,d, -|33: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-10 d,d, 11-79 #f0f0f0,d,b 80-119 d,d, -|34: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-10 d,d, 11-80 #f0f0f0,d,b 81-119 d,d, -|35: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-10 d,d, 11-83 #f0f0f0,d,b 84-119 d,d, -|36: 0-1 d,#2a2a2a, 2-6 #5a5a5a,d, 7-10 d,d, 11-59 #f0f0f0,d,b 60-119 d,d, -== snap separator-resized grid=120x37 cursor=7,21 -|Kill Newcol Tutor Debug Colors NextColor Crt Dump -| TTY /home/goblin/00-projects/0x4200.cafe/02-pardes-code Del -| src/dump.zig -| src/gui.zig -| src/image.zig -| src/look.zig -| src/main.zig -| src/modal.zig -| src/pardes.zig -| src/petscii.zig -| src/syntax.zig -| src/tracy.zig -| src/tty.zig -| test/deck/replay.zig -| test/deck/schema.zig -| test/e2e_harness.zig -| test/hxdiff.zig -| test/snapshot.zig -| uucode_config.zig -|╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ -| NOR build.zig Save Del -| 1 const std = @import("std"); -| 2 -| 3 pub const Platform = enum { tty, gui, web }; -| 4 pub const TreeSitterGrammars = enum { disabled, zig, minimal, full }; -| 5 const GhosttyArtifact = enum { ghostty, lib }; -| 6 -| 7 pub fn build(b: *std.Build) void { -| 8 // Default target is the Steam Deck (deckcap's trick): x86_64 linux-gnu -| 9 // with the glibc version pinned low, so a binary built on a rolling- -| 10 // release host runs on SteamOS — a native build references the host's -| 11 // newer versioned libm/libc symbols and dies with "GLIBC_2.4x not found" -| 12 // on the deck. Override with -Dtarget= as usual. -| 13 const target = b.standardTargetOptions(.{ .default_target = .{ -| 14 .cpu_arch = .x86_64, -| 15 .os_tag = .linux, -| 16 .abi = .gnu, -== snap source-scrolled grid=120x37 cursor=0,0 -|Kill Newcol Tutor Debug Colors NextColor Crt Dump -| TTY /home/goblin/00-projects/0x4200.cafe/02-pardes-code Del -| src/dump.zig -| src/gui.zig -| src/image.zig -| src/look.zig -| src/main.zig -| src/modal.zig -| src/pardes.zig -| src/petscii.zig -| src/syntax.zig -| src/tracy.zig -| src/tty.zig -| test/deck/replay.zig -| test/deck/schema.zig -| test/e2e_harness.zig -| test/hxdiff.zig -| test/snapshot.zig -| uucode_config.zig -| -| NOR build.zig Save Del -| 10 // release host runs on SteamOS — a native build references the host's -| 11 // newer versioned libm/libc symbols and dies with "GLIBC_2.4x not found" -| 12 // on the deck. Override with -Dtarget= as usual. -| 13 const target = b.standardTargetOptions(.{ .default_target = .{ -| 14 .cpu_arch = .x86_64, -| 15 .os_tag = .linux, -| 16 .abi = .gnu, -| 17 .glibc_version = .{ .major = 2, .minor = 38, .patch = 0 }, -| 18 } }); -| 19 const requested_optimize = b.standardOptimizeOption(.{}); -| 20 const platform = b.option(Platform, "platform", "which shell to build (tty, gui, web)") orelse .tty; -| 21 const static = b.option(bool, "static", "statically link") orelse false; -| 22 const dump_path = b.option([]const u8, "dump", "dump .zon embedded into the web shell (-Dplatform=web)"); -| 23 const emcc_path = b.option([]const u8, "emcc", "emcc for the web shell's final link") orelse "/usr/lib/emscri -| 24 const is_emscripten = target.result.os.tag == .emscripten; -| 25 // wasm: size is the budget +|0: 0-52 #969696,#2c2a3e, 53-119 d,#2c2a3e, +|1: 0-1 #ffffff,#6e4fd0, 2-19 #969696,#2c2a3e, 20-59 d,#2c2a3e, 60-61 #ffffff,#383c54, 62-116 #969696,#2c2a3e, 117-119 d,#2c2a3e, +|2: 0-0 d,#525252, 1-1 d,d, 2-6 #969696,#2c2a3e, 7-18 d,d, 19-25 #cc70d8,d,b 26-26 d,d, 27-31 #8ab87a,d, 32-59 d,d, 60-60 d,#525252, 61-119 d,d, +|3: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-25 d,d, 26-32 #cc70d8,d,b 33-33 d,d, 34-49 #8ab87a,d, 50-59 d,d, 60-60 d,#525252, 61-119 d,d, +|4: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 d,d, 60-60 d,#525252, 61-119 d,d, +|5: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-27 d,d, 28-31 #cc70d8,d,b 32-59 d,d, 60-60 d,#525252, 61-119 d,d, +|6: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 d,d, 60-60 d,#525252, 61-119 d,d, +|7: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 #f0f0f0,d,b 60-60 d,#525252, 61-119 d,d, +|8: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 #f0f0f0,d,b 60-60 d,#525252, 61-119 d,d, +|9: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 #f0f0f0,d,b 60-60 d,#525252, 61-119 d,d, +|10: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 #f0f0f0,d,b 60-60 d,#525252, 61-119 d,d, +|11: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-26 d,d, 27-47 #8ab87a,d, 48-59 d,d, 60-60 d,#525252, 61-119 d,d, +|12: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-37 d,d, 38-41 #cc70d8,d,b 42-59 d,d, 60-60 d,#525252, 61-119 d,d, +|13: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 d,d, 60-60 d,#525252, 61-119 d,d, +|14: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-10 d,d, 11-12 #cc70d8,d,b 13-59 d,d, 60-60 d,#525252, 61-119 d,d, +|15: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-10 d,d, 11-59 #f0f0f0,d,b 60-60 d,#525252, 61-119 d,d, +|16: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-10 d,d, 11-59 #f0f0f0,d,b 60-60 d,#525252, 61-119 d,d, +|17: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-10 d,d, 11-59 #f0f0f0,d,b 60-60 d,#525252, 61-119 d,d, +|18: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-10 d,d, 11-59 #f0f0f0,d,b 60-60 d,#525252, 61-119 d,d, +|19: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-10 d,d, 11-59 #f0f0f0,d,b 60-60 d,#525252, 61-119 d,d, +|20: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 d,d, 60-60 d,#525252, 61-119 d,d, +|21: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 d,d, 60-60 d,#525252, 61-119 d,d, +|22: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 d,d, 60-60 d,#525252, 61-119 d,d, +|23: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 d,d, 60-60 d,#525252, 61-119 d,d, +|24: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-43 d,d, 44-44 #d0c070,d, 45-55 d,d, 56-57 #d0c070,d, 58-59 d,d, 60-60 d,#525252, 61-119 d,d, +|25: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 d,d, 60-60 d,#525252, 61-119 d,d, +|26: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 d,d, 60-60 d,#525252, 61-119 d,d, +|27: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-46 d,d, 47-56 #8ab87a,d, 57-58 d,d, 59-59 #8ab87a,d, 60-60 d,#525252, 61-119 d,d, +|28: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-40 d,d, 41-48 #8ab87a,d, 49-50 d,d, 51-59 #8ab87a,d, 60-60 d,#525252, 61-119 d,d, +|29: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-49 d,d, 50-55 #8ab87a,d, 56-57 d,d, 58-59 #8ab87a,d, 60-60 d,#525252, 61-119 d,d, +|30: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 d,d, 60-60 d,#525252, 61-119 d,d, +|31: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-59 d,d, 60-60 d,#525252, 61-119 d,d, +|32: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-10 d,d, 11-37 #f0f0f0,d,b 38-59 d,d, 60-60 d,#525252, 61-119 d,d, +|33: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-27 d,d, 28-29 #cc70d8,d,b 30-53 d,d, 54-57 #cc70d8,d,b 58-59 d,d, 60-60 d,#525252, 61-119 d,d, +|34: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-10 d,d, 11-59 #f0f0f0,d,b 60-60 d,#525252, 61-119 d,d, +|35: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-10 d,d, 11-59 #f0f0f0,d,b 60-60 d,#525252, 61-119 d,d, +|36: 0-0 d,#2a2a2a, 1-1 d,d, 2-6 #5a5a5a,d, 7-10 d,d, 11-59 #f0f0f0,d,b 60-60 d,#525252, 61-119 d,d, +== snap separator-resized grid=120x37 cursor=7,2 +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +| build.zig Save Del ╎$ /home/goblin/00-projects/0x4200.cafe/02-pardes-code Del +| 1 const std = @import("std"); ╎ $ git ls-files '*.zig' +| 2 const snap_build = @import("build/snap.zig"); ╎ build.zig +| 3 ╎ src/crt.zig +| 4 pub const Platform = enum { tty, gui, web }; ╎ src/deck.zig +| 5 ╎ src/dump.zig +| 6 /// The ZLS the language backend links, spelled once.╎ src/gui.zig +| 7 /// build.zig.zon pins (0.16.x branch) and is passed ╎ src/image.zig +| 8 /// `-Dversion-string` (its build.zig otherwise shell╎ src/look.zig +| 9 /// which fails on a fetched package that has no .git╎ src/main.zig +| 10 const zls_version = "0.16.1-dev+3e0d0820"; ╎ src/modal.zig +| 11 pub const TreeSitterGrammars = enum { disabled, zig, ╎ src/pardes.zig +| 12 ╎ src/petscii.zig +| 13 pub fn build(b: *std.Build) void { ╎ src/syntax.zig +| 14 // Default target is the Steam Deck (deckcap's tr╎ src/tracy.zig +| 15 // with the glibc version pinned low, so a binary╎ src/tty.zig +| 16 // release host runs on SteamOS — a native build ╎ test/deck/replay.zig +| 17 // newer versioned libm/libc symbols and dies wit╎ test/deck/schema.zig +| 18 // on the deck. Override with -Dtarget= as usual.╎ test/e2e_harness.zig +| 19 const target = b.standardTargetOptions(.{ .defaul╎ test/hxdiff.zig +| 20 .cpu_arch = .x86_64, ╎ test/snapshot.zig +| 21 .os_tag = .linux, ╎ uucode_config.zig +| 22 .abi = .gnu, ╎ +| 23 .glibc_version = .{ .major = 2, .minor = 38, ╎ +| 24 } }); ╎ +| 25 const requested_optimize = b.standardOptimizeOpti╎ +| 26 const platform = b.option(Platform, "platform", "╎ +| 27 const static = b.option(bool, "static", "statical╎ +| 28 const dump_path = b.option([]const u8, "dump", "d╎ +| 29 const is_web = platform == .web; ╎ +| 30 const is_web_target = target.result.cpu.arch == .╎ +| 31 // wasm: size is the budget ╎ +| 32 const optimize = if (is_web) .ReleaseSmall else r╎ +| 33 // The vendored C is never what we are debugging,╎ +| 34 // the app: 90% of a Debug startup is tree-sitter╎ +| 35 // (perf: ts_query__perform_analysis + ts_lookahe╎ +== snap source-scrolled grid=120x37 cursor=7,2 +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +| build.zig Save Del ╎$ /home/goblin/00-projects/0x4200.cafe/02-pardes-code Del +| 1 const std = @import("std"); ╎ $ git ls-files '*.zig' +| 2 const snap_build = @import("build/snap.zig"); ╎ build.zig +| 3 ╎ src/crt.zig +| 4 pub const Platform = enum { tty, gui, web }; ╎ src/deck.zig +| 5 ╎ src/dump.zig +| 6 /// The ZLS the language backend links, spelled once.╎ src/gui.zig +| 7 /// build.zig.zon pins (0.16.x branch) and is passed ╎ src/image.zig +| 8 /// `-Dversion-string` (its build.zig otherwise shell╎ src/look.zig +| 9 /// which fails on a fetched package that has no .git╎ src/main.zig +| 10 const zls_version = "0.16.1-dev+3e0d0820"; ╎ src/modal.zig +| 11 pub const TreeSitterGrammars = enum { disabled, zig, ╎ src/pardes.zig +| 12 ╎ src/petscii.zig +| 13 pub fn build(b: *std.Build) void { ╎ src/syntax.zig +| 14 // Default target is the Steam Deck (deckcap's tr╎ src/tracy.zig +| 15 // with the glibc version pinned low, so a binary╎ src/tty.zig +| 16 // release host runs on SteamOS — a native build ╎ test/deck/replay.zig +| 17 // newer versioned libm/libc symbols and dies wit╎ test/deck/schema.zig +| 18 // on the deck. Override with -Dtarget= as usual.╎ test/e2e_harness.zig +| 19 const target = b.standardTargetOptions(.{ .defaul╎ test/hxdiff.zig +| 20 .cpu_arch = .x86_64, ╎ test/snapshot.zig +| 21 .os_tag = .linux, ╎ uucode_config.zig +| 22 .abi = .gnu, ╎ +| 23 .glibc_version = .{ .major = 2, .minor = 38, ╎ +| 24 } }); ╎ +| 25 const requested_optimize = b.standardOptimizeOpti╎ +| 26 const platform = b.option(Platform, "platform", "╎ +| 27 const static = b.option(bool, "static", "statical╎ +| 28 const dump_path = b.option([]const u8, "dump", "d╎ +| 29 const is_web = platform == .web; ╎ +| 30 const is_web_target = target.result.cpu.arch == .╎ +| 31 // wasm: size is the budget ╎ +| 32 const optimize = if (is_web) .ReleaseSmall else r╎ +| 33 // The vendored C is never what we are debugging,╎ +| 34 // the app: 90% of a Debug startup is tree-sitter╎ +| 35 // (perf: ts_query__perform_analysis + ts_lookahe╎ diff --git a/test/web_harness.mjs b/test/web_harness.mjs new file mode 100644 index 00000000..bcd45746 --- /dev/null +++ b/test/web_harness.mjs @@ -0,0 +1,136 @@ +#!/usr/bin/env node +// Dependency-free JS harness: instantiate the real freestanding core in Node, +// then render its packed frame through app.mjs against a deliberately tiny DOM +// double. Chrome is reserved for the separate browser/e2e snapshot harness. + +import assert from "node:assert/strict"; +import fs from "node:fs/promises"; +import path from "node:path"; +import { pathToFileURL } from "node:url"; + +if (process.argv.length !== 3) { + console.error("usage: node test/web_harness.mjs "); + process.exit(2); +} + +async function main() { + const webDir = path.resolve(process.argv[2]); + const wasmBytes = await fs.readFile(path.join(webDir, "pardes.wasm")); + const module = await WebAssembly.compile(wasmBytes); + assert.deepEqual(WebAssembly.Module.imports(module), [], "the freestanding core must have no JS or libc imports"); + const { exports: wasm } = await WebAssembly.instantiate(module, {}); + + for (const name of [ + "memory", "pardes_init", "pardes_frame", "pardes_frame_ptr", "pardes_key", + "pardes_mouse", "pardes_output", "pardes_lsp_response", "pardes_file_changed", + "pardes_effect_next", "pardes_deinit", + ]) assert.ok(wasm[name], `missing wasm export ${name}`); + + assert.equal(wasm.pardes_init(80, 24), 0, `wasm init error ${wasm.pardes_last_error()}`); + assert.equal(wasm.pardes_frame(), 80 * 24); + assert.ok(wasm.pardes_frame_ptr() > 0); + + const { DomRenderer } = await import(pathToFileURL(path.join(webDir, "app.mjs"))); + const document = new FakeDocument(); + const root = document.createElement("main"); + root.ownerDocument = document; + const renderer = new DomRenderer(root, wasm); + const first = renderer.render(); + + assert.equal(first.cols, 80); + assert.equal(first.rows, 24); + assert.equal(root.children.length, 24); + assert.equal(root.children[0].children.length, 80); + assert.ok(first.cells.some((cell) => cell.text !== " "), "dump rendered an empty frame"); + assert.ok(root.walk().every((node) => node.tagName !== "CANVAS"), "renderer created a canvas"); + + const firstCell = renderer.cells[0]; + const second = renderer.render(); + assert.equal(renderer.cells[0], firstCell, "stable frames should reuse DOM nodes"); + assert.equal(second.cells.length, 80 * 24); + + wasm.pardes_mouse(2, 0, 5, 3, 0); + wasm.pardes_mouse(2, 1, 5, 3, 0); + const looked = renderer.render(); + assert.match(looked.cells.map((cell) => cell.text).join(""), /build\.zig Save Del/, "right-click LOOK did not open the embedded source"); + const sourceRows = Array.from({ length: looked.rows }, (_, row) => + looked.cells.slice(row * looked.cols, (row + 1) * looked.cols)); + const codeRows = sourceRows.filter((row) => row.map((cell) => cell.text).join("").match(/^\s*\d+\s/)); + const codeColors = new Set(codeRows.flatMap((row) => row.slice(5).map((cell) => `${cell.fg}:${cell.attrs & 1}`))); + assert.ok(codeColors.size >= 3, "Tree-sitter did not apply distinct syntax styles to build.zig"); + let sawWatch = false; + for (let index = 0; index < 32; index += 1) { + const kind = wasm.pardes_effect_next(); + if (!kind) break; + if (kind === 9) sawWatch = true; + } + assert.ok(sawWatch, "JS effect drain did not receive the opened file watch request"); + + wasm.pardes_resize(41, 13); + const resized = renderer.render(); + assert.equal(resized.cols, 41); + assert.equal(resized.rows, 13); + assert.equal(root.children.length, 13); + assert.equal(root.children[0].children.length, 41); + + wasm.pardes_deinit(); + console.error("web harness ok: freestanding wasm + Tree-sitter + packed DOM renderer"); +} + +class FakeDocument { + constructor() { + this.body = new FakeElement("body", this); + } + + createElement(tagName) { + return new FakeElement(tagName, this); + } +} + +class FakeElement { + constructor(tagName, ownerDocument) { + this.tagName = tagName.toUpperCase(); + this.ownerDocument = ownerDocument; + this.children = []; + this.attributes = new Map(); + this.dataset = {}; + this.style = new FakeStyle(); + this.classList = new FakeClassList(this); + this.className = ""; + this.textContent = ""; + } + + setAttribute(name, value) { + this.attributes.set(name, String(value)); + } + + replaceChildren(...children) { + this.children = children; + } + + *walk() { + yield this; + for (const child of this.children) yield* child.walk(); + } +} + +class FakeStyle { + setProperty(name, value) { + this[name] = value; + } +} + +class FakeClassList { + constructor(element) { + this.element = element; + this.names = new Set(); + } + + toggle(name, force) { + if (force) this.names.add(name); + else this.names.delete(name); + this.element.className = [...this.names].join(" "); + } +} + +await main(); diff --git a/test/web_snapshot.mjs b/test/web_snapshot.mjs index 7c0c7462..4c50956e 100644 --- a/test/web_snapshot.mjs +++ b/test/web_snapshot.mjs @@ -1,5 +1,7 @@ #!/usr/bin/env node -// Drive the Emscripten build in a real headless Chromium using .snap scripts. +// Drive the freestanding WASM + DOM build in a real headless Chromium using +// .snap scripts. This is an end-to-end browser test: Chrome creates genuine +// touch events and the JS shell translates them into core events. // Shared commands retain test/snapshot.zig's spelling and output format: // wait | stable // snap