From 304e7c631079671eb909743c2392c441f9f8e96a Mon Sep 17 00:00:00 2001 From: Rolando Santamaria Maso <4096860+jkyberneees@users.noreply.github.com> Date: Thu, 10 Sep 2026 15:26:02 +0200 Subject: [PATCH 1/4] feat(webui): build rich reference client with structured tool views --- cmd/odek/serve.go | 68 +++++-- cmd/odek/serve_api.go | 66 ++++++- cmd/odek/serve_artifacts.go | 267 ++++++++++++++++++++++++++ cmd/odek/serve_runs.go | 1 + cmd/odek/serve_test.go | 16 +- cmd/odek/serve_workspace.go | 142 ++++++++++++++ cmd/odek/serve_workspace_test.go | 141 ++++++++++++++ cmd/odek/ui/fonts/manrope-LICENSE.txt | 93 +++++++++ cmd/odek/ui/fonts/manrope.ttf | Bin 0 -> 165420 bytes cmd/odek/ui/index.html | 27 ++- cmd/odek/ui/js/api.js | 22 ++- cmd/odek/ui/js/artifacts.js | 39 ++++ cmd/odek/ui/js/commands.js | 1 + cmd/odek/ui/js/health.js | 2 +- cmd/odek/ui/js/icons.js | 17 ++ cmd/odek/ui/js/input.js | 58 ++++-- cmd/odek/ui/js/lifecycle.test.js | 111 +++++++++++ cmd/odek/ui/js/main.js | 17 +- cmd/odek/ui/js/management.js | 72 +++++++ cmd/odek/ui/js/panels.js | 91 +++++++-- cmd/odek/ui/js/plan.js | 1 + cmd/odek/ui/js/render.js | 166 +++++++++++----- cmd/odek/ui/js/results.js | 197 +++++++++++++++++++ cmd/odek/ui/js/results.test.js | 40 ++++ cmd/odek/ui/js/sessions.js | 22 ++- cmd/odek/ui/js/tools.js | 10 +- cmd/odek/ui/js/tools.test.js | 15 +- cmd/odek/ui/js/toolviews.js | 167 ++++++++++++++++ cmd/odek/ui/js/toolviews.test.js | 63 ++++++ cmd/odek/ui/js/workspace.js | 148 ++++++++++++++ cmd/odek/ui/js/ws.js | 23 ++- cmd/odek/ui/style.css | 215 ++++++++++++++++++++- docs/WEBUI.md | 136 ++++++++++++- docs/WEBUI_REFERENCE_PROGRESS.md | 57 ++++++ internal/artifact/observer.go | 23 +++ internal/artifact/observer_test.go | 27 +++ internal/loop/callmetrics.go | 1 + internal/loop/loop.go | 41 +++- internal/mcpclient/client.go | 2 + internal/memory/preview.go | 84 ++++++++ internal/memory/preview_test.go | 44 +++++ internal/session/message.go | 2 + odek.go | 7 + scripts/webui/fixture-server.mjs | 31 +++ 44 files changed, 2632 insertions(+), 141 deletions(-) create mode 100644 cmd/odek/serve_artifacts.go create mode 100644 cmd/odek/serve_workspace.go create mode 100644 cmd/odek/serve_workspace_test.go create mode 100644 cmd/odek/ui/fonts/manrope-LICENSE.txt create mode 100644 cmd/odek/ui/fonts/manrope.ttf create mode 100644 cmd/odek/ui/js/artifacts.js create mode 100644 cmd/odek/ui/js/icons.js create mode 100644 cmd/odek/ui/js/management.js create mode 100644 cmd/odek/ui/js/results.js create mode 100644 cmd/odek/ui/js/results.test.js create mode 100644 cmd/odek/ui/js/toolviews.js create mode 100644 cmd/odek/ui/js/toolviews.test.js create mode 100644 cmd/odek/ui/js/workspace.js create mode 100644 docs/WEBUI_REFERENCE_PROGRESS.md create mode 100644 internal/artifact/observer.go create mode 100644 internal/artifact/observer_test.go create mode 100644 internal/memory/preview.go create mode 100644 internal/memory/preview_test.go create mode 100644 scripts/webui/fixture-server.mjs diff --git a/cmd/odek/serve.go b/cmd/odek/serve.go index 28383081..bd218f82 100644 --- a/cmd/odek/serve.go +++ b/cmd/odek/serve.go @@ -26,6 +26,7 @@ import ( "time" "github.com/BackendStack21/odek" + "github.com/BackendStack21/odek/internal/artifact" "github.com/BackendStack21/odek/internal/bgproc" "github.com/BackendStack21/odek/internal/budget" "github.com/BackendStack21/odek/internal/config" @@ -614,6 +615,14 @@ func newServeMux(d serveMuxDeps) *http.ServeMux { h.ServeHTTP(w, r) })))) } + workspace, _ := os.Getwd() + mux.Handle("/api/uploads", apiAuth(handleBrowserUpload(store, resolved.Model, workspace))) + mux.Handle("/api/artifacts", apiAuth(handleBrowserArtifacts(store, &browserArtifacts))) + mux.Handle("/api/artifacts/", apiAuth(handleBrowserArtifacts(store, &browserArtifacts))) + mux.Handle("/api/capabilities", apiAuth(http.HandlerFunc(handleCapabilities))) + mux.Handle("/api/schedules", apiAuth(handleSchedules(expandHome("~/.odek")))) + mux.Handle("/api/schedules/", apiAuth(handleSchedules(expandHome("~/.odek")))) + mux.Handle("/api/maintenance", apiAuth(handleMaintenance(expandHome("~/.odek"), resolved))) mux.Handle("/api/resources", apiAuth(handleResourceSearch(resourceReg))) mux.Handle("/api/sessions", apiAuth(handleSessionListPaged(store))) mux.Handle("/api/sessions/", apiAuth(handleSessionByID(store, resolved.TrustedProxies, wsToken))) @@ -1011,13 +1020,12 @@ func newServeAgent(resolved config.ResolvedConfig, system string, runKey string, EventHandler: func(ev events.Event) { recordPlanUsage(ev) serveEvents.add(ev) + if ev.Type == events.TypeIterationCompleted || ev.Type == events.TypeBudgetExceeded { + sendFn(map[string]any{"type": "runtime_event", "event": ev}) + } }, - ToolEventHandler: func(event, name, data string) { - sendFn(map[string]any{ - "type": event, - "name": name, - "data": data, - }) + ToolDetailHandler: func(event loop.ToolDetailEvent) { + sendFn(map[string]any{"type": event.Type, "name": event.Name, "data": event.Data, "call_id": event.CallID, "outcome": event.Outcome}) }, SkillEventHandler: func(event skills.SkillEvent) { sendFn(map[string]any{ @@ -1183,6 +1191,7 @@ func snapshotServerConfig(resolved config.ResolvedConfig) wsServerSnapshot { // immutable wsServerSnapshot, never from the live resolved config. func wsServerInfoEvent(startedAt time.Time, snap wsServerSnapshot) map[string]any { return map[string]any{ + "capabilities": workspaceCapabilities(), "version": version, "model": snap.model, "sandbox": snap.sandbox, @@ -1195,8 +1204,9 @@ func wsServerInfoEvent(startedAt time.Time, snap wsServerSnapshot) map[string]an // ── WebSocket Types ──────────────────────────────────────────────────── type wsAttachment struct { - Name string `json:"name"` - Content string `json:"content"` + UploadID string `json:"upload_id,omitempty"` + Name string `json:"name"` + Content string `json:"content"` } type wsClientMsg struct { @@ -1236,12 +1246,14 @@ func newTurnID() string { // is active (R3). Lifecycle and sub-agent frames stay untouched so old // clients see byte-identical shapes for them. var turnTaggedFrames = map[string]bool{ - "thinking": true, - "token": true, - "tool_call": true, - "tool_result": true, - "done": true, - "error": true, + "thinking": true, + "token": true, + "tool_call": true, + "tool_result": true, + "runtime_event": true, + "artifact": true, + "done": true, + "error": true, } // wsTurnAnnotator tags outbound frames with the active turn id (R3) so a @@ -1925,6 +1937,20 @@ func handlePrompt( var total int var wrapped []string for _, att := range msg.Attachments { + if att.UploadID != "" { + upload, ok := resolveBrowserUpload(att.UploadID, msg.SessionID) + if !ok { + sendError(send, "attachment unavailable or belongs to another session") + return currSess + } + total += upload.size + if total > maxTotalAttachmentBytes { + sendError(send, "total attachment size exceeds 10 MB") + return currSess + } + wrapped = append(wrapped, wrapUntrusted(ctx, "attachment:"+upload.name, "User-uploaded file: "+upload.name+"\nLocal path: "+upload.path)) + continue + } if att.Name == "" || att.Content == "" { continue } @@ -2112,6 +2138,14 @@ func handlePrompt( } else if auditSessID != "" { ctx = withReadLedger(ctx, auditSessID) } + ctx = artifact.WithObserver(ctx, func(ref artifact.Ref, roots []string) { + if sid == "" { + return + } + if item, err := browserArtifacts.capture(sid, ref, roots); err == nil { + send(map[string]any{"type": "artifact", "artifact": item}) + } + }) _, allMessages, err := agent.RunWithMessages(ctx, messages) latency := time.Since(start) if auditSessID != "" { @@ -3260,7 +3294,9 @@ var staticFiles = map[string][2]string{ "/app.js": {"ui/app.js", "application/javascript; charset=utf-8"}, // Self-hosted font (variable weight 100–700) so the UI works offline and // does not depend on the Google Fonts CDN. - "/fonts/azeret-mono.woff2": {"ui/fonts/azeret-mono.woff2", "font/woff2"}, + "/fonts/manrope.ttf": {"ui/fonts/manrope.ttf", "font/ttf"}, + "/fonts/manrope-LICENSE.txt": {"ui/fonts/manrope-LICENSE.txt", "text/plain; charset=utf-8"}, + "/fonts/azeret-mono.woff2": {"ui/fonts/azeret-mono.woff2", "font/woff2"}, } func handleStatic(wsToken string) http.HandlerFunc { @@ -3351,7 +3387,7 @@ func handleStatic(wsToken string) http.HandlerFunc { // Strict CSP: no inline scripts (all handlers are addEventListener / // delegation), styles only from self + the few style="" attributes in // index.html. frame-ancestors replaces the old standalone CSP line. - w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self' ws: wss:; frame-ancestors 'none'; base-uri 'none'; form-action 'none'") + w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; media-src 'self' blob:; frame-src blob:; object-src 'none'; font-src 'self'; connect-src 'self' ws: wss:; frame-ancestors 'none'; base-uri 'none'; form-action 'none'") w.Write(data) } } diff --git a/cmd/odek/serve_api.go b/cmd/odek/serve_api.go index 03592664..0e6cb4ca 100644 --- a/cmd/odek/serve_api.go +++ b/cmd/odek/serve_api.go @@ -32,6 +32,9 @@ import ( "sync/atomic" "time" + "github.com/BackendStack21/odek" + "github.com/BackendStack21/odek/internal/danger" + "github.com/BackendStack21/odek/internal/config" "github.com/BackendStack21/odek/internal/guard" "github.com/BackendStack21/odek/internal/llmclient" @@ -581,7 +584,7 @@ func handleSkills(sc skills.SkillsConfig) http.HandlerFunc { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) return } - extra := sc.Dirs + extra := append([]string(nil), sc.Dirs...) for i := range extra { extra[i] = expandHome(extra[i]) } @@ -589,6 +592,13 @@ func handleSkills(sc skills.SkillsConfig) http.HandlerFunc { var out []skillSummary for _, s := range append(append([]skills.Skill{}, res.AutoLoad...), res.Lazy...) { + if name := r.URL.Query().Get("name"); name != "" { + if s.Name == name { + writeAPIJSON(w, http.StatusOK, s) + return + } + continue + } out = append(out, skillSummary{ Name: s.Name, Description: s.Description, @@ -599,6 +609,10 @@ func handleSkills(sc skills.SkillsConfig) http.HandlerFunc { Untrusted: s.Provenance.Untrusted, }) } + if r.URL.Query().Get("name") != "" { + http.Error(w, "skill not found", http.StatusNotFound) + return + } sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name }) if out == nil { out = []skillSummary{} @@ -612,8 +626,11 @@ func handleSkills(sc skills.SkillsConfig) http.HandlerFunc { // toolSummary names one tool and whether the resolved tool filter exposes it // to the model. type toolSummary struct { - Name string `json:"name"` - Enabled bool `json:"enabled"` + Description string `json:"description,omitempty"` + Schema any `json:"schema,omitempty"` + Reason string `json:"reason,omitempty"` + Name string `json:"name"` + Enabled bool `json:"enabled"` } // handleTools lists the built-in tool registry with its enabled/disabled @@ -642,11 +659,24 @@ func handleTools(resolved config.ResolvedConfig) http.HandlerFunc { } whitelistActive := resolved.Tools.Enabled != nil + pc := config.DefaultPlanningConfig() + descriptors := map[string]odek.Tool{} + for _, t := range builtinTools(danger.DangerousConfig{}, nil, nil, 1, "", toolConfig{Planning: &pc}, nil) { + descriptors[t.Name()] = t + } out := make([]toolSummary, 0, len(names)) for _, n := range names { // Shared filter rule (introspect.go) — the same one the // agent-facing list_tools tool applies. - out = append(out, toolSummary{Name: n, Enabled: toolEnabled(n, enabledSet, disabledSet, whitelistActive)}) + entry := toolSummary{Name: n, Enabled: toolEnabled(n, enabledSet, disabledSet, whitelistActive)} + if t := descriptors[n]; t != nil { + entry.Description = t.Description() + entry.Schema = t.Schema() + } + if !entry.Enabled { + entry.Reason = "Disabled by the operator tool filter" + } + out = append(out, entry) } writeAPIJSON(w, http.StatusOK, map[string]any{ "tools": out, @@ -799,7 +829,9 @@ func handleMemoryConsolidate(memoryDir string, resolved config.ResolvedConfig) h return } var body struct { - Target string `json:"target"` + Target string `json:"target"` + Mode string `json:"mode"` + Preview memory.ConsolidationPreview `json:"preview"` } if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, 1<<20)).Decode(&body); err != nil { http.Error(w, "invalid JSON", http.StatusBadRequest) @@ -825,7 +857,29 @@ func handleMemoryConsolidate(memoryDir string, resolved config.ResolvedConfig) h t := true cfg.Enabled = &t } - if err := memory.NewMemoryManager(memoryDir, client, cfg).Consolidate(body.Target); err != nil { + mm := memory.NewMemoryManager(memoryDir, client, cfg) + if body.Mode == "preview" { + preview, err := mm.PreviewConsolidation(body.Target) + if err != nil { + http.Error(w, err.Error(), 400) + return + } + writeAPIJSON(w, 200, preview) + return + } + if body.Mode == "apply" { + if err := mm.ApplyConsolidation(body.Target, body.Preview); err != nil { + http.Error(w, err.Error(), 409) + return + } + w.WriteHeader(204) + return + } + if body.Mode != "" { + http.Error(w, "invalid consolidation mode", 400) + return + } + if err := mm.Consolidate(body.Target); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } diff --git a/cmd/odek/serve_artifacts.go b/cmd/odek/serve_artifacts.go new file mode 100644 index 00000000..e5f53cf7 --- /dev/null +++ b/cmd/odek/serve_artifacts.go @@ -0,0 +1,267 @@ +package main + +import ( + "bytes" + "crypto/sha256" + "encoding/hex" + "fmt" + "io" + "mime" + "net/http" + "os" + "path/filepath" + "sort" + "strings" + "sync" + "time" + + "github.com/BackendStack21/odek/internal/artifact" + "github.com/BackendStack21/odek/internal/session" +) + +const previewArtifactLimit = 10 << 20 +const previewCacheLimit = 40 << 20 + +type browserArtifact struct { + ID string `json:"id"` + SessionID string `json:"session_id"` + Name string `json:"name"` + MediaType string `json:"media_type"` + Size int `json:"size_bytes"` + SHA256 string `json:"sha256"` + Created time.Time `json:"created_at"` + data []byte +} +type browserArtifactStore struct { + sync.Mutex + entries map[string]browserArtifact + bytes int +} + +var browserArtifacts = browserArtifactStore{entries: map[string]browserArtifact{}} + +// capture takes an immutable, bounded copy through an allowed filesystem root. +// Later downloads cannot race a tool replacing a file or changing a symlink. +func (cache *browserArtifactStore) capture(sid string, ref artifact.Ref, roots []string) (browserArtifact, error) { + path, err := artifact.Validate(ref, roots) + if err != nil { + return browserArtifact{}, err + } + var data []byte + for _, dir := range roots { + abs, e := filepath.EvalSymlinks(dir) + if e != nil { + continue + } + abs, e = filepath.Abs(abs) + if e != nil { + continue + } + rel, e := filepath.Rel(abs, path) + if e != nil || !filepath.IsLocal(rel) { + continue + } + root, e := os.OpenRoot(abs) + if e != nil { + continue + } + f, e := root.Open(rel) + if e != nil { + root.Close() + continue + } + stat, e := f.Stat() + if e != nil || !stat.Mode().IsRegular() || stat.Size() > previewArtifactLimit { + f.Close() + root.Close() + return browserArtifact{}, fmt.Errorf("artifact exceeds preview limit or is not a regular file") + } + data, e = io.ReadAll(io.LimitReader(f, previewArtifactLimit+1)) + f.Close() + root.Close() + if e != nil { + return browserArtifact{}, e + } + break + } + if data == nil || len(data) > previewArtifactLimit { + return browserArtifact{}, fmt.Errorf("artifact unavailable") + } + digest := sha256.Sum256(data) + sha := hex.EncodeToString(digest[:]) + if (ref.SHA256 != "" && ref.SHA256 != sha) || (ref.SizeBytes != nil && *ref.SizeBytes != int64(len(data))) { + return browserArtifact{}, fmt.Errorf("artifact changed during capture") + } + // Content sniffing determines display type; never trust an extension's MIME. + media := http.DetectContentType(data) + item := browserArtifact{ID: newTurnID(), SessionID: sid, Name: filepath.Base(path), MediaType: media, Size: len(data), SHA256: sha, Created: time.Now().UTC(), data: data} + cache.Lock() + defer cache.Unlock() + if cache.entries == nil { + cache.entries = map[string]browserArtifact{} + } + for cache.bytes+len(data) > previewCacheLimit || len(cache.entries) >= 128 { + var oldest string + var when time.Time + for id, v := range cache.entries { + if oldest == "" || v.Created.Before(when) { + oldest = id + when = v.Created + } + } + if oldest == "" { + break + } + cache.bytes -= len(cache.entries[oldest].data) + delete(cache.entries, oldest) + } + cache.entries[item.ID] = item + cache.bytes += len(data) + return item, nil +} +func handleBrowserArtifacts(store *session.Store, cache *browserArtifactStore) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + http.Error(w, "method not allowed", 405) + return + } + sess, code, msg := authenticateJobsRequest(store, r) + if code != 0 { + http.Error(w, msg, code) + return + } + id := strings.TrimPrefix(r.URL.Path, "/api/artifacts") + id = strings.TrimPrefix(id, "/") + cache.Lock() + if id == "" { + items := []browserArtifact{} + for _, item := range cache.entries { + if item.SessionID == sess.ID { + items = append(items, item) + } + } + cache.Unlock() + sort.Slice(items, func(i, j int) bool { return items[i].Created.Before(items[j].Created) }) + writeAPIJSON(w, 200, map[string]any{"artifacts": items, "retention": "Preview cache: up to 40 MiB, cleared on server restart. Save files you want to keep."}) + return + } + item, ok := cache.entries[id] + cache.Unlock() + if !ok || item.SessionID != sess.ID { + http.Error(w, "artifact unavailable", 404) + return + } + w.Header().Set("X-Content-Type-Options", "nosniff") + w.Header().Set("Content-Security-Policy", "default-src 'none'; sandbox") + w.Header().Set("Content-Type", item.MediaType) + w.Header().Set("Content-Disposition", mime.FormatMediaType("attachment", map[string]string{"filename": item.Name})) + http.ServeContent(w, r, item.Name, item.Created, bytes.NewReader(item.data)) + } +} + +// Uploads are addressed by opaque IDs in prompts. Client-supplied paths never +// become attachment paths; only the server-created, session-bound file is used. +type browserUpload struct { + sessionID, path, name string + size int +} + +var browserUploads = struct { + sync.Mutex + entries map[string]browserUpload +}{entries: map[string]browserUpload{}} + +func handleBrowserUpload(store *session.Store, model, workspace string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "method not allowed", 405) + return + } + var sess *session.Session + if r.URL.Query().Get("session_id") != "" { + var code int + var msg string + sess, code, msg = authenticateJobsRequest(store, r) + if code != 0 { + http.Error(w, msg, code) + return + } + } + data, err := io.ReadAll(http.MaxBytesReader(w, r.Body, 5<<20)) + if err != nil || len(data) == 0 { + http.Error(w, "upload must contain 1 byte to 5 MiB", 400) + return + } + name := filepath.Base(r.URL.Query().Get("name")) + if name == "" || name == "." || len(name) > 200 { + http.Error(w, "invalid filename", 400) + return + } + // MIME is inspected from bytes. Store only passive media/document types; + // executable formats and HTML cannot be introduced as media attachments. + media := strings.Split(http.DetectContentType(data), ";")[0] + switch media { + case "image/png", "image/jpeg", "image/gif", "image/webp", "audio/mpeg", "audio/wave", "audio/x-wav", "audio/ogg", "application/ogg", "application/pdf": + default: + http.Error(w, "unsupported binary attachment type", 415) + return + } + if sess == nil { + sess, err = store.Create(nil, model, "Uploaded files") + if err != nil { + http.Error(w, "cannot create upload session", 500) + return + } + } + browserUploads.Lock() + defer browserUploads.Unlock() + if len(browserUploads.entries) >= 128 { + http.Error(w, "upload limit reached for this server; restart to clear upload handles", 429) + return + } + id := newTurnID() + suffix := map[string]string{"image/png": ".png", "image/jpeg": ".jpg", "image/gif": ".gif", "image/webp": ".webp", "audio/mpeg": ".mp3", "audio/wave": ".wav", "audio/x-wav": ".wav", "audio/ogg": ".ogg", "application/ogg": ".ogg", "application/pdf": ".pdf"}[media] + rel := filepath.Join(".odek-artifacts", "uploads", sess.ID, id+suffix) + root, err := os.OpenRoot(workspace) + if err != nil { + http.Error(w, "upload storage unavailable", 500) + return + } + defer root.Close() + if err = root.MkdirAll(filepath.Dir(rel), 0700); err != nil { + http.Error(w, "upload storage unavailable", 500) + return + } + f, err := root.OpenFile(rel, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600) + if err != nil { + http.Error(w, "cannot store upload", 500) + return + } + _, err = f.Write(data) + closeErr := f.Close() + if err != nil || closeErr != nil { + _ = root.Remove(rel) + http.Error(w, "cannot store upload", 500) + return + } + full := filepath.Join(workspace, rel) + browserUploads.entries[id] = browserUpload{sessionID: sess.ID, path: full, name: name, size: len(data)} + digest := sha256.Sum256(data) + size := int64(len(data)) + ref := artifact.Ref{Schema: artifact.SchemaArtifactRef, ID: id, URI: "file://" + full, MediaType: media, SHA256: hex.EncodeToString(digest[:]), SizeBytes: &size} + if item, e := browserArtifacts.capture(sess.ID, ref, []string{filepath.Dir(full)}); e == nil { + browserArtifacts.Lock() + saved := browserArtifacts.entries[item.ID] + saved.Name = name + browserArtifacts.entries[item.ID] = saved + browserArtifacts.Unlock() + } + writeAPIJSON(w, 201, map[string]any{"upload_id": id, "session_id": sess.ID, "auth_token": sess.AuthToken, "name": name, "media_type": media, "size_bytes": len(data)}) + } +} +func resolveBrowserUpload(id, sid string) (browserUpload, bool) { + browserUploads.Lock() + defer browserUploads.Unlock() + item, ok := browserUploads.entries[id] + return item, ok && item.sessionID == sid +} diff --git a/cmd/odek/serve_runs.go b/cmd/odek/serve_runs.go index 77a1f7a1..6b12a3df 100644 --- a/cmd/odek/serve_runs.go +++ b/cmd/odek/serve_runs.go @@ -568,6 +568,7 @@ func (r *serveRun) snapshot(includeEvents bool) map[string]any { "id": p.ID, "risk": p.Risk, "command": p.Command, "description": p.Description, "allow_trust": p.AllowTrust, "friction": p.Friction, "friction_approvals": p.FrictionApprovals, + "requires_confirmation": restApprovalFrictionEnabled || p.Friction, }) } out["pending_approvals"] = pending diff --git a/cmd/odek/serve_test.go b/cmd/odek/serve_test.go index edb24323..4883fb63 100644 --- a/cmd/odek/serve_test.go +++ b/cmd/odek/serve_test.go @@ -1272,8 +1272,10 @@ func TestServe_E2E_MultiToolCall(t *testing.T) { var events []map[string]any var sawSession, sawToken, sawToolCall, sawToolResult, sawDone bool var toolCallCount, toolResultCount int + callIDs := map[string]bool{} - for i := 0; i < 15; i++ { + // Additive protocol frames may precede done; the read deadline bounds the wait. + for i := 0; i < 100; i++ { var raw []byte if err := golangws.Message.Receive(conn, &raw); err != nil { t.Fatalf("Receive event %d: %v (collected %d events)", i, err, len(events)) @@ -1294,9 +1296,18 @@ func TestServe_E2E_MultiToolCall(t *testing.T) { case "tool_call": sawToolCall = true toolCallCount++ + id, _ := evt["call_id"].(string) + if id == "" || callIDs[id] { + t.Fatalf("tool call has missing or duplicate identity: %v", evt) + } + callIDs[id] = true case "tool_result": sawToolResult = true toolResultCount++ + id, _ := evt["call_id"].(string) + if !callIDs[id] || evt["outcome"] != "completed" { + t.Fatalf("tool result lacks correlated successful outcome: %v", evt) + } case "done": sawDone = true goto multiDone @@ -1662,7 +1673,8 @@ func TestServe_E2E_LiveToolEvents(t *testing.T) { var eventOrder []string var doneAt time.Time - for i := 0; i < 10; i++ { + // Additive protocol frames may precede done; the read deadline bounds the wait. + for i := 0; i < 100; i++ { var raw []byte if err := golangws.Message.Receive(conn, &raw); err != nil { t.Fatalf("Receive event %d: %v", i, err) diff --git a/cmd/odek/serve_workspace.go b/cmd/odek/serve_workspace.go new file mode 100644 index 00000000..acd8d2b3 --- /dev/null +++ b/cmd/odek/serve_workspace.go @@ -0,0 +1,142 @@ +package main + +import ( + "encoding/json" + "net/http" + "path/filepath" + "strings" + "time" + + "github.com/BackendStack21/odek/internal/config" + "github.com/BackendStack21/odek/internal/maintenance" + "github.com/BackendStack21/odek/internal/schedule" +) + +// workspaceCapabilities is additive: clients must tolerate missing features. +func workspaceCapabilities() map[string]any { + return map[string]any{"version": 1, "features": map[string]bool{"media_uploads": true, "artifact_previews": true, "tool_identity": true, "tool_outcomes": true, "skill_review": true, "schedules": true, "maintenance": true, "tool_schemas": true}, "result_renderers": []string{"code", "diff", "terminal", "search", "json", "sources", "text"}} +} +func handleCapabilities(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + http.Error(w, "method not allowed", 405) + return + } + writeAPIJSON(w, 200, workspaceCapabilities()) +} + +// handleSchedules shares the CLI store and file locks. serve manages definitions; +// a scheduler daemon or Telegram host executes them and publishes runtime state. +func handleSchedules(home string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet && r.Method != http.MethodPost && r.Method != http.MethodDelete { + http.Error(w, "method not allowed", 405) + return + } + store, err := schedule.NewStoreAt(home) + if err != nil { + http.Error(w, "schedule store unavailable", 500) + return + } + id := strings.TrimPrefix(r.URL.Path, "/api/schedules") + id = strings.TrimPrefix(id, "/") + if r.Method == http.MethodGet { + jobs, err := store.List() + if err != nil { + http.Error(w, "cannot read schedules", 500) + return + } + states, err := store.LoadState() + if err != nil { + http.Error(w, "cannot read schedule state", 500) + return + } + if jobs == nil { + jobs = []schedule.Job{} + } + next := map[string]time.Time{} + for _, j := range jobs { + loc := time.UTC + if j.Timezone != "" { + if l, e := time.LoadLocation(j.Timezone); e == nil { + loc = l + } + } + if expr, e := schedule.ParseInLocation(j.Cron, loc); e == nil { + next[j.ID] = expr.Next(time.Now()) + } + } + writeAPIJSON(w, 200, map[string]any{"jobs": jobs, "states": states, "next": next, "execution_host": "schedule daemon or Telegram"}) + return + } + if r.Method == http.MethodDelete { + if id == "" { + http.Error(w, "schedule id required", 400) + return + } + if err := store.Remove(id); err != nil { + http.Error(w, err.Error(), 400) + return + } + w.WriteHeader(204) + return + } + var job schedule.Job + dec := json.NewDecoder(http.MaxBytesReader(w, r.Body, 64<<10)) + dec.DisallowUnknownFields() + if err := dec.Decode(&job); err != nil { + http.Error(w, "invalid schedule", 400) + return + } + if len(job.Task) > 32000 || len(job.Name) > 200 { + http.Error(w, "schedule too large", 400) + return + } + if id != "" { + old, found, e := store.Get(id) + if e != nil || !found { + http.Error(w, "schedule not found", 404) + return + } + job.ID = id + job.CreatedAt = old.CreatedAt + err = store.Put(job) + } else { + job.ID = "" + job.CreatedAt = time.Time{} + job, err = store.Add(job) + } + if err != nil { + http.Error(w, err.Error(), 400) + return + } + writeAPIJSON(w, 200, job) + } +} + +// Maintenance uses only the operator-resolved policy; request bodies cannot +// broaden retention or choose a filesystem root. +func handleMaintenance(home string, resolved config.ResolvedConfig) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodGet { + writeAPIJSON(w, 200, map[string]any{"policy": resolved.Maintenance, "description": "Cleanup uses the server's retention policy. Zero retention keeps that category indefinitely."}) + return + } + if r.Method != http.MethodPost { + http.Error(w, "method not allowed", 405) + return + } + var body struct { + Confirm string `json:"confirm"` + } + if json.NewDecoder(http.MaxBytesReader(w, r.Body, 1024)).Decode(&body) != nil || body.Confirm != "cleanup" { + http.Error(w, "type cleanup to confirm retention cleanup", 400) + return + } + report, err := maintenance.Sweep(r.Context(), filepath.Clean(home), resolved.Maintenance) + if err != nil { + writeAPIJSON(w, 500, map[string]any{"error": "cleanup partially failed", "report": report}) + return + } + writeAPIJSON(w, 200, report) + } +} diff --git a/cmd/odek/serve_workspace_test.go b/cmd/odek/serve_workspace_test.go new file mode 100644 index 00000000..0dae630d --- /dev/null +++ b/cmd/odek/serve_workspace_test.go @@ -0,0 +1,141 @@ +package main + +import ( + "bytes" + "encoding/json" + "net/http" + "net/http/httptest" + "net/url" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/BackendStack21/odek/internal/artifact" + "github.com/BackendStack21/odek/internal/session" +) + +func TestWorkspaceSchedulesCRUD(t *testing.T) { + h := handleSchedules(t.TempDir()) + call := func(method, path, body string) *httptest.ResponseRecorder { + r := httptest.NewRequest(method, path, strings.NewReader(body)) + w := httptest.NewRecorder() + h(w, r) + return w + } + body := `{"name":"Daily review","cron":"0 9 * * 1-5","task":"Review changes","deliver":{"kind":"log"},"enabled":false,"timezone":"Europe/Berlin"}` + w := call("POST", "/api/schedules", body) + if w.Code != 200 { + t.Fatal(w.Code, w.Body.String()) + } + var job map[string]any + _ = json.Unmarshal(w.Body.Bytes(), &job) + id := job["id"].(string) + job["enabled"] = true + b, _ := json.Marshal(job) + if w = call("POST", "/api/schedules/"+id, string(b)); w.Code != 200 { + t.Fatal(w.Body.String()) + } + if w = call("GET", "/api/schedules", ""); !strings.Contains(w.Body.String(), `"enabled":true`) { + t.Fatal(w.Body.String()) + } + if w = call("DELETE", "/api/schedules/"+id, ""); w.Code != 204 { + t.Fatal(w.Body.String()) + } + if w = call("POST", "/api/schedules", `{"cron":"invalid"}`); w.Code != 400 { + t.Fatal(w.Code) + } +} + +func TestWorkspaceArtifactCaptureIsImmutableAndScoped(t *testing.T) { + dir := t.TempDir() + file := filepath.Join(dir, "result.txt") + if err := os.WriteFile(file, []byte("original"), 0600); err != nil { + t.Fatal(err) + } + cache := &browserArtifactStore{} + ref := artifact.Ref{Schema: artifact.SchemaArtifactRef, ID: "a", URI: (&url.URL{Scheme: "file", Path: file}).String(), MediaType: "text/plain"} + store, err := session.NewStoreWithDir(filepath.Join(t.TempDir(), "sessions")) + if err != nil { + t.Fatal(err) + } + a, err := store.Create(nil, "fixture", "A") + if err != nil { + t.Fatal(err) + } + b, err := store.Create(nil, "fixture", "B") + if err != nil { + t.Fatal(err) + } + item, err := cache.capture(a.ID, ref, []string{dir}) + if err != nil { + t.Fatal(err) + } + _ = os.WriteFile(file, []byte("changed"), 0600) + h := handleBrowserArtifacts(store, cache) + req := httptest.NewRequest("GET", "/api/artifacts/"+item.ID+"?session_id="+a.ID, nil) + req.Header.Set("X-Session-Token", a.AuthToken) + w := httptest.NewRecorder() + h(w, req) + if w.Code != 200 || w.Body.String() != "original" { + t.Fatalf("%d %s", w.Code, w.Body.String()) + } + req = httptest.NewRequest("GET", "/api/artifacts/"+item.ID+"?session_id="+b.ID, nil) + req.Header.Set("X-Session-Token", b.AuthToken) + w = httptest.NewRecorder() + h(w, req) + if w.Code != 404 { + t.Fatal(w.Code) + } + if _, err := cache.capture(a.ID, ref, nil); err == nil { + t.Fatal("accepted artifact without allowed roots") + } + ref.SHA256 = strings.Repeat("0", 64) + if _, err := cache.capture(a.ID, ref, []string{dir}); err == nil { + t.Fatal("accepted wrong digest") + } +} + +func TestWorkspaceUploadRejectsExecutableAndBindsSession(t *testing.T) { + store, err := session.NewStoreWithDir(filepath.Join(t.TempDir(), "sessions")) + if err != nil { + t.Fatal(err) + } + workspace := t.TempDir() + h := handleBrowserUpload(store, "fixture", workspace) + req := httptest.NewRequest("POST", "/api/uploads?name=script.html", strings.NewReader("")) + w := httptest.NewRecorder() + h(w, req) + if w.Code != http.StatusUnsupportedMediaType { + t.Fatal(w.Code, w.Body.String()) + } + // PNG signature is sufficient for MIME detection; bytes are never executed. + png := []byte{137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 0} + req = httptest.NewRequest("POST", "/api/uploads?name=image.png", bytes.NewReader(png)) + w = httptest.NewRecorder() + h(w, req) + if w.Code != 201 { + t.Fatal(w.Code, w.Body.String()) + } + var result map[string]any + _ = json.Unmarshal(w.Body.Bytes(), &result) + id := result["upload_id"].(string) + sid := result["session_id"].(string) + upload, ok := resolveBrowserUpload(id, sid) + if !ok { + t.Fatal("missing upload") + } + rel, err := filepath.Rel(workspace, upload.path) + if err != nil || !filepath.IsLocal(rel) || filepath.Ext(upload.path) != ".png" { + t.Fatalf("upload is not accessible inside workspace: %s", upload.path) + } + if data, err := os.ReadFile(upload.path); err != nil || !bytes.Equal(data, png) { + t.Fatalf("upload bytes unavailable: %v", err) + } + if _, ok := resolveBrowserUpload(id, "different"); ok { + t.Fatal("cross-session upload accepted") + } + if strings.Contains(w.Body.String(), store.Dir()) { + t.Fatal("leaked storage path") + } +} diff --git a/cmd/odek/ui/fonts/manrope-LICENSE.txt b/cmd/odek/ui/fonts/manrope-LICENSE.txt new file mode 100644 index 00000000..472064af --- /dev/null +++ b/cmd/odek/ui/fonts/manrope-LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2018 The Manrope Project Authors (https://github.com/sharanda/manrope) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/cmd/odek/ui/fonts/manrope.ttf b/cmd/odek/ui/fonts/manrope.ttf new file mode 100644 index 0000000000000000000000000000000000000000..23dcf5e05a97f19a3567d40ebb3765580a4325f7 GIT binary patch literal 165420 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

Q@0Oydeq;k*5RD1yqZfxX(;~_mV*z>&_`@e=WB2 zimI8qeS%xPG)}dt!`T`m!zo!eO0~i{nW}LYt!l?iaZc~Mmy#h6@Om@_!YI`_9 zS5)DYu3~JEjb~eh^L1r-5!O)V7b(N(>(iAL%5oOL0+d*K-t?2{BE6!7@R3Di?max+ z4EXp4f_#yjgq^=&N_0Nm*PAZRGkvUtv4nkc`JEr+AcWM=3;v84OLN6U%ag1P*Dx>J zJkD{y6>Z&wr42rMoD!;yD_NSMeyVq#Y1a@Rv)c*QO<}YIHtJ}JlX}%v*!srUB0g04 zHchExbnBLNQ)a9{4NE0PodqRUS*8Tow83r9LhAT77mN*<;t zX@2cZRuw9}mm5)=o~uc>bjF4w>ML0C6c^Kk`saA3YxE7DHuFM*8k*+gayr+yp~XBc zjR?sC2Am5T)X=2o%S`93p5^<8&s!b^1+c;*RAgV7dwexan2a@=}-7xjX8v1?9`0qhI=HqKRliGHs#pum7ubbZ;+@BX}D>k zHiTyh0y^Rky6%XQXz>Rc&6WZ>qE0M?wM8^9Oq~0}Dc-Jk3os!z%8mgzatZ}ynXX@SiRLtD0;(K{o@-Hk@1FYXi(7so;h`t*Ll zr=?%B4kL$kjB7P;SVCf}9%0InhkbhW8k`vyoZh0Pd&?H?_eDn}n(-P9yqY6IKoAuH zUObu6kE5VQnmBml!gcHCFIrc=&^Ua=h>_VNSV-m4Wl!%~vTWDL*`vqIoHcq(3HlDr zEN|CgCmb{vZyT|FIZJ0bi;JJIVL9W7cPz49xY|zywh(s?FPAb*9`v|_BfyqC{O}U( z05GHCXMF~kQI><=U%2SKAe{sZIK(o60isI40-vQ?V1Oi1WM%?>xiq`>imp;U-9!8; zYRhu{D%K46J@hlKCCBnR&1I(f{h~G5OW&JkN~1M+9lX7+#@e&G%F3JKypZfVFI@rP z`S5)EKyRF^k(}h?lN=6?iUha$f&hBPOS@)|osrne-OI`GLb zZiclxv2LZF1`qkMiAt4g=Zn*itxhLV8&QvZ*IS)TVwRXnaAY&CC&l_BFD^p4En;bF zH)blEHbe<=AFa6)PjhQx;yq7#-6>D>xnEOn?F4_+N+=3RM*_?)8ZZ`4J=slfOh zlb0rShk=7CbsV;Lxg2GzT?Hbb>6)Wj&!K7X%q&YAv7!xNj^Dw>yru$v=jZAO+nQ@C z-e$P3W|i))F#VZFtLWuCQxQ#)r{B3Ld(;#VjJD8g810stj z=l!cbSibDT72R93=)U5^Wy?QUb-$-Zr740+PYEh)Q|hX!Sc+ry3Jx?4DV1E+Ndwj`i-=XU#8L=^ACn{38o`jObP>bp|2%sz!khe8z2I zT_V?s{EGM2$#>Qmr3&Nb%1R9BQ9h(M)p6Gw)w{VQnC}PUPT~KXZ^i8eTq5fV^grNk z9oJO4#7Gd3SLQK4rQcj$eS44gXl14GrUjIEp5x}FBPz6d+_0pv!*ty!oi>`TU%#$F zEV#~jg42f2ZQ99}fMj#FrI^{oT8%cf86D1RHb+~UPS{OsHYZ!wT?534fXG)cpc^os zGy=2oD0OQT>JXy~u$r`X2GnS}h;Zwxr>sh;U){glqVatUT_l~yFM2u+2#T4<@Fu=D zAmbPQtQa{y-|(?$ghEnw?O`dXNrW=iLKnM0T-brgk->>+kooz*kCO4wD@M#cm@)b3 zoS2xS;^PQbyrW{G^~``-F@UdR1qMX%8dmJ5ua)mM>U5iE$QRdWMpABj<)<%R{{3MC z3o%`h5{C?~diVqlN-#zos0lqqjbB`%!;UF;{^R-KC5i1)uD)iR`}LH9tAD$Q<&7uu@8R@?yK2G)t48UfEz1wOIL>Lok;E9K;20xG> zVRuf5;o;w3{zCbweQpvR^z#=qWRp&}L8%Iz{n-;iC%%$ce&Lj_=Nez5!Mm7r=|j)| zP~9=*rAuEZ2eEgIRDuei8tBoJ>qK=gnZXU8dkY;&>aMWU;`a>P$#ALCFY$bQzPqm- z&!-T<6DVP^l~8X;##!%{8ByPqCK8S z*YxeX=F1B6Yw4kRsg(7Y|8gnb^xyJJfkTubm>>L#rh{`^RJdH`AYfYi7m>F zFUpL?Z(U!x^4B+ui{Jcp<;v@C6@z=T(dQH(sGXt;J0Ki(iP&lejKX2|1h(@I$7XG= zkOjNM%PB_F1+R*I>XEg~r*=^x?VbToKHaOU`RLlNUaYrg*bm$Jv9&s>rhqL^%4DxY z+O?x=Wf}Z|fAVI)4%eg`Qp2f0yg>sPMwY5b+#~QVF9+3+r(NCh2W>w6{GO#p3kr^} zul)QzUjrw+l2kH9`9t~7zB*E2EWKE{{p7eMkN4lyPl*B_a5$b~oOj@@YSrceF0{O_ zlM$|NIJ}iE#+GwBW^m9`oS@8CcN;sUdWF2hw8!OHxZ;?-)W(m(1?Q$>p2FJTU?S<{hqsDrqU0Ac}o6-fB|MuaTuTPvfdnR-l z_4sn+`}?~-@M!y(PQkt{vYYvZc8*N=ZrkKJkNmcK_pd9Bf1dvQx8FYh?03yaIEM&A zE7&*Kttz&w`&luKzOr$cKR`?GJ z8Qgz*eo$hdQbFei_G{gzXL?$PF&@f6xx3z@)zby>W1@W8G}8yiEXTl)t2G-K-vjkUW= z*=i+3ZsFa^+b0Sh+x)T-C#l~jwIQklCsm9(b?Q*hUK2Tw30@Gq@v-1Bl{ad@D_?_G z)O^X(QqcodoY&<=I5SR5OPf`1ThqI&X+k4+>{~FZ|qZ zKY#64E`w{era|z}x)y0#J7)^__j0}U1c=(=Luvu-s zw1-P9Bwsp$QE18iAA8@9*QHZiVC}6ee>%wAoK;rAD#tDJNHdRz!Mn3+?SA-oG~C<@ z7+1M*)b@FmgU_NT?&{2`dE_vSE&Fig?xtIIdwS8EvqDOs71d~m#h0f)@{mVg>*qCz zv2BHWguh9r0XYDW69a?-v+@X8Y|pfiX5PVp9_&@4>1H#(fS?wh?envnw;SGl>aVop zd+5lOM}9x|Vy^+CLe&wG52G~?(GP^%1yQMYc@8~BkL4JZ+4;(B3`ke$ES{WQTfr}F zB!9qjJgTl)`NA(WvZJs%h9C*jlis*@7RQlZHkN7gtx&<*-Dx&O1BerO2b4Jfww-2+fq@1AW@RcjVU?C z+krP(u~Vtpv4iS&8h29tjvY$PPUEos8%K}cxc@orb(oSy54I|!9v^%_Jr}j2*~;No zipb6K62#JSAI+l5Ezr7Y%H zDMzkfS7F^bb=|COxGZ>M^hms9I3K)~l@i zvP)oKc&E^WM<|1;qF+&J&!FQ2)wmuwAchaRux?>$Mm5_5uFMGuVgom8h*b}aY`n0Yo5M*>iSLo z?sC1hnf?J^@MRiq^6_bIfUkC=g3UfzP@BcxtCwY53g_ zo3kX-#~!DSYsH2Uw|>b|Z20CWzjD z>c~3us}j9Yz1)A{on)?}cbl&!P~s#N4dU~v>r z9L3P{>_yBnRCv)s-|)&)oOqnsxS`>exNp+#&)aIV%=24E?!BMu7GwQ9bDyytpJz;` z&=$r*wIlFO?DA6mS{J*mc1T7g%h4t#p2KXq?s{vL%4s4CJe1e<1gG(FM@=^GszMFTTDA-tyKWrvzaM)vC~n2Vp;JD3eCn>eOYaX^ISeV{ zo7;G}H8Zq65&G=Hu%R7T1yaC!O-LH~?EJN_ySdBvjely^ykoO+MsAt3BLo3qpHx$mw^GQ_3w=ogSR)(0>U~{g(?ydO`DF0*p$4@L#S< zD{7arU{MYy*mM=|u8P(d$tjR}1D%8%?ydMn%dCcFgE%L6Le1m3mki}NEB~Rd!^|Qp zU!sW_%1zCu?F(;XrbC#*^KhMS2r6(N>8#L>zYD5!+hQ}M1zAg4bc7zxr)%<*J<9G} zVP7AwS?tf9Ec7ePcaCBH{MMRhT z#*vB6^V_A$YE=Jm)K4r0xJ+{wBYRoQ)mr5rU&${39GsMh+*rOQl89y9NMzB6tKTOE zB7P&5N_@|-T@P9n{?X-R=}lkQ6#jvm7F1vQhy8Nr6q4&r(d(YGl>T8qARbVL)s2aw zw>*zutQ7J7(k5e~TTyMSIngLOAVyO#(#8+gD#qi87!NTk>MB7kUR_;yWsT2`uxCy< zogH~7tdEj}(?jS54KH zz#a;}@#RJ>M##BWw4trP7Xl_$L%^+j%-mbQrU{zZMMQb#iG(!>?ws*>zwpfBlDN^p zCnsjm`vlN0utoTP5)nn8E74QcDiX1Ov3hkcF-`Ql!P;%5==X3yP;LFgI?e?K?)Qip zl2a5H)@<)o$x*ev5voIox(1Fq59xB>TB8oAmusOOTEPg-w0zDIP-X#&@ZULgMbsdX z^2WodKaLPCXY);KWiM#&DW>gGel}Z0ySb$SXayH~;l!P)LC8youUKPigbfGr-L`AQ~?dX2fFQFwFV>aY4 zWi5KkvC6=YG8eH)ZGD6<69@XI(vA6a>(VsO8br76Z@ntgFA)xSS;=KD&`){DyFVx#fCgOoh~$ggkAnD*MwD_5L* zc2=mMoLQ!#fe%&z+4(wOB@Gng-(LeoVju@_V)-x1%jREn>%}iAyW>a{q@h7Er0DKa3_|3 zeZ~vckR?3*zd1XcYorj^3c_Ny@ut8W{G4YV-nTjALTsj<@x@cG{@lthE6cCduSczp zxWHy=_Dm&ZTfcrYi6Uv29!z@s8=E68xUGo&p!HSK3X&do&5 zF{&*O*?t$~<~H>e)QI90i$nM-1fMgw@fesGr>6W^FN9EJlH)hw`1o^=hv&wD-$gyJ z`QJUI)&u+G?|=W~(~mx-BYQsg)YRzAq^LeEXoa$(b)0`fdXG8JP7QhFm!~UltZ?&u z^!n4gu0LwL{psoJw@!WfhqTE5zFyNub{m@9qM0;Ar}IdS>yVzD6vj0U_m1~sMAhiE zx*%v!G37ox-a>67gcbk)arZ57RaN=^Yps3G;VCZ_@DTwb_{75-4N;yxLPI<%A}S~d zC;}lWKEr2Lre9>uYJ~MfAesy*6yu8@rQ47{AukW{E zhfal`cFekqG{{-Gz3T_JF&>~nbax+%u`EfW1I(|uX$5XQ#xxY?KC)qA|COtHt$TV- zQ@$2DprWQ?Qjevph7=sx;5Ky3^&?7Rd>SVf4e{|EdFRUXyHDNGd*ktPhhxzE1(o?d z8;;zOQL!jSTCAQUSItBDp$8yMcDkI#<#*9?5Zp<_-WbTi#+axbm%4Hdw?X^CX)zaW z&1VM-xcaK!)h*wmoOU&TtwuvmBH6#~0aa3N-rZ&km$zqET!$m7vU^a5eeleFq3I($ zJ<^Bckg9sSDLUIRU|@fnMf1pYbE6&tsl`2RB;`DW+KPIB_vcVsv8OIhVnv$PE-0&m zure%j<%X!lNsic*?y+4*O-&6oq+UyM*~U>hn$@><&s0oeL;U4F4DD5cQmib{Tm-6d z9G1E1aAuzb79XQ9BiS;39*>dpl4p{s-MO5_9RK61hstKop59bXw1O9t zJwN@K2ezF$yesI&5mt|GBgR%gUQ+kxU%HK)5SlV4&bP6)w8y;P)Ng+>WWeJ~3U4bI ze0WRvs?B$7Uc230N{6Od<5t!!*)a;$$z#OoN}}2rQ-f;iS@fM*G&c#3O;R=1Zox4z zw;tSRd9u-gox(i1PLr&{;ClT`PTR`$coGH)ZsB*-JgHR%Zq%el)u}t~f3u?U&3o3p zWS6yu`i?!hH|?RV>WMjlx4pmIyqBxKsA-O=yJOi0cW(T+!EA?E3m`d{ayBa3VyG%K zvJ{MoiqmX_owYy=${sh~vpjgzjUgjT>^_YPii51y zn-<^N5dEU`y8Vt-xTx!vkM6i(=eA;MduglYBDIuPnCQU#zA^LU!VQyjz4H3Z6E?IU zwa}BeChuT zZgNQLJ8wygl*`_`^}N%G(ui&TnpZh`wzenYG-3LoZ?jFQ1Kg(c)sL2jl{V6BSSulf zt!~q_B#)LqMOu1YQUAO7Xnk;IsGe)TV@=@@N95Rfx8?EJO@3(}Moz3gut23W9VvQv z<&QgnQA$OIHORAZR9sJU^G11WnyUM1tW$0R#$gytuDU> zE!tP)DB8Cuh$Xo2Rlh+{a*sCUuBoGIdaG3DfbfRYqI>hD#rES5GXLJ9)P`_*zUgG| zn$eEC3N>e;UTZ$F?m?}==uPkC0x+A(+emmYNld`dupdviQK1g&d>{^2GMr!cxZ~+F zgMR&swDo1>^ZGg>=2cXz8~M;vgU%kFd~o%mgWW>A9t^$Z;ys_pp=INzJOBH{k{4@c z?JATZ&Wlrbl`eR3(M!^M+V~3R>EGXbam6j`*4={I#JrN%15vu9qq=Ly9PB41=TBg#Fx~BI#s%wjuQ6qTOJ%cnYz47FR2jZ%s=V_{Q&das3lTCsCLDo!`e0EK>PM<^V&GZFRk3}V;wd&{!qCKS@OUM-<>k(WY(V3LY)O`N) zqO#6MwY^M3ObZ3qAk!%YQnp=|yG;bH?Z%ycn<&h1}M(O9UrtY4#8^a^G!7K;Pv>vDS9G4_rMlgL$(ms zqSWrf#94bv%J$53EIG4m<(Wl&#-%nD1#7f-cjA2oC3|L-JX*Z$wR-%^TVI#lv@^wl z7)Z`O0xFFDjh2Y?WjUI%$5njP`QXTvg|;Tyq;u}Ur6J=79jm{2=Y$s@9#}dcR?X_! zq_mKx^J=%0_f)+clD%$v?%1pv5|#;dSv6dS|e4K5X6aH z5wwzzSxbF+w~s#p%9f3VPCqrnaqyswby#}-_?bNEOm#TVvQPBK-Qbht0JJjK(+o^+ zR~npat$SK*D!%sk+TOWAbq`Lt`Kj`%BXesHB~BisE;WUu4hl^>wP4K$YgT^{GX0VA zz-jA7&p$G+=BbLxf>`ybV^~viw4-G82WwY#GHeY;L}8|wZoJ^y0`4)Gb@W( zSE#B~uKi&3st?w!{r&LKalfttDWM}S-T^yA0HWp|sbUPltLhEwwUq;=&WDwATjauf zU4=>D4<=zVOgPFPz+Y z=MzudiT@#Uo?E@;y_o1;uhcKvH+Aa1MfETD8Wi*1metSAaU9zH=wpvPy8Dp&=B_*M z+`ReDJMRKdKznP=QQXp_H#3qUQ3v%7I>?yTrQxX|PVxujY)g)QlsY=@>G_N$YX$p0P=(A+F5QL)aU1l?4K_=e@Dy%_7+ zL4i$OpH6+vUQpyoWvoIc)B7%bFW~pE6nfu=@0t7_Zl`x6PnAu9hvEGz)RD{h?xrHd zgKYCOd_-^zeN(Tf*Z=xb;52-$&S~3m=Hdn+nm&aMamqSvEo@Q@8}LPSP}>0;%&xMV z+~zM;1G_=8*oNGkVw(}B4cr`Mn~{di#^%pdBgd6yh67*Y*-g4(Qx7*s*i8o6aLr|3 z;01#~Sw}UO&Jh~JKdQMjPr(gJ9-nkaUf#z1n{FMD9#WE$Hs^-WzIQkr8*(S!;h4T^ z)pY#Vw&&eB#d)G&Q{I^2@%CX@sQN1M#%Z~?PITO!m%C>Av{kF7O<%($haKzZtcOus zN!}uvqkVq`3!WuGXC)8itr<6NO`eXEmoA+=Y1uMmfsLH2+c~%6nY(O~teIS2KiRou z(lY9!RBu^F^$RihyCo!{j|x9YI`rVHpN~*dUMRi@gM#}Qk@wv|D5(9_dIcv(Au||4MAvW|*GQqWX>W(`qCQEyv^PC)? zSAt|8&Q+_MR!VQ@H@TQRrJQhAN8uA~59ML7F)R{OA-F|d(KpErb06w8zT48#GjADQ znliHZx}2Wa5|ADl7#dkWI&XdM#M_noEwj7bICXVFYUvF(42h6$j}LX`L?@@9Hsswl zk!qq+su6WSuZb>opru#p?$Q~ynb|XHV($8unizR|+nT7<#EnzrNYup9sU6hB!iI)I zs)={K|rYs+#=VS+jD-&zhxF#*)10 zw}r$9t;nfuXsFFu84w$`VS3(@jNIANW)>IEoHkpYop4hw{%)F}w*1?v z&C*!|Qk=*`4KfkLF6Xhamh90f){CQWJ4NBTJla{D0(XQ>~#{umkb8S9G_>gIAUm^TZjM?=%@-wZy zgP4DY0azN^5Y>-~`e~-nbm! z=5JuDAx?S3Ei81-+{nnDp`rF$N9C;Q-#5%LFeYW+q=H9=#ts@hB%)$gj~=q1K;G`S zc|^*@?EZsh#-$d8C-)mXxNli<`fYKkiHWK4tHx!m9uhTbyxm?p%DHI!cBad@RNDyJ zb-MIbKb~d;5$Iuw#yI^5g}!&kpgcaIE7tB+icVMGUSZeUH)M}n)h{yCF(5W&?_|&w zGdMb$=;~Qepbi;i4J?WqUeqV4|KP!qWl11wcv8~vgjG3NYoen@kF(q7WXsz@7WI;m zGFYAF^;ehk{Aa@L_VCc?XcZY9-e>S&OtA?m_sBz9yp~G4TMZ6KdB|K()eJ36N-7+h zFf}o8syq}wZRpTx@jAjWYDP4j7NdTtYgAI-BrA%xZ;&;}E$U+CZs+Bm(3K!9J)M_# zW$x0VV?TD}I%I(JD?C1q{h0EOxX1zc??v(gwy`DY|KqeUObCRzVPhu#_vsp@b)`LS zhnG5Y0_D>sjJ5f7@^*qFfzF&cjLRo4b=EK6DsL~rQM0qqkL&%Mg%+etMj%7+BGF3741;q zsUyr&1_T7D9g7amm~n7XYVDr($G%wohMmaLO{rn1m)rMnXYBLPk?w+!zNU0Nt6& zU5~9Rt?y7YNl8%@FSaMsf)Anz3JOGwIEdHHcDk}MVGKnvCZV#DB6fF2#Li5|m^gJv z4_h5f7~@zrrOAQFJ$rc}@}@kJXgOsihztBtLN5chk#?8CGUw7IXQulu$0c`~6FCBU zgy9C;oM=%*3FnbZmt+nial7Qe*e%%kDN5}*lwu)xH>KfIvY53XPG2$-axQjUMBhZl~5I5yk`ge* z*^BrwkB3+a^moKU?{m#}giY`B^mo07#`{(BuEpD{HgPM=&6E_#L{KV+kcNkCWlPx{GcZ&&B?Xn;ijFO@dem|=b51z;sOSEVN zmx9Cqb+~jeqYq|`k{a!!>(ga$AImWBk?D;`LT~7+I8P1NL??EFfD@V_>vXz=;O1hM zpBTZNG=m-A5^Q{ni9!=KT9I}JyZk^;UkM>nS{b!)=K(o66@wqUb9;-iMjny}?asB% z)%F$>LfME=a?DVYqNGfc8snK%ct4jaCl4?UHFmjDF1I@!&OFnEbV9P)uZ37LQA+!$ z?#L~8-)_mI^N4*pB>8Hx+~F)wmS^`T${lh?qBB;{pJe$dax+q4#}P_%1)V11Tuv6$ zdqP^H)!%vuJF=X2mF|)eT9IWX<`U3Pp&o#G*yLDN>Uq%hC#lCNjVs6}>LunxEe|sF z#N)T%eY@pBqF%P6UMiD(uDdzZLf~&MQBApEJBU=f<0T;sxk$c)Etj2Jk#1*fvaCWo zkyS{$Gd59@Mj%rbq27h^qf<$;`8%7iPR7jAD<$ZjRaEmun-gngfwWd<4UfXI5v^GV zk%$+fFvo0*!u+#7l;ySEz#z-E{z1<4^ugCn+cItK`qcI5)3+4%icWW?2lbW5M+T>? zoIGNE+NR}GmJjQZ8q!mqANBZSo2FDHC+2T??6GX;fSx$}lX>u=vh2~D%6C1M0Uool zImJ?MD`&}+?v)I~{7NFIAvqTR>E2G3FX`-z>%=8%HPUzYU>;Q8=+h@m7D1#vj{i-k zRe1T6bJtc{Ha}kT!a}FFe7$^M@zi??U^+YD*4)QdIAc$J{IM1%#*F)><&9sPSHG3&Q*QGqjaqFu(TAOBSjq%>Sb)}drreqQZjd67fTKO(ip03#QLGl}qj`~6~r@pg5*IQzZN($2O zU*dn?cH5oEPE}PN-;$TN<#^@%<9Frd-F3X_7bz!FhMi0~p$$5ba-!)hZX%|CuP$2j zs{CTuiIh`tGvC!u1l+4VCx@N5Tm%m(OI{`Si+{Ux@vBSJmnkP`teS!{9AK1Td~4ZZ z#mQwtB&u%&Eu@p+8|21UBGMFDkkycbJyB?WxBq@?kKBl_4<5O&`a$R0&d+Xsbn6`=7?dA(VDqwHqo!L~ZaRYt9DG^ zJHL9*)XBT+Y9F1NsAj3kA7e4>QGVbYH^<{94ih{lj$b%SbQH=sC z;0>Ny{=3ePppb$zW;hqE5 z7J#vy=A&suhCQ_^8}oO=XCy>S&Cm8<>Nj?FdEs>#wHaza^2{5;ic4?uTN*fXVNIU) zK}hfGWKNGBLFo+@>WiXVa{7Ar3eiRf2m2>g&uj`@_lxnt>J$j!8(`P*XE`o3mzSsG(3Bl)koXi(>}24fY?D1iQCdAuCe#A zdpJCX4ocbA^tkrf<(}GS&W6Cqui9J0>C8LbGIUHU=LBU<3rX-H4 zjtCnvI4Y`g#Dq<8_TP6m16)c>bU@=>3mE}*PgU>w%XJou^Ig=xFL@w~Tp@X2Zb4mJGJ&Gxp2;9kS(MGaI0mXGu6e)?kB5EDw^(7WqRz;BZcy?SOOM5RjJCF z?whb>wjVag<}hbL-V8NN72VOqDK}Df44p82ciEJUl~K7do6DEo zqpEO_*wZm#s8&_AZ+gxH3wv(g_`sUW?hf^|Uh>@#_6DSq=Cf#4#jM}v8F4SYT08G< zYP8ffHOfIPb@_6hzAxUO(9Oo7_!&G0Qx*C@Y&1-4ETr71#vboo@%PLefHj-Ah+NYnt!PLkG9nEH8X>=si!oipTahun>a#V|OWGdMK0 zm&Qj#BahcG3Zqj26pyUbQZ2C*mWR^CREYnY=Dgs%aD(i}Ap70myde9@N_tO$IEwe* z$tYMlf5-B-+^wC^oY*t-FtUJVC`W4RY2HSTl)J&(8K=KS)&9gs?_!?&a+U72^w$Dg6qa zdvcp5QyE6kOJg_Ob0$wr&S86TvZ?^Sm#QED72nhqK} z=&W(mciIVgR0cX^pz{ld^9$!C$~PtcEVpRQniFS&AUPZN3t}yfZ%n5xl8I4th6?J* z`D$m^55|||8|Ifx>pw8c;yK5^-;5E%s>%wZVxzm!OWLscC50}Z=FgelFS5V87kyKg z;xpru$Mi_6&V-?8*of+E=MGn^*im7yLoNGEUPAq7)HQrC8Lm|5>t=NbA8IP~H6=1vSHe}FN zDICs&aUz;`K7c*x*RFu7D z`t&u~1(n;kSB_hpn!0$Lj`U6x=ZkR5WJ?H4bSI#|cpFPUZN~=fCE9H%+Q}5BD*k1| z=+OS-19+NTe_I#1-}*H}LG z&B_Z8?`_MOa`TVje%TYkU?!e~O8q(bs2lfSyfYbls~pZ`>TF1HA-QQ@s%^4dB<>$X zl1&n3vXk({wy1jbLz4}M_GFXlsXlG$-BT0m^VI4T98(%=Z`wYiX}g`)e1p-#H`%t( zI2&`|31O^Z^6ZK4Wb9#;>S)@bW{hom-PZg28jPsv+z0lNV~lPAhoe2hpFqphF%bfp z6X#!1EmBobA~v{kCyVtfi>`UWSk=Vj5$&l--TC1{r51g3{|&X}`PaLJUpMkk_jo=j z)##`w@5R60ar*UlUO08`tq`^L>)m_)wnoVy`=}wAtB0+*%`?yQ(YtTl`{(_S{P)_) z-@f_Q*P8Y}XW#iNjcn>MhNm%vt_3WP?sACZy3kUC&DB+XuxxCpX}=E9zOFQ;Sj$tK z@6LW?R>_{C*?WqM_sqU=<&E@jMNZC&%gwN&50A{6^@!^STGIPrdGRA9v-ZpamON7I zFubv6b+pq@n75&{czo0*EfdA;e@uG*N$Iuyp_3f?`!nM5uAj)GtDaSAKO4n;(?;ty zuI>IbqvR(2)i&qWM7`JB>N>ylBP#hd&qJX_H8wX`Hd?#!%oTQxK#oX~YMaYkm9^WC z7Fm_7cez{J#SumvI!K1u4!SzBTvj=)R2pdfbhO59?1v6*PDx3jnREgObvC|I4RMJhXkJh6iX~>OU72R&j*cS?M7V-?yC8%1mDZdd~4VLbK4@F@9(oM7W+-jY``veqC!NAD_hTk=Q?4tM)@m-p}j-MVDfjWhI ze4Yr&9G$o^XVliAgOUR#-%&B=@xeUTdv@pMr)oeJ}=T zgVGHJC-|vjll7sOuI}vNg{##1@y3UP1r<-!cuw}8f5-5#D|2)gB@a7~4!xz^Z$i<)#PXcc zxe3=_pH?xgxFNyEulMr8^zku4AsGwj;@p<92fI30otAs&G{5O{2gel-Z*g^NH2S!d z=I^XKF@xO|tt6l7PFsmb(`SD4tmIt^s6u)jvb9vAxLB$%XiBhgqtjrlWL4MwtiIgz z!}IgzJ^#a|&EM1W`#UCWNr(?uePR;s%1=8kv_F z8tv!kkrgtyWW@3dk4~Td=!NAgKBVV|o-QG6rjVsiYI^zuV{Y6rB0V*zSFgOd-eIZT zyLXMZ+gGM!H4Ki4>(^~qM99!F-Fo+a8va+fh6iy4d%yB5(bjK}{yx~HF^o#QZ4R{W z$D{mFy4+s+MD^*;gK%13RWp7<3QT_ehG|3k=jY|tuMV-t_gt;=Iur;GmX#eOv2mw- zJwGLCT)^Qydp;i$7BPtGc)dDon}s^=jnlcP<20)7N{ak2xG{$4TK!l#Kn@tIa-Ekm zozAA?&aYLK^BZ+oebw~23U0zwkaLiHx9NnsAG7&$5N3+{O7jNSp!<`#rkm5r#_qAU z^39%3Boy^k=iMu7w2|(h8{=eZhesSd(StVI>~7dYCZ)9`+GBIXfy4Ezh5vFe>EWl9 z7>MR4;6F;eCR33SZZsl>NtbEs@C7Hapye9_NjC#=e===gH&EsjP)|{yqoaU&3~ZVq zRM`c1{|=xcnm)qA=?Q2$MkDZzLb!(_Zz72cAoerpg&|R?a(d$XE=Y;=uyF` zQYdSLgTz=%1$vYYK zJ9rxPi+5}ex@w21YjvUD%+jb|NbHt*-~a~wM1O=j%DU_In(1<9rhL~$?~JRKdZO|h zTd=Bk+le}jdeMQ5ifL&KsnGe!r#rYG%N87;pV(sWNE;kIa%A-2G|+=9HMDRyi>^t( zWxP$Rdd6&k+SJJ%Z8k^SE77T@?~;(^?XPuphWmMs1(S;#=y!H!_wi|?u|9+RbM{ulL^}6~#@L(GgCpUFG$VI) zaEn>**gSj6s+CFU{mQFj1}BB}NFLA+wOxK~*{TlcwNfl|rV34_WB#dz&mytL46_yn zQJuI{-}H9e^N!Bc0h6x7Y|lJ8ncopKz%B z!)lGNSS+;0yz+VHGnY1Qyd=jwe@te7w{hcl&SS^lkY&>E{`;Mc&imeY!+D<*nj@s2 zEYmJK-*vv*w70G6V;n+0yLjVDpJ=pV2=Yvl0rM)T<+>RbHoURDBt6Pq46}kv8f2Jh z-jsCok|zt?_c6>?NXPvRvkm=CjA3?zG@D?U-66RUM==s&w7gW-E{t4Gs@12A9Afb_Tq>j9b{ z&4A7KE5aoUOl4Gy8nHywiV9IC%0--d5q<(v5HD^J6UAtRFb1Z!DHtp|3THCHA^IyoT@_N% z8q(GH9tVH(I6W1hBouMCO&jGc<%pRdrHG>rw9ZGYCGcC!xn05em(3JVSxkg!4%{u~ zv{BycE-LYy4WCtTPyR!Ze#%2iK`7koJU&4ml7Cd)M4p07|F^*1&cFVx%&t z#FOe%8EVB%@SpQ{`Dt5n9hLeNP;1ux);cwgbF~7wIv-_F3amiaSq-X6TAr<;nP1w* zHW)OUA-Dh1w$8Ty>Kc3dZ|$jR|GhI>uA~+{f}&mm((6uId%p4yGyejsuD_K^YSMxY zYc}a7Ucp@~9@0~KNpCSrb`g(DAL%RoP=trX7OY%HiYC!4N}%5|0JG-*DZ9#UUf1D{quJ za-2vO@5=GwJy9-i66dk6cY@556Qx5=l9S~WnJ=fx0%%|xioUZ@PRFgLGr@3D#9w5Q z_>C-aP)+$e98x1%z?kLI;VES7i3jbfp^Q*M%*vHx!zw9So|Tg6TCZn;g~1KqH> zVuIW*@5S!F`@nAV&^;`Z_sa+5PWcP@pjZwKGE3zy`LNtAAHlx+N9A6*Pwp2F<3_4q zp|N}gMm92C+&W5x2-+%ctct zSaf?<9+SU;y7cGearuHgA*PA~`Jy~2Uy`T9G*KwNlrM{8^0a(KzAAq!rpq(pKjdrj zbx0#8#EbH*_=R{-zA4Yix3Jy)9r><&Po9_W%M0>%@&oxH?!)@M{8;`$ej@)UFUmj3 zPvxKGXYxPf=kh=07xFLiOZi{&EBRO1DE}tEmj5lkk>ASisD`leaf zT&1cJYNSe2=_*5Isw|bQMyb&_r7~9Ch~2{D)OdB1%2g9oo|>o}YLc3)reNFfR8^p+ zVGeYQ=Qu-KK6=cc_i(PPIvGR$J6vYAfbXx?zVz zAmrg-$j&`6`s%IjR@>A)YP-5u?NIlr`_%(#r}_n^X&=Jg%!k!(^@!S|9#wnQKDA%{ zQXNo_se|fqbx1v-o)pjFEbq7CJ4m#?SQQHqk3n{R1p5SciplzLg6Rn>Zu1SNxB9 zOTDe$QSYkv)OoQ^y{|5a?do@s(f^8dfurd1Hj6OKs@x;CiMt_(7el{dn%Js75Ie>F z;y&@H`cUk^$l$d4Nc~=Ytp1=rQGZky)t}U-;#rIxJj4dEUfco6exq0;W{S_nYH?Ei zS$(GdLw&CPQ+**e;oMV(xKsQ=To8YRKDytF--!>z$Kn(97xkt3FQIH{vuaBhmAWmg zs))%-%hI3eiN@1zJY$V#y#7oxpBcux;XWbm0DvrDV$Y?-r*;R=u1>f$@l&io}*fVv5cNoTn%PF3{u&&gW(~>6GrrXBrw&PuF;}f*3sxqC# zOe2+tBX+9tBC*Ti;-i;Xde8=7TtAj5197jKCiwLLZ_%{IxUrezuQ zXC+!EwbGkq1e9&0I?JTrpgSw8%cM5+PBOB8lAit6NwpPKWwuFN2(~FYxl>xn^_Wsp zQCeHNpkje-N?C33qEfG^tsnI)%Z|5A zqB4v~GK@eo45Bg;JWE>w(Bn-v=txg@D>dRRZPR9$ZhLIPP_MF9I>;~DPMl|1OK_HQ zYCGkvZagZYE30Q$I`VGRW6Cg6nlaR^!icHDXhjuzE1KKtS&twt$yTY?%*vKjq7`M> zs&v~b7u)zmt+b^T8R^b65|?SDKhr3TOf!FsLdnRsR=3v5OoPxY)0g2Y)5zVdm@d_A zYGt*a99ykURjmtE2}!mEZ0oh4UE*S6hFa>V_0+jIPvj`kdeUtRT`F6aL3dV?bzv)= zSw`xzjnrnDbQ|<$Wp`QFhR%gXwl6eV&q8iJ3-#8sSSNFFE14dPTUyUzz4a_<{iv5| zc7kn*YwI!cHG8OSDF^4dw55J%b7s!5;{VJ__qv&N(Ulct#azhoG2Hm=@iCkXJarBd zAEW0*yxn*XHQg~QfjiC=JC=0xaO|dkZo>G^#Nf$H22ai|xYuiRd<-)iyfd@Gcg{XM z&3DrsGf&ua@!R8Ljrd}X_+kxuV@-Mu_pt_@u?C&720gI`eX#~zu_j$+_(uG(27R#x zU3Sx*Nw=APGaiFpyAi(Kh|g}sV>iNyHR&_rv&VW&T7bE!in`fL^qfThN$op6E7_Ny zG4b4z(?{hQ?}_c+)7rhKo9}u!aYl~C895ebnBR>Q z#u+J$Gg2657{kW)=|at z=NEI)#|@2l%c@yWQCVGODZnQ!3!fe3Fj>Yx_O;$vTvJmF332|cl43P(p&GwXvDwp& z@RE%1l8o?@jPR0-@RE%1l7@QDu14LCo?X14)VH*LHj1~Tda?fQfAhl91$7nGRV_AM zYf5V?s!M3V2Wh;7efiWB*OpdQmd>fu1L49xnZ8)V%Bp#COe>PVMS$S>HO-}2)edd zwMN0t7GMMdw?;bH8C$tH(_@}#5I~YoSHr5TwzL>|!qSjOaaDC4l3Zc1kff|$EqOF^ z_Dq)yYLT7nX?B&7r&FD1@3o)?c{a1Mbism|T=8bIMT@8vYfsO%lvG!hS+W+^a*KnF zQQ~@+k9VV{r5pLC*OXX$8h1%}a@T^VUZY}T65LDY*VHXpP+F&FczS}jnJCI>52A+i z*{!&?wtDfx8c%+5?s%|~s)=r*T=ao7Tw76GhKf?Ru(ry#)isCW!|yHG%}I}mNpveV zs?F@`nkB6{@5g!JlJ87ooLEET#&H z-59=jVvXMAFM!ut{dg|DC+y?Nr4S?W!;BR96B~B!ee%@V3m3oq&a+!czm(h((rCl3 z#H;ijE6C-Tnbk70a~z`E>?O68BDk`+t_t(!>G+x|6a=tPk%~?Sh=mciw1O<`qtD25 z0B=ky0FJvU2bg!$IG`hq>@oZT^4=7RL(VI$t)iWo9HYeSnZg@ZPeadQpT{?tnHJ(( z??U=%hxF%9qh*u#Fz;b*r;XnyUiQ%Yy~l^%Pd~4^)*tK+wfi-MUiHu0$7{K(Yj2;Q z`}yQ~ul0^?`EB*4-*Wu+dhhkgyZWEE4?+rY`2~8n{jK#bq_k2l;CYDBNoLqKz^6{< za-Y1=2J%Nw*lsochj_=r1e$;d1vyRrI21gQUqmM;hJWw190s{0-$;d?4m^)}pY5^* zE^B?3`fTv6^WEUPJs{lo!GQ390WH7SZa&>E28Z_A5K#LBbgw!V{If~+$*PHbz}!tMy8AVuo^N;+>aHIGVuVfdF;e$ zM;+$vZ}|&Egfz^DFTx=J-9uZ)tX4yg{@3;!Vu#_YiN< z9b4i&=JX@P`ZlK1yJ=%#siFxF&<=mobeFj6O2zX{)+K1<5P@B7=O+9G~+XjM;V`GJjVDN#^)HH zXFSe$qWK~yd6DrX<4cUE7++>Q&3K0KHTLy7;~R`;+5Sz&bBu2>zRma!yLp%KJ+?W| z=J(lrfz7{T{D5sfWc;2`N=C(~FY z8M`rdXAEQvV(dv2%6uwEIfJo+aWmr<{<@uA-pl44jQ24<%=UX2_c1=k$Yms-W%CQ{ zl5<|Z$~K&b@&bqdA>&2HMn*k@DQWeZDdocE745QH0 zm}W>DYAoX>3P)H}IkzIST~X^=PHhaULK18IcxBWWEsR!18>1VeJEI4qC!-gmH)9t@ zA4XqBKSqDX0LHG2-59$w1~LXQqD77Mq!tBS*?bCAJ;1oX`P5iHv@XH}jE^xMWPF_Q z5aSb!Pcr_B@i604j7J!M&GdF^ppwZ)D72yq|qNz=%Exe$giZxi^xpkiGI{j1(gKBzjwlyN+!Z zv3WV0S1>ZiS31Xs5?_PDI_zV?PTdy26axDK^$RG^AboJUkrv9q1r(N0kbfxu%Q+M) zo=@^OKj4+UJ>>)Chf)jJSNk|A9eSKZ2fgWOFzv>0=wlh@HDAa|6rtdDOb4UJXkoN6 zGS?MuY<6e#VDx14V)SP0!sx@uc`5wZ?9Uj$*p;yxV|T_t#vnrUK7=zED;PI3avzF% zOXj9u^s2wy8ObIEBlNx^;c?sfsC=*Q^K7{J(-u^VG|#z4j(LX;fg48{t^&5RcqKV-bf*hmOn^F(+U zn=Y}6bscYVlz5{J6 zgnRFKkUXh{pl<}CZv>)m1fp*QqHhGEZv>)m1fp*QqHhGEZv>)m1fp*QqHhGEZv>)m z1fp*QqHhGEZv>)m1fp*QqHhGEZv>v;R{tX7Nye8LPcgpCc$)DH<5|Wx8P74k#rQVk zdyMZhe!$3_UVP8yA2`Mz2_aR2zetu}B+D<7LAWcfw1{32O?ku1MRmR}^xFOuaK$?}V2`9-q)B7>P8)LzgN${5BN&e(@Bf>Gz| z=mX($JJavVvma)g-TZYAoA)t3#;9}gXW5Lt5g~9s%a_^A+#NC}<;gj=;aruRZ}KwR zI~kklD2=Mf^nF9`QQ1y?<_5-9jQ4PlyPfe~#vP3JG2YMk0Q=p^?tj7fAmc-fyBHs4 z+|Bq1q0xuCa{E~n4rC?pNm;{gZf2W0#${}?g3YTK*HP?p1KZ!mcqiNI{e^4Iap~b9 zA5r+O{m2*W_b-h9#UXIdBEMyuON2(bhcd4U6DcE(s-0}Fr!*WKDkas9-iHt;LV?f$ z2DCClZywBUjP8scjGl~MjNXi07=0Lh8T}aj83P!*GInF^&KSrTM2Oyp5E@&76^xr1 zFED<{c#*M@5FGQ=@E_0zkvRgXhioqV8U*&u_2gR8i;-)#fLnY`U`%98V$5fp%2>cS zjj@n%I^zt+nT$n@#f&T=<|^m(o%23>)55+Zi8b+{3t!k^5}S z9Z)X4$iBEN44(cf+rPo~oagcnZ1WkT-m1T3^IsXiVf>C!&;K9U?`5`e5<;^rp_S~> z2auU_8+`zoIfpUJKxXdM!2QY0Ek$i+GxG)PmY2i1 zTHfzDgpV1yzKBoQ{71%rw|2=jOI}UujHHpLjAHD^*q?C#V?LEWWOKp_#?6eTtc9|W zowYxfb&Xc|0_74UD?(keVqOTzifr^&c!5Lykntj8BcqneFbYj=;__PY zZ`IC{QKM-LLsCET<6ls_KjL_QPjZU*nDGycpD_NB@&9fepTM;&kI}){S-t-09>ujr zx2?;_w|_ugb|>1dq36(R^cd$3_!`T2BaI=TWQZ`IQLpcsJW6GVd2qr_T%HsEWwq`9 zS6=$})*j-4uAJ~6#qq|_HNvPFgnB)&w9FG>G=sH3s&D4}UQTlk-pYv&VTCjooIt4@ zmT1@x0_Qy9ph89F(;kMXqk|kcwi*kYwtulPp=~X&Gonbhp)nNwr$07tz!Nm+e=(Ek z+5DaUG%WeS_0`qFFq2<1ybeCMv2u0Sd@+XCtU3#~jYpT4YjyA9^? zkF2wN?aaROkgoj;t@WCJZPL-sp3+4#>E_>+w8g~!BltwyaAV5N_&R&K=67dqI%cxKq-zQvwsq5nl>8xza3%w%l$r+?QiO|#i2kgY2}rLiHsx978> z-tfOu|7QB5@Lc(`?y6%n!z4L`<3L#SXVy^)i~jg~5gS|bitP>d{da`= zU#IDFp^xi^%e(3KTAyaQwD(7}x0GF*cw&~4Ti3L?ro%OyPV@Q8R++%nJxi}-k=w@h zs$SZs!=(MHJR6QW@m*68ULq4_H;~=#Ro{apS_XJ9K-JY<0d!CNp01 z$#%>`TiuXdM}KYnY-n}QV|aKlX`;UTYW{S-7*j}YTm1f<$8Nd<)4lopId87tUH!Pq z=%$7nP-HF>$hvDu!99#@)J9&1;JT)&$E zbv91y$gSz;pYiOd>`c2hwD6vuD=9GZ;mR*pZ*w){V2X$6A=*qH%X<_MjY%iHo3yu& zo&CA=@221O?p)tn!ligA?49~o*Emd?=u2mLaW!$7@tSd%@8+{Jd-MDMm1k#p)SiAb z@2}Rry}N(@d(7Btiz6mecYpQsL)R95tLu*P&b7{(F1bw@ZOXL!XFmUtb@+;U^mmLS z{;6rD@%)CED%UtVDi{5GYv13-y&lF@*E7U-)oxwmX)j;=J+fwJ{aKrM{)I0c$tCT{ z>AZY&msb-;`!LP-p9|Y`*U{6p?P5NR*I+twM|Q69xXyug=KkNqUYA+_J!rW$Dk#5Q z%jc?nx8ql?<@R%7Tuppe9+m4=QKA3Tsva2~}>(Gx&JRN=S$j*$Xqi?Qu;JY1;po50#9>@$?Jr%+M*sTvp&6I?yp~X|#ZU8>F)pi_h$ZD(V(QFo z$8teuuCK=4thX(0X}!aoi|b^J$8PIeeEht@9POJ=^3hp-81oOVfnICbUy&x)!2X5i zYfZ<`k=jvP`Z+)UF5g}GziWB9+MBexemCu|_4)V8YS+@{ua%~MhWo#_PW-+8{uycb z|0ztf?zZq$BXMTEGN1n^)2wh|fy9n7Tvvr(3@(=#irrO$kYQ+@RvtEEz=T~uC%Ngi@J_Kzk-$H}@|KN84XTEl>iwJwvX8e)nv-0s7oWljaoY zs=ph*3GyCjYtMtW_JU2YhyMfgq;H0f^v@9L7toio4cgKF2CeYlKri|OtQY-3`J?JB zcR{0hm^=wxC#CWw(qJOrfUfWr@+>r%Y>{uOt!k@$n>2pQcSxIwe2=u5$n&HvTfUD& z3a602fjDOrgr5c4!s)i79?(2Pw~&QH>kQq)X5rkoaPIf!+$TNwV{mK0SaBmxu;!p7 z`f^G1MM=y@s8#q`P#!f1gEZMFluRu&D%Igqhknquv3^Z`t#7Fq`hd%BlE@{vSMZNeIW~v$8P&2;AnOxGT zLsxqS2^;Q8=phElp13g~8aF0{i0-UqCs6j4eTAQl#18o|x*%J0pNhNdkPTaX1Q5t zatrP&uu?5YKHP)53cBN-g6#;0GzQsF>+eSzcjAr$$=ZWLQTrc(`BC{OaIf5poFq*` zUbq;3Km6j30?|bt#2p0zXeE!s4cZCtFzzPslSgnjfuy?$U_L63!WV8Q5bkI>&*L_v z7vu~0dP1In`9=96a`+T(De!?7qL)P=?kG4ddf=XdR}k`VB{asfMxsz$jr|5(;tq7! zkai+}w7j=qM%x3vC*MO{=jC~rFF@(Z~C3$z@0;8ue#VMDr(`k?jx6=u?Sq@f-E4JG>x^nNMU ze&m5R{TVfG#CJ(GzzibVF#} zRS@iZs-6g^m+FPDq+Q9M^(Tek=7QrvSY5)gE>-9=*CiL`*i;R{S^375-=HkLKJf)D|4lOxCdhj&fZg>pbYLq9H%RD zoUY7ke3{qyFt71-;Wd8DYkXXIO%QkuahVtRUV;+_m-#LD(HZa2Jh=6A%q zFu#YN6zB2t#H}Ci!+Zg^0eFHNeF!u0qh8F9y0_s+e-mHh))nGPy$!DPowx+9N?b|m zTnTr1;A}toF5Gg4n_PlXgNZ{$Fo&`;hYDm46#(8e05x?Wc#y_C$cuSUH|9a!%!5L~ zgYv+q9MSYK;}V#EdqXh8|zGy;8SN%Qm=tqS(#h)W^UyLZuKT?T)EZT@?E&Z?JBT; zA3b<~=2jNwP!{G;K`tE1%DlZO5TB z=1{$vLk(dL6~P?Ji#b#nw7R*0*ASoTg&SNvL=4^H0vqB}gPBihxX;B0HpH#EF}Koi zw~Ie)0>G^_-0WgzRvPPj{_=S8h}rfyB|mTsT@+=4c_z#e7}37;bVEo(&{= zD@HU1{B>c}7~L7Y8GRW28GRYu7zLx1(Z=Y-=)q_Kf-#`iIjl}}pvSTjcb5q8I9-pW zAM3HiZb9hN^ntwukJKQmSs`utLU!_p45Z&4bEOOKb}md^nB!R&W)17Y+{(HzkFYMx z^Q;T=66wN(3`OCQMwHeVe=a^-yZEl8$o*$sc>Jsjy4Ufi)9v-MF1q}z3!io_0*i|) z>%{umgquiZtJqdjRXtzaKL;vy#V%HRx|c3;5C<6#Gah9;&UlLP4C6V*^Nb%=Eu3E~ zE>_o;REf`P@FE(a8F!BOZo$G?3&iCGP{0f&L$D`(Rw#YF_DIOtWFqY|60{QfF_I=4 z2`QP-laX}akPcHq(vL$WN=SNeBx(|&jge}YLY*QlH@G*F(VLO<^cUwI!ABXm~kw^_+E`b}2EZFxM_a)VWew?>(FI=SBCq~G1N z(zu^#5#4sAPT&rsa|#kBZU&N&MwXx%?-zeY{~eC;!VF0EW$07yLZ5awda;%}zR+_) za)#WzAAQduNX1X0_c`9-T~#;Y#wogQ%Jp_B=()jtQs%u;EBHRA=b*dtCESComzBGa z?q^YwJux;LfYCJFOFI@fjTPYfKn?N4s2lL?hkLM6@a&J5J^L$qs$LX{VqsHK?T=uc{Q`H>f4QuPV1&Vv}xrAZeO$OSkQ)!+O0(E<#>| z244{hvJJD8zsNrl24wFgg(t2H6r#=@SoKvDRl$ynk4 ze*R*=;!8gC)R}bP)>z0zbpIXIaLP@pU;E*rm9}oMBN{F0O~?yUk-k}pQZ~at-Zo>* zf&Mf~*$o=lhwU)vGhK0RqaW38G3&g>x2^9%=zo8%X3{-lX1%m9r9^E5awtF~ijlYw zle98hKuZ8PQwU^L4U+S>n72`wxtR$3GbC39Ss7`RlOT;o;*H8-JzSnZe~nr%~KnsrD{c5Jvi2W?WA^I zYqWS;A}ooPTuX^%rR9L-Rm-PVcWbyc-8#d%(z@09r1gyTQ|l#LpltwBftn%bK!wCP z>p4(Kw;=0wd9Zs95S!9##;}&Ow1;j?v&MTMNO5vh*E<-W$i83!fvBsNAxMA5v7Z`t|Dw+HhI64JUJhmkL&)lB=Gsq3ZZ6pbvk^T;=% znC^&{&=O4Tb2`SboWJY`^AGs$>SuQwKQq|ROpJ9~{WM(Rr>c#gBKA|P$_zjKKuM1F z%@w|q+xV(yUrW?2@FlfCyhR&nBxr;VDu3;YVF;?+3T$UFl~A zM(^ZjCi^*bg`b@r_$g9z*iSM0S$c(^@(%peE2=?K@m<&IE0|3l*n{nFxH{m^C4v+u%cLJ}`yAOkYFjs~o|IULQ6Rw;U>ru0bc>sCSd{dJdU#i}F)%QK9q& zbExz^l0y#!KbH!zN*ip22xAvNwD_eMb-&^Kg*dvz+zL^Ra$^aAo<`Ymjmp70;$=I9 z(61wnhwS4);|o2_oZrh|z?Ik!Jajq(H+mqFiA|H~<2d_BHhj?2 z^bvwyUH74zOdrp|R-&I#TppB{9{6dHv3=3M`QvAWeB2woO$f@`50nf>{iTb$d+}NN z-l!jm_?C>DZNpGvX_yttz;6KGP&*KFUZde-EabOnQH0+J$Z@k!pXNfwN`uU`MobXv zFa|8ZEtVTZq1b{uFsEZ?{UK3|dt)Dl9(kHmpN~19&EjTA;FoX@C#6c4qwS*m&-DK; z(k}dT|CzquMIv>HB?7a7ZKVs6rQ3$=+fL3U8Moumf`vz$&^Ro_=Fuhu_TNGS$wM^L zCNX14X{W!oI|azjo4=qf(Q_nzxTTrR__pmDez_>KLYH41WDNSB(&k5d80cp{$()Pw zGJkrE&x!xX+xGxORc!yyz59m+mK6{X5fK3u5fKp)5ph`-L_|bHL_|bHL_{P*MKao5 z$gIrFd}d~T&CJZmd}d^3O6K#K&wOS^W~M}jL_~^8gt+_r%)NK{qoTXY`!O!EyLaZC zIdkUBnRCvZxnH5*Q5&QYN-1XkstzR^`jv^rP=gF^YdL+4+EJH*U)sxin4`u*Iq~6T z1KHMAj^mEh&V~AMXh|@=7;3@w$sI}t31$?S15sTTB;^$fy{Fb#sQ;<>zSN`?-h{FX z1%E@6IfVIiihG`~RgC%8RSCj3^wm~4jMIVPW}&FC2Q!wnu+(sD+!hxp7HFFE-(+ugG=y)A*6f z!F%ezE+!QyS@4d+Vu|&j81TiI@%R3u;vQ~)%wjL(L2khRVfcN&&-P>8ZYD?J1KosC z+QbBNbfWWi8$Qd&`cjUv2cObUs4Q8ILbe0rb+Dlo?b4@w0g=8!@$w;O(3+Y-Pk=!o#tb=hQ3$v?lX&AZAKV2^%O-fe zj{%D-q!qW8$jC+ra>`NMPb-W6s7&WIGzZv4sV2oP#~oSRvY-I355!zh0hbiI4&ZSH zy%1InIOu%ww+Jtmf!7rOQ5^W^U|(4`aiiU$h-aO8nwp_${f% ziiRJ_75W?c&nS%BMtInpm~pV1?S+0|fW=@w?gu}`)`=`cL81iFbD|@no8sQ$$>OKP zd$6M&D48i)BRMR&B^@puEsc{dl&+C}Agz?PSa?~?vDjhpzQvao7c6ec2Fk)@i)C-i zK9>Dq8DzQK^04J?D}~h{tMOJ-tmax3TD@qs+3G#3gH}IT{ci1K9cDe>`gQ9Mt-rUv zV*NK91%2fs<&)%daF5Ss`RDR0HcmE?Hbpl3Y_2PYDe@Fw^yt%LT8|fc9JZC%M%un$ zd)m(4Zh_r#JA-|I{Sx~kd!79O`)fT1^i1iwvFCRVy&ZBLjyrlfu6O*?X^PVpr}v#c zcRKI%vy;A;XRo+krM>p`s&=+<9_3u%yxX~^w|noD-tYFl?c(Dy)g{$so69bjPhGxq zY3|dvPeh-2eV*yFq0invr~5RxTDp3cr5TZ>}l&c$Mauaj$SLgt_+A9aAZK!K+l0m1J?}v?;y#b(SsHZ z+C6Chpg+9(c~AFV@BQ`Q9)sfsuNz$B6X6r%qx1RH=g%RdhAbNLm9MjJjPF9ZJ7{eJSh>i73B#W1H~Zo`HTQw_@+RxoVGuv5c+_qXwP_gDGH`ltD4 z`|JES`d=PyKRjmmv%~)tU=c7qKo{^)z||2RBW8}+IO4ZJW#H1lcLTp4=`u2L;I3_d@)$LPtUH;n!%Bp{?HOJm-M`6T9K%$12&6TK#m zniw`QZsN3wsS|T27EFA7;;$3yV{Kyx#D>Hs#%9HCj6E6KGAUxxiby95aZQs4PF^|r)5#T+FHf$W{Ac{o__X+}_+{}=$Ct*hiGMZzt0|UK zrcRkT<;^KOrj$+jXv)DU|D94f<Q{$)3oSHRt$<(K(uA91d>ea-tiIIt~C;l+4-?V|#=1*HcZS%B4 z(`u$QB#lW@B_$=TPdYPQHht9e`P1{JFP&aKU7zfqJTG~1@;k{@$-gCEn-Mx=#f&2} zjw6`GE+r!6sg(68-^}bg({JWeGf&L?8v@%RRgvnL>YD1A>XSM=wK(%$_hiarW%l zIkO9AubO=(-6ef^`uOyW^mXZPq`#BCH~sJ&*&N$BL+4DKvwF^Fb570qaZWWhL$ZvJ z3{^%#MoLC{Ms`Mi#5LyTZf5A``p=D-n=yC6++}m0nfv_Q zSLVJqckkTK=YBc2a_+^sSLgoOUNZY<=4QT?`Q5xh^Rnk{pI4W~WR+z7Gwb&JVe=Qx z|8V}L`7POfvO}}SXD4T;XBVIpXTO}iCA%#9VD`VWe^@YRLEM7m1=$PsFZemfBF8Cb zWX^<~_?(w>jxLlfbX@4V&~IV*!l?`AFMN98s|$B8{4#ey?xx&N77beT*`hmnu6coZ zVR@7Drsoyp73V#hw>EEkURhpw-toM%c~yCTE*33zTs&y85*JOcS-f%aM~lxczOc9< zzjuCrCDG6oZ6IX2hLnXv1=_$?#;TR%uvn=~P9{pSL0cMbSZP?P5tV0VmY49)2jY1p zR`h|nN^+^oilXZ3l$86_rt7(N%y7$V*9rRouqmMHt$;K%vLYoAQxyacPBx zg=ukdBjq>m(`wq?t*ZG}$z1X>(|4|teAgwS_cR}YwQVD#U=;U(gIIDWN37;7f^O(9 z{N{e}7tt%pMrn-YHFV289N=HP3nZgV21Tv1nr_NzXVT*20suC%oTu!J4!uZ?8Qn%3 z>0HT?;mb{?4>~~6CmTC;fE(-89Uye1zId+F-@UU`afeMEG|ks=YuG=?JFt&`4Snk@qFWGY*9jrM&#wU^hm7Qy@UdYNC&boY z{>@`ZaCoFTG&o3wao9mNS&tj2|Mk}e3nq^n>gcE?UT+*XzQLS#I+Ym+tcgAIW{!`GpnYotR~a3!|3f` zoS4*yW0#V0pWZIJtG83gR>W?;MH-j^j3-_aL_}?ewdqZ~4v|k$J|u5-3Clvjd!h=a zsl8;E&9aG}&2>%E2*17~!XhF&5u4{H&QkNCML2np{L*XEgvcl6&xntml#)F2c0=>< zkn!<}Qzwp(RDm%+BJXwy)>Z%;8XB9PpP!!{ACD^(!N9bfMd;Tau6)XEa$Y2%ozURM zXbh!-pIti(9lFqvWp;}tF@eXFA}zli5|XPEx7E;6T;1sVZXGH#jC^<;s;g>8_5_dnq>&#&j26sKZ5yAG%?) z;6I=eUpmrWuh-kpR)edtPM~NdF%x1YbcW2!dP$SDpDMXXN!H4Wl2v}zD*Ol#+hjiN znL}7XM)21dh{dU85q-x^ixG1Qwgj!U#cRBP{wYAN1S65eu*47Xe*b~LFI430~ zW!|!7qiXN%89cf@6tHE|J{f;BqOvG^2(`mti9?J-ybAl}cvywvnbEH-dNZ=F@|5rO`bQn&BE5tyll2sw)F`f;+;GBfbT?(M0Q{7I@-D{gHiVzEwS z=Tf~>XhmH5EgAY0#5OIW6t|i`OF2%Qg?6a|q)1ef zIXO5*jrH}lYcUZ8o--&nv;X+x2_^YTGGf>e69G#Facd$dZv0@mAkvE$3kpnxA*w1Y ztTGV*-%-i+QE z8S;_fN@*`C>ZN?IopDu~R1iWM5=xE4p%6czp_;oTjTbfxh&*YRShIc~t|V`FswAdr z(mgT?R!4;mt=V2#RO;g9p(F=H=@&Z!wGif7hbA}>=(Pa;7Xi!w2fNI z-7Q3;-|VJq1xj*?4GQp!U3w%&76Z(bhNqZsrz^>aY;Q-q2qdHNopJmt;Q z_wGT1;};3A&|(<*^`$Rdy0E|sKceICbF?!ITUd4Xh`2(*u`oU_I-5g6Blu}SLfNdQ z_NO%*tp0b+3(1)mT2&n(h^cnhUQ631GeweG*)$a#4lj^3R=FXTE#ekWcXuaQ7nJEr zwY!G|{LDr#I`&!yZ&G`&$x7|r^P5U>r`F%TJAL}}kGEu)4NxWgJe*j)&megh7rl(VQ+oJXo{32M|YF2P{Vte*84JY!G7? zPhT3PLCvIX=jlHmxQIN)jB?e9295Q|p*y(s;?qAmP=)4gPMtYH-nGpPJpbYg+d@Ng z7v|>Xs``>#t=96!Zw;iU9hm8hNJE|>+c4WOjjko)=b+p?t%90ZMs{1xyjoV~<1^aR zx3`q%!PS7*)6?qbufCczX@sZU-+w>-bY|!yz`w^t@(2j={ILQUv9JEVSV{gZ9X@pM zBjD1eD?B1io&^RLVzHIqlti(Z&I1&2!XqGJz54LsLtkCGl$CYq->V;iARO0FnQ3wU ze185TAi!%h=97UR3CE6Wa3n64JWn>@1!t{>Bxy+*&#^eG&|yAn)a}n{!s#ZAKFgFr zk=~9F5w1tx_pZA}^NEO>Pdb5;35s6_h|~i`?Q3Ws3#5)~(*;yglGm9*iYc%j4UHOiJ97_eGnD2H`J2Y&n%svmNGLtYk_5}bX@ebw2V13=*IdZH2-mj zrXDOs`5sK5bV&5E1M+aD%a*AJ>+623tgMXUcGeqVf_M#V_8k1{)EF(%>z({kiX-4u zr)8t4c){dgtu)xj)5A@s=l6?LYZr7bDReHA+m;Kg_+St`Z+HTRHkzZTGr5MK+e$+t zeFvtj)ar<{megsfJ&Wai6|BR6@HrNcr}va8|dTIe9bte!YRysG8A>K>*}sKj0&l%Te4(H zFh7ob{m%GwXa_ou%)+RhGnJK*oYB>rTp^{Tl+lDM$zG-&I2r8*11a5)c$qwlpL}t5Y(?S{OBz`c+!I1Z@|mOe~~86=rskCKA^W9Ve^ssvvlXiNS;WH5~T7 zXqSDG84vvr%~vqTkE?0S3ioIQ2((Hd0V28SxiS*EC|i<-ub4>05_ za}eqL)rzD(lj5~1%q?2tx@e#?^*XhpMl0mFisDLEDMA{5+Ph=Nr=K1Ewxy-z(jLx& z!nX+$uF`646{lCPUcGj`jQ+HqIex(#eJP<0@?$s?jX9(ysK<;7j*N(^`QaDW0Rdyi zg#`ups}P;C72B`-)8@hRv~$0yb&xZb^n^8L^6Ih zL@Xw-%!E@dMZ97t`BtYgBw!z$Bwj`J7bV%l&t1-XF#C@YO7f2BKswoEOoc=>F?M6a z5+yk)3H0}+HUyJ;WL!#&h6GdLEv4|bw-iG_u*%Tj2xd4r!bq6qrgyXB=FnW|Pqz0~ zjNaDPh7%2(C?@yX2%FlP&4tbNoVN(Eun0xK{QnX$Fp=g%=j_#jh0j#FzlokJ4f)K8 zScn~o!b+MEIWH2CL%)%$czs1)6J<@GGaYt7>C;a?InQK*JY<_{E{)!&aSme|T8vxXWiRI=T%B3?4OX$Y2$=udk68O(&a~ds=gG&H>JhGxV)>WS#W<`S^I# ziDz_qm;sWPaOr@Fg$bTL)5*X&NX&+m21wHHUlC0(xmUb9#dP-MdsGTIq7JTCn+~p5 zlRboQM)YZAhCObLAb?8tpS7&=`lM%6L`s<7B@9+BWQIRES{p)YD;cM>? z-`o|!t}`0cJZJ_g-1`0uFwv?xb;kaY$zez3WoKN>#iO{LB6b}{#4OIdn;g{bXD*-a zXvag*0guP!Tt#Qw{EM5az0LRC`Oe-uui1&C4yhr~paK~Wd2 z&U6Oi=F@UOf$k$q^atRnTX3k$UgC#iluqr^| z`4z+WY=`%|NsaJ61K(>!ad8WBqHs3mWf(_kLDan{XThX6YQjWOsG=rB`P@2t_UtVm z{H4MM44aD=w9h)VUjO;rzdtG4MSn;FeiEk!>Cf$sGAx0eE|Ig)P=~VZ`DhB_k zD0O<`(r7q|%CR4R3E2A%5Gr8OjJ~*BO2?4sWH7t)q5LOYc!g6tytKqFHJ9jQy2AbWEjAWViSsA6`r`xvg+Er@#Fd9-%mJ);-3`^qA{J=c| zNN($37Tf~B6_u%?V!}xk)&=n+gEnp}&4Nx>B@4OSK4?a&T&|+_HB)I>zM z*+aEzu`1Bj)qJYZg<&*zXtg5yQ3<(fQc68uD5bJU_doW(@!IAs zuY?<(GOV!Pa`F$>pl@ZxtrtE~8w&YNq~U4BCzW>whpAJN;wOX!_LUk+IV`DGtt787 z{pKmj_x}rY`JHFC;=Gsg*Z!Ee1R9OGP9pyw5ZTCi-9~I)lRZZXq8jTEuJ;~S_F@%%Ppd_Ksz@xoAHyC%%NkkS zV2_*ss&Luzipr2ei+KHpvV(`UlI=(8{;FvxvABK9tCwXDx8A&bQM6g##pT3%i8p+k z&`#hx;c)IrZI_(?05N0d{{E#Q1XU!1AlG5h5LgPzjqel`VbU&mWQ#U;XeiTd)yAXv*%X{PnCPJ)b z-FixStR~TxmXIiT{~y*MFE>qUH3O~Mds$bXJQ)`k=w;v1Qd~T5>_hOq*IW58P&_TB z(jKh3lmU;B#LM0FAyA~o>H4t7xe-c2+l)-c+1;ckPAHWRX}v8h^r6J(ai`uM!7}oY zmU(-~!;t1%rBNc%U;oc;`or4fOmn8SnU6L_HrH%tQT=5-*Q6@whsZ* zrJchx$a4Xi45OjH?-7lB=?n*jLLt`o@O}tX8v{A{@xgru%87y8xqbVg1Hz3r)lcsS z%d`n%*BKjI%t*^H2bTxr-?(QfxO+2il9DQHu z2-Bt==A$u|qI0*qGDDbz+18Gjb;V^KorUb&8531u<6>hb{ZUot={s5#6*+eFC>nqL z4tbr%&6>f23J7HKz`$T(7s`2ZmP;lo$>-9cpD|B9WEQmB7fhl8_3KK-Vzv4q&2qK` zlUg*cdWWKokp^@(rnv)KM#Q|ZQ{eTh1h93E=0RY z)#1l9UgT{HS20e!ZGn3KxtNHmelvT7ACSN-S{P4$Q*Wa1n6-{H_( zb~8;d{Orcl+o(g-htU)KhR5=_;IRxvJ*DwL(?c5I7TNo@Lf3p|pH(>Q4K?EU*ysl% zVqE9$YKohM5wxYiKRg#j2_6%a;t|oZ84nZ3l zrjAvTdM4|F3Xb+m_pc(MqPo2rkJSj&W6pSkN{m>Nmy>m0U~Q2w zona0}Vo*8NB0232zeFTK1wGcDyl^)Lmn80pUJ-yZH9TypVKSbc;p8*&+1(ZRUP`Eu zx*cVXCY(Rrzb+ND>Y@@|@Y^f#u%=K-ss===v8;cEoaTI(HwFt9APk ziMya+-a=!i!3GGfh%{u;G!RTWHU`IunCkU#QwzHNfVSvM{^q#(rBH9uV6r#i-i^7{=!z_fossVxrwGW(kT#GKWjZd6t&C3eAv6I-Qx1`<1sP*?uw?SqM|vYyOEan?o}QiaemY*DCTaGpN<`i zj`nkt-@I8^ID6FG>!Yyq?M`an(}A|rv)#ZZd`}LdC;Z;#e>oC8sT{ofIB2)^;dAuC z$%Xl$qC&0qb>R*_&m8gH%gp%yB`>v|1MY@yaMJ4}cek6X43CSQ{AYFj z0KYNn=<(ymjHV}&-z9HYs|GW*wYj+oDt~8Z6@pN=kP^|%ZY02C9&GL|N|3ie33knu zY$d6X_zd*u#vU3q&2B)I+Kc6^d;{j+0xwZ6o1CZC~k}X_@bM` zoBAyTTh9N4&K=K#cNeXx$6aYy!F)4KNj_kE_3RNrKEX8`zc7RUC)B2Pf^MSrCCVl3 zXSAlk?Yju}#!`Z#g!n>@pq6Q;ic~E)5Ai^9>1IXDq78r5bl;r zRFbm3PWFlre~;ddPM-a}j(ze)i^#TjUsnfPMc&H%Zk*BPhM;v#JR$}qWmB)^S zhIV6r+BUG=zJZYXS4<2VFeYl^q;BH|nhQnBvMNp zs4*b{e!ldW+h(%1JD08dSXMeDpXj!cI*&fdfBosm&Ye3C{`c(V#>Oiu!x)rs%eO0A zLNYQk`c%FhZkS>iskqtvN43A<;~lTRwqzHQNaNI-(mt&M_h zL|j_Y@Y8QPjPs3et9G6Ji=2vyIVITPGtomkb%2MPo144mK>vxzG%#7I*V6-}hX|75 zS~=f1h*Sd~*D6M>P|**_Hc?S1Ne8C-JNni;IGwhGXwjn3A`)8-DjV>j4u`r?f3pWOCIjX*`f>O+$B$Fd}Qjm3QL0TYh9i=upHtwPaOx-2|;0-nAL759E zqICm({FLOFeQvF3J!y-0F%Q;Cz#0%Wc7%UiM4$(Jg^u>}q}+nMyu4|qf$btN#bhLS z4T1Jp&`*2fJez5t+qP0B1LNd-8elQa&0I{sse{O;)i9M+_&&|1eR6fT)Ae-p4;iae zsZ?Qp(Oxwb6%|(pClt~=z5Fr7ow7w06+3ohAYC8W(V*9hMLNlyR`9*R>iL88-y&TM z&+4mB>-`X4xK+cfU%!g$&l7;-;p(Q)6TOYA>u;+!z4^+U$7}w3_{490f`fzoJzf8! z)9KE-&Q~D{1VuXERtVE=5Zf@1Lh87I|@$-X0p-+Zmj=U;KbrZuFPY;=H zVO9E1R5*y8VVKPxp>YpeL|f|FeY|Z`h7Q7%OdOQR#3r1v%LX=5E323oGkY#NpO|>w z%UXYAn6Bb7iHRB;Nff9oA&rgA zI!XOGh`%#}_+t+fWCr45@?=ZGoE7AhN@bK^S#&J(T2*jkv1Wl1roXxHasf}Y(bpdl zswc%u8q5OOE(jh4YKQY;=0P<^ikMB?B1&66qXvtN8WBuSm|w0kGt47&CmV&?IM9e! zX=PT*q44? zpd?@P8ZyXpa^xsKpCQ3PqklM6*~58&U%>Fe13XnQ)4oEUHIIbmZspBDoR?J+V6KG( z;O_%=iW{+v+!Q%GJW)PO^ z*>ix^)!x`d@JwT4Ntb(HbMeWbeW&M5Oa#uaOZ=G=)5*;96tw``73YQc4H*;^Hc=HS zzjVRhFRm~eo1smZtlJQpyc4g@q=d;zQ6cR7IZ|pKw^@j9E4+gi7CjY?V0Mk;Qz@RU z7k*KUo*EmjjG2{{`%G?{YflSvL=HD*{{Y?(%n4{7k`LLdnLC0rft{S~;fGW`!=3F# z*KbKwFp3-?`(%@(XEhqlS^H?JEFG5Jye8VaH!+b@D{d2o!a^r;@C^*CM{F9Go|RRR zf2#Oxh3uuHwKquM;lqKv{zU!c@|v2O%T*0BRd!}tT4n^i$=hksiqg_ZnpPv#X}6!L zGFag(c|I+o=T8!y7S3gU>|aF-;s7sKFW+#)bR6wDJFx1#T|0MHRA7TOD<$5~%@i$+ zT|_rpq8>e3R1uI)Tn<4dyPBRs+OY%9`yz44rtL@TbtdbkeDA0?P@FW@v9*=kMT)bM z)V|oH)41B#B#XNR>3jUL-QSCy=mm46S2!%;Sm|HIu%a=s7SD9xLiXzbS7?%{5Jz3hH! z)4hkq;lqc2?KLL2FapV8z66C1i}Lf+vedx-Gvv{&AX~&pcu0*MbY|mg4Jp=Y$k9l{ zlZLSdAqZdb{Lw3w9>3Kf=|$B?+rPFiVe;~XSQxsNSbKS8W@kRuB3AijC&awyCg3Mnh&47=8)Dn z|Ac%$QuJC2$i~c#cfWV+aLR$tlhlT$D60vGa_gBhT6u6jq%it~f6ozWSk*qkiHuLk zYnJl@2Mik!H*sS4hz|I5rH2Uk%G>C5Z$=~u5rNYy3#4@QgG%Xg2B{k>LWTG$kh|XUeF+-*@cTQ5T3k!aKZalU+%2v^tRi zmSUX*c4OR$#ibf!WA(-zhe&r?KLOG9yriQyZ?FYyG|dKRQsbQU(i{k!&6|%ik-&~` z5)h*_HU|!!Iqa63g$OWaLxKV#a4GDk$hY)_Y2E5*D>Mh{0zid?rI~rm>|;m!pg9n^ ze)5(s7M89E9P)gY{Kbqlv!C=Rff;@kgAW}5%Z!Zs3@;`T;3I|A>GH!i?+ z!u`W9+;@!3;XN-T4DUsR89!wd=6i?fo+F|sAG8c6J2v8&>zLL|tX^0$G0|}viCa}t zC|!R0EgV~Ut!e${?0aVQhH9D8roA57CXG6mHOj2^SEBu{?0F`E>`H?+3yU0JVcV3O z9~$VVW+ngS7OlVF%DuAu$m=$2-&y z!b`YE>9_H4Wd{UI1kQ8r5F7kNTn*h5b$MxwDUDX*SlUSgQ|N3-} zqUt<6W>JUAy9e4!A7#kyqq6jBKRfgo*v{1bwkI$q-J~cdH64lzyUz$i5j%TL< zlGMp5Daj-d)W%+7##%@%B1*DO=IoPo^w5O_HF5zSfLq)oSk~1kxy2XsZreAk^KUS* zOFTEOremEH8#Z!yz__u>s&9XC>gPLhbg;j#j|!W%O=OK}2;66MJH#)Ug%S3ygdQra z70!QV;_ZDSdW1cp$q_wydC*!P7SXd9&>)v!JbNUVIM0QDcZCu?1Te>2X2fvp*iliD zVQvgZULGIA5k>o#Anf9Ig2T?@Lb<&dXnIZdUh-d3g+!i}wEr+4B5RdaCu?buI=Nc@ z^%tR8W~UftiZ%aNW$Pg9WE0U|dzNH#8s=602e(c&4AI`Gn7D9q1wnT*voJS?Cp@GF z^8mxb)zu?vL9VMSe|zE%Yl7;OVa&Tfv@vVnc%E%288QFp~p9SgtQ(8oi~ z<-Qj|JsP6C)P9bRV#$xQmE;p?|GvE+554wO?T^A%+*qy!K0Rt`>TO2^)zl!QFYxg& zvg>H@c^o=XuO*^L9Tz^ia%I-6WRLUb&-aRpQ`yzl*2-g+^YiOdKFN_Kk{mT%yU`~y zHYFCmQ7$r+{D51(ZE=VC0qP(^c@`pZtyZMhi-;OF%0qlatkoZ%qOiI7=;6mYXm8N+^e;=sX!2bXa_g(+H= zUcLm+t44a~?>n--6Ed};f~Rr|Xq3rj$N|nJ%h5a>^|4aXL&06QVqKY-SVW>DD?5cOAv>R%hq?yldS5<&7<6hY5(Ni`WrV}xu$l=D zHs(%R^?-i$?8qSxgAfM@;%i@)9j+5r=mrFCmHcZ*8cp7n5uElpEl;mU6nzy1N(?k&5 z7(WTj?{{IVB-y0yINf~!*BscKM#ASb77Cep}X3#?AHOy2i**7nn<{7^zO|K zW!rAmFpIadfHAH-XS{Nh_V7tChJ6;!FbEw~I&tvv66*;WAj-*w`o?95xjp z`&>q9`=wLE#)gG)FZ^c`K6f2JbG|ptm06fkYlnut2Hk_tcIAZkh!8ozq~Jz!of{XQm{QIZ##!1G+r2$4fnA(&?kZZ2Yx8`FNEm4Nj$;#0W+m z{hXwz0VzgYZs+>j6s; z%2BE`WD6FK{uEMeO>I5gAZ%C|Vhs0@RTvfxh%J*r@Yj$U-nQb0Cza$?rvH2;`QiRm zcoMf&RCuD0t)X7ji-BC6%Nv5)aYpSR&>x??%PP4o?_csPiaSmYu6I(YMASw zyGEEny(nt%ba8p7lm;myw^cH7#@Ci0ky9?%Wdnb|mk-6L-v>A5A@EcxlFM!BVfl^y($YfjeESQ8*9=f+~Tbx9v>Kv}FopMdFXK)K!2lV(% zQ#^t^mHECcLEp{@eZx+TkR_Pi$nW0qnKVp#7vY%+c*M4-C@ie&c;D#ga7N6CHA+T| z2w$xXd&v6-|MJm1Qm`ioioGVD=XyeIvZS?S=pWZ>e!5*--5~4ZHNaqCEX3Bfj>uMC zU*GWSEqUuNKVN}O;M+U44#*zpNgQzJ79+aNSXf%yy5Ii(`|oRRFgR~1vtXH4ZO?|^ zt`m26oBG*veh7S@q$vwsFo(5i7!NZ5SG;m{^M$F)N?-T8+#tLTq_vxGuK4ntl7+h7CA z-!ezI8;V0U?U{`|@T8Kw#SB}jBv;#RP{ozZTHZp+@-VnKXj zxQ_!1DUU9ds_AdUP$e6RMCV5)&JBn8;Se9)!S~I0GjHd2UNn~*=Y6IgXqF{z&}l@M zk~&^oE9Nrm0c)n*eHOcHP#!ALyzQDgbcTPzzXh^13 zLvIB1<^JK1HTcKV`E|4*&X}R}L?(TjBmG6^{M=+uWVW^$lQDk*u2;*SJ1M$HeSLjk zrV7TCkH{HuUSV-g{zOESZR3qOq>hoo1WrTrD#$;W`52pXh*_6P^+l05==>fZwN75M zPxboy_@1)&ckkYvM1Q6-l{lZw9qMJ)T|(A&qS9G2cmAvr+mj}1Z)Xc0LuV?TFrBD( z9yis|JM}OC+*N!U+&_n@9V5_V7^X43n;K72dUC%+h*502womF)dnPf&htQK23+a-C zs`L&&%bW7Jw8Fx)I7Dx9vz5~sP?4`nR^dWFC8-e0js_N?cdN8I;TAm&=RW7hSPDvF z22~nokUxDtfeX9qbVnn3p6NA9N&c&$&kC0-O12TINeD9`hSs!cyjpYh%I`Ou8XHnm zw{45Waqy_wYptuRul&~7!YF#Vy26Ti7=hs` z!vsSvTi!A@3aNVb@y;Jijy3G)#@!KyIR-U-rW0QrH_~e~u(ddFVE>6@7q9-+W?tK9 zo$5PK@}Kep2bL|vT_hSAOq|D$AOHGdoz~KM(()phh_f?Nd8+m1)@x2!u*^v??J!ldqjN7X5?f2}6NiAq|$Z!T$z#R}UXq)eU7W#{b)No34QS8L|*-?Ck)hDR89@lcvyI`&;a`K+Y zOXv%M*Ea!w<=`VgrPpQabXqeZV`lKH{u(BlpDT2)f?T@9ThKI$@fP|oLUEbgT>k%o z1H*BMvzjS*G6vZ&*J0V&53eFEA47Dm!)eok0wt+dWaloV)-5A% ziHkD*rKTiyxIfuiH?pepVOJWQ=r1?-4KdXl}T{ z%a^%;CU);-FUP`JPTm#ADC$1hrZTL+#o`6brcE>+b)l&Azls@j<8VN0W$E58aJ*{l z5I4B;wBj2L%^r&*5X4N|-6$(k|6Ep1e+HQcIdcuKtQcjAb2BhQgCVIAOX)XNSYMBIe6cQe-Y+8c6(w>PH38Ib9W z^x(n3VMG06sgUHaOwmeX{f7<A5hf=+o-F1%F3zj*~xd(jA^M0S3IqTh=1|L9v;%x)3^uts_*d8DlQ&H-gx_3?H60OZvC?AmW?f*p}I#&&%av@uIwLwHr+-p z3j^Gz<>|?fxACNV=XZ+%yVI?zW}T95&rc^d z{irmjaZ@{ihFNWe;}&peMw4?WVbJAE8951}@9-(LHo@YcEy2c^Ae^RNOX_)!Uy9nY zCRt5ZcA)e=)Z!MQtiNN~+DiA=v+|2(jzbz2Hv=-R zXhpxC49FL9jK~)S4yZqL=n%DVo_!+%iyAFUn059ga<-+;+PcnJEbs3wH}KH89SXni zV56Xb)sxi*Jr*bjsxRrULERlF>`;c&9SZa;VQ<21RaiD_fE?nOU6vI}4?4ZuxrGjU zlg@4Vq0j8#U#6*W{1w??nEHBXOPr#GT-}TVfwqSIFpafDy%OM1%F7B@I>KEajuOs8 zQCp7^_uf0sRFbbB@Hn^Q7V1Qxj@DXFBr=$jT9;v!iGp_hI@yLkeElsV#;oJidk7 z>~xf@>B7@|-DKgNU0YrD9Lb~`?o6r(P=$cwX<<#$bX=2q3OSg4Tx8d-6%@=IabHuO z{XP4g&bGm|ppNL~&6_PcQ49Wy0ccuYfJC6>1^&GlUk!UE0zINd%LF!49M?$WMJG?5 zluY9+1fXT9R^uQRGX_?|wzf7jw6@|810xngo!`!-R-a{9&VJ60rz*+YLLA(7@;n>K zRz%>?*lhZYARl@9HWPBM4++S_fN>& zug-pR>f{-%<(XfvRQ1Wq%1TeX&wl5OUQG^Sn6^-vh=q*qV%qjQ!c63LF+?AU%}x#3 zh%JeRXy{|~C9IgRQCrIBTFd=J!OnvjYkZpV_eaaz;~iV?wA-m_!vm9#;=%JRmEBA$ zb~{K&AX1H6m>&t{>t$iLqY=eV_4R|VLY_Ivj=g^R^y%Mh-D5NH0l;9VV}PGQT9LqHR zjFVwM5Zlm1>U>E~4rd$~2gqj!V?Po@@7oVvFJFy*Xf5=NR3?=$nBed(^$>dw3y7K= z6B83+Z`FG3^qIS)2eZTn*E!k@w5&Y#+4gno*1dPO&V3+0(U2IUOu->ZUZ!w;oRyk1 zc8H(1q?9v>^fC$ zeS>I9yz;+2R1kUJVT3CyRT$|?@~q657%v5TAZxk4iA#*9hN*H9uZc^(Q7Vrf#r^jD z?zlr{JT4~G&*B$M|3hTEc%uKgXV*|uN2z#C>G|OFa4^pSd2^k}%P%@5C1vs$96QD7 zlr-FrxsGp4GUVt{rScoKpz<%G*(Xlx#D6#G<<_M<^`vw>JM6O@I?7@dmBnlk)M&c% zamQI1VHOItHW?)(PnTkWE_79o0?EH8Rk+LJ03|*KD2^WlsF_tzi;t2De1DBAl{nOY zNc@D4kIxdit+>g=a)kxwU&8`_`J?UIOR$BC?WdFI?~t}5d6V_~1T!SNleC}6qodOE z=+WRP5BuBjf-*iMCdL-8B)e0$1AHVvBsxayBCBR^n)mX*FE0xMoe#1rv`D-ox`}A?ILH5XPWvh5TNkUsvKm3>! zr7r^89W^T!{%y41BWSc898UPTaqX6SlzK)iDIwUvp7lAtouc;iDMR0D z?lym3Wd>T^29;>=+p|`a{m8yDb(r_9W5)1C%hh}L?mgiX6&;nOBs+NypxFU?4D1O! z|Ndd$-Zv1|eBL3M?p#jVSoP@X>^?LE3h3CFbm;Xvd8W5abGY=9P8Bf*mJqpK@8~_) ze>hBC*Drjaf*8m#WQyOaY}PY6>%Xec{OhAVELv5xW#3{S~EaoEe zl!FX4H90x)N!OvTiXcEK6RYDqR5M~ zwG9p)>gLjPLnf1g7fxw4Bu5R^hhL1|u`E*FY!!*c;(p#G++wd~QlA!fTUJjhZ55XI z&U2)Pu$sI;d5T6oAW{JTKNc!A0u7kGd$o^)lQ24~jiXZp9APP>BSfV;| z(^xG(69o+K^6Eqj-}2mK^g%-ZCE~(DclUejLf{w-TIpTZA!9uOMw>U|ZkSX*<+7`p zZYnz(7IxGOQ`!CX4FL}`ZC-cz!&Vu`wxfqdqvSRZ8qkGqBcMxS&%q{@bsT~0&Lhya z;}fuI^Oey(J2sbTTISd>B{>QMDSjiYhaA%a%nocF)A@^b85Z-54ns#M-kqVe**f`= z&F}ne+X&^+5ou^>s=HKs2U{?HLhgb(@j5%Mp@D-UO|xvd-q6r60on{LZ(y^200xY= z>C-?AV#MOW!Ckvgz5Bvy;1^P?Qv@bQL8bW!hHhH+;J)^G z$;og8~Amwo+w1NG?5WK@KCUMwf7z{)r)~Vn-)iZ2~O5bWAhC)mNdLFP-+T-;)~vZ0L=(DKapfgN=m1*_Xwo);St*m2xw*xl zcW;0*sjrLY^10~FoD(&2wWtr)1v%x23Qh`w2jAv->HDtMj=XaH;Adl`CSW6oV zomKzHDWQq;rUp%Q*};2&tk=DBD?Bs!irtu)_{{OJp}?$(@*dfSR#!6W^++y@t9yaPhwD9yF&=ZLum{_>IXgPw{L7?>xLNvC*8vhn~jh*WU zZvILuWyOE74rA%5rNZ20k=XaY4D0Bti1k>nVQ;q>_z@RYl3hkl4FMFb%vNsY>f++- zok6Q@fK2?DZdiEDQ$saRE%OaB@u$&()D+E)xAZ#bq5|b&&;~ZtG;<&=ui4HESBt;; z6lR^3D=%EQc)ejby_puI63Nl4a7ph}8j^)J1w7kk)GL4?-M@d= zr&kP?I@^;6FCmY;`{*f2p%Dq!WP_5_u;Niu|2eY9s&GkaJRJSgXQVAvgHXbPV4dlr zo<2DtV?k;h?gUt6Wno{}&|>}9rG`6O^Nhp93mEXIOcbOF!aIB@0x;h)b0k%4^ zSjrmoI`;Dyz_L`VJ~5bFc*U4a{>5)vJ@cqov$eQHs*)9gb3wmOO2;0GkaQY^M|Jo3Dvgl;$}(^b*+f&{|l?NJG`tn|BZo2zRb@-E+rjEElJ9u!-b@2*Y$N-O~(D zvnRJ?GmUl6PUm(IUiuupUU$K2dtQ?EeZPECu?Q|Pv z%a?c`rnP2=sz*9t3OI~Z59LRS=c~@~P)3V5l}^%|H*a0NTNm3R%ISCWW;oeFc37+o z65peZl|$~mNx#LcrrOw*nzQGczumtd+E|uhh3JcmE%5Tg1pvhezeUrn>Q9AZe6zF` z`^&y>J$t(5iZDN)0|u;*XAd3w^Hx84u_`~!_V#=#&YPM+U{adrFZ=Ob*jLYaWB;ls zfT?GEfX}$G-hRD%L0ns~tjlnJOB+JZTx;tBrqKu}UNrv`tbdYeZH)qJl!GbxPhS#E z3#fY6OG)Wo-lLIX>=F_MHaAy2=G>l- zt|OOF$T8>PN?G@~Y8;QrW9V|cyfW%fizsI4!97aY9>MA3v6K3zASo;G*J`Wu@h;S^ z>M}lkMI?-pM}@MJTiPnLS_x`xJ8@kny?$aFT7f=Jg}{2zyx8(L)zD`Xxsoq>vpjYl z%?`GQmjYOQsV2f%mmruSnC z{M@0doH)SWnZXP`NZz)}3}j9rNU0?_atZv+(va<2^!m)q2*w9RO!i2ZELoB?3P%f& zhQiS=G>dKzKEeX}0eMjt_RArY3_F{@_whuF)CHI$5*0#j1BupH{_&w_Ac{M8dVtGr)fGk#&Jm zJsLq3UM@~G*x2A0h#^Lw1sLTsDt^BrTd8FB z@88dTK+~$8VxED7(`dEUb_0FnjBTCMALlPO>g0`=&;Q|AqY%k`2HIh85Qrzs@~K0R zd!0`fjN;F4Db`5{CFno%c-%tN0Ys#Nvb^85C!$K~;n6gfS z^~=X9{)1Jys;*47SA`0074>b8pvtR{NWwd(Uo!_xu>W*9Q9->N+O6YLL- zt;FAGoffaeZDyDmoD5-fXG*m4)~lzZJtUa2pKlJxiV*yN&#}?&FCZ_!<$f@kzPXh! z$o>v>WiDxxU>kO6~3(}!woA9@d6jzPg|U+<$0I?&cD+;qs5Z{&a2aRww>NJ zbb8mhUYPJ5wbuGo*Zu+9U&9|ipS}ENjhpkIXTRKu*wuAw_nkiV4S4Uzs%l96IqO3F=hZ&$)S`CUibiPUF(EQ_}C~s>vAz^IvfkW_{ zeQ_WS;+WEx2{dV+al* z4X~F|M{1eK-=FwvH8#;6&TK;^V#dF?)X>mUDr>HwC|8UI1l8Y*V{Pzj++u6=PUc==+UFcj>|Wc zm1!;axHvRksFzua1h1Q8XNhlliPR@%UkdgL_F^vhXhlAHp9_MtkEMO_60;;J&Qn&6 zu;Z^AWzL~7QkjE;IwdWA))?nL^pvo*2uJU zX=X&^&K;pwsc4mzOPP{EjE$?pAUjh@T!%zsEYfC=b@%8?=Y~RF2cu7&d>B3*%8fN+ z<#g$qUe~|Bf8959C@wc9C-_5nvm&C`lZ1r+AHTYG~{xi8v-4xh+AlSdU}W(fmM*W zjlthzu-np#W%dq+CauWvcEfd@=k!JbAIgYbgd!M!5}En}ED2@1nGQo(pLp*SopC(SqlDnKI5bed_~xm1L1@p{QB z+AGs$%F2~$YUO}Irjd~%)!%r8wN!Gt0sX&~l(9Z5DfPOVPd4rI32fn`wea!L>wSDK zT;RLNUmvPmS2B*O)0W2qx!DHVjQ0v`H)8QC(GiO)E}K z4Q<#gjFlWuv$b{jeh*wVJA_ZM&!K^vq!!h1+F8Rxq|Y+7!3f~OfCOt-@t@kX#Rh5+ z6{F!IUr0XBjly?0l}Q6;xUV#19e)z%1+->YS=mtk>%lk6KE#Ck*Z*toYQUl@_xyX# zoEZifz7aFAno^fbM#j3X zc@0g;kc(u-ddZMjLNY}(L`tL)ah%!Td(Ij2Ub}7k?6c3abLM=%=e%G4^MC)}Z~H)~ z9;(z@FxRIbOKmZGtL9~`)JG<+E-8XfLcDg$DkG`FeHe~H`a}H-us6fdQf2GAH+22W z&pW^Vvh9Pi1lYK(L_9jWtoGfy`{cQEcSAy8MPR?t`Stnkx-IdTXtYpK{$4}l4I2m< zSY%0f<7Jd71zA)<7qAu1H1!ZPoq>Q`5*^@rh3~=`Rm-st_Sde@j|vzw-4x+s=Pb(T zl*fJATmI77DTue=eMJk!1;|vRrc4hFi3m^GOk)OBOM-&eeAlmvi->@3dk6sP8yYe> zc)>=h?%ttzVYz;;A4eXDR8ISoNu6q8r>3qo2xY5c)}p_vc=v+`FOXp1!(ejZpwx4q z6J3?C_+dF##>lwbq_G48_W=-kSe2EPM@UXm&k?cbrr^zroZb!+Y3qZpA6u+nLkqD@ z<~b9dVe(yr^;OXkygVYhs(uh)P$KqeDxPwy-$x?aYU~l`P832&#!9C9s*Zo@KBS|UaM2=M z6uxi@ix0!?FTvaY$G%md7N}_zFTvkqv~BzPZ`p|LR)636LL=DH_drj*2NgoWdc+^_ zX>0GhM`WYJ!dpK1Vu-j#CPaz7G7V3H(o(1jhPC>G4X`RQZT8Xn0g~{U4-^ ze2^#G8l9ApGJ_kqXjK-@QcF;Uu}aPf7O>!(s10qYfeER=sKuy(Dk;wNx}Sn;s%bJ9 zh#GgpwCgu`zC?Ieo67r1N&b+o0Fe z>EZ)gyys9rcwFR|-qyyBzC~k4q}q#l8t&)m{kL@;!K9>)e3*)fwWaA_k~P8{O)Mje z^KuD3|MuSBoJ~aZbk|P_qoBtCp%B>ZV)Iib{j5y~T`7+S(Ie38_6a0F86L`NL6<03ELyZ7}ipfO+jgNG)JZ7JQ7Uig?|=1G za{{!MYp_0e%^+SA^9@5D31|lk)^3I)-7*zXWdJWQ87Ryd-hIIC-D-~zw^F@B@r+#8 z-`uZDL`B)c#6rO^54EG|BkZl-c5y4E7rzFl)Sq%GE~fS^?WPQHHe6o@*&85!C!(x$ z4SFG5k`Dt~9-2c*>h&{D4ETRl8W!brLa_$Nkej4)XZ^$c&*~i+W)j9L0r4#Xq%XQr zs^^1G{5(A*mYqpc_t@@437<(-f$5$}STK8KWltl$v+`d#Cf!E1yg_GgVmIm_m}WY5>K%nHJ4xOayRJdRg1b>8 zW(24aWQTLl>8Gl_5k2A@Y_!Y07kR+9#62ehF-<1SNz2S#2hvAgUw>)Rq76n6TY?~s zyu+3(E23sPSlD%`=-5i$#o5%n%zsvD!8}l!f~k_vGeJEy+bXMDF5ZTpAS1JNeqe-2 zL@HW3&9TAlgAR5^;<6=%m`A-OY)ttqnI>{dfW==OJulW2ixKd#$T-_+45FXii-Qm2 z5h7BqhrOR~XxNL{y|voKi|M@BaGO)kpFhRdO%pX$ZISI)HV9PItRjG)faStA z#9=7>{+&M!8cE@5zu3J@C#G>R-^3(V@7V2sjfw}+?n!(jEL51_s zj)in(19m}uXk_3bE5g+XO3xx7JEheYPe4!`Hy7f)fN5l2Vf5r4^vshO<l)W*h+l8yBA zt0RpCB_`Nrh?-3*26}DGLalaAN@@tHkBzOT9n$jEP48)@$K+ifCc;xW7Z4-zT=OAz z%~sTQbTl8>ci!SUJUGzS`Q4@7HfIkmMjJ5a&&PwodQDjxbM5o`zuXx&E*@X#8Sb}^ zmZn~wNlM~bKq(!AED5MbGx)&<;JV$2r+ek>*>BIc4mjj`$8VVc5541A*~#qXABqsU z74P;>PfuH%TlfT`4)^+{7CyT$ZP~Kyr;;#g?|>+LAFLhdQVpE2gOo8(WrHyV42bNh zc#LKN2jWOlc6D`qeX+a!qc`Vcm|Y45{t`iv59NVH!4OCH!QEyPyuy;OBnsO?X8(R5 zlQP*$O-(OJ5KBGL`Ei5a4_KRk%iry^-n>3&G}>>v2Tq#{nb7n=_nUU)3$_!kje^aT z8R8_@#wAOZEMB(Me)c^RGJh~@FJ%40h4xPx8XFoLtAc{6MBNdUIhj4+YSkz6LRj7( znvb7r&zftgE4kP?zvXIip%MA@5R2PZrP5@ot&NK#CcfPN-mP!j4!luSy>H(> zxVNV+Su(@kR%^nzMREO8g32U~*>{lV-t_W%b1P4_ifvv>>z616Gq zeN4he8drhN*u8_Ai$D@|L%DF_^l5=!etv#*CLy})b6K}^N!p6X9z%!U;D6^r%fT=Y zWxd5k<}p6p;RsJNfhnP%t$;W0+m2HDkQ$mgO5Mx0;`i1^&0qHq^ivWo%f0$Emz#1EaRyeL?1m}R?7Ca0uiD&Fq;{r9tG z(Y3A)Y_2=OlT4g+(wTknYBwoePQfO7|Mh^DO~9W;x!PCV7LFm9;dX(opixAfWx z#%&dK*TxlIc5?3AlNLRcZgvn&VQ~3u7T+-WVXH`pW@||lyyHDR@y>3h5IUr8;M;Ck zad4id)1(({CH!i7MXW=)<%judZ~`t033Dmn#TU~b)30dMTlI}@NKPqkP;7t23k2cZ z<5uW$sEAgC-dylvGD+s$yWa1bE<5|kibu}Mrb`eH*%W!%r8g(1w=yuWQiKxlT0|Dz zbXNDW!IA8!AcvLf?r@4ZE z%zAF4k(dF)Z-P>i_6uCA?vf!et*>*~5(H5!e- z(xSL?SE;=EQMFVvBg#fYZ*B7{Dag%xVZ)}OtC!vNPdr_)c1><(#youBKae5vA7(x2 z;Kyv=zV{@g#x1qAJ@N2w%ubj(b?V%uOUItvF1^i3ox|gpZPa%O{V(`7z}e37L^)cR#QP163hWnz zaaTTunsLwDM~}X}r`BlH*-t`W{S_kZO~SkflUV!6S2#au*BPa9#n5@KKwRJlF&N!) z;)GY=C^?21qw48VS+6(OH@9E6j)@Ml_IG!5boW~W0zAxWt(LU6-wcX2rlc4ZH>08^ zkMp$+4f&3nEVRfx)Og&*foq@FR_}hR>b(Pv->X9>_^P9qX68PVm7W^sbFH&XRiRd^ znG=?GPJMOpHs_o)+ilAkMenIY`(FE9MTH2pu%LFzCFU`kFuv6@n|L(8*tXM=6ECl- zB97mHBO8H}Um^BGWJFd_0AU0f0WIkoF|s2ns-j{`fDqJ-GQz{+yT{{c#$OFAP|oHZ zOA)C36y7Ww9;U&7S}{tA-+-Lv0;5OqtQcornsFX>V)qQv1YZB(m0fSXPL+7Y{x!|L z4IiE!)*_6+v_~{wU?4lM0bLF9nAEX3u(CCeVilZy1pd$WJR{PJmro77`th+CT`3*d z%<`}wIfa511h(ws_QM7^Q)fG#WWnGlX+l+bHF=q1gp}KCZLjGa z`Rr>UxrnsS<_c6hyHlGFOKB$GW|kohKxha1ob%3eKb^^TYM&F^^%+9O2mNd=tTWsH zHaj-|T7v=l)HKIt&O3Eu>a|~y`OlT*?_)f%Uz}VvXiVbP(UC*~!Y`#!fhx>2Go0*e zy4ZKWj;j^ll$LfWJb)y1;7x##8ZN58y+2A1QH22G6w8w^I8t*Nz_}R!7dA}bkQ<|c zbX)X#slS4eOeUp}oj9S>(UchoPDpVxlJRUqL$s83BGNv@b3?Vj^!Dlc<^7yS!}U`H%{kT( zPI}@vEw}RSk9RDOdW}^L+_b62hs{a}m>i%A3-s|G{G_U?s?qA}tJbL11$lXotCa2U zR{cI6-CfEZVJAER`HuzT(92v=l16obUeD$%RaZ2w7G+S#L^yno2UWl;?tFi_+b1m0 z;^!VPT6GT|@W&1w-3KhzJQ5UNJYOQicK}DeO^>zOiQudskJe1ObA%F!tpnF?g)E1S z;?n4Y|4Fo3Z;c=9iM=(CYQ;9XfI4uRaVjOlYZ#?!&wcOhses<~a?|18Z%c$tMILOg zoobg{$2yn&XTDX0Oo@n?Cr~DTCPzJrih`FcPR;6RIMRIX2BB(+1F#Y=cYj6~v%9Lk z?YjvxABUyJ77VhIwG_pH-j^ZShW;bj!cD+;od2dI8Kx+0O8e<1{xC6QSA9f!`bEz%nUs&_jL0eA408ff5Uyqc+Y^APcU_W z-4E}&sbn$K@6i+BuL^ze6VGijp%D*(r)d?IgX2n4r@9Rf4ze!8cdaAJn)mxP(P_Ck z*-Mw@rJG{m0B9y#LpLu9bGg)d=1j+xo;w~8ENI56`i^fmo6S|{hup*G=wc(I6O&Ws zN^smsh;bexr$ZdvhUhT&@XvYKxxb$R4>!u5oUe-t2?`1diP9x3h7rKxgqWBp;~c$yzR467otT(7b0)s!ctq$a;bWVd zTfeoko*~gt+((Caves`~n}dVLdaxrm5P0Io2hUJ^EfUu4l;K*iCnwJ%VT2~ErJ)Ag&M%?9jQ!E5Vkx9Xu6h*H5f-J zRp;m=imT|rN9_vf==Z>gC#HAOa-jLabcy;_zn`d$`+8akCG#8|4!v3UUMRIss>{u! zK`b+HwucH(g21{EZP2Y;#j5Z(fpcl29F4GTa|7=0$tKy^J-QR3q@L3MW?4=S$>HH{ zCB97@(VU)rN~GZRkew2{1kJy8)B$fom@hEUALZ}+oIQB0LV6#@R*AYIdL%}~HEhN3 zvO;a~j8hs7eE}jYOFR$dCD@4<7V61P3?fau82D6dSAX2QACFhM`%^SiN^|MSyUeub z_2fFc;=8FxibQ947i!Tfggq5<4n#VpEgWilMky;Q%*R7Lyh4hNE|s39k+tO)7R574 zqzgwH8}FR8OiBZ&5Mo*4+ZOsKeGF2Sv-#kz`MsKbafo0R2f}y*XkZ&SO)Rgc2^;uJ*akr__lbI@fYWUMCIS$e|h>p z5jO6_E2G!b$P$$IjKtePkjqGrA2-`2JMMb19)gj_X08AqvjW#^B*g#yz%}mPPv}sd*mS&VfdYXO(ddIpl zXY2y-Kq8k&+l?eb9|h8@E~-IM;u2I7R71N}C@=VYKVM2$0 odek + @@ -72,6 +73,7 @@

speed
cost
+
@@ -79,13 +81,17 @@ +