mago-0.3+bzr20/AUTHORS0000644000000000000000000000047511515544761014257 0ustar rootroot00000000000000Copyright: --------- General: Copyright (C) 2008-2010 Canonical Ltd. Authors and Contributors: ------------------------- Ara Pulido Eitan Isaacson Javier Collado James Tatum Jean-Baptiste Lallement mago-0.3+bzr20/COPYING0000644000000000000000000001673711515544761014252 0ustar rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. mago-0.3+bzr20/README0000644000000000000000000000113111515544761014055 0ustar rootroot00000000000000MAGO ---- This is version 2 of Mago. Mago is a desktop testing initiative, built on top of LDTP (http://ldtp.freedesktop.org/), that aims to have a set of processes and code to make writing automated test scripts easier and more reusable. Although we started this effort as an Ubuntu project it works for vanilla GNOME in most of the cases. This version uses a standard python unittest framework and testtools to extend the framework. The documentation uses Sphinx and is in the 'doc' directory. To build it, cd to doc and run: $ make html The directory 'tests' contains the testsuite for mago. mago-0.3+bzr20/TODO0000644000000000000000000000015711515544761013674 0ustar rootroot00000000000000TODO items are tracked in the bug tracker and mago roadmap. Bug tracker: https://bugs.edge.launchpad.net/mago mago-0.3+bzr20/bin/0000755000000000000000000000000011511546543013745 5ustar rootroot00000000000000mago-0.3+bzr20/bin/mago0000755000000000000000000000261211515250106014606 0ustar rootroot00000000000000#!/usr/bin/env python # Copyright (C) 2009-2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os, sys if sys.version_info < (2, 7): print "python 2.7 or greater is required. Exiting...\n" sys.exit(1) magobindir = os.path.dirname(__file__) # Do we run from a bzr checkout ? if os.path.exists(os.path.join(magobindir, "../.bzr")): sys.path.insert(0, os.path.abspath(os.path.join(magobindir, '..'))) from mago import main from mago.utils import a11y_enabled if not a11y_enabled(): print """You must enable accessibility to use mago To enable accessibility check 'Enable the Assistive Technologies' in the menu (System -> Preferences -> Assistive Technologies) """ sys.exit(1) if __name__ == '__main__': main() mago-0.3+bzr20/bin/magomatic0000755000000000000000000001624611515275242015644 0ustar rootroot00000000000000#!/usr/bin/python # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- # Copyright (C) 2009-2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import gettext import logging import optparse import os import sys, subprocess from re import search, sub from shutil import copy, copytree import gettext from gettext import gettext as _ gettext.textdomain('magomatic') # Add project root directory (enable symlink, and trunk execution). PROJECT_ROOT_DIRECTORY = os.path.abspath( os.path.dirname(os.path.dirname(os.path.realpath(sys.argv[0])))) if (os.path.exists(os.path.join(PROJECT_ROOT_DIRECTORY, 'mago')) and PROJECT_ROOT_DIRECTORY not in sys.path): sys.path.insert(0, PROJECT_ROOT_DIRECTORY) os.putenv('PYTHONPATH', PROJECT_ROOT_DIRECTORY) # for subprocesses from mago import magomaticconfig from mago import magomatic LEVELS = ( logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG, ) def xprop(): (command, appname) = (None, None) (wmname, wmtype) = (None, None) print "\ Please select the window about which you would like information \n\ by clicking the mouse in that window." try: sp = subprocess.Popen(['xprop','_NET_WM_PID', 'WM_NAME', '_NET_WM_WINDOW_TYPE'], stdin=None, stdout=subprocess.PIPE, stderr=None) except OSError, e: return [127, str(e)] out = sp.communicate()[0] for line in out.split('\n'): m = search('([^\(]+).* = (.+)', line) if m: wmprop = m.group(1) wmvalue = m.group(2) if wmprop.startswith('_NET_WM_PID'): try: f = open('/proc/%d/comm' % int(wmvalue), 'rb') command = f.read().strip() f.close() except IOError, e: # Parent process may not exists anymore when it forks if e.errno == 2: # File does not exist return (None, None) else: raise IOError,e elif wmprop.startswith('WM_NAME'): # Remove quotes and spaces to match naming conventions of ldtp wmname = wmvalue[1:-1].replace(' ','') elif wmprop.startswith('_NET_WM_WINDOW_TYPE'): if 'NORMAL' in wmvalue: wmtype = 'frm' elif 'DIALOG' in wmvalue: wmtype = 'dlg' if wmname and wmtype: appname = wmtype + wmname return (command, appname) def publish_to_mago(suitename, magodir): """ Copy a testsuite generated by magomatic to a mago tree""" logging.debug("Publishing '%s' to '%s' " % (suitename, magodir)) # Check if the testsuite is there suitedir = magomaticconfig.get_data_file(suitename) appname = sub('\W', '_', suitename) for d in ('application', 'test_suite', appname): dp = os.path.join(suitedir,d) logging.debug("Checking if '%s' exists" % dp) if not os.path.exists(dp): print "E: Path '%s' does not exists. Exiting" % dp sys.exit(1) # Check if the destination directory exits for d in ('', 'mago/application','mago/test_suite'): mp = os.path.join(magodir,d) logging.debug("Checking if '%s' exists" % mp) if not os.path.exists(mp): print "E: Destination directory '%s' does not exists. Exiting" % mp sys.exit(2) # Everything is there, do the copy destdir = os.path.join(magodir, appname) logging.debug("Copying '%s' to '%s'" % (os.path.join(suitedir, appname), destdir)) copytree(os.path.join(suitedir, appname), destdir) destdir = os.path.join(magodir, 'mago/application') logging.debug("Copying '%s' to '%s'" % (os.path.join(suitedir, "application", appname + ".py"), destdir)) copy(os.path.join(suitedir, "application", appname + ".py"), destdir) destdir = os.path.join(magodir, 'mago/test_suite') logging.debug("Copying '%s' to '%s'" % (os.path.join(suitedir, "test_suite", appname + ".py"), destdir)) copy(os.path.join(suitedir, "test_suite", appname + ".py"), destdir) if __name__ == "__main__": version = magomaticconfig.__magomatic_data_directory__ # Support for command line options. usage = _("magomatic [options] app_launcher main_window_title") parser = optparse.OptionParser(version="magomatic %s" % version, usage=usage) parser.add_option('-c', '--child', dest='child_window', action='store_true', default=False, help=_('Child window to navigate')) parser.add_option('-d', '--debug', dest='debug_mode', action='store_true', help=_('Print the maximum debugging info (implies -vv)')) parser.add_option('-o', '--overwrite', dest='overwrite', action='store_true', default=False,help=_('Overwrite existing files')) parser.add_option('-t', '--tree', dest='dumptree', action='store_true', default=False,help=_('Dump component tree')) parser.add_option('-v', '--verbose', dest='logging_level', action='count', help=_('set error_level output to warning, info, and then debug')) #parser.add_option('-p', '--publishto', dest='publish_to', metavar="DEST", # help=_('Publish the application passed in argument to DEST (mago root directory)')) parser.set_defaults(logging_level=0, foo=None) (options, args) = parser.parse_args() # set the verbosity if options.debug_mode: options.logging_level = 3 logging.basicConfig(level=LEVELS[options.logging_level], format='%(asctime)s %(levelname)s %(message)s') child_window = options.child_window overwrite = options.overwrite #if options.publish_to: # if len(args) != 1: # print "E: Name of the testsuite to publish is missing" # sys.exit(0) # # publish_to_mago(args[0], options.publish_to) # sys.exit(0) if len(args) == 0: # Run xprop to guess the window name and binary (app_launcher, main_window) = xprop() if not app_launcher or not main_window: print "E: Unable to find information about that window." sys.exit(1) elif len(args) == 1: app_launcher = args[0] main_window = None else: app_launcher = args[0] main_window = args[1] magomatic = magomatic.Magomatic(app_launcher, main_window, child_window, overwrite) magomatic.create_app_folder() magomatic.discover_application(options.dumptree) logging.debug(_('end of prog')) mago-0.3+bzr20/contrib/0000755000000000000000000000000011511546543014635 5ustar rootroot00000000000000mago-0.3+bzr20/data/0000755000000000000000000000000011515275242014105 5ustar rootroot00000000000000mago-0.3+bzr20/doc/0000755000000000000000000000000011511546543013742 5ustar rootroot00000000000000mago-0.3+bzr20/doc/Makefile0000644000000000000000000001076611511546543015414 0ustar rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/mago-ng.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/mago-ng.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/mago-ng" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/mago-ng" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." mago-0.3+bzr20/doc/build/0000755000000000000000000000000011511546543015041 5ustar rootroot00000000000000mago-0.3+bzr20/doc/source/0000755000000000000000000000000011511546543015242 5ustar rootroot00000000000000mago-0.3+bzr20/doc/source/conf.py0000644000000000000000000001572511515250106016542 0ustar rootroot00000000000000# -*- coding: utf-8 -*- # # mago documentation build configuration file, created by # sphinx-quickstart on Thu Jan 6 15:39:20 2011. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('../..')) sys.path.insert(0, os.path.abspath('../../examples')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage'] # Add any paths that contain templates here, relative to this directory. templates_path = ['templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'mago' copyright = u'2011, Jean-Baptiste Lallement' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '2.0' # The full version, including alpha/beta/rc tags. release = '2.0.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {'index': 'indexcontent.html'} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'mago-doc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'mago.tex', u'mago Documentation', u'Jean-Baptiste Lallement', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'mago', u'mago Documentation', [u'Jean-Baptiste Lallement'], 1) ] mago-0.3+bzr20/doc/source/gettingstarted/0000755000000000000000000000000011511546543020272 5ustar rootroot00000000000000mago-0.3+bzr20/doc/source/gettingstarted/assistive.png0000644000000000000000000011135311512643737023022 0ustar rootroot00000000000000PNG  IHDRL|NsBIT|dtEXtCREATORgnome-panel-screenshot7w IDATxw|^]rIH!^7A;]勊 * FSE bMz !ҮwI. }.3B!k6_!`txrP[fF]Z !ӤA=l;;xrP[ȸz'B򖙑n/պ {:tV]V!J$g頵Th'̤%螗qKvyoEP3ar+Bq= 1χDX%Z?9!6_A:&2W Z}uV #9ɨ@-E$6岉Bo~)> Tl"?PkA/h9׍z)~oɍUr@\f[r;OqKzW>] |wZ{Hye򹚮6gYþ-6ʾsflPAPR[1H\:)$npŅKנ*njD&UxODQO`2Y X\N&Xw.Y+v1y ^X9aN[|JUvQRچ.JoGnz B4l@S᷒MQ3Cph%Pr.!|EQ.Ovv&pW<鋚ʫrPQDO~OnD:j4T @QXm]EUZߒeJK!סSVM2y3l'D{*A|=yNJ:M1h0?lG+.ۙ6c`fܟ#+#}к@wKe4Eaߦ_.QCInߤӭsO9Ϸԉ_j-ri<2c7cAu0Gټ@fV&#p_Y@\ʞ-K:b㉎+߭{*no'p;y .|^Qb TUnw`ٹ{Cb.q!9 ٘FtRl+3pSx~2]{Sz "[w!> 'wbNPUWJg۰U mV.%c9;oO:+i~ G۾H4ҏ3)6$iѥ/~ +>jf:m{ͩ$kߙ$N$Z~mZ!2M_EJyEb?XLU3)6n1]U-pC;8l+X/9h}X;ȤYX&k[ >X?ͱ~z` F'ſO652xUػuRnnEgOSyL֔ҥb3t Jz쩨p.fw~#6~:-IѪa$YGz*gRl.EÎ߾!ܷ~Ca/Ц睜}> "|ng4#^[pw}i=.ϯ: '9}h'!r}P*V;$lWw/ ɶ%:lCHR\y_JHm.$`a \݄^ɶT #-:/&Zl[v /?T =_iTPݖb6)մD^˼5?TU^ޮ[Iͭ\t%]i4k戥@/\ǢOC\y8EQpXǠIP<";T3-ɡS;GobX{ *b/i'MaBn Q.{`x~gc1)Q:5En p8AZB*VsuP_٨S<͝&$ D;*vM1h/&V Sp(S1;⾔QY֒TJ\4'pDT)s}:* j -fԫ›uXrZ7v<]v~/8rGy7j[8AE?TUp, L֕l]'odF"ښΧ9hؾ7A!:༏!tvBhqӳ\.8}p'69{^U0g:T5Grapzߤ&i>4܇ԄXHIC ~uv MAаU'FN?vDۊmɯV| @DZ?5mpf/oTa߆Ut;bt}ZN o֩eۚrIv'sb<8:z67w=^3(,k}ofݲ[غT^.ӵ5QpNּ͝eSGq}Ñb=[6&3(!>D*l_C_ F=3qg;8M_n2s06ѹJ&N;[ =BQ@H8_Ot h4@ U# *z2~zFt ͗JLjNAl6-BB!r0)D T~OW2[ 2ucąld _T!9Q ,хGm|^B!;£Z:{*&/BjbB!\9… !'$B!OHP!BB!>!AB!|B !BB! *BT!'$B!OHP!BB!>!AB!|B !B5TDoLT|+ Y/B8|%2eCyؗٗduءVvQFB䳠BUU>_%Z%BQ_8.j7v&Bq 7q)z-nSlܴ9O۶s=Ӹyk5kŐ#Y*/.}tszFZQQ3ר"5"tهMZ|8!oցwШiK:v/}S ooG͹mlٺvptޓ妛`|GvK>k4h҂[?(r_m<'B!K>!v_ps3Yv==;FϽ^_qs ԱC8$w>t~v4 ,X1gN۶7w6.ޘ>^\ϙd*W~gO9rhoܷ8~/L|Di-Xsؿ{9s`Qf%-թ3hҸ17WK5>i'B! ǟѰA:oGiР>2220QrePڷk yt M~})S&HňBCyeʤy=3v ;gKf9|(GG sjYf/` ś~B{> *~<7䑇|ŗyǍEawӴ ~=lظ4}a6h@8r(b=zΝ:ҠA}.\GDoL68[\|\իU+6JzB/&>y',, p.\/LoqmKUl3x9]"##uf^Sn7bi3IHL$5"g^sA,x1}[u 815"))L޴MI!WF)lZwY`ٽwɆXRv^sٍ(к5^|Ν<h}n7P<ČYoc#h.[Æ `0_ЮS 5# +AK]M~CyȧK e'KU^qƎyUu,x1*U䙱c㏖iGfBqml:q-`V2YngÝa{^b۩IM+=G/?Pkז~EѠ(hZE)u~uꕩ^B!բװ1w0~{xT<}~O;g'LfWy𡇘5k:?fO假evRS/b6'^}:}#gq<'ϝTN?NŞS>8tOdϱ}<ߞK>Lff&V Qm;C@UAUydOOkUFZĝ!==!o_}m=;:p]wQR%z=p8ZdggҥKٺu+4o"0ЄhDs)!RU?NEѢhhh44EQPPUppر;vlv;v ݎncvܶАPL&zT=^~io !CY2Bq%>M~)=Rz.:}'~Aq=h$00,8 eر,Y^y9o̢e9'4gVAѠhju EAQ4(+rP58;vElhUUՠQU43 sbJLUXw!ZQ/f̢}w}L& qT@a2P#Gܹs<2<Q4hg ,E<g頪Zg@δL Fc1B!5<_> *6m]` !,,y"䯪Rnd2QNFň#szz``@Qy8˓Fq_p(r@pEqCIff&f U{*>Xz*G֬KcE}l6*^hxXWB8FWRBQ(&VZjE~ظq3 sC۠8{.4ZZ-:NNۃp8Tv;7˜=nu4nm{4g6鶜sT B@y|Sm&~~~/wgoNj)B^K]DZZAAAe9˕{(\ PUs߄Wu# }H9@>]Z67|A P*jf21X21\955`y$N^n޲1O%67Q`r-?)YfTy[&J:>Oʑ:u=j%==,f3fl233IKK#%%łjbppj`"'hpCpCaa۰m:9hJΠ!CpI&t.DX&7O-7V&w=O_b׎~_l8oL%EDUr3'9s?^Tz:Uo?agKyed> v-_L2rs7Њ_l, f\󲳳k֬V侾 :TWv'fcrcw󤻼+(]E咯ڇ!0c3X^ 4/ǯX$r-n+Qy֭[WV.v:Sv]C8s6fcpw}2JZ.lg~&n۞- *0lBCC+׶iզ=6as0^/ϟjթhѺ-Mb˿gΞe؈Giиu4CILL,}m6[xiԴ` 1-y~ :vFTw&7҇z ع_|c;8$xۭ|7;v,2333f233ݓl&++Cj*Zl/דG29#e:{)96ͽZGE{K@e𑨹dRUX4~AE!F+{z"&S 'v{,#q;<vf?rqTU>`Gv܎``ڌYJD>AUFIUU7MbR6gͪٸiS?}3yUU,tIزmkYŦ IHH`[sKsޞѣeOlްϻ >Çc+uթӋlyl._9˛Iy~}z3ᅉOqc9~ ӿw}6Ef̜9te 222HOO'== wPNZZs!vm5i|CkP+Ձ]5njc8(@K}aG }~iK.wVv6 鞶QL ՚ǥy~7&y򒒒xit%)/M"<n8g>s+S^b%Z^-Oy|Gygx!L>qơtKݎb!339s~ FEh4ỏ# ^UcZJc\Ywp8}wޞ~Kk 2g9nߓ,7m1_ÐMN=rhA,h3Ĺnc6Uv+?}y!0DΝymʤY)IIIkظ ώs;J$$&¾'$Y1кgo~U`;&׼Ĥo=@^zq76<_>;RE /Nӧ5juAZX,=z r!z=/A1 :Yd1>0NΑq}1t:F1hQ#FG18&Е+pd&Jrv ]0|FW #"vDVT.KODx811VĜ+2/~z1뾇7 ?xǼ-tBv:(z;GBCC mY EE=.L&DhqN[ކb;x.3}֛efшh \,_~5ϺA<}?|dg;x󺽟6n̂INI 4$ڵk1|M&y;Ϝ=ô S V ` ++=Fq7<="" K`!|NT:nf8˅>xu2Kddds 5f@@ZHŴdeec;5g VC5h (ƍCӱc OfM1-PTYwޞ}Ƿ˾ŋz|PS12#oJRs`rJ@8͟XĞwҲek;(r*GK`! D۝9rk`w)Ol<ªcܗTp?MpbJnzyH˧AMN?@~FCXX(Oob^dc&3#ry]® tZLP m@(Ae3Cup9c(5 }9g_v=xy|J.xS%Tjo+_>GeG ILJO|$̡wz^ѧHIIEHpp0!LtZ ⣅|)Z(Qc5v4Z zU6hGjhZZeV.KBQVq`o]6Zs*VCH 99Xm6Ll`8_n4Ga0|BYƸ#(MZVnǮѢ9кPݟ.J@{P6Mκڜ?_ !Dy|T8L>}7e 2kTL i6Ta9XɃ11L0^z)v:䇍xOdnQEF^O@u꾬( $<_W?n ,G||<+VD/1EQ8t06nbйSG6m*Qu;o>]+rO-kcKy3FWBrTr_e*5r3 TZԋdgg繑sM \Ūǜlz']`h!mvMXyS#Ԁ?nφnu-]]kkMtU\NLk $&&v) բhuZl9co |ʧ|ʧ|5iZJ?dn>(bXX'f61biѼ9n@F U&*a4h4Vªcٜ>Sgx=ǁșWs%` B"*F~L$>Y4^RVrh1!9{$Ỳ;%" ~S7իK||s?.09Of7lsόbŊlڲ7fř3gi׶ {ի+XPu L/w(YWgggcOIժE~|Vp`/!LY.7J9O1 }c̞3#G}NlrGXP\*J[8(w/Ji4hԄj5j^<BIo4b*e}~> * B!ĵΧA) fMs[@*Ṳn(N<_jRRRLFJ.YV~}Ф퍼c=YSzۇu;_/ !ӠzjLxY͜ř3gi٢9d{ep.6=?lb`nظ9zN{SsyISļ7^xu!BO =nyDGǐjhSԭ+]fh`0io 1 4El/kyB[>yL9|mG5c@VJ ~  TUh4?\O8˗)EACytBҹ 1ÁV(Bσ7zUאItt )'h$8( F< g{-\\.B!_W233S6o%++MM;7z'AA M=B@2U (B?TUNT<"+U"%%4,3Z??? ~z=:.I ~ #B!=/<,Sg#ԬQ'++lV{ڥ3 iKzuh\.xYD!esN1s:N&++ tE0;'.4IĜ;G||M9o-e EqF'ZU * !A? '44ԋXVz=Aho$4$ OPQ"8(}oǕѠ^TDo̩cJ\nwٯB+Oh?hZF#&Z V|[Zs(/*KO(: Ft0mb ԭSi3fYy }B`8߳sF 3ߘ]d<̳S۽ݻz,ҹzwN;T'$}拯ղ8V*T.ѶU<;~<_=-\.\~Ᏽ=Ϝ)y.]JgúY vUh>lUq,Y٘еf8"7׿sO"#+c#s+ܩ# v6lʳ/NDx8S&*˾_DʑL&~"l@B|))TZY3z,7o7b>Kl66_.cİxyTIpp/Mz1WOW{V`KXB)+f Jͥ_BkOfʊ}K>t~ m^ n4'J]gs!Cר^=ļG\.\Wyw S}=2EzܼM_:QԯWk~eeͯpCkVRm-<Yz܊ۯ'%%QF 5kT'))r)e,n<$oܼMWC0pk>Zi\m-<*VltLa}!<<<~=CXXSpƺs,6e !MrFvQʃIϢs ݊갡`.Of3F?&N~@i3^')9dNŠ I/qYl6GeآTScs P-nyq"wc.䳥L4mrRIc:fι'&2O?ʓm ڿ/όSh^{E<4x DEѣJ]v[z2ꉧ8s6ڼ5 V\F`wYd{ :I/'i[ +SO?3_M*O=1KTt4~}yJ;~Ӽ8y (0aCa 6{_e?!51sjQ!y'[jB0<,/t TtoO3hղծ^9yCGaMEW3XΘE[z^* !T >{?|gZ-?PS4իq-}6"/ !D~TQFQ]8(T.B\ Æ fؐWBk>Y<ByT!>!AB!|B !BB! *BT!'$B!OHP!BB!>!ABr IDAT!|B !BB! *Uq/zʻj/F qMQ9.wWo㏿aۋMqS7zܽ4 k^}%|TkשcvĿBHPQF[ٳ1ꞯ*p8PUL&OL󦍉,2?׏dbRgΤ^fv!e%?fa486 Պbb`6i.{oDx8/O7p6:i64jڒ!%1)ɝ~ k|7uهcǎ}rcǎӽg, /NBh޺'ObFoG|JnݩӠ f&Lqִԍ ?*v{=݋-rTw_p;oz$Ap'Wi=Q}ccڶ[6PN͘^̳S۽ݻz\֭[m@\^~muvn+ߚK܅ /v5;yg^VG#)9M%I-rT9oåKlX;^g~[Y{vn݈``ˋ/%ݮ}ݲ/ٳs+}zSlwvykY?>ذi˾=;1hm K>amڿ//L\NIUn%fOXqmm}JHPCE$:c&]t`t@PP?; 6HINj*̚1㲛ueG? pPCٻ&K&tB[JC@6lDV\,.|eL'?U*(BIH i ~q&F.|>N~`BCB:e+ޥ'Npbw.L2-mJ+p=8('X }L20|||xg駟%WyxiTjcd*Ofuc29|j#AvtGPqN9y{3cFϞ]lӺ,~Όi]/M(_#^^&z쁪Y/D׫;󋍋'+RBB\)ӗ-*$$&:'$o00g\CCCcF~;qKsAIUJS}ZWE,ҎIY}$ĕH 7pgPq)шH\|<'OsIfx=js%%uv3g[pL2݋T/ПfBZz:ixyRbyo4璞AZz:/|mӗ-*¬W撑IFf&3guyfSJ$AP#;{3gϥev0ڷo~Ӎ}3lӎW-Յʔ֣{738q8Q#sB>7ѳMgǖX{tmӗ-*Ǎۛh׶ WfO~Uێy}ŪG=(:灡#hѺoL/iۗwʓWi*O+/ϞC"5 B!NJգ'O.6z^={( jNddoB>yv.B\${ҪesSJ7( a/5kİ6!W< * ,,y!rB!B !BB!p *BT!-$B![HP!BB!n!AB!B !BB!p *BT!-$B![HP!BB!n!AB!B !BB!p *BT!-$B![HP!B~\u{ѠI b7!;2 `0P'd+sС{y ^?rsׅ2oe[h|zU= 8Ӗ} /N&<<aw+8t3,=?ڵ7_[Xl^!FTIPys0h@bώO?'Ga29|,eg,ٱO9Ӗ| _$4$@OTb$<<N;B!-5 6IzꄇĨSŦ ty @7OHL,u噷2 K$"#"*\F3w .z=-[4.BqqkPQ<ꄇ϶ "X> D׫W6ˁǟ[*??_B+eq`deeM6vޢhxi+qYf2\38x͛ӵKg<W!nÆb4dgtz=Fڷk#F\51L,Snћ@Ǝ~\r̝wBQڵmˤ+W9Brr&-"B+PrI!B+B!p *BT!-$B![HP!BB!n!AB!B !BB!p *B.iZSK"B,D6lqaIƍi׮-ݻ]Odd$zN(`!5F?> ~udW<|7d&;LlV}<(&/^sbGc6ɷZlZ#BHMeƛgذaL{D4T Mqk?;`L8ZģdЇ0 z\!լZ1q4~}+>(NAKq>(2HѲm'f]ۉI|j^|yڷm l g$$a٫dB!DUhҬ[򬶠Ͽ`jՊuѳW/K/{g{g E; >7H 77|UU|EIYy-w yFMK@!⊤7hԴ9w y?%77yV7b`hb.]ҥKjN,YK/'1-M"I㉊7*B!DM&)1|||*WT0l0TUfcٱXmY';BV39fxb,x}ħeũ䳜L:g8ɑ gp0./WoOٳgX,nBn3@dAAg0`o`T65ҽ{w-[ƲetбNo/zX~^Đ^pe{`}:w}0ktZ !EvhժW?~u`hߡECთ Dv Ͼ]K(nt;GeݤGsϽ,$B!\UIPXd !!47\Onʹkѥe8|A`ѸIbW/tsWE4Ziw?{׎z6v4M Q9Ӈ@=l6 Ig:/ߚ.BTJxEQM+e|ꜮOnk'.Ï?ZpοUs (,zq6ө*xEu[w̷ʝ7E:qLG|MH#Ghՠ18~9&ǦO?x% w **y ^< 1;iޢ%de?&ͯA4_?<&N'0(KNH`/; ˄!I(+^٥)xB~po=~Fqq¤C"nN1͢kx:)EDT-ZG݂%(ӱQiחm[}5l/r)Dԋ!!%ۥ-6^ˌ[?mL4 Q~~΀`轷_đwZw_=K^FRˈCЉw{Re2~e-.^L#~wq!>DRA ֚ 6ә5k? 4SNBph(z<˹ȸBsXLFZB/biS?ˋHv111[m6*%}d%Qi{KF6nu_yʽyo'_}?歮yk\G94˱'0͜;w%_:l*ybF_:P6t>!%ƳOPx4yY6o_sn9hӮ#6ɧG;o{rw.y$$&Үcgx\۾`sX,if Ͽ"ZYLxa"fSxQ4Mᤥ9#ұuDob9;b_ҰAf<˥;wV{#υ[6v~Ζ} Ç=i }A>ZK^#Y[leJ+iiƘq?n,믾;˔Vt}JN{븓;yJݯ5yŭAE\|ڵs2/`~y9˿]EVZV4b:#=#|K>yyM BTZ :P57㛡ßi)Q|ՌIvj˴ 7+iShuMK_|_^>:Yv-={tLJU}'ٸq#F w?cBB f)Xҙb*0cTV\L_n-_ш&<Ǧ[\7u$bsy$66aA 8!..97|L:Li%m;HJJ*Dԭ)B%m(~OdddҴE"_/cE0=*.T/3?.R.X;nsiZUin߰=ɵ#b91+kBg,xp͎fGa)4'1ӧcIs˴8[:dނ%m -k(} QVSaWUV&V6Q(:ZN}5LoVpՅaٰl&T:'F/!᝿#{h8m}m&OK!f~f.4232xy}ZڴnEddHZlkւpyiRRa֜iKJ+mۍdkoz:uhCUێ<72A~hbvhߖ{UqvgBCBo vǎqϙ̣UN<0t$۵s)>?ώ~-K玗-szྋ=p z 0p{3uqNWRZi>y鱴nۉ_e9eJp/~tns*~?+]ORΤ%U*#-ncOrKBZvj~ah0e7WtnȪGH+gb&,6GS/*:sڋL6JK9قc\ZKfM &wj|ZBjA IDATj:o ǞxA3h-U_EE̞1GKXXXO?/v_GMEqF ~|Gi5~/D)50r)< LF< __7FvivqWUnow0o Mw~8Oq_Ն^C׻ 2WbTU_éS _嫄Wq9p[PЮYKeCs6lݲelmtx-EW?u];c02d2U|ףzE^0U;jxx]KQ=53(͆^5+\F[[/DW~:={0ad ėZ||ZZ*׭)u֯%qs.D\8 Ʉ7FcB<. hZ\6zԿo6G>H o]( 9jV& /ٯrE^(:v.D\~-|ɇއOb״D~ gQT^:F ^&􆊯QCA``Gtuxh6HUx|zzGNǠc*A^;ncD៝;xa|_ӆSǏb6#A#Bjvx]M*E\| bMJe"::ݎ]GgP;Thoot:+Wa0$B\GCxE$&v^YGC=[bKc2ڣ/[7 x޾DF7(&@PP ;u*QI^NQw%(쬩95t:|P! ֠BQ></"=$a.Y61IEp.i6GDѲM{=HPHmfaQ7*[ugݫzOKGڧ,8_;Vtr !0*t:}/bԣ#l釕>cn呓E^^.AFp07Yҝo,e`~AK^1y(+| }A5sE zlVkd!{+*ߊ:?Â3v\?~۴:Qާt9>34.x0Yp<_mxC)cMu\vUP&D???L&cDz *B:n\%AEa/%K#ǠjidggjA@QX(zΞA۩iDo ܍.g&';̌t5{-?t._e2狷w;{+o~t&\!ĕnsq~\SvU%_z `֬YLh5~V|o |=֥ͯN#)1/o_CjiC!th3pS7,G[/ =3{lf͚!<FS;hD׏_lZ&%bKI!zp}^ԩWN7=I&+k*zIhNYB뇪@ ɉEw! bֻ_2iԽ|k9?Yfq0`/y^M "*'BT7}[-C $ᄇӺuk }%lV|C]<JbI6Nr i~L~vCRGܿ>>>nB!ĕJ/?8rf]nb8}Cg>]4M~&3JD.0UFNb> ݅Zjl^tR\=!BQAŅ7Ǽ;On[oNGMF4ڏ՚Odojԍf'=-Mo,?}gO#+9Ms_4aŝW ~6nƶk-#s:QuIܱ}UUO>u2,Y>▻VϺev5<?G (z:ҒOYO'(<ʴ_7l$ ÇX 7[VfB4> -%}ks֬[6r2mˏ?b׎FfΞL3n<Ǎ|sgҊ~ضukVM/:mip(>Bټa=~D,|%=++mbݚlWrb?;~Lxab2{wBXw]jgz{(> jh$;5eoc,#66aA 8!..97|KӧQ'<M\/3LJ'<Ϛk&T223[s_)SڅfLBHH0!!L:+V^tS+VbzrCCC1m*+Vr\ӦL"88`MTb~^AxX^^^<'5#}**rbUBho׎lƬ8 @4;-v6 fp9%-#==Z]4K?ZƄ %5Р%%%'ӳύ.EqN荅,zg1:~Lyq{(5 I@!.<st "-=>5-ZW^l69ψ+B\atO:^qx4mw9VeJ솷y{^b"#:'p0'1OLSZ_.'v틮KVoi6oa¤R.@tt=  t<\OPPKzbi"j'(2PcCI8om]oϭ}m3vf㗣7kiӺ.㣢"iղ?Y YsHJI!+;Ys;-)ac9t(c?L3y?nGTZ4 0k223d 4ӖVbC W摞AzF/Ϟˠgd9Cƙ3̚XK\gdMܷO{s̺h3EQ &| "AӲaҷxzc3n3=~;oO=Ŝ 8N4M'G9))mԣ! b'wا7O>=ظ8bGpޜ2gCtrME-<ӨYbƍaKo|ǎqL:n=oחCd-\A3Jrr&-rŘ9E&NYR:^6^7kBhh0{VRS9x0]'~Oh$;v8?$~YSE3&c 'yRSQQ BT'MӰUMUL>`[iӦ- =1}~rѣǹfԻxEavAjAnlзO/;Z&A9i4{v;6 %͑'d|aW(uh&AE51!F {!D"b( (vEgG4 & /z^^hz W~j*K.HP!^Cף۱ *zg NCQtu: 5]!j(rrGQ@K QYSCs6k((tB !D5!CQ{@Aɱ*&TTޠfi!W8{+*K+ N$ݠ"BTJ|)D凲лM+  !nsq~\]<%1?MߤD6{MI!(^OXxދ:u#tTTPf-&''"BT`d-IPQ >>>nB!ĕN.`B![HP!BB!n!AB!B !BB!p *BT!-$B![HP!BB!n!AB!m;|p?[6'9%I.ޠ',7tEf-4Ozib&7,Uq ſN@&׮Sy$v9UGK㖠[#y/1 7OEղl8v|Et?α{iҢ-AtJ5T[ٌT߉Ón=[? xS+6RSQvl223Hl1`2 "(0???\n*x4 JHhmEAӡPEQ4 MPUUUYgϠ*"DEilƲr{FxA zE(V yh\s6%cV6+AxR/:> %4 =HVrr K#:HA4iCPP|\4MfcZ=(lv4M@*97jv0xt:@4GPV4{Aa{>ZZN|%ܹj4\n'.>_8;g&ԫӀAv9l<)9N.MZ@EP P5 %b`ɓ.t jXZΣf=h *K62X4;y^-j&5eiNÖC&7M"04&_oR2|BnP_FԫOB*]Xh4{>8twk\MR󨪪/lh=A}2ڙ ? 厹t:OT<+}XOE)4M#55u[#NiN/uC|ih "ԏH;o9gg$5ζV<Ǜj:[T9:0B;8ɄAwwNf銕2s5KչZ>a JݖXHPaÑ~&׷Χ9L}rG)VaW ECpV;7uiHz{7rա>n!)-_/O2r4v%GeDFE_R\rRYh^Gc05W9ɣ8n7 [ſl^n7dq~2WӸ>eΣ||~aT;P=&66Y5(9EIb[AťG1wyyy4o֌'xR{LPh#EqOq[Uukee_SQsZw7Yg28ou5 ʔrtu CF5brgV7iNb$Qm:wh*s^USeo;ChzPhq;/Q@ s=S]5 mK}N8C1̛3 ooo?c-GT=7vԼ$Neh osMpN#4DPBՂ^*zET#`t *Rv_ȗx#r[i0 rsr4xghRUj\N:E!=9輜(GaPrwӄ;p.7t4MYx7s);ǗXhX]6%3-Gc>M[`vcIJnFm.| \NǙt4U% (&-ql;6kM#XxѨE[|UUHKND7ݰl"i9zRN;U'.c߈t\n69g3U+MI8uFZaw(XbK."-MwtE]]P=? ) m7xQ<qm^w.NwA1}&uFfΚ͉' ]<} +@1*TdPȷɷ9<ҳm'u(X*٤=HNJF-lkR(hݻXŮ1̚=lƺ5}&RSY5MdbVl򲳹y#55UUxxxzOfFQ br.MUAӰY9[F[' ?B~gTU%!39o' ;۱şu v{9x RP7!efݰ9vMUAIMJ9]D q%U!5YrҞvz??HIDATW9 G0ʸm~wXz9 ^/Xd6oXϦ_!11 _u7r`n ޹+}pW!UU"恦Xm*6;fǦp2M>-$.9?ͮ(n'AVV^CQ_|_^>:Yv%?cBB f)X}_DU5\n.!!(Ji//7 7܀^/SPaZ'l.qBI3&oo̹Ykؔ'__g38CL $%Ңmg|>CDT}bDv]{ kܳԉ&5)o4:vߑ_Hh8Y %)QV/GY5+:^|w..F/rՠq٬xFO HI$#%|+/D=2bZc<23XW\bhh3MeM-&T223[s_qo˹?2r\ffWʵp6BV9ccHͱ0zX\u\E"h5oܶIsK(.۾!CIMK*SY٭%ݹ X([fbX'#- EU jg˦ML&􊂢i6[rحhE~< X-X-f(nǚo! (mV :f3F/3hZRNshtz=6#(8|XFbϞad;j ܆FN:jXMS1x.Y֢Rz^Ț_|-ۚo?0Im6 :}<8ٚDw}_s4ң}˴M٠1^~mVVQRVMhY- EùXy ҖP+ uiɧjw( mZlvPrC^Ny99dg;Q0fgHFJ IIzF#& OOR?"7]&cY4ڷӇg_*|N9@hx]NfZ2Y) ZՍbןH8q:^Ijɋ.KUwضrmpUe=z\wwsCjaώoc:]o/^KHH#Ņ  A#Wn(F @n.9P. $A1jV$ˇ(%Q"%]).$:}$=oggpyΝ^X-Πca\u/ z+`@4`w=ٙiO\0Lu-̗jh{0G_?k:r"m94??*c;~>W4.>o/K^k|r`{To\a+tj}\. @u|2 Cxn'uDٶ!.?s"[H50YB)Z;:;[ lhUJQl`d3‘=>0_ctP$F} z&,IΞ~} rSX-m]\4 Rڷp)tm\eܛ }f3xF5[>h3t4N@O}z7u͌ RtlفX!T7Wo_ {^zTJ ӆ|0ڗ_PP[%}c??KT>о2 A? r(O{:~Kӹizzh\{z|y{x𳜿pttdMWU5uli4g6!a6`Π榏x"l[hhڒ:ea2MxA:t:#f ežyhh,"i, ~e2ł–MwO?z L>'G; V 5txx\(Txa:y2G*Ŧf]iRl%M]7\tw,<9 4=:{;w!ٜ*F.[u]{,V85\_~aD՘V0.E~v:q( K]Ī0L u;*v`ǪPJ1r2G[Jsv?C Wdoz Hm^9@x&:;;Ყ0.!G^|ǁ']V*T@SHN}tLLtM1=Y?ߧ-l LZ};Eh7Ttlݶs`iJ)xO>Tp s7Wyk+%^]M,u=t4B_V1S`nݑKoԚkK_9-,23]sS&]L+'䲙5sǟ\~|GjR=8.|c75+o/ is댍\^xzAd3d3K8*%bWÂ&.o,|L0 ع)>2TTFfXH)iY)vw={q= FH$6ZavF*´A{ ~xÖnݾ+alj [a8L:4"1338B! Ec:|t/ɦe\:_rouowCK^0*%*J[jWv˒-b4M#Gqs\vdBh1o:ktxw_Q)EcF2YE2Yt\`*;Gf8eD o t VSpXISKM٢GSÑnT߬?Ñn4%|R¾R 2I&x$q&*f&Es,!gmz}}lMMM eVlm0% -i37t\74x4 iLNN2::)0SSYcf6b~ۈ\L(3Zܳ_Zf/0L,N+πXYx!j^b!uCbCPZ|hZN%;cqt56604tT{9v'Ī is@MԐFZ&UWf,3,qT|p’ױ֢_*u$UUʅ8\exdc44l*aQ\$ÓocGc n9>EzgT⨸GW251ѣo"n\ s,-:g܂m+_USG~.9zsݽхX-MSDcUljĎ&J>襋Qqk5Fk Preferences -> Assistive Technologies**. the following dialog will be displayed. .. image:: assistive.png :align: center :alt: SDFSDFSDF Check the box **Enable Assistive Technologies** Alternatively you can enable it from the command line. Open a terminal and run: :: # Enable accessibility for the current user $ gconftool-2 --set --type bool /desktop/gnome/interface/accessibility true You may also need to disable the screensaver to prevent the hang of the tests. Finally restart your GNOME session (log out and log in) Additional Packages ~~~~~~~~~~~~~~~~~~~ In order to get a fully working system you need the following packages: **python >=2.7** To take advantage of new features introduced in unittest **bzr** Easy to use distributed version control system to get mago and push changes if you want to contribute. **ldtp python-ldtp** The glue that uses the "Accessibility" libraries to poke through the application's user interface **python-nose** Test discovery and running for Python's unittest **python-xlib** Interface for Python to the X11 Protocol **python-imaging** Python Imaging Library used for image compairison Getting Mago ------------ The Mago project is hosted in Launchpad at https://launchpad.net/mago The trunk branch is owned by a Launchpad team, mago-contributors, that it is a moderated team. Once you have contributed through merge proposals, you can apply to be part of the team and will be able to push to trunk and review some other members contributions. To get Mago from Launchpad you need to install the tool Bazaar (http://doc.bazaar.canonical.com) Then run the following command to get the latest version from the Bazaar repository: :: $ bzr branch lp:mago This will create a directory ``mago``. Go to this newly created directory and you'll be able to start running your first tests. You can get the help of mago by running the command: :: $ ./bin/mago -h Running the examples -------------------- The directory ``examples/`` contains few pieces of code which exercises different parts of mago. Mago uses Nose (http://somethingaboutorange.com/mrl/projects/nose/) to collect and run tests and follows the same syntax. To run a specific example: :: $ ./bin/mago examples/test_minimal.py Or alternatively :: $ ./bin/mago -w examples test_minimal To run all the tests in a directory enter: :: $ ./bin/mago examples/ .. automodule:: test_minimal :members: mago-0.3+bzr20/doc/source/index.rst0000644000000000000000000000263511515250106017100 0ustar rootroot00000000000000.. mago-ng documentation master file, created by sphinx-quickstart on Thu Jan 6 15:39:20 2011. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Mago's documentation ======================= What Is Mago ? -------------- Mago is a desktop testing initiative, built on top of the LDTP GUI testing framework (http://ldtp.freedesktop.org/), that aims to have a set of processes and code to make writing automated test scripts easier and more reusable. Although we started this effort as an Ubuntu project, the framework and many test cases work for vanilla GNOME The Mago project is hosted in Launchpad at https://launchpad.net/mago The trunk branch is owned by a Launchpad team, mago-contributors, that it is a moderated team. Once you have contributed through merge proposals, you can apply to be part of the team and will be able to push to trunk and review some other members contributions. Documentation ------------- .. toctree:: gettingstarted/index tutorial/index referenceguide/index userguide/index :maxdepth: 0 Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` Contact Us ---------- * Mailing List * `GNOME Desktop Testing Mailing list `_ * IRC * #gnome-testing in irc.gnome.org * #ubuntu-testing in irc.freenode.org mago-0.3+bzr20/doc/source/referenceguide/0000755000000000000000000000000011511546543020216 5ustar rootroot00000000000000mago-0.3+bzr20/doc/source/referenceguide/index.rst0000644000000000000000000000124211511546543022056 0ustar rootroot00000000000000Reference Guide =============== This is the reference The TestCase Class ------------------ .. autoclass:: mago.TestCase :show-inheritance: :members: :undoc-members: The TestApplication Class ------------------------- .. autoclass:: mago.application.TestApplication :show-inheritance: :members: The MagoConfig Class -------------------- .. autoclass:: mago.config.MagoConfig :show-inheritance: :members: :undoc-members: Utilities --------- .. automodule:: mago.utils :members: XLib ---- .. automodule:: mago.xlib :members: Mouse ----- .. automodule:: mago.mouse :members: Unity ----- .. autoclass:: mago.unity.Unity :members: mago-0.3+bzr20/doc/source/static/0000755000000000000000000000000011511546543016531 5ustar rootroot00000000000000mago-0.3+bzr20/doc/source/templates/0000755000000000000000000000000011511546543017240 5ustar rootroot00000000000000mago-0.3+bzr20/doc/source/templates/indexcontent.html0000644000000000000000000000702111512643737022634 0ustar rootroot00000000000000{% extends "defindex.html" %} {% block tables %}

Parts of the documentation:

Indices and tables:

{% endblock %} mago-0.3+bzr20/doc/source/templates/layout.html0000644000000000000000000000066011511546543021445 0ustar rootroot00000000000000{% extends "!layout.html" %} {% block rootrellink %}
  • {{ shorttitle }}{{ reldelim1 }}
  • {% endblock %} {% block extrahead %} {{ super() }} {% endblock %} mago-0.3+bzr20/doc/source/tutorial/0000755000000000000000000000000011515541545017106 5ustar rootroot00000000000000mago-0.3+bzr20/doc/source/tutorial/index.rst0000644000000000000000000001035611515541545020754 0ustar rootroot00000000000000================================ Tutorial: A Step by Step example ================================ The Smallest Test ----------------- Mago uses extends unittest (more exactly testtools) and uses nose (`Nose Documentation `_) to run them. So you write a mago test as you would write any unittest in python. The smallest test that you can write is: :: from mago import TestCase class TestMinimal(TestCase): launcher = 'gcalctool' window_name = 'frmCalculator' def test_minimal(self): """A really simple test This test verifies True is True. If it fails, then reinstall your system. """ self.assertTrue(True) The mandatory elements of the test are: - ``launcher``: This is the name of the binary that you want to test - ``window_name``: This is the name of the main window of the application under test. It follows the LDTP naming conventions. To run this test, open a terminal and enter the following command (mago must be in your PATH or enter the path to the executable): :: $ mago ./test_minimal.py You should see output something like this: :: . ---------------------------------------------------------------------- Ran 1 test in 11.570s OK $ Which indicates that the test has been found and ran successfully. Mago uses nose to collect and run the test. For help enter: :: $ mago -h Or refer to the nose `usage documentation `_ to find information about the differents ways to collect and run your tests. Hello World ----------- This is the traditional "Hello World" example. It shows how to manipulate the application with LDTP. Mago provides 2 ways to interact with your applications: 1. `LDTP `_ 2. XLib .. literalinclude:: ../../../tests/test_helloworld.py :lines: 37- :linenos: This test launches ``gedit``, write some text in the editable area, then closes the application. If mago can not close the application with the ldtp ``closewindow`` method, it will force it by sending a ``SIGTERM`` then a ``SIGKILL`` if it fails. This examples uses ldtp, so we need to import it (line 2) There are 2 new parameters used by mago lines 8 and 10: - ``launcher_args``: This argument is a list of argument to pass to the binary - ``setupOnce``: By default the application is launched and closed for each test. If ``setupOnce`` is set to ``True``, then the application is launched once at the start of the run, all the tests are run, then the application is closes at the end. Line 30-31, we use the ldtp method ``ldtp.settextvalue`` to set the value of the text area, then we wait for 2 seconds to let you see the result. Configuration Files ------------------- mago can use external configuration files to customize mago itself and the tests. The structure is similar to the Microsoft Windows INI files. You can refer to the ConfigParser reference for further details. Below is an example of a configuration file: .. literalinclude:: ../../../tests/test_testconfig.ini Additionally to the standard ConfigParser format, the configuration files support an ``include`` directive which allows to cascade configurations files. The files included are appended to each other. If the same section and same key exist in 2 differents files, the last value included is used. .. literalinclude:: ../../../tests/test_testconfig.py :lines: 34- :linenos: Line 1, we import ``magoConfig``, this is the global configuration for mago. The default configuration file for mago is ``~/.magorc``. There is also a specific configuration file for the test. It's name is the same than the test but with the extension ``.ini``. It must be located in the same directory than the same. For the purpose of the example it is evaluated line 13 and stored in ``localconf``. Line 14-22, we load values from the global configuration file and the test configuration file, then join them together line 24. Line 25, the text area of gedit is updated with the result. We use the ``application.context`` object to access gedit. This is an ooldtp context corresponding to the main window of the application mago-0.3+bzr20/mago/0000755000000000000000000000000011511546543014120 5ustar rootroot00000000000000mago-0.3+bzr20/mago/__init__.py0000644000000000000000000000221511511546543016231 0ustar rootroot00000000000000# Copyright (C) 2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Testing framework extensions for desktop testing""" from mago.core import main, TestResult, TextTestRunner, magoConfig from mago.case import TestCase from mago.config import get_config __author__ = 'Jean-Baptiste Lallement' __copyright__ = '2010 Canonical Ltd' __versioninfo__ = (0, 0, 1) __version__ = '.'.join(map(str, __versioninfo__)) __all__ = [ 'main', 'TestCase', 'TestResult', 'TextTestRunner', 'magoConfig' ] mago-0.3+bzr20/mago/application.py0000644000000000000000000003433111515663552017005 0ustar rootroot00000000000000# Copyright (C) 2005-2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """ Test applcation object It implements the application under test """ from sys import exit try: import ldtp, ooldtp except ImportError: print "ldtp is required. Install the package python-ldtp.\nExiting..." exit(1) import mago.mouse import mago.xlib from os import kill from time import sleep import re class TestApplication(object): """ TestApplication class This class present an absctraction layer to manage the application under test """ appModule = None appClass = None isRunning = False context = None # LDTP Context pid = -1 xid = 0 window = None window_manager = None def __init__(self, launcher = None, launcher_args = [], window_name = None): """ Construct a TestApplication instance :param launcher: Name of the binary to launch the application. If this argument is not specificied, the application is not launched during init and must be launched with the method 'launch'. :param launcher_args: Optional arguments to launch the application :param window_name: Name of the main window of the application. The name respect the LDTP naming convention """ self.launcher = launcher self.launcher_args = launcher_args self.window_name = window_name self.window_manager = mago.xlib.WM self.isRunning = False self.dlgAboutName = None if launcher: self.launch() def launch(self, launcher = None, launcher_args = [], window_name = None): """Launch the application :param launcher: Name of the binary to launch the application. If this argument is not specificied. :param launcher_args: Optional arguments to launch the application :param window_name: Name of the main window of the application. The name respect the LDTP naming convention """ if self.isRunning: return self.pid # Sync args and class properties with a priority for method args if not launcher: launcher = self.launcher if not launcher_args: launcher_args = self.launcher_args if not window_name: window_name = self.window_name self.launcher = launcher self.launcher_args = launcher_args self.window_name = window_name self.pid = ldtp.launchapp(launcher, launcher_args) self.window = mago.xlib.window_from_pid(self.pid, launcher) if not window_name: window_name = self.get_windowname( discover = True ) # Raise LdtpExecutionError if not found self.window_name = window_name ldtp.waittillguiexist(window_name) self.context = ooldtp.context(window_name) # Get XID, WindowManager and Application Window object self.isRunning = True return self.pid def close(self, timeout = 30): """Closes the application # If the pid still exists: # 1. Close the app using ldtp # 2. If the window is not closed close it using SIGTERM # 3. If the window is still not closed close it with SIGKILL :param timout: Kill the application after timeout (in seconds)""" # Force sync to avoid closing the app before its really there # But this may cause problem if another window exists with the # same name # Pb if the window has already been closed # TODO # - Check if window still exists and kill it if it is # - Add a waiter and kill the process after a timeout try: kill(self.pid, 0) #print "closing with ldtp" rc = ldtp.closewindow(self.window_name) if rc == 1: rc = ldtp.waittillguinotexist(self.window_name, guiTimeOut = timeout) if rc == 0: #print "closing with SIGTERM" kill(self.pid, 15) rc = ldtp.waittillguinotexist(self.window_name, guiTimeOut = 5) if rc == 0: #print "closing with SIGKILL" kill(self.pid, 9) rc = ldtp.waittillguinotexist(self.window_name, guiTimeOut = 5) except OSError: # We are here if the process is not there anymore pass self.pid = -1 self.isRunning = False # Lets wait a few seconds to be sure that the WM has time to run all # the pending events ldtp.wait(5) def __del__(self): """Destructor Closes the application """ if self.isRunning: self.close() # def __guess_window_name(self): # """Tries to guess the name of the main window of the application # # It does this by checking the last window opened in the window list and # returns the name of the window following LDTP naming conventions. # # This neeeds to be called immediatly after the ldtp.launchapp() to avoid # catching another window that would be opened during the test # """ # winlist=ldtp.getwindowlist() # timeout=60 # # # Any way to get the window name from the app name ? # # appundertest is not implemented in LDTPv2 # wincount=len(winlist) # wincount_orig = wincount # while wincount == wincount_orig and timeout > 0: # winlist = ldtp.getwindowlist() # wincount = len(winlist) # timeout -= 1 # sleep(1) # # return(winlist[-1]) # # # return False def get_windowname(self, discover = False): """Returns the name of the window for the current running application following the LDTP convention. It gets it from the _WM_ICON_NAME Atom for the XID of the main window :param discover: if True or window_name is not set already, it forces the discovery of the window using X Atoms. Otherwise it returns the window_name """ if not self.window: return False if not discover and self.window_name: return self.window_name title = re.sub('\s', '', self.window.name) wm_type = self.window.type type = "*" if wm_type[0] == self.window.TYPE_NORMAL: type = 'frm' elif wm_type[0] == self.window.TYPE_DIALOG: type = 'dlg' ldtpid= type + title return ldtpid def openDocument(self, path, actionOpen = "mnuOpen*", dlgOpen = "dlgOpenDocument", btnOk = "btnOpen", defaultTimeout = 2, opts = {}): """ Helper method to manage the open dialog. All the names in argument follow the LDTP naming convention :param parentWindow: Name of the main window :param path: Path to the document :param actionOpen: Name of the widget to open the Open dialog :param dlgOpen: Name of the Open dialog :param btnOk: Name of the button to open the document :param defaultTimeout: Timeout between actions :param opts: Additional arguments to provide to the dialog. This is a dict of the form {'componenent_name':'value'} """ txtLocation = 'txtLocation' if not ldtp.guiexist(self.window_name, actionOpen): return False ldtp.click(self.window_name, actionOpen) ldtp.wait(defaultTimeout) if not ldtp.guiexist(dlgOpen): return False if not ldtp.guiexist(dlgOpen, txtLocation): ldtp.generatekeyevent('l') ldtp.settextvalue(dlgOpen, txtLocation, path) ldtp.wait(defaultTimeout) ldtp.click(dlgOpen,btnOk) ldtp.wait(defaultTimeout) return True def saveDocument(self, path, actionSave = "mnuSaveAs*", dlgSave = "dlgSave*", btnOk = "btnSave", defaultTimeout = 2, opts = {}, replace = True): """ Helper method to manage the save dialog. All the names in argument follow the LDTP naming convention :param parentWindow: Name of the main window :param path: Path to the document :param actionOpen: Name of the widget to open the Save dialog :param dlgSave: Name of the Save dialog :param btnOk: Name of the button to validate the action :param defaultTimeout: Timeout between actions :param opts: Additional arguments to provide to the dialog. This is a dict of the form {'componenent_name':'value'} :param replace: Set to true (default) to overwrite an existing file """ # TODO: Put all of this in a resource file txtLocation = 'txtName' # Confirmation dialog dlgQuestion = 'dlgQuestion' btnCancel = 'btnCancel' btnReplace = 'btnReplace' if not ldtp.guiexist(self.window_name, actionSave): return False ldtp.click(self.window_name, actionSave) ldtp.wait(defaultTimeout) if not ldtp.guiexist(dlgSave): return False if not ldtp.guiexist(dlgSave, txtLocation): ldtp.generatekeyevent('l') ldtp.settextvalue(dlgSave, txtLocation, path) ldtp.wait(defaultTimeout) ldtp.click(dlgSave, btnOk) ldtp.wait(defaultTimeout) if ldtp.guiexist(dlgQuestion): ldtp.click(dlgQuestion, btnReplace if replace else btnCancel) ldtp.wait(defaultTimeout) return True def authenticate(self, password = "", cancel = False): """Manages the authentication dialog :param password: User password. Defaults to an empty string :param cancel: If set to True, it cancels the dialog TODO: - Manage it automatically with an onwindowcreate event """ dlgName = "dlgAuthenticate" btnCancel = "btnCancel" btnOk = "btnAuthenticate" txtPassword = 'txtPassword' lblFailed = 'lbl*unsuccessful*' # Wait for the dialog to appear for i in range(0, 2): if not ldtp.guiexist(dlgName): if i == 1: return False ldtp.waittillguiexist(dlgName) ldtp.wait(1) ldtp.settextvalue(dlgName, txtPassword, password) ldtp.click(dlgName, btnCancel if cancel else btnOk) # The dialog takes some time to respond when you enter a wrong password ldtp.wait(5) # Wrong password ? if ldtp.guiexist(dlgName, lblFailed): return False return True def about_open(self, cmdOpen = None, dlgAboutName = None): """Opens the about dialog :param cmdOpen: Name of the component to open the about dialog. If None it tries to guess it and returns false if it can't :param dlgAboutName: Name of the about dialog. Try to guess it if None """ if not cmdOpen or not self.context.guiexist(cmdOpen): cmds = filter(lambda x: "about" in x.lower(), self.context.getobjectlist()) if len(cmds) == 0: return False elif len(cmds) == 1: cmdOpen = cmds[0] else: # Check the properties and select the first menu which matches for c in cmds: component_class = self.context.getobjectproperty(c, 'class') if component_class == 'menu_item': cmdOpen = c break self.context.click(cmdOpen) self.context.waittillguiexist() ldtp.wait(1) # Find the name of the dialog if not dlgAboutName: try: dlgAboutName = filter(lambda x: "dlgabout" in x.lower(), ldtp.getwindowlist())[-1] except IndexError: # Cannot find the name return False self.dlgAboutName = dlgAboutName return ldtp.guiexist(self.dlgAboutName) def about_close(self, cmdClose = "btnClose", dlgAboutName = None): """Opens the about dialog :param cmdClose: Name of the component to close the about dialog. If None it tries to guess it and returns false if it can't :param dlgAboutName: Name of the about dialog. If None it uses the name found in about_open """ if not (dlgAboutName or self.dlgAboutName): return False if not dlgAboutName: dlgAboutName = self.dlgAboutName # About not found or already closed ? # State is undefined return False by default if not ldtp.guiexist(dlgAboutName): return False # Try to find the close button name if not cmdClose: cmds = filter(lambda x: "close" in x.lower(), ldtp.getobjectlist(dlgAboutName)) if len(cmds) == 0: return False elif len(cmds) == 1: cmdClose = cmds[0] else: # Check the properties and select the first button which matches for c in cmds: component_class = ldtp.getobjectproperty(dlgAboutName, c, 'class') if component_class == 'push_button': cmdClose = c break ldtp.click(dlgAboutName, cmdClose) ldtp.waittillguinotexist(dlgAboutName) ldtp.wait(1) self.dlgAboutName = None return not ldtp.guiexist(dlgAboutName) mago-0.3+bzr20/mago/case.py0000644000000000000000000000712311513404246015403 0ustar rootroot00000000000000# Copyright (C) 2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Main TestCase class""" import unittest import testtools from mago.application import TestApplication from mago.config import get_config from inspect import getfile, getmodule class TestCase(testtools.TestCase): """Base class for desktop testing This class setup the test and start/stop the application under test""" setupOnce = False window_name = None # Set it static because LDTP can run only one app at once. application = None # Class and Test Configuration # This configuration is specific to the run and different from the # global configuration. # By default the name $(basename MODULEFILEPATH).ini testConfig = None def __init__(self, methodName = 'testMethod'): """Construct a TestCase instance Loads the configuration for the application and the test """ super(TestCase, self).__init__(methodName) #self.magoConfig = get_config() moduleFile = getfile(getmodule(self)) classConfigFile = '.'.join(moduleFile.split('.')[:-1]) + ".ini" self.testConfig = get_config(classConfigFile) @classmethod def setUpClass(self): """setUpClass Called once for all the tests in a TestCase. set setupOnce to True to activate it. This is used if you want to launch the application to test only once at the beginning of the test session or want to do some extensive setup """ super(TestCase, self).setUpClass() def setUp(self): """setUp Launch the application when setupOnce is set to False """ super(TestCase, self).setUp() if not hasattr(TestCase, 'application'): TestCase.application = None application = TestCase.application # Check mandatory propertys, launcher, launcher_args and window_name if not application: TestCase.application =\ TestApplication(self.launcher, window_name = self.window_name) #TestCase.application.launch() else: if not application.isRunning: TestCase.application.launch() @classmethod def tearDownClass(self): """tearDownClass Called once at the end of the class to close the application and cleanup the environment and destroy the application. Only called if setupOnce is set to True. """ super(TestCase, self).tearDownClass() if self.setupOnce and TestCase.application: del TestCase.application def tearDown(self): """tearDown Called once at the end of the test to close the application and cleanup the environment and destroy the application. Only called if setupOnce is set to False. """ super(TestCase, self).tearDown() if not self.setupOnce and TestCase.application: del TestCase.application mago-0.3+bzr20/mago/config.py0000644000000000000000000000622511511574634015746 0ustar rootroot00000000000000# Copyright (C) 2010 Canonical # # Authors: # Jean-Baptiste Lallement # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; version 3. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Config file management This is an extend for SafeConfigParser. The configuration file has a structure similar to what you would find on Microsoft Windows INI files. [section] key = value Additional configuration files can be included with the special 'include' key example [section] key1 = value1 include = ~/config01 Only one include and one configuration file can be specified by include directive """ import ConfigParser import os MAGO_CONFIG_FILE = os.path.join(os.path.expanduser('~'), '.magorc') class MagoConfig(ConfigParser.SafeConfigParser): """This class loads one or many configuration files""" # List of configuration files loaded config_files = [] def __init__(self, file): """Constructor :param config: Configuration file name """ ConfigParser.SafeConfigParser.__init__(self) if not os.path.exists(os.path.dirname(file)): os.makedirs(os.path.dirname(file)) self.config_files = [] self.load_config(file) def load_config(self, file): """Loads a configuration file This method loads a configuration file using the ConfigParser.read() method. Addional configuration files can be added with the 'include' directive. [section] key1 = value1 include = path_to_file Only one include directive is allowed, the last one will be used and only one include file can be specified. Relative path in the include directive are relative to the current directory not the directory of the parent configuration file. """ files = [] try: files = self.read(file) except: # don't crash on a corrupted config file pass if not files: return self.config_files.extend(files) for section in self.sections(): if self.has_option(section, 'include'): inc = os.path.abspath(os.path.expanduser(self.get(section, 'include'))) if not inc in self.config_files: self.load_config(inc) def get_config(configfile = None): """ get the global config class :param configFile: Path to the configuration file. If no configuration file is specificied then the value MAGO_CONFIG_FILE will be used (default to ~/.magorc)""" if not configfile: configfile = MAGO_CONFIG_FILE return MagoConfig(configfile) mago-0.3+bzr20/mago/core.py0000644000000000000000000001255311511546543015430 0ustar rootroot00000000000000# Copyright (C) 2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import unittest import sys import testtools try: import nose except ImportError: print """nose is required. Install the package python-nose. Exiting...""" sys.exit(1) from mago.application import TestApplication from mago.config import get_config # Available Nose plugins from mago.noseplugins.maybe import Maybe # Just a test plugin from mago.noseplugins.magoxml import MagoXML PLUGINS = [ Maybe(), MagoXML() ] # Global configuration # defaults to ~/.magorc (defined in config.py) CONFIGFILE = None # Global Configuration magoConfig = get_config() from inspect import getfile, getmodule class TestCase(testtools.TestCase): """Base class for desktop testing""" setupOnce = False # Set it static because LDTP can run only one app at once. application = None # Class and Test Configuration # This configuration is specific to the run and different from the # global configuration. # By default the name $(basename MODULEFILEPATH).ini testConfig = None def __init__(self, methodName = 'testMethod'): """Construct a TestCase instance Loads the configuration for the application and the test """ super(TestCase, self).__init__(methodName) #self.magoConfig = get_config() moduleFile = getfile(getmodule(self)) classConfigFile = '.'.join(moduleFile.split('.')[:-1]) + ".ini" self.testConfig = get_config(classConfigFile) @classmethod def setUpClass(self): """setUpClass Called once for all the tests in a TestCase. set setupOnce to True to activate it. This is used if you want to launch the application to test only once at the beginning of the test session or want to do some extensive setup """ super(TestCase, self).setUpClass() def setUp(self): """setUp Launch the application when setupOnce is set to False """ super(TestCase, self).setUp() if not hasattr(TestCase, 'application'): TestCase.application = None application = TestCase.application # Check mandatory propertys, launcher, launcher_args and window_name if not application: TestCase.application =\ TestApplication(self.launcher, window_name = self.window_name) #TestCase.application.launch() else: if not application.isRunning: TestCase.application.launch() @classmethod def tearDownClass(self): """tearDownClass Called once at the end of the class to close the application and cleanup the environment and destroy the application. Only called if setupOnce is set to True. """ super(TestCase, self).tearDownClass() if self.setupOnce and TestCase.application: del TestCase.application def tearDown(self): """tearDown Called once at the end of the test to close the application and cleanup the environment and destroy the application. Only called if setupOnce is set to False. """ super(TestCase, self).tearDown() if not self.setupOnce and TestCase.application: del TestCase.application def getapplication(self): return self.application class TestResult(testtools.TestResult): showAll = True def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1): super(TestResult, self).__init__() print "TestResult::__init__" self.stream = stream self.descriptions = descriptions def getDescription(self, test): doc_first_line = test.shortDescription() if self.descriptions and doc_first_line: return '\n'.join((str(test), doc_first_line)) else: return str(test) def startTest(self, test): super(TestResult, self).startTest(test) if self.showAll: self.stream.write(self.getDescription(test)) self.stream.write(" ... ") self.stream.flush() def addSuccess(self, test): super(TestResult, self).addSuccess(test) if self.showAll: self.stream.write(self.getDescription(test)) self.stream.write(" Success ") self.stream.flush() class TextTestRunner(unittest.TextTestRunner): resultclass = TestResult #def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1, resultclass=None): # super(TextTestRunner, self).__init__(stream, descriptions, verbosity, resultclass) # print "TestRunner::__init__" #main = nose.main def main(): global PLUGINS nose.main(addplugins = PLUGINS) if __name__ == '__main__': main() mago-0.3+bzr20/mago/magomatic.py0000644000000000000000000001643311515407742016443 0ustar rootroot00000000000000# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- # Copyright (C) 2009-2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os import re import sys import ldtp import ooldtp import shutil from time import sleep from magomaticconfig import get_data_file, get_data_path class Magomatic: """ """ def __init__(self, launcher, main_window, child_window = None, \ overwrite = False, white_list=[]): self.launcher = launcher if child_window: appname = main_window else: appname = launcher self.appname = re.sub('\W', '_', appname.lower()) self.overwrite = overwrite self.main_window = main_window self.child_window = child_window self.white_list = ["check_box", "check_menu_item", "combo_box", "entry", "icon", "list", "menu", "menu_item", "page_tab", "page_tab_list", "push_button", "radio_button", "radio_menu_item", "scroll_bar", "spin_button", "table", "text", "toggle_button", "tree", "tree_table"] self.app_folder = get_data_file(launcher) def _launchapp(self, progname): '''returns the window name while ldtp.launchapp returns the PID''' winlist=ldtp.getwindowlist() timeout=60 ldtp.launchapp(progname) # Any way to get the window name from the app name ? # appundertest is not implemented in LDTPv2 wincount=len(winlist) wincount_orig = wincount while wincount == wincount_orig and timeout > 0: winlist = ldtp.getwindowlist() wincount = len(winlist) timeout -= 1 sleep(1) if timeout <= 0: print "Failed to identify window name for '%s'" % progname sys.exit(2) return(winlist[-1]) def create_app_folder(self): return template = get_data_file("template") substitutions = (("name_application", self.appname), ("NameApplication", self.appname.capitalize()), ("Application Basics", self.appname.capitalize()), ) if self.child_window: leafs = ('application') else: leafs = ('application','test_suite', self.appname) for leaf in leafs: try: os.makedirs(os.path.join(self.app_folder, leaf)) except OSError, e: if e.errno != 17: # File exists raise OSError, e for dirpath, dirnames, filenames in os.walk(template): for filename in filenames: target_file = filename for pattern, sub in substitutions: target_file = target_file.replace(pattern, sub) file_path = os.path.join(dirpath, filename) relpath = os.path.dirname(os.path.relpath(file_path, template)) for pattern, sub in substitutions: relpath = relpath.replace(pattern, sub) if self.child_window and (relpath == 'test_suite' or \ relpath == self.appname): continue file_des = open(file_path,'r') file_contents = file_des.read() for s in substitutions: pattern, sub = s file_contents = file_contents.replace(pattern,sub) target_path = os.path.join(self.app_folder, relpath + "/" + target_file) if (not self.overwrite) and os.path.exists(target_path): print "Failed to add file to project\n cannot add: %s - this file already exists." % target_path sys.exit(4) file_des = open(target_path, "w") file_des.write(file_contents) def discover_application(self, tree = False): """Dump the list of components of the application :param tree: If True, dump the component tree instead of the application map """ if self.launcher and not self.main_window: # Only launcher pass as argument we try to guess the name of the main windows self.main_window = self._launchapp(self.launcher) elif not ldtp.guiexist(self.main_window): ldtp.launchapp(self.launcher) ldtp.waittillguiexist(self.main_window) app = ooldtp.context(self.main_window) if tree: self.walk_application(self.main_window) else: constants = "" if not self.child_window: # If main window, then added launcher constants += "launcher = '%s'\n" % self.launcher constants += "launcher_args = []\n" constants += "window_name = '%s'\n\n" % re.sub('\W', '*', self.main_window) objectlist = sorted(app.getobjectlist()) for component in objectlist: role = ldtp.getobjectproperty(self.main_window, component, 'class') component = component.encode("UTF-8") constant = "" if role in self.white_list: #constant = re.sub('\W', '_', component.upper()) #constant = constant[:3] + "_" + constant[3:] # Split prefix for clarity #constants += " " + constant +" = _('" + re.sub('\W', '*', component) + "')\n" # All is commented by default constants += '#%s = "%s"\n' % (re.sub('\W', '_', component), component) print constants #app_file = os.path.join(self.app_folder, "application/" + self.appname + ".py") #read_file = open(app_file, "r") #contents = read_file.read() #contents = contents.replace("CONSTANTS", constants) #write_file = open(app_file, "w") #write_file.write(contents) #write_file.close() #if 'mnuQuit' in objectlist: ldtp.closewindow(self.main_window) ldtp.waittillguinotexist (self.main_window) def walk_application(self, node = None, level = 1): """Walk the component tree of the application :param node: Name of the parent node :param level: Level of the node """ if not node: return if level == 1: print node children = ldtp.getobjectproperty(self.main_window, node, 'children').split(' ') for child in children: if not child: continue print "%s|__ %s" % ("| " * (level - 1), child) self.walk_application(child, level + 1) mago-0.3+bzr20/mago/magomaticconfig.py0000644000000000000000000000310411515275242017616 0ustar rootroot00000000000000# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- ### BEGIN LICENSE # This file is in the public domain ### END LICENSE # THIS IS Magomatic CONFIGURATION FILE # YOU CAN PUT THERE SOME GLOBAL VALUE # Do not touch unless you know what you're doing. # you're warned :) __all__ = [ 'project_path_not_found', 'get_data_file', 'get_data_path', ] # Where your project will look for your data (for instance, images and ui # files). By default, this is ../data, relative your trunk layout __magomatic_data_directory__ = '../data/' __license__ = '' import os import gettext from gettext import gettext as _ gettext.textdomain('magomatic') class project_path_not_found(Exception): """Raised when we can't find the project directory.""" def get_data_file(*path_segments): """Get the full path to a data file. Returns the path to a file underneath the data directory (as defined by `get_data_path`). Equivalent to os.path.join(get_data_path(), *path_segments). """ return os.path.join(get_data_path(), *path_segments) def get_data_path(): """Retrieve magomatic data path This path is by default /../data/ in trunk and /usr/share/magomatic in an installed version but this path is specified at installation time. """ # Get pathname absolute or relative. path = os.path.join( os.path.dirname(__file__), __magomatic_data_directory__) abs_data_path = os.path.abspath(path) if not os.path.exists(abs_data_path): raise project_path_not_found return abs_data_path mago-0.3+bzr20/mago/mouse/0000755000000000000000000000000011511546543015250 5ustar rootroot00000000000000mago-0.3+bzr20/mago/mouse/__init__.py0000644000000000000000000000213711511546543017364 0ustar rootroot00000000000000# -*- coding: iso-8859-1 -*- # Copyright 2010 Pepijn de Vos # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """The goal of PyMouse is to have a cross-platform way to control the mouse. PyMouse should work on Windows, Mac and any Unix that has xlib. See http://github.com/pepijndevos/PyMouse for more information. """ import sys if sys.platform.startswith('java'): from java_ import PyMouse elif sys.platform == 'darwin': from mac import PyMouse, PyMouseEvent elif sys.platform == 'win32': from windows import PyMouse, PyMouseEvent else: from unix import PyMouse, PyMouseEvent mago-0.3+bzr20/mago/mouse/base.py0000644000000000000000000000455011511546543016540 0ustar rootroot00000000000000# -*- coding: iso-8859-1 -*- # Copyright 2010 Pepijn de Vos # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """The goal of PyMouse is to have a cross-platform way to control the mouse. PyMouse should work on Windows, Mac and any Unix that has xlib. See http://github.com/pepijndevos/PyMouse for more information. """ from threading import Thread class PyMouseMeta(object): def press(self, x, y, button = 1): """Press the mouse on a givven x, y and button. Button is defined as 1 = left, 2 = right, 3 = middle.""" raise NotImplementedError def release(self, x, y, button = 1): """Release the mouse on a givven x, y and button. Button is defined as 1 = left, 2 = right, 3 = middle.""" raise NotImplementedError def click(self, x, y, button = 1): """Click the mouse on a givven x, y and button. Button is defined as 1 = left, 2 = right, 3 = middle.""" self.press(x, y, button) self.release(x, y, button) def move(self, x, y): """Move the mouse to a givven x and y""" raise NotImplementedError def position(self): """Get the current mouse position in pixels. Returns a tuple of 2 integers""" raise NotImplementedError def screen_size(self): """Get the current screen size in pixels. Returns a tuple of 2 integers""" raise NotImplementedError class PyMouseEventMeta(Thread): def __init__(self, capture=False): Thread.__init__(self) self.daemon = True self.capture = capture self.state = True def stop(self): self.state = False def click(self, x, y, button, press): """Subclass this method with your click event handler""" pass def move(self, x, y): """Subclass this method with your move event handler""" pass mago-0.3+bzr20/mago/mouse/java_.py0000644000000000000000000000300011511546543016673 0ustar rootroot00000000000000# -*- coding: iso-8859-1 -*- # Copyright 2010 Pepijn de Vos # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from java.awt import Robot, Toolkit from java.awt.event import InputEvent from java.awt.MouseInfo import getPointerInfo from base import PyMouseMeta r = Robot() class PyMouse(PyMouseMeta): def press(self, x, y, button = 1): button_list = [None, InputEvent.BUTTON1_MASK, InputEvent.BUTTON3_MASK, InputEvent.BUTTON2_MASK] self.move(x, y) r.mousePress(button_list[button]) def release(self, x, y, button = 1): button_list = [None, InputEvent.BUTTON1_MASK, InputEvent.BUTTON3_MASK, InputEvent.BUTTON2_MASK] self.move(x, y) r.mouseRelease(button_list[button]) def move(self, x, y): r.mouseMove(x, y) def position(self): loc = getPointerInfo().getLocation() return loc.getX, loc.getY def screen_size(self): dim = Toolkit.getDefaultToolkit().getScreenSize() return dim.getWidth(), dim.getHeight() mago-0.3+bzr20/mago/mouse/mac.py0000644000000000000000000000556311511546543016373 0ustar rootroot00000000000000# -*- coding: iso-8859-1 -*- # Copyright 2010 Pepijn de Vos # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from Quartz import * from AppKit import NSEvent from base import PyMouseMeta, PyMouseEventMeta pressID = [None, kCGEventLeftMouseDown, kCGEventRightMouseDown, kCGEventOtherMouseDown] releaseID = [None, kCGEventLeftMouseUp, kCGEventRightMouseUp, kCGEventOtherMouseUp] class PyMouse(PyMouseMeta): def press(self, x, y, button = 1): event = CGEventCreateMouseEvent(None, pressID[button], (x, y), button - 1) CGEventPost(kCGHIDEventTap, event) def release(self, x, y, button = 1): event = CGEventCreateMouseEvent(None, releaseID[button], (x, y), button - 1) CGEventPost(kCGHIDEventTap, event) def move(self, x, y): move = CGEventCreateMouseEvent(None, kCGEventMouseMoved, (x, y), 0) CGEventPost(kCGHIDEventTap, move) def position(self): loc = NSEvent.mouseLocation() return loc.x, CGDisplayPixelsHigh(0) - loc.y def screen_size(self): return CGDisplayPixelsWide(0), CGDisplayPixelsHigh(0) class PyMouseEvent(PyMouseEventMeta): def run(self): tap = CGEventTapCreate( kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, CGEventMaskBit(kCGEventMouseMoved) | CGEventMaskBit(kCGEventLeftMouseDown) | CGEventMaskBit(kCGEventLeftMouseUp) | CGEventMaskBit(kCGEventRightMouseDown) | CGEventMaskBit(kCGEventRightMouseUp) | CGEventMaskBit(kCGEventOtherMouseDown) | CGEventMaskBit(kCGEventOtherMouseUp), self.handler, None) loopsource = CFMachPortCreateRunLoopSource(None, tap, 0) loop = CFRunLoopGetCurrent() CFRunLoopAddSource(loop, loopsource, kCFRunLoopDefaultMode) CGEventTapEnable(tap, True) while self.state: CFRunLoopRunInMode(kCFRunLoopDefaultMode, 5, False) def handler(self, proxy, type, event, refcon): (x, y) = CGEventGetLocation(event) if type in pressID: self.click(x, y, pressID.index(type), True) elif type in releaseID: self.click(x, y, releaseID.index(type), False) else: self.move(x, y) if self.capture: CGEventSetType(event, kCGEventNull) return event mago-0.3+bzr20/mago/mouse/unix.py0000644000000000000000000000654511511546543016617 0ustar rootroot00000000000000# -*- coding: iso-8859-1 -*- # Copyright 2010 Pepijn de Vos # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from Xlib.display import Display from Xlib import X from Xlib.ext.xtest import fake_input from Xlib.ext import record from Xlib.protocol import rq from base import PyMouseMeta, PyMouseEventMeta display = Display() display2 = Display() class PyMouse(PyMouseMeta): def press(self, x, y, button = 1): self.move(x, y) fake_input(display, X.ButtonPress, [None, 1, 3, 2, 4, 5][button]) display.sync() def release(self, x, y, button = 1): self.move(x, y) fake_input(display, X.ButtonRelease, [None, 1, 3, 2, 4, 5][button]) display.sync() def move(self, x, y): fake_input(display, X.MotionNotify, x=x, y=y) display.sync() def position(self): coord = display.screen().root.query_pointer()._data return coord["root_x"], coord["root_y"] def screen_size(self): width = display.screen().width_in_pixels height = display.screen().height_in_pixels return width, height class PyMouseEvent(PyMouseEventMeta): def __init__(self): PyMouseEventMeta.__init__(self) self.ctx = display2.record_create_context( 0, [record.AllClients], [{ 'core_requests': (0, 0), 'core_replies': (0, 0), 'ext_requests': (0, 0, 0, 0), 'ext_replies': (0, 0, 0, 0), 'delivered_events': (0, 0), 'device_events': (X.ButtonPressMask, X.ButtonReleaseMask), 'errors': (0, 0), 'client_started': False, 'client_died': False, }]) def run(self): if self.capture: display2.screen().root.grab_pointer(True, X.ButtonPressMask | X.ButtonReleaseMask, X.GrabModeAsync, X.GrabModeAsync, 0, 0, X.CurrentTime) display2.record_enable_context(self.ctx, self.handler) display2.record_free_context(self.ctx) def stop(self): display.record_disable_context(self.ctx) display.ungrab_pointer(X.CurrentTime) display.flush() display2.record_disable_context(self.ctx) display2.ungrab_pointer(X.CurrentTime) display2.flush() def handler(self, reply): data = reply.data while len(data): event, data = rq.EventField(None).parse_binary_value(data, display.display, None, None) if event.type == X.ButtonPress: self.click(event.root_x, event.root_y, (None, 1, 3, 2, 3, 3, 3)[event.detail], True) elif event.type == X.ButtonRelease: self.click(event.root_x, event.root_y, (None, 1, 3, 2, 3, 3, 3)[event.detail], False) else: self.move(event.root_x, event.root_y) mago-0.3+bzr20/mago/mouse/windows.py0000644000000000000000000000644211511546543017322 0ustar rootroot00000000000000# -*- coding: iso-8859-1 -*- # Copyright 2010 Pepijn de Vos # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. clicks = [None, 2, 8, 32] releases = [None, 4, 16, 64] from ctypes import * from win32api import GetSystemMetrics from base import PyMouseMeta, PyMouseEventMeta import pythoncom, pyHook from time import sleep PUL = POINTER(c_ulong) class MouseInput(Structure): _fields_ = [("dx", c_long), ("dy", c_long), ("mouseData", c_ulong), ("dwFlags", c_ulong), ("time",c_ulong), ("dwExtraInfo", PUL)] class Input_I(Union): _fields_ = [("mi", MouseInput)] class Input(Structure): _fields_ = [("type", c_ulong), ("ii", Input_I)] FInputs = Input * 2 extra = c_ulong(0) click = Input_I() click.mi = MouseInput(0, 0, 0, 2, 0, pointer(extra)) release = Input_I() release.mi = MouseInput(0, 0, 0, 4, 0, pointer(extra)) blob = FInputs( (0, click), (0, release) ) class POINT(Structure): _fields_ = [("x", c_ulong), ("y", c_ulong)] class PyMouse(PyMouseMeta): def press(self, x, y, button = 1): self.move(x, y) blob[0].ii.mi.dwFlags = clicks[button] windll.user32.SendInput(2,pointer(blob),sizeof(blob[0])) def release(self, x, y, button = 1): self.move(x, y) blob[1].ii.mi.dwFlags = releases[button] windll.user32.SendInput(2,pointer(blob),sizeof(blob[0])) def move(self, x, y): windll.user32.SetCursorPos(x, y) def position(self): pt = POINT() windll.user32.GetCursorPos(byref(pt)) return pt.x, pt.y def screen_size(self): width = GetSystemMetrics(0) height = GetSystemMetrics(1) return width, height class PyMouseEvent(PyMouseEventMeta): def run(self): hm = pyHook.HookManager() hm.MouseAllButtons = self._click hm.MouseMove = self._move hm.HookMouse() while self.state: sleep(0.01) pythoncom.PumpWaitingMessages() def _click(self, event): x,y = event.Position if event.Message == pyHook.HookConstants.WM_LBUTTONDOWN: self.click(x, y, 1, True) elif event.Message == pyHook.HookConstants.WM_LBUTTONUP: self.click(x, y, 1, False) elif event.Message == pyHook.HookConstants.WM_RBUTTONDOWN: self.click(x, y, 2, True) elif event.Message == pyHook.HookConstants.WM_RBUTTONUP: self.click(x, y, 2, False) elif event.Message == pyHook.HookConstants.WM_MBUTTONDOWN: self.click(x, y, 3, True) elif event.Message == pyHook.HookConstants.WM_MBUTTONUP: self.click(x, y, 3, False) return not self.capture def _move(self, event): x,y = event.Position self.move(x, y) return not self.capture mago-0.3+bzr20/mago/noseplugins/0000755000000000000000000000000011511546543016466 5ustar rootroot00000000000000mago-0.3+bzr20/mago/noseplugins/__init__.py0000644000000000000000000000207711511546543020605 0ustar rootroot00000000000000# Copyright (C) 2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Testing framework extensions for desktop testing""" #from mago.plugs import main, TestCase, TestResult, TextTestRunner __author__ = 'Jean-Baptiste Lallement' __copyright__ = '2010 Canonical Ltd' __versioninfo__ = (0, 0, 1) __version__ = '.'.join(map(str, __versioninfo__)) #__all__ = [ 'main', 'TestCase', 'TestResult', 'TextTestRunner' ] mago-0.3+bzr20/mago/noseplugins/magoreport.xsl0000644000000000000000000001511211511630315021364 0ustar rootroot00000000000000 Mago Tests Report

    Mago Tests Report

    This are the results from a run of Mago Desktop Tests. If you find false positives, please, report bugs against Mago project.

    Suite
    Class
    Description
    TestCase Name Description Method Status Time Elapsed (s) Message Screenshot Stacktrace
    Script Error Test Failed Passed

    The suite had an error in the setup, teardown or cleanup methods.

    [Show/Hide Stacktrace]
    mago-0.3+bzr20/mago/noseplugins/magoxml.py0000644000000000000000000002140611511630315020476 0ustar rootroot00000000000000 """This plugin provides test results in Mago 1.0 Compatible XML format. It's needed while transitioning from the previous version of mago until the tests have been converted to mago-ng. The output is simplified compared to mago itself because the changes with the xml file are incompatible with mago-ng Add this shell command to your builder :: nosetests --with-magoxml And by default a file named mago.xml will be written to the working directory. If you need to change the name or location of the file, you can set the ``--magoxml-file`` option. Here is an example output gedit_chains.GEditChain Tests which verify gedit's save file functionality. testChain Test ASCII text saving. 1 """ import doctest import os import traceback import re import inspect from nose.plugins.base import Plugin from nose.exc import SkipTest from time import time from xml.sax import saxutils from subprocess import Popen, PIPE # Invalid XML characters, control characters 0-31 sans \t, \n and \r CONTROL_CHARACTERS = re.compile(r"[\000-\010\013\014\016-\037]") REPORT_XSL = os.path.join(os.path.dirname(__file__), "magoreport.xsl") def xml_safe(value): """Replaces invalid XML characters with '?'.""" return CONTROL_CHARACTERS.sub('?', value) def escape_cdata(cdata): """Escape a string for an XML CDATA section.""" return xml_safe(cdata).replace(']]>', ']]>]]>>> nice_classname(Exception()) # doctest: +ELLIPSIS '...Exception' >>> nice_classname(Exception) 'exceptions.Exception' """ if inspect.isclass(obj): cls_name = obj.__name__ else: cls_name = obj.__class__.__name__ mod = inspect.getmodule(obj) if mod: name = mod.__name__ # jython if name.startswith('org.python.core.'): name = name[len('org.python.core.'):] return "%s.%s" % (name, cls_name) else: return cls_name def exc_message(exc_info): """Return the exception's message.""" exc = exc_info[1] if exc is None: # str exception result = exc_info[0] else: try: result = str(exc) except UnicodeEncodeError: try: result = unicode(exc) except UnicodeError: # Fallback to args as neither str nor # unicode(Exception(u'\xe6')) work in Python < 2.6 result = exc.args[0] return xml_safe(result) class MagoXML(Plugin): """This plugin provides test results in the standard magoxml XML format.""" name = 'magoxml' encoding = 'UTF-8' error_report_file = None error_report_html = None def _timeTaken(self): if hasattr(self, '_timer'): taken = time() - self._timer else: # test died before it ran (probably error in setup()) # or success/failure added before test started probably # due to custom TestResult munging taken = 0.0 return taken def _quoteattr(self, attr): """Escape an XML attribute. Value can be unicode.""" attr = xml_safe(attr) if isinstance(attr, unicode): attr = attr.encode(self.encoding) return saxutils.quoteattr(attr) def options(self, parser, env): """Sets additional command line options.""" Plugin.options(self, parser, env) parser.add_option( '--magoxml-file', action='store', dest='magoxml_file', metavar="FILE", default=env.get('NOSE_MAGOXML_FILE', 'mago_result.xml'), help=("Path to xml file to store the mago report in. " "Default is mago_result.xml in the working directory " "[NOSE_MAGOXML_FILE]")) parser.add_option( '--magoxml-html', action='store', dest='magoxml_html', metavar="FILE", default=env.get('NOSE_MAGOXML_HTML'), help=("Path to html file to store the mago report in. If this" "option is not set only the xml report is generated" "[NOSE_MAGOXML_HTML]")) def configure(self, options, config): """Configures the magoxml plugin.""" Plugin.configure(self, options, config) self.config = config if self.enabled: self.stats = {'errors': 0, 'failures': 0, 'passes': 0, 'skipped': 0 } self.errorlist = [] self.error_report_file = open(options.magoxml_file, 'w') self.error_report_html = options.magoxml_html def report(self, stream): """Writes an magoxml-formatted XML file The file includes a report of test errors and failures. """ self.stats['encoding'] = self.encoding self.stats['total'] = (self.stats['errors'] + self.stats['failures'] + self.stats['passes'] + self.stats['skipped']) self.stats['suitename'] = self._suitename self.error_report_file.write( '' '' % self.stats) self.error_report_file.write(''.join(self.errorlist)) self.error_report_file.write('') self.error_report_file.close() if self.config.verbosity > 1: stream.writeln("-" * 70) stream.writeln("XML: %s" % self.error_report_file.name) if self.error_report_html: cmd = ["xsltproc", "-o", self.error_report_html, REPORT_XSL, self.error_report_file.name] p = Popen(cmd) def startTest(self, test): """Initializes a timer before starting a test.""" self._timer = time() self._suitename = self._quoteattr(test.id().split('.')[0]) def addError(self, test, err, capt=None): """Add error output to magoxml report. """ taken = self._timeTaken() if issubclass(err[0], SkipTest): type = 'skipped' self.stats['skipped'] += 1 else: type = 'error' self.stats['errors'] += 1 tb = ''.join(traceback.format_exception(*err)) id = test.id() desc = test.shortDescription() self.errorlist.append( '' '%(cls)s' '%(desc)s' '0' % {'name': self._quoteattr(id.split('.')[-1]), 'cls': self._quoteattr('.'.join(id.split('.')[-2:])), 'desc': desc, 'tb': escape_cdata(tb), 'message': self._quoteattr(exc_message(err)), 'taken': taken, }) def addFailure(self, test, err, capt=None, tb_info=None): """Add failure output to magoxml report. """ taken = self._timeTaken() tb = ''.join(traceback.format_exception(*err)) self.stats['failures'] += 1 id = test.id() desc = test.shortDescription() self.errorlist.append( '' '%(cls)s' '%(desc)s' '0' % {'name': self._quoteattr(id.split('.')[-1]), 'cls': self._quoteattr('.'.join(id.split('.')[-2:])), 'desc': desc, 'tb': escape_cdata(tb), 'message': self._quoteattr(exc_message(err)), 'taken': taken, }) def addSuccess(self, test, capt=None): """Add success output to magoxml report. """ taken = self._timeTaken() self.stats['passes'] += 1 id = test.id() desc = test.shortDescription() self.errorlist.append( '' '%(cls)s' '%(desc)s' '1' % {'name': self._quoteattr(id.split('.')[-1]), 'cls': self._quoteattr('.'.join(id.split('.')[-2:])), 'desc': desc, 'taken': taken, }) mago-0.3+bzr20/mago/noseplugins/maybe.py0000644000000000000000000000063711511546543020143 0ustar rootroot00000000000000from nose.plugins.base import Plugin class Maybe(Plugin): def setOutputStream(self, stream): self.stream = stream return self def flush(self): self.stream.flush() def writeln(self, out=""): self.write(out + "\n") def write(self, out): if out == "ok\n": out = "maybe\n" elif out == ".": out = "?" self.stream.write(out) mago-0.3+bzr20/mago/struct.py0000644000000000000000000000155711516142673016027 0ustar rootroot00000000000000# Copyright (C) 2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class Struct(): def __getattr__(self, name): return self.name if hasattr(self, name) else setattr(self, name, None) mago-0.3+bzr20/mago/unity/0000755000000000000000000000000011511546543015270 5ustar rootroot00000000000000mago-0.3+bzr20/mago/unity/__init__.py0000644000000000000000000000255311511546543017406 0ustar rootroot00000000000000#/usr/bin/python import dbus.exceptions import dbus.service import dbus.mainloop.glib import dbus.glib class Unity(object): dbgbus_name = 'com.canonical.Unity' dbgbus_path = '/com/canonical/Unity/Debug/Introspection' dbgbus_interface = 'com.canonical.Unity.Debug.Introspection' _state = None def __init__(self): self._bus = dbus.SessionBus() self._proxyobj = self._bus.get_object(self.dbgbus_name, self.dbgbus_path) self._dbgiface = dbus.Interface(self._proxyobj, self.dbgbus_interface) self._state = None def get_state(self, UIElement = None): """Dump the state of the UIElement UIElement: Launcher, Panel, ... or All is None or Unity """ self._state = self._dbgiface.GetState(UIElement) return self._state def walk_state(self, data = None, level=0): """ Dump the state in a human readable format data: If None uses self._state level: Level of the node """ if data is None: data = self._state level += 1 if isinstance(data, dbus.Dictionary): for k, v in data.iteritems(): print " " * level, k self.walk_state(v, level) elif isinstance(data, dbus.Struct): for v in data: #print " " * level, v self.walk_state(v, level) else: print " " * level, data def runtest(): u = Unity() s = u.get_state('panel') u.walk_state() if __name__ == '__main__': runtest() mago-0.3+bzr20/mago/utils.py0000644000000000000000000001015211515250106015620 0ustar rootroot00000000000000# Copyright (C) 2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Various tools to compare files and images, take screenshot, run commands, manage packages, ... """ from filecmp import cmp import subprocess import gconf def a11y_enabled(): """Return True is a11y is enabled""" client = gconf.client_get_default() return client.get_bool('/desktop/gnome/interface/accessibility') def file_compare(file1, file2): """Compare 2 files and returns True if files are equals""" try: return cmp(file1, file2) except OSError: return False # http://www.chiark.greenend.org.uk/ucgi/~cjwatson/blosxom/2009-07-02-python-sigpipe.html # This is needed so that the subprocesses that produce endless output # actually quit when the reader goes away. import signal def subprocess_setup(): # Python installs a SIGPIPE handler by default. This is usually not what # non-Python subprocesses expect. signal.signal(signal.SIGPIPE, signal.SIG_DFL) def cmd(command, input = None, stderr = subprocess.STDOUT, stdout = subprocess.PIPE, stdin = None, env = None): """Try to execute given command (array) and return its stdout, or return a textual error if it failed. :param command: :param input: Default: None :param stderr: Default: STDOUT :param stdout: :param stdin: :param env: """ try: sp = subprocess.Popen(command, stdin=stdin, stdout=stdout, stderr=stderr, close_fds=True, preexec_fn=subprocess_setup, env = env) except OSError, e: return [127, str(e)] out, outerr = sp.communicate(input) # Handle redirection of stdout if out == None: out = '' # Handle redirection of stderr if outerr == None: outerr = '' return [sp.returncode,out+outerr] def dpkg(package, action = 'status', queryformat = "${Package} ${Version}\t${Status}"): """Execute a dpkg action on a package. The user needs sudo privileges in order to execute the actions install, purge and remove. :param package: A package name or a package file for the action 'install' :param action: Valid actions are: - install: Install a package. the argument 'package' needs to be a valid deb archive - remove: Remove a package - purge: Remove a package and its configuration files - query: Show information about the package. Default format "${Package} ${Version}\t${Status}" man dpkg-query for additional information - status: Report the status of a specified package. This is the default action Returns the return code and output of dpkg """ action = action.lower() if action == 'install': dpkg_cmd = ['sudo', 'dpkg', '-i', package] elif action == 'purge': dpkg_cmd = ['sudo', 'dpkg', '-p', package] elif action == 'remove': dpkg_cmd = ['sudo', 'dpkg', '-r', package] elif action == 'query': dpkg_cmd = ['dpkg-query', '-W', '-f', queryformat, package] elif action == 'status': dpkg_cmd = ['dpkg', '-s', package] else: raise NotImplementedError, "dpkg action '%s' is not supported" % action return cmd(dpkg_cmd) def is_package_installed(package): """Query the dpkg status database and returns True is the specified package is installed :param package: Package name """ (rc, output) = dpkg(package, action='query', queryformat = '${Status}') return output.startswith('install') mago-0.3+bzr20/mago/xlib/0000755000000000000000000000000011511546543015056 5ustar rootroot00000000000000mago-0.3+bzr20/mago/xlib/__init__.py0000644000000000000000000000370711515663552017202 0ustar rootroot00000000000000# Copyright (C) 2010-2011 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Import pywo library and define additional extensions""" from xlib import * from time import sleep def window_from_pid(pid, command = None): """ Return the first XID matching a PID :param pid: Process ID :param command: Command used to launch the application. Used as fallback to find the window using WM_COMMAND """ WM.flush() # Lets try 5 secs before aborting for i in range(0,10): for w in WM.windows(): try: wm_pid = w.get_property('_NET_WM_PID') if wm_pid and wm_pid.value[0] == pid: return w # Workaround # BadWindow: : code = 3 except xlib.error.BadWindow: pass # Failed with PID try with command if command: for w in WM.windows(): try: wm_cmd = w.get_property('WM_COMMAND') if wm_cmd and command in wm_cmd.value: return w # Workaround # BadWindow: : code = 3 except xlib.error.BadWindow: pass sleep(.5) return None mago-0.3+bzr20/mago/xlib/xlib.py0000644000000000000000000011016611511546543016373 0ustar rootroot00000000000000# # PyWO - Python Window Organizer # Copyright 2010, Wojciech 'KosciaK' Pietrzok # # This file is part of PyWO. # # PyWO is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # PyWO is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PyWO. If not, see . # """core.py - an abstract layer between Xlib and the rest of aplication. core module (with events module) encapsulates all comunication with X Server. It contains objects representing Window Manager, Windows, and other basic concepts needed for repositioning and resizing windows (size, position, borders, gravity, etc). """ import logging import re import time import threading from sys import exit try: from Xlib import X, XK, Xatom, protocol, error from Xlib.display import Display except ImportError: print "Xlib support is required. Install the package python-xlib.\nExiting..." exit(1) __author__ = "Wojciech 'KosciaK' Pietrzok " # Pattern matching simple calculations with floating numbers _PATTERN = re.compile('^[ 0-9\.\+-/\*]+$') # Predefined sizes that can be used in config files _SIZES = {'FULL': '1.0', 'HALF': '0.5', 'THIRD': '1.0/3', 'QUARTER': '0.25', } # Predefined gravities, that can be used in config files _GRAVITIES = {'TOP_LEFT': (0, 0), 'UP_LEFT': (0, 0), 'TOP': (0.5, 0), 'UP': (0.5, 0), 'TOP_RIGHT': (1, 0), 'UP_RIGHT': (1, 0), 'LEFT': (0, 0.5), 'MIDDLE': (0.5, 0.5), 'CENTER': (0.5, 0.5), 'RIGHT': (1, 0.5), 'BOTTOM_LEFT': (0, 1), 'DOWN_LEFT': (0, 1), 'BOTTOM': (0.5, 1), 'DOWN': (0.5, 1), 'BOTTOM_RIGHT': (1, 1), 'DOWN_RIGHT': (1, 1), } class Gravity(object): """Gravity point as a percentage of width and height of the window.""" def __init__(self, x, y): """ x - percentage of width y - percentage of height """ self.x = x self.y = y self.is_middle = (x == 1.0/2) and (y == 1.0/2) @property def is_top(self): """Return True if gravity is toward top.""" return self.y < 1.0/2 or self.is_middle @property def is_bottom(self): """Return True if gravity is toward bottom.""" return self.y > 1.0/2 or self.is_middle @property def is_left(self): """Return True if gravity is toward left.""" return self.x < 1.0/2 or self.is_middle @property def is_right(self): """Return True if gravity is toward right.""" return self.x > 1.0/2 or self.is_middle def invert(self, vertical=True, horizontal=True): """Invert the gravity (left becomes right, top becomes bottom).""" x, y = self.x, self.y if vertical: y = 1.0 - self.y if horizontal: x = 1.0 - self.x return Gravity(x, y) @staticmethod def parse(gravity): """Parse gravity string and return Gravity object. It can be one of predefined __GRAVITIES, or x and y values (floating numbers or those described in __SIZES). """ if not gravity: return None if gravity in _GRAVITIES: x, y = _GRAVITIES[gravity] else: for name, value in _SIZES.items(): gravity = gravity.replace(name, value) x, y = [eval(xy) for xy in gravity.split(',') if _PATTERN.match(xy)] return Gravity(x, y) def __eq__(self, other): return ((self.x, self.y) == (other.x, other.y)) def __ne__(self, other): return not self == other def __str__(self): return '(%.2f, %.2f)' % (self.x, self.y) class Size(object): """Size encapsulates width and height of the object.""" def __init__(self, width, height): self.width = width self.height = height @staticmethod def parse(width, height): """Parse width and height strings and return Size object. It can be float number (value will be evaluatedi, so 1.0/2 is valid) or predefined value in __SIZES. """ if not width or not height: return None for name, value in _SIZES.items(): width = width.replace(name, value) height = height.replace(name, value) width = [eval(width) for width in width.split(',') if _PATTERN.match(width)] if len(width) == 1: width = width[0] height = [eval(height) for height in height.split(',') if _PATTERN.match(height)] if len(height) == 1: height = height[0] return Size(width, height) def __eq__(self, other): return ((self.width, self.height) == (other.width, other.height)) def __ne__(self, other): return not self == other def __str__(self): string = 'width: %s, height: %s' return string % (self.width, self.height) class Position(object): """Position encapsulates Position of the object. Position coordinates starts at top-left corner of the desktop. """ def __init__(self, x, y): self.x = x self.y = y def __eq__(self, other): return ((self.x, self.y) == (other.x, other.y)) def __ne__(self, other): return not self == other def __str__(self): string = 'x: %s, y: %s' return string % (self.x, self.y) class Geometry(Position, Size): """Geometry combines Size and Position of the object. Position coordinates (x, y) starts at top left corner of the desktop. (x2, y2) are the coordinates of the bottom-right corner of the object. """ __DEFAULT_GRAVITY = Gravity(0, 0) def __init__(self, x, y, width, height, gravity=__DEFAULT_GRAVITY): Size.__init__(self, int(width), int(height)) x = int(x) - self.width * gravity.x y = int(y) - self.height * gravity.y Position.__init__(self, x, y) @property def x2(self): return self.x + self.width @property def y2(self): return self.y + self.height def set_position(self, x, y, gravity=__DEFAULT_GRAVITY): """Set position with (x,y) as gravity point.""" self.x = x - self.width * gravity.x self.y = y - self.height * gravity.y def __eq__(self, other): return ((self.x, self.y, self.width, self.height) == (other.x, other.y, other.width, other.height)) def __ne__(self, other): return not self == other def __str__(self): string = 'x: %s, y: %s, width: %s, height: %s, x2: %s, y2: %s' return string % (self.x, self.y, self.width, self.height, self.x2, self.y2) class Borders(object): """Borders encapsulate Window borders (frames/decorations).""" def __init__(self, left, right, top, bottom): self.top = top self.bottom = bottom self.left = left self.right = right @property def horizontal(self): """Return sum of left and right borders.""" return self.left + self.right @property def vertical(self): """Return sum of top and bottom borders.""" return self.top + self.bottom def __str__(self): string = 'left: %s, right: %s, top: %s, bottom %s' return string % (self.left, self.right, self.top, self.bottom) class EventDispatcher(object): """Checks the event queue and dispatches events to correct handlers. EventDispatcher will run in separate thread. The self.__handlers attribute holds all registered EventHnadlers, it has structure as follows: self.__handlers = {win_id: {event_type: handler}} That's why there can be only one handler per window/event_type. """ def __init__(self, display): # What about integration with gobject? # gobject.io_add_watch(root.display, gobject.IO_IN, handle_xevent) self.__display = display self.__root = display.screen().root self.__handlers = {} # {window.id: {handler.type: handler, }, } def run(self): """Perform event queue checking. Every 50ms check event queue for pending events and dispatch them. If there's no registered handlers stop running. """ logging.debug('EventDispatcher started') while self.__handlers: time.sleep(0.05) while self.__display.pending_events(): # Dispatch all pending events if present self.__dispatch(self.__display.next_event()) logging.debug('EventDispatcher stopped') def register(self, window, handler): """Register event handler and return new window's event mask.""" logging.debug('Registering %s (mask=%s, types=%s) for %s' % (handler.__class__.__name__, handler.mask, handler.types, window.id)) started = len(self.__handlers) if not window.id in self.__handlers: self.__handlers[window.id] = {} for type in handler.types: self.__handlers[window.id][type] = handler if not started: t = threading.Thread(target=self.run) t.start() return set([handler.mask for handler in self.__handlers[window.id].values()]) def unregister(self, window, handler=None): """Unregister event handler and return new window's event mask. If handler is None all handlers will be unregistered. """ if not handler and window.id in self.__handlers: logging.debug('Unregistering all handlers for window %s' % (window.id)) self.__handlers[window.id] = {} elif window.id in self.__handlers: logging.debug('Unregistering %s (mask=%s, types=%s) for %s' % (handler.__class__.__name__, handler.mask, handler.types, window.id)) for type in handler.types: if type in self.__handlers[window.id]: del self.__handlers[window.id][type] if not self.__handlers[window.id]: del self.__handlers[window.id] return [] return set([handler.mask for handler in self.__handlers[window.id].values()]) def __dispatch(self, event): """Dispatch raw X event to correct handler.""" if hasattr(event, 'window') and \ event.window.id in self.__handlers: # Try window the event is reported on (if present) handlers = self.__handlers[event.window.id] elif hasattr(event, 'event') and \ event.event.id in self.__handlers: # Try window the event is reported for (if present) handlers = self.__handlers[event.event.id] elif self.__root in self.__handlers: # Try root window handlers = self.__handlers[self.__root] else: logging.error('No handler for this event') return if not event.type in handlers: # Just skip unwanted events' types return handlers[event.type].handle_event(event) class XObject(object): """Abstract base class for classes communicating with X Server. Encapsulates common methods for communication with X Server. """ __DISPLAY = Display() __EVENT_DISPATCHER = EventDispatcher(__DISPLAY) __BAD_ACCESS = error.CatchError(error.BadAccess) # List of recognized key modifiers __KEY_MODIFIERS = {'Alt': X.Mod1Mask, 'Ctrl': X.ControlMask, 'Shift': X.ShiftMask, 'Super': X.Mod4Mask, 'NumLock': X.Mod2Mask, 'CapsLock': X.LockMask} __KEYCODES = {} def __init__(self, win_id=None): """ win_id - id of the window to be created, if no id assume it's Window Manager (root window) """ self.__root = self.__DISPLAY.screen().root if win_id: # Normal window self._win = self.__DISPLAY.create_resource_object('window', win_id) self.id = win_id else: # WindowManager, act as root window self._win = self.__root self.id = self._win.id @classmethod def atom(cls, name): """Return atom with given name.""" return cls.__DISPLAY.intern_atom(name) @classmethod def atom_name(cls, atom): """Return atom's name.""" return cls.__DISPLAY.get_atom_name(atom) def get_property(self, name): """Return property (None if there's no such property).""" atom = self.atom(name) property = self._win.get_full_property(atom, 0) return property def send_event(self, data, type, mask): """Send event from (to?) the root window.""" event = protocol.event.ClientMessage( window=self._win, client_type=type, data=(32, (data))) self.__root.send_event(event, event_mask=mask) def listen(self, event_handler): """Register new event handler and update event mask.""" masks = self.__EVENT_DISPATCHER.register(self, event_handler) self.__set_event_mask(masks) def unlisten(self, event_handler=None): """Unregister event handler(s) and update event mask. If event_handler is None all handlers will be unregistered. """ masks = self.__EVENT_DISPATCHER.unregister(self, event_handler) self.__set_event_mask(masks) def __set_event_mask(self, masks): """Update event mask.""" event_mask = 0 logging.debug('Setting %s masks for window %s' % ([str(e) for e in masks], self.id)) for mask in masks: event_mask = event_mask | mask self._win.change_attributes(event_mask=event_mask) def __grab_key(self, keycode, modifiers): """Grab key.""" self._win.grab_key(keycode, modifiers, 1, X.GrabModeAsync, X.GrabModeAsync, onerror=self.__BAD_ACCESS) self.sync() if self.__BAD_ACCESS.get_error(): logging.error("Can't use %s" % self.keycode2str(modifiers, keycode)) def grab_key(self, modifiers, keycode, numlock, capslock): """Grab key. Grab key alone, with CapsLock on and/or with NumLock on. """ if numlock in [0, 2] and capslock in [0, 2]: self.__grab_key(keycode, modifiers) if numlock in [0, 2] and capslock in [1, 2]: self.__grab_key(keycode, modifiers | X.LockMask) if numlock in [1, 2] and capslock in [0, 2]: self.__grab_key(keycode, modifiers | X.Mod2Mask) if numlock in [1, 2] and capslock in [1, 2]: self.__grab_key(keycode, modifiers | X.LockMask | X.Mod2Mask) def ungrab_key(self, modifiers, keycode, numlock, capslock): """Ungrab key. Ungrab key alone, with CapsLock on and/or with NumLock on. """ if numlock in [0, 2] and capslock in [0, 1]: self._win.ungrab_key(keycode, modifiers) if numlock in [0, 2] and capslock in [1, 2]: self._win.ungrab_key(keycode, modifiers | X.LockMask) if numlock in [1, 2] and capslock in [0, 2]: self._win.ungrab_key(keycode, modifiers | X.Mod2Mask) if numlock in [1, 2] and capslock in [1, 2]: self._win.ungrab_key(keycode, modifiers | X.LockMask | X.Mod2Mask) def draw_rectangle(self, x, y, width, height, line): color = self.__DISPLAY.screen().black_pixel gc = self.__root.create_gc(line_width=line, #join_style=X.JoinRound, foreground=color, function=X.GXinvert, subwindow_mode=X.IncludeInferiors,) self.__root.rectangle(gc, x, y, width, height) def _translate_coords(self, x, y): """Return translated coordinates. Untranslated coordinates are relative to window. Translated coordinates are relative to desktop. """ return self._win.translate_coords(self.__root, x, y) @classmethod def str2modifiers(cls, masks, splitted=False): # TODO: Check this part... not sure why it looks like that... if not splitted: masks = masks.split('-') modifiers = 0 if masks[0]: for mask in masks: if not mask in cls.__KEY_MODIFIERS.keys(): continue modifiers = modifiers | cls.__KEY_MODIFIERS[mask] else: modifiers = X.AnyModifier return modifiers @classmethod def str2keycode(cls, key): keysym = XK.string_to_keysym(key) keycode = cls.__DISPLAY.keysym_to_keycode(keysym) cls.__KEYCODES[keycode] = key return keycode @classmethod def str2modifiers_keycode(cls, code, key=''): """Convert key as string(s) into (modifiers, keycode) pair. There must be both modifier(s) and key persent. If you send both modifier(s) and key in one string, they must be separated using '-'. Modifiers must be separated using '-'. Keys are case insensitive. If you want to use upper case use Shift modifier. Only modifiers defined in __KEY_MODIFIERS are valid. For example: "Ctrl-A", "Super-Alt-x" """ if key: code = '-'.join([code,key]) code = code.split('-') key = code[-1] masks = code[:-1] modifiers = cls.str2modifiers(masks, True) keycode = cls.str2keycode(key) return (modifiers, keycode) @classmethod def keycode2str(cls, modifiers, keycode): """Convert key as (modifiers, keycode) pair into string. Works ONLY for already registered keycodes! """ key = [] for name, code in cls.__KEY_MODIFIERS.items(): if modifiers & code: key.append(name) key.append(cls.__KEYCODES[keycode]) return '-'.join(key) @classmethod def flush(cls): """Flush request queue to X Server.""" cls.__DISPLAY.flush() @classmethod def sync(cls): """Flush request queue to X Server, wait until server processes them.""" cls.__DISPLAY.sync() class Window(XObject): """Window object (X Server client?).""" # List of window types TYPE_DESKTOP = XObject.atom('_NET_WM_WINDOW_TYPE_DESKTOP') TYPE_DOCK = XObject.atom('_NET_WM_WINDOW_TYPE_DOCK') TYPE_TOOLBAR = XObject.atom('_NET_WM_WINDOW_TYPE_TOOLBAR') TYPE_MENU = XObject.atom('_NET_WM_WINDOW_TYPE_MENU') TYPE_UTILITY = XObject.atom('_NET_WM_WINDOW_TYPE_UTILITY') TYPE_SPLASH = XObject.atom('_NET_WM_WINDOW_TYPE_SPLASH') TYPE_DIALOG = XObject.atom('_NET_WM_WINDOW_TYPE_DIALOG') TYPE_NORMAL = XObject.atom('_NET_WM_WINDOW_TYPE_NORMAL') # List of window states STATE_MODAL = XObject.atom('_NET_WM_STATE_MODAL') STATE_STICKY = XObject.atom('_NET_WM_STATE_STICKY') STATE_MAXIMIZED_VERT = XObject.atom('_NET_WM_STATE_MAXIMIZED_VERT') STATE_MAXIMIZED_HORZ = XObject.atom('_NET_WM_STATE_MAXIMIZED_HORZ') STATE_SHADED = XObject.atom('_NET_WM_STATE_SHADED') STATE_SKIP_TASKBAR = XObject.atom('_NET_WM_STATE_SKIP_TASKBAR') STATE_SKIP_PAGER = XObject.atom('_NET_WM_STATE_SKIP_PAGER') STATE_HIDDEN = XObject.atom('_NET_WM_STATE_HIDDEN') STATE_FULLSCREEN = XObject.atom('_NET_WM_STATE_FULLSCREEN') STATE_ABOVE = XObject.atom('_NET_WM_STATE_ABOVE') STATE_BELOW = XObject.atom('_NET_WM_STATE_BELOW') STATE_DEMANDS_ATTENTION = XObject.atom('_NET_WM_STATE_DEMANDS_ATTENTION') # Mode values (for maximize and shade functions) MODE_UNSET = 0 MODE_SET = 1 MODE_TOGGLE = 2 def __init__(self, win_id): XObject.__init__(self, win_id) # Here comes the hacks for WMs strange behaviours.... wm_name = WindowManager().name.lower() if wm_name.startswith('icewm'): wm_name = 'icewm' self.__translate_coords = \ wm_name not in ['compiz', 'fluxbox', 'window maker', ] self.__adjust_geometry = \ wm_name in ['compiz', 'kwin', 'e16', 'icewm', 'blackbox', ] self.__parent_xy = wm_name in ['fluxbox', 'window maker', ] @property def type(self): """Return list of window's type(s).""" type = self.get_property('_NET_WM_WINDOW_TYPE') if not type: return [Window.TYPE_NORMAL] return type.value @property def state(self): """Return list of window's state(s).""" state = self.get_property('_NET_WM_STATE') if not state: return [] return state.value @property def parent_id(self): """Return window's parent id.""" parent = self._win.get_wm_transient_for() if parent: return parent.id else: return None @property def parent(self): """Return window's parent.""" parent_id = self.parent_id if parent_id: return Window(parent_id) else: return None @property def name(self): """Return window's name.""" name = self.get_property('_NET_WM_NAME') if not name: name = self._win.get_full_property(Xatom.WM_NAME, 0) if not name: return '' return name.value @property def class_name(self): """Return window's class name.""" class_name = self._win.get_wm_class() return class_name @property def desktop(self): """Return desktop number the window is in.""" desktop = self.get_property('_NET_WM_DESKTOP') if not desktop: return 0 # returns 0xFFFFFFFF when "show on all desktops" return desktop.value[0] def __borders(self): """Return raw borders info.""" extents = self.get_property('_NET_FRAME_EXTENTS') if extents: return extents.value # Hack for Blackbox, IceWM, Sawfish, Window Maker win = self._win parent = win.query_tree().parent if win.get_geometry().width == parent.get_geometry().width and \ win.get_geometry().height == parent.get_geometry().height: win, parent = parent, parent.query_tree().parent win_geo = win.get_geometry() parent_geo = parent.get_geometry() border_widths = win_geo.border_width + parent_geo.border_width left = win_geo.x + border_widths top = win_geo.y + border_widths right = parent_geo.width - win_geo.width - left + parent_geo.border_width*2 bottom = parent_geo.height - win_geo.height - top + parent_geo.border_width*2 return (left, right, top, bottom) @property def borders(self): """Return window's borders (frames/decorations).""" borders = self.__borders() return Borders(*borders) def __geometry(self): """Return raw geometry info (translated if needed).""" geometry = self._win.get_geometry() if self.__parent_xy: # Hack for Fluxbox, Window Maker parent_geo = self._win.query_tree().parent.get_geometry() geometry.x = parent_geo.x geometry.y = parent_geo.y if self.__translate_coords: # if neeeded translate coords and multiply them by -1 translated = self._translate_coords(geometry.x, geometry.y) return (-translated.x, -translated.y, geometry.width, geometry.height) return (geometry.x, geometry.y, geometry.width, geometry.height) @property def geometry(self): """Return window's geometry. (x, y) coordinates are the top-left corner of the window, relative to the left-top corner of desktop (workarea?). Position and size *includes* window's borders! Position is translated if needed. """ x, y, width, height = self.__geometry() left, right, top, bottom = self.__borders() if self.__adjust_geometry: # Used in Compiz, KWin, E16, IceWM, Blackbox x -= left y -= top return Geometry(x, y, width + left + right, height + top + bottom) def move_resize(self, geometry, on_resize=Gravity(0, 0)): """Move or resize window using provided geometry. Postion and size must include window's borders. """ left, right, top, bottom = self.__borders() x = geometry.x y = geometry.y width = geometry.width - (left + right) height = geometry.height - (top + bottom) geometry_size = (width, height) current = self.__geometry() hints = self._win.get_wm_normal_hints() # This is a fix for WINE, OpenOffice and KeePassX windows if hints and hints.win_gravity == X.StaticGravity: x += left y += top # Reduce size to maximal allowed value if hints and hints.max_width: width = min([width, hints.max_width]) if hints and hints.max_height: height = min([height, hints.max_height]) # Don't try to set size lower then minimal if hints and hints.min_width: width = max([width, hints.min_width]) if hints and hints.min_height: height = max([height, hints.min_height]) # Set correct size if it is incremental, take base in account if hints and hints.width_inc: if hints.base_width: base = hints.base_width else: base = current[2] % hints.width_inc width = ((width - base) / hints.width_inc) * hints.width_inc width += base if hints.min_width and width < hints.min_width: width += hints.width_inc if hints and hints.height_inc: if hints.base_height: base = hints.base_height else: base = current[3] % hints.height_inc height = ((height - base) / hints.height_inc) * hints.height_inc height += base if hints.height_inc and height < hints.min_height: height += hints.height_inc # Adjust position after size change if (width, height) != geometry_size: x = x + (geometry_size[0] - width) * on_resize.x y = y + (geometry_size[1] - height) * on_resize.y self._win.configure(x=x, y=y, width=width, height=height) def activate(self): """Make this window active (unshade, unminimize).""" type = self.atom('_NET_ACTIVE_WINDOW') mask = X.SubstructureRedirectMask data = [0, 0, 0, 0, 0] self.send_event(data, type, mask) # NOTE: Previously used for activating (didn't unshade/unminimize) # Need to test if setting X.Above is needed in various WMs #self._win.set_input_focus(X.RevertToNone, X.CurrentTime) #self._win.configure(stack_mode=X.Above) def maximize(self, mode, vert=STATE_MAXIMIZED_VERT, horz=STATE_MAXIMIZED_HORZ): """Maximize window (both vertically and horizontally).""" data = [mode, horz, vert, 0, 0] self.__change_state(data) def shade(self, mode): """Shade window (if supported by window manager).""" data = [mode, Window.STATE_SHADED, 0, 0, 0] self.__change_state(data) def fullscreen(self, mode): """Make window fullscreen (if supported by window manager).""" data = [mode, Window.STATE_FULLSCREEN, 0, 0, 0] self.__change_state(data) def reset(self): """Unmaximize (horizontally and vertically), unshade, unfullscreen.""" self.fullscreen(self.MODE_UNSET) self.maximize(self.MODE_UNSET) self.shade(self.MODE_UNSET) def sticky(self, mode): """Make window fullscreen (if supported by window manager).""" data = [mode, Window.STATE_STICKY, 0, 0, 0] self.__change_state(data) def close(self): """Close window.""" type = self.atom('_NET_CLOSE_WINDOW') mask = X.SubstructureRedirectMask data = [0, 0, 0, 0, 0] self.send_event(data, type, mask) def __change_state(self, data): """Send _NET_WM_STATE event to the root window.""" type = self.atom('_NET_WM_STATE') mask = X.SubstructureRedirectMask self.send_event(data, type, mask) def blink(self): """For 0.25 second show borderaround window.""" geo = self.geometry self.draw_rectangle(geo.x+10, geo.y+10, geo.width-20, geo.height-20, 20) self.flush() time.sleep(0.25) self.draw_rectangle(geo.x+10, geo.y+10, geo.width-20, geo.height-20, 20) self.flush() def __eq__(self, other): return self.id == other.id def __ne__(self, other): return not self.id == other.id def debug_info(self): """Print full window's info, for debug use only.""" logging.info('ID=%s' % self.id) logging.info('Name=%s' % self.name) logging.info('Class=%s' % [str(e) for e in self.class_name]) #logging.info('Type=%s' % [str(e) for e in self.type]) logging.info('Type=%s' % [self.atom_name(e) for e in self.type]) #logging.info('State=%s' % [str(e) for e in self.state]) logging.info('State=%s' % [self.atom_name(e) for e in self.state]) logging.info('Desktop=%s' % self.desktop) logging.info('Borders=%s' % self.borders) logging.info('Borders_raw=%s' % [str(e) for e in self.__borders()]) logging.info('Geometry=%s' % self.geometry) logging.info('Geometry_raw=%s' % self._win.get_geometry()) logging.info('Parent=%s %s' % (self.parent_id, self.parent)) logging.info('Normal_hints=%s' % self._win.get_wm_normal_hints()) logging.info('Attributes=%s' % self._win.get_attributes()) logging.info('Query_tree=%s' % self._win.query_tree()) class WindowManager(XObject): """Window Manager (or root window in X programming terms). WindowManager's self._win refers to the root window. It is Singleton. """ # Instance of the WindowManager class, make it Singleton. __INSTANCE = None def __new__(cls): if cls.__INSTANCE: return cls.__INSTANCE manager = object.__new__(cls) XObject.__init__(manager) cls.__INSTANCE = manager return manager @property def name(self): """Return window manager's name. '' is returned if window manager doesn't support EWMH. """ win_id = self.get_property('_NET_SUPPORTING_WM_CHECK') if not win_id: return '' win = XObject(win_id.value[0]) name = win.get_property('_NET_WM_NAME') if name: return name.value else: return '' @property def desktops(self): """Return number of desktops.""" number = self.get_property('_NET_NUMBER_OF_DESKTOPS') if not number: return 1 return number.value[0] @property def desktop(self): """Return current desktop number.""" desktop = self.get_property('_NET_CURRENT_DESKTOP') return desktop.value[0] @property def desktop_size(self): """Return size of current desktop.""" geometry = self.get_property('_NET_DESKTOP_GEOMETRY').value return Size(geometry[0], geometry[1]) @property def workarea_geometry(self): """Return geometry of current workarea (desktop without panels).""" workarea = self.get_property('_NET_WORKAREA').value return Geometry(workarea[0], workarea[1], workarea[2], workarea[3]) @property def viewport(self): """Return position of current viewport. If desktop is large it might be divided into several viewports. """ viewport = self.get_property('_NET_DESKTOP_VIEWPORT').value return Position(viewport[0], viewport[1]) def active_window_id(self): """Return only id of active window.""" win_id = self.get_property('_NET_ACTIVE_WINDOW').value[0] return win_id def active_window(self): """Return active window.""" window_id = self.active_window_id() return Window(window_id) def windows_ids(self): """Return list of all windows' ids (with bottom-top stacking order).""" windows_ids = self.get_property('_NET_CLIENT_LIST_STACKING').value return windows_ids def windows(self, filter_method=None, match=''): """Return list of all windows (with top-bottom stacking order).""" # TODO: regexp matching? windows_ids = self.windows_ids() windows = [Window(win_id) for win_id in windows_ids] if filter_method: windows = [window for window in windows if filter_method(window)] if match: windows = self.__name_matcher(windows, match) windows.reverse() return windows def __name_matcher(self, windows, match): match = match.strip().lower() desktop = self.desktop workarea = self.workarea_geometry def mapper(window, points=0): name = window.name.lower().decode('utf-8') if name == match: points += 200 elif match in name: left = name.find(match) right = (name.rfind(match) - len(name) + len(match)) * -1 points += 150 - min(left, right) geometry = window.geometry if points and \ (window.desktop == desktop or \ window.desktop == 0xFFFFFFFF): points += 50 if geometry.x < workarea.x2 and \ geometry.x2 > workarea.x and \ geometry.y < workarea.y2 and \ geometry.y2 > workarea.y: points += 100 return (window, points) windows = map(mapper, windows) windows.sort(key=lambda win: win[1]) windows = [win for win, points in windows if points] return windows def debug_info(self): """Print full windows manager's info, for debug use only.""" logging.info('WindowManager=%s' % self.name) logging.info('Desktops=%s, current=%s' % (self.desktops, self.desktop)) logging.info('Desktop=%s' % self.desktop_size) logging.info('Viewport=%s' % self.viewport) logging.info('Workarea=%s' % self.workarea_geometry) WM = WindowManager() def normal_on_same_filter(window): """Default windows filter. Returns normal, not hidde, not shaded, not fullscreen, not maximized, placed on the same desktop (or sticky), and on the same workarea. """ if not Window.TYPE_NORMAL in window.type: return False state = window.state geometry = window.geometry workarea = WM.workarea_geometry return Window.STATE_HIDDEN not in state and \ Window.STATE_SHADED not in state and \ Window.STATE_FULLSCREEN not in state and \ not (Window.STATE_MAXIMIZED_VERT in state and \ Window.STATE_MAXIMIZED_HORZ in state) and \ (window.desktop == WM.desktop or \ window.desktop == 0xFFFFFFFF) and \ geometry.x < workarea.x2 and \ geometry.x2 > workarea.x and \ geometry.y < workarea.y2 and \ geometry.y2 > workarea.y mago-0.3+bzr20/setup.py0000644000000000000000000000060511517754330014711 0ustar rootroot00000000000000#!/usr/bin/env python import distutils from distutils.core import setup VERSION="0.4" setup(name="mago", version=VERSION, scripts=["bin/mago", "bin/magomatic", ], packages = ['mago', 'mago.mouse', 'mago.noseplugins', 'mago.unity', 'mago.xlib', ], ) mago-0.3+bzr20/tests/0000755000000000000000000000000011515407742014340 5ustar rootroot00000000000000mago-0.3+bzr20/tests/data/0000755000000000000000000000000011515407742015251 5ustar rootroot00000000000000mago-0.3+bzr20/tests/data/button01.png0000644000000000000000000000142511516265061017432 0ustar rootroot00000000000000PNG  IHDRЭsRGB pHYs  tIME ,jpIDAT(ukTQglfwWLB!@@ _( Vڊ/(PD"bJbLM$w{=gF0ϟ; FaXDDtSǎ͐®#}=\#ћ_֝xdyu:T ;`f$"$U͍ImjxpбMaZX&f];^ͯ4x!y012mOB]㕗sHm>3؀6\A4ܔeZqܣ'5LHDolgkؚF̷g7lͧzCs*ٶ?U._ޑS/@߮tKAmc q6+< @`ז?wŃc?ƫ{e@2v~[xV\:LmE 6_о:9~v<|֪Ʃ$"R)+g m :S:0w_7'QQ L{K^)vP%+N&i`ĉ7)Q"E*h%GDB8!k-98 \G kT*eDDMe5a 5)uO z)kC* {ġjqiu/QiN&7~1M""mԞIENDB`mago-0.3+bzr20/tests/data/desktop.png0000644000000000000000000300223311516265061017430 0ustar rootroot00000000000000PNG  IHDR@,csBITOtEXtSoftwaregnome-screenshot> IDATx}w%Eirf66˒X "$sx9R(4 ĕ@!xlD!B"D!B"Do.Ɯ M"Įc',K ѱ:;;&L9&"D!B"D!B>X1@BH1 EAcʊں}f N?ӿVBAE"D!B"DчQ0@nA"D(2>L%+be`,@7 ⏟r:d]]]("rAE"D!B"DaG~; <`\Әd2f7o_{D<_DD14 99@u=do^!9c."x_>SI8?O?5gm۶_+]Tg5:fWkd,m!B"D!B ,ZtԤI}ƍ{ c`lG+?yAB@hF<* 'pL^YadzL"m||7RT}d/jk/㛝Īʊ! wqGtBE5ShA':65o;z"Ça|~!vlmdvqİcF|1=&78"rJi}}ÕW~L?gqwl&89x֕W~+lN۾BZLOw˘pm7?{!U|jw߂#D!B"D!¿Ta哧L~8s]vm}}ֲm۶M2ͥo5Z9c*/vTٜUdu$2w+&~|%/hZ,!GJ7.=px1F8I&Nl޾khE|ͷ&7j;v޸iyg$ g iL#wXnxՌd׃HT_K oއ % XHcf`r$ wMj;кgLjjoVUUI &Mh+?' ␦O'Xm\pgg~冷G[/i,KlY;<bax;߼hڔW1O,?wQG_._(a +38'|?dB {Wp9^I'r^!\<*'$~kWoA1$dI~ݜh E!B"D!B>"`>tT29vXD^UYc͕ :LӴD"1zzZ,b1KͧWͲ?}zu;zeL|g=!OFDx֤I(G,\ֱ z|O<[IM^UQow/mnܼe5|WN=X4.p{yW\Ǧ$=yǣO#V/|gբ_/T :f @ٶut"x}W5^j`qW]{߿6- mOx}9PTD( _A+UUUW\zJ{۟ 1%疂fz7}:Vbo"|iS&nٺG6co\k5%D. 1J͚5;:_!;Z';?p֗z}[:tȐ}={c<ٰںNJ >tڥ^a16{_?g*Jک<Ѝ Y=e`b$T֌01:+B"D!B}2L<_fu.mlk׮-ɓ&oذCysٛvcē2/#B_Wt=1# ˦ GT'0sx<3|ǹ}mD䌙$9ap:GWr]׾3kԚt_/@A,);gEuVİZ6n~}EΝ3ے-D`^yij9bwb/8 wo\|J˗{oto #xUV:ah2ﮯ}gu=CV͟3}OcN\`h5Hy̏50 β6jkؙSc/}-8_~|gLuێ_ .|wiU?Gߜ5ca˂ޣ41Xw3t0ywN/ G H! 3K9fXGLR\vE#G-Z_zQ8)Z+>k'g-9NWhg\qC!7/Zu~tUw~kGyUַ po0RHoy[n|-36u g~|л?=w[݂nV"D!B"D1mmm7mB*+[63K6mzv…=7lx`Ǝ;z{{:qrڑ&`9o}Dn͒_s_;&خWpHc~yT9_'ҹ9p%ϼbfM2q-gbX?߽l\7ak6Wa7΃z~᷎h@ N? @Oq4א/׮.;1Ӻc/ruZG8IqaOL8h}AY6UwrMxS73y`L0ءw~>o/__qWY^61Xpءۺ=\779;2S~|3x_]rn}FUE{΢$yk{G.^lv*cţٮ4{G22|/w>6ثo? s+}O ,Ό7 ] Q״l6w׽;wa/}pqGf 7m4u44c~@&?pg~/ېD0 9!沅o=ڜO:뒍-n3>$wXbUtǟ𘹟<е7vvTU4vx1 ܾ's?rgsϿ?#D!B"D!1fFwwWccc6I$1]OGuY3gYv7L<%6,_( ںx<sA./rB7]{mkR\$ۓٟLoj,((='M#"`kO4 爤"9/W]s{ ųkt͵>hNxMtk= !߳':~3O>ܣuÏ>ga>#0h5+okKeh56c-<ݲWg`6 !O-ӿOܰjA߯^S 9g'49?/YLfw2܌/ X佮|]6k g?oEnB}&rǴWǛo5W7{.~̧_bO\zgv}Sy 8me퉻| 8on_f},s ֙Ì ^n&8|U !N$<̒nG@| Fq9N8B:=>vS0$&42|慊PlFȬ~3ГN@uU"syiG,kGz얫~cFۯVС>CE*s4sSq%wџy [4[/$+zޗܼ,2C3{no/SzZ]L |g̟9 wDZkE_=oOo&SJ]~s55U_qop2aqJjew$!6~Δa1t.j0G Iڗvz0<ݺĈJҩܶ2_mmu1B'jOt݊G!2`$1B M7{a|Lx\.y/~oG_3z$q5l9b|k:7֜yX|ǟU,8K7<HW06uo[wl&Y  ĵq㏮{w;'8u4nyneBQ:>_߱z;ϞqZb-={ڥ xK|ATRjMT[4˶Z|TbBï@,-[1\__Bk ykŚ3x‘ 4 c`՚wTX[<Ѓg!C@OϾcmS?M2޾d?KX3XJK$9~zy>cgL#RR3$O @14'& l`0}7qg.[Nh;tڿ>D!B"D!B10 #J}<+ 2i$pGXfȂH= }=ߟ \K\A- N [ap/c^u'>bF,>&ͽl";`v`lx+yw }zɋg}#8yء1T*i, O+TYys㜓g_͟Rm|*HL>gv<- "huoܨ <{/VvHk7{; a\ySGѴ/[ عo\arcB<WtX'/>._zt]/Wm L:ӧi&rs@ ^l󵧷|_~=68xgľ[/^zM*%ߺ(?%u䜧)qv)YJKh}ۿ;/^=;X #j;/:%rS>f0G$~!!a̔ BƎm>sw2/ 6|ժ۶m@!Vtoss޽{X"D!B"Dęg}G`zҝk3SO=u}wiT|괏xQR'~=>Ш~WΞ?w?2;CvZ1?oX}mrd >~0foά|bBSKgwjCO8Z״%zdthv`Y;[v)TjybW^Yb 7~%E|@qE!B"D!B^v',"^;;;? /=O=xO#=Ǟ #c;JJ50 Ɨ<2 u?aP"vǽ~Xt B`v؉DW]wӧ2soW}X߈oֻ.:2YH%0>-C4&-:uE.[n(>߯'`Gty0!B"D!B45b;2( [ndAvƩ'1G{G<)J53kw닯aF?Y* sÇ 'M￷q_t{D3!Ia?ZZ>]{'cr3+$g<İa;or"D!B"D! X}ṡ MN?Oru_0\f6wꋖSp\e Ba@ QE2+ *5tI(Ao/*?wM, ɩgDNAa +@V0ʠ&VPɈKZ %BD \YkJ0۹1NY&iPOH(B^)UK`6%a,)S eVt1Rzq";BnkB9x[,88H@Mi꠼A})Pp xYhDbWd{Jھw|b@8<-ȗЍfZAHm!Q!eMZO3<{~'!Ùo Bw|z:IpR'<;9uŨS'X&98E2|a - AZZ]q'8+܉^q^z!TԔU>xSΦA P HEDJi&X ^A%6wydd.,:ZK$G(K+ fךs-Zh9A+b%P- #(LhIMl SblxJ],@lE mnQ(5PfRBXr.WA#dW.ށX5Uـ>La*ITћbXaIe(۠n:eAѡ )LI4CˍuAq!koko\ IUtZ 22Л-9JI9!$a ~AIxn(W:Ýz''BOo[ė+ d($HISlC@R.(@BFZ 4Չc+lCs0@k]@0SQ:K˲R<]2 #nǤD;Px ע75; 7#X~%Hz0="*vtI&,RLZC$R蕘#zW.@ooj!GySO<7L)pDB)7cX&a|˂'ܟڐPϊ$L}GJ3JH\k1h%84s c9S![B' )| 'bARB r5)F^A+f!wuO;(?'zbϖkꠀ #;Q$!BHK*@Cb"EY%mrbc)lsBpt|HG9|E1w,-,2:^Iቅdm.K~!4~:W$@υKFXHQ8ƫT5ݵz'Oy w?= ! x(EiYC hxu!:S/BTj1t3A >ؔ*aIJRԹsCಣUBnax?I1>\>dM,) iohұx܂W'.Cǿ'+=< ]1 W_!B7H&x<|>f{{U!,h@=CGP 쓌4`~"! Zv%%Eao%q2:7yʎH~5 ]A1HJЃ\l{,+vsz?cꙢг~ph0X6{Xm=}nB麮4?Mũũ@uj::4B))"ghY@Y!oƪx!ό+c(0 ( g1~lC+}b{[),R- q$ϓAen]4.77Q~]d6W}2QOhˍ5_,+T͗b `h~ ` "3B<ZVS@Mҥܫj#dfQppMELtR`Ɩ$R\,zf,e$ t$إM酸(:SR E&R(w+{{rǰ<1h[ټ\ ?"Rq~NDgVr z" rSXPj>!ۡ$hv`seq=x}tS*v9>Ѕ:R9w_Y9rg$D0\aÆqV"O$Uv0 B,&=? M =Q?HeK:0bXZ +晞IiZ 0j.\e)(!#tk9De;ť{ht[K{O ‘ڥ0W<"\a/Mƫ@8Dj t#b0^¹EEAj 85qu%vqzL:SUO2op(ΐ j4N"&7&?1=25w0(9b ŒDD@@9rfp8m czڤCVLoȩ<]'䴬=1 XǓrv/8!9<%@Bw]Le?k{wpʚmfM- > #r-Y /J*Lc *n@Rg)gbE_XVQ%q^zxL ??<%_qwP("(0J(^z^$ ~2r=˸Y@/P;hXrA~+vѮ.{ː5!pֲlr3)=zu.4ؗY?iC02/vIh*ңPD&ܹTwg)n)S)pO1th9DYO ACA| t&V'i Qq׃pG/ܬQ#B,x|Ԩ;w2 1U%wXoO&oxB!7 @QІ=fg^oW>>r S_ ד-8ƑFx"2F__DuF}|hꅼN8UU4bw*j. Yu=+;U1"ƫ+uJ ټQT%K2c!!HsЈ_+ӌ lyRtZK%]z7"c<38jbFD乜a0D ZLKĴNGٓGǑi,ՠl_ASUa;GN̽Pm豜EůՅb -cFÄ|LPX8<bb$^ o'+IW-I3$G^pE<>~j[ CB;MQ^쎠JdC3L#PJ4pF(EDpB 8+4 ׈3j9"͊s+Ƙyd;g kT=ݗ1+{'m( "+;WrҲ+@$g2y!*KF]3_R=Q8~R0zLM,ids G*?AK'},-V??waĪ:4dbf )a!*-U>>b-3IY 2 TO>@-@8]d3o:wfY+ V\~ZΟ8\ގl~M vu+Loƾ /BqJZӆ#5w[ۓ%c+ ~y9@9`u j\d@ꝉ͖ i)-7;_ U/Z Q<R#8C"hVR1o=- K !ʍs]AT "GBsN)A34 1cX@(!3#r!EN#Pw2fm^f2fm2 ιԲhs[Z5q05|aF6GeLT__"QpYSma=2ARg(/닂@[wi ꋒKH\rVFe$=N tL(;'cvy^UXDqZ+HXAA-vAHs;A*=*lVBXU / B@BqcnJm~S [|TC6Sn<A׭dy>s>d~!$󒷂3V.4kP,]iY&jjGu1G;+F2hZnK74|Y5qѺjli٠Au[khcڥ;XE7 [o-ݞ5&On}羂tO#'uhbֲdcg6&IGO)% fڼiu@m͊}zDä yUO7iP o"GN +X@ ۟gRoPhV'5ˆLyO!BE.T|Mh} r{,MQko=/7\iWHlB(Ћ1, 94P1z@@Dڧ{0a0`>bs&nM-|KKTjUW87)NcO.r)z>HwcX.׫ވ@&EJԠ(1,50[Yk?DR;\;*9];\ rK>H =,%:p}? du Pl .,næ 3tQ uA"4˘ӧ⅓%ȁznI$o{s6(eP_<QtK% #sktr/HC\(M=&=ҢK.h ueiOE?6<]ǹ3x|Y:ݻkѣGڽR|Pq|i 7~C)PoݼwjC㈦aqoI"a&ղvg~Y8vVǦ]C"BxEڙ=ld Is @)I2(%ZU[ݭ6nhTm:!D5=Fܻ>5 7;V6#t8Ljk]Lh;uҏ՚eq4m̬ y}1V;^X qjFw.BFa2pU{YnT/j,&{9%՜Sͪ$<--;]H}H9y)!GW`059a4sDJ)9#TBXKB;en2 ('3 ~W< \1HPAM# pǹճ!~2q%2%k $M+w1 Q%3Uû%2%kxl cxR:!-ZAy6"q;&z7L=,|j, 8 l}+@1b&T Je#u\tѼMF B_un0q usWZM266lFZ v&o'1X3Z!h\"BiРT:!SH´(wb , rcoMg:o'RD"a;^TWUmhy< !\.T̴]'M24շmF&Wڲ8r܌Qv%ص7ΐpT+!l[ g6~VӮ1%ÞnZ_5n;8X*&UzDWTXR`v(PiT#hF-!+;b!Tƍ}<8}9.7[ <H5K煒X_AuR㽅DMmq=-o,y̌OhDӅC ۽jO>.+n/c m_vAml2_rTI`uEmgXg8X決$ !W`U\HT{~/19DS Iz[{?4Ȗ#do ZGy,iC ȇSNbrQS 4MN)5şB4dw_Ϸn"u" NhnBq̉^fh08/Ts{sЅڌ=#2$_B@!;De'& $+I,~s2[F\nl8}愠FAuuw4 k AxlS3'Ec-W67ĨFDid߉8<|<~+B Lo !:!.=0 ,P9&YI[M(@q9`%z.:ESr_,!%.u\_Je(l9_ T MR&i'ɓ&ePJ{z*F~!>Ȍ 9xMЂQi͛zGNHoۚMsB躉B,W9su3M$Ah?p(i_-NzaM_1j#gLō˞؀B 2 <TO7e߲Kbhr R0דPQ;fxv\X̃hcnqD5duJٺWw|㘆6WGSsC;|E] @P<3^0I^h]ҳhrzMlf{qlBKI=~rݗet7 `뷫YS1P*(8ex [ J?AbQK*E=Coc(Hԇń>q^R@$cӹ8a gBi\sNOf℮e4Kr۩ɪ̦v~2 O}j;W]W֓" "u |Io~soNR/<vb_u ș5ZNΕBit0߳1?Sp$ F\,0o޼0rλcdz]{x4D$ž6a5 :۞+̘疿i|⾈KtXPeR/-(J΅w:\F.nBl.eD.xKR?<ԋ겒 dsYK;8i^ly}dǾN{Ŀ)FO·+ 0:[+z @n#S;BՈgeIi#\QvEe[] ble I/ 4ؠ!;~ Ilz֑y+I3B6Ѿ}=uusSd*Uқ Z&);ֺZW-]NFN@gikM}W%qB߻6ooU#hU F aFIK_L6~xc*U `dQA޲Zx@1 ~)߻ݶ9V$J ,!fe#:o_zkTe[ҩE E4^0mjBz 7iscج cB3G4#]k^[T_MVnHkz9ϽmlZRvҌ #TVeCb 2d aZ<&/|99TRRLF.P\t(exMҥ+-Fȝ\MRTg ÍqR /.)2`L Ce\܂9R(;ԟЖd<[:Zu/]xaM WF_QMm{20ƶmԷ{KzːϠ&S۱b n1f<--)? 1?Av+ .{}ϿV*ܚ i<ﱝ?<ۻ.`ΘM"Z+cH*Tm$h5HZsF;Ub`ũ bUo*%#UrqF C am D-]#'P!.AK0OIෙa<3)N埥AOޠ3WB!f0p0 ̙N;C覭h&͈ey=[ F /33i˺[B]WZfH9i?Q@.-K H塆uG}ë.^soqDNI6r(3Kɂ)u=݃!*a˩-dM+Wv -ZĉExhK2uSj! ; A#9L5bؐdTWgfּůu{u] {vÆ: ˾q}h0Mcwj?ꤥ#VK"ca=l/Z_ަSCqd>Mfͱ# &dMɫ(Rԣ1`sd b!-WM5TZuEy'1d8Jڎ i@UU%QͫUUU03UU`ϑɩzH'))tE~fq[sٹ6v)@fJ4Gv3nrB> !A7Z2IwX,q2x0 ZEbL娏F+7V/%-F*ioBH)|viaٳhVgXc;K]@,LXl #[JPPoN'yg!+XV?Bo VQLCCeSӾ<9ؔz@^@ -S Irې4_c@S^:dc;꿜N֝J e,Zl;mjX {eثmށ1$ai-mR2 u0v䚤m[ ޯ@+NvxiZsReVd5}ڢ RCh(nq,T1ɇZst r O!5 !٦[Ƒi<9R+* ~WL*VG)Ҳ06(L( URʵk6M4b:|RMi5>XA/30l^yQ+Q<氀Jv̙ߋ^֘>,N+U6j,Ѧ#GLZ1A2y$l!$V>'DʱIuwWHˀ~ *+ !y)v T#^d{dk6E׽H}=7?gq{ǢA,ALA ȈhOOdZ ESn#׭LT1ť/l*Y"-O]zuBp},BESeZ3K{ES6^qTtf![7(DM@Dr48x&'B.//͝Ы?_^X>_A՟bo̕1jB@ Q~<8@j3bi)JT}L&Ǩ*19[3oS}ˎQsSpӚ| dymUHSNEjq%C<^֤H690Emu#J@ +$iДilgɪʷ-bnRȾ/{~! sVdp%d^lN)w-ݹW&N=)M38-_b$5 4l3kP<t#Ñr>Ѽ#6N–8Jz'|i6|`y;'6QDHEV Rp>oӈux)1l3c51,*zвiWg1oh􂈔``e`\eJ cE~tQ͙ qAEhg )׍sσ^BfSL@Dbtxå.rjRUbب2$7R(@i]Ylg1y5FΆ qi_L@f&܆HBZdPb:DxX[7@NԞ>}JWE 6=[~ojĝ??"8FVcHٖIщKVf3)?@6z q$t`g.}d:kj6y<Qw,rSQ./ IDATd:1Z9fffN>=;H 9w aBk*dK®`tG–6DԀڲzo:یDΣіo; }6>&^"M E&ئἅn@c0\}aaIovc"`!+N]Ddw'il `e`1.mJ*/) 91%10io}#gQOYJЗ%.ߪ*n5HneC H i[EK2 KO9|e3܃s 焴1*_7"F {mcf{B]PaF|0޽G}a)ӧ=dZ]ujl0 SW6^ԕ^u{Il:41Gx)-"-(b{鉯yf;,vO CZLw働Rh1J'J6l0 M#!I"@;qDRLSZ%JBZVtٮS LL"/ ߈B dgwE>0hu ;Ċ)oAѼ̫}ڛDKޫV SA!%ĸ9Yb*[9w$gt_%̌=vݮи&i+AίcZd$!ۃ *-a`5Wv2e׈<0e ty0% C^hڄ 8CMȐQ^,ѨHw3yVh:"*Rf[-K:<̨ENuAKQ&!!M}-?ZkӺ<Ѱ*%tU+OV=ŲJXIYP蜥xˋu-h(m.a1 j(K e;;$ԛ K =5 sZ悾`_+_Oqv"MC[?@TjId`UU~+  !w HaW@$RFP#%IH-P?#l/JT&]z "Nڮ j$PEn2Z9c:`*cb^la"ԇ꺞Zfg-DT2H,ڮsܱ]bN"pQ}ÏI! aq9\*̓%k<:e َpEzv^-ve= h$tZ<24? "`Ev0 a~'ӛØիJ^%cQ85UYnAP TA J~ڶ\M')ᾄߨ󞺕)?c@{x1NF>ץJh[2ݣ&;cSq!$HIUT&l9[~vJ0BS,EWؘqnr3QVkL ?tZTU!"hu6uNnQXj ,B/0.)`[~<} NLND똇 HֽJNN.y&56>ﲪׯ~ի{U]XۢD*$ҥID4D !d3$)@4 h9h:.J|>R3a3l'aY&xi4.\!^5/}+]s `q?xrÕ͙lm0Z6{g\_P"FAm |A ^FF}`wFUŅl! A 0Xl QACi*bk `_N{]1q @N{QO+ٽ,-HC+̝2 mFN)UD9%*4%NER}"mҼ %D0bkT rX)VtF.`~ztXpQI:2 b_J)`C񪥛pҷe~0GhզmFg #@5Yh!1)#EEٽؘ :G&%)o3iE_ )qDB\hBzciR5de>F-yW [7>›ľa=ԈYS29SV;WYW*.l 3䘂 AC#LZvU=%+_cF.C\dUFf3T ~a ʊ cSB#LUr{/%-ANEnL_WmĊ'ie8JdD~6%M%Wcq%A !^^-,d5 K/Jj ҋI:-RR-Α]]lїhn 5-rA*<L5 W&j2DO^-Q% 29,X`?D"!e$ **ՕGv+H*%H) )I' 7L=RRӀ$DH "R @A:60|{ѵZ-x3:c{=L04,Գz_E7'vt,!9?k̽t{+c Bav[V Mk*ܞf2c-{ \873QbK1۸o8.ߎ(tWԜU3hX!|<7d$d:J<Ыtk&C$H#r "ms j8fhŀn8Ddne0ڟ#S^Gn:nG36ڑM5,WG^eusջVj {[H̨pVn:h<~$wy򳓽ļIJWzۻS]AX`#m4Ow>[@;ٽgb^?zϜ9BQDę=w_zkgf}GWJW#nu ͐v<"?#b `i $9=1wԺvMp1rs &t*EUF R+Ro-$D@w IHw?S\uC$QJAIـ$$I4*Uս4(l!-Ӗj`o]z{LoS""SǞt9{ϻ_sMm%SC2xCgjx؀2M#(ͮy8^"S f3 [^_~*]p?v(x LWo|t4cEh_Xy(Z:oe9,u~|/Y`g$1{%9,8Xd5@Jfk6ʼ^B^[?'AQfN!zO;,. .3I#8*̐J.:b Htl~?"J/茛31v|h(,G6Q"uJAoŋ|{&8a%؋mS{TZSAK&,D6C?kClU6SG4Ms}]]wVl9[J 9sG@;+NDw*SwKo6Ƈ tg-X%vfDx`HHTaE ڬ +}@@I̒@RHF 5׽wDDH" $1@")lEe]P ½pɝnx.Eqo{KWp#.^~I]<ɣlI?Wx*'(0)")0$ "@ v)RY! _JY>2ŋ06$5O-۸Dc ?L")=ji:e.dCPCQn %@EHd?.p.^dZ#d"IRY1hJ8yDTAvb {HSNclHd@BQ(TQS*8Ef]Vh֙A о.Xj\IHY!J) ꪫ^ZZK^3罄V>*3^v}O\tu]@3>ȣRʋ/j*&^&''׭[{߽\s a+BۊSN"CWMr[P jtpښd/f03D4,K#"܊{CaF­Jd:G -SCN(ڈGL/ꝵlZtgثQ u֕Z˕$Hf$RQ$%$ߪ=JH$K/ԟ}[NmڊEBRVpc!6|b.9r׮׽"!O|lׂ;ڳͻNOlzzVFBCL+h nE[<+!e`bZ GzT`'z^8d•'eˍ*+co|^,quK `r;qTV ct:`gToe~vzN/hc~FSmkm2QmOY㽉K_-wH)tZyqvxb03]xr.џ f)15Bl/(2'52v(_өVHO9$zZcW:[N̝JJy੧Ep}9@D)e=[HBgyyܳwB*Qxx:Fp3)f`0!B:pv`q3")zh t^M?T6H+IR Z $۶m{kg@ C A 4CZ /;nVuɻT7'4؈˥3g?XJ/+bVHK' dU1QQ&#,X$,U'\LXy0ҨKg ğgi(^EpףM2I#"Pb&x3fL#_i!_$EN>$UC>N6^yόJrz<' "Ip% ,6$GY12šws k*iKz cHift@C!oت9v,vvJ4%jHڡ6@rZ: U*fDj0mlߟ+̢wԧJh3^1 NȎ^2ɕ^xCo|*EYN`c1u5dK.e@H)I=C~lՂ$CH7" B`LRaÆw}2$I'kvk጗Ճ^Lb#" a ,ID#\޼GIt6%Mx"QDbexw-\TWm \CvfiOc;fG'hvƻRm.hTaQEbyPY@CK֜$̸Y7y",|v g :1Йb] xyY";A%n()NSD㺒MTD?w뚴~떫E*@wO-y \KsSb_Av^!D;NIt. l6tb ]Nx 3MfTvֵ̰9R"ۀL尴Vr Ef 2Ocdx).ΉUmH@X.՝TԶVvXQM )ͼ3t^#Baj靋<_Sf®le^6G" Xz։S$B.ۦq(2?%z6t4%':岓f^;yZ<}.$v{N#X8e1\0Q[M +Ypy-UIQ! 3W\Diwϗ <:~ ouTTG JYM@!9ТPKE֋ g`NYjaW@H!ayg0)mW/J`s|sx}^w:З>W,FgEW/rAWȜHeKu]ۄi"-߾j}ծ1m;N?ѭ^s B4kGmOth״Y[΍:/"Vxp^TY5dP/DŽ#v 筱_B/B,rKZGD(GGyǒjci cI>ˑ@H2p5ߌEg=+:--H(T$А uL@$$JBk@֓^͢-jfzz]|x .f7$丐  Y0<KMp(F0R IODn?Y兣&0#zSi%BH]Um@3Vij [iX2ihH5*#txm4.$L.Q$OR TG頁4.{m&BXkI|FUz%VG*:]51 lq, %=c5->0 4Vʍ5&i֔DEI\Q\~ +^%e_&J$)&vA yJK~k8х?q>[Y#܉S򙥆:wW}3_ȗ$Rpji鉿Z=hg 0Ty+!(yqQTŮh{;-}yW]?8~ [}/hNalyĨ'uQ,(pRc%6%Cmo#etln[:^o/ % ̡1ghdsoQi:bF%Z( 16y$u@1ۣ4C,J)!*44l64D$AJ )AJD!?O~>IsJq4(Rb5呙HdhZhԔ+zN:Ω DHP!% 7kQ :e4G@^"Qb&ۅE !,|Lk٬S[AB',`j_d|'3"nzo$T|ZxR~L(Q%kpf:&] |^`jڈS_:jCB=ҩ"8]>6hޮnDԞr8lLkvf{wU^Yס1˜C1}'#$'yH,*yms1&.f@ ̐;7jͫ#C<,#ikFÿp0y\u5w$K:檪Z1XpպJ,Αh%TB}9SHRSW[_ %,>p7uz|x/>xuZ>W렽~ޥo-x7? (]vh-Ttÿ>+_8sG?#ȦC߷8Q S._y/7\2\ 52v =.2YMnv3[#'/wnǿ셯{ɧ~?Fsf_zwzO 6\o}yHT57(UeO%@?]TfMdAmt ;_'\C7faX0ءnې&b٧Z$a %TM$ ) ֱƗ ?GؾqL.k*2&F} L%5pT(p9PICGCX^>zPN-SX!|4; +P9,i(u> I ̛bwH)zow}3(O/h!I1u'@2o`f4NSbե0!ae_!@ 'u$A-JxhpPAK+!T!_D'O` F%RFm\5cjot߲%J*؋jOӌA4+=FҲMAzFgt9Q"3.ENc)b<`c͔Zό[kfi2VXK.יjss:bJEe~`#O')tv}D1qsq(eOtU%`r]9}+\%=@5m!;v݉n%˼WLw# LG#Q| Ơ2Xed^E* 6׍XZz7qc`ߞsވSRÍkg }z^v^I e5yZzG'{ͦ幥moݛ/uަto0$pME$jv7_O_z ~]>q uQ;Ű-"}oqӦM`޾yJ:{.{6g^H^q&o ^|䑿_|[N.U+8Z 3W:ͫY GN:` ,S q_(IRXL :m>6 z~O#z甝6ue<Ǔq|~Fg[7 ZOM}!2#,+2323aK,MH~0.$+)HPi?/M郼D P!c#+`z>G'Ֆx7k`[ #s)啝5+aNZTtZ,GeGj% pL.٥dPa+[5A`RȷL5D7Yo\i*_V[oloi3j:1R xJ؁+ɔnrX (Y4G=$u$Kygdޚ$V/UJf: /өJ|7WG~ZD[)a,14N6!>k>rPIlmaWBcC˔CaCTWX e$6YWc`CE$F#p"/!24|SfÁ(?ED0'{D,zIY:7$Ir)zP_7sOL>EןmAjhb& JR{Ԋ\9UQhyƛJ\K @DH~6Q՘VI?$ECg½\&3Muﺈ\p"E--Hf N}5 P5s78}ú{Gf6b8wH%R9gzg]W$Xs>puˠ~bʅ^xСG_~nnn{&RJZ8ȥWݰZ|SີEyRjէeATj){aʹUZ&m"j#9?L :f&asP1c%9LT6gEm"(j&'fFMFJ; }kBeCL,3ep{mTU(v{`|A&+48H柱E/yXKQJ-׌!.nzۗP\IW pE55p2p8h!״ɗP Rȥ IDSS![wKJrHyIQ*;RqQ)H/ݽRQ)$jm pTG{ɭE `%r[.e'IJcx cдD@&;{֔cO X؟8Տ~7eKMu߾O)/7q .:?Oko~ ~~OW[jBK5[>?.^wl""y//x`釾 /o ?x9v6Ңo߾/}KGzSQo#-ƵKRʩs?/YO|jؿ%<G֜oW~G߱ )>OBY.xWɃـkD1\$ŏ^^`QH%G|a@Ȇv[8L2*cycO2#ɾ8༜;d@(2CuhJɸBF?um dN>uUJH Q3F#RtJD %Vz-+Հ9 o-_"}|'2rwRQ멻=э#l&g&G[6ԝPVRk\B+s?;DkF*?>"JoN~eBͦ;< :wcdd''}z ^VV\ ljaU*0[x(%Uya_}]ozc7.z{/b`~/H7ɕ087N\k~ - ų(Q+_ʯ}kzիIx[^!V^,HL]vp8oYDM\"uQ¨o+B,Hl3 IDATS\Dդ2M̊/V~o&s&ߵaa'2 N}aM] Q;>{O m7?wM ֭[w7NNNfO"G9s^/,,('Dmua0l0䭆%+ה{膥QC2By43gɑclw*rNJ;RB|RQ\?&0 Ζvh+UT|qݘ-rfZ'QfrXhjZ'X"FcbS^@%[:]{Q[¸*.kޙH G U1@Ei~,cGX5feTbyU,%2>q m|*]o۽+IUntQwoF}C:HJ8W g*3l@;9eэD[ S)`>Ly5^5K>FfM( u~7;Ԑ {<񞥩:NI]o]~R{ҍƹE2$ZȂ9 [c5[t6TjgDvhM0gxkІiaɉ\y9WX}G0/b^㫑NM-;@!M ;?]YFbL†5PVBr"Ჷ25%d`wA. L9X?Q+"BP/$"0 kym6oٱsE]xW.$Խw2XԖ31`~ ZꮗGWFy ӁPdܻ^y*Z~&#?*wp#:oQ"SݣrpffC+*J?ը%Jatd{R0G%#Uȧם'ϙ^)_d :ɀbiT8%e$VG0q[Fh)I`KrIyy:ZgoFܧ@Z´Q㍣ s$)M'rs"My!<DxIpRpm}ti^H=tfʓ++,O"x/B~w;^25}mE80~3#»{r$R- o:S3/cII륐{!+LdQRRJ#Dd3H=fLM)R=J[g(BL_(,oɊ֌4r7+]pʗؒNٸu^RY:w':/dLWiޣ``*"ݯE`uPN}n~?*His" m**0JyeU~O!"wӺ2cS8jotSXs|_xd.Ip zZpR,lA4GhRCı W0Zyek8TOaWf R?;D@ %9,"@D#w|駞Zaw\]( H%Є1'gQ .)!źQ+$8%cD"4Kipq=ȟҤGU7*mt^ʰefH?ًY%5PNduaR+) ʯHu$?%)\0 !j~FcɈPEuJY1DU:.3."V ܃0hv-պ^eOۥHu>zCk |QÊJw&լº('?տk֬4\/ʻ&>k N0G]#m!+rSP]T6aÆ[oc$ 6lgxT>6bNFEcA6A.R*M#Z(\^ ~tU N Y۞]ھ[+WtZ01B\if*x ӋOK+/<b{mm!7eXWFd@?âmY'5ۥ3EM#{̓w_ YM`=#wgr;w/WO:u 'A BUIwF#IJA ]bb( >S+QbP:^&VzPL۴+)tf7]sΙ}]--zݥ6#<'-EɲiZ˨dspXt*GJf\Q6!΍jbfg[fSP7WQ yK{FEHdC16ӢźQ"B2Ʀ6d WF_Sh q;3u1JJصh2Fڗ#GFFvjQgsXyi@$lҩi7l9аZ^1uAИy/CN`J6RC@5E?A<Xq‚7 VWϖ+VT!"q!{ºvhgv!:MKcT+{bff |H#"|3m6=e2)ES^nJ#*]I FFsxhYnaw) sFH*k<_[%2aDڼnobv#TQ>TrI-/uarS7Lɋ1%J/o}hmnpB4y*?z퍇 ,lsCǎXXXشiӹ.xĹ{UH깏 DH|sk+de11Uo^Wcަ};=tXR@Qք>F;JnpMUVF_MT{ۮ ZSEVl7˺Ԓ>z4 !BL:}=.QT.Cw}jd&xH \{;ȃ X=ҽ3{Ի0Mv'1c#iK4Dk뭻OIDKf}#ϣ9B0:1HM8@>blnԨOb \R4{9Z2m_aօ.Z[(4Z43J@ȼxo7oNO= _:]ɐy(|w l.B?tbX* %/xNS寿V׽ {& S*?>j^F)">kuȱ.ɨe~a[L(`'?,@piIUauٳGWDrnĦڿݻ=|͛7+[YUwO z{m2=zl=RʪҟrXlWBk +GH# AziMǑ_kQ["˓9;NP_sr&drq'&*{p\~ZlAgZ.Ψh5h҂:wМ)IQN"[I;Ac+<b Xoy+=9eBID'&&$($MYoNmf \ ]߽ory۸޳e/?sӧ/~ 6m̉R˿bSd@gU'¿?|E-_|{^rؽ*%2_ɏvlWsy!5.m4'5[{s^7PIk^2 m>#yEm,TdH?o{Z^i"^d&Կ?zӯ_<8iۦO}#|AgԎh4[{jԀ6'Z_*=cэR{* 5iPҩpZ`iT%mXc>ճeފ2߃Khg%sN3r i$Hm\}|-k i)l9z uB-;|߾տfg&љ |1 Jvl@v*ONF(–&˱gyOMJl&س{<Ȯ]~Rgϖ_M6jiipLLLf~ ?~M6z=d=W/ƞ8q.LT{h/=TQfEt kl*ZԮW㓊#|0oD[Ȅ?6f**}ęAa&  >sA=i+9՝݌ZbhUHdY ,U,Wp#kI_NL˥O8xW/-MNN͢SSGA+׸g,io(Y(LA}?^Y̔r/H*/B3R/G! [ߦqu_v*<!1\bada?Rɘ/É_Z5~W_}ud2U)H)̮VU4y + ȡRzjOc\]]^{YO?f?Brرcnj̰VVUz!}њ5k;(M:&61}w o?:Cŕ~RCɲCcR?!N_r7tz*{O(7׺Q9,#JUXq4ˇy 3 wFW,  3eMlH Md#T@YZ,دX,.|ߘI& ^Du H*'2--gjwPJ&t0풯߱s09uAzɃޱM^9ncFLl 3O͖ny԰jC9O3XvWs?fӣθ7'1nuoXcQb;_|.W~1?6=ii]}_u;7?reoMnii1> ڀޞ 7k؞oO_3^W߽v>=ܻb {G\tȓoO]7vfk"LHqAĤ!عݥ̤Y3vtuo{K"l$1o^rWd~_Rk- ϜYr~?>_p?-ɢ{#Î?fO>%.O7%_ֽlܛu?~:|E~oe3۽1u]}Џr}k- Ɏ=#W&^x5q&81A.ZhƘ&d3 HRa!gqAPp3$-$Ynꏘ_fvvT2/'lL*0C"E FE)k$!})8N9ѲN)Q*7TVE\ z7:˓\HśmSN}ѣiɲ6T]SH)M[^VHAr%m[/xi{ O{tBo[w+5?җROl|ɼoByqlH >CFڴPr;a`UGb hѸaL=!5IuYoyD)DR^7[d۴Uko;ǝ0kK$[z~n9{ bfcoW}<V{/væSMǀ}#f#z ٷGP/rިe_8~bƻ<4yw=DZ7(5Rǧk\tȁtE}oOMoK_j=ס}',LK]rw0Sw+t[G~zg9Wk BÂudK}uG}z-/}uP:yf ۿWc7 Ҩt]IgKIwvkSq>/ϯ@|Hi) ˗n? }~yOTA@r2M#\o<^ -&e Me_֌B$wK/^l te0g\c*C$d}wGIq# [)_Ʌ8x2ahG:屎qͲ,0fϞsvatӿ\YY)j`V?gdyk2ԣ授! Eʿ֬ciF)fmdsl~#M\<"`B4TG BhӖ xXdŷJK̑j B&jeE %ङ8>>@9d'M愄T/F ,n=3"O` }(c"UI H& .^XXyt-+;0|LM:_[Gt3Y,%Ǝh_NL !,5UfZ]oR=bl8m|:bی1?0kF \U-^}߻mYU:/ ɚ$dgV 7oJ+eu7C܊~X1I oپ{{or[V)ԣ3GӃowWWaDaӰ=zs˽?ycy jʿ7`=Jյ kiKpl^/ {4W0N~TTNV667@j{[ĥ2w71Y5Y2pu-ڏnX?d^0q!iU%S}Isy12SE@1'@@^!/J P묹RهBdaL`J Y05PGӷ `Gu G!d %:)n(Y%!OQSK`hhm۶m4ϟSOs1T/"aI.΍rW*M@S׏If)N?{Y5pDi;20rgQ` flڈE(<* Do#|! yF=ǧRߑӑDoI{ᑴG"XnMl"v CľC7Ebnm\zgO*a̫T~xЩOP_aZ9 ,^YѿpĚ-uiЛ>̽[uWџ64 ɦypӏ7OLSjeֶƖT cl4eH_1k `$hq&$v o3gz~SgU.r8K (j-wAV~!̥$?PH56kH!\Y}]== i2 ;۟:{ʱO3CM>O;iw3c,+U85Y0k{?|x}pĀMHiT_kdKu8dGD{[sg>P@FL%`c~D]yHGt^p @u-#h3=ok!{j DVOY7ۦWLP !R5VuBHZCLUUg$­p!'^ǥ#Kv6FVg勖,1o;N`hg(D& ngU-8>olGCo;xt\[B3چ8BҠȑ#뗝'Jʆo_R.EH7!B K©h|9(>!qVyǏDqw0&T*uDZ9*;ÕPJC%0wS:֗)7:ďW%-\n;nȣ? f5h`F`AKȔ3902b7tB]pi)`[bggb;r:* 15en5)Mn\'bS3Tw8DEq& W +>):Wޤ8%.`UGDYI JkZ~Ysf9 `)zU~}fڪ;DrW+ϘՖHTdH_w$g(8boa^}wcf97?nҏsAj!n9/F6M#L/DZH5 kNRI)K㊖1ciՂ(==V$UU7uS:oN\h$/9-}#/WGnɬ7hq??G{B41Z~|egW % ySDsC' ={8Mϊ#Iȹt<Gg0$ qE"N"FkDƴ_W Ԧ$eS_}ˊ'M361 LB߶vzqLJ(d7VZ]IqƕU!>vO"΅?l_{%L$7{cs^g- l]#fJb Z߷q:R]mmC**(^֑gNJдI,OtԽkX lITN1 ͣ+3;+k3^i|ytZxߑ lௗQͮLJ~Ұ(#a?N˿FqZ:~J oi2 iF©x r^8'c9>aN##UCvWA *Ӷp؈Ls\Q*;BJ".*|-;_(]w@ <?pR$^ Ed^k̈́2>@vdy1 5|kHCsXοO{ /LZ3TI^S5y5#l*:\\G6fXo pC;䝸ݚp?$3rQA2ҺN\J[O:v}oZ{/߳}Sl##fvaُ\\h v'*}WqQq@{Cgo#`vWOݧ!HdSO< -w.AQ;'~V1{퓧,}ow:K~ʷ[Rh9~+N<둷`ʷ__cIЄ;` >y͏N~haǰoڻgt)dx-mo?K Î{3V.Ÿ?<*+)R{g߰2Vܙ?_E\;8sR)(fSGI H6Uk8EZDi\TV^IPŚ:\D+#`13Υ21S@kg;Y wg`b$2#ĀgQr Tii$%MpDjx ی 5ؐfD҃89;Vgv8G^3J̓X8[̄)4E+as!(EI$׵X"Oa@샣R^"Qu8@!P R GHZEVˍ6roN skU1&.065/ISrjXyY Yf.^|SP*g |sɇ.SW~o@(_r4d!-v.oPbD46)s'P :s#1c?_:%M`~ĈLBﺗty˾mG5KR_%+*=)TY K'~-!+߽y܅h!g?}NYi.w!P^e)%Y b< 8-hT +n''FD& 8?! {(+X&<(0!q Obsr63@C ȃ0"R rqtFIFR}6m1zÆ )ٳW^rs@p^"W5Jņ_K*fE=a#NO?Q>aW$ nRȚBB -IhZU*RT*KweWtwm۸a}v?N, *GشS]S_ޔJ'D"aca` 00cs7Qسa'zQqowo n ^x\#hg wa9Ф]lЀM|XR*Gf=Iq~#ޛ'UKH?8V7V/-&[ J`Hc0gk.aϲ1#Q@(%BɦA%EQͥMs^n f>c\sk^5๰~8>D^y艡mT 8݊ rIN 8`HB]1 DC_tHdIg#Jb!~B W{$,w6G" ވs\(zA:_JI+ K.ϰ;$M~K cBnEwedF?km?,>z$E)AT\wę7, ^0*A@OB g۰ߩ̄0  [BWl@s 1o|Qʄ]bHȀǭ2X,?帕f8d *ꯗJ"q &(r.Bڎx{(<_Jc%KSV_.>.8 [ջԠ vegdUWWכo}sι;;笚D2N Y>Win q*`9VZ[:1dr쉱n21JPĕI\4 4:SD/{R "hѼM2P"E[dG<䛜 d k(ijC*8ؒ7m'>bEhq8!-@7#?G0zK7܊xHE ʇ_7?d"nҌ` 2{A+~\]6Ir5ۑ,Wyrk'g"YnA\y^$Gb)}2c3S&WVt/Ynb?sz0? Hdr\} $S)X$Ij8^H LUTJ^΄Nr cs(0B66svcs3ԽÀ467O9kV_gG{!Yz !J[ZkgJ\.FH{ !~3EQ:fRkƅm˨0YOWqh9Tv ai8F]|F1q{\KpT_hR~/1fp 0 IڔTi4fDmNF€q'&8@Ғ yޞ#]Vՙ dh޵sd`s~J-5pNFǙe{QJ"0|(tŻ̂e PK W*L(wo9D)P=K/Kn%')DRZ2(7ΔqnUZeqc) /B~x]Eni"5bBMY)3eA?p ##X,P9 4X"$pC9!젘=ewk=i@b 7 '搤Ś MrK|7nxi͞5nk/~#!ˆaX;"ūdf˕ o ۡK* v{%ь1ohlJR40}}[l1jtmm=xh<ԁ}{Ϧ a8TW.>S.v.C!pK'^y oڰU% [H%tYu)";YB j#AqG ؄T:떺>jC9j \3:+ (mBmVcKKjnkJ4@60@Dfa 1 0(PJ J()!Զ(U"VK.QۢvZ6mJ|öͽ9#!6DꝬZrJ*{%4X ;& ŹVqC z3_pı&WI7^}f{ E?a<97 "(l8b,xY򉝲`9j5lh+WW˪V7T$ҳјGE&@wҨl윈v$*kjV48"V!Xڵ$Ch"1hO x^oȏDKȆ #%GS$c a(|K_k=:|.wE߼Kor-,9t:Վg"H×Gj!4rS My&V@F}|yYc{aBъN [˜R_n!I#G۶U*휎0Ƶ@a5;ϔBsDR!U b7oP'E-ѩ;4S\* ^ >2%T9,%"c\n*@'TK]V p'aͥq *d&|S5xP LMԤ)jK}{HiFH$ 4LH$060Q¦&6 1 ڔJm(!vHmUKE۶e[%*YV;huEb7)Ԣ&`֙DFB8q4 n^<C։eR^G? ZU8ϕURT1&os Bv0dJ?I~qYL`{ڃk7>!rQ'rtd\ۅu ޘTK?cq~\+k{ۿ?u߸;3ҠHC0 НjY㇯4c13V YTE ;:>*LɈTp;2D ۤ D -U#{DřT>R1$#QpyS* G%˛(8눴i8FMČ/-n IDATKeSQE,\+6cd"1ko}{OR18)eP='brδڑy(}GQ9C%t 8nrE`W!EC۶)5֮] xw~UxvرجbgRc_G?9UUU٩8^rX2fxL6j-˿pbJӚȝzW?kӤJ[I: x;ԟ}75'p(1?"U)a[iėArX^Zm ߛ.SJ)%ؘRL%0ƔHֲs+8CƍWW[K)e~G"w @EA\Hݱ.e&Cf |B<4Վ%&R^?9 Yʧ\(JUCtՔRHj}үhm=Ƅ3i"˾5sbmh5՗Eos;sܻ\ϻv 3 |+xWk).f([LibHRDUP|٨@#n3/p8xoCMC9pGi&$18\$kt'R*3t`m/b~84IC(6LƄs٘C[h6T7UUTU$&Nl~.csm@i Bmo'6adc1`l,&-JWzVNCh 202$6,F%ac7FM R0Z/"(~h=6)Ms]}1'5oθ$5 {Do׾"sߓ3l⾚1",^h݀ >o hq`'>!``KF8 EE\pjO]/ Փ= s1c5V@]kW'l=!m-_~6Mk_FNQZ#iR1ݲkiT@K7m:HH5HYQd}|C1WZiD'*ky]Cxn,Ej(.M0S@=qEؑLh*[Ei o{h;cN~ɤ%Cp,Q"v)b (;MT :Gf2 WTT8w'|}'SQ!uB8CPN[()ry nRLs_68e%_Ed }UyI+ uYaŇ}0 "7"X,Ν3wڴ[}O&Bm۶[ۄؖ^Bܾ}C}=(Hl:SQ񮵿] }+FԳ-/F8td"@ޔenĔQT% TrFT9 .nUdITN>A0d/ECG3:擅N'ZfXJ+u)$S:t [Yۑ~aQRy0 MT[a Koی6Fb#!D& FwҞ94inhO'ӆQ!"mm冞YVչ~Jz 6mb=E(myؐڶ\ixMH8ib\|j}^pmβA46rB8Y "5q4!φ~>߰ƢJU[{#WV>Q ;/guËg]qP)~{zG|ٞ'+*>z33.3?52 u%@$$Ac813~P[zӅ_W^kzqQ}l[}sapxj[uϓ:;v7'}WAg<o\'ycUl}߸߻+fpʞg}ڥw7r51x/U>Mr)*5N78É=A&b *|r\52w‹m.m*b2ęjGıGz|w}a@ڗJP+ ]I=N0*}ED)M&DUf2lumBYz2Wz1˲Be$N!gB'}mVOe5mJbEy-+V6u{̍!Gljn)y㭍tlofmJϖzGN8Ͻ@;X\8fvew9%9]&#+/!r@a*!B~f7kaŴrMB$&r6KJD3R&w {đRMT0\!Dߊ{s9Ķg3 GYSҤX8Qh68 | A=B; &BIM#Q`PQBaJ(mР\|%U8ī&n$ j1 WdtrB ML)|sy}us:LB-Y$BlB B14&޴JOUtW]sx[m ֦kZ> li^hϴد8son~'}\=H2bAu/ȭtb)HkNWNlƃOU^Y6 S.nddD 5fN;^cLg>gvO?ۯapKOҳ .v(*A!Re"Ā6P_Wov WR[+E^-0,rtFq"xxtLtF%,)@anYh8bGC_1Dc{A`azy0 3ߩT*JAX?z**rG9MS#'|㣎:6y^P,AsS"Gbi``@i^XAN$pO0}]p܉-*|GOvF2:.l뉔1ۜY$Vve#7jΗDlJVNB80.ضX`ԮIsOXKhb7g%lf VO+)K=N3= ,9eZ y#ZSSb:x"tDy/w`yQ"!LE V۶D0`hmn5aQm(#DiV٪M0pM"59rŚ +'ثVcjv_BJ:K`bPHl:h9B.GTs~~Jgzd8p.q_v$ Ip<8`?bcl+fev^6%j-g&?ޒ>aqwHT74$hŰևKd~skƟ'7U'12瞹mYU:j{g[CHpHM(`c X|a_5#љ*OX;g$un>f2eળ8- =` ~ynjdwOooEt\EB94ޜKt\e>5t$TqulCp2TcMrŇϭW+$r?[6H-*dp~U uCtuUASZ!|ZCls3`BcYTCT.7CP3\"VQR%EljrWR%A57JpǒSaBsG\?6hiKW}u:@P=~q##+lXzc)ߓg;~A@a;O־MjkfYղ>=PdGP Q#tJ@!IyS/1|E.+S&e@d[pг8=E@d~%C ӽGܝ"$&sh[ɛOu\UrfZT~i<;H{[>o gl$BCX L➬m#+[ UUܐSTJ5f5F6%1(m hRJn5?e~>}tљv5]BMy3u G`͂r!DK)H89&pZ*c,(?x|©q벊{-#S|Kqj=V}I1p_\o=ا{|nw]}m.u/q8aGg<Fi fVad[{; o9i*FL1Z̝9@À#oͭ;:a,/J>9$Onݕ_Eg>gn5Ts J܆b*sؙGӫ~Qײ綘ꧣ\ͩY:-!Q(8x yܴk\h9T5M帪XC6(uh1b2~9:Dyf7Ы\:,MWx/%{F;8Bȉ:E^28>?qW;p{/GgyֿPyxr@tU,{|Qry *y _n1ҪHzzz&Hsk4mwxRlHUH")zrm]72({*PDX]l/rP8Cfm7,ԏ=Ţ 5 tQ\ ]&-h2ѨP[JƉ <9]vU;n?u7dYzU-_yŇFLQkO| #b36OZ0]7R̲f HD0fq8 veȴgd## nrz.WY@W<)eͽ߻sC{v+եUhe/ܞ m1:4m~*Ž" ",qc3z#tSqȜ!ꐡ,sO&;Ed>0\ؑ!KjW1w3ĝx q=Br[9۷kVlU]]ݪU+'M޾zt;{`t;K%铃OrϨSf>z( ;q^?de=8kb+7W="_#Z69F0 ~@uW֏w*^;Va]1aXSMhO=^J /*G;_pG듺@^2yTනR8'\5Ⰺ}G,>뷻bBZkݵMwA/q9{w}q]^0K!mkS9پLM-!#B5f>=X2-x䪺DalJ m[bucؖ7t4&lƈؔ -PȦ\_*(9|o_\&gkHPpRyTpUJ%HRE>'O^peQ5vߣ qɣ {{+__IȚg'=Z`}79gF՘/z}ree zO,L;Z~քJ{pô+I`- $Cu<xwM}@)}/ih59mعw-c2 #vkHvs_R]9+TPk`^Vk[ѳ[M m__6w1j޿-}Ë氢.AV vUg89)SQ[9HW*-hY ~@iˬM1ʂc* !ϳXƔ fJho c@lSWR(EepCNt9q3[tQ=?(N5 z dMK9#9d*X3fQJbML>\2oMMN^/lnkrDab-[6mݻj{} Yiēw'~86sb̉S5=ڧ3kOuw?}*Ȭnu놥djkBl@F#PBI38Uw}ۧ|?”bw⊆ٽYn#٠Z]FR[w."kUGL,*o3)Hu6wXhS!ȭʇEJo_GKah;" Aذ@ 2M~EaczG܃YL!|Hd+$K& ) x4OCi{qk/i^@e% ȃ/ k??s(߻a]Yv&EB[$g/?PKv_o{ad9n}֯]ƿcNLn쪮,:+vW1QTԛ#8 kvy|ตj%0?*2 46j.!k=pّ4_~~lnË7?g\S}Ө9'K;6kݭeܯ=Qwsja`Ǐ\qQN7OSTV &67N:{gÿ0 ` IDAT'Ј.9% 1g-,w3.-(i̊BLbJcYz!~4dz`G "@;?%8yD|- W 1$ O9R$4C{aL @R:Db0DV!U~m!\Ur!2m#9|<4aCTF'ԗ?N׾Jd(==XRBȧ+>4ql6}0o}}͛3 6N7!CxK޿L;ֲ,;J%TK%²,˲-+tA1jM>l>)'||sZ[:)`l w޾\>'^r9soJ{'K5]i-xYypd4j%9۪2SsҤ:1]8iKq<'#g )G(:h^jrcYu`C]l[1+*`A& >S(zd_6Fah?1u^93 *R," 鄇A(B!@&L 5WFV>f.w1N _ZVFfw]il^[aLmotQ%Q+edKiL Zt;!?[elo5N-ޭ_>yD*_kƞ҈9~cm{cvEga۠ETՌdD xeG2} 떇`Oj-pؑ%fy+ncACmE!)pkTN,B ֜Vŏ]+EHx@ #wU!!VS(  nh<"4u pCzK"WQB;1sMG?b$&ݟsjDLkw|BdNL!+V,:B{NZ l+#/J ;vFl4_3#IzmZb)GQو*J *=AGY]Ŏ=2TfSbWCTFƢۑN r bVnO惧FTR7RXrX*tm=j!GcJ7|ⓣ:L>=jw}!c=Lf"sO-[2}B>Բ9u!|Z^AA?/̊Gۅy/etå͘vqџny}Y"KVu\s׫7]|Д1MGR"4M8#[dR>>ܰqRdpӊ0FrYUKVbӴFOb!vE̩;R…d"af"aibaw0@z9BzőjԚVbK`N«ՉZ0%;4k#\Jl;RUv8N;%B[M=[{&Ⲳ@{w,w<颞E:/M,1:#`)!X"IȌL5d`S߰S)@H0RƲU9R؀%!J(^B v@ 9T/.ilI#r0qK}w]޻ &dbZ_*.Z6A!d~(y!S=)uXB1Zchb A߅#W˃=?H<ϫP_'lC(Zq%+&I R:e}a ]ϕ8I@)aaJK4M8QZNr2kɞ VQVw$"}ϻOd_xOMi] 偺fcz>9ZGSiRGpZpL&;AXa'AEaf6 n4 uEIRvwlP 浤D8q ~zGFF7PGjKʕ$94ƮWd#&ch3 N2 ={4j3)pj>XH![[Z7nAI>hkKW^NK16fvR1B)p -6g{ϴ8Ys޼Uz;avք/=k˶,8#Z̳>f־sȩ7<过;aA3va."i$+v_H.ع }f/wb0njq, ,MVY g?h( 3NT\I'}qZAϡ4Λ,7FgZ{ 0335a"yKgppn8Yy_O-aE:-n(tv@ j) `& T BE PPRdD2fE+ږLnZn_iNJM\1w@_v?Fs(;}%G6Տ}Ңs={AwXN4z]u,;տ*";,s߹HC2Aٵ;M"0ݪ|rN Rr%r#f?#^me>MlL]26JfDChLYcY&||rX}"^Gs(NHFP@ a4Mu)…+*JP*~}뒥Uĥ0{}L,.?i@g XlMNQ5z@6؏Tz]$tm kRMu5^ Y0+Fg#fmkp󧷌ہ`ôK8Qk$-C3 6lVZ]Y]\7^E-s+7mcWT!h,Ƙ zL#ᄍJ'1dD S /5-Ug5)+Z ̮vd&ljfee*[KDuV,Y)5!1v4OdW^)dVb^Wj{jT@4P#4ƈ3CиnYuQRliGsn.8ԅ1@l2<%r}{Cg|r/a.cs6Lf! :7r9ԫ8x+MNb5(luiM(bq'tz_a&RIG)7+2 )k[6礧R@r (ّV`ڻ<*Iz) x0غ<-n7F*JKͺS[9$L$٥dȦ&@2`Xjoj&q_=sܩr7UJ24<cU@h29}psKiZiċEf޲o]=Ab(ЩڱMɟ5ݴIB-de\~!hr-ҊIݺTT$"?y4-gz xe?q5^Y"Jei*4͎;R@Dd9"/LB$XK,5 Cio͂x`Y7|J+7ާkن[<{[DHLlx`jn?j}pʉ,]4YrH9Ǘ-i6[\w(PZ8~ -C 0Bp$ hG);@<瓀)l8v& 8FЈAcC;+Z0cm " ɶm%lKLmUbA|=m s©1. ^苔G$.e-UZzih@uCCfN\8y$pff;GƦ1 )΂0أG[a1 s$G*@ݽcw+w V䋫==o=i,[ ^*W-lD` ~c5o`teEn & %Il,úqm1DSTJOp]!cB5#/ɬ-s, GatGwvEw DJ=4MA{L1)'TOHnMF4')zZrvz oCSK\#,ݨ= n f. WDBvI3"3;%q-XCJKXKJ4i0-G)6ʒI-cb||OE-d&2f1CĢւj=4S CH*1(ʖ@-"VE"V7P }PHmvʼ@ꚒUa?DQjkM*XYkk6ɛH7a A"y߁#q r_9y˓?l_8 ڵY)s^M\S9 =koX*@ھ4rWڭKV&\\rfvtsdžڌ嵁;eb1:R#sH".C(ڃj6 h޴u iCXϖ&@!*]pxge21$u` ! Yt e[JLMvc+R5;'ɋs.]J&+4Ǚ|90#>x1${A"D#9V*t09@@ &pLXuWh|ݷ'5K".1UO B,6 t{˹ظΏpc rn3 ":UHx[Ȅ><N>p#J+!Ga]`5}f.˅|!醡km7z^VgӓSFmhx`⮦%6n#Æ5=;G _E+;[otFWza+LQ嵽_ O=qwLkVz;6<]hlnO\r Ov=# =}rA}mè\t ,S};~`WSO?fEDkr=w߳J _9:'{~KֹW s ;1Q:UK5v}={,(,$(9IE`bWG-+mh95ၩ[Ҭ揠ZU]l" qؕh:SafUhp{V;_7r,wז~J*n0\OI.6s'eb|_R`8psnOX#;z{"*L[ZgQ_'ZM++%piT};C{N>׿b熫~hp5?QuU+{G{;129A"`"9z1w$"d]Dw~W-%+i=:M!=mYĔج(PVJ}"o(?dqٳ!_ }Б\x$;90oȥ@yD~ɘmr! W Iӷ۱%$Hr"v|P7{%5"xGtlTru̝a59o0]Bx@\"PgcGFr?EC  Pg c"۲zAőhZ-ae rE"Z%TDK2ÃcrBI+(csx= /g|l1}= '|^vq_I8S9o{٫?]|MN,/~y IDATx+J~wh@O}䢗~vmv𑋁~?!7o=겟]߿xŠ|veQ\y/+~U+N|'yL՝F9 I|8@ʹ be6;;\HWLp,ҔJA4y"rw0?iى&Eʓ풲x'婮/U(}$Omm+#-5-)K)|):5w!bzL:AZ҃ŌXm]VO lH\G1+i-L̴ҲhUO/5}m ʥDgT\3N~M5s`:_L6MF0ޡ_v]gwLc!.Vĕ@xu>X=I,mx?l!gbJ;.le]fΔcOEg)d~b?e7wo;?v}: ws/{܈|ޭ :V~֪4rbW=, FdP`m KD,4>)}h%S [ME]P1dYkb y;'d \?}\כN}MdnmeD! }Oz+ɉ>rk[W`mp47×LQUAjgE !_"ա"h$4tFH>LgI&ݝ#1`3 L Ǧ9gb_0̩JÕfMLriX3Ƕ=9T*ĝt~hڶØaO`wMaM547궝 |$[ "iqGͦS֏9f13]۷ortdl6帉 "Ƕ 3|Ww߼aۂ3AӦ[Qx-7}םu( ]C!'/\dj/fcWGK~3֋ֶ+w lߵ r;:ppj߹s{G>z`~mc10")4D"X\]s] H`"@,i!j׵ 1f謬{|VYD{ٕSvܲ̌p8GQWPA:n&>ݠ<C)2(R5+H?G}۶#]V\|Y>u,=@$H@N$8'mJej-S{zij'wy ʆdْ+o߷ _U61W`_C4MT4(>MX۾\6 y;]4~i٩Sa1 gؽ7~G_ɩd__uSԈR[9ٞJ&I5bz6)"jQX$:g3K-] >u"GI!`JE[T%TLJ7r U!@Z-,t%PՊ*A)U:e`{P8ù{׸[ԠBm'ٱy1YˠjQI)P|]-f[ GT<77ejI$˦QK_ywr3ƔѝNb]66<0N Kߧ7Gs4GsM ! B!KbK}id_25UUCww MPP#!zaIszzZ $ '!xS{q\~`VEj UͶ-Gy VFl!~ABU @ҕarj̪HռJf*ݖl I^$a=JR=}4 WA>t& Ou։@!n*B}\ቛ~60F4"plkx;!!j;5:“ ;/slJc~+!lЬ4k$\mOSh'Ivgjfceu;L &rEÑu,_~Ur\]D4MP(̜e[z" ݜ78=rg[fW(Gmzt?ywvRAz-͓> Tɱ0MYygb۶ O֎2BOՅK֋3v?dkESVoB @8+/ߙ;K{|zdG?zOԧq!k {xl rp`׭~x>m%kfւa뚕A ݴ E@t=Ol !.v0R;+R R9U+ 2ƀ""̵dHKj#gh"م-Z4+hh(@H|݋Vf!wySI!.8ST덆eYiiB\vw%e\SUb^|e߼_t23s_RrpdȐ PBh`= CDd!2Ms7a1D D! zd;lci)@4iA<ĢάV 8w;kCm@dH#ƈti>`LljIk -3VV#7:utq8~̓e5w3'Aɮ-6"B*RyxrEk̃TX퓇 MPlԩVZ4MkaC]Ѱmi5&ՙ*c3u$q̔¶lI {/vuoyxځ9ܢ׾A {;kmFy?/_ޞ毾.8yzeiXF E7ʓcVlJ)U\㉦8v$ij@z)JበWijĢުDWmrVH#%Tdl#c:rfa;d(f S8]̲  V$!Yfgh{: M\z:2IbEW4uuvuuv4OX8C|OH$z9b~>4 7|E Ә<*3 }Es_!-n`ȫj \ 31\3tSKLib1*U,uQUsF D)ę^7QWgi?51#1 !C!i!jX!HxuwT1`hp}L%ȸme/zwVDvIޛF$<`ar" PoECjƴ;HF~c,PDEGmw(>2JGOTeٳ8Eҍ~)j?3 PUD, ,(`x06) VMWu>P.w<0Gs4GsF*-gS›C2*Y,iBDQ@Z3s/Ibm~,'q`ڃydWٯ ไVVR | RbOďheEGP^sMa+݇l;C^Rx8yҵ#`Xn PDT 2qi.AS ^L>@)7umߔG&A354P/h'kNCs`00s4pWGG1~Ͻ괵{AONu?޲ g&ܚ1loSWL4cbI2fd- X!Ș& Bp0y'^ȥb)+>ٶ=95͹@pEPbFDm.{K( 4M*Ӌ~eS ?'x/X}Ը7?Ch$D,;/9km#0t]7t]5iiOd,ާ1Dwv3ܚ.—)_LadZAM< Rf+meŵ%= KrbR [p9w&eĒJ<ąFUL{~.nzαۯ CG7 vC;5p}?a Bd00aicf 5A6#{{ {v,o#qw vŠb,[1#!D7V]v z /GpK%]痂M1ܭ0t}Ão{е|rəzv!rc>0%6KMgķPa&3\ezudwsDS5LPQw׉Pk>ַ#-'hHYkԃ&%2\PJ|$*EaI=ɭmB *7ݺK n/O'G~hdA/R)z:gD8++8')0R]H}| ZmBTfl!l;cLmą @4YXDe,q&' ,w =-99p\v!;&''B^&8/z&O鱱||ՠcsz:U;b$SmG}/C oIGۈ>5(_COa&3do=pvUKsc0 Tf!js狉V(dո[~^r@$J!O>S/UTm:2FwbԫB#PC.mttӿD4,5h8FIpE]yIL#v.?h۷~|aTtK\5O/U DGTq54j)ʾ r| du Hx7u<|VoE!Bq Z۷kN۶zhkV\xaG_7P75ٴ"_!#VLjH@ $֓DIvP=2$!K*+n->a}|.xZ$qo|(QyOAwT>aɻÈqy[|o)=HhGP\\n ?P$*oʤPz!EJ'qW[!MIʃ߱ W6l'`rE'7Sx-;^+'d]䉔KӌpBy"鯗-_5ɬeH e$}!^߇% &%!{L%[г|!Bs!۳wV|)g#l <::&Wokǻ+rɎ%C%y)B|P}AiSC qC5(/ ķ!&Whz[Z/;D$T1&*ְbbFVnMBRfY;ST*8)(Zx砄n1"+ALeR˥=R( ' S@i("S1,ynVb#✻U%TB%S0Ip6Ut6opPe}GwU=! i͹\T*3\nѢEK.Yf-ZP]+ϝt !8F4sC ߿w}VhoNeFT-`JFfF ?;x6FTZf3IN}НgSs4GH `hH7R\K[B]jFӄ DZEr$qeMc .AG$ #kIr,bJǜJ.%'%4,(j\ [K%9ay1uZK[VRե,Db)qXC Mwwǃ?p,ͮP7"FX43YI,:yODb4sٶأelD`- G97dQo[ j.64=Jf#PHnK' hՖG\!L >Ux\3YCȀT"]tĔrNðdQRb N q() ;x 6FB0,i0x*(-lbQH : ?ʗGXpl/>=}NM;V$\\%d_^ՅK˹ϟ@=9grё- (g}cRqo "`\8sZƤgejQ% VGgϾFZ+ %FY-t^}+atO|5˷~碏݁xO0{ZJě G+tфn6 ˲ t(s9 [}升_&i2Iͩi+mEC<Ù9$X!g~_1i{Q@IG.25< !f%Șð ;ي=ͳ $.HHV 9Wދ8(6髷;e"EFxuO1 {*EAptntL:qtR3ڴ4rP44F%jjBpkn;lLMtF\;7&bd5d aDX9cU2#8:ui2٥I eRIzIG$u4s;oӵRl{T.9& >>9eYήN45%lIi蓬ѫ3Bu(Ym/?*&!5P3óHqS/tuu)LVvl5Iʃ6񋀧弫n 8;aу&}G= r伃ҵJqے-T2G8 ҈<T{{zd"! J H&]^ SZOʷYʴd"'B!UVAIEXmjOh_/ Oˆ6Ry vݤ.\kpBD@j v ₅ vt4<TaM$9@MSۀ$U ^u@oУ{cl "욖s덕˗@Xgzm|r̲\GWWwPpvZV*O{UHN;DEOW%_ Ң>)62N5Dz2 * B`3G Qft1Qp΅yMMM[ SQri=KcqGp7A#8$%D0NA`iVvhm3I37eP6 2Rf}."XSsNmR8mg8/D3C i_js;4DDb#;j4sΐc|omF"p#;[z$O| 6碏{("yϿ/[c4=o|GmIJD$-u=Gou[#W__f'6}ǯ?Wn_Q'IX/^Κw~G?ۿK^ l+~?ozKK(嗾-ozxgZ} %y5_-{Zf󱆩qtK1/7|co:gw_ͫw˯7Lir˶8hnhH3h, >1Gs7FM. 槲$0< +iQ\oE`vRZZvҠ $.Mt@ҼN"+Pҵ ӂ8O=ZtDіkp$Ybchh3jilG#HRlc7HH'BIfQ"rm|:gAEB`0_1{LMhN`W[<m]*q}yDT92 nn-<8'I߾\E dL+XKPp?Y.d!30 kolttnnڶc۶m]] lٴW.r7W|D*'66AϤB<؄BAlHXWq9kViN~P^-rUd [Σ ͂cuuq΅SSSͺڤ1ʄQit8M[Y0PRraFyT.p\^P>%g21+C;7dB< )K-m LL)6:];^.<6QAԪY|kTs؄b)pʥe5c:G[#GDΝRRdYV^C]q:E"VluJV6ݛww|scS›l[>zs[キqБǿa02t2ЃͥV~JgƇ/Z.z~7_kCM[}؋/~c4T3M8G]pn+?CGos^~E/}g|;綇\Grr/oKPg[Ow7ҜݓW³3z'~_?tBau?(8Na^}2~u3}'{<{:ShHB#au93P zZJ[UQ3fcU* V<QHRlH,OH:[Hl[IY,Q"PP&[Iϥeѳm4Ks[҈f$!䂖#RWz1ǁZIqD.&#*GmjWn΃S$&מr>iFxXp*5biٺWnHyM L:Y6p!\,V3|ՙRKpLMgR\UK2"Bض{]w?ĥDU}g럁P9@FFpn vE9x%&-+ߪ诧|vevtWsPQ*q7dTfpd5al#R-_ODDgJIr уzB+O/&a%_Ŕ~H2gf ߳(VԮdĶ_f#<{c?ަt? t/n!l`YQLYaC.8еϙ$ܯ?ޑ{NkAZh6$a9ws9 c`eho]_~: 7/Y6b'_}иWϣ]ѳ>cY/|%=}j|u 4b]Oߊg|/\~v~MM5/:z9Ɩz)x1/?n!3c{ .\k՟-=}KoX~f)lҶE=wz'@l:so\ ]ohp5!.Շןqb"}7)݅9rX48GsWE6lW+W8}$ʫDlFT8>7B)G c`R8DdZiKi-Im$9l.4С]=cIILCRmy&=6+[ 2rX o9csقm :ˆAG v΅z4V\':E4ƹQs9FuǮ7:]ipޱgT:}_ڇҒDbMLz!ts>6^7߲buqbz\utLת\j6wuoT{{&&*vl.AlI'#/+&6crBfreTYMƒZ|.-wē ~NCCA.9DldUA,VR+Yp3Z |&#o mH͈8So8'+cw^H5'Y˃J4zAv)(} M^ PG}&" cofن1:^Mi_QK ?:a8_9,:k=yAsj2g8@hHIi̛̞veIx̒+%*{v`yKL=nF4Ix5o㣏ܵ5^Ndt=}߿q_/\s4Gs4GsW@6lXh䫛niÆ W2>O͉yl1p!_lwߦlS:$@F_N8F)UĦ/-_sR`uY%oH~>O(zog_i6R~F:ĺR)PLO;ˇ m-رtY0 d42b d\T"D1F© h ҴFm1 zwyh^ҩe?g59p+Z`ҙ;ID vp4(Gw/YSW:J]4'^ @`Owcc|gU<{6k΅S4$̳I/+dT0a%S)nKJŘ)̡R1pՐG@7{T+%H=x!15Wj{HTEӴrlY\ӴjjN\|n:22dB!=~F20mV؜+J! Q \PuB|RrPjv{VU Ҏ LD8\ʴ KLOyGQ:@7 ޿o}o~4]i4jc3dcDmxNtwi[ 9) 5 zC_Ocl͹'.ڵЋ 8b1}塊 Z^;%0̅:V,*]S@^5ڝcMsޡMhToƔ U/m7^ւ$OlȱA׌bcbzP  \.gfԘi:2 #!n qYa)u %.2%QG3Z*ûzcO$L XeCWJx.P9v9G_^$LjUbX箟,vpwWnFgfVԏ8aR~Dt*(VZPڇ%R9:Cb FYq+%Pղi_ 9ˁ 0eq)/}5Yg з69wc "nX;P,t8;]{wܾ'ٿ_T# Ƅ1t] b1Dpwq[rcyLS_vɫFisZjms nrI^oxb(v]_[%xXĶ6 .{G.=b_خGvºgڰλ2o]q ?~ߒs{׬w;8Bl!]q)4+ku_Oij{.K?tfuهt隖7Gj5L y9 2&*~'_.^3h{\dI"IȖf|Ia $‹'?y\Ĉϕ!m< 11dKKcX&躮( W%,yqMbogшQ6c ڢ9~+@Tcl#Pw7 i#.D4ɞ{+>3?$l]do>G<えwMjg+ "t*; ܄!5f*(,!!XWwwJׄP5JYpIcll|bll1{29_0x\f"҅ UU7UTv{c_t Q۾}!{@>%=6x7o:5['dV EGq=\x#Z03 s?p[}s~ha'?=h,է>5T5:~TL8J%׮LSElQ:))TW dB *F&\4] o.r}ɒflb/S*gdwz<]_T*nݥiiUQEa eYou͏&)!;kHˡ fO8`B~7?qg&5pN-`T3)!4Cu0}sR`< "*>JZ/;(OXJSg`I !) 6ӼO'S5TRhA0$d 0m^@D"g:/Lu1%ۚ%i0DZLa3.V$K\5Ɨ.^299z:%bw̤rR,L:11Nw-LN䥙3ErrhDlJlkW_2݂zqn(zH"7Жu`l?zWOz@sݯtyK~ybk>}ɲO81}ٗN>sxc{+W)1W[thM8Y!r-?$ 4GX :0ᮝ4CsŨMX-0$Dw֖뤑hQ"ڮni; 5r 6|ba",Y+'Q4~sW&ȳ+nIp|!#"OpGNDDTb 2)!̛f#RQZ:TƲ1@RhbtscuFSǔ*SsCf`bGK$UҐjS㪪ժVV.\ӌ)FV*(N\wy$a;Y8q9J&N7b$K((3k_qB6B(2>Pڦ4Qd/:Br¡ܑXb+9LSݓo HXs G{#\#/P}Y5A/Π_7/[gX<'ܧØ|:+!r׉;CDx<(<CFDX,@}$ CMNNMLLI]N*QhPSlaAIs H_t{V3WǀGvz<}iJQ_>yׯ'-<`ζ*:U u6ac1GD։a:C4fڧXc:A\ ZhN&b#?]qu #J]]c\o30x|<q"|*KXH+o 5 H %(N#櫡,ljHܿV8]5;Vv-YK4yn`],du J5d JSKL+%ƫJJ PudTjFjL>mӣL*UQ2Ґ1[Yx,|+r1 fp`phR.jL&344>o\>o'_|^T0tyP3 X,[Z#sp: G%`}hX9Lk?h63\pHo؝xDD>:eޞqe 8 zpD_ ~.R!XEI$%isM/IvvZH4г>$vF_q`"=K?B/acSÒ֍!F ȅ%pWp[FPxΙhAd!Mb}F8uqqˎHѤ >[vexF g'lK4bٮ&/I#*&}Ԟjx6nAl68 gӮ:బ]#@~fRlR=H!LADa2DEQ@,XFQ*՚p]ZAg|JkhU%ht";3S RΒ;M>֚ϤRbK.VZmlrwpxRRj2<:Q\KKđ oCH2&thIė$4"]{LSgQ’Qg0<|F4(JM@FL=cİ ,<(jgenC -6PrVH-%Ȣ&HdH̵OjqI76J pat$jm`M3PlMԬ.γ@1Ybc?=WiTij38o嗇_Z3Ψ23+Y' !"#!o g}3"|:A>Uh8<ԣK B1Q+ x2UEp bBd$%u+7JDbz 0d!w ᾵W[F- Q'] NǰʦZY n^cIb`)1TC]ŬSjj{59K0M'Fd&g}% \ZJ-i%gt¢` {pZ$ڥ)8"%EQ:顑bR**L6UUUfr9Ռjfpz&f-y:m0w~&]U(@;սMM A̛dRsj\9A Gt!^L;Ee):(ҶgyIeMH ʄ3cҙ! ,HfBH& ^(ѻ& $шY!h S(}S%?Nێ 5pD2Aĺ!4Du^Z[ 隘\ B0x7$nM4ދ.hb?g!c1Co4h@s^»-~˚[u2APT6y*ê{b# 5UfKZffV>\fdM ѩB㻊4N) S*,2=ti,Mɦ4UQ]bS5ϯĂ; + !}!d3," !87M0)0 2RJ[뚪:V@yc:_=3\ & ʆ$bAӬuq΅˳H7F_uLF@ 1qu䈄22Wd[Xx=mOT!XB |*؋!H&F7'j".~Wx<*U٫*VM4q tt@.$ ""aWm1hF&c SX-!Ӈ&hb/<Lw0wC!c&Y!*M`̤Ԫ`@e(Y]5A5878\dQ bPUXJSRR0Ee s80eNVD$ tsjȺ Zť0EQ]Oژ$#lQWpB WB3BZt=m#D1Br94-%vW(N2Ayg HLnlv$qlGmX? .Q)s .e[}p1c0r<Ϩ""C)C샿#_!c+9xDX9YQp1raтFsjv m.:ҢT~6lbnNo% I`5DRV9ʀ>DM)w+A 2``]FQXW!fjJ5>6mOV/Ц ,{ 24FN@D\p! "+2wPA 03: )pmdj Or\Q,}2$T!u@ޫwT#5K+U9@=UnLlv4,s&2/{V&#HczK.疦}!Xs/tQWeԉx "NqoZ6HgYfWhgo9"0PWDZT{!'0kbdCd,OhYu78@D!j *`PeP)E ]-J0d NP`YT Vfӵ}Lrd^㨭[w@vhl(RBpEQJaC;F d9yƖYdw7܏hcVu!?u!6>‹/taAHd4^ b:[B% ٛ !JouFk^.lhóKA5Puԏ ,aA_g%Kb SɜJJv(d1NkuLJbz*(ģ@`yM-7'@(ľؘ1X0vce>]_]PA|i&EWBpe#;H={ы;Zr짷am-AjkC$i42} OrsBȫ:C?;!5`|Ⱎy<09ʣq^3$fUp۪rEQf"lC@PV9jBF,޿M ^xw";ߚhgx``X;jM-La 6QDT3iGJt-)=HDi*bt)ce% Cj08Wi{Eo.=SzefϏ0.*WAJ+҃?N{̎_K/.7 ֩튢躮( W|.3AqhFXZB&fOYm#\?q"' oezm)dlF鸑'YKI"DiAv,fgd^z6Z]IVlr Xe W8 tVg\cnk/~>`&|F#pytOAj2e鴮뺮jFVT*uOΚ]t:ҒuMQTM0R\jEa,ft$3"{|}Kg "D Dĸ.7=hy4,#FMםu’M#K<ի[S;~/Buyک/Yۙ>o`= эSH6aFCب![. ."FjNm% IsfED$PŪ ʍ?woE\v2kxz:&JN<5kT 8ܖEcŇ%CMO9U@`aiՈ 8KC*63e5[0;+arK)<\8>PWuk$kn!ԍwD}ܕ,Nf^ѽ3Z.d,&:>EɾJ΋B!WuvuM.{y?7W\>Z]<֪XԼ m` 笻R]'}boELuOv;MWEo=K;>=p#Ⱦ]8=ND0R5nu JWkbAΟHq;`fJQm1LSD$Z~K`bTskn85\tgF1-(iqI:}jӝ< Ԃ$Vvr(8ߨiڑG% W&ID]ȭK;wlck?RUհr4dkHf A%b= $g|>:DMX#"2$"AU=!`D2osAOlC${q〞TmzKVDTK[U%c"^[Hǿ[ß?\W@yͲǝtMrzzʣ-]tBҽ?W9s?lm[]Qwzɯ. S4VO#Q/SgAXVWb,Y"uAH`FtU2]Vl?I(SAyHa*!7-&#@85x}T֌pMf^d3juӏDJ+I 2GKz5އ%ɗA(BH8ZE+>oX{l@_T5mƽ9mT PPeMU"?jYcǏsb{rˎn86(e~ +ԿpR5[[v`#X@MjCVJ=JS0@8> +w|q|ʼn4WXϮUL0C<Ze% z%Pڅ~M, ZgDŽRQ4Zgft`/Xˈչ>ѵ M ) K@u 劁ik+RuBRK^|p_YUZ{{riyّc溼Hqyr4rpktFԕ@ qINOm|vp\IG!?uhFQo{I/_h J OaM܉l|<[9|f>LwJ;~pqE}`YGDLB]Kc4/,1g₡k|Lyy =4V'ҨR{Է?D8R&|& GSh7zs@C]EڑJ&Yv@mu10|*ό79,?4KW@ZݶU+-bi˗-Mê,Gl$Z|s]R|v-fP?iv95HѝO>m2Ԟaδ#Oo}dWd]kOX5-#Peb@9wȼ4Mo䨒YSVêŝ)f=讒39BzI'lt}"$ dRK6+؎6n>㋈Dw9~e_kZ=әޞVjSݶ$&v,]; T*l a}."r$&^-[Hؼ;#"a-fsJ Ä1ٿ}DŽT2C!XkW xC0-)/[GܪN]{G gVv=W`L\6TjֶCt3 @mo>2M9H@FDD()`>1;ߧ6& DiY!M2 J~vʫV}-'-[|7'M!;|׽Gjiup>4ɂQblb\B!c,Lr \ӪꚖH+ p`-{gπ+# uƋ@He١NiQ6DH? F*`1Z/f_Ȋh+n#A#OC䝽P'T:Lɭ٥'!9}-.DGULO3:5+tdZV>υ]L3js.c)Kk*)PGU]cwk3-[ԃ™=! BgmM]Oϭ+mݶc߾!jkk#%*Iهғargq'@6{x]ˎ<+}G.L<ӽ|+r GFteUyU9ሥjqhxu]jWr(WrMln}ce\~U1AD:Z0m kSE^j&׭-]znw^MOO?On!g1i`9"E\  w?o)ZrN`ޅBs2 5~Kµt۵sv r(AyUo8#?L_]? cOF6tM}y%$ d@'1ۡ5)º7j^5ʶ^TUƹײ[[۵{ \ʂP;v GZWB5YTUַ 2{Je.6O;+bK@ ?zj/~ŋڶ=1a0l=?ui[rоda 8O>aqV6<`@غ @m͞r̔=̒O:5iB΄$DMy`0c{aGl?5,{50v4R֢cKb &^pKkB&X՞JR`%&ZwhCsv SJ;T9z+^~xP ]"EaqQ&tɝ=Lӣfo $b6d?dD@*\pk^sKӥ{"(*(LaLUUX6ҲYs)$"ιEc !87 ac&itɢ+րnҴ.V[X !NΞc>[`wlʄtߚWCo;KGsÍQ< V#LH:@O(lkײrafŀf.˃w^#FgalB%AHu'_v/r$"|Z(1aȿU- MRN=ёj0"`~\>+r_yaԽ'E9rL)Z#ZzDh/ 7)K?HA-K$H2~,8*szg\Q/Zj=.tyҏ|$|[Ꮎ"{ ^@ Ϯ]t ?<' $4e|l9\ҴdfwUX\`ྖO>J JFOH8{>Bw/hb*jFWJ%(VAM1 j (V1, lJy^6J)@'*EDJ˖֬ɸSS1z rj,+ԵrK9g-f֦@nCZSMm`~g𬉹1ddڕ B@dv,9f% g`3\1E$ST DV2]o kŅ@Ƙ7!`U+^}9Óx1T-`$"!8c`]+=ND@$x+a,' n;wǶn)+|ltt[tHET|'M%'"~G]G裿o{la]?\w|MЗn'_TCywγv[얽k;5$#W9u?R uJ,Y+NO7vB#g2WVK\1\30B}ɚC{2ӻظ<|ݪ{Yy#-4?YT^5 {/?|ce:]y^_W"͡i]W@F`a@PKƫ޶ay vU80*oS?}~8aW`-L;Y) bAowƺT6"BD`Gv= =jKN@HD(Bܨ!S. ^m8 Ba$([ +K# m*, i 0ƄmʚC`q sx) $GFSwg>7r={F'-ۥ<2uil8 BmEw^˻m~G/5}m\ {4O2qSbHױ1yJ6Uܦ׈0,sFY3B$ǏdG7dBv ~oa1iAT;YgY`apM 2| IDAT,Y,ˁŵH z&*!6?#+Id/FZf!:/7oD7F;F6s%avohJ IDQ8@,Er,ϔmxa b#Q,2PQ˗ oYra P *|"ZJR#O,n( @U 2Ɵ[^Գ'jV=&2b|^sA֎OT@iѿĥtաe0*5ȯY21V\(yDZPm;zbzÛǪ-Q#FDC puG`5{yko9GD!",'c̱`E0: Fʒ^ɶWB6ydY#䚵y;o\&ƔgjTeװš98? I4y 1 C;?Ad Q3+pƣ=ΗqįwGn}s=1-_ɖ Ao{kamonϟ _` /i9xۺMNNn&P"oV]zN=϶V ^wМ~B*܋IGX &6=#u,Q-L<]-=**fMm%\5cOWQTQ@wc h=ueM&^h["de~ơA>N(B.aDܯ-sʦS.h?i3g~1H`4#2?qX 刣H྅ (iQe>144hP044 5hQRZ߿…-e0@ͧpSX:*v;dt}(i*cgVz/6+iujw0VnFa(YN@m_vyOO6U6qT둻v(JJocuSd)uD5]?)Nʶ?I`KMFMW`||?[."Qe}Knîݿ8Ois\~'=.] ~]ߺgpL4?5_{gl #ZZ Wj9 Sݪ3HL>5һ_1W^0ozeG'޷z~Sj^{_5+w;3a.&M<9_/[1&رW]]?N K3*EXav?קuv"cLӔ O=NES5Гw}QU1k'<,.D61r;Ln2sC"XWaMsnODsAvB igcCZY,Rss& Hg7pqSUVkLch\[9[--HN4d=>'.8\I?nqч6O ,:v}ώvޙf#Srݜ ׯv:Ob%Ox ϱiċ!h~ڴ Q[⒥ 6+ Bܼyށ2(:?k.Wv Xтz.d05KYN;Ʒ W "ҽ\qA N5W}VNWGY%]TPZ98-Dm8mTc*}#N&FZe˗}:]51FDڳk45D0f@R@l }Gӆ]#o:ɱ&p6h#=ٵ\*Va1*BrxL`YWa {%wvmTϯFI닚diipovُ IGd2cooŽ#H9qr&g;P JՌR:>}B?}߾:MN*5M_vMִpl ʅL2['^i5uyܤv}h1ăǸkA#\{}X+9`DaG~ [%0]E諃K7֚cx t!%s`И-й~ڷN%p]=-_` /}<'>>Qz Sz2Ž^iE-Ϡ2񆞛jqO1:KNB:q~{H7N[zwZI/,D꼖E/#O|E:1Cs)DH hU;K@DtJ. Rre< ]Bl۝QJh.3Gr|q2$$au1E)w98~t?(vIæOQo`PDU|hݽ]g]˞8z{GxύkUvy~q7p=q%=o<ʧ(7uv}M6󢱛3>co; }m}'jqxpUdltٻN]v4^E,`^Q*ꇽHޮ`] *""tO$9v,Mzɔw&d'̘UJˮU Uvhi TFp\@p {g-=G'p'ZC/=sɣ&Mpur"4ұ˞|%:\@(8?~ 3]߱[3c |mWV2V:CXx)>;  p\G!LdY;@2 Y(2@zfp{0Pa>d}3:uY-~SApsؗ^y9` c&BX.tkd+[Z:Iڑ6`8Cԯ갑z|(!1ch a@IWcCIIKZ r|*8q N`?Y QCP[E`A]dhk^c NMX n8,Jy ְ{Ge8 5+||d A@v/jH6P|ȸ!βQ;J}sGRQ+e@;=&[<@Ɛ7ۆRbgvM=&7NM[8tԡ@wovRPW%R3 ,9,b&K&NPB{^xL@х35 @Y`B(3 1$ c,X7@#MR*."&%MBB7!M*tdVsl ʷ!XUiٹb:ꊱe^YD~(wlrK=kv+|PJpV 2Nh|yu>xr{H6wN{s{~3mszH׻d+>kn3fS$A]c?@MOʏ{G?ITtշGIӜֆ̚y?;m!hxM/7^ځS>}vЪ3'OnRV隻;CVӹ͕}9yyV;!aiĭ40,giHzWP_Bo"7E Y_' brXD2pX"Ci̍2H#ͷRQf- =gW9g;fHFOVcVoq@D}1*Kmu J޼Bq0h ӏټpqeځPEf$2* ٯ8,?,Uim-لg$(@@KЗ#AP}Ox@0ǍLB"c/",o13Z"Dt666RU46P:De(+aa,KL (ib\7%he_(AnUf"M+Մ!} FLR+hA9 Lc+@.;ej=R>v ZrBy{q57X#wH BsSԫ,,oys -|e-SWAY1s/b#Fi˯ڟ{]_yF|>aԧuowKoxN𚪐LX5m_|LnwuN/.j-~铊]xqpӹ# ESc wzϹ`A齀ʚc;.2L(Jt2(QfU܃) @Ir{NB 1W8jfZrXvəH)0#re;φ~*eD #U"fRTyn*]O=\O<̚9E \H= ?x300"xⶹ𸢣԰d= yr%. hbYidd#ۤe4ahlfCyuq*ALХy=POӡߔ]1<"@BQWQGYd~LR|°-ٲ$Id!qBSՕF]iz5o,{EF`)J,eY8ReRzTɪMk̒y%UVvBW(Ev)zvh1}4&R'CjUJ)J1TT:qXb)ڲd)Fbk)-Q`)iϖۭ\8PĂwĢ\pnyޠsxzIx^3  `w0@`aQA'!z\ȉ . Ņ99)֭bHGd%м^vk^xA'yuWTsR׾)q ȫn>o@:4jc9u-e‰Fj?QA3Kc-#5iSJ`׶UUX6[.E:\)g]- pX]Z6ʜC+i-_X 2@GK4vmqֺZ8Axk3sqwWxFs;ݐ,AG L/[DƀJ-KU`e4hI@gQ xs!(" XZd7 :OEZev &jָaΠFVɲ,I((, p(%IaT^&XH};+(,+ti+9J,*+)-t3bLrvG&΀h+ʁP)XehpU,lp)w_+Iɸ,*-֕.bIKzeV߷Lb5='s}? /hV(2vN62@~)"KKeUh䬈iRkķ̖r7tJ1l3~"ڱV ӇmհV>]dFZ_B t ,っ.&-ίf! 3JKgs8|nFcUz&4^?N3 ֧k4VNns=yzѭ7y}wVd/ IDAT>~^zU}Vb]౥o%|fjE1 :_ZK"5aאH&8Yu)B޽!ryqDF2F*< 4!` u !C-n<.%j0B ~EYAK9 ]Jy6 p'e4K;@Cנ({%ԕaI$I֭[h`r57NS75D?#ـ ̣ʆҝ5{VHtv;08H#_j5v5xV,l (+];Zm@S=r'L8fUr Qm{|ȴI} . &n :mDp8]Nwl xǣ.Ьt@8ow:v+B_v⩓PL݈fҋ|  GM6s$8N0@|{ndrH(Ax:s畔f5%21tvׂDW]|;b"]L [KlB6d;Thfǎ2ʐBiIL'XeNߙ 8p<~OMˍ.{Z*]wj-IK/Lqک#Quo *hҝI0n'n]RxZH6yud,o%v "{[^%__nKڵ۰~me>8 @t8&(r{=逄S=XpZ]Y9ϛ֭Kee1;; ݱDL2KZ XwdY&PBJ#48LcK)}FxLMARRwX'bTEP , aNcnB[~zqs {@Wzʴ)J]rd/M1>9dSD2,Y~9vw3 'kC=,Zz-qRְyRg(qXW5A7E1zԶnr`{DS;ZRre[Jz3i[i|NU楧v [ڝMX?T*.C.xn@ jC[IB}7g b$`"B$1L&IQL&5;B;NGYye.]{JoEew !8 /]rii0x\Nt\Nt:Na+,*>+ףdY&әN !yI(u y1RtgKLoP6~ʲLߧ$iISa)@iJd8~vB̞nKX&t5YÔ,04}xvx< !R!OV9,UgǤq 3u\k~`y֤[}}+ra%Ec2S焒MxTEaim,EA/mV M!t8drh"Z(XT*4a W5<7Uך:h6Jkcg85}*&˰:T3I RNZd[tB 1-9,;2DSA~&w+_JU$\]N/b˧1.=O%#.2B R Z‰]Æut9R)Cl$| R:7t"5G\3k]ZJYhRo5k  [ըKJkOgBe=`2'7aCZ,:jd{hf}^>ݫ-[ 7{ ,{l6Ud} 68wwY&x^;u.oˍLȢ-@Cy˕Oe!vF!sY P')d#Fٳgk4h,V_@aXnPcQ]$IQlQ hꖆ0qI -/~h@wM h0=Y?*55x ŔF27F҆G|,MfLlHyEhN売3* j`B!R_饉ӕp8VǦֲFn^?<**Z(=Ԙ6XJ>LVD3 v4sN~$\Y!|ؓjM++3˶-S@ӈ?Cj=~ʤ6Pݬ7xYdgrYdEY@ Tv>BHp:TȲqQ#Gz>(RKin|i9h"hiL&to;\ #8qqH1;AG8Laᐲ Q+Ւj9SJC]x`Rl=55ܜYҦw9-}3ƸA<^?y2#e,ZGzC " TVk3YDfZbK7k[21^5S;>r/Z)IS^?эzZN̎khk9yZ4 &m:bI-I9DzçRYV64_3]4 X4$|hZc] i}Q]D|]$9H&QRCgc2%},",b_B{X:Hz,tAGIk)M!EillL& {~amm]JuiԕAj cɲ,B"EI5k>ϿY\ wB*5of/TN\t-bnV[Xؚ̆8߇"n)T<"ch`ݩ^34̆"L28ltvNT(ʪ)35і3b_lxJv2Hְ+ݲ9cIY-m p*M?˛*h3qE_8$ R{!`3CC:~ Ʋ[}֫*B%Eg; py:0@iLwc7\lcZN=om̺A#b@igy~bJnh0PqG";0,",ؗTN 4B0I(sD "/k֬ |>yW_eXb,-&i0p].pRAފw'f !W[hvtك4ΡIC[Ij50yhT*c!EpXZտom82ϸPl}"^0e?۟p~~ ]̦j]t ׮7vo !fX 9ǯ+"9WlR{3@e_A

    ߡq^[S*c,'Z[.49[&1u`Jc$}>34$CS&g%q'|rG/C׉;.yrK3@~衼"0_;k+8>gx+__Κ~ O^ח}:K>-ܐ3kV$'[&ygMy'˯/IRjggqF`̘1%%%_~; P64T4ʾ -ЛN;yÅݱ5TR5k=P_KK`O յ*X;fp'gFPc08E+JWg3 9=OVh+|)Nz\=lJ[!yZsi3P}\3,,j#>:s 8;D/ﻡzhTRcN!!cgܻ$yl' ^"nR3s+t,\A >I7*:eL!xM/"\tх=,y^h}B,ohljnĤ,cAgnN0??ϝ]n!xUʿږ=kt='H֛k{#QDQ@c@\1hG_MSy떂orz9*A W?6|knÛWx}x5>L(\r-WT>9ʫ{}m⽍;L?xjДO_=ٿ+MSAQtܝWvа^U^s=᭎UW2OQ[WxKU35R&~ɷ# ԳJXGS_0 7HmY5 #̒0쐮XCg4ZG"^Dfh=)RA(E@(7__tr?#FʢXJ )15/E3^v LQc LOeJc$-p6ܞB26蟔t>4"L -A17\2lPExuԏA@&8Eޠo\,_`5<d\ N]…0iAKгgSN9q̷n$CY;)!駟Λ7 )6&(m栶rNnΑGUymy',RjO< aՊsH$C,f(Lfӝb'15RA/nQM{)PPӷ?Ǟ|9gM~ⶥUG_DI&8}:# rF~EP<{S]ɕ7>Nq$7n&O>tlKg.9d˯S _λo$ɼ6c !O Cg/۲ko'oE:2cIRs;Okq)k ڇj7vB} l,YQ$ 9nXeqŪ*թ#{D_2үsArs5o:8!\rں$z(9vyy7ےzHq͔hOҵ1i? .Y@M$Exi?9ڙZM0b`PohZ!PPGL(YeLːV;ehB|`GZE' BR9GP#ֹzYtԙ5UsB-|'VE dc'`ęoH ,bZS-dh/%5XE)2&o -в&zu XW{qvldYRnk =~? ijjunYc1C֮񔔔v[xC]ݦMUPK8  B#xш({rm_KK hh4446nڴ%??@q(B`P+uyY!H8%IY 1K+X; 8hod=l87Jœ9rC>P8ډJBErCy/mŲU+wS1 }s8sʑx~}LC+~x>+׮MNϿb .Z#8F;hk=$N33ɲ"Dc?Ӳ6zX&EɀisȲP,UcYig@f'V@gi)t9A 2} !Yzf㺭D)%7)f%W6k]-G nSt۵uᙹ8WvnY^1)PGlp(cJ\ip̯!m_SbFFG02ιqU`gǴ-JWYiz.t([U[ v\Qr|.EbCXd2kAusⵟvL?;z$xdښ:%2Yd/Zأge^D#Mϝ!+5P0(ծ_w߼}<wŲi1Ţѭ[vѽg,KK,q8vBڷЩS'9;vm!vдy֜ Xx<!)H:`0v݆n]+,OQS˲!|^L$IX4ھc}`… Cp$>RRL:;_W^c bOkΝraK~-C\N_4pa\>©gˉ5{:M0ӻh4Vc24= -2_ZzKM(nwQʼn[(+ j\L'!)3(KMNmĊnIkeelB5UQ*][ #@0%!"$z7GL-{r{[.kxuL-- ’UYda=Y8.MisÇVݎH9KK|.ф8u]YגߵvȆUd:, BH8}#]PXHV[ܮݼ8|T d$I[6mӯKEp \nwV,޹]СC\Nk_ɯQ'*KbM~aI z}-LN# Nǽ~^ٹx,/?_d"A8 -{ .jWnXp8 C8ƍU_|1V<; =H$I(c (['eY6_$2=lpO,/ZL 4e0w֪|Tv_~^xϵ _ۏ{aCO=ȓλzھm+Ʋ]AmȘm_cd7v̓=J|Ҙ@.hq$żQZƆgL`~@; 1:+*7_6qbrIKa&t{n@Z?e||W}\Np} e!綗u،Rtx<$wn3&}aYmx幚{Cb9MJ );g#G9"@KU Q-]9Es=2 } 7Uy8caXQֻXAhW}]#v*:3ہ$DfѬЋ(9Nt[ U@J)|ex*Ir!KVo-;FY]Oz )k9;2ȍg)F&{UIw'$etǸʴoYYuAI὇ۿ/h]z׽U{e= ݒz551Kڝ!'p I&19^pVYe !} ++~kpG`,]{ .E^~a=׭^`O~P%//"QSeW5ԩU+ڕR\Q=kI`K34Tmv(ǹ\.1&D$h4J)XuOIfb}.8cyْ?NsIϓy^Kr9EQy_C{Ï;%Xk5Ʉqy)Ve%@9P k|m3#M!ǭ:@'vAۦEZnk}<.)9H, ֺXR$a+D-E vIfH c?,v@٩sٳmL!ظ% ͥ!.Gf 9犟VС{ǽa֭[oA4BHRo=1ҥ_E`ÑD"\<8NC$c9x<1XBD"re׿ߧH&8;JXK,/$Y$Ἴ#x<ME9se!LЀ;%9HBaAa.=ʲDBR{b&3k(:v*6|؁}DOЋ9ܮyRlc1!s~^G:d-;C۷i:x'*'/ӊ%r۟,+~S%-_KE#w|/.I"憡kmZ7"7x`Nd]p]Y[?Z]q$eGoSo\-rC튡6y0{5سO|۶8Fw.}?c.xUrzߙI!%pON?6|yןK:89fgnҼ1#: !"aYqa .YޮIH`̄cV6 .K0yǎ3~t!]MBqpr1-aL3Ra,…Rn" ^Z|)h5M)5ToTZH4 <}?10N.hef@&KҔ$S-LE,11׵jtO?knmKo~mh8X{RsPQf78-snuX<$zQq'Q$WX:rMèߕw?yE$BCfA#ϻmyL+Ls3^hx/\x3<:XĤa1ҶdHz\{˪f6x?=qgS:{py&f`Aܼf\s8GC{Wy:Zjn޴eČR+R?^Sja>x= UP:Q׀;ZKhvSU1=gcS2 MH%IW8,FaRd,˄rHߵ3ȩmՕF#Z M"DJojq;Enaɦ#{OY_v혓ucԮ˜vm/!sι.X,xzw{YH}b,_ aHt/0(W\0ٖ\KS/lp,WdY!&E1mXBcYV"M_L链l]<:s+|a?4Qv,Adѓg_Əke _1cjS> .-ގ9 ߗZgT9Zno0تgTÝHmZ!Ts޵Nehm CK)!rCyJbAH evQwܐ4%Dhawn;on9s\Ŧ-&ae?`WZC1\8O rmK)F1/vaXd_R#HIIɵSN{Yƹ }3l׼,vիW|bl$I'yyy;wE:T!h228!A h:P<$I$R*12c'0YUh ,B"!Dd^#(lR~ERbRr;k;6d2PҾu)Ļ.]yNBHP$?/0ay_v"ly˫%ɘ@f[,)pZ̈́s+!DVfn~pV9%Ak3]9ѥ%)Be%zͰ4An`S̿3qu>Ǐ14 *Ͻs =t7^~5~SG_r{du&L3Ns5Pk2opHBHšNjtԏA#ij)5ݨT3wlk|"Ya9j^ Ej@]y^ƴ`t 3FфW$1f0k=B 3!"RY;41FeLaѿ}(BGc}Mnm1wX)!.:bt3uKAÑH~A'vq>Ã݇aF8S>6(_Ynx_tָ> :&}L{qq諮>K_5ԛj軫y-7[qiZwνw5aEm9R+TWM]bo{ XN&:Չc@_uEQ o߫~ S$ꖬpxZ!|z'su! l:\Ɋ{iϚ5+77;/ wD7l"i\:yY1q]-`p8 Iڵ p4Lt6q%֬Yv ,KppC-$B]Pvg+:6@Fct:9CƲ+-SÜ{`fz,L˟XQ%N㉄mZ. C&IY~U{N9vxd$[T0zx>֬wI򯳺D[J#;LFWHke#d")w~Xk9 G@3l~ gM'%ͰԲ?nkZ }V!%&,Haf_8͆'7[i2d-1GNC M@UMcadVB*r&U?ON; -DDgn֣UZ!ڍev[F]]zض&ϮJј,b i#%[cЮEh3*cZƺM~EdX˲߯cu^%\P{vN\rIDv9ݼҦnj {7Q)]=挊yVq$ۍv`m r1[RK,%r3 l] w2> dY:ˍ{5Jy,I'tmY2`jre"aOiC%|_Bx}s߹8SI9/=yW= |AW}UO7ȵ5/U]UW'J0mZe聱mdw,H8ܤC-iv߀A@Gq\SVcXSO3ؐpu~6Lj9 te8!n2UjIZ!D"$IڰaC8joz% 88'qIxxQ !bÆ Gɤd2YY=B6o$8D@De,sZ@ΣqbMB2צ߈Of+eGkoPCnGPL0Fa1t Hxe<ȋ-WE )|oZ='>oNaU}QNN0v`[Gm޴2+.NRV;^@#j(cW͂ц;o8^VIE0KJX=R!L]z4B8DK_j,ylD# iI.$,CqUlRXePa{\]EX w GO.9,IqX̪ H1do=C;hG>@{l2AESm1DX҈Xf @r*Cs]%{UNˤo+}a;wLkkL*W?jωl?}ne\@F";o{Sm1jSv^ R"!JIIrrc`xıcdž#a,]s}1q^{cF#;>C X IDAT A8e[DuC[(.N8R)]]ޯKZ89[d>3_6t[|އl]\#Pqө+s}CfaAIdI+ U$$//е8O+8֜tuc{9 jLJwOq=;rŊ@qB׊j Ih8^c^!ŠbeYyK.UUU 1r1_urۖ7CN"X1eaZ ,]t׼jiu9 wQ'twbN! gWAB ooc̈́5/L ]ms`oCs)H#L̬C-6BP-JiB*+?V|3Te2_\s|FRd!u(WE(Lt,;R? [Bճk W:cL]eIW(˲%Ǣ:aqN.;oV4q?'j>!%PHHIH'DQC_WAէv-q2$e"I6ۦ" {_MME?(R#Dl#p@K$N@ÆuTq]QW !Sg*;sw²T"ذc5v1M"I$bGTDD  Sf?Nv$gNygΜ2yw*%I2ꗒٯvZ2dW^VL2[8?70 d'Vo 糦WYKoorX[]^6eRmLql'zTn]L^e^ǗGcVJ-0sJX]u]9Uy\ M[^ ´*JoV` .`oױ#Zrvih3ؑ_nD!֭u ]쳫QpSB55غu~ee_-@^NaXIT{EF p,XTՉ$$??wD<' dIRXڽPРoBP~?P "b83[Й~ea:'T+msO9J>F(1F0Ǫ@/ϧ2N :sj|tVκ:A#λT9> N㘜q;nEx ;?]2Dx2ϼJ5ax,&Y&hjj*E帢’[O&FěU/͞gs԰kyn}7v0!KSNL!ĴZpzO0!#YPWbv]t/tm$d2B~GT&0 q\/Ȋr?{%B>ز+EQ8N8y(@)!*ʒbu)-#FW6sFM; yXh)ܡ4>4iԝ[dJdY_ _^U{SN͝E>R}gjg76ԽW2, OH3OlQ5. 4Ȗh*Йǩu u̗ fϤâTw0hɒ.rL?MLMh!};^ZfcU? J!䎻.",}? =߉umpA@֣,jɝzѥE4ށLyEߥ_Q;tF!Y/-qj^|1qFG ɽ[@i|ukڶD{\PtM!r60RSڝ;w&I5ݻ#~v8Jigg3n=H,8\jeUk6`K_f3-{iB+SaS}6VP=H m'SXTt4$À^!wk[N'Ix$77k ,q$I^,1BaXA`YVR ʉh*&,w/p'u:HŮݚnTrMV Sͅ]{tUGNo>ڀweݫmAc"^vx,gV㑞2I Ruf - 'ݱlBx 5>۝e_0OR/S.S+YɅPxOP~JMa{]Qr]wB.,"Bp̙1B c\!{Z{5;/Ll+W,2̶PB֮])xAD&*>-;T2q\ .//[r'N`˃1! o@_ݳ,[ڧd,˪oѼ#:(v*--yOHe)9 LnZ'Ib8NR@槙L&UFBdԍ#/k'MW_8Uk6E{^F`@͸(k&}Ww6ʉ=xR$_4VnJ"]`*x`K$}PHTZYQeyfT,X!F 秢D<~2ޝu_;,fܑ-#d8Y #XvϲW03z.._~`'kQ}7oѮ=`^pXcE&y\5MV6[)g=zZOE2>vU'iMՓ<͹CڅМDj\aY'#:h[L+l6}s0W_C?z@NE!4K(Z eQ Jð =-O~}իj׭aӜZ!p8ikk>LBz#?eY#^%4)Dillb9e9 qI$I bH$hw/H+/-1ƣeY^z5777WWWG"n|,0qƙ9a@xf1!Oՙq2Exkf|:,`=Էy(+f!P8eM@Dq,(,ʲ$˩h0?'u$)/G42.ˬ1&sum.+ٗ$j4!q]X:֡vPc\< xhj 3앸BN_0]cfjq?\փ0ADQToMMͲ,o۶kwUZg?۬B֭a 9ѬR4 m/H^Yd kcuD9=/7 𥳐0 XZhbPyQ)IJ2:l$A)%,wnaӄN/{/];$':CϥqvĄH fLv-SSz:`r4yOFϋ6oOЫ/CAnV ꌴIIePa^m+!J9T/B)CuyJVS\E= '4]'Ez,ˤIs=]d딚yUwWbk{ˆw$JzUYW嶵474زe+B l)i eVCh4ޱiӦŔ*Dz8A*8{SoV͗O ,! ]഼eTE^SpM6 xWq\IiviWg~re֭q#8/(,,.)U˕hd/LFx (p(ўJ`cSS)gmѮ@0E ]/ظqcGG0Jd\Û?kߋ*ƍՃǴ !uS|cu~sQ$I$IHgN5T7R#-Jx'ֶ9|~\xҔQ57=ֆ&5X-e09"qYaYtI#GOl8Z~邾eEcFbյM~NHG6-i_ӸOV|ti$B0A.̂ܶbg>ҵiލ0uRA=yZ{c.1} Z3h`XI T83tP<ύbzUpASJJ !B }**ʚ[.4wvvE"')ָć"\(xg"HvXhn@^4{)|8"5E }EQXք+^e7S0eڡ@0CfqQqII^9E^a(JE^^@q& ByBƈɲqJu1 njjb& W|MWgf!Ϟ<tZʼBB"18f}"Bd*ڱc۴g@uxPsX-NB7:4g@[z_\|΄!U{MO>g9u0 P2)I*-)?qJQq5`o,A^)̊VHeX.m4in_ko?W<-' 4%-Pitn] W?F My] /V+q50P*!Ilڇ.mJTNSڰRJa 3ʝ&o/gz#4SYdNE"YߑGN.RHFp$tGd2ŻߠG>Q_|("dvJ3)3=Rz *]]BCQ cѸDݘn<Pq81߻g-ؕ eVRXBL0>bc)E+YN7 j_Vo}ۺ?=1yWy?g3b ]mq˕PAعk>*nJ-1 q9AQCjo ,;ۢ)Y,o,!}2""Nzz!gߙ" b1 4 0jN ҽ3c_=3_L#bJiJԌ=`/OG?}cuD?scuwjO׵4gٕvJijƋ-|] ƞix mo:Ap=QPC-:+龘UK"앹n_3X9OA ɕkFdIݘ 4 (!DOS`yB [,ec-T=_oOBT(qcȲq?pNSJ1D̂#>*ɼI]~?=ͭr)HOjo(Жyqb6,.jJௗO+ @Mϟ[?Hq18N>x\hth\~ݧo%mayI $49"ɦ.6TqAt-ܻDd3KuP}eq;nCoߕĥ 7䪧n˵mR~<91tQLn^Wg/}o,``uPP`}ffG W^RWF IDAT|~c9g0?UZ; ԥAV^J+3{Ajkk &5Odrlҩ1BE'_r광5|4.`F0)jF׶c>lP\Z,b0FI\nG.+c)kw"e a!I_:2vA5\q}T~u#61ڴޫG:B]ckJȒ 0ȵ~,œ>!U.\,򪲊#O+W^(=,kK}*Tگz~ÿ6)C}R lDS`kM]BqM.tPؑH(r"Jf@2+z$R9A%E p793o!qKXQ14wlm% HI&)|iq ꞞKM_)@qy<% O9cJ"}r $ 0? οOnVfecF! V0!TQB ఌGEGOYd,{ț3KOw" M,`Y6%ʊTJEYVdY}ffIJ,˲< *8K&.ݱ>=4ŧԹt"^E9a_uߵ[zaiLmhw3j BBXꎳӊ9Ndv'߿9ctK/[/o?8NC\54H("*ЯzYYiC}`YYd2(釙K͟$Iq?.ȥg<̑k_]eջ^O_@ Kgm[ʿLrǞsGsث U!@l^󏼺}} +<󮿝2 >ʙx*:# J7?=~v|=X-H9ꟽNBWMܣ& aRK_~9#Dڢ̏tNC$:`MJOrQ=;;ϿwPD=|7( :=7;6O듊h$1_$*9OV3뙗W㒚98vKWF}٬-P4g1$7,sS>cڰc?ѣg̸ /{iQ`=s`ΣVy}'}۵4}wzMw,\ Y9JqyU U=7i% eǞ29>DEW?wߣ+R\s︂11k)4X7(3 QgYۯzYdEYdCx` ft֕I)8c@RJUs'0oXe $IGFzӺS[ 'Ϻ!8$7nܸg7CG>_i>0Grr ( >/F"`n_&&P3Mb~͗3QsШGVxX%dDi^쀍[qYRJ `<$:Ȟ}[?6<*p365ν$n9,#}xsp>-F=! QRLJ K(1grѠ B%z9,4үNS-rPqRTޔB_xËxZpZ-?;en#Q=O , b iF`0(Q$HGv)j=`+&}}WϮ7q_9յ-ED~E֍kۋ8[׽20^p'_r_\l>ʍRĽoy }%hO|!y׊oxU}-zF_PÁ7xp.˅Q1~S yΫ-"27m F@,,h[b]3"e~)a/~y TLEۺ7A|Ɉ)y]16G@zi:cK6U;Ӗ][JL!lQ[/<"7oGO uUT)jhLD۾ +kjrV1c 9u^{͉7xNܾbq1=*N}e&H,41BLMwëuri0eCy][@AhE9f>%4)8EQ0mAހUYdE?"`";XG/z7 RbXzcseYv7,!y[`gjx@]Ħ$Sk Fo>';o/o<L8Js;ح6ڢF}>mO/2X:q~aS{AM4 ՙႤ'3d] d[tyL:[dGK6Q+FŴ$Qkgz~n 7VY]%U6ӌyAb\$Q).< 0xGqWIæV\/ϙ:'4z#Ogv.{桷h nmQ(< бS?*j\Pe:3е?&-_ӵCQDlzpEÿ51W8{W7L-]WڲIDߔ =zZ.$uSk'w =[}S14JPfH֤1>O`燯L,FdK?#ϺHk||aXqr *c~wT?[zՅ C@t;">NtAĠ˿<֗G]=}#.f)\VY$t~^”˨Gno|Ҵx","2``(BTS`YAekKz)'wvv&II_967Ne crOEr"ֺ:צ\)JmY TR+}򗼏{g}/:!77Ұj꯾4MؼϪ+"9eY)FbZNY]_Kl"jڧ^u4])@z Z~iH  D/LN%Mw^|h{}NXTsJ""(\=$CČ-gќAG]vۉܺm@7k~wBA,жl*yO CǟlHHqzH 9B`l~vv(aLRE;飹ۏu_W0EqPP'dgҤ bë, վkO> [6N9sŕjݴd/N1r &_1t^_L" ]˞n%V1%R wm;kƅ~X-׮;vhH߷-?;(m3fdiv'#VF|1]v!Ts漿nOVc͚<њ5k3ds%z?VI BҜ7_~~}1p`g; !(ug#u[.]q!CJae,Q2lH:80^IO{2~d  *riWP%oj%9X,pH[eg`I6sz8K LD1+3}lI{ejtV/:Ik~3^ܙ΀ 4QTkM&C@>TUFP/:(ڕ3HmBBuW' a,!J 6vkSW1n/1C! "Bjn[[{8`8*獾;2`GGg8b^PYVgU4~/JqQMumwA4M@(^Ȣ BX@J0=Mm-X;GbMliNQObE*}[67SҶ4ԧ4~3 V~%G_qCxul40@7z[c*chS_}wwJɱLwv}03.~6Qqg s|6%eፉR`yGQk!]vjbet{0@l1$Z/oQo"[+Bn#SJ>Ue }AJ?c^8 ,],pRφ .h]w` zsҿ\ȷI@1 βW?Ihr[P=Ǥhe-N,K̽6> Ͻ {bڵv ^~Qe / ;_vyH* a@XCdO|# b79iZ)4vno?ncQlUf|m^U Lr?Z38g !g1:IaPXf5k{l A<ltsK]va4p10Boe}/xqܵswY_nKvm'(j,p˼te}$!uBp Թ,}PZ>0 4Fqw<ͯiSie>8~euW]s59YXk\kv֦ 0 lcLgY@p!47at^raP0Iƭ1*.B4="):!kMRPtY6? 4~3/?Τsh(E4JAѝpa3VT ϽrcWuڣ&M7oM_QƄavx'eF'Q cD),^Yj^]?\71vp)@eDZׯҊoyPV[]~y4˻g?šv[֮ca.y/Gt8Ͳ94raS'_yopuH^aqɃtHڿNtXJ}W9qA =3~stm]ypr&R8o3Qi[;+O8oҧw.WʩWm̮m6qΕWt U4-]Y{ x rXAT~/))S5xd,^ҳ͙s }Ma\ЃjN77@~#AW>@ܾM d0R7 u6 *y]Zq΍8^=kLOz(\>}g:^BrJ&Uofy$;'."&]uyBչ'||5Inڴ[B( iZ7!+cVw'Z[3MgWNił)YY1l^" вYFE <̑\ݴ+㪓9>S*3$DQ=GpJ3E IDATcοԑ %4νOXq7o8gC_>~S5(}y?4/o|no*iq{#H) Ƿm2j'N@ŝr2)sNU.d)}17Cܲt d9@?6)$׶`xqGpU1%Ƥ7򦛏n>b92QYq [)g3,P!W቏(iH_3)"p,唬v t[TR!!$)ʤ)b ̽m>BWx>@ygYX}'2,K)e ][wAfԙ`NJ&ݶ!L|邊39(ʪv?l1i ,zDu3SqwE~[HɻJ>vY֪֍iy =qZ>n2}J?9+^Q?cvZ%|J TBƇU;] 6wގQQkksK?XL>~\ {K`1%]Ν.w-v̲l;+LJP\tympӺs1ʯH^1s<#]"508ØQX'77_i\ʉi,ݝ`\) &8ҶskEl%0W^`g8ƌuZ!ee1o]Z9 p}.P!W!CtFtUufHLT &VZ}cDjzH}clC֯i;c8F`n5 SƳ7y}wR+.Nc,&TyuaAR ,B`c(gH?.M;:yðRN[t#r&+UdaUS9&*43DZL0^@T_ž}F" ſm뗀RTS1U,t{a^i0$qMee}ڸQ!B(ڹs-DSQLmذVF9ERRY0'`ϧcAd];Sx ty{+ZŬ.a| 5a3Q)YNIFZ7},Fme6ƍ{GM\:n5`\֕X(+rl;FܭFZ~a͎M>Bd qNڽgo&LHӔC挚6O~+ew 3FL*̲~s97{MsÜe <iAR)_p ]EQLlgضC#47y^0 3l+]";Kf/̐ϻ:q|K[iYEuaΟx/߲h4!T(*.閽D62-Y2jඵb wyش9{Df$`aQU]t@&,z a|ήpMu>/R\uJ×v!H{g|~#xmz@dQT0 пUk+]Q~ ʸq>-2ҙ<})e1Iքa!mmSxy3}1w '_p_[%>i͚iDu. 5DrrQi7z`T:I27$DX:ƭ5XZ,= ,m|^%!ۜ k߮\(*) L0o&B R$?=Wym;kK}xe`T0 Ý0HrXV?pmBJ߄~.|6*7>Cy1CBCSl1 Å_>Bݾ9P}s%1'@2 u ˂PN),5t[]f˞ai6T V{e;0]`aDbL0X}cL&1 5WqBT+)e{X4 ִp4F6Ym)icO]Mqj}^/?"&Witw3uN,xV./L}>QZhQ =d YG`I8od %mT鯞\sμMNJ`^[YpK(")(cʀPJ>CSjo쐆[ c0BG1D G_3-䗇;׭odRRa&ucl|~ߜ5wW(9+mIq=zs7=[ܷ/9:)f8=MՃSDۿ1у#5VY=8=RRɁNxBeaaNnbs󘶖Vl[SyeHwf9R@P]E.}JYd<W^v Ƙe0CbA@(Ɣ"ddNTu/6иeΩ&LruWRdc-eܯfoMb]"pxgŏ第CN=c4? ]9:cngf>Ip ͚;꜓h7ONLz$^ Y+̑/<g2jOSoPѡW~̿]Fs啓r@vMy#&y.?n$daj+]4C T~{&o ֿ:`eUpPUC0uB_YD,_40_`S'㉲ CjY-:IS&%>_ƫI5}e#oY FN^y"K~q8a͘K O`^^E.suzkEy3>c]5jFSJAC->AeO-|#A F,8q Xb2XKdƈ#з25 J *)TQPI&BeB% U*&m kw|zt&ԃTE!F&@ugJc wBul{9 Qv e쥺 ;yxTg -kf)0w;Nn̨l^ý7 ơ9@cx Jj @(:!ql_ݽ*3VZm}}?wgGGZo"Ҽlm@4K0/RJcVQ?beuB+':ss4 u4vA(8KTEUUEQUEEEMAFReifM9 ]MWbۗw^~7]oWo^pfZJʗ*vs?61վ~gvv3K] !q꩛iǏ'߯"+,J$qEQ !!"c1@4k$HL(1tI NL\utG?YdEnE7"I!e)Iz gSFU}96\\(*F)$ ADÃIT.PNUo^uMc$:De SOL/Ch/>p 8I˞|(i@K2}oW13մn~8 '7]_r f9pvD|;*sB%< ecTBrB¬m' E/Z^^ n&, 7 ݚpieECxZ3nJaF"krDf:`K<"Z=Cpnu!+JÝHS؈3 i`? nZ/Dwo"؋Mwl !tSfM=i QX+ ;iy[Eqn'ݭx* IcM<aUY;\&(R!89&ɬh)ĬTNn70MVwB!;nsn6/制?,qM5sݻ 8?djeg"Ұ#-!e47׻w! wz:/{WϦJп*oT_vp9_ @!@.T:09Q$(xx i2d Y6(uJ).Jv2NEC۾\VkXJ~$*~<>'q7Bv#K_G~QSW\໣w rZ[2u~fFHkk<51,%eSGvCϞn[Q7;` GYʓeaͿV\'b*2bJ !HLp`چ U<ˡ Ѹ KSH#׹LI'SJ2RsNdfx-P5l>'&HhM'0SJ[3w?wێ;?C1azk[ JP۵`M˦HĕGkeʶn  |H2>*S'W=tܴFO^S>frjʩr_͋f~T5I1eR!sʁ!\d"if]Pc V+BǎG z" TS++֖KdfG9w ( ZjG*E9\Sw]|YG q^mX16p0k$T26_fmƼ?g B)3Q:t%ã@ u p}y!B&Q$>ȅ4,&WKB)-]V6S>E҉JDZӌiHQ%C`K3FA"r409BpG+)fbXE=qLvH:| VpvYc+9/?a#JK!d qB2ASIH@jcch|sާJKkG?|[M5;e4!6~*9fUz{.ݱxf{jviŬ'f)A] Ru#-S:K2I.~8ֶx(Jʻ^km^᫞:S{\;5=}ލ_uzxl[L A(B0Jf4z'ʅȜ>!w8pEΞ=wu>FZc0t-C O:}f[[M<ۄr)>IRkss4ZV^qzְ%zɢFOiq sdUEj{xxxxlJ=//HFϲ(!vC="EvE8p %5E ֆk**|(RI0x"'Sf2m($Ȳ$1 )&OML MA3鮸jDfZ9-M絝v±5~+2$d_IQ&jJba|>׳գnV {꭭)g>T|ܶvlǍk"m5a]. 3UY1Ksjh9@0;"AY)Ѭi<&/x~g}&kֱwH-)" IDATę^tORᮩO(5wRIM) ãB)!PA H@Woǁw"^P{e˗U`띷mr8)KXyg ErfgA}G?pH$"ہۅ nԿ{6 ~yh[`r 93m1BpiiksSK;4y[|l'PPZYY:$ؾU׹,yPp@Dp6,5/),SA*K4 i01)#U},KDR@(''S" W\ K :TaAʶ 6q季enٔyS=h[i/ᛚ#+ZaԌ/vʪiJTp\ZY]ZS7n*o/] ݼ㎟yG6kN.;lec6c߻i9L*Zi1k/hhed\0T؉ɹ: &h 4$1*1tIK*$mw}c.@f6-aQJ!у4dŒ麉H(Uʤf*Ӟ+^Zkd%X;R}ken}awv|˵Rn߫ ۍyp=tPc'ʷ0ۭ+Xe#ߵjӳ#1)\R:e}-Qdq`{g'Yգ5q!ZOJ& ᜤJC,6h%a*nFZ3S)#ׁФ[ L)p.L"JsĈQ`2КJT"P_"cց"ʯ~`IGtp'`4~.{1𯻟^߷>TefdΏ36Ԃs0塯0cϾ7~*83k4tG >28 ş՟vѮ/XUJ][@a&0:́%8G_Ԩf2"L6o6nRJߒVs.C?f2oMN˜9&ҺudzNhSմ4IIfh꥓OmN{gN ^7+lu^Თtǭ.57= ˣ/(sPB3'dE^HtekYGnEM^׿=+f:2&gWƏܡOPhh͔uReⴾo<ٷ=].ϲL 0=1~l~DaI<W_o^\e(pku=sGByw+wEgZã@hͽI# #nHRNZTCui#ד&O$HSH_$ljMH}*!1%fPBac)-)Ljaߗ⸩<sKB;}\4',L-~ϧ|㇇(׾pOq?i !DD~ w-&-ՁzW^bP_ؽhd?g?YؠN5tʋjG?3Y&v`WFsp>e`|:Vm1|!"ݶסB~2:{ۓF孋Vqټb }!h|Fct[nGė^O=qک3sPTm[̒$Ib Xs0 FӴ+:XS^IޞMlATTB;ČZկBPCAvESSYSD@WZƆTRo6B"jL-4D9> 8A** +ys%` )X={ tD.8F%s*_;ISE !( $p®bXJS9f5_Y:i_fʌT$k]Lظ|}2[ Ԗˤx{;B0CJw@~k𫫏 RŘ TE-\=}Em_mg $clrPF2.-n}8iz޾+>[oRs\{Kq3[ڎ.w؀Myxxxxl[H&Sv,XuA~0`ƍ-<цOfEHK jCqMh22$H$~ɲ5}7,ݰ|MtcFTl jWX+՟=U=<<<<~X!Ŵ!j(P|r"߰1n_sdVzyӦiC7,а) PP}&$!ݦ5&"o䛼Oh&h")eP00HJc}pIR閉qtԫ958sr,sVgDdG@Ҿͅ q8fya4[/gc A;Qp6нfGCʄi^e6MP ҩ6>IvAX ;mri[/>jh{,9翿؝kʉڸhyK;Br÷oQb xqO{'zkFIbK/~MNOJhJ,T5:̮j!q<~4lڸMw4 R~wk1*}l9U5ґH~/X׿\OIS0>))u]'K$ldTD}t2BegK(Õ0UHN"&^eWg;Y9z$*kac~IO}m%D#]TE9kCpܯ(e o B} |u-_>9ƨl b3}_c^_2IT(ZdY&=pѱ#%E7>U S=ʣ`M֪̏nuE~YGe1K5u]n07sv$ -vq8熡ǢFqW3fv)3?GYfc=)%vì?: ytm8REQ:k+ylx5nɾhnb^`\7dݜV^VD2 /odejRƹ%zii  2jxBLFLSU'-@ִX1K(eSSɤi@4W)\ oA,WKvwhw>f=d ] =-A*ƑoqzeG,*r/Uv=J~ OP`ӭ:ln6ys97u4 0a}2esMEJb{\ty'|(H,1\8rM Mm4M۰nU0<#ҩ|/F۸|Ç8U5p: ! HB΅Ns|^ [9R_~H$dHUTUUUUdYQYQ.I${m筯ILd:&1c2(!R*)Y#猏@  5r(6t6w745,M7,UH55** 2tڲI%I2Mz hѢuk׭\мb񐱃aMZ0 *&9`T ` ) TAL9EC;T⹁{Ų U+{CX̰3;VgJ|_H؉д4htrb zIց6uT ؽ<_yxxxxvbsf#qR(#D`I`s(L4ǮI $LȀɅ4R:R -76&1|ؔ){Li TW5 K*** :zR&I@@UQ++*`i8rPR֊W; 6lڬ #E+x[ `C2"d> "Z!Zs%3ΙRaE^sLnїɄBgGկzvq`$Inw,ZU*uhM E},IK+#m{|5u:6"f$F04]O&@ Pƚ4Ufm$OƏ;hָ=pJ<ն~#:2([$W'.]:Һqu+_QFAp!QTe#mmj7y W+Ӑ;-{nNɯjYyAN#NebKyxxЭ^A&k $XB@s(a:Fι'#Ərp}W}#9]MN:[wo>7 ьyGfHFt%M82O{r٫wՀ.;_]ǺY@ 0JJLBj*dR $2%(ՅT"e͌P>wPN=7z[d2I)I&(Jf똊,ﯪJ;֬XKaBɀu"h sA!@ !55Əq޷Kb "G* &A`>2 \֯`"7u[l/a/P,{qVWܪlbd-vzK3B4=<<$?O Gu~3[LJI4?hkS+ 0#2f)QT:$B$JVʘ/4V IDAT 4( {\g2>HPXmuU𼵜%U"q %UiBQⰝny :lN9x+ؐ؋:.hhi[x늎l;p=<< P; E64,:^<;URmmAC&8/Ͽ"}֙[a3=<<<<@ƆM7lе0I5nKu ڱ]~-/XԊ:aTIcQj>Ƌw (\כ9z+w3BT'TU dGK$@;x$ VJ57&tcwᱍ(⯄H`ܸ19 0 FA#$M.)~]dHX gT̔pii $ՕBA&e|L@BH,_:i @8 d 4Ұ(PJ~IQ$ך[0tJ ŷysZ5uty)ڈKMUHu^ҕדض (SŦ 2µ'@Jf)a|tͿ{{l<<<<<7E 'ɡFTTU+lF$Һ~][4:``wF J [f(YߋTcڳT/oL?">ros#iӟ{Cw,@"MA$r4Yu&;#MƔ 9w>ݯhܲFV3@Xϱ@Iꓙ"C O5 TeMM-5@ed$1(uMɻN 7-8'(KZ זT 4SƆeP*A/ɊS2 ΃PJ$Ü,Yst?+:}tpU!@(Ul qc/1ֽuٕߴllPnf].iz*®zu~'=zJqAA@s= B3xms,|L^M.ZDOA@Q)Hq`yxxxl=r3Ee^K0gw~q<f&LHsc|Z6yI~1,]4AGU3F ]ZQ(-֔sH*ּ.kUMMB7l.S-ա;Eֻ\] ]K!-qםn3/XVd֛!SPв Y,,m.bt4DRȖ"ɲl~ǵgu}TU-H0M3Lv鴮@`5YVTKJ)e3E6ZХt"Bx5{]y>ڛ3|oϙG`srI'H, \U}+V<3f>l"˲^Hw uwʹ=X74#|>̹i4bK6tMT0R @D er C%P3ICDud]>>\eB2lHce6YWB(FpcXU' iwPE ֚Vh-9Wox!n Gv>G8iΜ|ߚ'x"4`kk,3Ƙ$0$I'N2c,It@hfK5,hFWЗXZkM7ɥ>;~$'gjGzBAu7,\Wa+B_Nr.cµvMr16r;`k !u=L @q 0M@nS%vN$1֒jiT{ߗ"H}>yom1B(!J)l!*ׁV:HvΓml]T8bhٕ#w(#'|R7l +|ɲ'|O4JDK!D4 #OAn'|/P @@M@}B_")CĠq݌4G٬,׳m ,O|}93ͫqe_dƓuwx.CIyLL5M C+kn 757˲$ˊ$1ITbJQF,!ŅB$F%dIA+KqchͺPmE h,۴uQ%Shq c[;~]ekdK9ɿCteg{$0D253d\ #tOqf/{̟0 0I)2w,Hɲyy۫t*_ ZWsm} M➥l֭0[)ȀgE*+*%,qMD(>+q0654?~g8~X] !B *zF>E,T`B=VW*B]"})]X=TJsn!DQמ%R:}{{#CiBHW!19?(H(=%9벾WYwNDуY+ nl9KzP*U pɧtsk=<<<0~ igH~밃-///!2JP$Je>(1Rf1eU`>b"Pty)hQqЕ~u />=+/zd~|]r%S+g\Uǜ">]Jnkţ>ފ8N棫w7x_?p__^4KO7t>w?qIG^qy6xOi e.9ӎD! )jIŒx\KimybS|u~y~*;"TB )eRIRJ1J ⤡B@DSsWU nj0czlZJ[dA覯' .$_Ѹ3p+>T;q@JFu"Ka˼\wJBf&H e].9 Zmf8Њ& M$Y%IVB4 ]YNM -N8xmAD˱1 $Ir$`q{JHҌb(`1],J]JyFGAZӂKFM{gG7#mٲT1f!UKs>㘑J%EȲNIGL-w4J[wR]гWoxjK?a7xLWW^ꈙOڙkLq˗ 8Kv);Oӯey};rι+m&~ۙuO=}Ĝg^=f߃{c[G*AA!0bue U?\3fO߶m` 蜍mǕw+0I=o5NZr.oH"^]mĝF!wZOUUYdCuDH$Fܯa d\x<DL$pPpqAӴͪ9Et(آO=*Qq`E& "1h7<W_أev.=ۀmR3yG;>ۭ֖ߧa_ii*D5* {愉-ך4qNcUv/wř9*K, B&H -9# 6|{A6``!$B (jy'uW=3;$}ޙ_Qp#!xSAiph}XGOJGVV;@CǗᦒɃcrYj7*dZAtk9E /p5;t㶻Z7m9vCky?}[low_~ Q娉YZؖyA?j8'B haBxJ2-4ohy5ss@ &\xm>}= JgM?y9+~yuI2Zwם[~?Xqѝ]DI^;VZvz/(|uvJD"T2Dt28ݥM1IʢÚmZ1m*>,QزucAeYaZ7\vJUYIAgg 'VtU.dx, "vw5 (5%#*ΜNP5<Э^'t+N@fsyku1tQL S*e9- 7aokx&)J. pDc1VFyUyHsNc=~H7D'޷Ϡ՗/:v@thYV o"H$^vl;vhii!TUcȾ=ˆ lD"vKyxdx**a[/q]m˹!DU GMGa_sҼ@ +2D-WƘAdx;\uGʢ7? ~ߵ_=f|5JQTW50/CO)R3'N&֖crvF>hNAmP(t@H10"#ˋp3"69)qx/_: ؾٕ IDATM4,9(PEQ"n6HIRnV [`U¡TҴbG֣y*Jb-F4=?^]}* . ,/4] XBqZ;,jN(Q4? #o]Pa{W] Ζ#z+:Ij9KxjWN5ʵ`%H1N'ZN&{ QBu]dQU5O BN9DB}iǫuu1}'q|,zg/%4i2@*|tBB(&k.Vֻ\{]/H$0rteRZZVX_\xB½Dƞt/)B qS\Q* }YHgJߢhKk;A#T${.:ϔ!O|}9uw$3qgaYIZU$I~ѽ{v389pf=+zeO8JåA4N%tPBHhBjxQ ZS80|%IItqJȂ'"]۷Sή7爴PX$ut*\>W`^)Ym˱hOڛ]a{ݢOH#9[}TԗuH}1vo!5gOu%F$C\MFvsږD"HL*Ji~Aa[ksr !3CQQ(%[3{m0,t~J]uaHjv2 #a3F 0EhQWCnN3`>A蔧zKNZ".f C%||ԁ$DII)8&{3q; M)pp M [Ms~eoޔ!Dr2`0֚|yBN~!GQEl~BsFP3B £rfaRP@*C!7t螸r8! F%Dr| :;;stLqbz,Si5!(/L'8rD$.l2%(4ZbQԴtE_Y5bgFD[L >1tWtj"C]B[xI`K@Kmf}'HR9^꺞V? {FD1J糗8S3);}јusޏ'Jvywbp n~unHX' ESB(H$'3-fT!Ng?HHڵ! Jqd 0 X1yBX+8(:bٻ'H$ys>xR< Rh~ 9 h܏LG93[xDK9P{55( K[[oSBӮBz*uڻAyL3W΍>0݉\ʗs] 8#!$-BFMKH$(mIщܔJiSλ>sɔ{}%E_L+s:C뺶N( D",}BN'˄@owh  ~1  f$ P!ā+#ZzQH$iIM\J(Q5 D`%Б3.]!Nv9A8mMG8T5 T ԰o9!sɓ)u<\̈́*aװa295lʕmó8ҫwU<]"vvv?"2z9UU{]US>0߶OܓɔzO?_Lgh`l5w|xPV!H$O' atrnCTX)|̾Roۗ@v%5F`OAQ,=eD"9` փU>xC H9 sdc:' @QUXHm \ v病 T)>*jn&IN=mEb԰\v[-/S nsjp-Qsǁ= !t&rѿVG,G8]]]yyy |h,ֻ/Er a}mtqb,n>;c8yPtVͧweO`+b7òD"|]9r;H i1,FXD\ED*!@H 1CݗobVJ$/("_9GB@5=;@ghBA!E@UF  E".]OD-,j\ A^Y/?>4dܠ+yrD FIVږW9|)H[\qйt̳uz~Bwq,2D$}DX,\H$`}>QG|>.+ Xk'G=W|11yg\^e:x D"d? 0*ă{jBGjBj+1  5i quld#؉4 y$D11{QBU0z-~; 6D I babH \meȵZCC 1DrbAG*pVB |ثEwKb,2)Rŧ€Lh,?`KB("D/>}Ό/dli2B4HrjRvB{0?B@ʚPJ8knS)+ӈ c1s,뵀E) Ý^]xCu,P5MO$7%˟&`=PjZm1!i8}͍ 7H$ɉ@]Ƶu0(汮绐: bZ!VzU { R%-G˯EVvvfɸ=1H0 K*ή.·E .,Hxʂ )q|>_c̜ʣB(@%pg2,\dkYP"H>“Ӂ aDrN!H$ "E(~s-DvFvJܓU jě͒ 3%5fKYGȘA)=rJC3fKuя!0 [D_+b1UUQEQD"a"~棔fD"qt;}_A/f4}JҲe9s֋Z D"|\ֶR3%Æ +)-s5;!;Αo?7D"|Bq9>i;1 sm(*uLzVP]&a0 31&≦i\dQJo5gVW+A鍻qR\1'>/K/aJhն M\mgVD"9@ݻwLexQwzB/T:;ӣI* ] *oy*JJ[[[x@hlXPPFcqƘg+[sIJ^22S& ]g:O B(WDف:J1xQaB(H$'1nD--ZL)e'ls8?kVdEyJH$ɧ$9m+㯠X%u)בdV7~+G,1-).IYa XLG+-(_Wmܶ:-ZLXX,&a؛ҘK$9LnLqk8ˆGXïzBYE1v0\lM,YP"H>Ft:|8! Q烇 ٶu^5H$ɧ kP2T@N(l܊,heA\ %Mǖc!IYjϞ=sw1gΜA=c܁а\Qb.ƘaeQr;"5!(!h"?)lٲӦMc%Z[ ͲƛYP"HN0p81 A B^}`(p\SBD"|@tO`hk6SqBrfAEFJJ( Q4BUhT(U񨨄P(@(HVNrd #3h nБ d:2!7"íK߫YqPt [!DLۖۙף >zmKmZ./mz\!l81J)cl޽cǎUUUX2EfC QlӦM3`Q"C)e=uM7ٺ;&DrfB R" )]"H$2u8}h%"5 J\<+Ύv&(r (gۉ3)sJ)Gΐ3P 'D8 oBBfpd 9C@-Vu #m\<Շ=4}PBȔ?N? {j˖-/d~/o_國<\މaEs˾7W>B4ͅ1cXSSS~~~,w vZg:5,gBwusՏk_lʱv2BLyV"c'mSrl%%ۂ'p QQ:~a⋝/^tuۖ=Li:rXCa_l`ie+Vڹb+6o:rVޗn3Qf;}>SnjCڲjEw~oYMD?O<-{cB)#G 9nXh7Q,N2D"HNr\K=]++ !H$ɧb+w@wa@#GB 'G$1Ba DU0(_ZN('B:_ƎԂej[QVkK'H$8:,9(^K.PUZfa̶Mq0!Dh=0m4g2xNH+̗;InsijW[fqaK 4udQy.uޚ?+pg~Ƭ~K<_j9gʱillٿݻĒF 8h@P(Q00q4)@xCdYu] +׬߮Kv\xX/}rT;jC;v{,/_2oAqqϮz4-//g>غyiCf_0H$(eԽӭz<됦-I<5^mD"Ľ4qfVq'}H )`I$S[I}  U8GB8vE8#` _^򫗟1@ (pҡwjZAh4Pܲsc}muuDbce`k?cf,G来Xx PjSsa3tiwڣ!%k4,x\zlvkк7SJ Wz#)ہE0aWVν`~۷owoW^{۶o=zԓ"n&">?}{ϻ]# IDATp0ֿnᄑcƜ2i)3gLٻhee٪VLk_Y)#z#666}9w~k[{x<ƘA|yywzKKKkolauG{[2-O˫͙}Ν۟F~ؤ V3)S{:8. ;LHӡH1лohh_Ͽ^{a|J!~ل 8XNXw}OgGߢwꚻ+Nd޶[Uڦ ֛n_8/\7^]T}E~~h`&̮~0¾ O<>n^|ߚ~"jq4ÁmtFNy$䓃nBC^"H$O$;Y,BΑ$sʑc;;<~蒒SJKys7|m~Ł!-&1uDH$'W}<G;3"ꆾuۡ*OH!ܲ,qΑ#r@zY(4[taXB\ZC#Kw]qOD.^c:_ν`>"~c5gn̋ͅeͦg8c?bkw u bN.34 ]lh+--on=="S{ګ۾cǚV:˫ 0٬C_~i\B@}p N[E`0'@XI_[Y+_w"rC͈#hW{K0j:T^V>~uuu-xeȠ!v].[l!xH7"b4X\}O钋/#|nY>/7>Y'iC-_wޖ<{}t^䔻Q"H$'!⚔zM ޜ2g Oq/y'&8s**]-6dx  k&v81]$*@)F1]w(;h|_C>|!wY]L;Ϗno|ᢝo8K;Wq?bdוPE$8&z1%0`=UQ^Q~֬ާB=29. ]5cD۶]ի]3 . -\_sWK77eAK"H$:wU zK"H$rl"ec^CQ5RK)E õ]OQ!@s,V6p _[S|䈒~Y_PH$]J5 mfNh0 D9uEb/}R93X*+nμQ3JKI)>G;] Ks<8 ðzٯ BA?!fsnCr| JdULfT^0e)+K ;:]3nnB&95>Ş Xk_^W,?ḿMJgg׿ @SOˎXBmk9z|JNK(7w-켬z!"tvvԌ5Gp [S&Ov5_3x8+~Mѐ+_^ݸѣwq_(++[W". : Xd!ⴝk+D"8Oۄ$ 1L"H$O/gBORH#!sZ~z@6D"yyM:@ Rԑ+KGZ~xp!nh #\hC,7wa}d87zD3ISl]f 1OWR,*))`Y"0GDri1%(BxO1*k$5x*h-G;egk,ٝє*hE, e_S X @a5r("!)Y4k4aףLXO2lob'"?_}/7w L=$ At#l䇯=5k]vvv X 7l Bx@- z!BȼW|X|GU~+7m۴eKyYyyYq:WUƂr7mSuCc_y+"g1Ec;j_}uy6{_O)B>SJiJyQ&XUM)`a|Cus# a`>4"b-_f``:)YL1gbgza 8fKJ Ff8̽`ƍ~(1k7O:잹J#ш(ϘKljݙtʔ/<T}}kU\t\D 7y('"Zt٢;5 B#Sն.iO?EW~'kSc_,;^F⺗ xJkL(UO0ѧiw>|Xٗ͘Ylي߾6>tޥ-؋:(ˇ)[~.UN;˗n[amyGqi/|zƛc,69?TY>`Ra*S]pLŒԗhB(5YP D~-L^z'7ns޹gYgڝ}V93T5+yqYΜi9o={ |A"H$D5FOa!ǨxP'9ٹP!5:6Th^1gD"Pćp7xҐ-uͭG4F<oo]zͶ¥Ck׋L? sƄz%,S8S`!SQrcDR`a81O|`'j%SN4``  rJrs !HTP!vW;?ςvdǍu1ց_0|B:VGZחM8![ͯzZZZ֎5rŚUU#N٧Koƙۿg>~Aθaxs^$p8ܻmyW _lS>ƾ/^3ko[>1hj444uXIiH}E@׿CF{{ho~ଢp>crj'S^YFc2A?ҟ]3;|"?#}fb%NalmK\B|+%ч- X6l]w׾RTTTWql|!h*<Q]]ϵW_yu˱e_v)Ǎ߾kgWsoUQf:GkC ~CJ9cQ"),.=;^c{?(+}sE@ `eze]Q6IA4'=s7nܨ }MCns 7?G-5jCJK/:BnО,[ &V g*I+=伨+W "q`:vιp գT6^cD"rGĥé^U/̮&Rj?wue1{>u5&;$o_s/tY?|p;DsGD"H$'% 1 TWC!EZB~RXX~78s3.7氡z׵i2+ZfzP(UUUQ ])BlR\TSHb@wzLPs]Wa٪w:x ێu_\y8gsm'M}+t֛n -kuwn+Xtզrob`09[Z0aiIao]3 mg"l ѲkoʅEƧӟlp`I$D"H$B켏f*$'y! 뺞uBp@nDZMWU!ByIhc[ǂS d禺  ,jU^wⲊPeeV!-%%rzEYÆ"gLLEIBVU=cGP#sj 3*CT$ Б܆R%\48*q""6G̿ZH RE>VDsW,!XT*+19kEb:RJ"#  ÈD"^z)ځ|VJh3ϮGhϑ^0աP(۱5?!Cn惇466YdM"G@AGvu T.[{|s̓?R9=|قEd B4R*'Ar7w~fO9w_=7~z[)fq[oSK֯޲o?67tϡO+m='\y zyg Ɣ%:Dʊ><բ"UUE /{ѫ 'a%_WR-ލu!۽k₫WpEK -ږ+dL:sht8J1>iE QG;J?_>$K| 8]I$D"H$sL)Qd I2Ru|iN68~͸>U 0|c{[? =H0fL--U YwpxX/6u<E}Y| uм|Ql!?^|c^9 y4/>Zh> ,%XR ي':t_ %8sZ,ӻ:}pkɈ<ג` Qג%ԶGu%4-#$D"H$^$ۨB!Sgz[C7i„2|>s<RhmkK揫 F,Gh)Чa¸ɍk=p^ 꺺80y\c ⃞9vaK*SI-@C!)قݘmap^<0glZxKR"X 9z䊶K){]!Y4-/~g_//[`q~_4 /iS/t~eEE8]#5W)SOENk%R!1/wrB)/|{ϙ?)SsY7w 0 -g H$4M}K_LS3fk.w_3ڈ/^2Z;/ure˪.[…ı7Ѹ;ͯ@tiZAAAIi). J_xB!eC`f_ #p+JUE!y2o̓phS+AKv[9(R3gz׳q\K$t\q_r"oh?/hF҈-OX"`Uzٌʗ7rӿzʤ!QV<ഊgꆅ7hc]3pJcL9skW^6R״=x`#y, ?o{? [7xᇏj\t,"rD{٥z<6v̘,him}wúgu;;wJJJg*x}k?/1JHZBpiXG IDATXx<߼QΜ=?9gu0h4jjv[(.v[lP}cEg|zH$*>a_pB42Ww.^Dg .D O/i XB%|V>RJ5U}TYY @1-{ʡF~_L&\WvD*#Bh q$g{𙮱 W}ӿvtc\dInBGn8/%caD~$YpM=!h~ ɏSv~$J-I~0`010 0^XvtW(}Ji)\ےP(J8;å.]fŌ駞2WD<Fch$}~{b?u~>HtttC0*~gƠ򼿿wuu=zGE޽3D(ήSPpWMCei9AJ>6E:tTщy 7?~[sIMιY&8R~OԠ{n\{^]>Mo=t(* e %]aQO:[,H rBw}*8\8\E٦+ۇ%9L?&WuϾWɧ]/nu{Z^Uzb Ezk%Ʉy~9ǔˎӻr1ͮ֏K?*ܚHJ,| ?EoMN$P\Vz{IOI %@-]D,`%}H0ypпm=sAԶ_~Pis:n"P8 r[b':c$ :tP~傱!?M[+ϛ1Xv"KIX睽tL6@ ]ӚGX,ҏoO_J ,Ԓ[qIg]k-&`|E,ar"gڪ AJ4 9Dt&;')(J B/U޳qQ`pQ uH \0 U.2$s#@WouATHvDBc9+>lo/o>vѴÇqaZ̿+~敃W[uтBEQ{(0Aqnٲu-$Cca„_L;i/BD8(wgʑB׍Ɩ b1G U[VX?O M"r ASJ 1ϳ V~My\M"ط:ll3[K-Y-˒\? 5PBhB(L &4wܱ1wY%۲ݝۻۓd>?)ξ3y- _;Eez#JԼ{15 kek4F(I?@joq.=W]/>bWœ1%--=5Oinl{k_ObA2@[]'cS f̩{ՏPzSSjxt;)׏Cz}; ' |l`|FSBxM_cv״!fUK9L.j/\_;4yBY:/p5Bu{ZvTygRBG(r2323XZΈ0 xA8.2vxk3Gp'h9yA8F%a+@Q`B)P(B`1QJ1F@z[ !iQ@jY`YHnj6Սnu,jxEsӗtH`RV"RUj;%eeeG]&0fZ64`z9f'lx`(F`  ~ivK՜A[85 a(1`ivtՄ^|]֭yY3;tQHTc@gWYU{N;{h& o4#pÈi'Ǡj}kOῶ罵Ծ(ކ~g_w^k[V;> :}o6}NX @Ce!S 4m(9ۊY b+tR$!-^pV:Bv=55nɲX cnQ2F)!Du⊐X.b!nKL9;C7=Ifպ{uO2B!H` v+ޅRB(8}< 45  XpBtw/qN3~zVfˢ$'b> CT ,%K+D$Ieph6Dy|-LT 4*Y+XcmNiXiSqdضqIDX<׌ )ehEB~˧9APic..^O]mWϸ űu"āJ1JG0aZqZzjlӺ}1%~9Y7$Z},m؊B05z#U`DA~x>y2D!B,ucBHX"~0P.py}?!`9a1{!–A*D10LQ$jjj!vfA%,u"^€PBkm™c r3J=3ŏu3CQZfz`<,\=ϼfF/^~KM\ewWz.-lkƭֆ. }퟇Fa_w4{pOs\棫Glny:/|b>[q5?ݝq0{sc$;,fL7zN]N1aR$bIÃxQ?BS ʀV[8B0J"a cbdD60J(aDR>`LL`s`0po.Lt4`7xC*3ƕ$mq\3x `;",$yY`61FEQ !a(D V8-N])PB՜N @82, *EI7W cjX?eOoݘp4FO,8a-4qm8D!@B#0 .o'n ICH }~ K.\CsJ4BH$qČA+eцK}Ż" =J>v=_/<[ {#[8|b ڽGH_]cz546U`1VOjISSSaaW":,A^P E0R7P0C,j_2BM %{ZWLmǑӆi;! ZZ >Z}`p[cC09:-e[P; +&bq<8.F҈*) 1v wݗe @Z,GH^;V/,Uy@ T/hW _yoZ)T>ڏ/Ƅ3VZ{Eom#!FW_ho` ,X` QPkrSO=ql2ZU7܇-`) B$I` >½;._toH0%  e# nz^" jo_Vwdy#oR`@>ѧ۔* >Z_1`lXC}2鄀eiq@QacQ}zGXX]tRಏRK tHK6=y5 ׶ ҏRK|m !P>~W{ ﭗweāthGw}'RyH10C:i/ }x7]'tnw1c ,X` ~ p~뛞|9/Qcޅ[+ PRDN1#՘XGtzdR,zo߾7yr="L:s(x0ޫ~;kӛnn˲Bkl=̊zk ?:poa9zp ¸q}*&Mrjg9X$ y eQ3, 2} L%zDF_񮑝cpd25( vVΛ>r3s]Nth_B"AoF՝>eYnmk'pTIC=m.c@Sw 8OJvD[` ,X`'csa`z*cB |>^9^xu:AXZ5@LuRxb2@ۏI+=0-M{ccsshר6Ha*#dˊ|;B/ @~QTVP.4&OAl @sAQuC-C>VO3 5cyvSkF*KJ2cAa10h|0FunsЮ̯(YVjwc̙h/`ZNcH44m(JKs I$u[c ,X` 6Ǽy>? TSfqY-4&|Dj>QͱLPb_۞ s z\[q!aO81 tg姬?6&++Id1#;YUw?bX7U^;0E_Q2MSV3Xak}qxŦ#Llai"c!ҒRFYTL{ -t&]D$wsFL-Hqg{uVƚb$2SгgnzzFjjJKKkSScMуGpuRֳgn߾E)UVV>|D rsrr;·zs! & ,X`)y c#,j'ncOQO7X`1?R/7~^_cl_E7Wt1*MT'B3+J룔G&zDF PBXTc/_c{h6֯(0 pr:ii~Ņǚ[j)غ/*ζ;U>K%W0L l3e'+2^ ץt%FȄ2~&=|\|\b4{('5!h IDATв1'{UU]UqѷoA~q}c$g̘h`0G3@BAs& ]Q:'w &io{> N8,F>ה{5_3<מ|ү^82 8,*}#~lOMɭM>ɢ$i|DIo qYH7J_@q utK 4`h=VTe`1W(u9k M_[2s KIv6_cs/ܶm23:`抡8DzG`5]yR9Eͽwy{֬Y1QJjЅRJ(A}M߼MՇT*Y57n4cJ0]UQdAǍl uŨƎ1A&Ll Ym6iaD 9/bO߸w e_<aߎC5J|}R"abJ 8(2ڷcOK<ҺqbɴAv;ࡷld:_*_zSIY7-وHW̾l(߼Unxb,e~6is7=x2uï\;RիÚ{MC%'&ᔐr[d초:xw{iv$¢A8~[1o++_?}k7<_NxpeɃYpq BW럧'5.[\6| ,X`ƈ1QSU^ugep%5 G6b0{h44##1Al .bk&N?zdc9NS jF^>_Mnwф` 9q2oDw̸;AQ3dtKP?a" TcT/Ff(UU.*(*88ɇlY)E} *V}g S47r'k^͹hIT Tk̙ja#c,]Z`I;3ב|r[3ƀ<0éV(o.#`{Wώzv?W5EœepYsFĜn4O*˲ުs1P/Ϟ]b&[x#`T $Ya afs!*D(964UIRCE*~$u#(:m`&C3%%JU'i&*DBA)$SENL x> #Z~qP 0VAY&L9aF /`@J\Ҙ$NQ9'X{4_ARg3nYpaJ)mf k5ͥhJjtPK sڼ ln``#` f*A12l1_3lk3{<~s;CNIs@v[q2Sڷko@D *8]2ӱZJɨ.kDY!;6 BAœn  ans<|#"2-BA&"7xbWϺI\vǗ1K$tv:vwӰp+ bky%-kԅOBAyϷ06fYN9o䇏% pф$HꑌHɥ-X`o9B &(!aX #g%1b@؊o؊ivEo>cE))e{M=c@TC0eLv9p|R4=ۿh]{#E~ˉxUz#[5viڹY ,͍ H8d2445.^t+5OW)t.s'+|;@wю :{U^yrXfjokMJNiokh5cqu _IY6J 90^zts@Nr}ZWo}NnN P`L7 ɑsssjԨ0Zb,c4gn͑x蟗굷|+WλhڀT_a\|HnntB 3+ b*R+~sѴ4!Ըc;wc1_:O~ݗ[x3tz.]퟽}ψ삛/v^>_YԾ;]-JoyΡ@gޜ P-~4^.k㺕1ŅnVY"U+9_4w m듿fSf>{S~A5|޻xWG<3y˦>~"Y_Gu#19ŎB=߂ ,pQB(!cpgxXU'X%2RWD-QG .T 0$##(j/8Hed9t!Jٱڶ6UWS E} њK($v܈6Қ&TP 8,cc. DR|W>CFqHa1Yd;b>}\-/*j p9}}nt/Z>CKkչ >;JpXDe1J,+gO|U,8 p \$I3%I!"# @B(.SrI7 (N1ֹ:+_1Ա @^l 6yP{s5ٺwf[rK=!B,lQ _LMa{[ :{ww%PTjwlkIX2bm=ؽ(6n1oښ1xy7]'[ggBȾmmrzS͡+z9-UOi nx,$9&A&f,Hj]¦>w:mܻ &\ڝݾ 3ttW^W8o#2f`Thٷ2&ߥ3 =K?]#}ܬ1euq6 XLg~N%K꨾r}1ԲL3*aږ1"+HP0PͼSZs?9eȈwI;{rxgՈ)3r9Eq#cq< $s6ѥÒT TQf &;w 2Rס^pC״co*TsX:WlI{nܸcAyaC5 ""drV5ɠYK9]}̐ẘe~k'zE@wt(8t}W˭.r* Y'f+Tm9z4YÉ$k m6N$org O]]6Lcv#&bW @>VϜV=Yи%8ՙDlC ,X`BGbxo ;|M;7o?@52BŢ, ;R]e!`N$)mQe~ŸR֠6+"dRDP8+B/wܸѪ<6]2,`fi m6PmZsBqQ(t|!Qu#ptC^@({鬉) o}ؑ>塧,6W.~+;r}ΘћfC_E*tƟy]~ =-ȞWn˚f!U{(M3~@ 0t+6E<ɭR<8# w"Xէ?aAX si>zz})12cKlݴ2G)ؓڎ+3.(}ƜÇi^Ҥ%7~^-CaY4=ClM3W*CX5qC" m)5=6\Jj-.{SBe%A۲.1v?##C?SjLFґNuL.Z{E"{z?2'm則 iq1˃ X&w= w2pteg־$Fg%%*>d3.5=|~Mn~ U>aw[rC8yܕ2Na̘YI=<mQYotSf ݱh{p>SN\hZKvyQԾ=дczۜ?"q[\V<ܞB˂ ,yՄ=l(E,&qjB7<2F!JJ}}e]OSO,l`GFP[Y8|SGU!');# 4wNjT#NS6^}G W@ ֙4HQ3k>'( J(3Bԥn]K).5u{:V/a(b2@H[_ μgg[ I&иna q-Q0.rX`x\Y{:oGDw9x{ 0F5z)0Wv9o/~E,`6kkۦ2Cg'.nR++~T!xQ|Ἣ?A<œ?}|#T65ȍD$W~i犍͔!bh؆Pvwޝk\nƭ[ >? B(k`Q/ޥڇO͟4pH)s2C6 ZV.{5#o'\`Ov &,X`118_7t+&a48=.cS]].Yԩ 3%8;?ciőz%JWWh"J@G+RKժ*7f Xk[X @a*=YiPc s* 'a"c@1Jko]]2!4{=T(L1"{}'Vo="6﬜{%ygeZQE߲g5DUGaKorQ,QcIkN=#+Fu9B=TSJBPO 2md=Pk|C=ֶG]YGB]:qPR1S >w ɨ[yN.ж; ?{-T0h<#JPs!zwM{S]|ɠQ;&6]5&;ɼElPˍSLH iI>ΞlhiQ0'(m Xq깹snĆyҽ!QlnH@7?Mk?-0 6棶` ~P+#3q LO|b6L'bzWʈl松g lZ!ǎN#-ة+Ht(RUƐV1vX`f' guT-&-8IhC] cw6!,i$ֵBhM#-Fdp:Rn6D39ְVξ!l666\BBcqH`&xMQV#`ÆbQR΃VȐUxٽw mT_vpF!c`@F|:jHJiæԮ[s_JGǦׄ2l=UΟ;ǤY氂hsɻ{kݽ;%V%F0xխo:G_zEIiL. 4oФ/vI@9&%N1/Nz_5ιQ%:kO钵v[яLWNb//Q%>@N5!1'j}j~Uu1u=r- p"oxfs/+t|b[`JH]8w ` ~(bͯoNYtrԿkFT+$]5wU}ڬ_y% Fg LlAalՑ#IgF#P .#J%1oc'RG<5F i'V|c, p „&m}6Z}ADL0"eꗎ5imuY'>t8= 7݃W۠{}/,綋NO|<|s_W01Z-Z4K%110Ƙ0j?^}͵˗P2 V BB#R*V)-H[M"&3"!mVuHsmjjRY%Y$YdI^Ȓ,ˌV :dԨcƌ3fԘ1#G1biPJ}~CCcLa_~iMO+2$?=́P` xOyN0ow2!tQo|ЎD$P$}/-)/6ޫfK9dP͗z >n{זo*\;a;nϖTIa^ő?pH[qw!i=p7i~5ї&U(Qh >ZW FaZVE4ny13GOptZBIe?珏!Pvoee)Qm?x XPԓCqƃbGRŪ'ǷңDCK2srRK}/#4dJ? ҮUvηk~ c1BlK|rο[kCBV*'c1ut7@]MGIѸΙ6lKGsuW_xɵsB^C!ߍAP(7aRK_YeWcLܺ JΖco)! i(rE #`p[?r˿,`D"9+  UՏҠDb*1xޭQ,X`n[D6QDQyAxa~Pdyu>oʍ<  q&L//"hQb2~eHJHB%NIU`aʎtD";GcccNzXcu"0R#1T@ z.`z]lmh[oY9>ጾ9m <K`e?wamZiSaiwy{ŗ b q1F1 X{(!g^^'DuZ*Qu}Jp TbTE+֌f|Ҩ ~r$8+ lc#caT؈I9-l[i.8;_KW2hD m~(%_Z<偙c,L cynhj fln{LBJRd0X'O^h99а*Ǐn$-;%04pI!-lU,b%1*TRjX3"Vn&o5")2!B(PBD9VUu_?yv8C;) "M@BeBlߙlI 6s=w9b~Z (_54K29 WjRI Ve%Db=]/6R%;[KY#V|UJEEEEE%ն寇QH!( u?:Z*|! m@K1A [XzL(NG >I^>Jr hF޽ "Z  a$#`!UU_I!JZ3N:D ! CwڭiެY3^stNV꿧>qqq o,J-PlXGu+$ov\np:=t:= [gݳ{S rPQ˚7;G9_6+ ˪^_7L45BQ[#ז_uTTTt(*Ax# ROA V07IhmL4pgw+ML)dH'[se+o"L2Sx Q7rЗ QĠF:MQ+i>_DCV5@?+E~c_Vi \ےM[nY4ۘ!"3hHJ9tЁ}%I: &?:%fpܒNص "?m/]xw&gMUR]HOQ$IAp\}/?Dx⽑ZyJ9Y !&?#Z .ښŻ!A5{ɺ}FǙWJX$D+TEF 53WMer&iq> Cv# BD/5"w !CKjj()Y &Bo y-8,̺uqׯ9s"+nx0[KJ8nin7[Fo߶ɧz.NHI{䔹6kc3f̘1cxx-kEooUr9Քxem6;9nٳq&huz^v5@y$*\EEEEEEEEEEEEEo WwG8xIY{UV͢Zt<P%UA|Նe)_'&!OAL3СJ`yK)P/‚*h4{'0ƒS rcǎmֲYڵ@FrnuC>{Ʈ9S6l9r{ZPJ:}Ģ5!_ni6K>7ka cY+FikV]JHLRnP 9/=w^hG%BxaTb.TP P妢M{!J|նIbw')ȓ)B[m#T*+xHTHJYX!~Oʧڵ1"I^W;s.'U-"l^G7f *1(I^JQA%rCJ-&-[q/n假 \'"[/DQEy@cr;u{Dt\O4*$IaNNhLJ0-_\nbC?*+JIh hҒ,wW_ٺu];wWNْLy 8S88rMg Rt:=׹,'[R$#qF^-߮J8p༹sF;oVfBȷ|wddfQʩiUTTTT cs64ou-RQQQQQ,s6o#WaOV%Fm\Y6<Ip(ũ, !XATQ$&JnrҘ^?!ϒ0/O!bAшUP!G4q " m/3QJ}O>f94A)e#yHw=cB&;CQJח#ʡHI .zX#v9+;GƪӾc۷\vaTTTTTT!F)V䔫DD/X1Dlj?7$W(ɯbeRc1onߦCKҁC,ZJ cd2(;dzEg/@K!TdyP~lNO!)߮%WyMT[22;{%c68vAFɩU^EEEEEZA$ȡrm߄8J@&FФi8o%JJ/c!@(*,Y> %D&{izdñLQBCP+"E×+UKvZǏEnzеCJVPhO0@.en,8D!ߗ]嚄P#CUTTTTTrr3E7LII$QmC)MII|:뼽QpQ? NUEDQAEQU-wU[XBx~WM~Ez|1e3/f뗱,3oDڥU~6YwbYwMSrɧ2 +V3g|og]F=2sJb?s-[,=…͛7ŗlVkRTjv 2C@k2(dVKLꓒ F@N[敩$M ɩ9eLBvr=rY0C;Aʑ;402$pu \DKY7/𻾈Uv'\k J!2u3餧K_vlf}}g>=y{5it3S̋ymݴ,^6+w6= Vk̞7=9?mރ—o9%GշS#޻Mqoߏ9zQ=4էSl[F=Y!AfШ#Gn}j!HγqJV.+DQgϧ5Ss>Y{!5\??R Yي8c}Ǿ5ϧNNNlRdʕgϞ7oުU+7ia4^:wV7{l%뾟:iO8GV.dyUBɺwѬ.-zcF%EѰ$f뗱l{iW+D|\k=UQ̔\x~4Si5 .~76N3q*5or(BeuH1$B="9).CON3D %0Tf = }QBGs5.HX~utagc%K=z3)Wΰ-Z tnDZ,HlٯgsןN .i0e".wvA~]ŏ?qWCXۂS9t&"ƨV_bl޼y XnmdXaZ{&NlժUkWq gp.^~;w:K/*>zJBfvfa\'T ~١wjhޯTW r6fE wؚG FÌ?|{G6Lb8 m\J۴\9lzl@Ѿw {&o͍9>L/+D3/PD_k=UQha7޸/i4lf:I7i$ISZR +0wݝ|%x*po3^w|ktxOIk󧿜҂;njo~]·neEO}6Wg?Yߞ_(\mӖ+W J,߷\oh8:0H%K=j{Nwyyzv{vz[as'? !#XޥQ.T~p+oln`,UtК>4Sm вsʼnZ}J1riFN}Os7ϿFI?'/6 "V‰]%RN~ݠ\W3?ﰶ@eC^"}0hQ) #SO~6P\ޞIwx֓SmM|?JudSYp+VFS\ Cќ'^?"ٓDDen{H ,崬lz?dٶ1ϭ:X#W Y,tgO<- Zq,lRW.CQsuqwu_|[yz~}ň.Q7vgh?wP[k}Z#AAEmwHR+A>%d}/$ ֭W%r7oӴBX#x@ .Qw+ )!Aw呈[b-xc^"(1K+]8x_w@A9:?ɓ(E=/K6;v:zHyڶ޵U2St`s<85rSrto+iez(75G][h:twϯ?ږEDY-ۤxd)M)k[3knw=_8(c*,;Hȝ .0Rwmղo˶{]wϲ2gKoWgl]۝qviL#QXϞ\8q̕-bI-+Y|JJÈk%#˖5ϯxX8 /aS3" ЫXcp(g[ f|qh=6„~wT;{jTg޳9 S豜ֹQ L~un jN*3 ԆAEOIK7u1RDPCk$EJ"%D>B'^]V㔬^:%""O8@#`%u<I{je`::R/#Sr~ro/6] Ah]Kb(1("G}aX^EtG?"ՔoW)ap!x=JoFF aF(8Vkq?3{wm} ֺP8oZj-x\jLלvֵC[o5Xuz{_ƈZšx&0YS@Lvb,^aRb$գ1騱nޞiltn X5wX";'jz<dhZ2W]ǎo=_q$w!.޺'3ϭ_Y|w0l""DDbm fe\Ŋs$Qи~Ep  vV{Z 8\rǑu !ȏ_?nZ@$ƺ;.}t*mo<֒6y&@+, B <Ӳ*PYφwcZHNXƭ,*ǙhF}㌻iNyޒĘ8uK]kY?"b+b8O)N8D 3R u\pSSa34aa6 .c&Il=篯M&sPY#2R>T-KYVfe?5&+`粥d ȋ"# 0#HZ^pN'qłJ@Dbq^*8 o I$x<$z< 1D$ WKu |+j}E`ywW]196! E((9֨}T9._߹iOJ4;DpTׯC7dff_^$Q%IjԨQMW^~ȆM&?:yǮ7jO=g}Z$9 Z$Iz&{*3&iOڤ|Np)CٟU M07Ęߥ_<:_ܻtz|:uѓa:G557' ŤS~ܳj{[Dߒeطje)n9k1Wo|5䎽/H!Ɯ\O8η?vҕ+N"1SCR(^qprKzze:Wo:jk\EiW<"̼:cd>`QG5K˞|[Ꞿ9;Wڬ[?V-Paש1O]X5k%:iYT7SW"TcZE] Z6\z@w_dl-Ztdvn7a(,_B >ճ mHy@tw "D1F(eq>GQbȈrB Hs̻'!.ܙ u1D 0b/woi{Wo.=7gݓ2Nu J^hWπ N ȴ]V'F6 }iPD8k%Չ;^.{ǔU8jOd;g]vy64o-^C}9ț9E;.?@X_k FX y[輈MyшMDZ`ͅAS#<AW@mp X()'rŇMhB A`ߐlnBXf$g?^6'7[%Mvv?qnΞ=xÇSSSgzԩ<_Mt@߿C{.]t CZfKLLnUZч8y·FhJݗ7L FNzs큓=m\[=|I)CY?vw޼{Mj:;'Ss'~Z. ' .gД {뾅6j3䅗nlhg-odrY&O:G/h{q|tܧV͝]wh-Ce-?U$9.М0m[y6oHsY|mo\RN0MraǿDr:'Vߖkw즼.8}QTZNMsЦ[$SVmѬ>c6}񗥺yüe0`r g;{ ʶm,`Xi~kM3Nˑ ZC{9 h"4.(~YU)Z3q^6~>kb)لN)`-ݐ4۶ekɍ~)5e%:=HгZtg[sS:> }Ce1]<> rzcu.۽r*Bf< wyq|)cLEB`U邧1L Dt9%/I4w2?G0 Go7h2`c/Q3j;8Q-a 0go^/3榷<֗1rmjRT^Fn[)o.0Nk{25?6XŎe貛m\wAqחÈ2-N Nd%rO]JєѠj=ji0\ߧV K8.!u^d=AD<4<"bZ9{+[$zvg|O"z(;eaR1:ph6oӊm~@Xμ.wیoG$99>J(coo#[2QQqsGyry;xH%Kzˍo?ݱrֺxiZYnle+G%PP?ϯʋקIWjᱮ-=Wzlp)c.t)w߉\F***} k 3f_5!$!!^NHBΟ3kn\߮CGÛY y.~7{;~rN4t#R>uψ}g#}гg;8 o1/fz:o} ‰?Z;T4v>+7?8򹋷%վc]n.rifì_T|buwgz{V,^㌓2:jۢTB׻'1-⣽|q= dٿN$jm>|@,ӼDqzrsG 2S:zJvXzi|B=nAo?Vpm}Y;f}gVk eо{D$?,yIMg~=wxiwo'݄ z<(0Ka<{ȼh<[~^tz Mo{-iPiBanaYTø[3Vs >q_kp$[U>L/ӟa ;xHmպM$R l}`^ cR YW)QyN0fh|;[jQ=ݩ-7}!7 iu:Vi5Vj5| nl?ύv[!:|F⮊5&`U|@?2̿_B&gcwGIehXs;ϯ߾ d%dPF?F"z r[ UqA8_t:]R]{?QF?~XRRAŸ6;w.++ڱsǜys{{e'/|qqq-,ϤXIb=2^#c?*'rߘQnnWky11ʐ.MKڧBh/+1Zq wŔUbl9/']&[kq^*kʘ$vN__{MrarOh,_{ O5;2cU-:$6]6ՓXšNtWaآNZo$eh!B6i%VKg.>`G>A!Mɗ@ժaPe/xVSo .\c22ͷxu={v߭vp:׮[?ed7BX# "ePD>)>RW0$("i#% "rlyBlX^zF$'%ۿHŷ>.7PBuRK[9K )iZu֮pH&-""0fw1"""dD8Qow1HB!*=I<ٛFBQ-) SMwHY*K`NBv/}}$Vry^_wsRTUL6nq\rr;A(++KNNiذsdddNX _STj9(JLthwrIkӦSDHB ""Q]A$F"%LBx056+;hyOJ<ܧ?`srpzhV*+G! wꆖrA-iC&f2DQtzA#Dy"olL%/!oէpeFv!92r! qS?{VyyߖM'رc.7;ssG$Iv*++=jϿr9@TCk Ɛ2dC,JHu`iqE P@P&TQ!C@ `l?7StVxщȴi !DdAB(!(* 5Re>ր"APW4!(m۶Uu I,:ac`s!*D*q\\bR欛>Pj0g0yKO6ę +4}G-Z8r$IpАsN:u)IӧtqVMرcNSu<ϻ\.- ;amvnE%4--rHm******WMWF !)IIѧu 2C@!dJ)%Dbp.h{U&mVZ@d҂ 6g|lĺ΁3w?LPD9K+i0C3==iVF I/5DhΕo]3bDm-Մf(pHswaCaSg ybd`lD/,/N|b*n/ϽQ)7ud0̢=$9`>Wһ]MJ #˕=C@Ytd\5uu|Ȳ!`vǥw={h/ǟ~[o?o6"&UV psouڬYqM7׿7Ó èu݋,0 }P8ICBP(vnG)( B1dt* ~fJ!9*Wۈ~kX2N3drB/K @@@28cFܽs硃m\UWՍ˖ 6ARd6 ㌝4=ucHiD9uD9jR`^ҳhUmm4G`/ 珂Rل['iXP(B> =@"<ľ3ՅDV__DM3toߗ!"aPqMc8r„7;fl"0 4M0|P(TSSqWԧ{DAD`?o2v0 @$ !WaN9BI4bf?HAױ&ِQ]G) iYV(r+\ x/dXE3,[uWH]#o$3"i:cٗietR!3㿓[TSR"x,D$]ە4]+{f-((>.yOd EX}QBɓS^t)(l&F}\nu]]׳w+˵?1_z{vYV+os<J"1W=Z4nn4pMEG6 HӰz !bGފB !cFː"uЈZgϚmXdӘ9s=%3p4pCW㰆Hg<5i=nDXpaHCF4 G1 *}O|l[*5 fvj=r1މ IDAT(B`XqJ?=K]}P0?7fU?1UKU?;w'?k%3gB!OqB|}YW_hϾvyS w{waybo}F }<tʖYeb(8ymRJ5*tP!M5d2^ Jw]EDzxst[ D5!1D"Ag($Bj|鏼MK\78dp"T(b'觩P( ⯆뺛7K%&N20tv:;;?q/oP "CC 83u Iu1#sN̟_t]mcO򝆁6ѵ #-/UUնTUU3ˮ %-4i]BƑ!"kHP꟏{fèS9);'zu hE~VTs y] ~Pܿ\a\pnƺЈ:S Uz%q[.J !:;;@ǯP3عsi.{QhƕN^s0M3D"D|G6otn=zT=RZ T_;@GGiVfѧR\3@J!KJvÿtid|Mϻ _4[E,ι{e۶q]7{a 'O1/uy`$tMlDuulـ>x4Ms]W[l("r u p~{#0HVzrK6ЦoVe+]Q= BP(ޡѦo Ui>aнwػgvB8(! B3V"l¬ B@8 1ɴa.$b:2ozu?ս::~ԛ.<88K)NkqD{V[ii-:'6F9'G b 3s渒AE׺EWE۵?EMϥ [J[gBD`YۿG: EեGSwV=^:xgzmsQ]q2m{CP_UUUP(N3<3g2ʕ/iқ/Ό뺎8bޜy?燋;?3 ظqo z˭ә}5J---1c 4aP; ys/'ضMDGo vS)•Rr=Q+:U&jGCl2X%RRƲy xBiez%$ IRP.۵"'YMOuʑ{riYv6ԻaV2l zVD" BPs`"}%|8&Mݾes3dJ!$|+IQYM\\[ƘgN!cȐЕDE 2eeےhȐaTO-=i0s(Z'y49Lf2 4dh3Bg.z=hFG7G}WէzQnQq')`b-pǝ3?zƐ`B䌜ӎɘS! йx.mkkrWA@RJ)%IID);v9~S27^U#kqW#ضmwO}nƍe;#rD\tM7vm^w2 8m۶eۖl۱,۶ϘwƏ~?{qG8"ia!L&H!o|3'YFRc̶m!w!TH9g\tN! w=-Z4KU:_輽5+g۶8?XZjs /Rz 1NzSʖ\bJH" ]{;?of'z- Bqps_*dP(o 0i $ollo;6rP)Jv!񜌴@;[qrA2bw \A:$.瞏õѱ9~8xnj$CGҙ̥_i6qfJv tB$I9WER@(&ڳo;mT/ڷҸD!|nU0- ]eodrYS̢h4DeyB+uN4M5o߼~ez15p>}zit:L&d2Jtرc)v C#h$#p$F#UUU}*L:32C4ZQ~jpl&)vlqɋK192q- C!ucXO9׀k> %6=հ h=f|^žuv]qȽƖ^c(c 2uuPM@G !Wضkډ+sXJB1$ e#h7MP(Â[[TU=V)E^lVNZ{)U4D H9  J245Mto믻ٹk>1L:s3?1qm麈VӅ K>69s\%qlUY r9ģۀ^?/RgX]W=C?q'[~G[6j ڟxh] MNnq^8y=6 +{mI #W?&t5_Xng]}?~bx{/~~'㈈a1ƳFh8=gW5;{6ugjgGg8<񾕗~?|bwMcWPh {V$[E%ˋPe N>'94%֨Wn;jRQR|% ފ~%Q%-rBQBP(xC V:8,B8(} +>F` r(k9cCU0ˌ^_#Q͇*c;s|c'3Ě*"B@:csJ#˞-^{6<ˬ]GIPI$j9PP) Bb8E|3%/Q-iX=q @ !cqW8!3D\a f] GRdǷ] iX:ޙb;20CP;LIBCTqU?}ݪPNuf ( s_?r_Ew[G켳up`NVant"I.οosmmq䑦ӱ}#.ɼꑏ~{N{ewSo|{K"K,@r?Ww0ś2e* sS,xwџEP(%\) ;P0O@Re+zm鯄O=X@ k+XdjD$ tΐ4#3FԚI B& }"kU.deC_^_y _6XUcv+_]K4ί~)΅g_ˋY):~_|+^ݒkx[;}c[K?w٢1 ⬲C~‚,)>*tI'GQ2B8I$h힅BP(~{m[$q!缺fYO QA 3 -td]b'DZfjBE&4*ZMH9q@D0ѺDƉ "Hk8<ϩa0G@4&-ȧ`xqjȳn=ygSpG?Vss5O؄K>6h#F}/j5~_>fCᨋ~1A~{'.>[kB ‹WIf?"G&*la|9|ןt2 2ue Ftq]ycO'H(?Ȑb g"?zi*JVsI/r`^f( [V?* B7/~:>gޘBp*طoW޵k-ߥ&dpX(d,=zH48c!׵ـ,]T:5 뎐L;q8wLеIɕ =RAD?taɑүŧ} VOח7v/[2o( LAK")PA\"Oya#MJ>rz01tEaLM&4q*vm>n%O3ɁX%zyD"ҥ`+Lb֞jpաSFؽ~V\3_a֘I+{kkEl–xa +jmڵ)ӹ&sCG3~ 9ˁ'brԭ5{ox'= BP(_4cI)p]8iʄW,ihZAHq IxZ(T,`)q~xMMm24MS5!DJq(лFnpC"ud:I[yXs e0,;h NV7/( VHX8/DcE|T$"Ԇ]/s-{ꧠʔUPAS , gPoGooh7jGCl2XN^C4ȃڻ݈ cx/7NqTw/Y Q7v+^t_e|u抺=*W=NW_5gkB8.}(6Mҥu>cbOUQ^Y b3ou#kó/QD/òV!B'[P( B8p7cnxM1!e>I !/~ePkR-`$Mj=zlFЏw:t08'K~RH"Bmۖ9NɖcVI4*<^X`*<@.rߥJ'ӏS r Oq1SJߟ^y-r5v5rITը*_-fcx,5{!՞{^c|ON 8mf] kLEWGJ/6&cEl^K/ OūTM:C_dYlt V>oo` [ݵ;l0z f):9ֲ+)>B:m^DK#9Loq^}(22ɏVBgp E2|Z$zycHl_n/YGVIjrHqK#YgFq366ḛNa ztKRqo<>@[QmX*Dgc㶟XTU2g i3-)֢P@,S$) B =s>4P5,IgܿoXu*_rXe~BqSom2s̰Γ8ĪY.gDDB%;IM2*z~Wt~XV=_ )T$֩0ӿ* v+V>[ "/RNYN49wͱRf|^žu,@tC:9cqE:aM_|Ԗ1V-`0N1zh}(ӜIaipm૩7 l{0$nuy#Ћ x_ô]xM.XY 9LBU^U.[N(H IDATY0{Qߊl|~}mw;JP)RmM'n2QdVc.|_@hXhʵ;DEmRrFrq[\=5Zʹld 'E$e31̶mBD]dQwLܳ]4W\ D$^\167u />5ttw;ꪘ[:L)6d !ajI *8kIߌy ܖlJsQ ~;k\HwRJ:;tGM8C8n_}sI52Mb:qa ۾r/WvPD;af$De's@9A8cٷ HHC,[X&B7 ;[5yˏw !ct}o.ONA|ѧ)_"◍ᕯnK­Qp5G-vY;~tRØ1͔2)!!c&H'oE5Ζ$`~$&1}YxCȋVІstYd\V>HÚb3 꽙쉢AWε.'U> %vbp (rV rݝ-Tua)&INHc8Cp./ə kQ,ȂȬl=ɖ.[Y;Hc&B$HD) B8E) @rMAC AD-ַo3j԰2tC8! g Vs[[ GȿUK1r?插ܱ讗'=i`9S-WFNWrB/EQFD _:-8\cuO/5,Owŝδp=ko]%Iyq8pg E ,y#f`⽀ {(tbl: ݛ^^wn^zb`TfsEׇֿ`'GvJ_Cv\b[6q'.\Xm.w r *BS͒Yi闚CI6d$3(C) #ۄ^R͢Dnx_wsJ8Zۢ-ܴ *l9ZIT`C\ ޲ĦtӴ 䊔gn88r-I*|c$9|IYyNVbݛmd5Jo@жOۖ WL{I6W]Q, F'ȴj1>,N^JBP( d@KRT WpVX%qR>pw~3mW慀IJe4jc?N#x3`k@, vaLzyقXУ B?)!"4TV $ $/}C\rt9Kq˗_{}K-wœ7sɝ[aD 8xKwͯ?bGo0asMzɼiGywKr:SP8QY%Ƕ:}yő{vO{̫~Izo$nuj5hrs.L֩{㙌$Mr0wǬLNn[IO\R\ip/^kmf},2(F:s6۟Ϝue&^9KnZb2/-1/Vޗ2Ntz 749㳑ކcr3 _l`5^-?f}!6>b'~NmYv|Fι=%wث:]R[FG|F#AoR%~+j-@tM'l?Z:4FDntXn~8t g>8ʼnbt힅BP( '#( G~pJS0IKyc`1zb~MW_/JZ%!{]c\fȬ>sO>rxђ RT)y06 9q~_a-Bgd*[48+84b0MٹIEH@")IJ!\IRR W/gg끭њani|<>rK[>aއ&kEVq#Ы6 Nɉ/*h.pu7my }~幚ƶտyCO#]/d}|z ":\ԴeYiҘMFENjO{ww5w}7-wgza4fg\{ֶ__9۰hC|ʐEB]%NZ3#HJD # i~ADBl\!iVLP,Yt+0t7zMtKī9zo῞zP(b"* BPd&/r p%v#T QUBMwmڼ`NK)uu 6(yMain<ʗbRRA4oe|_f%+ܲir]!?r};]O]Ҽ?/$<4 ,I\`483mڲX  # 6 5Цǿؿ{78~n>aV)IMSՏ_uVq<￰VE>37.<^zeD4d|שr ա'nybO@,BP( B1xzAZ>V)Nt^t_tSiWy*%o2XY8ZA4)# z_a@cn) .A0'xۋWh,(z[pme g/٨lfYJQҹK;}J_g<^FFuSA5uu??zi4m_,#aX0?{ukc+nFK;#z.m+G!#&h_"&n>iW7>uׯz Dz%" {?p-O0lƐB+Iwn~hq7<޳8Kl+MѯH]ȒH$/$ů\2~o9( BPdVB3*~;Bt~,1RR;F,Ӓ˼G{G3z-'yv9iJ AJ?ӋR5aW맮?sp-K=O];Q:\7yi\|sosϿމǟL:Փk8=tB2-l$!$+iw}Lf!'uN BP( ;/8 [ Q)'"`P)B^qXrR=*|U]UFA|VFlT%6^ԃEwSC-~źѳ0iX^_:&ݫha#;W/*C,Ko, BP(ZNX|+ɣ-QN*j rS zXOU2E*n\XA`$vXWGKʫ`eI4\2!At\_.$|+bw !1=B$r<9cB[zʲmGk9RJ=gVsD&\qMJ5HzFZpUˇ?ڱ翇p+FFp{a"4'{5+uܻ#<_jPD"ߍbm BP(At~E[4*/Ԍ>~G4Ɛs8깿uiyw9G!c1d!D@R$p%II$W#+]r A$+:~pt/@`RWIUbxkA) /v[T8)r ^K6+7 whqKs[ +ʈDDOC :ҳ@,/οCH$"ikX^_:jzSet 4YlT G޴*DuΓn*J)-MH =  ׏-0 Lq!Db]1+GZbjxmlMuد!mof8vjOX#@$mǎϚ0CI?f67} GёcPm3ۏWWW1 K GfDpm O3̾cr<@2ҪMW/ ;fX/\7ι![,YsP( BP(A0l"lXϘfV!c XP IdBJ΄$! @ƙ$92s$q]"խB I@H!$!T]$$I$3mFmO|dR@SR E:^k{$A@-*=ԣ増5CWsfrӕn+RHIBJF ;y9S>ueYTziӆf6makE _JΟmqlqu]ښ!)9 f.915}{S.'}sF*QAu5q]Ob2J:Y(+BP( B(B+Y&V8TL IDAT:B!+!"J&%CIRdLHL\! N:g!H 2r4DR# +/JJ) y7-TWșe ͪĻt  x+;jQ!P~c}wcE`DFN_\וRzq~o2qMx8badrLӿܲ?[mɴ|pݼ}/>I hݷ|/kNMr#~b ;sM\#郭ҙ$DDs!(AD@R~ᰖ5ksm!mጚטikJ`:Z~Dw?;.T?0zv uW:0t !r=~+N*JR( BP(|CDZVbZNŁ$8'IRHd ,BYqd t) šƑHiR$"8""2DBpt\A+z%<,7igyJZOYʪBTڸ{iГeU1k`iڶ81/0 M`D'NWusL>g\pG6^;MxbcؘU@H Ihkf4sjH3!uW:ԩ~< 8T>ծgiOR87t=5gMW.%I,(iif !b ہY:aԌ@C ZJ?9 SU_,BP( B84IV5F@ 1$)%"c(%1$!$DD9"=.bɂZPf n5dLz'%D~%$I%ds_3[7-Ҫ.jU[WLjģH+ 4 Uwm: ޾)whJO~Y=&DyWZϞ9Hf!D@4-t뺮'.ȯ3Ɛ1 z);vH+g$mj@(vBP( BqIdhT1Ғ$(%!D ΐ|M ͙`C= 8DA8U-% 5]gKǕBcR@ ݯ5K/øKKElQ]9Tp~6&imzL]]G_۴'Ͼ:P(pٲVWAiuC GC|6k=Y~kl$5IK OҖܢj56%0[42 T(.O熞uVG>?9P( BP T%H AXBHd`u>JSN>rbӎC'8g"9DdK!IS ] ! 0>$?4zIQ̘PySڿC'`%%HFIڜ'y9.sN_0&㣽s^g?O{LZGM|)miţ]o&C.Iq@9k?q2_xva]l}悅6o>TFҵ3E?>+_.LQD#A3<څq'w+>Ijrg6dń=i>pBP( C>٤1FH@$#)I`f.=p uӌ{|!)Sșٔ5yjŊBq $/V%6+_9Hso=~ )L,dҥ_y^09#x>nK/wt ܗ;]XW@fo|#+] ޳ߴXuѕA[dX\O]yDv5Dviv-?z5Soo~(KGcr(ܜSv p͗Kl[$;^3M<9bOXstq`wBP( bIRjD $M2U&t'l }ճDRGY.Y>{)g {ݽ:zXuI")R_/I)If$|$P`TxD7:WWvӻaߐD  =`J0bV- j*#շ&5 #ygQMUJgN>d VzBWsm|K].uܗ׸qg c%>0&%axĕ Fgޭ 4soLS cqa+֟7jl~ˣ.[~!{P =Q93Hqu1|0~O_~IMǿU>;sr|WvםCcFuL0aЮ]>r옃!<:}E2l|-},ĄKә~v,ӽ]_9`w YܡwǍ4}ۥsR-WZ^#tОucquƍ' |GzΞ~$ BP( ũ8d(}H 5h; p0KJB`ɉdzrJ&KF,۲wv|33N/mشs#bM:eŒws68{ USݕ "_ }SRHMDaEQ}FBQTj-bMmĺ$)CiGHX~=[Vzχ .!/(kew秾[a睴pf:w7,JB!'d8zsdֿE7}uzDDPl9H ġ ["L֤ B|ZPCk,{f,YE2 Qǧٳ=4ifm[-X(pօډn|Cu8ްHf=Ϟ4`}]vj_S.1V`UXH;j~(=ɴU!4S`/} ޺LP޾MpU{_eRfvԬYl_kC0-c@7[i8} MҤMΝBDg'=&rיVZtz'HڏzОvޛ[:hmp3E7ޖ_n}ɭ BP( ED{ZZYmf4ՐR2RRW>8YL Li3_{믹'>rcUPo98ѕ!rۣ{ͮ+.^#{ϖ«Sp+IBP( Bq$HM$ Y-9N2yiHJCKl߽E ΛظOlֳbDm2˜`2Y\=ڱiտ?uEv3 0nfՓᙸ(AK]tر -7Q10@s}VTj2 Oc$4y5y5t^vٖȌfgyX,rR[8z]kKZ}oJ*hkb%A !,iU>{uz)NjC `3WS)3e.6~S3.A7.'uBVHc*C9͔j&7qο[`h5j/{P6E(xݰdȇC^p]|${m-z7{pqɘwF,KjL9 kQ+8o8hG:, 'ώHIǝ:/]Ϝ`SB". BqơZ.\DDC[L܇$ CI4y$ʗmi4PY9Za5板׶<\0Xp슂9]unOUqv7{o='7?z~׏MC#")ɾySv ɧ0J ThPmT -*ZT)kc4ѡ$4Zzգ(0CyŸ>;g״CN*|1SwRV8Dޠ8e>:_*U lJ)NV_aSK 4 #ɌKw>a~@1KV+=:Go1.|{[͡ׯNL-ZwLde]-s:Gu$2@`p(ՙY[Uy%[sS'4a87춎i]'K-u`=wN ֶ_đZ ƍ$/vuCTrH,l-޸rR跙 vC6y&2qvG1{Ddkս~"#:Ia1w$D}|A;Il{cl=7eY^^%Gk*q lwAP(.0cPDqzDŽBRђ p~'gz\Qpww\;.|],v-?++u!Dj״m0L,/?xwxH_ "f>Q|$hANUQIFk=*Ѐe~A/:|,}+^J 쀹.#G䎧ܚԲE ή٩j v6t vg}TfwO~FqoȟxٛS_a \|wgo=эybXՅpK t]߷v>ȍ,%,pG^O\~v?cvSm#yS8$|A;‘'%h\g1BP( bZ- )3~pлudȦNumw;Q'C!{뺮y<_̲vex qGK,oOS :;!Қ q<0c8thb& E,jvz Ig sʭrSV b 3(ޜB|8/!}M={~j^CwH _C\;~!H NS<K_m(9"|''/niiiaa,B$rZ|۰nmR>\\3931dXB )!%TZ//`َaWx;ǯ쟏]'gΘ>sF߯N:3ʶw`2 a{eWT,2sf %xcBGٗsY)NHR\LRc\kV ïֳok5Tk~_COl()UEؑMMqH8 :l/j"Vy:2]Јa,weYr:n]yaGK_/<۽eFSrd=OiNz/Oq?>˃VP( B8-QI&"2`:'$""s|ihz(w]:Zn(_rgpMJOGHH" K&h/7WzeW\Çu9Ϋqc``%HvjҰF!I<~.i+4]IV{[Эh;AُoP|0ԫP\tL BP( b =~24 Q(z8 !AeLgG8ٶ,'X%ןlHCerJ'Oӥ '-?r\¹KWVK{lݾR7fGJٔS,Cutzz`s`C@V8 .)4Pjض2!"1dRtD $a6oQqb..he7no- 1ʿV<8/sMF IDATj\Mp]W4}3hK':W\P( BPm"F'oIDjȢCB]g15D_"yDe;*~J檆QJQ2brʶ(.qzz:KR wlǵ-Y1w%?^:@ h< F)6W׃`.mUlETjwǨ%9*kt)L ~bI=5]]bT\_iAF:8 ,d@z/㐦P( IR&=O@t4,Sۗᜏ#Dt_#bARC] AP!6 +UBDM)/!Bt]h4Ȑ‚O#M2 cBDžzqI eK>!hv FH@yc 4eƜzgSzJgG-lئ޼хFHH:j:V*h_5M?nPgU?"*j\e[`[S!.b~p_[HRdB+ B&D4RT݊SFq_hgҔ[ "\9zHInyDiMCԠ%Чq`(1Y$pt1{VﱔtE4؎5h?zm21s _J` Q_T.2u_ϔǨ@Dјhzm]:^iڛ"ZۂP f!l-(.iLW۝zcouܥ{壝*-*Ǝ8i?r]S( i+g0ƤJ-\"̖sfg(v՜wۓi"j A SiX Ÿa(3nºbjj%pF!q\D_BOJ^jewc2t(]8 =G^uSoWٕ}nɛYS޳;9gٳld P\O#i(Qw8 ˵I~AWvDu6YS%u)V2 EկMܷ3*9?tۙ2U,)e<;ib@`9!g[ B/4y\DDTKpNj#;v>BJyUƈ3*=1|A5PBJ"M$BI@cq@$ Cs>fZ腹=xɳm'|ǝ0gKLCƈH2aOݦns{nko)6NCc# /I@ 2HH-ȓ_%"Qj_QY+/V,QXװhPR|0A?ZYف؂9(viFYX"8Q!28 fhJR( )S'[HF‚I{PR>Y D亠!T( iqնH~K1Ұ1420C{ؐV5 c3N_%IA ]Ia)|B1. yhM$IrbᅗIw C&Ԙ:1B@~ʵKgtσ;o7RAѣ (E" @ӦM~4` HBxnK)<<֗A -/_5)%06f"45a>`YÜmKӊ ˖Z7wc~T㹕=+f!A)<Z) BqҠQ\xL5, VZ{2 ~mi" W_ 덮V W5YތF]5#!A@Kgtn<8H P()A# B6\3&ׇP\r+{)yk. c3?W/$$s!C BFLC{ʖƃx.u kqOD4G4ndZCoqiQjv"@ۏ(3J݇YmSW Z`0[T3h[ w.&@`{_o >S{2R BPD53g; #)ZhD=cd\C!ca$ &Q=pԛp6y$%]{n ŹK=*_ ֖#VDڶ68I*Pиӛl9^xyܷuxwbwD0inܗe+ ku}H:9d 6 .LFkCQSՐ^ب4E{vS=5C*׭4t8Wqa([γo_M*ܥmu|黾@P( Cfk?m\fUF׭!VZ{szFcf ]W{1A;u!ep(cVjtuQ("]y>M6qGtL +(ֱғ'#غҮWJ[_4yҥd.z U!%g-I$IADBiOT$ᦷTWE, aK.`:ɘu"TmT5omp4CI*ԕ](ǰqM' 28rmW( iB&y;6kF&sPD]eqDJkOFΙc8PՔ$[ތ&7$$4mChl řBothJ!l"iw2}{l_Y4 2\ѶW7xϮ-oP)"2]c5+ )%b9ER54|5 oRR=Cak%X[zC-ɘacd! l[r>ѦIAX5a㎑Fw's2H+PՇa:\9(%0=x !2`ҳ#3QʠP||0J>qX8ӗo- B4ճ˱p;k=7-qWB჈t]Zq V#zA_ˣQ%N)c{(mrsMG=07` o;ZDƐ1n0JMKU(5 @Dx׿eoК9!C`PY<5㎽?tG$J b ka&H5 A2 O>5I"NF!H!ݪ2n4։m[3rcH|E㾢QָwUm;/ S^hgkŃR75ߴc9-e] v: HЩxhRRM:^:g΅.\.b+O˥)JK1/L$s!HS]/~׶̕Mw;Y!cbK3,䜰})+HK/7=w,^ O_4 9ʇwwV#BW% -ߝnIVq1-]Cuu&0ڲa!5**)w\ v!g$b c횯P(< i$+֡bdy^W;^,Λ)Vv%c P  5qN]_yM|3GZ-q)koHD 5HJK! ]34`*18ՃŦ׭ ߅u}*ZmdD}aZ&'HMcpކkջ@H2S>zJ}s?'h.Sv1wwB>+R7596%Wtʽ418EXU3~myZsf?OSN.yw|"PEĶ?2$?}Ҭ/T бp}ߞ*rQ忕y"cg37ڗJX$9wwv#BA",zMc@\G2xRejLzc[%q&ͰJJzd%MP8*0Cu JB1vD3[d+zQv=#/O8dg↛{Ah$d8W 9)Cwgg~{ Td>hLUh#:XM5%&T2VS%IU&GVa`Z`ZV?3 W|4G0?<dV+o<sNHTص9Z;?N yFݞZy.NޔF ;$giw ?[)V+v|Jl'yU4' -؃]1{S%4 xG"}IKmXf:*!L6٭F-[?Nؔ[9 q.U[8\g.ʿݖ|v{Gxs%t^dCܶɻV.o+dlؑ]zkCqZnEx)y896?t̷KË2:u?Ɏ;LmߑNIXz{K3>^u4G+{uXkC"s,%2 9W#V{[cIZ5l?.]{R_A uAyUw}u/~ljILs$̱R)q'W%^zsy( .}8wэ ϸqJV_zWx07f31eMSk>?W~ u6c[’%"AȲc >2cZ}i芅x T0w"vLmG^펄]P< 8?f\MR㊛‚3Wܭc75MviuKW~c޾"4D>e+!ͯT)\p_{Oa{{@q>[2(ϡ?BYb|_Mc5"3FFWiW3 ҥ|)d}-ƙk*sPpI sD =7真ػ8#:o%wyǎI!j 1"Ij״L*%(bk$6$jsJТx&UQ ۱q!j4~Un7Zs$ 5m7EO}4?e>T3tfw{Lcqr'酜Rl9\0q%Xd'D$H kM`-2|rI'O5Hi.HO2aY4V(J2OuflNʔ;v^o-L6zKCa=>i6酜CЙ!-VPqҲI(v[̓7ZDv1ξ\ώ~ˎCt)7Vw'>-K$!e٥I Ilk޷=swMY'}4SQǧٳ NZY[=G +,dflwsiq2H: ciMٴIi+baj%O=;ˎ!erJWJX%J{=Ȫ&P@Hb|4tCטUtHf+֪k4Q_H^,<ڢc]W*SY8 j@.f5>η L\RՊr;\mnSBAK3>uc|8*=aոtzRSA:̻ BCh'RQ8&{Rki ~;ݳA&6kY:Sm^` KŦwqߚGτbG>f<]DxgH ޭpZWHN}3HKt8Si` +SvJa=`$CBfqz개1 9G BP($ņrBEhyG+ ft-חvo9ڳwpp|]C |$fW$$)][ OdR)s]9,n/sfIocl>`G玣{`IXC,s`K^m OyO:ٸPUA]a@J?1 #2e.6~S3׶1.`{@B, A)5BjX HNw[4ט\~&ؑoYc7~aϙ]z70> N @ԓ]8)@#wR9͔dِ :v e.K`ImhQL g\lC!MP%7rs/Ao,  BP( ýIw8Y/ʓ@j;s&TD c(ńI)BB!Sf9G,tXwb:!ծESTtꯃ98Ţ+COƔ@}S~hݡAJ_Sx==+Ͽ3`7J[_GEO;:s6X6{)O@DTn_57l~mj czx9N,ϧI莔32@`۸MU ӗt;[\syf#)::?LȖf.5  4صM'Į[t3a@P,Q]r9i9 eS 6FvKi!kkQՉ| t&5۴׹|u,="* IDAT-'v,û IXtxmh4q-&j,|G2l{bC#:ed|o\rnr"9-x${s F- BP(sdAM@;j>$9QΙ1@EA>_}ot,A ñRB$E 1L:1R:SzR&w QCԣTOkwKd8cP`ꍮ aauy5F5h)S_3]:O02s_7:=\ߑ8awĹ35ׯ̝K/u_ߪV:`=)w䳇5i Né`x׿%;uwfaO]TzY)&]S?@@m.Ɇ]/ؗߕlQ3ζk/tR[O#Ŏ眫{o?~5:snMpUܜ.;f@b{aY0] Ui7*+3|4壵2]r@c"`?wJtM1>esҷ2 u(nwwOePz_alCquΎ;ĮxYEڐ_.QY8޺% ]"A`K0r(Q( BPP]:N>="\&v#c,ݕK젞<ڽc߹{}ЭJ%%%}_ !% {{ʛɾr[j>ɆzǭFچO̜{CTD婇OՍشf4iI0c,z=Mi}IT-\-Ij|IHB !|2?]yw@+F)坍??|⻞>k1cZO#2B0eiݢj5Vu%/`B5kx7 WYpDlqbܣQ|x) YI/5?CO 3TT/i5ZM͏:hYoN8c":3HO}$I) @}|''/niiiaa-X56[[Tg8ksg1Qcɏbߑ;L͝ϥd*Yp~g~<2yB8n0 "\ $$y^7rwYnE#jPiwuFq=Kl.W5َErN#bhơDDP{)|S+%IdhPX4 %3 #xF>V)U1♟!D {]Z:>S6> o:uNd^>x{P|` $~(*1D1B 9@] DL0}KP|ƘOMJ͙>i}zoo]ueu䳞 !H/h/ZÜ)r BHI@RXqg+ b4i"T@ +X hj>cN1sg-^#}?`OOOv)\MT-BP(DNlwMP(   p "t@;| O֗\O_{QQfqx6 _^R5f} B娽e6bT UtmbM tW9_/6-yzu λf=*LO3t"U$[XqNvBP( BqPөB;ojaU?㐙FM8L9}" ! %5ly$}a@:HP@ZO\UX+YŋL^Ծ(4*\ä_dSOl4oJn$k-/z5>9ų ( BP( E;bce]I;??uLgqCc:X:o/aK=QGK6%F33)+)0x-JRcE[*zHu28~5^uw۞i`4fWT?{g EyyPPDFx$FCn.fdsC\M11B( (*r0guW>?S]{tuշy?`CEhX<.ߣjW3{aەn,W+XțCr(+W BeL_uwX*mjG*uڪ+l(P`hS߽R*Eh/JXmb+3 ʕol|ȇcR;pu=%H!I,+YQ>hܫH5< #HiUs{^y{*U]u #,*n(mr2 U6eEV^vR lzQ*˷"hߎG#έQ١]ѷqpSt(dA3{5_#eenI=Xq\X^@;7WXߣ<Cd^2z~; "<܎QXrwwS*5jCœfmw682K Ca;!.,Dpo{BOm*տ֒DVߝ+} (W]&!{8~@Pñu g˧F+V!s~C+ z+G2+K*c+y9p²SBDιii)oJ$d^":@`)17/ "cL*:d{ՖR;Q)v酀u̝m&ݘ} ~-:b?ʨ WK:(<38 l^f˅xb0(=! o y~Jh.0 s̖z BxUW_vU\}{$I,K$&I!Y$&dY C$KBD@(XdfTYL\X• s9&snB |'5'ZCDJ[6,;ݻUBUȲLXUGx1u+Y/XD`G g=u麮놡4!62+1nu|7O_kJ"-2{*,PiUaÅ:I"ͻ3zoB@!Z+°(қ,: >3aiUaXy &_oqLɶ xΗ;Lo4&}Zf}jT6Bx0+h`3C@@@@@@@@I2̒NNٕdL$IB& !C*Y[n@w8!JWdBpl/,KKp#odx˯Zn߫igYw/(ҭXWU^lٿd5KH)^郉E_Y8X'l(+ENb['IS5 p܁cH{_p1 vF2| `DJHbjS42 YH?R4>}>IpE2{ ÕEƾbzwwf8N9*>=Q^ݻCj]/]T("IRm>xBKXWBչ|C %`$ \ &! $v^jm`Wv p!J!hvE$^k~hShݸ/$DN0 \FENc|b=鹿׻DD_4UYZ{v,3Ys^&aaaՐsHc֫"DyU4`Ʒ%r?׭2f̕vo֚@!O:/@ZcK ѠS&I$":Rte\%m|ͣ}y͋vV("ڊ<:D&9ssW^7K9H뱉Mx3=7zRmRͭ-$Μ$HV>*P|vs%-{5evH0Z_6ݞԶ !~'-z:Ĕ(lk+H:/2v"}cNbQ,lY2^9H́ &;!2:5O afBwggOE*h$fVU' 0D ?4cF[$X2j9`~pOuv UO sqpM|xk,+O֏'i&|(z;]=KnMm .e~l7jOhyuuWE-8 o}2PĦb X;m|L Y%F`Bsk <tD5@ ADjoƎ_p.2A JB#""B , -$IRU$A. .~%% ˖2c{5^붸#N^˲&PÒUҳ죨ɫdZW>sUlVD% iB@A&:т@YB97m,Ju]׋[Czs>[\6?I yɫƧWOZS)X/gf{c$`]LF*v%)Chi . %z2c~x#{+cS,zhI*ߛyB͒fQ/xTi:z\{ sM>WE$-)>^bλ;D1h3 xl;:)̤zJyu/b&12sSkY_oI׶,^+%Fu1y {"%?S6~ڬguoK֕Zd@AϾXPjɮШONB}R&s_^7 5:)㔳f;.DϺ$^Ixg4@ŗ܌1IAoܕOq܍)3ŋMqme%]䗷WYm/-vieѱx_zKhB$]G3i]9k9v c7SqVhUwi3ڰbbtNJLw(Ju,oyvbEdM2(I#`yc w.iy :v1攬WyW&\#|a ~Jw?T٢hzQ548F i:5mMeD}DcLNaճLbǥAsLx`է+pk+ #:2I]EErcC   A." QDtR;2Y$;TW)`HAK2[)Ur"!|ʱXau_b)+[^ٹ ~fi+EK" fr\D 9vZͱ lRD`)Ngn`p'3kVę_n9?s%H!I,+Yջ$ez*SvAWDJ!_cCxzt. x;_{m\eEu/k>עQ+FTjXd-U‰'kY z71oh ?* /2 ,K ߟ-+^@iui2 7sM 8z늢|`u[ YYJ=NV$ko!"r90D$@JH!!Cۭf'o+rVZXv+?ש+Lc d׸+%{<t\w8gfޡMͧ[ IDATmZKXa膮b57Q#$8ly'Kk+Uz{bpHMp޷΁215RbTLDLH @STP>ں¢EFFfh0wUlJ 4LTpW*=kWׂ=5{RaLGS eCA*.B++tmǪšCRY8m+?ّ#},"1Qfr&PS sZDUAZx ,+ZOcZrSDόNhcK9z(gmw& ŭ#}[ RP%H,n۹-:;$2 lsG!rb$梶"~&WӨƚcW-Ct`.])G]fs&D!HҌ]f~1x[Yj$,:_/HW/G*3νF(Bj|:ҕt0X,"0£'J`$ZTU-)5fB8r6آ)]w^dLآmeFb,ɡ™`CNm\OQ~><$ pXi&jb7~LPf$QieQ^Tdz/GL2F? pyLg|);P:w gk`rrkA':Ċ20BdD 8 F!cD Q}"ZUVURLӎ$V*,nrg7Q#(5NEzZ)65C9]>~awpVgwfΝvxN:~zSΎv^yRgb|~0,.ɳRʡG6bY!|mr@ՂqsE߆!:hӪ'" bIw/il2^76቗H {' ApAJ/)1rs7GE%9i{4L6I/볯.Hq jK(ɿ%~Cl= y:o\@&2xw7$Q9k,I1Ƙn^,VyU2Lr],/^8ٖCB4囏=' 4eY._yiJrٳ "“k,Ph&$!p.=.0b1UTU!!1C {!&!@0lި_ n Ѕߟﮀ>}>|;}7a@i%y0MH$M=+ԋ9RB(B%$a.$Q4˖r=$ɲ,3IfL%H=!iߖS< F 2`i;3"# JW`& APJNBXڭze/DXBT ͫE J_J*<*wᴶ){OHD>ǩ JֳX|7?01aLhz.hy܊bcO |{r'!>țH$r˔$)xjXno@@@@q ,^N-Q~@ҏBӂs!:nX1Q1Gfd["iaX*ƔX3UJN2B4J ܫB L6)Uicyw`%^YXְ+^n}x A8 4ԇ>DD'Fכzډ7>,q||V8| WA\ϸ]]uXJD"s'PQIUC]Rf+* 9l !D1wO\RҫCp;yFKF)Sd)Gڰa7ש~܊:$!ܱF",'MU2:^G겋#;oU<:[;iS+#^1E,ͼ)=]"3JđDrNl |zNOQ/[GS#">!fRyx:$HBO,\~2%zW<^S=‘((#̀ ˒d]'ɠ&oU*իҘ#]`@@@@!T%+gw d2Y,MGr^ A"5jԫK_ ŚK(W%K Ѳl]Yi>B˷ s7|8@6dXI+w]qKˤ?5&N=J?*/R;" = SURblsygz[̪wx$gyfڴi˗/:th(0a޽{-ET&1bpO=z0Dvt!b uVBQ&Zړ cU<#zՆ=Z7*V,'pa8k;+y٪mDDJBD D@$ SjmjNwڴy)t*M=180[ MٚY&3H.͞%I&6_:Y h~,6ic|c}#ANF_OP~ cӾDP{}B7P%O:a$j(h()ǽFCӈ7_5crݩSڅw3g'_J0XL"O xD,@:N>l+}HLl/d12eԩS 0Mw׿SO} .%fzY07kv_Ns3n6+YPn%hR3f?]z#łǾ'ZDū+h(,x:N6qS JSߗŴu$erluǣ0Y= {}3 hn*%Я>01}Iܧ G*"P)zI޶ܘ-DrV缳+loo_lY45Mcԩs߿*Fk׮mnnN$zƍ>0M*Ē,.KBH$BIn+\iQոYnힵ=w^SW_Z/kHvk4U(F;˖ ϭ/|鞷)}Lżcq ~ Q}On?^z$}!d,+G$D,'"@!w!n2% 4\YܼEhxn!a9*(׳sWR }:@p!9VԺV9&t16>%fCeL^Ԯ‰'#2pn]kF(Ë j/_2zF:eu];olv1w>j TA$ҕdEQˆrInRqPDGL$Ɂ|Q Pq@ JɼP[!aG!kF'IZ[ns9~'I9ϟ:qDtgp[ZZIVJ"2Msȑd*Rri4S#jxʰN*er:|Yz$VPtI]^8[#uЈ_(O/8Ͽ|B+nWgM>ֿ}j<ݼ{_w}Զ_Η~wμKo-E?_.ؒPn\Ԫ^g O~˝+\wy~hO!d{2KMp޷́UB0VH7?/eA5LZ,@ˡhQ暸!;ɧlN!ir\sHeu[h f>/>n g8aBRIh^A_0{'E|QUjșw \I6]K / LHj;dwϯ>iX)sɣ>sQ߆k3ت{rR">+zk9@"@p(!A\R9iEǣ@˭F\ϸ[ +B G_yabM3h9 *}!.(s"0 4 Y97PpP;\ޮ]_[LpՊBpH=楇^MKno>Ww:fj$D"h4:CifU\w\iRs5*}[Jǣ kNV+@_ld)9۷>qԢX~=yV,ɏnuu>?Ͼ|j|ӟ:^~Bfo׷n~恗/ڜoDpUU4;iz} 8*aB!* 0^, ਣBB[Qu}dK#Z$1&FɒyJ$."p4Jmdh]!\6ڀMU.Ee +~ IDAT\{ND1y$ %"'*nlz_6Îjvm5nVnʒ)Y_ [N?$]m̙ީ"ۆEEzݦÀ`mͪif]Ş.@a_s/ZԽs}ih>ݦuWv^`[7yWQ(4DuYC`W o{[n.&0XX׼\<\`Bj^P®BߨO"+? wdϮ#c#Bg3=O0_Q|gXxWc2pȼ,]o wbl7_ncʆ`ڭqH1řK՜e& 3KE};_nLj='CƝb{4mSΧ<'Md֙˟q%)1];80Iza-$ҰL ԫ#B_T% HlqZeP[@<ǷV-ѹ]\.J㫟7;tFtuww{Ӑykˆ&ΟzO0 i9a2VSS"*r{(m3}3Z3oU*Q_5XZvê}lUFnYPMӰn s0MH$M=+ԋ9RB(B%$a.jç>ʘb\.woBDdI1$$dLz1@;:V( :4Mi+ص/e6tBVp0}>wᒿJD2LԐR,McCh7U*J< "z-Y]EVkL)x7 >>졅_YG[} OOo3blt\⏟7ؾDkRY=!E8 #<4DN9s7|mYn,Un2|\L~ -&G#{([gYի2YTPZS*,*=$Hp!BpKXGߵBGyRc>^8X> ( 3pj) 4Ի2%ǰ{aܪ$y%,#j;{`5~=z`3A!3V0M@@@@CXW IUX Xx`}`8X? e&I$!2$VzIɾD X~ۥmÇ bvM$1YiIǏ D$IRPg/_ XE1=sN9;Bfr&сl^֋]T``'{J.5*ʁDf7N$h;O9ӣԝnm?,c?[9w^ԇ9{iħGy.dK3oieWn ɧT#"9'6D{$Isi$$bg|cm=2(D&(gDrۻLRR<?mJԶPQnuku<4K1 ZSSӪ7W-㭍[nʋc' Ș@d嘶֖,1hiNݻwϞ}poۊJإVVJ<.NRjJ*.s[标Vߑ+le#"+[#yr$*"ւG}s@EA0RXKm>}'CK3֔EjG[dTX|8xY&4$Nbj[ArCllsygz[O@6YL8_q˄:*u'uZCBzڹXDv=_ +°(қ,"8|m?0kr"SoC=~Dgr@@1 M¹Ҵ}apADi oRƘ,G& U9k,,O YF,5kq}9Б-΅;B̆mpV]קM{wj1V/92d7};W{TXZEw:a,zXUsNU^SwmO gGB>*b>56!esu'|h}7]ߵgE%ICl@$IR4> {qc?|7]xݽ5Uz^[/YD &L01$U+=6Pgs-4kvu!m's+gۏpİp4E0>b9f()w,P!<5x;tBG-L' "d""|Ji\ߎ+a|_u=+1IV\bm4W=uHӕs(u :=Am)/H/Hmo(^=T.͞%I&6_DB mz$۞c NK?UnjB({w!9Uzs;3\!^U`R ̝[xQ@qQ]g'_J0XL4S4}=6L-T_8֦wfJ~Cni8t3u"c'H$"^_XQ{x)F(3V ' ui^&6g9g+zA!U\nb^A GɊGBd,cG?< ek/p*/kλ"a͝FsD4 09:7rm,%ѕJ EYٺ02'诮 Ґús{~e,Wu_Y:W nb/!bUVGk*_U{V~[Z 8lݳ?-Ԣ+(ܗ> bt?q3͗Ƨůڔyn8t<_|9(1~ڬgu:t{;:),ɾ,a]tO:v|ѓwn{4;GmWE^H1Wc0>ѮI"Kk:%3We%]䗷WNB}MP8K`nG^kZ]!/\ح舼n%-.#7ʧ8ņ9m<'& `}Հ#q; +0uRr%ar# BĀ!@o)J谪_=L 8!;+Y^T"C~P,}yj]{ T؟.rFu Fo۝dvu$(JuHR֖Bp8,IҘF j.e4%NU3IX0$^kA$"$BOU>xWğgb f;^#K2OHhH'd(p8z"1L=,F')2ta)$@/ɁLҺI7<фHTdxv/~_$DM!>&QnnYmFFIsTZQx=giBM&?M1W7oޱD5vh74ldm%DHp%?ҊM\/%&|w]~3Ou.̦E13*SnE=:^`/sٌ;3?$BbUwozFO3k7rj@LeʥD d=2g)E0 $&[K<{Co_un(I7mן^|PH!EUUU IduSRE%g'"'>T% 4MӴnV.nQ iiE3 "kKpl HX>Vߕ9"FE@<+Bax<:3؂eR{bLAsyt{08i60IN8^.4h a{XC#%{˝65UU]Gmɨ|s򨪎XlmwGM}}; !Z 4ovHCYV\ˡ‰'#2pnx;_{m\eEu/陞sh!yQˆJ]=J^dV|ujz2 ,0D^<~0G(Ę+LӶ5|Yn1?o65+c'F9)y 2~k&mejg(s{H(  $B i69}_Zu» JPF(\]IΝUTOOLܹҽB~o[]{:d1sr͕^m@@VCa Jrl_4 OYH TV>eel,˶@Kz%NwlK1UǴ=h 4-K/Rd#}I =00" R&;&"3 `+Ⱔ ;g=WTA_I4JDZ)_G-*IicZRHDtjt aDt8uI 03^yj;mbq„vgR,Г'ꩍsG|O*7bX+_9c&d2T|By%VEu`mbT 5hYP_/VȚX e5Å-7<6 N!bGGN:S_'4Jd۬ }g/<0m_%|]|b3Oݔk>׆ChfPB)w@>SHF!N~NxcPUQg 1{On"{i,weN[ڶ#l;_U83xH܀"x{r޻Ϸ W{M2-6=PZK)al4m⋾BVMjϮ.qUI^C[WZj/qls,Hg? W76Ø?k }:=\gdnП w>ZNns_N HLJ)eOM4f$""B*AR9 BI&D)Pis x$PO7䕌 AD4JE|@ UoyHȚ17SJÓm>c Ŷ,x7%O#bzf/79qÌDtuKNG8TM;#*Wh?TRKU :Yty$rg3b%F얊ﻟgΜ }YuwܹkWmD:튀'_.ɻo7'quL|[vϏ{퉖:QVƶqr϶Y ! SJ݁DnbwgN@q?~[b}9Wg } 6v_p{> MO(|0/m[ *-௺ \£=ryuza @ajQPz2{Tֶm`0%xo+ BM=|*r7g8ʮoeo߲V7h4F s̜m.sU)aުSvc,ng~[*zwu7)6֨< "X>w_+R^j^S=УJ>l]OڥĭPu7NJlkdn+Y֗4TG?}{K'86㜫SRoOиm/3J=\6!qUjPTH IDAT%HaKr TZՓSCuQ[^v(,_)3$2C ! iRKfG/ ˑm{Jۖ(,Rd9|04L"$x ́#syt/~g{,X0_kN?}4>p¹f(M߀V+SYСxIfl{o8f L*Bl߹;5qR0SYne^l\0TWW Mʽ( dɹFUE4 -Ȝ@Hf#D_te\Yvǎ3O=ղI8ڇd5_֭[7us9G·S>2||<}u{}]&r֬eZL/eq[23Zk_jL|k4 XnUO8)_2+1(MiJ8G#bRt z|+_ЇA)߈sy+_kq_dێiO9TqR)ǶDZǶ*"GW='E!BJDJc܌BD%OhVG2e{wkϘy">g*}E\-6=fڞΚ36G&DKm⏁zBO!4ב1$%T!B iU2zf!u*CXڮxVUn5*Ycrћ*!"5v+>h_شSNBضm!dlz|N>}͚5KNOpTBw5Y7yU/K=k4/z2U]xwpP WB*B-//w7Sp@pg1}?aLj<2a!J` ^Xr_!D#  &H(Hs0bS#ZD%vsM?`ɓ`$OhJ)|LMthGzXu@+I8/qHp $xEˣثQ_(%".zlg_|N+}Ow]+É.f|VnSVn?1OO-[bRlvlqc\fb055j赆 1-VDWٔ}ܠG4CknWUXXY85 4ßn_he7acxߤD3323CcN>@ LnD̄;Rn-Ѕpٷ>$R#Tjc[`Z&H #/6܎ $H AYyW&zI6kiٶRZv,`FOrV_P]R!GuA^,{Guٶl[{%U)@!Ғ堬NXG@R*> EȦUz`txATGg*ʾ45,4XOKXarG!k^hI4:o|,_OO3O1S.+5u8pe 9ϲh2g[q"b2yq7[rgo\WߏOɼ~T'& ]88h`Ɨ >Aᅔ<_$8:Y5X2i^ɟ $H We1Ch+BHHdSt:IR|f٣Ǝ>mT5  ];w/G9.fۭ-< D!Z6xxbHh{57 3HaT )VDg/mS42֩7!B"(| w:wcO8M tٍV810[':11/^g ٫FL#1$SLDXD,wt4qVO[s~6çܔ`K5DV -P=4+MAL Aj+f&Fa5B^%H Ac\>z0խD)+om]ݣǎ;n N1aD.vݓOym[7KƎ'3q1&7a̸'n8Ҷ CP3dLpB/e9O g|'h]FLqqFUZE#dL^ͯ}W[ْw?}5Tϊd N-aGccc]؆9{.%vݛ-?ޜoXn-xђ]szS>M;;ibo|^}_[~s =^o ?d ?W|, \߱Ll{]Sᕊ#jYZ1B 9+A ^Z#Ԟ cQC4N*a$H 1W4^/B'ة.u=SZ0!,˲ǶSՋv(uAAHCU4!Y¢˔^|Z/ŽnϞۉޖufAC sive7~󘌱)$q̥ŋ<qیsn(|˟b.|KdዟdZOܓ?ɰtٍJs~ O~o]}%~i3_3?'Gw.RJ}o=oC Hc/,0.>\ފ3?þ NpfuQHM%#J<$HBp|M|3#V9 A ^ @ +F,0 6fMGH3tf$X*eb8@ղSÄuI ^M8hWcUkژ]:+`&$nfj`x?}yġZ`~}C`V+R JBBG; 2v[΀.&^ j-?=Xe:$H AAXU*BH#A JQRQOFc` q='sEO~i^*ZhYs\Q&37M~n 'f/7t̚֎;mJiSvԩY[wǛJScN8J==,ݜBǞa,uX&LK|s\\]EUPρS>gB,]v#(?gZm8ycF7M3%X sȤ m $H ChxV^tN0/HiŐH 'UrKM8,c  Gc#`AC'p1W鯚8IX= 0@#!Lb"Զmò){mꇁ"qٜ[/<8d7]'_yԴ1}I}!WGx맿%?qVgRM EDKȮǮ_qz{EKlɠ)캆2iʁ I|~P~B,^sП~@?r[ll#m9(6.>yK1%r 疗|Ccێs  $HL?T"@a%H A2 V 2jM&Mn|~D:ݸa]X$WK((ȹA*(ǎ Xɩ8=4SXT@!D#2)gbZkXc!W}ȑYy%HYIYR1-}uo_ ;| Ew{mι\WLל~沝h`\hLȁj;Yw&$6*TaZh5e7~ o$.01Z`b&v OYi>àœy|7_dODz=ѲS'jpWG+员xˌYCL AGG>D$& $HUj3 PV2"Ƒ-xEm\rWKŢqX5c::o_ׄG9XJmZW-WrSզ"%Vʦ_a^U4Uܴڮ*b2V^6Pň\cs\e!1okຯ,FGC |. <q'"D\Ə{~V DF/ZrD9>{.Rp Z٧6-D+9U9F4p'1Kw=Npdl2!@ $Hy^pֺ̝ )b"@[=+]fܓ71eK)jaDZQEVB&HplY̶ Ə[lmz5J.iFTe4BiS鶎n A5Ch\aep}Huը*92Vb55PjEHEKro{[`oUlf.s/ho.c+4+_kmjr;L B2T901ۏR $8}?<6> `!i Id*i BDBLe1ݡZv]!DLX*~B`%Hpl| T?b*d& O;vl}78uVwWs >q}ްnm:BNфQͪ[6f`ˡUHԗUUqV &KFW#n ,BX&;axђ+VzKYhI] Cʘ8!13!>C:7y80P!!݆n:PX7,<-@IBb"ο Ǻc10؄) 2ոJϨTLMXs-Î(xђpky޼+ktٍsݐ2Z CU^ %X#9A.xcaQb:KQlA0vaj|;\ȣأn{]/EmgVpʗ:>Q 1B)sznwX zS%wM %Qgv}czTxOr`e6ڢX;)t;n/g3)%Ņ׷K xP}3x);$2I!7x@^9uv5S,(j_Yif:զ)LÐDt,SʖfRJߍ.3R ˶rޞ}zzFm='Usnf>F k "rfImg.>\ފ3?þ6* ,LkNs]tjx|OygWo=Qg8p5gpl+/zM휫SOllwK@'/_},v +({g<-ٙCSWX >޵㦾my 1Mȉ1Z}Jg?ݾ}[?_'_uwZYm‹au;vS?~ Ԋ*o@Of~se-{MjOU#o5>_ozm̯v}QԼ;l? uo=ej/ vѤk^gn\y;%pxYW*swVY3/ 5tǺvԿPqVCd_޹F_/K >,lyrVʦ0 Ä[Uؙ)f͹%l90 $HСJӚs]۶Ţ5>LJk̶m+_)h8Em[)r[F8"'@)vD!Hh5'z=IjvPi@Llk1*hZA* ANH4"& T u6+d>pWG4~U̔K~GlPY͇D `!b]uCTqMs>+T&h_AJ#cjԌa"_~kHIñW6'\'_~#ߤϲ !7q`e)͊x8w4Gs  a-m|^kO~[zl5UQŽ]}`%+aՙ[z=F6ڻb̬ @9] ϥir{4 1gض8CkJo"53Jx7=O8QJ%]"ԅӤ|دNG6-䓦I?z~/l|N,?y=eFكN@qKOOuCgmv!L[VI"Ēb+ҖЍ{KbrE@isC?PYr 7nIVÄ{" )M}vTı)ދ7xdH-abid/?A!˜Yi5iDaԕ;IZF[5aHb ֣zXe*LR\>"G4+mLaWvTI{yïjd}R.}BL +/=4ˁϬVа+jLo4uci@#P+Tsw+8/HC̞_*mq[p0K͋qf(eqhp=<i2AãaG HZqg9sȷHj7وA*#̸c+OqK"![3CHi.]t 51j ".@a]DqbТV48Zj;?!Z=yr  .SE7,2籸x}~+#Qk7ffM砟>i V64 @9 -'DKv_WXzR3%34\GTR:(N`X Xw7ct ˔b!2-X}gK} /HkS$KRMJtRAfk)#m̀Vʑ@}%KZRec; ,cTlVLđ('Hpl@bX10"XV#iog?_eI۲l)mKZma[±me K _e K K)(E"DLľDZiV|ER&׾־ҾRZ3q+m~;HּN0r%$CE _~q΀ x0^SEUm%UX\pٸ\:V5m l ɶY+$.]>/e38"S733;3,x|V>o|Nϻ+W9vstfw $DSC#%ymڲC~nkxݪ>>УO!> aw%bJ?`}\|Ei浚'@0~Dagc%u3SK =J_o; @@H l. (5q&ENgnw6b8Xv,="},q {s&lT{ouc{|vJ WFO-7lLBKk,Rvձ]_28Nj_ X|͐0X  m#" R;YF+Y{iaKԊ<i t! ʤxX>u<)+BHD ˟ߧ%*Acla1[P ]fN9@.IKJ!@&&b$Y0d !H3!O-uDcWڍ{UĠ5)""V֤5&`&"bĤ־_Tsѻ6k9JDjƒqQ1ކ2p/kDWZ/n&։[+<7wN}E9x={# ?3yb{eNպQeOXV{Znw+4ݙ2PďR pim{,<\>{62&!&PMf^vM=|k!SP{܃g^^PطڣYλ"*T÷JW'9/3~i4=Ux=ϻr * \Kz=+:/3J[_|p4s^z'ν&=-]ӢVNECmc?!+,־4:1B)tn<=mmȭ''{z~[*R迦˳'w_E#mo 6򧱕Gݍg\А{f#[weeն⊟E8A@`@Ի셟oSʟ./ԥA<6U%']ĭ̖ ww/um[(?}/ZyK1ON=L_毼e Oo;J nZC{Ѫřo^mq,l_suvaЂL9k[uUyWdN JJ` `(v˧s^Y(@KRχ3}񷩕 IKpv V|-  ^},KkZ{0ìRlT+\KJ|X`v!l-ѶG9> u֎bx&@ ,afҼ1áR-qZb2n'HpLE %>0[ȝOIg^y}i ˒eI)m[ZeY–%m,ضXBJ<}hD8g$3l{43ֆbk֚<)E&_+H)īNwO̟3ĺl%[zƚne*Q kj/P38j 7iN U֚c^+`xa&[*W<<\w.޿;m)/wc֬eZП#_vpG?ߕ`c (CJ¤ @Zi,WhYN}њ~Bt~M̟Ɵ̘[̾;ʲ)#+H4D pR !bK&@˶CwSn Dd\EʇB'F$:ۤ`ҚDs}L`3;a/!*:z&H' ydydfTv.O""DD zM7 63Kض8NNby5ص9z Lȅ@`FaPN8"00ia1Sm0!3Ձ/~ ?(311@@KR::n/wOؙJ'rlqqlAE ]p>\JKJW|@@%kʘ~?4NHAeGwD"0ZeYsfϟ3X੧׺YxeK/mN&+Қfb5^9ϪԵ]:xC6 8~T _0̯+.Ν[v/h]ibY36VDd b.{ԠH,Nj"4rkaŢCE]ḙ' swJ1\I'HC\zT; m3ᠩU%N+qH62&H3Bνc]%iyB'* QE@`ʴK` + { I+OC틅eYCZIi@+y~IdHZn@aw=_8@!PiRbmX:K fa 0bJXcʭl YFP63iFFLLHZPy<G=<@<#Co$HpqTTjǶw1W̠5""am =[Nn7/(4kJ#R(hD+Ac#!`f" Q)d&Sa&&֕Ĥ9mP1Md4JBԨRomb6tU^)JRZkҤ133r{CBoD'd%aVMͩ jG_A+ݜ|DDLNO]j[K BF$vGQ rum{J6 ae!0k’"aApTR BsZr53J i +y{@2jBd <N* 鋮|  iyF]0 >Ҷ٧QOd .H=爵k?cnJuo[naXnS;ӿusfvۿr'8tpۺ<Ӻ军tDUq:6}oGF_:v S4_4(_8 6BL\0Elݪ+iWҪlۧ̽sڵ\$3_3<̙s'}=|DhїjR[Z*JuPiC׬Z%` fJ7qW~糹>[5î=GpW]H+o{8usJ~?J J8j5C|L=_nPee2~}[jJ()‘ZX牓2h!Y@f`x vy@@)Z?cy2Sbj&*vQd`QU+G7 `dUp>)صbwT,J/K`rdDYVh8>Zt %*G sRfuٗwpH0?xx,E@DU @lmf~OPvD$LkaI&kim}_ݶ,Kx,"1i ( c}S'\\uV e=mr:\8wC- IDATQ|w\P 6ӯS^ *nP;ʳoe9^`++\= [_s\@Ѵ y"}Mď64vyݚ| v6d8|"S=tOiTW[VM#~~i^9p|חVr~!ܻ_po3ZT%t91=UhZt[/:J<slSa@=g3γlZDƎie9i ^A7yU ~/0Q;є5q?jo-֍XUoGj+v_kҲ?9p[mz~acBL  4/lE,cm ,{cͻ@];/Rjfs6y2ņG48kh3nC|j=|h}/o(/ʠ4gI\+AiPϒ28a ̶\+dn' řA)>sIO*.`!:(kb(DLF3GF4t=}1\3"M{~`}ɯҫն_7{W_}җ4{p۾Ye*S+oN" }g|]W~|ۘ9Kްr$5muЩ_f7F_xy+ A[Υ0؂|zˏa+?_slY7=2M7:MS\qS/s[wFޡ]ndz1kiW@v4|_ӳH~8c [$8%7uO~c~׈)1wEޡy-ZYD|$2M_Mr+[稸1n/7 TLM)s9N?J, f1{|{N&V?Dtuģ}0Ȓu6X }mm>kSx.@@dncvUB` VYL}]T':IMLVx4(wY ,1;iZBp!(-B,7V! !{Y]!ֿ"+{P]nU~x HJoS@@ӛe dr\*i ,OTKHZ!VH-8&MF)dr9MϞ;})EQz~}?1.ܽ9a'hAddl"Q@Uh9W|DP^(k"0-BWhM{F5)T1t5DPPd(n w1lRБMpuMxܔ;5. R6% 6]MCZ+:-Lܾ0%.Ama6'1BDj)NV?Dǎֽ΃+y@cnKVtaNWcg"*BT<))r$(+4={Hk/\[ӟb%"hY԰L--pܔq%_۲|BUߝ J-CG8qܔOEJ,SOe/I݄Tȑ8=Q4iE?9Ws>+zךg<S"mPH# r}ɍDyOȯNb+IFj^\-.2&`Vc; `~gR;"ѿ8Y;Q% ,3(X,;Pt9#WMAaiɬ{o9>Z+ DyLRmFX96%AJX *źI97-L#"1aec&H [ .aȲ8眄s6q%t9,jΪ*T :UL('VWHGꂽ 4p0nlfət6Ҫl >}ǍxrmRpMZ9AS_mÕ_\XOtZzJAVV<7 Q9u&xXā >8\`f]-T 3-\53RfRK$jr`?6>n"wq'.H\Qbu OY~ "qM߲4.d &Sm0n8x԰#qMnZyrV);UD@3M0$7.u'ѕGC亄a #RiUPySm2h0rXAj7vO.%J]j3-VKiǘuCW}| @ *!,SyD&.=c6|ꮕW.c/K[ib(a$,.1&=D`f&qcGsASuNB=?V΅5Hpn{BQo|I%oYATް^>cW0;e8UOJ +vn.F1*uyU3 šF`$:cÑHE 7BnƚO/>ִxsT-ky䤓덩7)2 V!TC]hyk>qRV֥`븫 ygcHٴPN b&.x e0/fi_s%泘{-nI )\D"e0W5sp-'8mـ4 %U@% +WrQkP mO MY̶/s_VEglF[s?5Ϣ>swg &k(kAk9XjB0XᆰXDׅ,2:t5ndi ƚcׯO=1MUl=g!D&DW;?mW<}xǴ# @n\l&>; zD2#P( q b-ikU9ɩcW:|$Xx)36眾*Z vK2 'H>a:+[4[:p ÑԣA iU#o!z0}'b2Ya13uY(!,s`ڂӠmRk1suѦrP_ |ߚ‘ѤNĨgS^+4SoF[pnY,OcӈԾ_5i,K-/n7s?N9goBe!ۅ"VQ,.A'K4|dD!c? < p G@UIiWǦJHD ˴$eZC:i} lkA\X8Ye[rmVf\D)RaUtVk6XT=.*ӿEt$\BcdXYR6n 8 uwrH4+Jf#J6OQ;X2Y"1aQ oMj_1tytx})[}5w֔fljmZ2{SǨCZz,$ ]dZOh-__L:3}V]ُY2`['4VDhY0FKHQZ˿nss|;0 7<z%MknAKkt OpX=\xXwj37v [pfXumib> {}/6< N;?)Ei̺Myސq+‘B!4nHνwd>}d\*&QYGQN6>aP,l@Rk&yxbP>C,{ho@j!dEwŮwfc,#EGVw*^Ĺ&G8vbrYBKFYG9\q"ν)<ə LIeH@e^Uw٢#n^+Zm͟f>ŕkZsKtrm8M/˪ 2Uĸg!w?ZuyhŗTzkē}nAK85LݢZLR;d1<⾏ ®h۾͵8c Z@ /OVC7;]~οءp.*ri*=ƱNGh<H4nt+2ƞZ{ZnzɈ5 uX( z>10~ܯY>ڦL `S%sGlRdm]g}@Bp?G|ĥ|G%tի[ΙPB@peh|-|D>4 Ÿ^KF J]O$vOBpNBB=ps\6sЁivw u vzz,M&9˗k`~v.b,k߳k9[ښ^6LzW>+KDFͭMW,jT#>q3_9uөKԋ[ښKϮ~b>튥 ھiS-[ۛ^6FٱecBa0-4 0 4ti|S3FM>>t׈/N #Y$iPcf+L`KuIYڵW!|$<-g94c\,_]T]@[ e C]*wKj0ez ?nw+q_g, !ѩ,Ӵ,H5?;{UU 4U4U4UQTUUTU` e inٴ1~$ 1&!cI1@Dd!`wd8aZs^_O3ƾg;>uU㹉h$Qw\{f"xT<Μ`޴NܹDŽ\I,oy^Vo^`*Ӯ*$srRS_*3!l1!}R}>VWtl"J>rݵݕ琱FǰҲSisۺDfV?eG($AEl²MԾ}i`V7xY)6q6=sXsYmx$5NQ;hMr/UKj;ww?t]i^7Fd2.۠{k*.:|!hpQ n<$Bpa+ c1,p^As. >iZ";pTJ"AȊힷ^8 ru*lq!5L7}J4Ǫd .*;ir_%h4z @]]$o:V.eٷ/g,j,^?}4a$ڱP8*{1L@[& JBΰCx)Uȋ ʕs̚'֦r9 g}9 ^KE*ժ쿈FQ೪+[ =]݆a$ M qI_w6熅iZB@lݚ].aqs7WI =vL*#?uLi=߽~aqQ$r IDATO{U_Ю(R2Qkn};zQ~lLL3 wmX80e}::lJd1B2L]ʊar۰˷zz*-#A ?m[}i2J/:Հz;fL,3Sg {*6^y,H9y)Gܿr|Q?j{VA!B}CcOwa ,g__u5 :披'"5W^q-n$ V6JB [f&2GA4G_ּÔb&Kܕ)DW6慫'HLoks' o̙GG abkH:?JKѢA#ڵwi;LiĽdnFk Z<׆\&`Ans z lGB2cco#a%00j\lhy߷Ǔ@wĖM7@-xxRQL:~7\"K``Nczëq6O \{\'ey{,Ѣ/JcL+oT2jY|nv(fOUSNw _sTOD]:;rN&MqUlj5HYmO'wYʊD9:Lql\[J)ޟ\wꮯYʞ6ggnn8Z>0lq-:gӾP7thkd_,K(oN!)vg6*l/dqitχvSM]H۷HBu-|ZϭbUuuDy;NyAZu_G۾wpw΋ w{TDi҇lҳH\< pHl!;N  Y!2uN l? B b8q.`E)1<6I+/UVcBN,o$ZQS9EO_cD_3zGEB{ZnbNP5ڜ[xIM;}lF".@n-F>_}O u&(7$,Ѿ[IUwS/>eb:󓱥kMbWV e+U&׾M*l5F ╭]ky(R5 ̗Xw71k`H'MғX>BOgK R$F|ۺo]I߉Nh⪻şyShɟ>ɵ1j[8({*.@aP5ta@D/>x7-ZuQ-ErWiR @JmFVqM$o%)دYu1FшܲPC}-⛏!G]/X/'^9U <{4M$+ !1˒ 0-xJE]**UgUN-JGvJO:E=jxyK` !Ѩf?ÛW/;Z&CAB\rwW4s^flN#b #hOwW}C#2x2 HtwFcРE-\>@n¹P;zrԺ>YNt]uT-G)W8DOmk$Hc}f|4SqEEQLi>k8dDL aS.{=nh;mm9.RrO-o9bYS`@ "0 ]7 0W}ṃ^:5ϟ hʣJr9u:>^qf3MZniL 5ϐ-B $E(Sqi%[uxԡYpNc-_>XixkY%W+qxDtucٗ51R^rb=y/.maBg;sBFZ'e7iu%}rȬ} x$P[Fu,)szQa Nޯ2SCi+m9P >axkjf(ޫP)yG2p7}FBk)jq@=FXC ΰPml 4tcICh]O&!SBa;D:ӯ?TEoSԏ_^^) 7d/.OHzs=+=Q,wnC𡴂+ @>dmZCð Se_nyl+-g(ٝ6xUrոQݻ]b0!킒$b10$e2ӴjkG 9񠒲^a TTxB$EN5g`m/"&"d~{3ly3GFJ.Eh8B3`&C`)b"H]?Om=N.nZ[-$:]}!@7g۸nxܔ;5\ڢ͋)kLlOcK&@fmaаT۳ t𷹱F3pϤR}çHZ7W twnA% ϫ*%8r~'8V_-:~~sSh~On<6I` R@ma-7XGǹg3ѱu_  ׮$>/3}qۊs^>Y})$I1Α?;YtO!%*5ǹgJE> ŞVt3gH'Oy/JU8EAp 4 ~kӿ%]^HεzҞ s v |2qF[qrn꧵K#`o ))M$y5P:ަ0j|H^"=Ob7ޝ{^k\28.Qd^4EV!TC$iQ8,+9,_$A`LeTUe,-x"nND4By+q*}JR@]k%1;pb1jkk 0-[\@Y{{{E" *^*z$Zu=2/^.%(ck[w+A<nZYM\5$UnQXES:iq3v/?c76@feA)&(֛Y{k;'gK? yVuqsiÎq+2yկn_кs %zۻӤ{1ǘK ]°LQ[ @d|2 OZ=Io5^M]_kW/>ۓx/-gҕ0!Z@a1=iv ^3)cBy>϶ sUyals vza+oʂ\e}e=:*&o]nVI  PǙDkD Hg_q}0?oMP!p(6t|I3W,4DyN퍾&PA0nyivᡱ.&l EP VW= iV (u DD.(*>$DĘ eY4\֝cu|^50 _s Br* [`AXs$IUUI̅ @H^SbW@h+6-E"nX`G 0@3r /oˌTG~h%s15gPQPf{h$UQDfI$r?F-M#LSRN=ERي_99jBr6']T}P \@$}>ф]yހ@CXc(?}% pb&(|#ʲ#a$En_N'7SoRd( 3-ʯMc~gLCIzKt&DN}0r"19ܠ&P"r?k &1Wjpr|AZK(F0 /*Vz,ʗ$XPfvo2&$9q* LU&dw w@<̗tJ?$)n>9A^̃/nWHFr׋EXM;g15F. ٷSk_"L{$ jP@ ziu^#Nf4Ŧ2Ay_ѯFO)pS^N( eXrw4 Bu')I`l?_1YR2ʖn=ʕϲ:E.J$3R̋?}_{!\c]؜s׭j[MEB qLɉtt42:+/fЮW4Ab R7`-\Wauv8wܪ6Wk&_q8kZif@d`8TNAнɐ M=[4;`&AQNrsgoPl}g#:qRp\N 5񎓜+8`QFC3$)"nq3xMtw ۢ;*`&n # yܥ B$RW$TJqHeXނݕ`p:]!?vI-3 0n<ɛ,y)AH&gUtsBP_oz8z~ᆍ qvGGAGiw:0ut|;oCVcgZȗk7.Ԁ0s~v,5JlɝeՇx`;m$,8G_~y>?ؽDQ4m_OA5ZѤ>e[DŽhf$aǮv';]zbZ.L2 0 4 ]8c=ԌQ?h|MQf^ \ mE{A*6C1D$9]P=THm[a/8鴿 Cl^7q䯲d.A4jX)$8+3Oy1",Bܴ""@IKZT_NL {bc_/}3XI3-"Dλ^gEU1M4MU5MUUUUU"O2-6f2o<c2@d 1IFQX]%~a#uq2գl$``ЖSP.SBصyJ/1ái`ǐJ?,!V.x @?AC G2PsK<>N>72V9Bw? 1? >]A"nUs @eۭ4r}<׫o|p5ObmpL@ɡHbs#a-a;Y4h ػ;R7$&C `" 0+UȅAʌXܟ. wL`y%*=zcG sm;"q{Q%:gQGP9wowO^B 1>Q|u.?|dab`K7'W9WKu?$|U0\M)DjYUw!BhH2|5 4zC Gۤ,˶攬H.'2L 56̛zM9ٶddkr!2I IDAT"SEPA] dM{~{,s_^b`W(6$ |$Xߦ?U04*O"6xֿy_ >Vܙ!W7DeXWҗ#XqPyʷTU )xnA?@KWA\? "A 𙨔m$p )u$O2I O1df~w4PǝC$z:!ByXEzѽh6.o̙GGmP_l#רh_Dsxbx푪X-v6a$vǖM7@-xxCI35ֽfqi}_L򿎟|(u}؇M29g1AlH$PF E*V {:T=ggvVZI+|f{k^ի{DQ@DA$f0 Sn ׯhՊz?._\@hʅH'c;u+|X`e~X?v9U(,LTn.i9␎Nlca*0*z.t%Y𠘔"-Gpy7~OtMCs+Gd`K*S)5  L],WxIr/bp@H@#ЀŊ_6R mلQF&Ҿy_+o7lՊ7v=RdSs!r44)r59pud`ιƂ K+f)PVSqyؑ\C7Tf _+qĒJĆ*Ƥe*[%/( ݕ>H?k3wee+@^s|ϕ=Y@pRvF/&; = eoiI,[&5>n|ZB% d8MYrY5b\FM o B)`rypz ;`n8Le(Fu v+9_"t3rT%$H@'nZ]Z`m0H0'g: 2/-[XYe;4F%Bm)[oDŶ,ftЪTM cfu뎄r ,\t,S\i6=Wo1-'bbvow9iUъ+TmmwC?wW.jIN*i@N愐.6v[ 7j jV!ҲJhDXT^桴XPm<H*Ôɲ&NὋUEͪi@Ir$XAT"yqY,=4!TɓcKQH1j]tZ/yv( 8sMw:tlܘX0Y)F"T;ǎ j`>gUEA`0z@dc& KO0@T+B A̴"GISKnZ3i+p@iC$+Sagُʊ@40CYJYRR:F@nVxxe۶l(/}RZUc¤Ɂ`X % \}m{W?ZTr)E ҄p Իkf]kX <~pOu͝J E`ln*ف'ʦEzn=Df|͐j}Wu$/{5ѾI6"ʽxGko sL4˾@h433#pT H)KŹ6qjIT[T#Dh+2EOOaqH,-|7"z$+roq3B-^گ-B"]5#$ jօ;jrlRfu LFq{*^ܜ-#790f_h{S;/ UzV<$VuVU˺Q/ Ҝ;*z3k:qӶ.R+r$w:>5Tii2 cCvjdZBdWv{iYSٳrօ-[s٪ >  H $ >W 7k|H~"/%SVWQ嫨r, L@%*O\Azs bu0%dC^K,)]y Xn)˳򖣜֖#F-(¨1Z6@uXaFrnNs% %@$!%zҧ+I ][ZmͯTI%eFo7۲Wܬ6t•J1vGd*R'Ї+ipPz.'TA$H@ˊ0=| O5VxۚK,R|ةIʕ ĺW*By :Ѥ+c$oz|]$G}K*GՔʽC`Q&B Iy&]$WVSWVԗވ:lD!&4K$Iqw$BeuѮRExB #ƈ *4:زR&z qnMiQsƁO})sPȴkMٺ#P$葢7>ŋc} PAQ':Lar0DC}$[w@ R٢pNu&m{r BR3e.|xqHsiR$u,yD>0ڷuŻ' +e/ pd?~CFO<m۴v#Tc $%f;JDhl\!]eem0T"tېsLfwN!Gbjbs@0 \.ïbn\y1U"}{ʃ)]qG0)w~4SUA7C|7"lČ \ssQAWP*Y@X؇;o|-YxGb#GmwȘ>FJnEWhW5PI$`Smjjv2@lsNwD`],i[6q7hKH&m?{xsr낗QWrQ= eod#mۼj H@Dm H%y!%jI΄DFrtnЖi4$|L6p;s^xo{W:7p`4K`UsadmyFDoޠ~DI I"!Re"rmo^?i$Ǝe0 Y槏˄<\U)yڋ9bp#g)rзK/HPo[oPgu7ܨk9P=eܰP/v w_jgHC7 ]4Mt]SՖ#}˷];T)cL7L`ɦ&f*t*~g٥̻c58:]QOȾJQlet:cDp/H^La<^/J!FW3Ӌ D4JpX-K?eZ{uW0t9G70 D^|k%Id%.,I,K,YP 2ѝW.>$4M)%D BͨXv!;x 3<ȋ;b113mt=4oͩi.ʾ~kS*h *>%O)d7Ъl7^wyz_ߘV]z ;n 3U!TLm:L:ӫY G^#2OUQݙrLLx:"b&ҋm,8msqB;D"ڲ8Pte!J(̛;n Κ֧o hQ8|H#4onm߷_l1X^{rm N[;etGdg V)O kR:=TY2J!`,I`_ p |.t[OunwMeM.rʿߛߨhmů21oZ q$&}Z%<{~C$`t/)ѿmk߰^Z+*ځnX1"X8n1ȲI?*- @1e1ؖ+g8cEKQ}k}1_Ys% ~'?\A&-|臯J_ LiΚ^hG½O+"PϚr /k]׾ IDATPܟP)u7 [ՋtD"o+ |!qKS$? TB4 tkX~e*s<8pLtߎꚆuUzX,!]浜hӶhhp,0 ,OU ޜ_SI1f @HRD[CLO{9ͽm)EQ2-O\U˰WNtX}ڙ_hf{gnLa0_ [0kQ=~復 >~痗/}B^ܒuŶRhzӍDfYϖxJQ.@p}]Бwі VVB f$ʌtԯǓEձ|_]"s͘%Q1v_ϧ 3Nr8pYnA ;7IŷjXHA"J S ɂd TT ! bpߺU[SӐ@OC^$xTiˣ@;=$њˣBzyST{8̷| \cyg jX-'+=8"f͔t:TKQv%!=8bZ"bAj)Ub= E)e1ƨ sja~7G?g||t7?qKɋwMc4E@%k~p *Է;z(I?Mat?5f .x:'qg--OF t~XADLGT@ d|2Q)97m=kM4aBJDtjX|6^PBC 4*npXq`c\&n8& :|b'l)`sMU=`nN}4Ӌ߬zCGlVQgQ-[4~h|xT`7[#dNPJ?ݶe؈ST۶TW8p`'bŧ'Bړr6k~}\3H/ɨ9 DW /㱷~sU}D@D(j77O 4N M9< P(Yoހ.j}g(}>{N$>t$ $\"iTbmdes,y?V_0[ԕU ,?/Ϯ[Ќÿ{h q{nk}{k2{=>Q3JE-D2:-sw%0 ,_XcG$I1]"ǠXNF8UgQּLHFŖ(mxiK&L߬Y nuVyEJHiLD=\xps0vٛ5|o\{͸ne7ywMz}57k/ո3xo^WvƋ^=G|on 1ES߾ϽižLbVєX3M/k?ho\q}Oy[?VZ),Vbapr ;~9!sЭ3.Wнٵh1GH[ew})Kd( m8v6Y8~L8)ey!Λ{NQ<Ry1oY rK`ڃHH2[C@99ڌ /i`e/߶8kCn\ҩ'\x݀í^xG_qפnX ՞=:2>᣽01,{=w"ᘲg{mSSgڦE. fP䧫zjt;+ cʧ=6ʶ tʪ`^_DOm;px3jN:Jvo|y,>Px:kgs,}/ BDZr`+?SjmLD&/)'eeo.:_ZŤLz]6^mh}cN]}fA-E-a;Թ? Q) ,_`&!!iغd:pp@ z }D^ލPg'ҽtQ6q"kS>%{t,5@R Oavdq:g5Á rCD)*[Bhq8Zrwr/ bW{ZڟG\}{ W.,Wm\U3'BP;5T.{~p8b(U^<~>|OXiD|b j?j=3Ik_,_a O)A9}(\U>qmC!!ygZ^BF1??A<_m`W=oyt#db߇IE\8;zfMO&ypwCt^tƉwUwv|n ,dĠ a{,uӑ׺aq5 .FR!μHxwXN B:Z٠|Eq}AFi#QUcwE}<w[jʠx| wSZ!檙}WT 'R@Ajbo3ByHX_P""CmB2SRg3+oXeJ8̙' gi NEH ӁB@"Y)95]ӔUi0xΗ]yTpڢ $RQD*Ȓ T$Y":MX RJԾ$-\u5 u4f f\7ns`΅v.I֧Nۗϕן9׾.~~=ͺ hm? ֍[%!`k$Zgk=-u܀r/u^U~Ҵj3ֿ{?W]Cxض_DD5&mmd:dm+BvX[-[Kx Ogvtp!]3L HF8GB<wNt#(:[v.u]ÂH*PB#2#R9%#ptji'YBD87 Dhpn08# 929""rƙ豨  7gN Jglt(>&;7p {;y_#.h2K_yxТ[@M)rञoǬo=G^{=R-~2fbΓ%Y*h~R~ҧ0$@FZjYpXVu ^l+7ݘID4 ͍.kUpy7~OtMC i_ľ[NpŖ$ ]($ݤog]EDIdџ 5}4 B5v_DfҦwEκ5f!Tʳצv=Rdgߺd7~yr$M/&NjU5xABh[E/+="t]W/-'D*?({cKU3RT-58tȷnh_lk֝ߴh' sU>PjP8ixҦ}D?R@eypekkWzAP*K^P*OH٨}]iK=K RڒPyU^ڂǕkm %Zd&׾%?+4"*~P1&|\UmZ9R9@f>X%PHlM~9Ѫ8]^y[xFz Ɗ#*R>\x{|m)4)seEADgGC!B-wg`x%y$ ,Ly ۢG%iH7Rm]QW8*j vh:r'u1xiɷTVISee)zgt\B<5fu''2]2yJE- { MёC1XѝT_B% CӀ (P( B,ʗN5%CJ(T0$ѤP8#K"P @R^Y ,1h 3-c7Su!r4)-lo=pΗv%k}Z*;W߾|2-0E$cW羱cKT{ҥW!ү}|4ܵqӞo{W4O%_h{EꡙZoڤ%?0|vx]-{6 _<Ƃ8?wT hn[|iusg~62*spS&iƻ?!asNSv"tg~|Zdpޠ$ 7tàHH8(K5b:7R92'N8cB9:1H sDHBh0dXWΒ:SU]g 83X:0 W ibZ+ { z^.FȡAuXCgWfbK'g I}͆">eGIOgUgϐGOEFTjS;Om =рi$wYLD͜Lȭq'欚Jι~qF" BHO;5cZ`s˘/#~߭;벼5 >@IjeC֛)${,29ia Veq˄gl,FUKL~E3& T.uQ X Q1d^ʷl0>8PvSb\DžXXRO*uӻZ4!z 㬈GN=Zj'#DpP'8>w)x;ՕDXy,(Fx?w^:l_kVE}x  AMwIDSmsy -yS‹!r55xTݜ(ORuaJ ʞF]<#o9I2ŢiwvJ vʢI@a Bi8lZ.rH?6: 7 Yy2sѕʆjDKJeÂd5갣S@EM[4FfN)= M5>7P uWҗa;ї?+&_eIB<.BǒM!WjfjWFDWuLۮdFͰqُdtguu:kFjAD1c=<8ppte+(e8cD9qB"!MqXD0`(*H[$nE EQ@q$I" úPY#TD,2 I))3C)jd9UM (G *"f~F@+3dɮ ָm :mUkս i;L78΃g2umaF*}u0P㓶1L70(As,J EGE"E_U@e6Cï^{~NWS9(q)@!ȾtMafo2ܿZ4YA&b( 3 ¥ZEDj6#0ĢȂ6qJ-=x*}G@ 6&W8*1Hl,xWgzǸW9تGc!E-\egDj̳ $ ѕH@p!(*@t(2n.5C2;D*`qH,.|Sf!Qk)4b:rI@xŊKth[+roq3L@_qH,O-:&M5^ʗ).}cUnA˹-7&۹gT H+$@*_1ͼ+Nmbz88e;$E1a:pp"qR'o38*tC D=&G֟ҮiPti#rhYGd38C1npf0n\ |J7Ƹx<;Ɇ7n2OO0AϞXQJZ[+틢s&1_W&ZoZ01`!{I㪨I+8MTֈïtmJ @bM?[--NjE߶ʥUc&b1mqF{-z4:V$>=,=_U٤ɟss;â R6 #x3e-u* A$$Mr%xB i*9FIIVգd,W&v̨bCLrP):AJ[Os{+b4Jihћ;3xB-KRAEģ3LhEA$Q2=i\YM!ZQYL-lΕ@f'Ny"]h$;ppRqr@/O?Up bo)e6"!fxN(30[q!" O3(AHK[tnC!W-0D`:c&93f08mJ߀=+9C0 Xg2ylLj`TL-T =g%2ES 92qݒl<~>wkOdRb-7;"i3ts,FPJDI)_q*ÿ!p? j!^C(cz U6QJh[Ud D7^4hfNs10 5 =>@@;ķ[v"ҶXm=.Yo0?"۴ k ^uFSXnw'"zf ;wZcǮM_33H[խR,,] SdeY(T&>ڷ%·񗇆6/_mQ+Y? %ah۷';SsUY&<8o,_Imo /sض؉#U-IwUJ0-쐺ot )ԥO[*&cdcr٫ D~98ʃ.}IŬy qX,I9$ٶwթs^ FCr*';{[a~GGq@K;./T4j]kX  SJHdw+G+p&p @퐾e5 %0x'iQ/3z洫WŷιBu}6כּ=z0+uY.c>ʢU`xCr?X-J4nѠ.y">.{ws~wXXz"أ5&ĠQ&Fc,c,]QADҖ;3<sܶ,]O6˹93w{9Or@V]L3W3Ei6;ұhuΞŠFdw+&^wEs #dn83SgEٟ<1e.JY"VES$?c^$V2Dd2ƺ:;֯]֚˙RZPX4anwo^,Lq8kij4ܠi/bD1M~s0,3\#h#v6 ?y$e6V?\`= '-) hnkߘt#шqA Yk,I{4qgeM}(=97j1VW4\V "2 ž/S#g38owYUnӕWH59Gƌ7MuDx_|s;wޔ$YYQYVYdYdYPG2}lI0J8J !qnf߅@aC<9c"r 0DH(QjW]C=dHjĭB0b#G9ihU#+3PIB)a$64F"Mu| +^~}j!D)ʟ?yOo>v݅$Dզ:!E$f9ook9f\7 {T{kUu(ؼ${CPO]R[x)Wou;)n&3n2r\?D\a=ZXXdbEYXX `)aqd* ?0&cAueӆ2tƚ}hTW#h Qq9j׷@p躮̤^Y\VB9H#C}@dL!ڦWWׄ QdÚLmpqmۼ:G{!F:g^pedLjU@٥y.{Lp?VG<$*W]\0#CbH`y.ɢ8#uN)%d\cstúgc] ?+vJ{⊻BWb <}]ʴY0bE]vfnغ;oƀ Wk!C߼_.QJ(9<>UɳmG6XBA5NE%Cu[ VX~ $v5 UPlX\P>~ˮP@%hj5(u~ XO]v-iסc{W_wPgd#ws†ܾho|e7\jIOê91)=)x\q4|\엝gpUGbi)ѷ9]^<+fi=9,Z07l=K}z[?P!c|ѣ~p mѽDņe>?-q?ryQ>kXS[tGXt44b߱JF'q.sF1[~"K4FcބXe?֨~|P=@`33Gzy/^^toKgo0°3duh@ĬVl p%HQSSE n7G@$G$Jk*d1rnE@("3 {e-9c7QJpi)ZK7@V*.=sQ{-1h~'2r׸҇ ,b<\>fN}1KOn⑐F_h& ԽZ3* ɪ҈͆T*JaP0CoQVcdV\Y^{6H +qTK5'j ]+M R: c?ճf;JKrmC!Mz{(("!hBЦdK*ّ Re {ݷfJԣw*B-xQy6{6?Jl}K;Hͅg¦E -+WUDedYYTlZKO RRi80'6;Fs=}ꐲDYrMydRrg\/۶,:YG}^ܽcGJcόR],,,z3mXxƔpK) 1 Ji<V̗) 9A9]׃@9P A񾯾zUuIsgUQdj(^ia6@{J5JcRǩtb RBʫֵ޸n/|- dxũ JW>|ykٷkx@ =@V_lAx[?gJ+G_ۇ9??91=T۱k=__sW8}MCoSnEALKԜ_G7 L(X[-0ִqRs˛|+F@)`Qײ-ER^uYA笟x@ߵb[`FH`Zݴ"9 &f۾֫P1񠘒 (|ehf n|#\u-uwb֯j ~ٸ1¥b.q@=vpǏ?2g?DdΒkaVjaYtfi]BCnN w /v.@b o6W:lNQ+ :#(Z#MZ 7!mJV=X@}Et9>Ϭ9gNۯʁz la߼Q3 *DZ8@oBM:!E"aj?RQ!Kb$~16zFRlٰ0׷~ Ot΃VN|݂p7íjqp_GJJ[ j+0g"v:1yѰSACD:1yѐSA_p*Up7 =CC\&*`%4J}UF0:ͭXe< #pcwׅ_ qpgb7lb EӇ)Dc LX`iţɜjl8yZY!,9~ʩ#?tT3 \^B0EMɒVz1H%)^qƅis ӬeOU3J(! !Ht8PC amG#Q`mm&#q0lÀqAkX90VԫVMףDbHs !#?U'෫>hSㇹBڅm@O.w[5=rp]wu<1w^ڸ"È膿4uG~dTKvJcNJ^1+ _ݤhw\=]aL,KOzMj kmH䵺PkL;Hn/-`i~d-'\vޚKH^u]H9?u'Nge[HV],xUlvo0=Cwgpלs%܁N7si}\L';8#}Ͽ~. vM3L vA I(XEsmGva})]TmF&<*{i"PJnYq+?ethi q Д{@>18k`}|l{T!cIM ~AM#zp@5gUXj?8\4.9%@dKCtΞCZV1p}֔x&DY%3QWx{U ־ٰRMD&W- 71s̞CZM ,)33LOznp>5x-I$V ^Nzg zazYHcJb2 \ecPqx cRc;Bm3PtDA\BKmsQY>auuyEB7cs@7|9HŅ7ZG-/KG"D4,26pD*?Д-uO՜>,O:dD,w ǞI->&.bW>_y2Pט'628kf1:S]1 OhnzG7_)N3զ}4KTYV6YlO/kO5gf{`F5 A=K)W1Ŝ_.~=ӓ.Nϐvo2[jʰkb[L?Sd{ʂgϧ[>̴@p; dӕ 6uqt4Ӿ@h|q\B 0p g PUQ.y͕abED_,S?rJS7o҃'UI}7TNy.=J-q `xq =>tΣe7v$ICݑ?Bs@4^-b(ȕmhvߧ8!lCTG>L|-?0`#"31`2DeKmmA$q 2&#gɴP+'bx7*Ô*5z8h$K"fKxlj9FTTzY&2q6@H;!RDyݔiU*NYmbP-C(i!GXD5-0_`ų|Yrhhe4D>~.?YKl ^{X LAͩ p؝vfeYDrI8D@Cι]8 ^3]DgeHs]Ka#|QV({t!0DDp@A** W c{rƙ .`5L3M==6;Wu [3A5<O֔W6[#Jɚ pZ# GK)e#` t`C$ᒄ\#NsmYg.X2߿t-?ugW 6f"=]!mTam`j/7,&)H,F ]<u>Nvvf*y<[%NCʆ v7{^hU xv0- J{!tMmj *Lt*8Jg7TɎA{TݡKLb.n'A͸SSƜ-* ! H$Ç Rq6MXKAF+Fx[Q9-2v3i4O7Bt؁wf.xyD<9jPG_H fKU)߆;z:Y,wT=xn'mDKEG84-;RsMތ<5:r;w\3INWFauem,IxWc; u$_$ǠXX)ћ`4dpSesͻNLmBE6*yS)ľ4#->Lzi^?Ae$Xm4C/$6/ͫ q+:=@ ,x $oSDuy:Tb'lb:,,,&֟ pO|)f۫Xy^D4-tmx!4~HiLD)PNH{/?-|51F4B#f^)- 766չ Ig)7Tf)΀VW0bQKdHl[{Tͽ>[[>=ع,)&zܕ[>''w ߄{c`h/w9!p!J#k47:-vY<+kȑsow{)Idw)(($ɲ,ɲ$&&zuk˖_?4%@F ,#IX4lG~BƐ!25D~#1`cXư!V( 6D )H'#v+!`s-Q!ТԈ{`nODpOؽH-Ʋ@A\n1SD2zeoP%MHqKt~~QS.yd+_)_wR m]WPA/+$U_KɌ~Սc`Z*0]!c.MOvƘVUvS39 '=7U[t>m!zSqmKGY9pxSwٷ^_߳;#oI~EoҶ>wN`Ұ?ږpfcC̶S% ,,3z~K:vc[F{R#V_ >"^e$Ecv†_Ql)J)Ӧ ( ,ɫ.Ŷmn֨ M= td6ҥdLWP{疝u6$FRfj:T]eFpwȦ%usL)*z(ؔ3DܛӼaD yLA4wT͊bhag9FDAE︍e'5S QznaaqH%AoLoԞ.g. O"|7#0ax1m 4v w >3$R2S2ď"P;1ՄNLY)mP.K K z<8=i_q:0fu(Va0IJ27SH@8N Ui2*M3AĨ ҄*ɠx(",2?-=Lǯ~m}KX[=Pk}vkK$m#4Jϕr<őNoJzC zæ~#j}$I⪆!̒в+^|U7b #]9ģNP7wn̰d9㊄$&{;]|1ʐ+& ) nv3<ʗM-0EJhG3'zk`$c+G@Bg62H/n ߄QFKL$񆮼+Nż;_/&Bx\u~dz9dbY Y2u#T[[yca%bw.%~M%E֥¢`BLBI8-_ǟH8iC @ Rq+bB=> IDAT`_H]>n6E!%yNdPd8]ACߡ5 sc8p?I+[\XUerfZ{dOqC,'x/QY,KMLJqZI䕱MukRU5JP7ݒ_Vpo\s[7x{ >ZEߣp'e¢PBPX|}aUlcNA0Iraeyr{"]e$e.B2U( A=r! G)!^\L>$4Kh{&BNLFd%d;dhC=?aE4ʦ^QEAHs:XkQfXlh ERg(^g_bxI/kG<~eqq Z狅E΅V<:[d56}_^FG"sL\!jnV}^k֪"Wׁc}5g'v6P% 힊fxM E=W0B2S?n0f-RpWYi}+ +f9rnq[]Oх,$d52p ۉE߀$VÐw}oHFΙ w¢ *nRc8"% 5M G"HDUU]g&Vl?axyf@& *k`kXevDnZBx]j^E FY'pϮn~5ԛ4?W{Ĭ\)f~\"[DYyv>\v7FK:lAӢ|Zʐ *X mHD9]GVoSZX9`%=b4S\%j,ZQ2,,Ɔ9?D cinqǸdf閦iB < D5#D!$xc2!cgS]YL # ")WO$Cy[TF2}x 1AѸHY`wN j|՝7x$֜gJԬ+rfW1Rn= ʑ^9°*c0f_-,,)!ygCcCWQ'(NiǴ/X"*q9D$icΩ$8 ܡ*R=aekbR,MJ 7*KW>}T BҞu 1ļ!H+iJ2yJ}(N6Iȗw7A8cU渱.}#J>mx~eXXHpH@=1#$D0̡$Kl_w3Mh"DڎߴvT\E.cWa5,TQTSΑGG3 n=!HvOIqV$&h|w?5+<9MUQOf!5B%&7d7 ́'_rPǀYą*HIrQ&]7Çan ,Hׅ^I30]GR/)EoMJ !n#9æM]Bj:,jtRe$H-_XXX${h}!1h"|wt6Hd3xvJ@J@(Cc]Iyv JGDΐs9L[rJhC)M`HiVZ'R||MffeM-#x3\0_gXvu{[ٕ h¤o<< xQ0xZOU;sBqe\ s)ֺ`[KmYXXX$A"'lN{; `"r)@BnC걃ںn u΁9.?p@}c6˩S7ڻ2S%qĉ=缳1v>p7 uӓ`jB D )!Mi׮1nͪrɳ,뻂b߫VwI5]=ڿQ}-G5tf5tlKQ}.']|9}AȹEڏ2ʲo{pi[) C2ysuBhCe߆MCuPCvl^0Faw]cء1D1FVxgYM2ae ԏH$Fu]gq*].gz5WYIwO4$H"V0=D$@3"8mݨW G[U-ow+闿o;V^b_qޙG E=W%f+S$^2Ơ6mەńbap$L˖5Vޒd[ ZunT*q  ~%,zY׍Qhx}Oڊ'_y9Շ]o_lWձc <9>x\D6 -- ZR|QLwGMo 7GnW!Äw8ںS,\ArֶNM7ب;cL8kyc7cͽ8׷(9@~$oO;?/y{h|뢝vL߶P[J^%FtC֬E_C YXXX B5 $S X$l]Uնcg׆M.yD sU+^S]8cFD'=mPY4Yr̝ {"`Bst:u]u=?ͻ'pՆm7]SnnaƷd4EouMtm9!`~?X?>T߳ZG3 Xˏk ?"#-B]ʱV8#<ӱhԩ-"n/'@_)xpĘlHN9P_^c2(gЍǩkDdW[UWNl:NۄVN9Jk^tP2w -ow5Ȇ[T XFo9VJ]M}`;C{¢;?E黕 iʎ]MYۂT,%*9ȴ7Ɍ@L~ X&ooW~x,$h:<кgz@@<},(אH|b+#FC[1E,,]I&q/࿟ۚh+EaTZ^HO=b'J>;%ܸd[o!ѰR"3&ZXX^X}rPڛ-b-[3 @&SH޴Dg7`SW \ϣHS3DX8$mUƕ)ۥ'Wīn,ҔnsޓUF \.U8g AM ~t|.7Αb&do"X`Sn{@xμOj6ǷTJ|S[獡^ɷ}^?+o z»]4H[h%獉.}[Əyc!LJ+1zX;@tSsWKk]w~ovWt}wL`B1齅;6$&N轆b۸t'iwآvw/ySvw{oZwGrdߺ7n}I3+ 7t q%;ռtS%W߾}3?\9Q^jn{rRfkGvD>^>u7)n:ke#o|𗏖X%Rm4:gѲfĬ@[ܘv(!jo6v7Y:<~Ajif)UYI{h@K PCr .+J~Um\V9$H?ƍ*bZ󡣤#PgpFV=T.\9<-G֨e3[&Ə}tCW"; aW+{ 5@mn<I̘gO,ˢx[$_2cyyyhT4qAdYnjjJe?M/LŒ7%tVy:s7C#Y4THB8kb.{#f)߸AwU(m\I8ͺ0PR&6ii`A0)6+ "Qo֩PfRrJZK`~ Uz~yuUӊw#P[N@Ii{R搵o|Za$+BCSx!-+>4>뙦tq#74LpmRm2 IbHYXɝԸjU'7%y[% XјР_fml ;\%ϕiSoAޫ$1qbdpRot綥r+_u }XBI>[9vp]˵7_Sj<+;Q^x bq {L:Y.\pѣ=n-8NG؅ WY%:CLA$va3zNC}T;@&hg:;tO`KI驗n0C $\)8,{xʪҘ s!jGY_r~$k?x{_燻n_oH\2wyfe P ~_͒!SmB}g6rހWPJC.>wB"KTsn[G_+nT=}pkϟ/Q YO=1H]沎=>ygvŗk+ݽvTN^(ۊg,=p.{fjC14v2Dž 3:h<:!BDuͯeFv8Oz-+gb D;FmSaM$Ic,ci\aB@@+Cl)f+2&o/xkޓ00|ϲ5S ]ts?|^t_Fw=O[a!g)/zxֵo(?C]3?c5y<M?wG^ d9?|U/OM9iʹ̀y0 hgϱ>VX kw yo|:u ͙}Fm.\poJ=k$a f…mF8X?z!;Pj> wxj s|BB43TRMn-sK,$I+u RĀ? $Șc/+[Ƴ]VyO`yS'%O5[lᢲFp}'2}HzWL9)Iּ#l ym{:w05|oxqRKNձspp…ޏ>#&Ul7)"4r+.z)^9!oXJ0M_n{ cd6;ĩbP ;_&X:4Ma6Y3˶ 0, 0hA cs.Ib'qY . 0AۭΘ*&j>]zFhy.\p2SKoK4Њv.\eM`mR7_L/JdMTr{^V&CVHKE،.2*;۩G]u@sY.\v9YԝG]" .rA)᳽ q|Cpt 2Mߞ}{fk^JSͭlZ2e7Hve-"9"IR0;{=N?\l'RuD1~d-bǶ.|$DέMm-WteB?|hۢ I)n̊˛So B,rWK\p@]1AzbgG2Y"E w@dZB… ?r2+YRJ-Ks&7g2P:OԞJ8#3;Ns[Lɞ˱Lx \g V_)oA2S=}E~7鿏H!/}kbxMV{ߊ9@pLh*󰵿ys?V M?Q/@hC{o^Sk J'%=ZGT~ GWVQ= 'fU~r9G: K/sυmo_;X\{n1]ۯѿPrN>GXT0lsΨ|DN:⛞Mi{w@,py N[o }~(;/~ |uð/ KVxP˳$UG8nOWp`nc߆ggD.{rp_] @EoCS~[w7KeR-cVZ/ Dd=Fv3GBУGfLV7IQ 6A QMP@"CE@`9$~'~%3e [`Nft}CyR!RODӝ{9?w?CtW",Ң4k 7W lm?(5nߠ}YU*n4Τ,u r RI @pH#ک@;K#(N3+ sq_HC{i׬gJ;k;=)$ɮ ˅gnu{ `fHLGg H݅a; M %~I)/=̫"3@f $4N:Skma@TMĤX&E` qe5ke%pC0f4< a;c |3z#KFwFm]p/h8`rXD`W`g>)?(*Ź\O^P xeEfDFoD(uFxsHkQZ5-jSH AB*ETW{YvlhŴZɖv!LVH,/iM`2r +|ênJH 0J񛅍M.Dy!kA-A-b_ZYJu'@Ō*QV CIU{JPܕx=Eꪋnwn/ӧ .\1:&5 }q7mz,b`! GFA%Jr>2LbLAIF0IA&3IAIFXFdd@LLH \#Wk$U Up'u#kZVW )rPI( A e2>S#Y4fWhDCiOdLf?$@bq}4`&?Sѐo|Za$+BCNɌ@(5/tE +S#\xN=K@+$I{{=ϯ;yp\u[{^UrzobEcB~ɳ1Ѷ$k^VUSC-)bױCck@g6.[6>ytC;=EWHݟJZkHй]ZEj}FFwE/t&M8)$̲}Ri2?2gŽ06Z1ɲ,+"K"I${(ddDI$d PKD \SIΣ$45E5MjsssMBpEl_ͪ&"P5 $83t<-"TF@2J Оn%3>Z!"s HHi =QǗ>UO`>\ L ~p{S_]沎=>ygvŗk+ݽvTN^(ۊg,ajf<ॗm3Ng .6)B=ŅVarLIy.I@ n= Q5ܧ+.\p@Lj99"A_.UdZ}K!C$:K:$C8g N I+ Ή M ԕQ ABjhdTn W5ɍmP B4Ex(1v{B,~`#$W,SXGB;I&a2\I9YEfl]pEU45UE"b"1tEWd+SBqӷŕ,3Hs@"` Upd@!NaBqM*k&E6H "24qV3Y4SDU~)PfyIď?ƖKO'vuDUv L^m9oinZpAcC}K¢]&-"4E"@ ܥ&90lb MYO6!ɭպJtу++ 7s)x/U{-g )IQk&)r\\ix~DŽ%W߾pbsC=Pl(+ #j%|U &+$@2$#!I2AB@R,".VS2q&,b4x5<1t3N[be2&}[|1rohQHȘ,e4ވ-nM*`1oIbbN #3̒5>z^hh=T+/?ix6 tԼMEBVs`[A#M!M;wC9!Jk~$'&d-ciզH:mwL:pM@Z_@2dҺ79.ŖN;:z.cJ676aJ@%rEOb@DHhRI(#Rh b(}BP%4FL&20PfB_=d* fyduZE .D|M`ol]EsX)GNh]eJ8WnPRdlgCG^݋j1RNP@PIƎ˂yJ3b@0^̒e?/w臏Vmƴ.\lEt''sKi9MO-SSg§4e*㌉ܩbDw˱ýxi′b.טq\paGb_4)B 8MT rz@Pb$řM [:uQ^z]ߺL OBGn(l+9o'0S, sF "D@cH_|gB-iJkPK*9BBpc,\PxmS%?SA|Úъ$JN*Xq<&7:2.fCV|ڳmyy9"jSfz:ل>n_[t t\PoVH.\p2Ʈ$ R*Qך GB :Rz4ȋ̠Z &2P7 Iօ$׵XϗD>%5!眄A]^bX /BX rXd RWsn9p3k ]ʄBq;~ຏə苓 ;-YȧU3Y 4SV@}/u7B2!D1af7/֧*#J\{eOɐJUM$7uUk?t*bF#[ _.z4zgkW;pvBl5zIx'DDBg]T~L!1I0q &%:oe.ŏ6^+a~O/9XP\vfꥧ}2F,LI$4 L5TYj+_ rd~*Yl*YmңaC& CO}|r3", ~ "/h]9U{/ѵ'τg>wp9c3J*1f1m:WLT39%E-U|tP9,Ӥ]qV iUʧfVꛔ;{N%t!L.1]xN~g.2EOf!0.\pܓ= 'mg" Dfh龄sY&8 %H1IkʬTJTZF"kƹ)d1Bd:Q,orCRM>x8 K}/! JK1}dv~Soe|ڕW_y[@]ïϓGݺ#BDd:ٝk=ϼ.zK4j͜ZC#.9goK޼q87}uyC_r D׾u_yy97<}s o`\!, f\(c,ctvhRc"RU59]Q}5Y~w=!Hgoh*=4A M*B܉.J-&Eu|aNe)7ՍY~mIE29?:d;-m ==oڲ\ .z'B`0=!ݑy$!I %au/3Ibh:1@M`#U D  +J$5L.GYiavG{i ̌ND9 ]J0Y#1?#iFjꪦ$f<9BDnJT)ﯜX47{D ?qY \ԥaԶ0EK_sOax/tҴ|^v¤S_kP3~V ,@0ns{>uȓs%A?p?O]"hga]ǯ~W'8pWq '>ۮ{|i{{낕w2DxDo+B=JWYq넅SN9O> 9qN<x&S$FW>^z/j%iu'?zJ>m؇.7ېeYӴc Dꃿ/47 OkfsV}Mޱ3-UAg;3kbL6y/aT²LhT4lOT@QŮК>\Hbp: b\ߕI+-7eN{͓ uK`.E#{tte=zföa)>"#)>4*SӎfB̭~Dk֬noktBSQQ\ -LٍbX`@+PY#>1_dF(xs"u/BhƎ[o 1Ɩ.]z7[#WU%KIm UpG$inWUU5΅W910|No{D*%3%8+⑕>Wbd+<~٣W{&c]HǴhe+'+Hy =x1m:Vl=``_{N>RCdy%! *l䚦貶.?t˱TjU+Zw xeltujf^3[Gn=nݗU-ZgՊ f`5yᕐHD"P%%)us3{n}<0&wbq}oxh'2+$b_{+_?OE"(07LK:b6K:F3YÌc[ kH0 Fm@:}D[53m]H~`k<:5gۇ RjL7K3U~mDTĽ2&@i[eI ԵY.xm7;^˞cM n[Td<ɵWnaMPBMXHt<ׁ7;Q.64Um[Qcn_~;M4ΎVWWU 9sm<k#mA)n}@\/+?z^@YO˚9 reeGRyÆ /())?n<0p5{UUUCCCjym5t)".h"!HqEUtm'Ic9f[9,-k9;+(M R YSA+S+Yrt҃߱T/N_D `MB,˺0ښ6"#\YYU?VQyKH(nF5T ,mZM "\Pp0-^4rƜ9,ŋ Tdpc$J,3I,X1&J ,W?GFs$hPny@R^ ĊnmxHPUM;5~pۈ Տ!#W|Boӎo J'%Nh.󰵿ys?V n}owڍm\_T?We=X+%PsǵM@++>lE_е5;T&3ϫLl xŝ*rh/on h7ᅋ{ٯ?{F6/V,ݯgH>Zr|zyVp^}:7)=59Wܓ[r5|R[^"gf=pvu ҼoR:&:yRbra4?~wɏ?_XV=},(\&0"* wk%mJHᆬ n+ڹ FSl ܸ8?E!PqÅר̣w~Q(j'[)β^TM*iDa◳D4.Y\n".+b˃JeJ}q 1@6i Z۶b%cǘᯓ*į ۲y.\dM֭Y3jCm6ԞD>o؈QK~zcIY92 ;}T,+"ḆtXִ?JoVƚ6~*UU[j;R\\rq9y9eh13ZVV+=$kaAس0l{A^xh u>nzK ܝ}El/KkU,"qysz}'=n_|,UMC&8 eMZt^UOo<^2GMh-4p%NT@J͓& %nĊxFxſ+((ŷ 8oP@ƨ "zp4w@ =eEvGuHt,TK 8)?oϚ~KEK yVz/M^WzfG׸ K 7v>Ӌy·\0˂%EAVk]4I ,;]?0UW-抶+O=vbp1_U;/ rͥs yT)٣sj,)D9;dz__xq~ߕb WZ0)x޶',SwW(u?raNu/hŸY7Ot>87zzpfokC 5dMA<ƜDĘ^w֏)'+}寬<{߾%R|'HRR%7~FDݓϲˮ~εkuLd%;hVվ~#%]ӖrfM kJF]G+,%꾒 IR0;{=S M$fy@@ 0dH\"\$S2Cʦԝ;Tz!.yfE]9ƕM  CʺBOJō)3yAHҬ70oH1{w7bCUzljk/SvRAUY\-@Qm Y2#O^ XSxo_uHt.,%W Α'gJu,P @IY_}rJ-v J7);IÃI 8&D#&%-RS3n q` ?Λk!H+khgo !8(vvKױ@`F7aﬗ;Erƴ&X,#k(jrcl=t_e9}7]B={bd뷃 $*T3 KpGآfg ڮܐ r5"Ң~,|m"ڮq'86>OU4YQ%:%"}Yo !Pg$)"C3z4^>Ĩ1 cƎ||I{GgsKksssU"4pC|ɧY99]r!"Nwaȸ1$>DKNb&>1Z#79sŢ@%/o"Cy_ XVneޥuaֿ{aWS G<5MҪ?q~Ž*xpa\yK7GYth?ӇZ[<=W}lT;|._-qyMmQP2f ŏ^`RAòtG÷Hظ3Gr.mDx}mmm+J$@ "Cb8]$AŻ]{v A;{\UK_[.YkrҢ/,8:_HN7HʩL?m>ObP6"`xVA?Sx)$ON"UNNt.5 @a4d=kӺk~ N-'7/;;[w.**\TT0^³?0 p~PG3(jG(TYY G"@cI,(3H؊[Q2ʗ=|,9Uv!C :eTh#&"&+Do=AߢɄ2Ci)v2;LƒU=|m$t^z+&V4_ $i;+1 Y7 1 ǃ1dՊeƌ1fLN’WY2!HSG8%7E]ak,CYւZZx 43MMJE3O9cn8{ $PssTκ쓮(5P|,o˜йx{DhMk=ͶG`Tc"H%w_+ΞU+^ ;Z% dXkG-"#{5t`Vr(Ϣ!$- L RKd 8 r@) wfǼ{KOQ߾ Cy€7$ s$&}$#1:gN1!&u: D&= -%٫d M"oF,鋱uٙ-HmSmdKu3"!%YSD {6l%q&ox{Z4)VX3Ϝr)C.W16r~Xܗ_Ҵ?OegDiBD55_`E +,-Ύv6^j!{W_wehz#B-FvCZn{  .)Hmt{l;^~ԩ=cS0V#ۓDGڳ$8,ʞLP<%<; _?TL IDAT:&\3jT(hTJjJyIemi-OK?@hmhvU8-.^ ɞ]=_:Ǿ޸}|KKdЀ$;1HMQe ͟Z$1qbdHRotgoc98u'YTRV{HRVtu"\*ﰺOj_\cދV4)m"mzYMMPB` YH! - ˪jj膯c# B7[T(kW(<83/2\S4)K~P$-yoURΗN:c=SNb6bilt(SExeI@; $DPe#b⬟N \;S2.Z ٟCZJi <}a'IՍħdf[\4AdEH[d6I#Ԉ]w|EoB*ގp#p -r@Pk轆 )q\dْvwf~lJZɲr'׳S|76vHpS(O9cr(Te4E$fMLӸ ey Ff[nj $6a8$gD4s$ l֘Ѣ#aRc9Gb4M $nV|o y4A~xYo-m{3/ڻhShk֬ s9s bٚkWy]j\t闊cU[?n13??Ūժ0dIp @Ī*5ho΂g+ j[w$jmWnzaDhk 4F: 4mԔ1j/hLHpLo,nȩY8qSKE%mE=~sám%gX:T4$ 'ђywUj=J|xԝh4*U!Φiu4J~ENiq {ޚ]2/ c\L*ݬ~HM{\47:e~ל1ͱf閙%.j~FqQ9Z@n?|*wJN `k*m3_!?>NulrM{{rl4i]/TrQ/ҹl{ck7|g"c/@>WxiM`zoOW~T鷶@H~BN_H>F?PZeeus5</-B.55mF-:/4,,8>$THsI!G9C~T*~'aCmאضH. kR" #4UC$x NsZm8T5T%)\I qh.1,۳ #z:\lyF@B8gLѭ xɌ{CD"23`rA] Ƣ%e3~l貇/#<}(f͚缠jCC'gpX40(aZ!!srr8 cGc * Z.]Q2? 5jcFH8. Kw;  ! R8F)c?(Pv{ :q݇[qY -jGO8ⰅZue GO w_f:SUXԤ$e.bՂ2%(6C:hlh0ݬ.ho5gUHC#vK0:L9 3 :u._1?|]-L;eey8Nmgq,pH<Bӈ=Q,看+DQڙQ Lu-SSեI< 1c r3nTQ#ʈQWגﴮ=%M(ySG_d>٧_wGVIK#NE퀿L4^WZ$P4 ?5S;5!ll/+!q8ZJOڃ; M pqhڸ~Uaqy0( T?w1eLw"4ƙQ3E!Qn1C 80]2I~@)W'[r5&S\,=s8vlkZͣM* 3y' {bJ{_uÙ'#yF|ʌ[mkz^s}wM<ғFB??W*>6 lE.S-ϱhsIf$].Κձ1bCRl}\3 ᄆ_(Ō7^y|oM2G=8%ٷ5.+srmK$NI*S<햰{SUhnǙ.1\Dr9Mc1"JUL(BU,Js*2|e!PSUM-cOA 8(D gN'wWŭ(y[Emy>[Lm &]`i.^(ȘV !q9(tn 46Qz Jv],}?~M+-͢q/•TԈx_xh%IEEQ4U,ePiQ(gsF9RזWPtHB@H^ kLQJp2@8Ps!o^e+=?iUUFoкşM|p\(? 7#~)*{>|҈#NsԽU)*GΑs@9#++++++ǜw ݹroט0 :Kc-َnz*LlŖNl3VϾkŖ@,Mv5k_\+Nm?pGҎv㓓@+<3tv}%,lSqZh0ZI-`k;Mڝ'KOD0U@"xɺFN0Ig8əP ˄Cv.Y@)mJV<:@8eQ_9Tg)QSd:>4TZڈ\n2Jk(!x&or@kޙ6x?lAO qޙ(0W*хBۆ/5{\r'RVNjw=J hcDyxNF>*tj^TEI :w.ڜʾjjDU4|ѾC!YsGf8]KeɎ/ܖ!KrWs>05k+{Jƶ~te_z)êXG']&8%҃Nl0/oZy葢e׭,9yw==ߜs] j%*ؗ 6.)+a͛<-]j2"0MIL{ (1"Uy|QCã'4J(䔲dHIdqHGkHeć8W' L@DU"JT)EɳrdY9X_7XF7LEM,A䌢kS-qE)cDSU MˮlYã DUǠh1F$[@樍9#'g^/V8)X`7v9x$<;K,>}kft2pwlMyQN ƞ'6oި{K"MFݍaW4|њZx y P8N5 QU%$ .-js9{և4ԆBmRMP54ȝw]I]e!HUë9w׵UUc>|/Jsԛ"pϷ~`[`<1BâQFf:sjÆ$ٹ ?](@>[uCS5~o L=7U?;iÕena|O02"#]-9'~,n OXT2xoo6Sٴ!m&/m"S%'Pe4=/AT\dE!jf]"U2W8=RI⪪;}hdB z$3S"IDQ#$88VG""ei Q*H_ԮKg!Q C Fz:(@wQ(Ȳ."cш!($$?$)}$$dk#u?qm]q (%!g]pQe7]گ_Esgl)7.yq9웿UH}q `pꕖ !dĨKu1T}QN}$v4#!=9Hd5*#0fP~,v`S@BUU¡d+'I(z^b7Hhsq=_֠r_3P6ka{3~]rU).9kV>s FY3[˝x!rE8Hu=EB7QdM߾z@.lҹy낌~}[veڝ{}Ԙ{AG,qoûw'?V5Ov?FAkkI$nFu[N׸zQcv)*.,R wMPD"MuzL(w^qұj,|S gmRvԆj_@?cި\z?p)M{HQiJlX! 4>5|aqr-ͨ-mV=Memӳ^Z#0=ZqR`\ p`P3U]EtܥbM+ɠ芷$ ln'1|t3dnZJA"1 I⋳mX++1.dⳌ۬@"(L!C؞H>+è(:A)D6Fl qc5Da7(% tMA1.(.[HãC橾/[ ל:%&\8XK$Y%kMJAG#/z[Bն1F3tkVr]px쮻BTU4|`uu9ѮrDssD#A@ r3x~!0B0ׅ{W 5RUiAIA>4 kF)n- s׼-Wv&' kB;d@ś.Grݣ{%o,[& H218BWyP̕!Qm{<6ouv[ըX)\IUMV`S0ޜS>yȱO}NI ?gUz4W}}uro)K\*?3(`Nۛ~S;9_ܼwyПYW hs~" / ߃FB-oMUS>P:]ſO #iYe !2颖o|V*;u~kCBwyЂ79\1GI>~Umcq"p!;kzV+˾fr`=Ϊzh{__]x~t፞gK*ʷXf=O)(sb<'|@G|.0If^2*G<֚2zAs"(&f=kB9QJ> !}2ArȾ = pn)*p`T@n3 C(o\ÎI,{EM%I׋ޠsFi BO%y&089jFy C\~V?GJ_%7k׸~>qE(>;NJq(M# >'}/(2GwOuG'0m#F2q'CJliؖls)[f JfY郢oY/5'M҂O a ֌~J}B H+h u_*zE6;COhh羗SSM!a^ xUE!#/mXLo@|$?2x@sՍ⯿}F[29m}1Ee* ZhIgz׷;GM4;"P8@],;WEO!XL[3jm /~6 (H2n3SF)cz GDA~|;:r'S:q%q䘱p8dRFWPGn[5v5}:75E\8?6g\dѕ[ȣ8kO#'H?VT}c NT#,2[]\٩+2uf-3lP>[S X85{G41(2dbm1GĤ&~Ky7j7Q^Q7T8TkCu_IhhIixn Xť2S~?V\1BjBMs/P1("Q6#,6*}rTZnet"⦹ M}*85\}[ u\})Q_o{1,oOFNR!nlAC9rf4^YtLXHg>jmp%dP;w ;EW[FS$:qWh_HD-&QKsS$ _@̑IlYJ"E*Dј]LB* iD DVTQI$%-Ws \{G 1rԘz Zv Gxtppp%7>7]ܱ;/6mD~/xcwL*-&or.$F#9O؝ %rS ,7sϻ[lXq.cb`A_{5<~G%W4R {K~;j#3^r?>/Gij oJ*,2a-S lͺ8^:$tqѨ{Upj(pBBP>yS+ 3⭂1&̦إfPcS+=LQ|39'7sK}U?11p-i(ƌ AJ@mX 7P!Ԙw֔?T=OLH4dA) ̓MQ昖&#/?֜lӢrRO 6XrhS*m.je2U |퐓b\?K ~ڌIɁr@M+$gd'9g7|+*}-M`Nu:Db|'pXԺg ÐE[u\ z8rFYx֎Iz$ T"onn*%'9KvKJK{e[Z !;u3]v:^(3.+$"22UTii/r8s\U ABA$(( D$$#?AjXz_~qqq a&i&'S$7ss@ni!"pZ<[w-whi‡=mʅAxyƅ_{+_6r['ݵ )X9.'?i°< 3OkdwS s bѻ{řS7wPYpk^s7aǧ;}墖@C,ȡOL9e?My!_VX!~Om|Vq Ju6qNͅ zՔtȺbi]:.SċGPrCk@`!GcDǩw|SByY#z5mdJW@s'_Ҫb0BgW\@/73W'떉(l";N3VHmZ: (5"&o|>"rkMYwNa,4Hh tQ;N~VB 4 O=gn3u8"* 42WdS<|O`CG*Uah]ub] 6uD3?ʥj/Z+dqFb%BGM!XMrwD _I;|5u>]!VrGeJOޠBE_Z57<m"%;E {kuQ.;9P1绖NZ)$Kzye>ZxYDhYQk k[ j%y˹DYdŶG/T7$GGԕ1Fh,\8pA˖攕Wl{'y^Aa[| "]u`"^8u6= nFUik3ƙna9qxA4A%] D,OsZVks %vVT<KB4`A1G\T;fݿ|l2%'_ =8u4"r vӀTY>rv?JtAz+ H˧\K⡦TLXۣxoV4ip5ztUwXd?:Nnz\VUj=J ?>5_z/>_zIHk'i'/ܻjyùm ^7o]/=R~Q U~n| 'W&O\q~V`s4p\|Mʏ ^<oLS(J\S)Df+1Qǻ] VE`).XTc `TU4Y^~kr‰'2}I%OKv\rɒ$˲$˒!n!4(%?g{o:/}k ?$:e8smᩎI D[h ,Yc}G(k Gەeu ZfM6 74OʰG6S|ъÙq_ж<.$:Qϫ!1FjA((wlщPhLA8pf8ֻ[H (]qН/\G.j(_O9#<6D]wH3\pƍs#g>y[ >ڗf=wspa;3oyH?0ĝu߯j^p){*ˮBvNgW1>~EQ$IE Q`7y+}:,s^j9 g+jy0e-ž;[}K]&jfmpP4IŝgņZkY4c('4ӞITJhڏ9 !Ј1DyH0LK`__TuڵYú}FE ;_Olnxsm|R:|EwzȬܻϝѺS3g=zs1Wȿ=ɗꆄYd:0`ޖ")l˘CfVv:ogu}v}c^+uWzu sp4koqWF7y,.x¥X8iڭ[Qꨦi U)|:N!~ nTe)ٌa@Fa ם,6 U=B,s̊bIeLRl+bfh b̦YmLKKAW~JgHCH,il9fZxh]?ͭTZ"d%ycF|ԺVH[W`w*@ұҼ/Yc] ?}>?9R7W\"yɯd٫,z׳ [" X'tCdSleŶEzvhk>'_[1b[<`sfO3PXzW$v-LإE/v l1 7hqҕT,+2\07VZd,"Tcy\&ы]gũ4 1~i\FMOEë;p*zEO]1*4jɦ,?]EHa<>NBqFx;ƌ;OY+C±xǚNY}G)~Z%kmMkg^ zH{^RD,[ؾyUtuv[u۪]<9W˿j@tM9z+ D'cwEfؑa~$N`e j;XpX, h@_氺K~e٫SuRU1ޔmv" Bh05`Rk:; q&>8`qu1T9dmau}_b28ƈ !]_q8W)W5ELS4(gr v39zJht\:Jcى61΍770GsMh%h`n,V +ug]⇫8nGiX.;iiӦRln6j 5%MzhŠh,RwJOm7BhmԓTe؞'ԝqbg ĠgJ|c IDATr>}V&Yd!-#̚Ju,0-nr*3ނPzQUJ݌Vcֱ-ѻ1yFļ:iEIv+)sҽN +;xfy H>օ]ɯ Oӻ)dv k 4oK㏄ kr~Y%3!b nhLY~L1TN77iEg@,*× YthڗD;5lH.:LGDw/J҈eKXWh'=1U9`PW&c)'Y$sN[cǨ84/#6pB ^Q_;n"qt^%/&+,3~SrXML`J6X$1gV˚,2&}սEZ& #vKvɾp4J}cҀc׉[=IwJCi[!orn2 ]'/0*7HDFDdζ2Jp^n3.s>CfFB%&Xu1ђ24֡շM낣B$r?,( 0 n[MQ9eցۀFTV6#7Y8 24Ksk',a,ꬸ8 ǘV]''!fe5p2ZǠcM^x^K"Ӗt#3-abGw +Iʱi'/Dqb8Kpٔtq;FcorX}eM.֢4J^%))C܎1@;^:HP@B =\'ѣŬ, %wb' e04*.#+qWBb!zT[^Qmj0LUj:Xj\1PzJٛ-eU 7f?ኣb,Om1yEbwθ(b=eQᯟYHLjdádv~D9g%UYd02g=֧/Y԰omv8qx+;:^L+8ssOmrX^!βc`vdG*UPO"QRdIBmr{ڶ19bc9|/츢bJ,dCT]1 3 &-c;RZKz=OgE]$`T@n-nt'o#G1205 VM^v?@nNݳiYɸa!b <P @)zU !J+]mV<2qKD :͌00c8P),0 E13uS:ư]DZH-2_hɴٴ8f֠xH(ui8DqN-)+@Y$G>z@~|j??o)#Ts(%lE gH;,[EŖ,~&kHY. EX;VQ8ހ "Ǩ$V+wvу9!LBìBO@씚ԩn6E`!pQLx{(H$V0  z)r3@јJAQqlB*ƓPf9NU\g$RWKKaR/FΑJCtv*1U ceChWO , M^$v/^8-Ⱥ1F)QFF5TSUm!zMӜ H^7(!d1!IH@BNZZ؂u}ȢSpMK݉W|qW^TʎIՍTo-,L-5-Ip2`^"1Jw0!$eN̲t OL9UqNGF;`UP3`'F2${L6f}F<D)%=0. ILብLM J0Ԭ8ιD̜Fߒ ,8p)aDAla;wg𕌞"isN9P8ӭ21@gzŠx?RuD.ɔ!i ,D/ƨ\1a!WTTVe̯tPJ5Rib@UH zQSEZH6o{B,\'A";LEvE߀51s]϶7>UIi1+drt^i&L3o)?H]"RH8a~  9qWoZTvg6^s.kpɯQnM?eն}ʳvR;˹QD砮2Ә"S eF<cp/xŝ=8Gqi[L"-r*4YBtm5;8pIMGW$7|PuˋmmҀBnoω%]Yp xvsىw4{߶Sv QBTv綎XTBv:c3J[XW Փ.|L [3$W{6p7a^,އo[٫Q]Gnȳ,:AZYmTwlSGzpǑhaBXa?2.bߜa0CYtv;˄.x/qi &3ㄓdFgaӝv1&v;>1n-6[8MćOoY@fAdM0ئlqƉ9o/M8s mf贗S:1h!~2ЎKm.]RvFb?#9e-}\mAiЪ0/=׏"+qQ_x;C~zkYɔ6O{eA"P rKU609| W_"(yҖ忱LҵOP7X/LNy['0{^&:v 1ֺ;*j?Umcu6nY.·j ;{{c܂Q='@׺tAW rړMua*Ao]aܙT ѵSiz|!/l@v 7o}LFႳy%ƁA2=0ƒC c< ,8pAdumIt?.(xxr'蔍Fd9R^ch)UkVzevJ(5Q8NB6˜sv:y_'Y9Ґi$ɒ$KRPƲX,aaYFdzݣc1ʈ2H2QRYB((*DUTJhv.p9O]gdhO.j=\ATϽTC7_ r!Uz~[+V ~.Qia|nL/`sKB|I'f%hI-5NAn)\quP HqnߥN)@n8<$%կo"^yjlH&.i*\Pg.07~sY݋qbɦ_9yކk'ٌmʥwUF %#8 @ gJO}W)B}Y)5sPD؉߂;~MiwP;U6q^AvT_gf$wePZOG;jìV4'] ZT}2g|b^в妪OxTj>*̻uwˏ{~>̘!?_7d ǞV0M^ ƧeCwm%g\\֐4I۫+>7(EIcݰc{ö_ C ^דQb)!(>D au:2(& dliBgkv6d$2\9Iх)dq 5ҖK 2f )5V 4=P)lh-Ncg<%&3R(t0F)!(c2¨9)FUEUPFG ^1Q1B1[1F( E)6gZJ̑}?LxO vQ$ޏ1 t:LB(eÆl f;!kEO {Z 1 61;]jxP9Ĕ b'D`CܑZI Q'߈n?]0i UP R}ra,}Nz-I(jm1N_4^/}fIf77j.^S1y,-fId];^躖 ޥu4_8y)L)Qe6YLHoR ;2YGV{>jG. ɂA| :iW}E8Q0ƎXY"W\o@!ƦKBX:Z IDAT+?fxzk"(!'唋F5O/,V"(3_=q7cY#\!c( eRDB3cFUNq^2 !U#+e2F!Q% %ڹ\ԩAD>dCEH+=5s6U͖TB]3c/ 9!j9a|p#qM4)xX>1Xͳ&d_8$66JYmZUĞUv˂r \ʝrEЉv/"soFFdCT8گ+T#eE!CJC-wKUtǟ+Ab鞽; o:Jyz9\UH"/_|_{rMJBLI4B+V&On-?DU cYԾ]HN[ΰkծQXEg$+yͫsb.nK)g5V4#eäpN8)O%c @@2>Xz^;י!M;(}>|M-g: UMAO;E7z6tyg^|XC$fL $]lȀO&11sbjm):tPXy BC#I}!kcR kU&Q(g Rer~RG+U%ѝY<]-Rh5ֆ(-{n/sJs7_:dE9wnnٽO5Leٛf:57#U&KLn'!myK͟[k4KvTLҁm+ReXQ㝪ϔ4'!̀im:PJj!$Z_m1=L 㣞4ь\Zn!] 'N<ֹ/vwv}iT[2wxs02:exsky5շ؎}pp 1ssEٟ}]>vba1R%%5ʕ+;ŘB^V 7/k.ן")&L^U88Si"aV9]Mp(e"? -J#!R½UB)f! +raJ@?0u8bG mtB ه$BV~470ƒ$utt|MMMXL腧?jXp2~Mf2e8TcCV9-F͒`ȇq2qBgMtp|O%іSYWyT!RuzDZ*9]"'^м늊T\>=>k̨JZ'Zv_-/H8}\7Z)D29jH_jAzpb %/2}Y SWeJcGe"r ulyyǎIaagUJT O mg H2,S;,SPJ2,}̔r5*S ~ʔ!CS;IO/K|F""u4YTN8.2G r yNIEd $I1 R@YbfeI ILXp#`tLlkHBKaJQUD Ĩ&`l S]I(n29ϫB$f DD"(jyYEǤhz5a94HfD'Bݙj>8XP?MlX4,kOVLi&dW>1DG*Μ<$yᑪO$ePhExM(>%bnm =qWK1wAk_{cU>q\ EYTtHd#[ξ$eOU-@,H:*w2fu]՗b֦C~?z2sM+ Z;!vxDYs."4~V2u~I® ^W. ?1_:!DQT~xmȚ]Zis|l_^UK(sU|Y';D'9C?ke@$k&B5 QAUн9-t/[| ?_G!Jcvq(#8^J4փUA{ԯ;:erTsg{*2J) UUE%_~=ז0@KFa !0gK$S=`x2|OEL`+ArXB'b:Jmi{l%y֨/JIC V4$2X%/g0FBHF|:2ʈ앨 3rV4"%Bg].uh;nct}k$I`P$"J (.*r#sxX3=te J`sޮAw1if!l[EȼB>zB$ɇ}~m@SQUރ,#,˲=GNd)Ŗ2uHol$r5:G7rrpX%cb nK K,;eQ`Te4Tb LBX*ƌŀ0 0Lͨj,aQu_6UZ>`C`k4 >|lcTF}V0nJBs~7tNk@&tӕ}[ ZF %ۍ,^^xy"G|x>|l |*j 5`٫>]0@PBJX@χ=T1ǀSRܢ_%*Aps%Uoe+*jm͚9ܜ&-fɅCyXZtYz7I2,GC9\0zk.jVMJ"E+ R.M$SjbLԛ?TS޼6!ycX˘RH7\oarclǼЀKR'Om:r"Qც[^,Lmkz"QǟFvGg5N\mt|NnqXtcbW?V`2}s8l*=na -b4܉g ꋓʘ*Ya6sn+qCdC>o8 U_nLNo, @7 G"}_w(N|PN+ec xXpˡ ,WFl堫MUM tcL) SҴ=Z,,!<§=~=`jZB LZJg )Ho^]?nVOu 4V7,UUA)y{[!lCk*>mGkfSuz9Wdn?orhG]6E.zQ•_X'7 x,㚏m JVQ_ dWs7ΐIoIu!H![`n'Ly׮=)U}ҫ.GS:oު>5Ww{ kEYLodA>Ǽ^սQcH}VEZX-p:U_1Y+Mʩ2ېsٟwO9(d\Qx|O ,ʈBI)^bX,HQ% 4,QQ Dp͑C4J2p6dVRhxT15HU gcpDt@Wl +IrcL 5nȺDŽ6g\Жn(H)i Yc{ IbFW8$f7޵0˴Ĩ]'5t4OZcthe;;MJڇ5Gg4|T1D^񝪪.u.N%Yi^ <t+ O_CU5ao|xNc >|zȮ߁bLaGq16Xt_wơ?_.{]Oq(@tO%BqmGI'E9t];XxY!J!IO;9Vz9[,CR}̗.yΓ6O]".$];ו?-LS%V>R]v˰6>'6/jjä3K@"щ 3q{99M_BR~~,ҐÖ2Q2<P;qDӳ2nȌ\VBιLÝ% 'Y0yކk'e-8E+3~A $cdSIgL7 SBB/ 9LDIZCrM>K*oyWpZg ;6yÃ^6,e ))M_mz`k*8 3o33hf-{[>p!'.kUDɈ(NzLwePZOG;JڲϣY3;^6=q^QC.z[n2gbb^мOxTj(}*;T fsc8zHZm ǞV0M^׃h!lSJ+kz$sgR-_S~Ž?_QiA?_ 4}Zr%e )vM_OCTɀ׷n1Å,osZ{D^_{zIiaF[`4N<6MyWE~[{|nj嗗}ۻ8b[)롶K^Òݏ{^aL+ dgfq.>¢NU Ʋx :aAȩ|I3_1n\LΟN6#G99H ~C`O,ֲ&XH#=H\0[6w!tx$ JT0(0%=k8]NL(*W`1e͗B7zb9?'S8\2 l,w+//ّi0E\g0]xUn_6҈ gD!3{t$FrJS_?>vqʈ`veE/||OǗW V{P󅣥%*J*lfm6`P (P"1L -r܇Ft({w߆ C@p-WlB%^ڗ*l@-E_ k)jmW83ǩo,ry,-8Eg.]' /A-)4tlj4Vw;Ac`5y,-Eg]1<ü5h@e8Q4N7I |,33PU $$ 4kzO+u=& AS'Z-YH%6h9CJ,-JѺ:7cGK_gP *hwOK \v IDAT> d/78ԒBe+1Eww0923q)6n_*'/$![^4dwoqV[aI[DяfRCmyUB]}.}T^9@PF BU:9Ӂe=h)|WƜ}6"BܶirHfYЬ ńLdf g0fg ,JY$I8dpXLPB2X`āDXN ޅ䎬琽sSN9ikVS}g!%!̖;* "?|S->b鯊sųŠL,󂬢0F)ѽ$jt"$yTdRHX]c6vBI}*Sf%j ڤZ-Rg7,dH[ ]ܖ\g_֯DЉƔrg(%:alb]WxAm ];uxbNqRbJ*< ă Uhy% cB^vWwmki 'EpNnnw;y(>|hȌO?2+½ òf.]agc Nݘ̉--+-`[FXp-N}rsiGlfurG1=f:BB8t'sƄU<:LdaEɤM@Q,1HQJahlMl; _ ,z\G>K>yQQ6N6Z-|y\}睄Q^@k\*;90G[#ݞ8݋&y`̉w]•N"s G:.j)F BǤמhMPi(UwVJ;x ؉)T4mf+ﹽr)M7i|.E3N65k2JVAa2%I#Q`ܰK$I#9"ٝotȊ4BQR;#r>4 @滿q֬kZQ~oֵMET X3nx&%0\&<"\!"hjXenGCo˼Ql$X q}H+\%N;TCЛtHkVE6+9K w]Q1+ӧGqD+3R9I]gTWE 7Ni߫F(WǍV L;$GR߆CjE@&Ӻč=UgǍVIm O1%olCKQAgDI'4 j&eVH 0tbvT>R62sT$UzuY= B 4$3޴/#<>5RkLw./H;:jFp![6'3=^"/ 5bF>i4V/J9i${1"*wBDR XFdt:MgQbclc[S?Y -t64f)f3 ċr Wvw'AVZ$&֛` b@AC\=2}njhm-_4Q헿?<5OKDr Xj%#]`AeR7aDx? VFET9yI1#U&pI.xV=]fP|JFz⮚bokX{:d/JϺC"{r%0m.{jyb2uIWϭ5M_}KY<.AYjC{^6/S {iIG[5-UzJHH-׷XRil9NV7Gf=yƦO Z 񂙋>魩o…,2`Ϲ0Zeϊ/Ⱦb^ K&"h3.k <{Oͻ Y-7@i,7uR WJ?;/vݵqHScET6y3OxTdm5dN%\[z;Tli;VD9=362cܤ3sf_ZI4\O!9m/A+."[rtVA>vx[_o >|lO?,^H^) {]{cH촃EN_eH h47'Ti,uX!,agtr,J#!fo>D *Q;snЪpoFv̈́L&Lto:ITGt$tn7O) BnQ(;g?pډwq_4;F0{5'ÀGw>?)yUz5n jn}zS_w גl;tZ`l ;6voDyϷK}|뢽'yp]>Pjn;]-1J3 K@7ƋNAtǟYjN;m۳+=lfW*,;"BcxtZOi)! X#"<--1ȺŠ97_} p2EQU1ZT\דN~mK@G#$!_R.T#!-v2S~۶(a:'ūЙ3VBɖ/y'{el;UT&wS87(-be/qC`\]X>/@< 6, d*%0T^aJ帥G pt~Mm uU^9~sE]D:4c G}l\s^q.AX:j\usEg:n{u-WhFq;>|5E m=ށ@gzdʅ6ɫ+ {QWyް]}5} LՎiUweqlJ W+ ˦ursKK8MbZz8"R;mֈ';~ĐrlcZcGm%Y(Ŕyv 3q^}l5Wa]u:0gglCn#wC2Y60aO;?n;F?K|1`10c3mmާaU/+5ףla_h@0m0J#/yq!vT%mBI֐Jb4\nlspoFnG:F9!F*,UZq&xZzt Uz!5G'n&`%.C iz0`y܃bFLP`F'=*X{1ˁBCY(@Q`YF4z㍮4<_cP].4GK:*&w9)>?#a|Ph19.*7k42WW]i0#A )vԅXjSt钪%j?׭VloN91#  n3qȓ>zBw>)zkW8)( )kR+,^7GPK{e!'',u6yJ?bnV2s cX$)b:eYC[1]V,Ga4bȓP0x ~ @E>u c.G/1NpNɡҁj6kRBՙW~=Y$Q~kl~v BB m]c)[ǎ 1Vjt20wjXGVN!'LnT9g4V.ME/'J(RxdgmtI[Nn⾲f9[ުݿC?kéeȚq @> _tqȱc(b0_D|Z@yQ}F`2>B (2 Yл {H0w̕k>ܯbbܓX) =i-=h29,KZФOHr1VS GYf @.mƤ3DH++xz!kyH+KW>@vw|OmK ƕ j#ZWF?>h[~U-.s̅0 .9,7SA/bdpXi| *T%!ފȤF!p"G7MhÚ̶Ѐ=~*O?,S40.5>|'rO2x,Q) ,B*P~YvL~`VQ9;1QDȬ<}Y g1MlnfD%@, I+3ɻt hN.gZaՂ1d/7 M$.po|MKK˰aDJ3D.,WoGXtA2I\EqYP_)DfەV6UBl4EP 2}1@\} F :'iFXghUp||݋ECڪQƘD}Ϡ>ϽX>|lavX} |ehSu7P6.-9k zly(THE #ʠ,ԕI/f)YtQFSX 1kfR.d_ZFl`rQQeaϬ;e Q6xm[:ºW4q`BaydxVA)~#U;ٍ.utw4B}iScĄIcڃ/--SQ򗊏8;qYZhU+麌aƨa [n~Ē˂|a |xu}+Ag|68]yОɁՐvAF'L_̉J[k zf'(wsF\euF02veq8]|}o'6$4 [=2 ;Xg"0 a5( y&{rw+V{xC'edswQ(6W8e+0Ƈ0NlN#$IcIxN1_uc,~PItPnz]Ɍd8%IA^5PzJ 󥥱zJд ү ZL%&ɬ6'_aQ9-d2o,,TEj{2#(z7懮*#ض/;$ć ven+xqj>|lo}Iryf1Ʋw~>uq0Ժur(4 r=p3{,j$Sӈa:%!"5Y¬B' ljT-w%00Z/5hm)teC#SS3dFph6lM] tKDr\a9TLKu!Cҧcs =r-h*2Yds!nbâ|`>ٳ]SJ?zV/rSc>u՟X]rpU,XOTcA*& 8wf`0fUG:n ūB&*LNtã$py"!K<(-!l9,-5ܔntpѽ 0ȈUw࡬D 滗lY<7gpr6YLe>z+Z ѾLNߣUKxnZZ?s%&ͳԮƈ~?&׬iV1(*Qށ9%UUUEUl6(JVf3]]9ڹ7|i IDATPl{yzaي\i#0'ճz{v 8{el u" _ou+wO~0u"}yÏ1PxuHyx)|n{%50L>8fri q1Q L$ŸXJ>nE14{XB20C($CWaAQyqU6F` MgX c({c̢D倚J9cLdlM4T1-tMb:q;d2~aB %D%*QE3z'Ő;%S'ŋQ!z3|>r~a_{܄Z zÇCd ?4-T/(%Cv!Xr#:C_wa``(Wt= B!K(W0-`\T6r#̺!fc:q€!#`&+a2hBzQ޵ ZOTks\\5F cJ\XMՏm,{e㶐W=~AU\AT Vn%Y(Oθ{ԇh@h30WcR?G_XՄ\!/5#7NU%GNau0$x.nu(-M}͸,+o[Pd+ɴ6mYH Rר g(7eY@$99gx;O1bFEavfvѩ:]gXf+ ]]^)#KIF?QöG[b^pԽӁ~Ki3E?sCT+]8:E[rw9adYƴnǫNy{J6!(Sq#aE DnddKJX}ggr  :\_Y4G5VbJKTH`~*UJ&oe( UsʤGD©0*)X`3Qfƹ;g3/߹1*roy|f7^||x/9wAeeKRx~wDj$8B -aF4pp{Zȃ,j=(( >J!KB<ӧ U+oS ӳٝ,]#3e9,{ܱDz ҙ,7FoT͖e9S߶v;Mu@ F78ЬB(?]S4ס=fOQ?SHʺiE, "C[l'RDJKsYi7FNXkҸJDZ|[itH겔+v>p֏aq?Y?~M58>0du헯_v}~~0!@2'/ǒo~蛏_^w>4×~oyE>Bd/~̼<`(lXϼ9ck7=T9W{caK$w@nW3RH **39r*^Re[{**d@QݮHcB#ܼ6czئ`V5{++I G3~5O\e|DVCГ`cf]ۥoxp[Ectm )h$nEx `A*WrX,CAc[[[[GʆRt\( ̮!Dt.H]&1Y4\XpDqc_t !TBuMiJEj/)ͤ@Q3 59<+X^{`#sٷaߤ(,|5?ԿF_ȿ8>FothF UX=7V7,Ier> QD`3w}qɁ7vqc\Ͼ"os#tAf-?$OY}߷E뚛E Ms 4E+ޛ~L-+ߛMѭync&sr8ž?'4d9)I?ctf}yzA,IAS Vt~-ҕ]atA8kgr;a&;Co7v!|>q$g&IQQ!UѭԱE#=ճ9xأ3*a{ Kq')V%EjNoBhRhQXxԄLhHAoD]Ţ["?hI زb}4kghȆ-` ꋆ%~[Q'7$؂G?(>l\JF7;rcalSEepÅEÒ U-(ToEqd+*2|yIJ^'qJM.wE4$rɺ(@E<>KDBc @Dw>{3xٙ -h;ScY;~ |- Y,~IIn٫sI-+dY3~(oϩǹn1c/e#=CAH%,#bO;-mvdnvvD5>KhȑAA;XYbJ65s&Ĺs)"`7cs~C2Kհ!foz:^Оܞ Ufjr 3ȋο%~)!_KS3K3u/ίaC+W1eWQϾ0I9=T,sԥ]rb=hV2< N &dg,[ZSG(idoߞԍllk*V]:.šmAnK_Zhw/e(6d1e`8Z;=dg_:zeqݟx'==gXb_ݻܚ$;K2@Խ,@(r}4 ދ{jn}P+6Iϋlh (l]s`fD՟tX$7 /DH=m2s8%.: 7LYм[ݦ$@6 JIHEsU rgi"[u4z˒; .=f@?QշM'>f|Ѹ fo|wƳx?u8Fc04 2* r@Vn(y`{'$:ѻe$Y?ft>l ˉAX&?xuUG o`@HaPoҁ\/V Ut!XoŃ7̌"H5>M^x'yLFXއ9(&m6neqvz5#[voЕ96+XՕ<һJ@U1L$Z,B!G{mӁl{B/$Js=yn{ Եݎ6^!{%:%Xmvr̠EF/PJ9|7WQlXpVI 'I'4bI|&,1PWS*dA]""0#-eݯ0}^<_W6xq׋熾K]Xy/仧~|mA$TEh~"5ZN]-ocyAˆ )(W@V gN?oԚG{r)c,?C@#wq?D |hCI@@V0#;kՠ#͠ةԦvA\rnYބֽ}jo:< )lkʊ솈~6x=XAWw&.̪C8'HC;"fl0:Gi*6,|g?wLuiY6WNUr/II>ED&{݋oxJY܆Mz%/^co`eԓNghJ$X0q:i=t!;gK?dw'uh$cs҈SB")ʄxϟW]}UӥbCJ[~*R=GH5 G~&3bvo=/YMׯu$*/9<$"ƀJ.WӾ ў} FHNHVpX|5ܽRη?'?)y'U,#D$V7/Tvw8YH$Eyئ}9֮LޚJm0Xu=<dYUW}w3c@auDYQ:% !)P=%O*z1$ aiXs9,U^\$j)^ Y !,"q).?3kٲeNI,,X*@E!fe :0[#~g?z߹展<{ErAN# !\P:3`|, 6;w@ \Q=WS&d1u ⛗} e `'Tʀ"H@e*!FM .41hTG;XQLU Ң>;byW@y;Mثm%R7?~rYt6HG]iJ&vyƳ,M_[tQy>I )3e.HwoK=$}@l/> e 3BN;}Gjar"T~H٧ohȪS UEKu\ bi?(\*TaaWn`Bnިp[Ue R#2PKC&YBxa8`R+hrN-e~xI.! Ff-(a@uR xc-mN (G ŀڏ SjSLH(!M_jhUFmNB¶MzQP;!< CD~L>|h)dR<Ee*9Vm<Ǡ7*%Y$`tazEH`;xrς-H)nӓ@GlL>zX-z%4RPBrr(j2z " @i ztӪ#/FQك.A&Ҹ8tBk)kA>(|J;z;e%PEҶ~o5" lS2:*ԭCUul9A+#*i*&#ođyO4U1}$9`p^ku"S8:C'@8I9J3-W}:}-HvEgM3k@}grRs"O|YƷl Nܺ.EOќWn#ğ5'Q]K^MKZ!Ha%^n.6z[4t!#2zJYF Who-U#I7ꗔB)؅M#"%MHkzu&#*e5-&1&kx.XR'P/4.,[5oI+గuͭN_{f>3]{[QML_!ξl.}rg<Ǜiˌ_S!:m+px( ǟ9 rÊoO7@,F>4` ±Wx攡I9SbӺE/>2bjJr`@PUyz0~ejN+!Q =~_*}:>ڼ [D_=y[2oGY]+ٲ W,/m|:f/nh<>׉悙3+e LvڷA`[pDTI]:w.Ē' ~YiU{`/&.>~]^5NWE?.:8n>ZAʭL|7/' g 4E'>zViZvުփޝ`YVE*e_q= ]zVww"qpwa;Y' m$p[S-EֶqӴr3A,ncq|M*ao[^l2?;A)[/0p.o3/ߴ6*= s>o*V5D$d#/Cx%k/^ |mg{yϿmC2,)gyoKW&~n`eGSs#A Wo,X?…EŌ粧[AdlŲ֢< &5/x">zܻf̆Oletrf(Qڪ0cxic[uĚӏ=1'\9̚Q ߞ&~lk ybd @!~u%Aß,^DĪlRHwZD=6]<,j`1L[x [An&wA\~͇޽:"$ eݧV??37aI.=)p]osgi0-J#8)vުփ6lވ5q,˖ÔiBz7iO)hL IDATҷhD\9-A @M r@dgyRW):xQvc@3&/Z6{ktr71rU#ˉis,kƞ)TSIJMkҾɸ=OTyV?O={rxy럿l-6[9X7󵗟RH6}L:~Жg`a]2쉾J+' B)˧ e0ܸ>\,\c-ܐ{@\ 1}yo^$eYHJV]&i6;\ ʞЩ F|P픽لmJl($C?tx4K&@bKA $L(&Č\[դZʂ"9"4) -~Px@͵E|P߬@_Z' ].D$ !II5|˕4@J&!(q \k\v9@5aVg'J>UjoRYGȏj>QO!'Qo<]h9|j).k3tX/# dTHRTq7N|eZ~8Vy=s( :u[ſD#>8cv9-\rQVY$˰Ȳ,"``PCwV%2cZ"~ROʖ- |W|ǟK.Nd'~t?}!X nu;@ _zyќx%½%R6guZW:h< I:<韱LK]:?gSDXfb$zVzx/hN:6}cJWlPPOrn3ܔj;vtxBY=,ˊSX;l=u@+Ńሚ+ʌ^e3`=àbl 5**HR "1fI{Wb[,9E?GunSik^;qXtNymSTI:{?%WH' Qy #+`Tj멇``3ן^LpW]2G0 "@8/^܇U3o8gNllTnm&._ym_E4k\) +5'颱& uQ@!*B8OĒ0ޭo9~ wjjj PC0$IRg,{<,YE ( ( "mmwY.NylԳ(⑓9R&yiÊ7,AXphOY{4М ej N r#V7i1!"453M}qb<j 'NJY٦&1`iÈ$/JƢW mGfgoL @6}% }#dlrFF7ꮈd-|kw9Jf|";9 h_ahVD&|x *I0\\Vket_ L(Piο3kd(9xI/ߙebyΟ.Nʇ'v^],I # $r9g"6B)>\{h_87<1toA5 ^yίjȠXTW+[֐aZhD ?G{pEon(.SML?'Db/8e5E|~Η W߯i 꼠~̳ܮvn7'},E*;Nc!.8AlM"gi(x'/0.AXﷰ萣E嵇%#`(·pbvP5ní gLJ]$%"L2N|kS"{UWkbÂ*T1_ĘUȱԂ9+Du%ri/!Ī&fOYs U9z Ȕmd,y{BY=}wMe}¹I Huog{8񩧛bӟ}p*FILuY2 *_v)E,ȶSρB  D?s$L^܎2>/Ś'(oP SP20&--]}ޏPAOו݂Q# PUR0+'1 Ӂl Qm~>h]up }DI-"tݒ[Vm >W0>#Z\ ,J92@R_(s>)f IjUU`7&\:"eHuզ(/ :X#x̩HJF#aujna LtXNtd;♀/.00V8,r* wC{@! 4a\HH8?UR!\d21Sr] #_֠;à5\P]@ɲq , -K6,e6`m\VwߡFLߌo>=M!W;5Xlْ6xkj"#0 1ibPd5iv>iM.I@Wd"+P; f'r#c5`Pd&%iRƪ3N2o K{ SUWyiq"EFPA.ZŗL/9k /z6b.%OO~WݖK t)] mAV_[7n Q؎N[P{Oކ#*FD mVCP+ów`nJv J Frݺ͠ -C&JZYV=&0Z*dˡP'cByl!Nʊ{EQJbJ|%ӾQܼ}znuEx > fr^4z=gA[U93Nڵnެ_$l(DZD-Y7ѫHٮ{fXJǒy#c?D y uynJ-w?/:? EȈ 5/z6f=.ıs} ojG4K;a`mu%zSkr2>Rz%#\<'>X/QuyV3r]v yXl%ȭY ߧȸU8W΋{Hܿ.\U{ذDn(ucH_'2(Ok:"W54Vig %}cIȭZBvBy:&MQj׀/K K∝L W巎̒03 FsF%RA8rA8iх_dZ|d3KԷrHc ӯ;L@G|,Bd?gwA_j黕Hyt]`r|JcrwL镯_ms7]~7&-c|z"nlՑu4dDYq2(A;K6dDYݣQ'5ec4 eFI4FI1# z9Z2j*OBV`tzC(w4gnjERlM-"pu,xL& u'T}όnzͼغo=Ų0 [5*M284O*PWxTl(w^ˋ nA,fmځ4(8OߦfʥάӦQB{?UpՍoP7w[y_1e܀}FE懵CmDNTZDn{//. Q{Ǎu/MG>y\wڥY ` }PުؙWT͝[/8礍DB" # Ww)IF}?.%Jwt寢jZq֭,G(G uo ʢY&yįuNcYs_#;[o[¿7L*:FvLiݴ g)\JZ7FFU|=}y1#:ɥɞZĞDOBh }_%^}Q~-9qsy |s(V-wvQ9߲WN 'qxyW/"d9_&^j=EL-!ZxakB7K@7֔}!2qW5I[w˞ꀩM3 +pz::bw([1tV'V+4e7jzHɊͱ""5ٕ,%tfDODߑY*},.Uw ȲLatW'=arFlJro\G4vB c<$jS8w-('ıUB7K퀈@9m"˒DX9$ym.YdӁWoUcAABdYfժւ۽9!ڄކs缫|9ݲ_.:X -P\Y>n+ 53cpX*`Դ!3Dq /YGmt<ď6TtV ѦrV˲oa iKRbjAY 3\p-!%2Dre ZnjQLE@s:翁 X5ZG]uOrn'ݰsܲ%ܶ@^#Q4RGx,<ؾI'H6-v {p B*e.% :kȎ<7wLxS/5U[se0e isan/^WB) cT#*"˲$#D'l DuMmC!ա]Z"AŸH*Ie=e>WH4BCG yM άmg(9 GAfhl TR_# n#bڒ+IUAo7e@зi`zT mbX-*)VS̚F'zN,Kؖ.$wC{C5t3hރÃ_^b3E榆rm7hW2T+CAh[4g۫?Q8T1N~U;0w+ZjRC- U HY4 IDATiCCs˱pEjL^}%-jvLfgzRڔSZV5JbXO"O7LBThoĨ[S9Y=U㰶+ళ6\?\ @fGKGݢuݡ* *bP<qQF-4aWr o⡷5C*Ȳ,л=x!}h/ΡtU U{q"E[[zc)nlZ%lIg)[ i ZH:~KY[} #P]B ئl(G)$׭i LB=kDAmES̊UOzB+5ϛG\XVlJ2t\ۺBU2Z ]?n0-=hQA]P+B <3:3m nWA/GI!Zk(]b?]=+ZySZg;V|1glj7c6C&*YJqN{nMzOJ>K2l ;b&`s,Ň=c؋#gӺ0+M9krsQSs!#(MODh]rJ2V5?oC?jv)BCY1u<UWtP-)LXjmᢩzʤ_^&Bޗ<)3uτO;BZkfQGl`1"ĊYw2]&w˸;RUpOcAOc?{/xH'f &=NwC`t#,ϳP|HIx݆̑}UMNGyaqqT'IO9]*e$GT8[MVw)-\7EzYi6pN[uR?Bq;%zFP Qu< :X:+gGXt+@@uciIUό(p+G9jqvWD!5?=U8\LmI7,4GgbFɶu+~c䭏%Wwv /zNcp|Wd]U+/QVQWxW[Vn=Y)eJԞDXNuӆ)M߸:s(`K|eRωwW采}ヲ^pȬmöjp> $2,  eZYŲ gI0R>.۰Q)]Lh讄㓮+Y,D;OOQ%E8`kvӰ D{m u7F=E34G h!jbRi)]HJڝdqfa}eeeWw[G~&I M j̧!mVߐ.iubt!v;&.z7䞽䆏[džjެlX3w%ayW4О~aZG;c{z?v)^X_UhM#?*6t,pjL 75. uC i ntJhc>mI*0+!F`9T@ʕ+^_&^uecr8osu} e+w&i%%P@V W| >}14D I^W^4FqELI6s_ߟ?錚C lXX܌x &,2mw E8H8Y8F27v_ѐ`-eo!'3}Z8mVF(z$k^q;,< őL#].gm/,;WD+5%wϹ'4r='MS9kÉ5vQJUqʷIk2V \nR<[ӳ(_H04ZNp6}u݇0Qu^P<;i4+_+44' f-Ǩ(rLjiy+n @u9hc2 8 /1Zf$4ҡU}1 A\v_7g]uX0m`jN-!Q¹kyG\w>~WyS{?g3ȅI2ɮ?|ק~*ɡS7葯90+sW2DN2[H*V:ʻo j]wY9V}>*gԞsYry~bD\sRTuh,# 1+C*O$5jQ(QX !&*JV'İ@q,v]ڼǯm ?"ym7X;O* ʥltuH5^ h*T̬Gf=xhP3&v? SCaձMibٱXE/x`g*v=o} meY3)EyULl^d~OZH>oM8y3urwF..XtM,8`Xg`x]ê`{FX0·B2IM՗J YPowd+MvB[x ;YMX2S@Ak62`]w][^úIJ.} ՂB=5[ڈwM<$e{싱 ʆ&Mi4;̶C(нV*(ԍtrT+A?a9(%*ɤPoAPs̍`?*$Itx(jj70~JBejfȈQGԘ)YZ{A&&B_тq-,*t4Sx'*pRG4bm !TjfM 5d]pDFN#NDbaP#P RݹBu)JU]k3]EK9nB,+ 5o@R*lXX-*{ݯ\nAI,%s5̑[ذ勣Xw`+zk "m9 )_ua!Uf_."|`KY4W~8'{EL.8`U0ኖ PQ:u*/9krK0rϝޜOzC]:q|lg3"ћ/;q מ/x.[p is8͖Onp<$6?Z]'jm 6ÝaĶ%4XץBet) WЦ^Yb+{. ڑY: i7d|WxO1WqA_ n9S5YXC\ťwGٍ'_8zf5Z?ZQ{O# LDyPtI5Sgg|W;:tFK/l->p~ H ­V= {?~-.UfN>+tN/,'qaraSk*VlTyPO~rkUky BWpھCh_| m4B J@9܇?.á@$$!\$ٝ{ ~6:4z$tU+ZG`wE2:I%{(tӮf5}qDMEL V| '&`;YxڙѱV^vwd_6061{56D@lRK,6ƍ oho- LİJʄqttO 읱}$+ -ÃAdV9i0Nrt]LGѯKd.Ͻy+z/ 5wx*– ڳ_4`ib̭bhQ;KZȥYbl'+@6vHC_mVΰ8R5aVF盃'gz..M:ZD+MʪM1lʗ`A{P*wbJ“&ADǖN}L̦'/˷z KWRʣP׆74bDA6A[[y>-icqB|qztϕM]<|PeQ'Ν"\'!5ށx[\ z/61PKab H( )U/AS]Kx ^H.+G)OF|̠W5lV Ѩ P}ķH )c kYrxvB~um!ٌ/|63)lr<^g=Qc].<݇θw??hjONyENBl앿̦9(W^5-O/էau߽J㛵d[w5,H =Xs=P,j\"8*Cڬ+j\)uDvrڔT'SbIN>S%A-YP# }RiIhM-zDɄ2j%R ecDŃJh@ƪYX@'kpW*ѮFTlE$Q_j0^ԶVuJԨ KWƌL uŪѷ{7ՌGuQZd6)@ /?g=7A` 0paCVme+>=3]񎇅YX9<6eL7 ύ{?8pmyH)7gS.jyDBf"ּL2] ^ԭ W0DYTb^ꉄU|G5D?Zs;sѷߚć`!o:N9>=8 ~qtpJȮhm4F;  W^> 4 hz$##Ez>뤼wz#N_{-)6$@B/(\ğb9aA/W_zɌ.i{E(ˆ_|AW~ ns*@eeӼg|Յ׏cc~y=_-4еiz:jt&b iZ<n:tۤ7tl"jO>j9ŷE=EvS$z&T׫٧MIPg+.CʈϪu eF#GM"+:AA1k4`uwy^O|CE?!RJ 1+B!k~0̌tvfbS-`愎S?-XQ݀~;K f.?9f'hZ1CQѾK`9_fry650ppH>.1T2THM"G !Uq=Hoʘ^8֢ЈK 5)-wӱ#xK)9t!Y(g HC$@& M coEҷΏ5-ovNXft D= dVPp"Ve5`g4z%\O[l1ig/SzhQfi%I|nQ~KA>D7 0$ EBFJ C>ߐXiLd}́5p9` RPRPJ(EMӸQ|1J@$ 1tEj# DdM3B7Z !@ c,ʥ\zKDEZfwYUOOԬxl 8K9IH :) rLƃFjY/6;XǭNzܲ+V^. 'LNU^j+?xjGO|Y"7 xp4k?zzGw L h?tΟ- :t۾]#}ƳhN Z._f>Ǫf֟А3E8+k=b@< mcDP$*L 'k|}wsC543ZM2Bf4rB)Pc@Mpb64y ӄ0 @- 2 a+ rΛCMO'3:,/YmIc&ʼn5^?kga%[4mljOc=,Qvϴf /""8>j ^carHwWl$lo0/I4MU5݉ڈ(JUV6$mcz߷J_';_b1-/?ܪgdJK[rFK| sJ ~+'"HiDfk6yw&So0kYW'?ApAb\{}WGN|?q% Z@wod!}Wg[Mۖ$rIgx)vϻO}[/4S6ne'3>hv̥׏ƝF PT7ݞe"jYL?v9znrꉏkJS 2}V `݅p0{!""9pFeedm O̡gʝlZ~ei 9brMhM?nZlFt%if'd[_h!7AK$!L#Z>ў)1 6l0"`Y ;@B0-~#5  IqM(gk.FjT}}k֬fSN`qKӘ4MՌp(N'E4؈Z.X^ӽ Qӎ˾ko>dco-a#i QnU74}[s'?ܧPQ] ++ц͑Xw҇}mO]1z}p@(n @Wf!_uy[937eƲ^mXL(mZ%ռ\2D 03#My/ jU仯>\]g#72ԡٻƝ'L~Bmm`D{{%Fs̺%7\׶mH/8͖(q?l^5 ?` ږxlƹg=iP y7e"V{7A="3r@ ,0v >lg,zhSheoP`ה]F7 `hֹGѢJˋ"u=n0N6IҠ8i4XO] B GW%ݗZ]w߳-)༕+ TJ?գ2$7%R\!RrICBh Be㛓PJ6ǫm{rN6@ֽy@t\'LV y9úŏ$II$r;&mXz6>o3>=M3Hoitty2M;( ^~՘S$GDp|wrB'vݝ@V\oݐoU*@'.O%Qm[aa+vJŒ 4%EGed׵,؄ 3Ym!X :iw M%* J*O\sZT%@H=Ҳ:_c zVLg~e;*SC/ cJQ"_wj#Rw;Z/䭦:َ场W!6YzVL3 e,ݯluo/!g9Ԯ;pDhV*4EƄM:Em|p= ݐFOi1Fvz;h$fX4e'6=P rliJ @%MI$YADnMvV<9TՐiDUO )dC!{ʩ7T5 (QUYf 5w~q>9~[& 3ɿNhYsZ|$r;yF`K @#l,q[pw`BpLEpP v1Gq,Č@I x-pQS}f4x&=q{նzc;|K|-n  mmQ:MK=+lnUlJmۈ6"R7 UU׭Y8i A`ރgX 9VM+9rګvUH%;sRr:=y^mcXL_}-ZkH/ϜEΉǾ/mzuf֞j Fx6RϸfåJb Lӆ-`!RW|X F+PI_cvT_uu'l?\}JPJ~'$;-1mj-ܚRW z'yZ6pS/xw"20鵖#g*]YiYצwk᳣3^fo$HvEAF6N{Wv~G%wU]iW'_9'rJ#9o|>qɱSn>o҇_<1վDӻg*lIn_7K*-|eMas~wN{K #;'Wº(.mwI{Ǣa'p "uHHDzf+i{Nbg㵼.h_Q @/yR}s/*ǔl_|m2WN,dXǹhe|}D+H^p]c%SIјY_)w.lz= `Tf1v+]V+ٲk8*[z\]z]ŗ4H˕>_iIHX1|gJ._kgbÂ0{A1l>MnOk<͸8rm| hIN -zN#*+Wn`N:Snsg@1S-PqsPf'`W3M 9b@d\ulq ,p/swtQ %3?cUS+$7#oB`iO4,lyuLОig @jz5_8u4犎 c5fCK{$?^ [O 3+ɤTOMkť"PJӈLPL~icJEy:oC ͍S js//C(.Xv/bg<ܰ 𗦧سj-i9¤8oz+Kδ l"˹ a?ܰ.gҙ,/\=X:p-C>7E^z.,UPW؅PuWW|=G??hQ\Vjv@{&L͒s9LHu](ZC*Ag$[FRo>@_=s7JuQ\\!ƟZ_'Ow 㾬xl#R+BJ#TɖE|ȫ%h٠XD{w# HN(hw0j$7c-_j3(>1/5$CGBĂ}m RF׋vI6M_mmog Gx`a SF&*kJ\-W&b7-"^?uKQ+coHq1[YgD'j`{?¬X>&f{hJ-7]k̤i`Bw%80rPf lCȅFw~DS 0mh/]LTO[ ,mlu7 oMM]z5$5)![)Rc*@G>O;$(&;@[uKco<(߳F7N*'ENӄ]G -.Sv9 @ -h=;X+Q}Kxʛ:׊u289qby뎮~L/S6LleUd&lHXyJ|<`ۦ7v( \58X[JTbJU> KqHb@KCPB䵔̘45c2caԨP%H41 Wzb=1@awu?X7; r ֥ m6!P @mܾ{`SlK% eoqXCLF``[cLQB(PH4 J:z+{ӌ=vJӮ̌VMfֆMfl8)ǂH_5MCa Fl~4"@ѩQU??>I.vNiͣO_,kݔ A hoN>؛8o O³. Qo, r)lafu]N­J91(A/u6>CxCKv!z߽Bx^enDR9?AEx6D ͟߼!MFƴ9cqHwG-RJmʀ&5ay|5? k5^74DbSL9(N'ۗ屈kXP,%f&[W U,%f6Awl JG3l  \5) OJwSG!{`0S' [fgttz6?N,0j]5y&T긆<<Nj;BL'w6qyyB&q&mBE顈揠wxdgZ,a5\.^U9D+%f2OEkǞb0а"ɗ Օ.x'FA$`KR QlH3p$m=*7]8uԩSˆ+ Pt {&x2};d$_Bq|l+xtT劊ZRT*rTnef}jDWD- M 74(Uu0g~9*_o0{( )7>֫^}QJgRo"f"k-B{q;*;79UiUb  B!ȆlviÒDc;vh{YmīMbm;k hݾ0 |}_J1FB0frhr{YSmgUV5nH]rZʷW:Q?Q9n*Ŏ!;cwP&5X ڴbMxf{$z7;ݟ?e1dJo߫D˨S2^4m v PHzʰ/d@3#"8zPh]1DD&!0`njtTô? Ʃ25߾ ArpjFm[]uWjS&D G$@REY(i{o Q Pǫ9;>'Q)nnϫMS9{B@צ 70φb =׭ir_b^i+9m9J T +@ӢV$n_w3:ʣt7LzK@ hw695)0 l0ru-3|~Mߟ{Y3 NgMDgJ#CNW֙ p9O̫.N=HyO!zָ@qE%ko0;s^ꉷ-)_{sO?ujg2;1C++;zʔ#?<= g@um=Q>I0IYLKS7e6?ƴooici5Pa[w ’]*c jP ?A d7$ =4qW zVa`V_ȄM4'NDA=T/"c$B}IFcw&//,A4: _66g21@={6TXGA~qB9mk(&f&ND xdo,xD#;1&IZ9G+er. l_#Њ$Qc$ "S["%DjcZ غngbf4_#G}EK{̼yTآJNF3jz8l(Rk\MbM"b9mpe.`f9x Cd:9oÏ8F?E}oՔl6%Q f:u/O+`7\qW:{8W+ʺU+z)g6fgV|$x;gRpD6VhR$XP)aF'@`lR!**gYQi߿h`!@; Z+R?B&~.x=h$ncV̬>m_\9pj2IpdVsg6~-=0SΟ:e 4̚״zd#AHد֟oAM~8HX==Ol8U/ l$Vi+C䠚܆H4޳yqu% lkUcKzWTO}]c$#7ܟh/%?-G)W^l2V@ùzZ <ñq <;lJC2 P(cp/ ҀLl&="W 1*R L;&(B2i2Zt1iZ!'oq'aF(`:IJ0V). LGǶrȸ 9P84?׭zzݪ;`# ܲ~ ^\x؍،|@ !$P]VO(#Hjo V ? VGn{L %B,w@jO[CshOi++D^MΩee5C7 H >XKkg}+ty?F~NY4?1 G;6I]kna1y ~DYLXhp't' l 95F{M%kt^Φ8OɨX! gU{Vs^2yl uqJ~ՆdYT-H$9FhvUɃԴ~YvHڱn芞(ON|?q% cT(]tr׎bmQP_Z7_:hCw7|o y:L4BI;^s܍F P'Js|ձ&s+«XI*E蹖e+{$0"8:4T3ױWb_4I\ )7EX#NLj#2D'N["tT6KSmTpͼY1=Q\gG3ֻ= ij?e0Ml{kE[!)>Q@Gd.}i5#PJ$ !F}5Ψ[uT'$3m., S϶B% + '}&W8}}PWP*cxջ{Hvs˾Kp&ȑv jT5Oَ]ښ%}R&gTeMSeY&CvIOtgbC%728{[̚IM>zՀ"5}]bIjTT6ګ$ɵwf-ܭGNG֫mڙ9mW :G}e1 Gĝb͗|{^ۜC؝l)gAYĊ}m2h(?] ׮ڮ0 #Zk tREznNh.i1y#P>a; aog4sM AqrCT:K710 5|{N[&F[%偨Ǎ׿>X5G@!D Fw9cU}p^<@Hrg|,X#ITf]׿_[My̻v>׮(QFw 숶);x}W.NK]yƂPjIl('_8mK"~20#g*]Y鐁+5<8ᱥ#9oY>cs˝z%f91~Ho!'I d6Ta{Lb/uy^ҼT=ju.џS^{ک7NzcIt~PYxCh.'y}Wu^yƟ©w<^ lI]s◾̾5uwC=5jt޼}rKy1$|`E ^p]c<HehL,Lv HۥPku`zIME*XJsaH@(˥'[ZnV%g%[VNM/ _mW7l%prdb`Tf1v+]Vy-V\fuQFGS2GnZN  @&|S4~QjA Pib=A$6 P(hEYp1/edfl)DJ,kǤGl>. 2n\ت2HDlv貛rp*8^iL{iN8| T*涆f2Q6GB<r0Ӏ"kԳ!! ,oIhccS&:d[OQO;u=jw tgx\ Kdܔގ H;Ŧ=Ѵ c3A{v4`i0tlhikAع6~Ti;ޟ_z/CqaZ켇+9"WN//H:,?>~,#XVU^mz[݁=ؔf4uaR lBZXRA^ې r.\Xuh~B VL)Ey$ \bhڽ`iv#<A,ߨ5;FS7E_z6N1Xx&k9aP]*1Hizہ=Fꚟ(l.h\uh5E(d?-mLh9˽gI:U+}$||ŝ"kᆲ*WQZ4!@׋=_Q(|bG GKR*Bw!/AJBd*5'BB"(e.9)gnz`#H~Jߌ|{#I4CE⽕8ZQSM炼}m,L  `+-]ƴBg_N/"S˓OSF""U򢧬$BS<:Bf&Ou(f7q(Ux.A ;V8L36#ձYChwofi7kln5,/HͲdO`xx@}ٲn+S.0S M^`>fq!W5?`hH PH۵xkG ȉ54`wMjlW=%Ђgh5JɫNHoh["foN  l@@:DNΆOx 쁵#"uTG6͊N 7iei(SF' ܙCWo<"|fuz9)Žh*ò9{t71 tQl8l,K+#ie.~OqĠ]s&G挵XUS`XJ}"Id&HXuX`BQ]c"~'S$ [<Ӧ1M4iLTMա4y^DU mߵVqb 7GxRƴtԍ7U\I}7B7߷mUPa*6VUնIؤ5ӼGh֫@M*|z߻G3wTkT[ [̀W%*)ve"*>xΨڸs~]Oboċ[*&7AB M--yem\y IDATQmaOKrcQTP#@:Di]%?6v5=ϫl"y*1(vs7Hap8"^0HlRf)hS#qCe36(<ǽXRYJljY%$&IcJ+Fܙ(4xbSPN_MQ1FIf@*-ŧ Jo+́j{]#["o+"90aרrӥB8{ePxz#lڿ^ ;Y&AF'D%݂9xbLC-Ne<Bcز$w#n ̯o9AE;#Ӱ -5K1m,-!j/)LϺ_5@ù8%e'!ϐF@7} t*HGb] 'vyavt5kCV:4MSUMTUUEPe,˼wd%e3;/{3>~͂@hqAW/gG>ʅWe8A-5l¬WludŎ&h_²,wQ=/ RBl8*hai>(Yv!FSIɿźf隅ֽ([/N=&6-S$@(5.WcN lAtZq͇r" $c4`("2rA!^+gviÒDcܣ* O9Kmɏ=o|mVUY7PꗋCvWTIW9:׬lS8o5+elu8u1*k7+)b)C#]wh)NjU k>.ޫ: wOIEsk䳡5C('}XV=\oCra^$VԴ7@m朗 ]#Xm(@/áfbkPvLf,״ !J=v9=ZH49W*Q4dRHlg:mAx,!7'~0}z|W$ԢT.ҠFx%VlUl4lAśw=-D3 04%'5t n#w[qU_LYA jsoCbtChmXɀxj砓DRB70+4) dHX"RJo-]3PhhFJCh8-Ÿ}Me-( 1 \g!VpJ -jxMA;".e"pN;:43 @}E&)]**B}4MN8,,H(bGgz_8RrPDDE~޶}/I?qG5P{~`u%=ɬ} `k[f?ر2@ᅴ?;f }Yv{t7LzK@ w695)0 l0ru-3sY][N=PyqO,Hܾ|MfBsgW zmK|hyk:ī6-ͳWzgeŏ6/qP>sԊծ{k)ݱ=36 Mp#>i}niT1zŏ&xҨ[aDij=00/dBM&Is 7ȠeƐR[Po]LAxB$)jC/54Rq0@r Fcw*?(t䥘_CDij90hJ<泊+y%Hx"mFw&//,A|6wR66:s%`aUmT8^Yo<=2|kRt{*"la!H4|Pa6vVh@cc68˄{=$|f!\sfh bF:[Y#9&WB2`wma #:nJfZOcPϨ`rʌlBlca56x|c̴Bcc\Ï8O ,KQJ[Q'r];}R0 n*NyBY\0iZU o/*Y"ksqW'WTuOl]U݁psT!!Xư R$֥K/fͫ73ٱ͎{<5k+F?4t,1Դ*>W\7%7ʿ/Sߐal7)! oy C/6 c[`I5u4UU!c tUQTU}yյU{00*5._qO₂+b AA&(/D#Ɨ 1EDަ[U{VfHl[w9[u})BpUuɹ翱5=c!! B)s R- ,ꄅ)+ͅ8%N=_ ^B"ژ➔#&f OGX-Y \b1]2BX4@t F 6.qt@-DŽM$>ٟh?(iULruhh!-Ж.bhұ,JUEq` PA xNJ 'V20冦nq{7Ozv`򪯊28Cwy@ِWNPuqMpw?~Q\?oF/k&t8>+Ȫ؋}W;(cOv9WC=3ߧ+VaT0ap ʉ{* Rea\{~:Ǒ*hwOS}Y1g`~RTěGNiJLH7,|ke2:Fk=P_uB0L:ĒۥQo8,?$~RCC쨹i'+ cTtU+;M걑rc#$0}J1Dc /7*0F9kVzI %Ue } sUPDVkq zVQ}d~ ]76U~_weهkx4XwםSGٿ/]8/jeo98}?>q^jzҢ_3,#^Yݼ^OTP^27X6vN|ϺrW_QGؗ~+_֪JL, td 冢Pczhi!S^DvHd~p:e$n )cQMs`J@Ox^:( M^Y)sIXPJ^g%mSeU=I )Y՗k+ErHQ2V:F{c!hzE$UPAQ&>|n[sZFƚ5u;m-߾T?:cKqWvWn_պ᮱3/H2*`$sw۶uUv"tҝoKA*]ˮЅE#Gw_14%'ID'Dr&]{i߂J'w&^)txɮ>}KL')/faT0 a"Rrߣ9XUw_ƞ_ZVB1{@/5 zC{iͨQb,CZ @rZ Qj ) iҩf9>W2HD! s BG%֊Jc9:H]HPN;Dq,=L/;&XJ`Ӵ[YFYjRQV2.e"+^>GnpA>{W0k\lUR}hѨO {">ȶԝpYmqoZS#/\7l#xt#!cN{Nfsw&ԟY{vKe/_DM=tm;_ϺsH9}/_fTm#x6qhe6|grȺ6'>em)ۢEO42yWC$9XI5'L Iyt8gx=:soEXTPkog&YDlJvכ/UYG zm;D9g\,rvMPkLDl蝾y$qE!zWz `Iح]NZLȈ[ S+H&iȌ)c<=L=8_]NV/`Eqҳ39U>iUNM'Id,a4{EO;D5dZBezCU0W[!x黧|p C[hu  P(~')ǣ{D83DWwU7BŐgoo^ՐyqY#~r;℮Ňά}?qx\3-G \,[[=.-]5b;>HBUXU5jUo v ,`ӈd#$i<Ս]_]UԌW *`п-> T8{f S'Gw"hb!+{& iu :dB%YIA]:r>Z,Jɐre+,( ;wlEUn[VNif]HӖmҬI-LM/GV'SWˉRj!D_jE]PA[DD\9 s% g?H,2~Lַ}" '=yE{u㒍n&SǏ~0O/_IE%W rޙZD́K,?.|HU/,zQ&7HQGiD9j:cv$87: |(?ʮ Mn#R-t 'ԥ,A%n>PwHngyu뺠誫3^9ai(9jF|&5u;ʩ>x ټg5beDK73.7Xӈ #ӕXЊJ!->ձpGX&r*1w>gDaMI;O$T?c\}hdcAHDJ&Q 3.k["{y(M!Y~rVwnϰ[fzZӉk=<Ə2͹tl:?ywU}y[ ;: yY5_ wsWInM g7sIv"VNvl)wuV).iMb`#(Pӆc[wbo33\JQ[2T0nÃ#P2ź͵<} YM׿ڶ,4su]:ɓ_tgbc/7l9ݣ]Kfnb[ɾ)st)G5G?1K6H2龦e_I#΍5-"؅ozl3uL۳iڿ%JfTY& ԯom\ŜD鰋Z6 CՋG.Aز9ѯoX 6&2_#&Gߘ|kfV y@׼[zuR#eP<  9ضP{&y7y\u"E:·cUu-(qeRi "H#wU-wѨ#rQ)*9)`ʩP_F^#ʫ`l!B)f]tͬ*an`|eҡY<z`? c'k~RPiᡘ2?](<Ī u014B,O% ;H\ɗc=,Kbc9Rq\n/{RmC}/n!AgEndEh3!{t>TML}_v?} ,dJJZڅnzۛ:.J9בrNOiY64L=eּ̥@1X}p4Y}־8cST{u5t7$ߣ%.w r0 1sx'`ɲ[rY\LNߨ|CԳŜ1qdIesb|G'Ձ2E4GR3r0e*˞B4Srק%.w V4M;ӑfM[$G{y68vwFW;),4 2s|)= |6~;x oۉfzsK$PE] X_n~]Nǽ=q$$Jr\qz>:Q yp5>U1 +e?^#3t=T0+Yw-E/blpޟszdU ZO_e\I4bTs=e%*&]tLA)nT52r3{!Q9{dEw1kE{dtjc{eBSs9˒p!N63&F!Sd)FcU ܫ*al%1 N*,]?8`*q\]ȣ9թ`@ p5|:wtwv@赿{ΈOz+fb8oNDW4qE?mZz_ZmsjYH eBbMyw/J>KREUr.v}cF ܮމA$>s$ O94IN_y.m3i'a 8˥xx>Y}`h,Z\%@cq[*-b kˁ_|$8a!,s'n>D$7?9fuoooΒ}n^r, IDAT:@uk"eDz$uf!XExXEfaTЯ\T-_Ĺ`3K`M:U`~Nq @2iR\\EA(4,5 :AgQ[Ng(19ai 5-_.,#;Z#B(¥f׈},C&2=-r(iS3He(G3vresG8VD<#N|{H~>`t?ƦO|jʬͶ-D@Pccwyf T}4/FK\$eƘ"pRWF[y(^pC 1PEAX2B H?8-#.蒚S-It*NySQ.<&g6WYF.21,j>Yl;H8G:eSVѧEi$7^U'(shUxC@Mn(Φ8R[,[]* Cr|ƒCBY˩֜~Ga3MrX]THxB% +@a g%A(SW%KN(S-sت&tIHuUA!ШO0(LB`M9@9jlKAĴ'=s;v}'ekh{>~ y 뽥ÿ)mZbVyDa\t9]/n:lmeϻ!N_MOJ #X0vQ'j\,B௼85?Vn ͚9#%Q.v8768w$5ȅfJ@Yy?Ii4wωw->P,"!V`i!9^ˍ$b s!x\6daTP7o"ǫu/E% 16Ƅѩ!Hat>ɺaBF`=bwM`SJEM ce`6UMQ8:`zA[2Iy)F)^1[%vSj*:,,݃ haK]`Ф&͔BM%[<\[w@?fD'+ny|/}-|'_!BYؿ6+ k 4;g~R~7 @xi≑ٳzoA~s~_^>gV|żoXۍH;wqç,z#_ir`s_T?/{vuwǙ 8LT#Z,9޽ᓃ/7o ވZg䯺 w._yY#.B,׹;Y_d2j[{w쿛Ta[n"w-ݵaQGdSG88ۨW4Ϯ |;?}$6-yd? 훞v"H-+:=Y A'96ߟҴcbӐ\ܱd1tPg2z/<'~sqz϶wؚsWܹ~Q4@>{ɮwΨg\tr9L "ۥWc&SwB4[h^[گɶ_'~K`y"X9VU5F+wL|;vM/dJGc8k@.XwX1IM'ϝ#|ٺ[Zd=I#Όp=:_ݯnZu?{ռ$?/ҹH,/|@.~]js͇s\>4m - P[~[lm{==<|"[XֹefqeA<ΩW^%I"cLdYٿ$C/>O=5\+x !D@IjqJ!80 :M> !(>B8:Ud(**D i+pJdDHQjKuB2!e竓rjR#+e)  zSJm;Qg{U͹Ǫ֚\W'Bu.иC+5"ݛ>FKU)]y[YJ*XgG C.# L]<,/gѡq ?Ÿsi錛n8'O9֌ɍS  nVϩd` MK?lW@.(Ӿ殣;΍]gagDwݏ_2vϛZ*w:F5Pٽi ;O1 U+qS *(hY +ʜ,ܔE.ٹXqR_ PN@NTJ#SFq?AFAJ kM)iE4PdIseK.rHZk]`*)H Ysv2t5؍-)B+% ŁGi`6SbRFA9iR]F])(3>Xm/O<Rw%]νwow\:C bs ];Ǻ(:|GQ-jeoZw S ϼڲL'#U.x:.* xS?塚VE֕Z_-NH&f zvtkI^5? ii _"bٕӳP4tNSNt  $nCS"+|n[sZFƚsu;m-߾T?:c).>=8)@ =n3λ*FB8wm[Wni+ApI7,ݹ6Jjݾu]c{`i(t-C'}Hsy?WwAJ>N UR\rD=J/[_Jv*ZyɝIk{-bC|ep9jBKBdOaD澫SͿ 1 +dzZ@Ȩ#v~ߪx+ D"$SKhjzҶF;Ii:J+zF1dtB`S>T UԛNC\Z /FjE_: =Q+TEsA ݝMeߠ{XPD ,&=kBs9&fNZe.ctT!-"-kѬJ 6aҚB|usU;2Hu}4KTF.Ig9~yQ#7^nxuKوpN!Hj_jkxLrő !0m=|Yxe$ԙgݯxyʒ] jl[΁;y:^3"4~!.QEϦJ5ߙ?!m@ɓm쿸JZ׺B&zcH'80@NV #+% `8$gx=:sᙅ *A`_Akw=גRӮ.Un?l>Dʣn{m,`GA1[Up`i-C2]wWCȩM ba)9@[ׅ2y~LpڠehρR(*TuwQ04!Ei=Qjx&edMR]kf$L3zZ95ВX@XKN/5j尻}wqtX䱟V57򃦞s;6W|>BwO?+#NPmz5U}` [F_e="N‹#|d+U ?,K4sij\a #NH,>DZ6/" >Q%B>P޷]5b;>HBRn{D@[Rf!jԪ^2)wyͫ,6pQXA "{l=t9YWef:z:6d%@U{.!0^ep4F”xXgn7b)zWSѝؽs܄!;( fbwF\,ayVTろ7z8 Ҍqд(Ƥ fb9/NC}u"=qF73'5?;o>\g~%^#K3o&X2=~\':3{SPLN|(U Tjqn)$?@Kj ߭'h[uFg\O?Qw]YBy$KI?ܜ>PwHngyu뺠誫3Pw2,DSB ΢b8s@Ȕ q0*%Yu.>N0N<1rI_Mԋ֔>9@\Ph^cx]1?E"Ŗv\ul=;0$3l:EF_}VTƌSupdYbrYu ~}XwU9[%PUPSccvʈd(-^3=}ĵ|@G ??6 _L-N+.i c5T`Eáb>%!͞#HڮU?,q6J^ QT*{F}R (: Qc4,r+Jql &v$v`zCJDoVѩH5ރ*`:9BdI&tBv*o„nhG*ň!1˴llf2 Ÿ{ă9MQɲY˿9,~0s0Жߎ>T8ݗ\ᆶ|v噑k##w˯yhxh3!{t>TML}_v?} c,9P3t ; 7u\7/r##9Y,#F(^{v^~#ɢS?\w@iw/}+q3jaIGX21~wraK+>~rjNH,{|.%.v?*l1g,c&YFRh'ɭY>h·3ĵ>_e3pXWhtpx;~[{w;.(Ppbagxv|v/lM5Ng &o߆:Q y(¼G5c4DY}K.(0a }^#.gi(y=U͆MIgaDN4UYڪ# Aeep,DAzF)YkJ+'c:я77!-~Bp9sS$J'zb6 ףkhcԴA, `SğI c]h?P̔kj)5+MQD<8S}ҷrDƂ=[IOu[Y;縺aG|;{T0H K׿>gGɻx7|ABYC1l ,xnKղ߄Kަ$H/sjYH e~XeIؒ@^t=6]x5vpUr.v}cF;ynWgOd*NI,>/}d=!" HA6s \1Y. gY=GD~_}":Pi\}w,H~q3s'nDDyN2\?Q&dWN_rtO2"eDzt/sYV(Y8P&3AQKI߉AC-hʱ*UTT S=ĝT`ںusLsg_P[Xy'BUZʼgNA N0l4A]iKpJ:DE_#-@ɘ&ØYE X5m<˝a^ȆW^T3&.Aꈢ,6 2NMaYH,uTrIc.)tOĝ^%j|jq'τE i!K#D\1}/NGMFlgՔYmAYN<;Fp'7di@GRHlټ8ֈI} !TQV #NnňK7kKR(J`e󔃜>\CgAL+YϘ~!<[MfL{݁D˺cЖ"8FFq݂,eTaP06M&/"l)" 19ϋ/\X,Te(IN է]v;hO^Hu#daRCW񭾓B/)nenV!Qл>u|@Eۛ`@aX^  cwVսh*XQSעT+ Ao!h~ cNc(w3 CZ#(_ME-`_Jɍbl1,Hq:X(˚(L30vaL9: ѥB*j1ƒ(B$j-uxvt =3S1駤Fq%=Y!A>!G>IzTON>B I/M..ǏGΏ;g9>sZs܂'妰ufz*'0ʧ'F<0^<Ĺ>-<N E3WWks:_)#'-}¦${I.ۄBu9F sƕ.HQEGy{ c>JjN̮RZ̉E E"E/N&vOTzU >/IcAӠ;}HOn 16{Hh%zOD3/B @q8@Bj#8 `]3bU>w;+TRT9ahfNN>vj614j#Egum E Z}t.HԤXjs`bZA5/ճ'J<)Dp.T<҄;M@]_Moa⹝8}w[C |S+xpҽ k!޹{N IK) EC̹gVp2Q! ܎hd {↹3/ b_VE͋Irވ-IMyK]j|Nu)#_/5:%q͒@r?ukyszqEC)WKByw-K`#;n{S,op ⭾R{ˊi.D'$.b)LN;V\z'fm[K4>)7o鮻Ses52Cxy~Ӟyqw&V살AMrtQT$9_1RZ5rXr=w 0@lvgC*:dW= گXۇF9, 8L[lG{.wSa`j2Vx:{NAb=`KzU$L0@(I!:XeJ+CT#%D !@8ͭpF_|R< R G!@g(`px.yn[﷯45P~#{ yWh}oU_ڹl\ Kwn-ݨ5xUU D2th?#q9.HG D*6UH>D 䙹2EU Y[a$tJ oQS2cM s:uD?CP 4]iK!LLMbb-UV2{ٙT DD ue)n{1llg#D@L/8gmZ#z^,(mY(c랊kaQ^>GnpA>{W{ޭO/Y?aom;:޴t#G^SoFb%jfwo9prx:^5~tYB\xU6)e$WBfsw&O={dPp{ۧm{hEꀁrVew'Rf=H eۻ. C*Z1N ,P@/ɡi ӡ_)r#/f]査yUC˒/l'WT#NH,>D"m_d)Go(ݒ@p 7v݇&Hͬ}?`ӈd#$ bȠ;19F&rһh^e{LONz,ًr:v me{"]xpЏ#rX^‰"7E0,9rYhC}&B3x+h@#P*FG (yMh2D+QH ҠRD 8,P Iu8*4c0^6 5u2T'h 4P KZ)Cfo&ݖ:d&XPǨnDl_ANf!苌U]g1NS=5k~"d"V[n+RC57O3]@K*sF=F4] *LX!4Ğ#arMM[sadu]:@eOSnnM$Sc[Ěچ,[2T0nÃ#P6Nz y YM'nxչ)tɵ;3 ;9?rݙ¸fy@^[u|]׸:Q3?tDj :w}ht^i8DZes__߰aL2_pGL,1̚:Kff͐5/VojSJ4{jgU RT_!7iٻW;T Fł%?{&ŮQDD@(ؓhѨ1X[("nf+ʼ-Wf[f޼wܤ!ko>:=]j\ %@?w&|M`wLSTivI  lꪝ$IrV2[| E]bMQٶSOCuQA-r4{|Rtz*.ԸvSxL_addd{~yʪm$Yt<ʇeK1:OE-K΍f3gO\`Lq$9aefGL:^dqJJ|v :-8\.x)(ie8+).8F'']]) K1׉ IDATibtK2idAN{ ..uEkg&3*u|@i^uHs3: uQML4) @')b,E݂a)+=s=dO9Wcv2Q7P4LZLݭj-4C/B+iMŌ/~H?^Pm{j9Xj-kf:c͚U.{|~y<\COO$Iyr֍"<S~f7[[y@5%ϕ(՟ Xvu}OԿ6_M/Oos}DSB, }'9n{}({cs&rV7@>BF".3dIsݞTF]0 vN$$chz#:ʨ"@ǘܑ2T>47'Vh %~H4\QDD3cm{W7}@x%Pұ$Y<ǘs2[.LjOnC &7rh8j5`sJkˀ?Hỷ#^/Dd|L~`ET+e{dp΋3+WK+ŝK%%|!J,@^"m>*Nv 2e%>W 0}-;8HRj{ˎ*gڪοim;Ҝ'CMH'xZ% S,U1,7F"H@>Wmsny#A7D$7ݾ|Sj̲yM,7%x%\5j즳P7t~ Z^x$@hJ;1M,D6'#l93ID2wQ543Q/v!<[Mf-7V;P)p|Y@HRDA+kēaA"p2] e{AZSw\`H HDJ#Ef)s5Fh7%r5WR@րi‘U̚@lQq ǻ)F(LBb9&r9d5]iiR d̉Hˊg*Tͺw G aN`[gIo|#.ڍ@gj)& t#p.VgעZ:f,u3eHVՀ@(˘\ ڇ5 M$38IZ#,NTg6 @ J5=@4F)E(%Zc(n\B@B4_*5B(ThnzDv*"@XHdfdfk&Biu=5=1{Z3RdľO>J)A.'UP]Г#;|+72۾ˇqxjt얹5k \"ojZy0)0٨ό$-f'9gS'd5'&wubr/"RjuDvtdT373z||rg%;șgmaGq _h**75Ԙf\W+=\v3yIW;iq#z .r2tw '匯d٭'X>-gz.;ĞiRvDLC^ĈAElR1L0sJ+*{;2ymlft=[~ANE͈Awf́ &G4ȇ?za@uFHȬgv߻l3{H`UILjC.^!1%: ^ F<&ry1Mq %L?5! Mr!V#8B]9 ]=ZoFtlRGbG=A&n|L?"(juܧ-\nvQw1iVEs&jTWKOpᓽiFjμ f<(;"-k[!/A(@Cإ *z=+0g }FLEiieccK*5)ri)!ꀉYa5٨*p2,O*j*RESjTc&EǕ۔/'Br3 TE@5QTZm4Kz" I51ErDŽh'Lwkz^3_[s\(1'S֥<PkP_)yI~aQ3ƩF:MU}2@n}/Sl9zxրtD)Gjh[gxPEH)ྞ55IS‹&@{+G<,<@b=BP[_ܫ84?MxVs_OkZ3'dyX"#1ϙ2k[z7׿"U&9q{‰B PQrJۼH$&.V3kWdo2=%οqF$޻"{-3 6213g)z̜Ǧ; CZ<-cqHҸ0XtHEgX#]@phֶT09@TH" "U5㳲<@T me%enJ^i HWCе $x'}O ߷ اV)."l#˜ c$}ts2/i|W]Ov=9S-)E)s*a(~8r>1ӧW*wtk^ U{d`"9"3ItSZ_<)"%8%poe R* OSF5r)4`x kj0HK?s~[Mm"o&lc<${K|%4/UIaYGP}ھ;$_qTwdѭ]|eYDJ1$Y)%U_goQ6B!@; ))j@  BTctw22 fDGJXa~`fU0Jsب=QcPaA bjX\2ݷZ*6 bڿLɔnvF(]WH@E4 (( -ZJǗ^ ,N:d.JAE@48H[*CjdjRӈZ[J9@$-V ;3dQTj"ӭ|e.L%o;g@u+pISl4 W[w(&ټN5b_"QUYtn O>o @niyږ%շzi5$LohmՖ;K_^VWa_$Mft:p? mW.;d0@Q6C*!?#.t|0w9#zJ;;3=;WErvؤPJ|9u $SqAGrn"1C>%G*,ũAS@_ բpҚw u߀=_45}NZrkUrx V2@e/}F%F-NQba;U<÷~!.z}W4:?2(:eH1o378h@a`86x> jJ)`hW4~JM2ʘax TD5Y=)˔"5FQ-< b-; !TNފ8@@@KCR+$QMNT(N;CB1,ǀ"sq<2[US4)Hz߯H+?ͼv`Y\dm?P틱]>e|<#?~n֭}tL֭|ۗ"ܕ{N?a(6;/8s׳uBH}y/>=%/ U ܶo7K2޺TV7*6o C m2h1D}{ɬg/ .ȉc=ضxؓ/E7/YN#sDM emhs''M9}먻$L,YIfIEhg1=NVw\w"ƞ:\C~jC&4BR]RAX\!0QVpt e ; ao z+Ѳa #Jy}i4kRwcLnO5 ρ [ JaTGk:SʈRC3[uA,A)P! 75bE[NfaSG`! 8}Rޱ:{hNB+m{}٬.HWjEI3 4tx|mgj!rq/"?i$ߚ_FxseVqauRŜԶ_n)?ï"G>~VyANyɳ'{?g5+>|7ZeHʣ PpCן [ϨY@ O IDAT3yוmʙ5S]LQ'~ : n_7 k/jG:%KgbheWw3#GU[< >&#?\7o}Z^'],ݑe]޾Q1]tc4Gi$"Mh]FuI>oOo5OLFD~y67w>Ǩ)T >A= -#$a*r,%_Orrr:~(&(, |#QJgo!ny.9VB'kbT{E稜gWNE7<.߯j3]PQ%ENӫ1MN˸{MYfRT @ƭ., &#F'LM@QSh%(k"Huס^z*tqÆ<S502 J6117T;9 J!j+piq@Ae1yTbw+=ܲ ڃ1=B(!"_Ϝ? bJp.-0r7%\f Ⱥ!%549P ƀ)J.c`\töm\]s|揷̨?OҏB!ّp#%<}$ݟi6^%7l:%]>)yE4oiwis}ڟkc[▪/us;=7Ͽ!c[/вdq do;Ƿ?8-ʺp+^cf7$g,tI˕( U}Ԓt05;m˃]^-C~ۓȋKk x!vQ;{W43 ՌCp?q؁`]/׮<}O74g.kpy[bYw&-wegO }ę 7y9bqGHǏwm<㟢teBGsGqU-. ;Lwm⫫WIf#O=n{U|Wכyoӥ_cϫxGUݷN= j2)BGtؚåomC]^-CtVؚqѧ~95KyPڜϿ5qJIhUe!gr2F^̽püUNw]Zv7fg9JEHn*)&uq^Tt]qiك%"˒fw~)1i 8Kxt>Ef9Jg;8OD(i( Hnr}vϓ$Yl-&gÈʅoN?V#™73؂MiCd55^)vk:NhX±xL_ldd{~2yFe#פ;V7dl'/'fdsaN[;9f3gM\¥̵\N݋tWm`!-BjbJYwYV%=grnkwa*;I1d)|Ňm N$Dw!e?E:aBKfǴ|~"WR@C]"m"͟}O~X.t]d_mYzv oo R* 3֮1#Sj * kczϨTUFqhBI`²UeܲR%`_`L5*Bjn iT>?YÄ~p݈ \l}⨐wMO1!/7& & oi!S SBkG#RB j;e>MS'O=v =';`QJ `BUP LWWڿ]аI{=x%kG'wE2h=M:q"Nkwy/ cPU1P2ɣӵVqؿFD^މ/ˣoz &3 eo4_i[4:ndnO[/Qc|_eE6r\_ գR'6_>cv~qלtEx!Q̥"܎:j: z3#@>*tiaɮn䵨vFtmOՌ;QOIe;,˫ G,e-µ6.3 ke5DklP Cc;kA̎#dT,7'n6ϵyčӓR+8R<'1`8t,_zA\'n@K6DjZ Y6]MLJ|;}Oj;E51qm@Br@m 9`^FiqI?$mN _Vy^<38N)%:{=E*AE)3OebemS߾9ga M ur(EIP)־/嬱!s-yߴP7s⏃uXπbyl?]oA4jul&\_Hij_UWW͵}RE)P/ 1ȳ.6VQxN Mw[-w*~o7u/"cY](fRa/B:jBAՈjǦˏ-I2iY-ܦb(kRBi4hJTIXj X+0FKioܲLK3򗳻k@ЏDzwj HF0Mj/$"}ۋ MR%cS]_(%%?jG`5c/BIۏdpۏ,pppϻ`\BKLv i'_B)jODC 4FEa5ۺO V^IRKmW73mUиbT^Lk ,G7bIx%z7uK YA 8Z،Uv1#մԩS5˞7&*(_#Ӣ: mMFJs ^gOil4gȨ\{&Yn˂ |*,R(dx.n lp.e3O\Ma d qe81Fs;AAPγ @y!yHگh6pԈ1Ox:Yo1N>xkg9.$dDFaJ9r"v8qOͥ:Nn44agQshf0CM_rD5bJXMx@ ƲTqE0UvQeV"`>s{U'7Xd@+3@9K~A8T=QwQ#~7Ϗ6ĺ_fg8<5^vo\ \"ojMr]`LA) g޷QWGJ"B -"/{SMЌkQC5']§+^ DEuϕ%KG,9|+ߞٽ^|-o<wk]vo_YϦL  8_B\?5 gN#Ggñ\G^XItjOCDbP9Yб}fV2l'#|"퓋 vtf.fyv^"o:mSxu[8뜬צE)ؒZTwTɩ,*8Q>~вҫ[.suzvމgBBwJRp8RVI ||@ǴiR#wG YȖ!5`Xvm0I4?hbdY+`*g)MY(X5Ҳ"  XͣAQbmJ-hYu[ &R:B֤=*XVUtNԘs)UzgMyUR8CQ~l"rG]1(6?zM彎h4A7x~]<sLW=$zERϭs~;@%e_߱ijnr 6ELi_^t}7Q=﬛}y3pzo %e>N`KN6H%O<>>:y/znJxxhogtCG( `nz:?E7{#V$z[ͭYEpœPRB3e > o 23J,9‹υXL rf3Dbo9gLOoi#R]Iq7 ªedvk2_ϴgg -{qHҸp#5d̺3&D81](Sjv) W^nv%s?\UsI:>+D@HArBy!{iG%H| kI=/OGϒ Kf*}힐sm34͚+;--jq!Txa<eUL&( 8}zS۟:xoAs<[ qvp,\orXoR0]\?$ bЦ; wHꠄw6bJtھTDhUL%1+%+g6BN Q}ӉBT1EEհϝzub*A+xd;DeSc,?YPԐN-@bLa iP^O'c?܋F}K ">Mc<[qsNᢋ8q*eH)0;uWz%f~p#\ S Ǹ65wT䟓k^ Pus>" P&Vfs"n;SșEEZ?'ڝ9E@<[`q:g_;]* 7G2V(??(TWdgۿ 6?*@<${Km̅k3<|RABXH\"KMU'sr+"[ -T<%yC]t"#u:7P^?|OZRCEЫA?!B!Jbk.'sq=e()OOHoVG*Kö sԊ]"&]e->E֊ *żM&^<(0v\.:vLlIDy6`g+FEkꝧZE3(f _} 8rP@,] rC)x9Ks6J/4Yq|CckGMr9a8k]jp} IDATUJdRq!8oáM~΋_66BT"z#W? -z͸oz-5x/I Q( `W4Kźi|w )/Ac]0E6.{|ĆQ/-vwbRWbֹaR⫮rd8ό<朔s?V51KqB\:)vlK|ҔXZ` /ݙ,sS) bFʔVw̖9<M=PQ*&'{E"pKV{:4P-p:c\k!w<;ِ].`UbbD,THwVBfXbbt"|]ŸÛiL!4W%bI7~zNũaկ_ի+F52XG^OB0!AIKBd"KH`k蔩M|m7׶3BꝆ 8YFEɸQB=@_o-\TYAemLA%!-'՛&EvQяf%{A:GNGJsE']F1* 4Rӽ?>\؁hAow ʉa)PA@{|`hsbqPY'sJUmPmeYFTSly@r+"pQqЭa%Wm++ܢ[oqh 0'3U{]o4JLȷs^{@ެGwVT&~߲n%azL)_%OQXJ-2U/!B{y"ٰBq6DebbGJiǮB_5Mqe:lbL ִf0*]LPEfӀ9qQ Z/]Ӹiѥ !{m_,,t#6)&Uc`)HV($ :dw^Rgi!y7v_$Fhfſ/HZ1ujǵT*c,FrNxzJd3r^|T1F6eqjeCG? ;C<>`C[-fvM۬~Kד c?ׁ pJntR+k_3 C wn?wQE:biSTT#zkd9TgF&ʅf59T Br& +;`gYd̾/^N_R2%V&'{g)`8aX%pU\gW=' }RWw.Iջch}V+<ٌ1t\PJ`%S[&J,dǰ\%SI33#,YHwoi-Ẁ@m[Ot`R4k34tr2%20XLq<^ "N꤆iy[sJ>^=hAܕ"I6FyVbE$JI$\ra JJT-&gmCG]OP$Cdr02 \GhWʤ_0aX}k@ ]׹[. 13hLcr@N4c ;7!l q" eƉ*kcg0tXd(bBhoL+~[i;W#GP 8UT]heeG'0[ XXJS!,@(D5*P@pj6RDl]4^Hu,[ !P1 $<Xuu6/@:,f y#_yRyviqmcj.53Ս}i:6/n<@g`j/Iu?y\ Lg~: lb^6UV$[3]3v.wm灗|*caY4xoOo|3s+˶!mN5ĉ] ݿm?bֶ] LOwMH˯nx+`n/FCoPz_#w~&v2R$QN?8u!nυڭgԼ@29ȃz⡺ g+' h*5+rgW=vTN|0}$韃od0r͌!Wqn,\P؅vP|#;ռlT5>ўj; hַ'sLӱ5DW #U 8sbM>~y67w>␽" ǬS"SPTY$xKxȱ|5ġ_ bX^!wswIzMޖI[Eux ȶ8Y>#z7-krgļ5lԖRCE) t Ǵ sgw'sBQ|'3vqTpQXO' 3 EQc >&rkbFSjgbr*ȒټP2:s8ȩk/ R2pMZ(j?EC~Dp#%<}w=6&..IQG.rx~KKOUm__-U_;.w{n{0d{HDuC}sZ6#&@N5Swl9j /cs?znVI3WKk? #- PQ\F֍λ*6 'mSo $gKY3G3GU5c#ߐ%4]Pf's˵+k>Oߓ ͙n8\^ضrߵ^%]L5?fT{[K'Ϟ>KwsW=.LJt`>Cko":)hhS#/~a*tz v\oxz yν%{.#}Nh⮽J[uB3ݛ#˒fw~)1i 8Kx\r|]TۯpUJ<$yjBչ43of0$ř#EMA` &x:2&_dL>7 LtrEU&p\HrbV*_L 7Z5eNnYwU*L»SJ-N++u#>EPřIU(8V𐹸]?!t T&q?WQ" uPJR7v]wRۗSq5Nd|3A#DreO1G6wB)h8E"Br#&HB"+"7R p( $!&kfggfMv63uE^lGčr"d`C=)aURs2JyN#U֯!`.iƀ"a#Whc{OU1#/]_")>#2^Py5GEpԻhc Y t4`5LW`0Vy.ا^C{b A*N p~a*7@`i]JxDك/󔃝$PM$ltL Dsx%N!VKxHIC8larD(?.B_;3UXaQI?\Y~ӸDDT.Iܣ#acgw1ј *>BGi성\E?{B뜣E"ԇCl*2+鯃 5R~'/3m^Wƪ W/$!'* R )B?Iv0'nDRuVlm*\1Dך'I_C1 vj]IF0ڔQLLv.`U!s5-< Cedi;NpKҨ .pwAt醸@IKDJ%݅ oz ѿ:>0t&>r Yf|i i6dE$Rkv ~ZVzcsB˗^T@8%.V ! tO1qB<8eBB&#,68e(ퟟX5;wz&:/ fn?gzOu)yDJP>]LdּrFz1JS49fBR6珘(X-'yfKާ jƝ?&y [`[bOk~k)h}^o0(f#Ou7^:~2OM1JOQSՉSݣl [Ou ;~2NS, F z VI.b q@\s`,.krٙ:?ִ>cP8?q.imgkܓV9M5ӆQ]<ǧL*&cz IDAT/EV"VY*7*/ XC+j:|v~[ &AF/cݵ TG6 9uqˍ'6nmýn8C+7l>^'tޏl9|Gpo@BHi#1+AKJ|O)CbRN q&fDtō~1C;Ah%BX:+.K L0W>͒iM0!t~i'JZsþ%Ri`&iDXYE]}[Ţ"C`֥F0nk UU\.e꣭G cBȊC^>KmvԻPG| Ƭ`RBC@>JUtVt[W!sh-sʯ dX⊂z {,EQ^|ezvƼέLf4;Nst!ɝ8_o$PȄqDbKO9mVޤk_p/2,}C>q r bvz8Z1VˆqE繌%xZ0̪&`@ XZC! pmԖmuJ~8H53>;XM&A?=>B 5g {Q~ |p{%&^YB(/r)ݐ3 P!B`OIl؞~)b}=us[7ݛIuwn{gV[DDt b>P/'?z}sMمg~DzwԨrg:W95x̣ݮ%[?7F~TpTvxVWJWdC ExF m(qRu-Uj u\vIЮhġhĭ3bz1T=(/AD2kZX+ϥ3!tb|܍M0RB(5G-uə'!S<ԧ.hl+wQ@yP hH%8:qL}6-k<1Ғ\[obPiW4~++ E.ecB# R[eWtMعe)w֙=Gy4J6yn}a9l9.o@(Iۭ,Osjn+}RuGnBz"]$S N=γl4q0:-II aV

      @}|̞3guѰH1]ݻ>#c@@:Z&U7[T"֭!ȖM_duL/Zka$TTw- [ H2Ș9|Ќl_e٦3֡7mjNămOl897T:|\Nc"aVٙ3No¦3Oh\5 A/FEAQ;讎jLpUn>`<>;3{` FOVd# .Z'>IQ7F;Bbq8y}aTJj9LjP=l+f2"3(<;&GE@%Eck6f2)k0? m(^0B>2K`*< ^)ɏ_;׿:}-Ao0QD&sSӁJl^xnK oz[|V',Ux1F<<8?yH@[Oy0OdH%4Mg: |g4s@{?\ :o&1 _I jJj7N\usIsP-J"q/-[ ꎛӼQѽ,Lҥ_~՘JNw9~nrHdR~ON]% w\vɯUW:iWˉ_/9 .pW;2ξuۏP}gミ s;/iU՞C4-]-0T!ש/om LYPdRnO~୑a;hZ嶾w5R%\J 9i%~w:Fi~u98 84 .lGbS hg#ĝ vͦm02Qub! f )GQ# Z0v'8ȃ\2N-.׿'ǭGY%9e-kb:Rclgnz J?KY2XWc̐%e VS kHb^0:7\iW͸@,յ7ݯ4 Y0%lX!fɭ-1 o.7&Mr9ܭ ;r2?=qopjBlR h=ռwk mM8i[K.H^j;`1ND noe G">rYBPǾi ~s)o14;̺~]? t]Ћ޺WZ+|h?\slB_86>O467N4 ްB5\ ~3_q6>(V\ts>o7~kq0vDW'?F=]| z{=Ժo$-3o<֓_uETZ~xFb噿^Y΍X"h g&|+O{?q IV 42z;Q`ARt΍ AFׇNoF\HҼWH>2غ~גTVH:IuMj[qY\I8IHv7:0xq w!ʊuAN;i⁁K@r6KG Swd.%,V% *9x\P!)xXU V19'@!t.`bvJф={;nqf8|5$Nzd>n !൑(i!ޭË>`ˇ)&fgoH HHe-SšN!Mdxs& /{AK*v>8'%7j}|yVr,ijRU݃Qla]z^lz~z˺,Aܚ.406zHX@oN 0o47f0=[qDEub-I3F,SXD>״⟞ə!Uv!5e+JÝWsY QчUn] Dxl24aWntFuKn щ"~xq(uw\F[0JadQqU}R N|{~ *cV Rh?8w***kR'dZ{S|:-FVcGlr")i>fvNI ޿#g7o({}mN(8mwHO,᱌@ZQ Ul3*6GrˋTHbB87%C4m|=D=J٫G)rےm"ʏNh&w6 Nj ê>35O+Q S8gU͘~ںÊV.wt=Bi uu ^DBrX6r!&T4!U:Y ` $P c\O˳!Wsj+F,VrP%* 0O V:[BgL0I4% [b@RJK7G3slz!q`k3i,RH57<(lq,I5=%hT)Pkc{x_s_ ˂xImz#8r|lGDŘS ꑇ{>p 5 p-go~=.Cki\'^1ۜ=bWp(<˄=/__-YPfMB³2׾M7!wDZLwׯsEE*$LSrA#yqsפ`*v6BphQq[_ mȘFؼ%>l7?,cB/m.5Ue` M98?וyYEijRCw^K]HZPWtOT FRͱ\ݗ]{=(Ԩ ↜ndF ]3dɂt%vH]hj]MU7@%21SH9R+V1`jvճWCj VE6Dǩ3sl 8$bG#0DWs#볠z s>{sr4p8#NF.["[CpCB3@A w1-;c@;OBy!X$%Q54HiJ#otl5FM޺qa2Y?&{eޒ Z8l"qF{i_ A9bJhʡLm0]R2wgBDu--!EBD[BzB`UU1@XUUU/yWUUUǚ?dv|`+BxuIq 6#t-f9%ᾛNG:޺)i&ϯݵϻcZ N^g;~{vv}+C˂8V{`;0j&stX{\>E|喙孙~}c[*i*:W}6.tjb }u¯;ޞϷ p*DkE# PIߤuo.=M3Ω.ɑMNO,EGN}EwCrj}7?qJ ?%oOH 3vqI)F%c 03q;Co# ލ)Yx 0mރUqk86910QX x vhyCwb4|@6t%r,ڻ3mٲK둻 \(p;$eR -#Z]Y:aƷoufi\J|׍4xAVYLkD5 f IDATk`,:t16`B`aW3x粉x|( 00 MuvihՄuUEQx^PT5/IEI$I]۶Ȳt=nwf-ܨ|PK' Li an;yQhVh~iWUU䁸:)Rȕ7̭1t7 L+YPpܾTxuEhz97~>|:8EffB<#0,lYLgh 0*;ofҋ9{س%.?”0&G/8GnCCVLlט)=ic;BE ֏SUEQEE!=?_}I^u; !8ck8!Nkmim#Xbm2쭣(FxI ΂2yw.T4CE./!kU.->l|9V+Պkw҅@.gjVzؘfY%~8պ<X621233wPopiF1$!:UL 2 ͛`BԾD;%$D%!/:=s&] [B@{oV3/k[zDᐋtӃ]gYSS.ldMvԂ0}> ;+;S>O$|P*k26gfEs_5*HwD?J\ єvp9?,FڱyVcڼY;4b/?oa?Ӌ+ [ʌCe=,\"qڔ֌mm XF8tki3f^Εd`tS1g [_N`2YlDŽoE/Vk[AXQzi!fn%Tvâs9J*}`I= 2" PCU´JAZ(@b@^1ȼ$^}+ן;R!kdc9C>FPVH So0Q邝۽FartTKAg.㒇H&'{C{cV7X9<@uϙPׄϾ&5n/8f dKʾD*x׆3u1tV -_!9Kâ/T~^l+I%9 })*߹e[+یxnI$!lE ?=k{$ (]Xmdr2峌|dj1.jW=|Qcؖ촠5&+7j֫<⻎ N̫Fm3A.TsjX.!rd$_xag/^C%AYfm[%[CBD#PJ],l',!4M[-yͺMs*bH:av]eMQJ ~]Htlo)CNYuf8/ {#V_-L@;ز$-!+@rX ` {AzAbƊ{Qh0iG *-y8n/k}5"kIfmƆ17!@MSSܙ+k3~q%E<;~&Dg]ް BTj뚏Lu%(@1zA rꙷufw_Y,'UE>xKzm]Y']ٳhlh`>aS'}jU?)=C |uR>}jfC$1, 2(+|q3!j!ea;1:'szp4ک7z 􏲳Ff 1'fά*w" q4X#.?>/<:0j2uNÇe#9>&cy:c8Έo~&&5XExc!!EtΊXɴjSĥ dή#̍rai,I=9yW`T88v7 cd 1B` 9O,ylQSR.)U`aَ hйц?`0ڊ$VMŪ"Djk=]2[ (4KUUYQd$t&N3Yp\ߞ582wUٿ<'r~8rvZH,ڛwRk-N2Vݴ<'Bxxޤ$ !:x*dKƻwg->K$&biƘe+n".M8G²ظeU2 Ql ͐S$y #_$B62FOR@G$\/BQ .q-.\ɫ8Xϛ0U,&MgE-Ѝn++:7XNNCqģr !׋:T06;u#-+=!iD%qb"Ggbu1B(^,5] /:ġu[9/ cWETcίtʤEi$@Z% Ĭ1xrŒ̕Ov ! pacx1YfSQơeI,IŮm[$kL<&qS8a,tٸ9S A0" ?NN r|߻м=vcј9?ʃ >1w~Pb]8u~Zs[WKESɐ >x?ujvcf|g48IO.[ ꎛӼѓ=Lͻ,u* ׍[P7']  }c}\+Jo෿jZJ;8ǫ| 4~YjdA[)>Kbv헥5԰ZȤ-9}4sE ^y?3>}.߼Vӽ>Nxn,"k"I4|=@{hxt=bgk$[8 w6>sFa㭯zRBquO[UwԶP^4>&*@2 Jl(#œ}IRִKGn^N;KH|8h&c?r >{9GUL?P ]p$C_֍zbf |HCDEE!5zԵV̾~V}jR우K+ R NSߍCOrA,[ g6u#Jp'h'vSӒ (M9ioE(brtRU7tw4Vn̔2 qcTcEו&bCjD]v*e&d14wGF/q2 tVgJ[agwf\,t}IX3},R!E'cŐ@;S+)({ (L,b@֎beEYƏIh?Ľ©i=s}r@>(nb $7m:1';1}~畇WL|P?yri]\m 7^v?-Ϸ]~M.V*[qUn͆7S^+o~ۻNEMM*ZS뚿x{UΜ&˂CbH)2 ?-kK.1ofk\eH r<53K/ʺu keP u9j귐…@ձgz-+$ۧ[WVwO @wЦ/;"/;k52u3q4Î=<ȒaWOqIkSiiƫ9{pØ 3~#A~tvanmQ<# ^e)ǃL-JG /˃Ns|SREP9lNv+pȈng\QoRŰ~Ə^Vr^[FV>҈99)٬C~h5ٚOnAcj ٔ?Y^,#8Ybk"irc*`o2T h>8|i7je'cz|wѭ aW痿' `&. Y~.ڤ6XL?ұG>c]-D<YÙ:4[$ {+c'V)[hA7w/~.X*hɷ k/E@Dpm^Bko{*Hq)us| dvm,*( h0׊!<>{ cHJAH ~/j1 B|7'jXE]~/&3@ojr">1܅䉪Zi]D†Td&NW( ^D31W-E?p𭑫`d)ltDVq&AC8]w$ Az8ٌ8/okVj$+Y+`FE~=ca;dPM?]i7ɑ~Ѿ *RK|Um-olYT;+_[ ¢m;@EieKekqgm3ҍܻh۬z;ɍ|(Bd{o>9}@&2 Q9Rۢ}bbbJ!ģ ?a^ did5-JQ393 \H@KNzjfb ,E6my"CB0Uۭ;װW4EĬR$_ۇBxD */f!\ֻ>ӓVäxk$ZLs\0h{ֵDa9͌n 'Z "'2^.yOcܫ/ͫqFCwCn+Ąp+˦,V[v!adfMDŽjGD*_Zy\wb H|<_Ӱ9FB,O7BPڶ#9R)[BZ|TEZr򩋖f(%-F ̋}m }*pyy @ӯYR&`!L%3#a@E ,V V#3Fxxߚ1+ R ~ÓZ6Fc*|4p}t Ty2q>`\oX9bC߷]("9I+ H)HJ yjcQRW>18~af{U&tcmn \8jQxIXՋYpBR"A7 ڸs͞3mX{{OJ'HD(kvu2*HH*j.D6, B 8(}xfmhf'7+_rk go9#QkC`WSag GNO.N7{|k듔iH.;p,nnR]U!(SxS͕+B(&V؞'s ajMdu,?e}%Mwfr̵w6HGOQSՉSRLlҺH)-jyH(/uJ8Zs]0xy:l M{g/gĸSU5 bABn*VU5@vNh<_xlaHpy>j+' Z *H6,7E^(ҊPruDmR$sb;'@Fb:+p(#8M$KniXٖ)T:"V&_x!*ce4Ҭ4e%sjdxENSmxbDc{t\RxwYG} 𦡻 Y!ɟS,%Tnߒ#Mܿ;(q|+[p y G#G^:k3 .QYK̲lE{])X<`W T![9d$N'ҽPKGghj 2:b.sFDak& Nض"{c‹q~gK5̠Oƍ /i[85Ν9vĮ輧\R[# Ծ_7un׫TA!@ҡoi;z.iW@鈼uk>X|xu}  .zMwv/59 _z^ڳrS:=&-(d{8QZgq*8禆[PK}ė }=\ a'WTM ]Zem%1bKWoZ1?+.GF2C#P"uX{. 1#9XEӋ FAZ֨-r:=p՗]N?tFj˥{yX Z ~k RB4尡krٙ:?ִ>3BLǹH|TH^??1 Դ>˱d[X\s`,ϩ_c }?OOQ@3;χ5 "u{enO")hnH=r70rX{SV)):9z5TLܓ^4tqP=չ}yG\R IDATZ0W۷(!*~UA *M21즏'4gaQEx\1υ* ~Bp"ˀk '8RXg;DY]پؘ#ZN_[wbPT~Xt)`8co\Bf@W(*Vnʒ$I$Rek- k i~#2M|QPrlnlRm׍cDUբd&J`0 2a.xB'Cwh@6U̅N/R H}N/6 <޿^|e<lV%@0W7xoپVڛͩj۞vۊU q2{Wnw7;|m ^ (FH|._4)|EG` 1PUm&+B{'i(N6Ct&mHA˜fwġC<+5I=BJkyrMneyV zڪI' c垆&|D2&9m~%ݥhBQbο*M N; 7snn] ωϜPgwxn:z%9UعͯHn_p`\Q7;$nhI~;jt::6៽AOYeNƿb+D~pIڇbX(> 70o ?Rft> ]H]a9!ڮUŔlDKl}:XzzS2*kp:8AY;}FS 5!ks2SiLmըe8TdIu!SB,hhuNeŮ|pѵSyF6g;R_olGqa 鑽.7ϗӐx2cƊ5b䲾36DSYW;aTL}lO-,WK&(P͸ɁBj'u=Tb8??{ E_uOܙ] "s8*<1'<<CzzzfOEň 3g$ݝݝ ѩ:l-=U^UWWWWwG*l̙_Q ΁ {)]cX+ij=F:Zi*kyO)>FꞨ1s Zp"(&t7.\4g˜aUH[!miEbqDj2ՑlRf,LBkq +TAt5#DDiHNA %gQxSPMuu _ hB^j0^`|.x`D \nո洔of|تswjƜ=4J'Iwy[.V|OkH[w\>轴4d]/=RS\J?%_ajCxM|kaۂ?ԾKJfOT,pץL~<.S}κ{RFΥI`49`NitL~ BqZcx %,$]`oq]ԓ?,ǸzA'H!aMDi8.9` |$:RYhr1HF*bKd#&f޹ ᄃ"}e k"G!IG#,!Onヾ^ďU6 C6ga-M)sGgyԶhOˑq-~, Gen[h𨬫iUu`ng~fkO[* \*%;4~+>MgwܪwzGOaɌu}ҊcFNoYhAvFr{*TdqKa9 )SCz2aTXܷt BuN!"5$^bLQo R``.!"JS :Aҩje$X@YS36F")k)REB4n*C9{~=: "+;=Uc.|&c`EMQ Xc}~F͍Ay:柷F0%F>6vpk+9rLtʧW Zvrz;7vE-Gxl Jͺi҈xW=l%w5[~ Y^BNM["do]lyd;▱>Ȇ]C3_lCsAw݌KMӿPOT7|[劧npng4?2_м+\xbwpU-ҕ4]!ڶ,Tp҂Gb0@eI_S.!;ϡLwl$`KIzx>{lW[ I Ps@ⶳ2 Լp/8}ӵKU͒o~69ɝ?Ι`P&dҫ/ N#9*@Gw!|֝1SV{1=ZSGW(W)-4v1B?9iЄ#'(Tإ0VSb6Jw4PG3&:&bz7ǫ|NWҸqVKhءLF'#M2*lUep+eZ}rqu?_4]$2r[>tS'47~࿿MZ~:e/̛V}[`xr_{ t?k@ -v '̥[HпgN̵Ob ^^ [/ɧ~뙝^} ;ܳFvn7CWX<)QNހ, )*Oc’f)h&/]m]O,gᘈ 'D1Ei%˜n@:$K#,EmӨk8sf5}-=crc&ijbv\B`{nn=5Ѡ]| 4:9_BhC࣊'n9i(Znq!ǁ%%C~N5G(ޛMGo%fӖgaYc=Y'+ZՐ,S10YvO_ڔZ{ yB< 𨹉oD?Y1wSGs@j#>e`u.h77S倄 KO}(:\H?*ĴcK8nKBگ;2֓k*r5H,'_B>zWFe .`tM@W@fIpE|hG߻~zrTk>{zC'NZ-K=q]˧N~'{5Ӯ;qd7{?z$_90omM>L{M9:ڋɼ) txUh+HyxePmMS*#{uq!;N_)MҾ*tcW6|Ye'ɩ~ nqL *Εp52#= 0;]F{+rS$8QcW5|UٗlUH7'v&u3Yq`n_\竧,sq8Dm BM4MIo3&E'9! r̂2u(;=kǩKEde4!%K7ǙsX9pлA%۱( ]~MjrѾb9!( [ɟkGbQT6@(FbJ4ʯ-Og*qې!` SlqJ3rAU'XZ*v>O=?g8?7 s3CΟw^~jmy3o;p_^' p{Ss][7v#_yω?$ʼpsk=L[oA__#Rko1g.Xo+yN]{ ptu$}VĨ{f. Į?/Fu5qlmNk~jbӍ]s7[1X~|&O*70T&J6pś']O揮O'wmYf  Q#qK3TC*T*QM+JU+uMa_Y0d5A&M'5j\84ht+~>B,A2h7BI1l{K/-kSkT$ \@ʲGn$ݻ6ٗ[ӺQʾ ;.0E65yekWf| {eVBa:ȻL W!UGN{!˖FL Zaa4MbmfTRI?抩?a!U{r.k1Qj~\{̝:~|<ͣ`ej6lkY} ߁\sJ5s99:ektcKnC kwm pweZCMos-κ?Cװb!,ٝRl=Zƹy}c"ò Oǽ/m毘Z%yt\ѿ6U_t7/m4hmކH@zƋ,76|6 ]6巤PpX -P@/MUW/GT!zD=UknA 2$_5M6sIZi tT­$j~Exׅ4  E9U^ڦm7H/?Zs*s)a4L(y #,)O2;nwiHmiB&$(k5-{聏o~DKiيuU㮹to)K)|`("ncpSomԳW{r{qz kcm,QM^ gj"}7ZsӴNhtD(-94+yG>jkr5<זCۜfy7FZsMׇഡvq!$|75|˷m;8@»oz=z3qn͗_<P}9 ʩ`jOpSl/$}$2WfhBF.vs}_ יּ 95 D9ۼ7έ MV<1ml~[8NIo &dieD>d6 !K3 T"`5݌?}16T]T ڛڴ~Np@ލ aMVx2=]hcAKx^;}/e5s/5AQt!'@U5H}Q0 " 1+XCU ^-#CXf6Z$GGXmd& ͵JS8>{~ك}3\=buCvu މ=p ὦ\w*qܴ؟m8H/8z ̠s=i 36Ft:%xe}msf3d]s3M^%l_d"`#%\/9H>a11 ^s=i7亲וMWgM/qf=ʧ|S.n9˚ z|~拇+tΦEB3־hlojsyF;CpIᴆuAEX#/hͱ͋iǝAυP![NB'Ŀ<˞yR$mMIFf#(V6)$4a1o}4Ub ֩hz=UJU4 ,)yVc^9#iAPUU(X<̿xǎ I>^L+'vf.L}O/ݪ6z %\6f\6ijؖe';uT[k2Yw NGYǚ%&Xn⌆;pvO;"Y}m~.HZ[~5HyߨDhBoeA}]߇85(9,=}}qՏ&MF)0PIgz}3ˢ?_x%|y q-1Cxwngҵ H4#ĮAA1oDhg@UTnbB1;Au&bZz#6x Dc$  ,2HѢ1g}lC#&B]dBuLwԁ n#DaQf^ Um(쩈nf' * .** 8ev81Mнo|kW!]6ܩc]㿨u@8q+g âEC;fAEE5&{Pʈp=g?\x2LUUd}mI^3agϱ'6~@ 5΁AIt :޽4sfN6.ksYzs;vK8O=YiL=!O$H5~5Տk+[| U?h:1ֶeF`t]L0&!g7Fڲ``#Xt)UT,eD3AE~KU,Dv{{(Y֩5a iJb%p0֙KC]PWeeAc500J՗-m*i޹'5A&C܄s"aܥ\& dm01w3&Or$NG W9l!N nYw3 ೄ/HY9&:nkd F @[It.:8c]fƈògAWu޲T{L۲6.Q2pU XwK++2QcgBثA~%z.1Emfdﮫ7ɶJdvDrAۯu^i۔3FPԽVE޲y/E?B6%2mJ02p`G<&A^&h.ZUw#u`+P9Yj DkX5';ac  dj7+4rxQb %;R `?H oJb4И`X0`sA1`1~Li^!W-ܩC45y!&=rʎNM T%Aוe Sx ;1'ML'AV>X( `R 4FD ;!J(Y &AEY 4FK'i\iX" EBq KzXt{X}{/%#*r"`) ;TsA/O^tg5k7>r1H앍o3Z V4]DKQlG4JjMi,̲SB|6+ؼM 6t_lc;JGc2(M#0E?#գՑM[$%S!8oZt1$/8- z6Q]r`m˛N[Th`R:Գ0X} [^/XcͿ2d2fQXbV;ӛP0#Dx@VM['Mc͒ !BKQ0sQtSj~%@Ҕ~ ePU*i m pweZCMoss< 6q;^E8p6ڡi U]'8,OزS%H6E RJDΥL/Q;l̤C͙lGlfٱBX%C"Y 5k›bȾM!3u'vӽ/V\4IXKT Kau\Jh_R2(H{B6T" @|t4yVoӎ/y#5L;+|Ȇu.=fcX8p{Lz, {Ż@YIFjAt`躤af;J:(,cP7aS[TZ}0#4RC`LVX9 } VL W!}qXw@iJҝpM>H Fu~dGZ9Arw@r2%'XebRN @Iwp5Ft X X=v1RxJԍݗ}3H抪Km3I~;T]Z!f!n`:uA/f>r= AA^NF,lr-EnaJ+gf(`ؙ}dzG] j?E; k@W-B^zv06Pk -,ۅO-.U(},ZhHl`,$!UefIyEB3ghusnuv.2O.UA|yqA  .*ҫ280pX('|zdmmjF%{'tJy]kQ7eYH-۟86[݊ BZ֘(6+qW:K,-:<7ag=y=,I lQ:b (3q@b,(DSƋ .q󌭻{z)NOb?{夤$)bFvn so\? Wu,=-1]%syhᔬW6VUF68ЯHp- K9 ֨AխP)eHAIbGx2pF.pG@62yU>F9 qUn%ٞUtֈm֨ GԘܱ#;SGmfLYhvCT2ښsHۼ&a ڣ^Z:R{ pDE,:-i#1ՀVJd㈥&V׼Ȍ&R$![Rb#I2%ao!*|([?b kG$~btzMXIKI#pX9&:nkd]شS[v-lLR'568 ־ƒ[h<|2??sq]=6JNMoΟB\MGMo. nCv=~¾0}bݒ-~P~qm5nWÊ%0vPTƫkL~O #6FJNcS`m‰SI;#.ٓja]~HaZ<ЦG`u&Oe^5=j vL1  4sVө; @|cWgpbyPtU%MөdJ717^]Z;xBkL"{73n,˪}d^W4<Lr$uw/ܾw5kOwY!~eC\ =~j.*Gz-#`.S-p &='91}Zޙ~W}ZJfHR#]3Mv& |ƒ):;9M9y+VJ(iJ-3xP+xB)T`@redDe= J¤YyP Ka&*8=egC3Xyz 62YmP$o%,  jJy"LP%Md,^a$\eɭH&'ӺdZ셞?>)a~k i .7we^09.< ,;7Uy{1opgoȭ+.桚Rx/8gs{0i'_7?2@nؿKy1_JEZ pLœPX2[QvEU򤿲y RNkݎsfl֊: 1!$3EPbնG{BY"qeJ %D94YJL≪TL8iप'JSȃ"-OJa] 3!}cq=Gm18)9?n>n⓶!8yS-u`<<?\L֝2(Wxې1n(?lLuxSw|00 x;R6殺otǛ|k1B9t|p|mHhv@6]XԽ7 LTj [eb۽˿c+sEwnؐ|fbv']4n|׏ o<Ocˇ伈^%C [$ nCoaSIϗ׹źEdBrLsR [e@82!2=RdkUD+Q YQY {jꉬ|}dy(CԊobB5@Uɩ Փ9< ,'d;M5cЛhPvu |q e=Su.ˁg7TfaB!+U殺ngDXKfiPs$/!dq&|QrE/銍g𙳈B; RJ%ʡJOȄTGȥ!d4X4j"Hq}KMXba a#H2]Y&BH4Q77ł&B) ,^ɬ OeBIw&!Q\ja~;WJWG7oOzu3FbJ*)?c-X<1VI\<ׯz\"]v+15@5f3\~ */ zoL"5yKU҂mEW}٤/.Ս0J(`i+VZ׵wjEK<40\ާZqMWbdJ.`m3b(ކGZ&M,Ur,PtcAS꺧[C,Dl{m'|mEVDT}p+tu=j/$#rM1N%Ē6{μh&&y@68p]S w&jͱ5ʻ`^Vv@<;`pzIIڜ<*h/"j8㉃@dEa@)d"/e+GD[:H#&ZJ$KB˄ƒindeΌFºzk1WIJ| COt'8PDjT+ ѝ gC8I`,n bYH.TĄ3}KTBj;@0mֈiFL+=ܰ$r+HmrB 0Io|y8?dP_h=1>.p0o@_zE-Sʫ2+1p{ {1nnFf:ީ&{kW^vÆթÏKkYVGk×^vcGA.\& F*$Apv)*G#Zah]܀y0?$bŷZwUy+g\s F$W\f~:~t"Ddo|̆/Up$7`뚠bl]9`Ώ߻MUDr;du \>fuGm[= D]ܑUẙV@|eòWUGw꥛]Æ Ɏ(SN/T[|M~؄ew?7!Ah1;%@#w&.2SG1W@׳W:Pѥϔz> ]3jOUѿH8k HG9{W ˏKye0 dSc'YdQti/*i1AZs֩35_*x".+Ssrq}sχ>aӉn= ^AZXJCK IDATӂn8[םpRAk G'P۸@75Nه8WÏ,(K͓GO@6TI ks5l=UCM< m^\s^S?~bIy8f9R)6/Jb3vV96[K)7^: ~U)?pvC5zdQ;/GMz\ _X̖5uwo.b4&xUyhݬ/ VⱹwPaqi}\+%cs+o,ɜ s mt&wͮoZ|>ppjLܿp0 r ͧ:ƴ-o'=5 ֝R\(Κ)eUNbI\ tT_0(Hk/]3Xr'ڧ2XZu#O@dq~@ hD/JIgRiprLύhPwDs׼Xi&`"}n'%QÎ*67-dYZɗBJ7 洲FG#G?vat˻S.0jzDpEK1[.ċ/{?& CKz(eAb{S\ '>*UjʂO^QMhyYd1Pw#*T==MqFAHX3 %Wv\CcaVrvK(ihLVɚ/R3# j ` `C:˂bBĿU-m~A-*AòU)ja.+2P&+PI}DD +dRx3yP:7H鱈+10f >&fzOz۟p|%-jY߽ !/EzeաS*+6 ;7z6.bPP=%39&u>xjl}I`I%DU цIR8Fӣ.zocΪ>4(|Д8 'Qݕ~WAǡ ifSK]jSV^@d-/>pJ8:2ҋP}VUuٶB6"BIA@XԽ E;Ӿg W (o=.Nk'|qij&0Tv;L8=b>܁L4KqRYZȗ!*gߌ(R4]I%@=Hv_sRBףrb0<WH$0-"ڰPK:i-RQ#d@B<*mPuP  d-H .o )5_u:bj5F}t\)="xM,8 V[2!(O,9r%5b6Z;HBEbe)yF -H 1ɞt~t8²akxCUQ#z30d(lZ~Xno,lKjʜC4i VXNQ~v#A2R jJ=)P1 ӑ9%ڃFXiis-ڬȬw).Ů !ɷC_% t7dI&":K"B\$PX!UlO$X%.N*"Y2c0x<p^ xbtcW;e "y o쎋ZhG3 uYӤ9h>E_{Lۿu] #`{֥$( 5廃Znؓav#!ڷz5njآ[FX#vT=#LJ04dZ}{@j?b#`D=}j)N|G<@i^YC m_ë]<@d=W$U% W=]Y)fRЯDNlpbgfK7S&߾eiº%q6H1E]xPwj_Bg kkNp+Eg/yddᗮ7wܨ mzx 4*=w9^\U{d#.[Qm,=~0kW|drUyueyfi*њf=&4J~ 7w†L|-wRǧJ?˜؉ouwojgzk*VHި:}wأ>>^Axr\zܙ7i@[5ߪcoƞ+kz,Ynn$= v/lছ>@%٭0켫?[[ *c[+k^'=fIc'ͅb;k*VԊWTFHjEÓw&u}]ۥ.oϿbktV+K/|sl l GRzxrW_дuoZVK^Td4ȉVk_9w-c0@?뮝ORo=w_M04mfYFKLZR@*/wZ-u6wV"Pa儖|{Bke,&W{g 3˵t -gޜKM0[LI&%Gh?BiEX69c Є-]A`̰;!1 J"h@ U &@kae@r#-eUM(` J? zGyviY%m:s**ɪJ N:}zT‡-96㟶$> GO@>^ V8RR'{,e[ƵmRc3eѦo}mije(Fǎ=5_, ' 嗴BAqpvVwH\ X҄Yjml+$N<[k`Y' ?'QS#ȼZ`ض}xe9#Cy^LB:Ů"<mv ztr22y4ٲU)s,`(WJ&9AXȻScrluY/::rJvEOP?8N=n7"LEzbmB,T//l+tol0lZW'[޵*l(JJ!44!,Xzv`ggApWn0XK}{\}pnU0z H& *'Wr RÀ M()PQ!3i89Fc:ζ![hPҬZn&&V/׺)b/MT*U Z[&T!:ZP=+08$W"n䣉va$ 4 ,r$(jHCD2+>F\IK$qĸX'7ˏ(-͈7Y{ w9wҼM8deBsAR) %6@AwBw N/%@ 򭙚a՜Mm_Q"V>QR0RX`, ( (ZXT!(bA) }â(ONE4IĢyQ2GD,`݇XIvRE^y,+ D R6^)ηѷ[?mvô fXٹW2_G% 82?_'9#qlo". ѯK{\9~_YՐ+ZW%] mEޫHԘفCGx2JqEWFj+7vvv$bDMxuaa>8V:.uՉcJѭtD2u ?A♭8n m IQBUpj|K֤  4xj4t\h݊e9BqzEٻnw?L:\ijbh$-NIܵr bU ό)yܻTJa ʼn=4ͻٟ԰jd*Xz0 V=o6ץJ5V2!Ηlթ3 fGx^9d\/ mzh IDATcIѲIQbe տKsuJRp3"UQBR\Ҕթ3dkLT/d;RtűQU^y,:NU2N>dNd鉙>4ѰB",;Kޙ UT'g>4tzSayJyp[?M6~8jL/KĦO@6r7ZC9X-zw AY^ty`r Hra4# G 4#y(Z(! rL;[rȹ.oҶ1!Eb{gǝ-xeD 7Rߕ"1;F3^pO]ׇ^qjY'-,$CJr;[M5If/([rSPwmN;=mpxnB" bׯuCyKJ%l.yA̱r^C{,ɘx AvOPM`ѻEb  E*5 f/(C%¤ĘMѐsyc꿘s`\f|:zBY;ܷ?2=Ut;C.@!]5-8͟ANNJ b(6<dC "|R]5#v҉KJwD\s/VR;_PuЊGy@ߒv< arsp㎕jm@x+*lG-x~J+lź([SYJPwjgy=[|-0#ryY_Br°ya8/-ue3h,ʶXeY1٪`c_sPCԷȪxJ"d@7@h=#UE\mruG9f}(WE/X;1DC#J/Rn(rw;(Ea܅) !Ütu3_'Hd(ӓH~C!FB_iґjhĢ(P5ĊHbPq(QXCsϻ`!H2+|6d2l6NZd WM9Cmu 3}P w0] +l?ӅIx2冊:!aӜ0z\ã\g(3:s›^Lk۝Zn`+S>r?U{GlO*!O?zF_7~ uVTUZ A][OʂM:J;0 H,%K.o9~!9~ QV}B}cR $ud峢eF32xDfBb[;`vTР*Ȕ$a1V[{*I$3 j+n{R{kHF,bQƒ,J4>kbVݳ?$WKΩZ(IA"BrA$W+"r1M{u2y3f' P˷Ew[W~t3& d~ec?.W/PWU=;ϕ>.{CAfUFie)RA whsJzwfu*w W%$7$1VEH4!旣yЈD"P 3@26:B/V<{$w|-TEK9Z3` `8R{54Fn+~OD &GXjDzg(N\PVl),3וUܸ҅a$yIY(AcuI +=F=" ./[:2Ly噛ABLb+q6SR' +#ҭk.W/lF-Z z{}C5ώT B+<$s:.4SMTePQ8|XFE}Cf B IZ!H`.W('V!H1L@G`a|.3PaŠa\edU$L?#%I]iBh9cwVk<'K? /R039<]# Z꣥@Cj !i! eVt5͒_Y@ gO .~^cV y"9g-wl{a׫B:V2 /4^Ӹ{Ud p/>^!W~]59`R,=ݚݯ4Th6Q,xy䶊3'1}Up",ہ><$`K5NX{.#]6Bnn{)X" 3."XҶ3U@6$8!P5&aStN};8شJ9'7(+ضAI1K[&hCS Iƽ[cE+ 1oه 11->W%)6y\0ve > +$Cu&}<^Φ>׎ sǴ߯9襆nr]s;C"8IFgqA7Lf4&$;GIqʿW|$FbR-c'XBJVKID,J3FGH$Ojy!HaW! Az! %Cb0EJ/dp2Orizc3$i/qNGpkGEz$Td(Ig.WhjZGiU@q4d^ϡI0Oo贼2kŠ+;==@TE3stmօ9ѝ]9n ۟9RB1d0}eJ$ط}}-bX7g;ßMY!DM-Df` يbPH 2$1@#,mC95_PD F$iJ}( #F*ߡ0\:"E!EhQ-J;.Za,J? w!=ar@pziR5#5Si0^ldb]F;ZJD)d1ʲW#u<4?ٍr0H yBnLR/I:VEC <Mχ#Fuqh?ܳѓ/P9sŵVh߇5>g]֐׋YIE_7~9zknOX[hߤѝK.84g[ME㗿PLJgTo^ԝ' 9{Ja+ k] ݅ IrbyH^ $܏ PT+Ѕl78!i IVi-xY ARiw9+\R)>ȬƈABF$@P,!됴 a?[G9%=ID%"VW.ʌMᢓ`C ˫8j ǡ.H)ȟ:l Ew~_Й~gjǬw}/J/5^q2-otR:pj}ݥ\"`l-MI|-_zV&i/$821N8r"4L~cyG㗺/Ԑ%Z7^5)Oz*6Yٛc_:}G' 1 )>9ıcRqfoeԐRKuΒ3;^D:6ϛzi˄/zaf0nApV7{~ſW!v{M1p ͤ7i- δ[}`7>mb6 le_>+bU'? m3wmG링n(oJӮ>uS+6 X_~"wzx;2US6%.ֱկwtcla|NLWe. T3*{ݕ"M_ji\Yx}Шn-N,N /v`~VzE-f*N̉ſv"Dp-+Gw:/+fSfq+. r"-_7u7PHwj63h][0}GPz_hxC+;HI&R JwSe)#K<>!U찂5 p@gIf ióycJCpTef$.nW+"TDV"Ḋtf3#RL${jLz#Mc~Cjsh, -rHČWЦjl"|"Sbo!Ms" Xq[ZHg,]-:}n/獘[N)7\(DLW _c/쎲[?,{%PK^J+R ipl8ѻ;ݙnL^I|ıkMMhcn?)(=&~GV@Mp|dcqn۾]E_c 4 9+ogS*疽86~gWb]+a-&ps@* : !ks -Rؖlcfd;_Qi :yXnpc9R E⁘̣xk@2~U` moc1Vj?*~^u&E1 Do^0[֕t( O,ڡBeرM8*~zڳώ6O\GD!ǻozG Pc,+D EZ"T)((Ro& )3T@Ώ&W{Q͇0#XH i1׏hl hW=`S^yc7yg1b C&!PTɂRw0Q bN< u i^kU@wNPXZv#Hd-:alBĢXIwHFAFTydU 95@Tc+;8@@W1EՐ-@fh |C\WJ%RKڹb"|]fsv8F.p=d"fxt-P-#bz]?BݽЃ:R_|r>_{/qk<#*Ep ];.Ĥ,r .gP pMv\>{/Kš@k, ~H|oW2S"2&.YR-*2kPs}R""`r|J4AVdȊt7 bn#%Uzҵ2d:@,lpff?aPDY)QJ7"^Q1QH,/%5d켹Gjwd{ȢnsfEsO55Ѧ"Q,9,rsX(j ͉쑤( 0R\P$X!ӑeJDQHf[ j.=Ǚ 2@%hlC6/1ȵ3TMQU-f9\(_DQĢUgT`vCG'bcE`TERH9$ azv )0:n f7L=b6g_K{)\x^lWqzdҗ cH[ŻxtB=WDWVG5d5U3gGx쮂A}.H+Ep M{&Q 2m̠V CGxe;@x伟FT 'TKEYgu d#Y34$>+y\♭pQPH49[RG{ㄳǤ 9&%F U1G~e6Oj IDAT,+i჆k_d9*JW#xf7IQjousvqG~3bixo7~ՉuBU%H@x_K$4YO!6^>k?hXg{WF+o6m䜟U TR7|RbTPU)M4t\h-/J]1r/O^om!V0e*b όAd1UbmV-NIJ4,3gQC`U4~x-I 1sN2z>aױϓabdd'xZ6KfOd)Ie够K 1WQI΄B]3L!|9[~ѿ:_lYHeƻ 1e}VBN؜(bPP쩛ytf5T4w>28cEU>BUB,JMGEQ ~G '%C*,*BFTð(ID ,BBOP("QjU)` XD JXm2¦oN`1 IKQw΂늄.thF&+fN;6s礮 PCg1^~HSr(5Y~U\Ͻ|+&vzt^`V8BSo̸Ĉs c]Tϙ6 l/;;|lQ{-D 7$;'-yy1 7zCY L}RŇwW? w?2IαOR~M !{$p7@ސ|2g5ԱR<o}˜y5 'v+Ž7-_E y;~^2X; 91vzA]7_/p-N\RxfOPaYI(_EGVub  W28I;h1nF!l}_]qs_͊-b}*#ӃN6ƏY be0%Rd)?mOc}]vf4Vn.\ ˴ߒ8@Q_`m_xHg>+DuOx5tƦǘnN )Fة<5eAz^ģAڤ]P#|i :Rw,čҼsB/m}۽uQD ㇙!Hr+a{J :Z-l pluTK dWh@ 0,ð18A ~g?8DZa0VU>zidfM.  =T=$03^cEwxnVض"8\Oȳ9nYc ^&@MwlָሮAtC֜PFD̶iܳ*2\_)2pYy&[F˳eIOgk"L.ja|~D:1z:Y+>bdOwN쥮o>Ɩc@bٌx׵QAeLce.N̥,A?.vJڨkŜOdi,{+9CT>׬EsX 1WcYuNے]a1`Fg)8F(ErqNˎx,/S¢ڕבUHNBd8y,eM}a CIuJfh biv;0Fsw.eK+˝1Hbrú)IZr=]I|#P$+ .~2׌UJ5t^t)_ |iLel-?G.8!?uЧ_#姷o G_3v`q%}$E7^K -_w;{𖺕'-s~p]9+mIg8UV m()wt,3Z:*6`^JQȋ(+<*[wSm!X2i}EkF ':&eS5{| NJ!1->Wb޲Y,A0ve3+<`}ȨBmVՔ/l-4|)65'y:|sg4?LR0d2 3{HtwչڎS+EÚKG܃g.kB,ieٺ6/c_ hjnOX[hߤѝK.84g[ME㗿PLJgTGx`+M_>ycgZt&tn5,gX o5'W͈V*?fBzsksIΟ0Rg(qǎwl5$jN̴i_uB63 ԜYvE἟f̬z'Cz<%ѕ}HD{ժ'f-Z*`:/Ƈ-qf*}3mA Z~-)r qa xMi6t{OmgDxpc4;ϾT _~²4L}L>G׷L`:G6@͜&8!yۃ`'06>Ms~]_X6M7\ (pA>7f+.?V<22}1Y?_>D:L]#*'-AS\3QtQ`'f8 y+DVw[ _UךO`Qla%?Wd?l7hTpj}ݥ\"`"ʦRє'^gnL#cX˾#w!!B37LIjΣ?*LiU3ʚԉo|53{/c욪>p}PƖ8`h9?dQY*9:%;Nx8wf(&9ge}W |bg'NaWO)G&ٙ0B| N =tKÙhI nR'w%_gğm@rFqn[nb+uϼ?ەyL5/dQ1ey[ᄉ+gEJ-YqƊs;gv>[7Tle/֊2~YᑗTshUf IK[&_}{Y ; q@&[ #E,%[[>8^E==}h!v { 6ȇϱB_q)B)T2Z[s+v>\Op~ RvX!9V|0B$a d#1V913`*Ⱦ( N3pcw &X&O}>`l[ ͡-4NR8D q:*_D,fâZV⏔8mƐl@j‰X ʼnUKX"-Xq[⦋F+37hБ*}Prtѳ॒QveD3?jZA6TPñ=Gtg1U{&Ƕf=659IaJ9lg50-A)5#ޠ'D;UdIJSbd| +6rDCch%T\ *.-#We^uY_p{+rzpUG뒕Txoy?Psm+ G~őQ"r8XbRA}v3(J`;\h.B9=>{/OšF`, ~H|oW c&2'gYR%*2k^JB?)ؠ q>w|@sRM*-کAL2q.(@γ'M Qw{8P#p&^'9pIȼ5}(I5md̲d̎6 CIjױ>%JZ iwBD&/H+&Z.WLYjY{ @IC|`a'r?'|޶l~k/Cld5[MPR8|߱)05e[8}3[}eIS(o,L <<;`:UhK*z1k|W_9=I8A'1h͒Lеri~~/8p}?!KXhA W.u?Ϫ9xhy0Lvt ʤM6M7PNLglyiDZGe*, `0{uk?hXfOS IDAT"ۼjM;Ymԉ COIJ443''3Ԫg?M֎Oͤb>'n`nWԶ", OG)U}MTBAmgSwȣR`!~jT2jach`cZx%37QvGX @>-Z#(gj %^"'u 4IP@dI,&& ߘk<ثddPR3fMcIk1t cA&/ `ŁBd;wx zc Fk_^Eﺧzδƶq-eSWxw}qcZIN0{C&,7//@Fo(kYI4^G: |G!<|O&9vWw,-yІs=Rz7@ސ,P^OH9oo}˜y5'v+Ž7P.pfptڷWq)'ewyy|y%R5ߜ!6̞2Zs4㑅p]xX%B;)İɤ%;nsb~*,&VB+mNϭ2Lnm;xL <^Lă\{oW.)Z>ݿrspb=[WPn}b`w<0z{Ru_s^˴ߚ8@!t'l`<""Y>~)kNQwj줈gYa1ZDE|ac-{2 |/~Ťri VDOkTW'.jQEuYI7ۢLLIH]7[( 퀔*L6LI`( (搂HH3DBQ Ps"8,*a8dlNUW" FO1rvrqe՝`ctW #7o|XE -S_2oarykS)D;hJGO\g {/bS vwgn4X@-z~o`zȓavԾ@ 8~ЏwNy٫@'^6J+üq'(LM3X) 4 -d_Rq#nDXizH?'xfR෬%}RDCOzG#2}ɿ?!Oˮ7˂(~,AQIǐr*ZŋHqL 4q:x3JKȖACJ#2Q $e>m^؉1XP =aNmقtfS |(d/\DEzdv9GEX}*ϴ@/p~E&$CV 7l1;6*"`bcAszz IYs{X :88+lpN=vgc0/O 7_5p}͇G"(HȮU2%̣_L22gMEsBi1'2EnE#[%Kqz4bL -eؒ~!- ق,_t_l.P m5o8d9ǀ5bx?׌TnBdVjѯrXT3cH"`J" Հru :+d~2]tέʒ'!%g%y$YCdz>Q/!'^AcY;2{ "U^cV y"9g-wl{a׫B:zK۹=5y8:CZY ʈHw0I&~=pt8d2pYyצ2̢s 9y䶊3'1}Up",ہ><$`K5NX{.]6BuDn< 1 4U om[\뙚$_WR@$8>eJD]1ݷCLqh5d$cCrp6Il-;qBjLpx㴉/6ЮQVcf+LZ_}ZGϺ19XGfۙpi}0 &qgؕE/"г=".Șh-!aIɪE??2R&Puc+"agtٹ@MM)i$",WT7' RI]YFI*wTR6;GDsˍ".ȩgT`}`kD`@WvsѮ~k_ C&{&)iۖ.tCns=O>K3KrbXD9j.~nHq Fh䜍F3CTHۧ"Bs ֺ%e ʼnPGmdQ.pf~zup8RL_re{Ɇ7:5 nMdC&2iȈ=lG5oFx.TS"-hiP&Ҽ"ÀMх!EiAhGqD=޹)tf8r՘3f 0d3(m!r+M{κ[ՄIg/0(l/?69 s IoǶ®% ˇ4u?xq(žng2·ʭ&WIbeH9=BϚ.;tV!qv6ٲro=cGkhb#".1 Tω!CӐZtdGg6G"K߼EC[AXI._HC هH$Y*=:R& `Ky(S5PF#} |*Mzh /Rx0s5?g>7$0fAgW[(w~R@aFjv$/z1ʘO1͟Ӌ 1Xz'` X$osg4?Lu1gP ߁B5nwT\qmǩ"aͥOA3B5dkorRUuhm_Nwڳ|mVlv7rt"';d~/$UD#mtw _'#oL+8F-K.Z^ :7fFc7qJ+[}BdՌiUr(vLHo{- U3b3F hg4ԼsV'F]8y8g"fVAzEKezO;Ѣ=Ҏ 4rcSe? mwT)^8im+^K1\8281yۃ`'06>Mao{1ޕ#&[">]mnѮ\ &t$eh0nԚ!64CeD&TfRK+# "rR}Dо* @񑾺{5/O bNG:U4}z:: k eT iQ0VY $zCzY#g #Vj8}+X5{#"B@=ji0*>+AdoKZh0J&?@E?|za겈c:şfp/c;7LpU;f+xQ|Z{Oy?l̶/oRS@E/wK׹DK$Yٴ[*[>M@^IPqdb z{wq.1$Dh&Ѹh${@ɪ"aӼ0L!L變+a1dA>(>#(~," ~?aY]$ 0Lx9~T'of`F_>N:NU:^rw/;S7YY|oqm;&T?/Й)feܑK~U:&t_ɱՅ-݇:xKk?K6srd]C5wXqiMC{MNSǿѱO/TҊC'|\-Ch_$[gf;-,>얋V\>{ɛמ7w,d{gtM.U/j钥薱Q$:))/{YlCf1HOUw9d\ֽ6K/ ] Oއya9~_5rw{mvRvU9cl3yOGǍ0l `ggceb,`sJYâp[ӓ7OՇN'#"gmNq\TWCDYD{1qwaQ(~րKpmwt#|DcCuxZ#Km'"U+nƯ2)Һx0cG'\w6 {o+>uHG^&? >"JB[s&Gt-I&*?_7ÌZء5!];n)R нYy7v?6<󾛦*=i ) /NffJw瑶nm-Yj7F SYKk=̾:m?6yelIgJwꚶ,o=05R:ձjahL 0{9"k?Gircj)d9Y,dt*yT vcSɺUA~ s_p1`|lRenI4Z^"d82,6mi7e '!,sajn}0{D5kUڱr{M:2b7sBE7?dyc)çH. i_cfzsOJU)Chjt%T% i$-JMdnm \߯G^kU^NyƃDRG e*4sH:(u3M)*; P\Ƞv7nYno.?MZ?;1ޕiX+>ϖWtFs@2w 235!EQ48{`X]k'[Ι4x,勒e7r|uĔ"gu@;ydd/xv>\fX]ʫ'߶r v۷M8dm:ӫpɎҗ/^!5rc^Ձ?t :|u]EҾ dT,/a)o w@dر@;|fy , @ ""mBt7'DuvʷM|Z_D Ūh|DtkY ;)HK}v4!Cë6b 7>ŞqVm>4̺1ex>\2jF5dYftļoLbF[hp3/R meٿ?0kf}9K_?b誠#m|f߶s6o<}F- dJ=ַbZwk颱5 6Dpvu62!YO:zȪ8ӥkO[NWO3 Rn[{IgGc Ǟ~_/pn-N`,*#mk/ml|`Dlz${tx0HbfS[?۳EW]eTh>s7gIw/b PU=ر+.xJ!=u_\]8PƗ%MҧK ֧n猥ӍR%^:1@CGiv T䞄W`zR,y`Ʒ< 5A'xsA^vpOe-(F1/lz/1[DAxGaG p(EPo8+ [H6]g@)\U|'>j3+Ö'ZiwA*b1MDdot w8 !qmzl 4"cئb)>((?!s)@np13A:)#!L22(eh({нeoDDX=#ʲ,amJYeY&@;?Yu{t'ߵctNLtͿrr
ՉҔ=pZ|u6S辣}So|.~{W+ [un { ]򣋟 ʽ BGfY@&"v}́5 t(>EB-S0`/~^  ɞ/ݽ1{fKm@*˜y--?lMm5 J߾b֚xtavC;Xҿ=lC]wv\~+L5ڀAǑ#w|z GULtHkSB}ιҕY8DEk>Ks_Z6Han$Zx]IIvq-7!Ru+e+M>)K?xE:8Q#w|z8f IDATGU娫uA8dH5X? ٖk.X'<{W|cknn%OXݔtbP+}s/[;FRm7+鷝cGtC]oOo<ژ>RkH'ʷ~mS ?:ڏ*r^߹N|=^#9Pק@tDH2a Iw\T]tĿ?uDK>|%o7;SYCm@z3K[|mًws3J7 F>t9_OVI?})ڳz.]zڡw΍ͽξ3WL3I:bV'/ݰs%sD.ľ{8Mcr(N>sRo{c4r!3: <]: l%.R>.C9B3~MZ`<ǁGo.ۦI>* yG* R͖M@`plK}8ļ8K<zj["jo}dI[K 􃠎A1=XdEH8&'C@D%˘ϏeqnDhu*'UE^_?`PBYt el׶Mo#4ʑ/xK`A8+!F,}G>6xݖww1s@&p0b>mAŔ+久cY3̺3E1rH )aIC{ۣ , 8s.2O"c 2}wW :3?~ ?Go~tvG'lE+Y<y_VKs_6݅jmha@y}a{=8`?|5H4\; /3˷y/aW6vޱ\; $i֣/v>̮BKO٧Uuhdn !*!!vF4puSb[a+MUOmHki&v9iWݐ9Eb?>##f<;=leBWl )v+ 2ע7(QWVA(@HAuWR ; &/7*eFu#@D0}T䘊@.});vs;]@(@%!D^/}7˛HBwyk<'.G-_rH){2cPED3,xn~`XcN9AzxqgDsp#()"ȢH_MR O~o,{{0ookss]˖6J7:c=Ln8A'u׊Uĝ}K2q,+?rcQ ϟ#{_F|CGx˅+O4 9#i/ؽU.-ƏʩG̿g~^Aa`=W]ғ0ɉF"[^AL%cA޶{SV+ I-Q{T>pڪcK@K8'|sΞ[V}\=>]x^@P`% n++o8I!yVsP0o~m3/"g3lԮANʊ_|`>xSxU V#w(-/9ljGtW^L!gP-}^ԀP*4RFI][093~p5SOSdEvS/k{/s*̊FspюyJBBD,D oJyc̘mB:wlc`?/UXk`ACu>,x#U09t8BA}%H=\ gH-D䭃6SoZ FJR-^ovSD(JG@ӂB׉\:GE\F[ɬvD,:ČL3YoS8 ݁ƇMq.39!;,,*gC̰,*G=4!Dx ?13!xe1C; y}kb(ͭ^{L?tYs`+3>ok mי3NyUk+/%KVN{O(nɹ|n{&'~K\q_Sz, <~[&_{KL}W9Xz{fi Kq")t=s&߸W&x z._会pW|Թ F[K-r$N\} Yir,<`8)f14k]r-&KrOOX8OC/s/ٳ%&[O=}'cٳmATxU:t6RѲձf&fo:E=d~QOZ#B$2/)JoJMIo@;,ln_;qߔZHϣ"Wӗ6nx i>$Īnloxߦ?9aL6"eIU$Ʈl=rbeiM-\?wLѾK]9N+pEoHE!tĔyVc#W `n?j1g%7po$)UDRv<6 ܬps.t6֢a+p#Nǔ0E6rfٴ {/S3FbmE?nEvݠPٽ]#PT)u0NtXqlߴV^3mqNqIZe @*L2HBH.cB#FDD)g.hR`y)y}l52Pbc=b_Ӕ_kz]-9k 4gQPuK@Իl[%Zhh}>X ۥs'QTO=y+u3]Ӂ9ٛiGߌn݇Wxd0Ow]oݱͷfi;Eov{!Vz,AsgK:N?`[w65d[D%/iX=}㙕ys)}eǎ|ɟJLԶT?/Й)fe#˗0+N1 }r쀻_}aKǿukچÏi?M6Ɵ [j:lb kBYE]}c?t+_g];.~@`O>w[z_17D*e+׋V]O/ysG`*`?kY\u7YAѩ.:vdSO ^0Fz]aEEgMu}maSe(i^y{hCk~%7V &;Ӯ,kIg>=ZjU4P*X~f?19G07#Hts+zk쭇"G[Sh]$P5G%6L}տ9)v8BRBԤ@X֫9VW3%ya2U3)3h)M:c-yW&{Pe--ث R?8 (r4y#Bk;@TT{2a}+5vkdSc#yݞ%XҖׯ'$@-^AoL2V&.Ls_,2H`LJwa=3^e#}LT4!&Qg$1HKMj2x-Vyϋ$CM1 +(r $k;vcd[vYgGMT~ֿn^ w}']{k.~3ݲ UvܹtHwORϻ䁟4UyLS4ZFձCLD驑Oo0Ojnht* TFUi7tqKԦҜPͧi#tCy▷8T+m3TyƵsXlYv!t7 g/Y1Xvm (0pGc3fVLsq TJ!R}s%Z.ƐrvLykRn cxf*4ME"6S?8k#i6zMaK) 0 >QU?iF@٦ ^li]4XjT,?"꺨 Z!B @-N9k$ysΰ>? Pu>946O.ɦ= Qm,<q'î"b{˵4w'I"ݽ:]$I5y VHV [$II®,(H( , Q/bOuwd_.̭ E1)DPg 9 A)&@aƜ+jj(!"9Rw5? hiś\+wB#ž3n _ʫ'߶:<кe'NܹBWw\y~uO$]e3k]E}F/xAUDKfXj[q544k}C _>~[f$|I/L\{_{zA$*b\ˮyJ;+7w`ӽ-5T {dmKo.CM<{E-^ g\% eI=㟿vr˿wzJ;n[zV Pg9;[7T}=> Ԗ$9]j7L\95yHk5"L? T=`V L@H9ɨD5HaRc-Uۃ5bbxzOb/)14;6翐Q,Q_˅r;9+PQsB7%`ĽC@\`4rbX#ETKdw%'̫U: PCA·?w 4ǞSAsh*n7ɫ$tT(9=Wf!hJgwgQP _`Sqs+Po"!mm`NP4eYDM ֮ۡ5e)dDmXVD'{ {FD)}Bjf!meS 3<22wU~DJlI o!̛ҹOG#U(nܹypQDχeWrt!Ś^{ƹˮszp<@ ̝yJo-+>~KgE,/}T׆uS;}R~ IDATWGڮk;m˥lxߍ$s[J H=ַbZwk颱5 D⋅le,)tjDd=`&NGOvY{=?|A*mk/mlWcǮpS~9sSڲr17dfS[?ط-cdfs[Os $R+%,ez86]>F5$Ab29QԆ[tu^w}Ͳ֒l=K)dGLvY(Ed]/9#$׌ Nk PY03T-4*{Qr@=6b@3!q*1[[[%g\o?84Gtʥ`O LS$8  yN`vn:xz_nj{d2 5薝 1R-[ #Xc9w NoAF\#lj!+UhCMbkQP{9ϐyE])R7ȑ}B=TW{رSHaޱM(9\[442sKf[Q7%L\Ds5[Rܤyd+ݍ+(#R 2U ,uGs\e B,dḠ96%Sws{#~L&xQ '$*64NjGn4]ei@`F x6B7SHH*]<H Gjm ÁQWa>U'Ig}{]`]>vKg )g޹+rso4\egRzءZkNZ`w|/إ6_ojcCwma"[~tq_ܙ?`[Ow@OX v܁虻+O+@liڗVf~~Z~GunzϴzԞIǯC77VrP l3-&0,(ΉcpCS3[U4ha>O2~Խ^lLmpr~:R)W٦^%`W}4]y߃-%h58$lNdB TALH9遦\s.#Xx9Y6i '^^Ha#BwHnL'&8us][0\|~Kc\ACw婟7\=^yy@@!@}ŅIRJJ ܫeО?u ozmF<F7%J\ϋyp᎑ҍf7w'3Pg>ϟ.졫7/:|⤏҉_[v$@uC&N:kLȨ_;ԉ6jΛ.={spiMq^߹NxtZ۞c/yx.QEG)/Ꝯ5Vw}TgWYzg/^ٓ<Ʒ.*לwsC&`>;#K{/,wn\P, PcGjI7 (s'g/tv? ]3/liQ4 >NjKa4y.KϛʣD ]kInۀXW+ WBőMC 8* H&UBֈ {( $ [#s&xJ19%* =hȳY1L{EEk 71 <ʺ;<mB1"wqpa |r}q%_<}0#BCF:UK#ȗJiɜn@X (f蔰EaB4<ʢ3)hF8^FO'W4/v70;]Z/iDA+VS^{mtq!}f$ڑ/8R1܀(dMfz-M9=UŬC^ m$Tr@?h\[mk ;RQkXZfTk !dZG&xC%ҥK>$^[f(t"ɘH]o{yb1cղ3J9eAXM.M'5mРU?GLQ/U*pU.--hEH!NR DghzO{P)KN`=McTrl%4ҡ,\v։yoV,#4[Ve=7~x[-27HMl.aAQ&-tt!%<_,K]*N {M(ۢs^SV5.Vƾ+=ΰm dQA^BRN8( nҏI7j ` vl`6WBvxw/|ŹńY1F|u.0><Z_nD[oQ^}/kA+z@#)g k«OˆrF^X>D V.2bS٣/]ʼ]oM)OTCͿQpʕ6 ~nM2 72FQa]e[Vx0b9E4M#k-5Œ]؜cGa֙ҵ J>3Y Wj6\H#HY;OqSqQvdoД%dyrLF'u9ڝ ~6W}:,^ύ*,Y:ܳb4>n\8E5TLĦ#ki+@J'4+qd,uCk?̠)谰k5'65ԓúPelF0Yً x :B_c$ҫC'ߐH1xgd,+IJ.4w˼a2gC?mpu 0%yY&%v{S X;,#}6G8(ėA>ّWv#ҐRϖ` لc]ӕ|[irڡLn'r{/gYS{TgY1jw1}q8vܱ \C,vo2X(`tz"}.q>-U'^dkkeյЧGRrZӞ{F ."˒!K7_5,ܺ\V݌ڞ=_0-{Ϗ 87,,t!*p:󹙪66*氌}ex}Gr9BZ $ٰ<2Mmm]"![EZKCe#v%yKM픣z][O 5`qƅv;EjX|  bw~'T")YT 7K8%nʰՌx2^u;^_$#$aG0Q L@zr t~!oeۂ|cbD"oʼn7u0  ^H}1Qes҅(h` gc!NH9,( o!\4(Em 2sJǺ#sP"jMMD|YUbʑwX|Ha)C)GW W ] kkc` `{Cl.  T)eۜlC ~\|X;((<[jeHƩ%6?ے_RlAYg/' C6wep{%!`mI`/fڊj3,ŒzX-W1wȴ.j(=jPq3b&JOFeR y70.t9EDfO@g2'6Q(E1`JoF"M%NZ n:\Z`qGJl@s76 )ML OS(HbѸhLʏ Ao<'"e'b'0U2ߣjl l<^ PFh="3ϺD7c\yM:փ}$F'wf*QCls0k(ELh+Nn.X^YHYD@Z$L/iz;QWTt[ɼˈy7S 4 o>4N;R2"$cauԜDB#'ʢ0* F@\i=L֩[>Pku.Zb`w bumnCw5ѝXDLmXVZ`X]Q$N@h 5G}<!㠨%4w)8Zo#n69P<ψ{11Ďt1K٫ \`m߼ KLbb˸LWs` yڔGrZ1Ƒj|NyFX y>>hyV`c۪/`pk+9v_2CDtk|S>~ CQkDNNjE.lD)ȆsHlf(뺾b\g FhXqX*ejdA^U1h"dg1TPuU``ul359+ EϏ#u]~e3p0 . g+Q8Q#YBRXQ`z'“y$" dzCWF#' 2+ zG9ohBNg0:iR{v[ 빗s;mr(גً!ABsUyx b7ǷϏS_2!L9QHϡ R/qEĉ'.N s&´Pq[^ ٱk6|أܐ.% C/䕡%y/YWŲ-Z2VkBQ mR1>Œnqoe~wmqJR/k=z:䂂sL| ս'}FVSpH?Ћ\S6t} /ѨhbYGtFMCF O K#4|h{bEgxFs%FMeBmQ".&n {˅@(#Q@@!4S !JwQ.JR"&B׈]ԥHQA~H! J^Y̧ s5iۜJsՕ''e=+?LVB:(D$yR ?BD6bTKޙ\Z11_\ϒEcK8ʦ-jԼ-'iZ }`5jl5pWh"2Ku֤S`gJɊ0/ [>y[?˖ݲe)k_,D#]TɺK{KT]tL qUYݰFuGYHcft쬈Qx9YWE3 @$,N]nr\!bQ34\ܐdf#ۉ>NXCerap4ot/3~ANr`W*'\cZmٍMT㵠Ʃ lw)F8aSDUN*o^ެŽ oY鵈ao(E&W O :" 0I񻚵oYb* pacU[oǁȿj*+ߥdV=,q: 0'[[=WT۞"I Z 3`, uy ZJJ*4.r~0;&qX3ybe( ,?Z pL6!=@Sc_G\>"$Bޫ[~!l,Zݓ#DFB2̤F$I"_e|'($#i\J-q24ˈ2cǀ 4K Tq5ʓ(|Mӌ x @LUWL,Rxn,9.-b29D6F6#JiD'\oϚa MkR\7: qjrA1w fvFj]7/+h^::;#t?U[{&݁泽 <ی. fExR W(Iu@h#1m#!J^8K.V` "$5 C+8Cb!ANď]vv|ڲՏ↺]Bfgn_޸ i. 7c_ }%j3~Ɨ4x= iEG@]QnkzA_azZ\ cV:, Na QccF0uEbG>:)Ly[WG[|yQkhVsGp?# ̲YE#'QI{tQr$'Ӂl=SnWX0+cԎc?BwĢ98d2T*Φ&ɆAN IDAT D6[|ifs/('=_8]/Y{P #(B:=eNwiy`DWWk3A̦!06Rl-H"ˑ`lwg˛Z9鮉aǫHn{sDx)çbdʭs dJp#c%yо*!A PZ!h bDiɀB!DB2,bIPf"'B"(K@J@D-fP?LB$I$i* 験t|e-vc~CdcA&hg{}SA4F[ѷUɟ#qkd,:&QmXBWY|%#i.깾Z_9FܽPR$MK0B{ywZkbhVrKF덎XL 5oA3WLu"S]_asx`y06v}I:گ.K*#mf~'2'TT72/M Qjw.ʨ)u\.̿Ѽ"0~)^@_\4x} M˰`q8> * FN!_aoN|eٙcQ̮j(@5cѾ͖X@kyZv6c-t?5&YMR;w5z-P;}mְV1U1#(˩yi.d}}:ˍX}an!r#}ۍ(\Dfx}\ֆ` !Pk8).C`ߜm-C-ך@xoGЩ81>'/D!Ddh_X0+z[r=DI@)a^K#6$Hؑ($E!@ &B$IBjU&"$Iluβ !mMOU(@#WP!,# $!2:A M׼9جSDhXeJɩu;IZ4l(tGDQLt}]'x<8kx-fY{Wxl ᫯o l=%uUލI=+9ala1h݈NeNҖO^ [pD#sտLKVڈ[/(l8ji4=Vpk(鶨;‰ mi+>##%GgV> f7UaDCâU0ӆ*61FtzvO$NqnE3BBpdCdјAoO$lbW9wFf!Y-{6A|ZkW ⍧xgP[Oɿ~fKzqt'_# @E>xrzYr{T,A\` dA(2-oFfDe6-DLd@J2D"  ,I"<'A6z$7)I{:: "jH)1I3ZA)eZRdt,lhe&ŜUε5)O!i(FHxyȔTΘUmpg$6#Ul Mp×@[^X}ksp8". -Lbβ4gW%q:M`5-TP8Eنv3bOUze7Ȑ)Dգ}iIy{|4Yаs(F33b6fʙrA*o*B]@FPs muT84^%`65Zsiil#Ʋdl1vb禎<VėA[g̈3ں#Ma#3T0\fք3vs QggfjyYs,C6^jb!FCű A R~ R`MsG|HA[UL^,fĢ z1ws1J"fYQ%CoAaCrYl$r$]ԔD1!/A$@$iV/ZHP(gtH )IV"`JJ¼Py$tnuQgTI@4M \iф.՞J]VO ]l@ #,#  d3˲r`Y@z\:υRoǯWprLb+}~hA+@qo V 8lZؑZp vXH,oK?|Sh&#3$"">nWA:WG˯0a@e)KzTJՋ%,SGL &=KA ksD0., BIPRӲ Ld@YFݩ(4O^u_*G ӷ`~ilaqO7S=HqeS&2R-9O<^ `Kb*ŸT9{rDI%! fJ+S7m(U :ej6K p,.f?%%,< zo"{[jޝ?D$,Q "5Zk 9 .2VWfjC9e+,BovQr7K5vM_ OCj-. HK,baTnK<)TsZbH1Y{Q"obG<ض" d@cX.rcH5/Jn](#EdisHK uK *C&_ _Ղ6Lr=06>McP ]'>nf6=i8_*p1%"nuÚeط8m[2^ 33ΑT!hE[YoyOeܩlVB!oy eU"MStoֲZZ̀03)l2 ,KT7)@ρOPQDa6ٙ0P(2*BM,Ӈ A',# 9+R]sD,J(o@r&d<ܡo:&7uHsE :cˆc4F~7NqrnILr Xiu HOG:qu7`{:$XMn䈓a5SȻZŀjr6ZE80Sx+ct@čfTdJ,e.J5B˕-v*hv3,;]Ge`{p4 8~zJ *}ak~a%pORkժȽ5t)JrǨz6b_t>ͣAo3gI>Iyx`Dj/`dt[|4bZS$:+bBq ĩlyۓ`W Rr+ t i*P-.6@c`Sx $Ces|BNR1fᒉ;lZJGdDiv>HSADh,,KZEC4C$酒/ʲZ*; )WC& T^ ̐UUg,AB^zXR&`!S,';! " 5?n&%׋H6I&t:څ76T#WрE+Ryh+jejv#5r )^e-}5G%X%!gZhT1'"t'&ˏ+0*HZEtlƢ1b~Htq8a?{`IQ}NuߙwfeQ⧢` SQ2OGPI A2( @EAQKͻsu?*WW߹]uT~uZZXuz8Jo6L {jpK # Uttc@(*qJ'}vz %z=aoYdԂP>*jP=) ,uKM9r>wZ/" 5˒n y|*.xtUN(U(G5X>y )gbZL*Ou!+8IŚ+ra5:I"FlaXd c S@| bQ5BUg.?Maz֚;-sw S/(@lD|F? J_dLJ#N9Hև[qq[ -@._($Y;S郰80P+Zm*` r RʵazVu,h5c!c v M`X%œ>TXV~:β̳Fv>e+LGmb<[!NtYo]>[z2L0JQm$FVBap:MjS6*z%6Ա2{~+J`*'X@GXQCr8I\ZGeD^8At]ݤFp՞T^UR%l:Ζ$m3h*uS+2`syrx3d*Q?[nkRȸ iڵQss 6Y acX6jS9 qZ;'7y/Fo8<86?ý4w 5\7\~ma˅>,|$RyXO 9"e'N)LsXCBg 4l<@meENT?Y yQXNBdLϴ6,YFDٍ^4dl22%k]:m~ngRέ ؈m3Y'c1c@*Drk3Hĉy9aRv,B@^dD#C(6pDy;qȐ!"N\.Ԇ@m`fQnvL*PX&11z%]/ZckBF#J'LO z-k=X ;+ r˂W#w5NF[S:@F'}wv3-8H"A$ \o{wDA뮵:"lm:+9}*)d4m 끏T?|sf<&Q.L$),`p*k"` TmtQM]EiUwrITȪۛ:JYr:xH(-n7`eGJI߅e+_>Iٳk=ucF7ѵ/+gBtm-5,Toء5/_%Cʘ+,[iZrP7#3? 7 xUj 8 +xmK3lmO@ 7T7,ɗbQ ӬE5ZVv5j:OnY:ߵKHr얖k69eBz28Fó$lK hV)fJAn2bE,6hMRd䇵ko[,9 mƼA3CnFs] j(12̆ Πyr)WqP>M+n%84㦔BGayVMza|&}Wϔ^ej˰|6WrQZv |ʏSq<dtfrkɫ.B꧖8F@GQ!C j͐,Mb]Qʁ$"ADDi^5a 1&`+ ŒRDEE{!8J9O~DHF-ƾ% 1JTOve}LnD`E%zՖIr~k@3UH yE%e0%MzX?Ճ!*b,RSIV)G5fUqeȥ` =׆lglTK qK+7;6ӽuD}z{/K+e-޳Pwɷf>2M~SW}dQxpe1闏2N鴸0 ifV(<'blL0EPA!X'?qeaպ ZZ 1pO|A㋨X&Hr(ugϮ9f4\}vWHgxxSN{F}(qBDm{o 통ֻzVf #PXzNMe%.LN6jAIN[9a-Z;O߫nnI@H9!1fq"Z_5&i'"E ?V0n}V/MU;SHDls)?W]y$|-?UxN)| ӤS`n0P gG4B,"8W2w0_y}G!;jw$Eկb&wF Y FZD竞c2W*'L(#K.E ?M>azHE*뙛a$#zfΰc3Ujd߷b>͠P nE2:0w:w.+ݯ &qqE8 CdqRxā"X D8R$c\ԩ D, ؾH"jъ} 0N FH #HXbr5E yjMDPqdo > ] scZD30K^32˟J822xCnj:h$ƆD 6Z;44 _"PYqU?\uXɺ֫/݀7^pTLfcTE}6F1mmY,Kʚ9mxĈ~ X( ;ڹm/}/~u6PZa|a(/y]Q sK%4YRfKHwV+&:oE6^cZngNt"At%獚 *yVU}$cnhÆr ?KRzde׭xo=l\(;a=LW-1 IDAT% JӚt_ iTܠv${/O)c;!1&Ie`(clRrNNrUnYJq$$$q<~O'䉹Յ#5kܪ!&j"bb%n_G/Jh!p |  {mo|(j k6!zlul(U% DB)O]ȤӼ AwL/-3!߀0/˨oN-E qĢ8(f 8Xcܔ1=)oZDDGy$S.kex4"&02T\q"& vBH4I$*IGXEbxy%8&[ŦG~9'BAp÷A[/6VZ.2[.DæDW֠?h['y] (Bc:5ȅ0 b SHL' kۓP%UÞFQh3&p0ߔR^͜j5<ޠ)*R3eEӒ޶r?XrOC@ 2^Awz#ֻjW#]zC]=ˏ|_ Aq>?oI^X!uٚ%G@ }`Y<󦪻X%C/s_TPqAi L+۳T0pu,,FmD8S&{2p:4d-sYGItEaT.bx#d8mL="/3+2(SR$1&Sɝg\ʦM`7 ə,tAMq3zc#LGD N Zqč2E SG\aU֗g񅔌Ai Ҡ2z\Y٣*zP3~WAfd[+z3jw9aŇsߪ aQ79NjcfO|MnXWtW?/U?|{ؔT2"xMfo;rNVVV?67u<{wsTeǁzKC^"V76;mu8¼= hP0q gx_XF~zSGέ߹S{\}j "Ҫ+|C8@ԟp՟?wLmMZ/lQ Ďns )K3). EZHj)Nݠ 8;f =IUB1#(P!1 ֢Mhbw*ZvCo+c1 ^i!Yq.5Q̚紒Bw:|H汙dFpQ̡ is3e y̠k@dm2vU9L8TuBؗ- C/$egF>Y]iE~]v2sSJd}`KH"=CvqUZf_`Gݚ^F~h<^SUyɕ׌;ewꏍ&Hq@$¬? `!"q.P EL((c3;4^s.1#XQ4c -ex @ (%KcLl^dLTӾ31P09Иp?NN-Љb*3?4? NȲ12/B+5MNv)@xb$@/z%){ʠ8LQ nTzèZ$#I"9xCu9rŹ6ރY\4Dg_Wxii?(n6/^uf<82)p8Ҵrq!r`c_GOfdhM7_cq>}[UVHg+␹8eX QSAiΠ&V&3oO2,Zniye ټL>esJ9q@@,bBuUUuuuP(8@G9(V)b,8u.!bLA "4MJIi&)!bzdqT(qGp(o~c gc!HXvb@ "Cɉ ba0X!bUq!aLlD`@ !B,DLc_}e1qV!|Gj)i,ooqY v 06 \ `}PZz@AqľM D&E)e9iD6AizdHznZ|ǯro(gz:ȪV@V[wwkjx(s椺q4'r-+{)p ySoaWwPW6d]ukNP;Hֿ YF1X,',x:T"Eu%eC֎tF=5-<ݺxMmY G8T)l+p #4!-Bi>mJ3bHRĒS^J%= MDéڱVTy⫛5LZ~r91ST9hre3-M 3ϤSЮfLjlBy<۵$lD 0r\g*;2Yvpei~.""n$ah)3SI"D\'DcD1KêÐ!04M1F\ŅIF$vqycL ʎul PlQQC퍢'0q:" -%BL1e@e8""2✈j(##oQCɇl3V ܐQ\uSsI'XRx>w <$>["dNOM'eU[gP@sJ%tzRWu'-Eד(i(`ԑ5M6\pIGHJq D}CKz -5?oQU忭L'NX S$?pl: 1[iX7n)O1އf^v\"i~J efE[&u+AdmmFAFg WO;wXbDwpִEOa^@k҆:&kd/:ggڞF:>幒DQLEh6Hi{IeQ[ ThIϲ>&#mH++% J9FhVj(f-KzE1I(l܀cAX`Lc<d&& ܑE*]Լnsɧ֘1_\ 0pM @Uh>DRZ "z?9i_m h]s'{s9 ,p(ꃦ]j+ݝ FV\)պ-st[2򭂩fFåT4o=a^^d :-/gRb*d[+MuX;Nt]঺n:'Tmhy՚Mcj #YԑDb7~N<)CK/6U!>\J J* ،n'W|vh$&Dȉ@Mclcj!y앳ibP,co B_v+}"3ͮNLbS>[\ͽAϻTby*`jX}+Uru#vFiRbbɔ_tz3u3wݢTlP /6jgÓؑ{.HX=&M&KũǪoh/͚[x٣UicfBim7US:P S@7o|lVCiv^q_}:zGn[ӦIގ2?ijկ-WVj eVUۖZ-Y غj{ȼi}C2wnZ|ЛbbF}2{^R\bjHj~1*)GT"++Lf4'E:o 鼹i:F]SulZKJv{L^DK^IZa`I}őnv֒lT-ua:o cmi豵f7½p,4(9^kEKHpMF;I1J/0T3Z a aM\DuGկ2C!$X - 1wjS󮀚~ŭb3OfƦJoh1i(WbMDAO^i:R<:.X'Г!TYeP'#kM;rV4^DQXWyS$k;B`y~-Ԯ1M ou F31\S89GӢ Yr [Y@82uU)&=C,jsks3ikBrb,9Y$y *P 'D&uNdor@Ĉ1P/YFX!bw8@$›qnl '4eEQH2Q@s% Q/dEAfs=$bLھU :Yx@fKY2H0i0*keFxgGP9?10Ips(沔`?r/k\Ɠq Jr@|Ni\ 2g 0ퟠRZxdRVWtnBG'N)Wق_v+i''*411111Q*Mww)&:쨭lzsox}J]h!{viu4gRm ߌ[p R^(d]!*aS{-5NNdwNrbYH̠rXw^3؇b2ٟVeM~ Xwz״q+KAR=!@u!f$PǓ py|-ލҁ(J 4^_k% S8b'K)uT|:)DׅhgɯNHh\ن@sVxH Tyݨ9 4*%d봑o T(?3[m_Ӗ@)nkl\ǠSՉ! 6;Ya[Qp{ T3*.l4ySi|&6sREe|` OwaAYѵ[԰;Bk8y¤AW sR|ІEH8OIš1bAAW'RԈ1n /2qqd_z?i:Si싾U;#)gwr2)DZe>ǰHs@C] pF[ТdĵtP%+f?ٷhV!^fB Òz!&FKfr}Zn.d&mB4@:I0ŏ[Xq{ ݒ|7$JMFe )~ʘF7^^`N?Iq}Fd-9.]Jkc*)CUxB/P4M{*+TVtzgID j1FF^ twK,hCU9ԏL|ЛF3-xȂ,X^ ]hHi%\U"M,~ , $,4NȀ!FQAj+D| jJ B6q 1DtTr0q q@ }eq[9&ijh2QN؏M3Gk!x4`@+*^14<%v HMՍτrʨzUϢll>oM]d #}ڹAE #q4ZQdgPQĢHfQ Hgc+4ɞu0,EO\SBDZ8-͛ȦtHHIPq컗{GNlgZ$==Cѯ:kǪ޿݁KP+iHٯu? Ҟ u}U[^]z2hԍ%7Y4՜6yԐ~'ˢWyuMaWd&c@@,n^~3;rֲs׿r9TS4k/*mkB°PjDtz7TJr6)B}{Lc(5)6UҾPHR=tϾ!H,[ s SVdV%wƱIA@|7. ^/?!@D듼 7ͨxTA"W~66zʍԋd'XW41UA_q-״F MvugT2Lr`[*%oj(s+^LuYh1b{Z8$pUXX3ʈd W&qD&ywLX_2 ]$]І6adosJcL4Z1 >C 4E̘:9Kc$"F?g:Ra?['L\qܧSepn5H,G>0{_t4|.G67qC'x"'rIuһ=8%R! mځ%v{^$ >{v|+7g#B) )$@uRƨ,X4ͺ돃]9ck5h96v6~tBXOyuVGSI0~Efɠ puNȋ>@)5&EFP00bD9`YOiK):u"*{ʎT-"nטUPA.+Jy%;B12n*,x2"D#gf !5`` ,pi2miS>@#SE6=SGmVeŔoré& APiB]aLxmDy~>r Ds=]9l&?}#Ԧ;1߳&`:CVBjlH ![Ih@xr+rAL9mU(;á_:* "%eι &L7Kbθ8֙xϏou0U9(%B#NM+J!JS %P\4z]qB I@TE`=BkQ)c"qZ>w.m' #RS]q XR|s$h$ɳź"ܩm|/+,A5bVDj=t\OJ>ˡ:OMoBھo3 kQhM&׸4A(a/2, YPc=Res^&>Psy6wמpB $ngc=y 'D+w$)A-*>"ɺg0g sDeHm.ϡYfA]*):LjڪOkz̓>U RQ͚`Uoؾ\S5.׍j 3VbI2VPNN qc ġ>H!g..@Cq"T1Nb !tc{s:KCX]n@j*p̜oט%$hɈ@7ъ;~/+Y _$e$%)ьnP65 56`wh<ze(i460@:u55q`N|&L7[f ӛ4EE >>Z뛪LJR}'#xSX;ETzmuqgWώh Y?Y9]ڱ>O@+-mYGvbUtל?(8k15T,^_7Zr\~fW>`q zo  Y"/3όEٚ%G@ᴣa~Cg 4Ə| TM|]m^j`0iҘ#vj}QS 콸s T] /m?6M@Nika[xWt Xͯ@TU+z 1l}G%DS a/q]=FON^vBn@ou?l4$C_ֹzP?fZ~QgdG\ƙs~э;`ͩ]?,0,puۅOT'5 O?K[}m>VUC׼XSQ+4ٺ3{`UӞ_igp7~~:N9o03(~~SU @[9sS\ ?9Nաt椖ws694͋ΛdOӏix1f>9sq]={T5qW W}JYhkviW/i8׎\y_',d.̂Gq:la%esy]ugR}?־tkbc&1_l3@9\W^Dwӆ% $,y |COP*_gb}?@t{b}жQ푧485 |`\iA:);{\;[=^nRdž8Q!95'8n,H{s֑]YQozi 48P7z=Uݱ'w?sJ^󓓻>qm6_4l;.\߃_\sƞo3vo_򩦵ԶWs ^{{}uߛ9u(msI7cߪ]wImA_xۃ{_PWn=?e՜5W׽}.+'v>{꼼9Gps}5r&+^g c_r? ?y-"hbxרS_h~ikk/g/6η4W`:`ݥ}P3~mi;Һ~~pfkS[WһX9yԲȮQNk~i,+@lDȐ'rd9$)NDvq<ʋ98rdOˆeٱMm~[BG FVF-L^z MAlZ0|S~#6Vī֯jz1 |8ܣݣ8ѷ>Zpgnvcoixu3n{> yR$ 8$!Cg_Ym;N;V4Vm9X__eOVwQCQ7s[[B~{#dh#nXꐔc^d=]QG'oW8yVo9x_վ4˟:pH(Ud|5 Ѫ?w޸x͵#WGEJ%ZIˤjAko1G Por{7"uG E; ϯ`xn,fM{wţV3ng> / p;;lXEz{-Iz-(H);J8~:.oPZs- K1-rwcͷr7 GUxhuF\Rs; Ϡ7:@{{u[}(ϛ^Ǹjʔ [ !`W}U;m-K!nzpZ9T(qιnPs;55czin儳›c,,FH)~BfN#jXMw$DzˇzZ9 (g"M#U/ e@u9/.lxeH)˿;jETߖ6ӗu咴-$8-%A-o/0t U1oInD[nlH*-Q&@4G-7Y+̼ 跜14 d{yiU3+yX qm|n_T5ϖOв lJ,ik'0q4))x!C ˑe:nш"Z  o<1@k IDATdo1/CN@YcêԴN@bkhmY,ցT`A+AJaJe UePyޞc!ȡW2L7= \T- dh iACV´Eju@yuf8jcX@ON[}P|K{sZ͖TZ xb>tO_>'Jso=W#H$@qtzz'O&SBPꮹyWՕ>?ѱtG $JccR1lӴB_ tmp)`ȅ;YTeA4F:JZjl G6[,/Oe\J|TpN,iJ#Z"IuƳ謾W'}7zVlttRsQ"ڕ'iGjЈ|/ZZKIf_WA]~kc5ݨ810v6r܉hgá=_4Wq 7j)UqX*Z>8QCtf=WruP-sRR9tМ'i.氪)J-L{W#y:vtj!p壦TePW ns҆-rX%j#4O?U];odޤZix%HTlaNT@Y\wJZ[cp Js$.ܫݸWRP1=-%2SjfEԪ @xx#FisZy xsʷ~KZok CL W߰DdʪVScP7ؼ6|عG oFsx|0^:eR,=NْkjxnVڒlyR/{-e5hfa)0λ_yh5K^NZ 4uܳ[Y3hfŵI*qhO8ZdDY 4 ^ 3p ywIaq15'#&b  Q1#pyJfz#f[n?bQ6՝P8H@@\ "6Yئ-88վADdI2&2|'!H+ 0 3 p3 &`Qy+)Dd$U÷0G ='N$_f$1<ҮzCd<\)7ghp٩.gVNoDQ]-ZU˟=7T[zt[>͛uu_yVemYni㗺nn/T]y.>odW^ʀV𼹗ʷRݟD 놙 "Q͙<qԅC KWce{gS0wCiy7J`)D c/5\׿UW˔|ggvTוY-_;}zb7~~ShmRJR4tEu<{;%I'!Aq@DuauX\YU$@DVEk}Qa\"̨It}}{?j;U[;h!ZNmթ9YZ j2 ՝sat^nňXP縇pѧ 2̏tSc\wp5ξt 0=꤂h_A ohNo/ݸbկrCJu\c8'E+^]㬥e33l3$+ۚI&^neW>Z ml8ǯӣQߚyՒMN=aeD4P{ų<:w+^.`Zy537MOl>!;o34\!ckY3Fju|b4A:'vC?+oa>-e!4C/;fL#n뤞{`鬒bk Wf=k7N%ߵ{rwPY +\$漢U>h^Jk$aҫGI +ֱ{TT^'Q )d,w93JlF[Er3 fҚj)dU{XId_*JfA'RG`̥<5ˆ"tK<[þB'u! X r|wmp: Xk:bXAN !Z.]`$BT0P{O"`McS ?\*ӴJa&&ux_$;_>ۧ^ĶSGkD5У?Yz :tLJa'sp%3B`Z6 Ӧȋ@H1.;m4$1FFEEb|um(x׹;\o7exH $p 9'+ MKriTBz睓\mg "VȺ\0 \Zv v,;Y ­NxhYZ8 dٙM^&!uN֛l-eԗ4b,@"CH:p"}{d;"K6;2-Ct|iaoN1~=W9YnU5q6wO. V&s/@g*mK76߼qVXknd_ +\]@ >U#+kJ7ۚf:~Nr8bmppJ`EOJL?^W0LamtfwGQ4'xrH|$dJתMPfrLfUmDVZ8KU,P`SbQKg_r֒- 8\* b(nnqwt_6[sՍP1q6Jbw8+(8DS"bGDqc*a^U< xV_c#q6P+l(!86ZYSS= 6L60獮Xge\5!xVR} VHY9wSO0b룡}[,#]['d62(oٷ-j8h̅xl;3C%敦b^7]$),3;gԯVF_a$#WLE_W췤~ǧ^+vaUf@mq G5c#*4hIPa_:bfɱ8*A[knF.-[ӰͽShDƣ%_&nI]ap+r̗'k #lJw7w?ueDX656?Е1sK䨜20Z@,ertg$$\PRb]ɠns̶>'-"z8C0.L,gB Ӓ1 wVW"%9I֋U@+rJuIoJ#"R 1-ScF QN`K7QN,iړ(D@"ɥg HUyVsu.;DFM\4!*q{)T# CcG1Q+# XEL'm颵bN9 R%l/DۋO1_ʐUjlNE3r0QPD@0Wd^"NS#ẀZ $RJЕ݉&ϏD$mtF['ewؾF#_wyD^>xYY?I=oZ[׵=ҍyDgqɉ3_xA#!q .\΃VF _z厑 ׭I;+Ccϵ3@'b耓.S{x$nBt:Rѡ+6|9z& vrJ'"1B krWgE0k2DƟkGM0瑹@/|MAu]<1[t檎Hy2gh<y;O]?scT>B%^U!uiUT]KT)kJ2is)H\;M oiȩ4[qkcڨuí5Gph3,T*\s?M P>m55)6޹!d]iXND$Vģ b7@$%!%JrD!1a@)WDPS6$szeEoK'?EoP8yr""`Dj.>w!8&XiG"\5k%q{ʌ_yIDMvLZ\jőVZ(eihJ8 7,Mft0GVшB-WuD x'\5DTud>/Y 1OFLDD6R(ư~Ʋz0*`-mGŻ阏 >~}{VdNyGrAk4=FlBȄɱ1UulbJ*Aa!b(./L@1HBUAEkx @~mPXO`>0^l=}ˏ{O{ k}MCuۍ!;ξO5ùC?k'a {q ~:уCjiOf)WR;2`ԯ[8,Y:jG)'( @#psM'/o}qy7wavW b@毬;ZՅt&9Oi_ mo IDAT7rq=z{//f[E*)T6'Q,{@ZVC6A-G*E)TD (4;EN#@KNl]?F{uW0i bl?j 4\?٢-ʁ[Ϙ?tөڞ'g,9u8u[5v_eB!4FY(X˟8jEl=|{>ںOC7/9K1PT'_8牚O\8}LmώsQe mck{οvq7֓z=y964t#ڦX@i2̏iGg f4-448lYm%rR_NIJsx+UDۛ.5^v]G29 BuMDCGimïh?|iCXw/r#cNm_?F:.)OҪ4s=إ:_ û6wz/%$(98V%YmKpNiop퇧i՘lfbu=UaE%h% ز  a4I (l@+%5̼̓Zg#d:`W﮹KIt ̥2(1dly&.E2HvR 9]`bjLI_ ?e }8ZDhlWr+=Ǻ,F)RfSګPU=7-JL CuT@ā@p@?8T!%A󲊤h,8Aȸa!3X3UlT@<XH`0o18[&^Ѫ?q}@e 8Tk AՑBdRӕhj3)"F,(w7X,Y9J887h[4ųDB2QaܽKE!(b1JXhїZziq#֬8hE o[KŽ ҈07۽elfe]w/?}x>'G> }{‘̣R_PGܫe8}ncw(\>;`vZ-f淎|(?gpd= 懇3_0/z]\]Ds'f( #ds+|Q P_ f=vE[if^1'RKDGZEy6}ȼ5ߛtdWyRonrQ̦݆?/ٞƞ`c=D2!0?>0SHxP^*o-Y#^mJrAm$xMoˣr5i^))mRJAɗ^҂q5@a`SfR!NP,ƣ|UXHjʵ8*XeZ' ="HR5~RZ|l,T/1^2٢eiDt̄\-OM?Ru,U%:*/#P*@ 9oBD&8NFi<$83r+ԓ fCf(@X:^uaJ@3XiyAizV(ə?t'Pm,\Z01@9KfKeJ ,P^CB"| ~T$%1e5@!(X1ucoQ 1QBBPE+ۨkxd̸_7k~mj\4*dsqg(w}7_ : #wLS#/+!7OS0 T KUqſ-P:;L톂/WwPG4MM+{FsMW~Gk0Ʃy(q |ZLH" [ 3Gk^L)*b<5fʒxv!SC%jUg7N<+jh7O7w)dnZ1容칦ASGu;Ft?7ť8L/d> yW!MņQn[ DZ9 "3 2:qSZ4qQ!.g}GLVp^UƩ K,MI.irVJ!yVfl }4+QAb,Rs+ޥJɃHcHuG2 cr2.ƨ4MLokr~XuDToݭI3v5.ɛ-W5_ ֎PHD+&ÉB'!K&j#LDdPhJ:I,AO<$9ВA4Qn̲}'-8F8:*;9ABT~p#rCR`G&Qrk]?WOE#zjMN++2&@Rp\C!D?; U@R!GK q K>[("̅Z"$@<&[OPybPcP,("iEĀ6ZSm.ꮿr ֽrYƓ:ͅcG~y_P9 }k=wW.z"ANѰ/, P.!V<HmbsF.?j+:<-(NVH!WwsXû/;g aNr**d 9×-s~0ob B#Ջ`NDoZZ}ZV4mB@ ,@t\l 5vpO8|i LX_J8m_/.^s~r%BL\Q/jYPkdh‰$AH5O6~W?OQ41ylSO >R kJˎgAQVH&wѷ͊jjd7uuL֘`Wꧯd={G4o77Bamݛ _;)wN3oʗm_~}n!{3C0{X1|w%!\kxqG(`OI2z郝pỶ2{Ś, ?PşsN^ug#clWu:&z>s O4~u;o}-`,~%j> b(fm1xEC_h]ޡEWĉz۬i=$I noSP̳zϿ=Q!OCP]3i蚮JQN ,ΞT$ia*kUjad԰(Xz[mouf"nDKWQ.Vm7ԓs(0S(eT9*rwIlW#3LcL@fC7 2jDNO?M#Y݉LݳHv&*I.X-r%[i&)f*#1NsP)3d$,;a*,J6IוNYtRjV*̃N 2:NZk[➎f lQ19"y&GG/o ܋?nJu^BH&&kD JCrʹԁv;Z:Tf$LRmوn|x|- [Zbp൦|d0zrKNă59!$;wŬ~@w癙/m.rӣ.^}H7/wTn4A:Aoj<ǯ BJ5ձ#|ꞶO7` }c G2+ug^6W}]a#]l_WrE66u%'nc`r?r#5ם7Mў=Ă`?4P566~쌈>|Fњo?2^{5C57.jSjC;͡ϣXshϽkwsz ןWgh'lL!xv򎳖q`OV F-мxgyC3(T]L4_.s/YsH7Ђ?)Xw=iüZ`f7 ^#zݢm/֝cn?Gu6sC9/K{򎎇+.?Rwb:9wϵ9}1AO:>֖2|`5)]Iq< ĵ#~I[^\r^ZX򩍼 ӳNFVnYC^Vz-Ow**otqZ#b/fD%:X@g%F!*[^BIV`RۉSs9$Pc^~sVZ/Ѵt8ALҟRtďhJǰD竰P]iU,VdJ˖2gz ¸:SpG}!*=|8ā$Axp0, 1tRɚ!vg#_FE]^s~2 3 Ҏ7PPK YBPS fZ3#8p!ao(/RuPkR18 {W?߁i͸tTTT( |> \׆B!w6zHmxc:J{7҅TaŗWO푭$d*/!?-*,ÉLs׼={ȲW}xH<Ӓ?[ql(Y4]DL|{dYf3$70[g]Ai3 ~ojl:mcW^{{&y4A~(!1[Lˏz8щ-VT2iD1J]L:z 3҈AKD-V,Aa|S΅0J) UGP}IJEWSrվ%(öR'@Pu%_KPU`y>&TYܔ&m&1}YK>X, V(Dqsˌ{렃}ٚ+9019]ѓƧJ|n>-hKBI=n`VmҰr\t hW&:54I9 *I$ SS>Zz'O3l4땈b`%n6Fo(%%^)"EO8se{oMu<:2@7gm!ST_MGl`_)p3_=[kg@kV*?z%1C3la_K3ɟuϴ!MB b> \H$)aoP LB_jGvd SNNP="UZU$kDDZpmFTV&t6g#3 5hCYaΩ_?>AK.;O0xL)2yIˬfC4+gO|M֖R;zx Zy?w ݘk53!dP{%&6CJU/=_4 o+'@MyeON6m~I+"X㠽h&CCs ]?fdDωΓ4~ڤNfr%] {FՑ?-XN,@bSPje$GY <6 ^N15N 9D9Kcb8@Ԛ2/hIP@ TgLq IDAT: R -ȋ)N EFhz^fpfr~Jg\smMo28rVU!h(B,Q$Kšo^9X//9aДBG+JlLpśoCR*D(o@C o|"dzr!y]XTYr^CH+2ҋ9΅qw9F%mO ǵC*&mEl}S<>_O$ٚh칶[Un#z>KN2 q StEtVz`W}N2W25.NP0e0\{ٶO>jD*Jκcd#Yԃ5c~*-1k})Uov1f0cU@&]<@8m0@İ8_6w7lW D4jZS檚t,!z*i 'Iƭ~$-$i޻VH ?Գ;8Vj߳g|c@v#g~!wN諽뻳/S ʮ`.-rw!D}w4'Ŕ+gkBS0TwWj,٣KCqyqǑ 8psMhs)nWױ#[oLQI&SBxgU _{S74Axġ/9>)fZj9։u'^An'#7|5`@cd.{sw!-hͱu請Y7\X^v#?8 )F)bMXMF>+TIWn,)8vGbAqMl)cz: ץiR6DT^E'U3@ >-3A5Б4=LXebe ;ƖYbN{ʽ7|NG04' z*@*B.+T*-Z 刨YO0d&s阩_=RI-)[+%;/G<$Rq b` y/!džtt Kb!ųsTA s`(!m#M`mB+p-фXTuL2>3Z[TдA¦\B>G(8la9jKjN*e>\a) -m#@=Y E9!#7'z~M;*TCM &;wvU֣RrZ<Er& ƔUt. 24#`3f^N3|/a L0N.Q3bWbN"wٰ>i}$eQeSYX3-?|5'a3) )mn8'vu]AЉ98jY@i#mJp63qB, swzƪC &)9md+@E :wB1;_KD;-Z[^yW~`3@[?՟}{\0nsT+{+uu*Q{ =_wi\5aNyauP"(e 86&hlCVK啺z@8b(.vKn+/5쪟75s-kj3p%MgԷy/2^>;Xw7Ǟk;?Z@]SkL粈ˇ.:h8%#fּ0jcPc N U>Xh>J~cQU4)|Z%e\0( {yrXe]O|6u7MLDBEgab =r3W?ɚ¼.KqՀH\-}aQra\a5s/ 84 \~SWt.y"[?V{j~܆/vn Ɔ0*ڜ3߹i!h peKF@,ϨɈ`~b&S/[+SҎ{_RfEvPQy  gW/aM.X"Ra8sEŃ ^0P/Eh fNWHHak*#i\{Y1<׳s%Wm8hf';Gn:Apmnp+6WXJIULe#U\}HtRhL-8b2•hUYHԤ> m m hyS[(ܪK'p҆%E+,o )gW=x k 0ּ&H> cŸ敱TebqKwl!D@L&2$Ő/w(Vǒ`mw^#!Xlyi B(Ls9c?xĬ3m}ohjrK. iE}YB >_>Bv,(>kC򀞄R^UܣXFAr=9YIF:]nP0*@n x=temYfm>q8<=:Qɟe;䟚HiqV!Gl9x] +AJAI'E<4;JG >hϰIrOw)ʈԉwHx vŀi0(ϢR*27ԾJLJ֫-xn4ƩY*J@hwbє@w`s @JBVWi((sX ckw|Zu ?[ % w| |@§i{Fk`7 p?)Crۼ~R{ƥ-W{6bH@Ty̽N}{H g1qɗ6M}O^c/6]y?gf_);B@4mʯ-g†3ȯae[ƥ}X@qO7!6E4M\~zDXI2\2: -VՃ 鄿:Ծ0h?@K&7FN]BSHd&t9%!C [ovPI+t82`.Y*4(ZCT#%M)2%QrZOAei}rz4•M2:\C~ ZC:JU7H=NR%Jp%y:JƔต^}E Kd>:S6H 9Ǹ%_3 ؇h]ðjfڵ8,,uؖF|4i1X%G%J1AnD1(µ P.r/@nOEktӪ|LDTw#BUV  ֯Z" 0 @&~Kp>\y ҍH) b!B!?1P(?bsw~FoEQT,>^Ѓ_9z2X+ti\0s.-.?m=ҁ2OQn`k$YvkuBgZԨ}ܐ.X,P, V(Dqsˌ{렃}ٚ+9Cmm @N-(Gqq9JJ-OK@Fؖ`,@nuu:K;IY>I@04Nrű-qS 1_r) BO, ǞHq/TUK%!YS (6:4yPGq`.LT )qp:q%! "7hÐG98r{"y*-~׺/_unoc%ARza:>H.S\rf~,q?xr1 |>Z&N;O~(LyhSq]a 6|^ԼN -r{rBOOBXʦ!jºkׅsh2ۭp[3-dz+n ԃ;7Y봤J%uʄ/"YDFAg0WQա~T *u oFvRI‰ 0#GB!6)N˄f8"@ÅkS&-lKݿّւ(z,=qC5ר q>F|9ZΞhZ׫D0w+?BFL#ԯFq9=1F-ML\f+ovQ'[٦A ~Ѧiq\_mMVf5.#We>[Iiyԭ!5<2 L!KPFSQ6BɠHN^+G}49uc)l$Mtb"]$Ԁ(H$it#`\m:D53RWκcz"'Q'Ivŗ:  5 >BA` 6i lj*K BEDefi%S [ ֳFz`벣N;*{wSjLwӊj&& N5>`?׃w#;[z^^ v=| xC=EȄy`v~F3W^3ВXy8 uDvsV:@$ѹ> PJÌ?s@ ItM~O5Kh&hаxS2zi0>D'nI [}, bbOrc< C ΄c^*4ok4yvB_0;rS2+*+ETdvɓ(8e B$QQhIlT=h׆G:叹O_{F/>~2>v4}_ߋ}FH7zqCou-#eu"'-߶荭j{f^颃fe]sx>}?nyߋvlVx}@uڎj=yFbY2$FoX~u7f q0,&vUO{ei:YZmlZL=}W_޽#CNntwrk#gw] [)Ý|M0H'V)¿XQMtB8PEƛkG/e'cA+CLa[E(Y*Eo&U )1ma=}5#c 6'"fU01ʑiM61ct+nHCՈmfr" ivPu Obj"`Q~S#8 \rl T6: Wc˔*ъ4Rr렄`,5D5nMWCEJt\ ~@j(6l&8:bxdav o`&^oʠDr\JS1D@hp=zC}E;]rRiפa,`9[OË%2geyM17z\ɻGT}מњywPD5az dYJu! HIaH:YF)iT]ތEDY*XzjAؓ t$! EDD? ^f 9 @)2@ !t@ɄyAEQw os[QYYmJN&8n(HnT-cnRAtd'K-N t)~W&'#]' 2һ) x %T͉Z{5?kt[G?ͷ|]mN7\֯a'l"uɚ.<r P=0_[o[@:z56U^^gsu ڍJ{i KqveER3 V񂉏mi\swN媁SɃ.ғǤ2+;Z?[u.]|؁lu Wt;'O6UvpҶNNZ{uF}oOT|r ]qيkJ8nփn:ow.ڙWl?kVF~N&$psWCϫ/^%loNw?W4?I}-呼Aņ_ 21K5wVܟQ#߻Xw$a /j=l?ȩ:lIe零U,k8ڣʒ[#fqMi<Rʳ ëpEŌxѢ'G9FfB BRhymw*Fr)>Bs%8#@sJ@/*%vW urFGHyT.HH^%0v;Aƕ+Sɾ[ znRePJefq:N0o˂4 rxL@+<OOkmȯ:J`ҚL#bLp چklN#P4 .%3#`M<2 Srf ǜ\5QΊ3rK8[_#s ڛcYZ;p/l܋{1NyHVtΙ^uQG v}鴝wFs5wݲ?i4Lh'o4=W}xW қ :c?-hۺ Lb"–D ??>vYi42;]םַm9z;R{;ƪ7xOZgյGu|-f_뿯__|hvol{ٺzMAO]q綮W[UF`]M`vKmzjw$_{()?+\hٞM}`t쁞?l7*}`Qm\L65kqN2͇&wEd W%%Zj_ O},3 7tڽC/M̓,|KsIM۝~)nˬOeTJn.g2nei݁ek]"{B5l)߸ey /{'H՛JA׊لqu䰐%폄2[OעkzcXq᷆@^ZV\ a=n`nFy8hb#/fȒ|}]IMY`1Z8O\&?>dDk tqe&28d*2v7` !+1Maق^]_6-PT),Sa_d+xS aPEqJ%cY`1) >mq(”"SU#6J-;5o% 2([-y;2 +b ֗\𢹥`h$strYΌT@jZ4%zBC=_̼WfŽqߧNYwЉ#]?s.鿎DAB>xP>?ٯތH Ǫ=ZP$:z^vqgv~Y&3LTO`m7v?|~mtg3¡)fU{5+Zv$du12X͢/sxAFhjԺ?[}:*U nlJع҃u6:[tUx>;5PFYovL#S(u=YekRڬ^7Ryǻ+3K[)ΚVD2:#("ir9g1ϞfD#ۆٹX&gHc e)"pOURlz"㈋~$C8V2WX95-w,}ʐ՜HHan#?l]g*A^4EO&y+;qٔ&#|6 >,~~vZڋCl^cQIcJiGJSEՄ)@2B51`L%PB5f{^M#QQ[ Cr𡍶Q H 5ǂ E"C(6iCrQcsBhF/݈N1io!tz]w0~kY4<2s_k;yWhRU]칄:cϨX&"^:5#RSl~Z9Z=PnEpf tws ֯v]u}۔@[W̵LP܊tG;z" 7-jy`|lZLuVsNksRx#)S&*g tN aTJ |\vO*pD\tɎ=UDiIIO 0/ˆ9tH^j/VĦ{A7 cQ4?Ou$n}:B*JJh.eA@Z:7Q{ EPJ1C o('ߵԤ1;Zrf4T.6k XXebB9XUu*j9.̞o5d;LW(_2%1ԄT S8U o5jTNӮ(<,1Z@-č@ȑXs?BDhV` OV8.a )O,TVMLYɍXVXl4k|6r (K,:yJB/H@Ot4%s"m&,let!x,wwL<΢Wn-G֝YN0H\UWqEg >';O+aD)B).ܿ>e4+'.:~y]-]?W3XZ)FP'jSΑ"$)5 Nh01fnjrÉSwoXj}Ŀ||4P\Uc.𣧮cg&D֖v'É檟fqxݟ\}]-rdCXKg݉} IDAT;SuTKIvGRmu/r0ږUٵ gc hL6E5 ,2U iV[^4'x$bK$"OBA΀91 ~r"\Yhv V렿im@6οo689HI!Kp 9fŔr6jy]xGs\vqnJ5gFrid[S %,OROq&-P^JT6u/gX%4ԯttiyMy\ )1{js3LGjg"D! "`&ò2ۨv2pVڠ:]TLgdL+k" u Q]oGɀ( !`X̘dƗ@Ol@#ByXSt^b#G|AifY&6|DE @jsVzN32²/!YVkz^g\n(/P|I$ KQ=ySk%j/yuc4Uui13R~~^4=b.#fU)BJZgJoVebNs&ޟz&ڢU3^;s@YϜ]!Tnߑ5XY[ݗ(  U*YK%fԊ_gك*_x+ֺ[D0up`i^oo9N 1l%"Tl6tOM]Q{v^wЍzs&j]/o0=3#w~h|`ܬ&$cOJ?1z` *$~4&נTz;/"SS#5%g"x˵Xn]h,VF$2)p2'*4$kfCC9aw;: JJ>Y\o ADdC+#ɚOM<e.jpqHH/I"HP"wFx#ƁW[w}bB$aI 5EzN:{ RFNn[gWEXA3zsaL+7MR5rtAYO3'ifp 6@9?' nb`^k;" 2T_G#ƶy%M%ی(,P lud"`$!gZ+wPpk"h֠6OTx#g6Bh̐7$Z d] f ::_I.6A4y\D$ }N6XL QS^ŇOvVY~''3|wSg]ɖ~lrA0MBNlGߜ=- ܽcSzKs"ᄒ}#0s~z3Ёo뷨u7~KOٹXL:1WLs?ώ)v|ُ;G7׀aK>碭lUz4{GN|wM ïd GGM7()qukXAF[Ou0r٫|rUđ/ ojvr xd1wnzTzڡy*7/gvM%,[[usw]]~7BuCzYlh_Y$S7m`Ȯ~_8O‡!@2\"BiqVh@+!4c a(hyKˡn6u4Ŧv8CH?fvqT35Lo+?f[PZEJ9.fy֪i~RoVNH& -uOJf΋}cOĔ<  ɑb#He}0~0Vl" rp8đMPa{gXzq0瘂aؐg2kn**<5lM@#P uBbJ4RܾM&$,f:ݜ`H@[!pm;sG m$cyMykp gaʗ")~>*d![SyV;za͍tD'2˴?=z#^;A=A޾:,΢Z~ E~,S" PXrr{2cpӊ@E,lb+rHH(LsQ}w∿o dVjܱǝ5O~^ǁdY=` '/+3$6уBۋ +d@k o1aoUzxw,? @<Q g.0'm!>#0ws]h]rН'@Qrf,+[Ckiu/]Wеwa"Z-ry<6 ͒& A-D~'mbtF zO$3+l"ܽtbpUg䲐ƪW D0wM^GJd~a/9o1窕v1|h!;BފʁHn~n[ٛ| ԁy?xÜX76LY Y@nBC,Řlyk9!PEi‹pa(nDG>~ƺ\(, MVDYwϲ_7Zm/z9P%DI>&C(Pqew0dfD$E$MQ gxo-:>7.wʶB*6-+ B$I"e-PQSo8?J#t-ĵLו3s|%%3K!uyQ6}.[Ȯ! @okbі2bddID?UeEj"[*T=zRP&VIl\%Z'lϬipd< g39ck3!g js`C:m_2p;CR_we^WQtbN|z_ ȍh%W1>UMؒe+\}.fvX1ьb7">4f̕p`63yw}\0˟8H:?3uFvSM8:CV `ڻŮ h#}|簲@Icλ8YQe[_$ Ŝ"lMb7.De)4(s'v}$uib3،FFk%̘yK~s_U5Hd gB0z+"f.O W@5$ek" *"MӖ %B4MI! 7jN%2x<-H!u?dik\B]k S! v6, !*ei [4Ky^]P`eD{4BRQ(ʮF=9`Xrw˕FGDL$  , МfGo4G Ǘ1$Sk1Fn8 Dc #{*K.-Ost~\7gkUb~j/_ձn W{7IS"m]#ىg|+5Vz3ƭsXcVlZ_k7kQ%u}qmؖM[. eIM_|h e Zؘs-],#\{.^`!Bδ7*Yq`WY;UzsTf~4rl`k Q9xrLPx{L@*W-XXO/v5QjzN)\cu⤘Vqx/ZQ%% '6$4lϡe+s^4nĶF6$OHq6:J+ hE3O<9 eX*W 0?FҌ2WCDHaL"WdPGFew% ^B bv3TRϒQ14@Hh І@jmB+MS'z. PTpΡ$I@>I%H? OBeZ&3|Dǂԗz=hЀ-F`+N`(<ҩ" 4//mVlڨG|z4@!2Y;#'͢$  HNȔw,=A]5[uةII߻Rd⾛VW&r޿ԝ=39RrI.r;O*}u_`ŗ7s0L遣fݥ睟lB??&ə M k)lG6/[AN a,Ss׶= RJ ▨u"uus'ӏ0߰_ISz6yM8Jz.?٢R(gG z@L\OYTyd&}|N jQuVuq tjͿ !Vި鴼az:Pyc!h,ZvY̧2kﲖ)]rd+,q).qa٢ tGR,( v Q&q, @ 1KJRInП*JI LnJ%HN TˮCl }/qb+^BK#]& /K+I$AF! rU|} T6Gpm0FN3}w=P\uWaBH-h$.5`z%DY!H"ČHo:4lRk#\ۧ֯g@+F^C_;{/F>nйlN~\$ң?VUEb.:V.{+6 rU1{:]bT}?nyߋvB |;0I:mVm:4|Y";mӕ%#250L6I3QK,FVEjUoY?~v~kHu]%x몣7yȜ9, ҖlspNcV `%1<O1)1~()CF_h"N,C!@F)?/,K 2tJS y_Ҥ\RHI2ދuD u,8S_(CjHok.C A"n-HnDtZF!*`gyreFu\VbƱ EfGTCSGc8<)nXɰcu62SS^&I@KfmYW aZɷޯ_տiWeN\l֤ٓuPB22B% OsV)5;4[8unܥTja#zlw}1\swN\@}WWpWNS۶6[0gvݺ]ᶳ>St-oo/CIc?{e'9_weG'7E6wrr_o>дomB6WP 8'eǽ}nwT@-=?@vpҶ?ϿN[-3vמ_U{x{ƩovJS/-$psWC.^" q7[o6=[fkeO-[Gf8r 8PK픷`KniL)9}Uut`חNy{hd8ۻ_s|1|-k^ ͏j{I6M9fǕowB&DN$XOĶl|ӱHEz}m>̊$f!]ˎ?w4=M;>uͧ9I -Nް?iTNݲUm^ec_ɓwolk 6MSw=U IDATo|ۺ7?^-@T'=3>_C/ݽ^u}]ov;ƪ7xmd{ޛ{{_[k+O}k'6}Sao{LـZm7^эsl%I [N7/{-Uoi?vֿ"{fn}SQw$ b*f*Y_l{O"{JJ vGϯ<|͉ڳ(GVx`Rڨ$.xd #ⰻ[ ,4H)v a*qmjͤ.9dXX];Nxǒ,彮MS~  e-% (jRT:}X@ptN [0dLB&6y$(ٍ$Bݟ qzny8RcZ Z /MPo]l2(RGD`1dKF8@DDhPT!0RNv 1MVr47QSl]x(@0]#<ֶɓı's_='s90ԙ0YQV_p.5II,N b`2zuMtξ=ރ,]yA9x^Ϟ!OO>&n݇Ns}'uw\\*M;7!M)Hdrznۯ7+R}zߣ]ɶm@$:w}|X7@OVdx<ٺ2)փg(ޜ~Wz}vbwj( (.iv+|s׸ABC.쑣zq6<<*¯{-dG/,d3R.Q GjD٢Ű 9R)`BJdUO 9**71ܿ|bR0Iذ!;L@ ~D!ZLl6JOӭ()]!'-E7ǩmJb*c>r?Z+E|"D*k( ays0A:(>[:kf`$}=TßeYz^DbwH@ @`_l YZ<а(UjU*8N̎ji#£.|eW@#bBۻ(C]n[\?1 GF~~er:٭h (S@$Hf=ijkm[`~zG[fɖdgH>ViK/X-/b7']GꞮ&:cϨX&"^:5#RSl~Z9Z=VF[ 驯]IGxТu#>mM\2{D:#nAIO}TcΞ̦$PW dzsWu#W|ftO~9)&TK!/9 rE|-w;ޮeA*(:">cv4r*v`gw8MIэ[m8Qn.SZ\ c!5Uنc>VEuO:Ʒkmi:ػҨ5A{1#^kQ O- E/lABEi8crd`0Fys8clD&2.7*V(ŚY7LNfQ:XEEzF7 OyP,)XaeH]z)b\S\(KH$IDL"w"6.+e{ L&g04 cWz+%S4C[t9D`ЛDŽ7vq?07/ð r⺆@y~"ʼ6Q֥Ė># P{HBxp,QxY r N%zddM/jC;DR_A! UGaՆ>s>Wu^Ɲ5W;L~?CP;JDIvM-)X9q\j"/:H|XJv$u$iw} ,&4NkAjrÉSwmXuo}&n8($h/^ٮo9p Nc֖v'ӅZV5˷M`7UVMn8qO^j}P'Ԩ>E0IvGү+6lgoCY#VakzO`c5Hjud͉!OY~@͝_6[\SEĥlm>VmzRΦ#ziL6a<hq+֛Q C 2$ ǁ*̛cCȿ-x/=|QEcBNAT/ڸB BFb%߇ -<䅼"m3n *YN~Ƒ_4E\ >8~1P3RW nysмVb|h掏\j:LsnjK6\l|nBy+Iڠm ̽Z| P9UPunJ܍€M-(a-@f\ Ş"Oཛϋ1#o+`#B [l+BB'TkYʿl -9QǒJ%Ver{ 3&iqwXC%S庺Dw+ S: Bĉ_IH6&Mlq&E (e:V =P4PaV(((#^Id%k$;i-O{zg󊑧ZKd:~1UA/}F;ƬTI_򢩧[[Z-0~-i왫}\Sxf290jk=hx{]kG*!A@J%khS1Vz"E([v}3tOPrZ[Կ~>}kgORIToߑ5XY_ݗ Gj03RZ1?wP;A%O=cEZ=PU5"680{h'?LA]ֲdg d0NgQO\E ~GtѶk~@ZwS6db`TIsOM䎟39}4gY5~u3B$O#`fW|J'fbNs1=@V~ݮ}?nWpD%D@-`S;7l={jV4i%=zbI'Ft{ _o/·O\j!{F8gM%n['Of 4Kyr3”^AMo8 nx K@]y b[I6qXfx5&]Z`/1v~!TXת4q(hE7jmLcqb!k6Br5 X9\>.B>.)Ewn+ϧTP/o>d4޾e/>]T=4PeDsdhhT:4x@B JӅG+$ޖ; J.!:lo4q,K4MS![*ևsees*RxjxޢR"gr DYo5Þ| 2U9Q;ɕi-Ͳ%(Z֦YYAEh$JꇾdεLlޗ0]MC矽3m+}:%;u k#QIv =ODD`桞On 6>ُbS.~75\iXmLvtO[:k94'Rn7>=S-9w7#~JWyC/?~ &>9gGp])v|;G7הvyһϹhG&[8gէM+FO|OM ï2Pݣo}AN?f? »w](L\~\u*|뮳/ oUlU?#'ۗSS>-O|ΗKy#(/^/rd笺bs_]ը<M%xzo>; S->gua7w=R CA3kݏFN'_85PqT}k_I`&#1)+7 36|J5˖oeV6m>'!lmyqȴE]3D (}*/eFΧ"+* m}CY1\OurXq&RvcƒRt@HRDsg6+ ͤ"PK6q/J;PNƳ=G/I,4Ep$~?~SmJKdoǓEW툥Z [TJ\P_AR@Dzm!bYF$@G4 @b",c[ h;`.Sa\Q.1 Q5Ȩ)O7 q৶,P2aŲLS!G`k2=<9`I b݅$0jҋ[:)uy+!V$D`PQLHC@5NybNj9ute1ڳW<j`S(K%苀@uɹy}~gTTkssssssZmNxښ'?R/@Y=` '/ [@ QaYBn2U|?Г~ hѸBA-<=K4N2fYϣGxA_1goq]½"U2hmhE]2 DR5ZQ]Tqf6ZEJz[ 2U!f?X*|@4Ō91Pճy@P 3A`;ulԜ4U (U@@d Pd%Z%ȪGD)jϗyأqv0?!Cٛ=m=9_5t'kS Hn}$ ]q'.g q#=ori?_)es;}y}VSՈ! ,8Plqlu[1ۂ[n=%JeV?pC7An)>Nt\_TfCjkHvJQwPHk_[94 f7A9*Њ+20S" (,kb"4O36ܽdQ=`b@yPo5֎y6ag-deo 9sDIq +8DDb7?dwɳT8(SuF/+:27KT6q=~/ 8 NDe[Ga|܍ztvɿۓ|G~w48.^Zd8~mQ0Ͷl4B*+M ;4'p`4+[m.{uY88C{RJ=fk#\ۧ֯}Gyp-KMuiH$Y76~,Z&JXgD5HyFi95D&%QSNCc486)/Odq=y(+3܋N&iOm%y.0&۔G8ǔL9 TO˜fѿ}2ĥ>v0

      ʇCcyG%0,@]QrςI/P3"5>qwt2t1 On\ IDAT:\ n@/Rdf032=49 7`-=]!dK^Leg]7DigwяaWxo%ǙF Яb[ Ō@.dSocngǸU(-)E綌E n3zWϵaK["2u5&M^VPqӾ:֓%"GEhPFa'%eYۋh`튆):^%,)MT"1^$be.+:s{E>'ܬ sؾ `je3cI?^Q;'L}DSɥI<1nϐ*"'1I<[{S. '9eCȸИ%&elU-EMJ]n$M&_/uK\eԁrDW"rPQA# ϑLzd7#b)5w0` .Ƕ0sC6v 5$W5(=H|b8+]̫MtS@.'WCb Q=y`Ӏ6coD-Q*g)>Qu/#OCYND<X#z5~B õ:< 28`kZIQq +C7=Q)iLulN%9R;|tbX N="{AM.,·W/0>F S_q[a'?]آ3qM.8wqr0ˍI/~ZOTceXvЏhRgxEI.q-l<|5Sk#nOwo(EmD3΍A3Q3#2ғ#効oĂuld7d\޴l}0 zE֦Ki"u{ː:Iu2l}':fG˝'Ād#ȭCmjYFT}tݮ1g̐8Gv>+T<%Wf+=KQh5)F̐2R{Z|&{aT*qMf(6ܚ/"YDfB '5#bW5("dVt8{$Oc{ yL|hժceꁀӬjn>$B(SȜn('/G6Ie */F"*0I(/Xz5+1Dtgpܲ$ uPrlfHHA:55PzZ^ʲ44hei#`|ehv,i-Cho!7oކ3G?UٮE#eKY5R. Ms꺲:OT ¹-2YbFyFsZ"I%^{aN^b0*ݯ .pSIB05 IV΢RU X344ʜ"˼E5peZk lP/#L ~^\]y9ݾC?處f8<ەHUTz5m|UXԙ4K%\)!-ǰ\\pib0xf] НB1j}k5+.M܅14`Gzb"t bIʊ jkk>Q;$dr?V\,ҍcpa>.4C ei;y`sFƲk!UqsȀ@w t˵˃D^4:DKA R 75yBqlEkMqIyZ"J7}-X1O!ggטD/a!"?iNUʁ-hfgΰcŚ){&@`̹x2cEo!3gPu$,jLL%D[@fU Ⱦ<1cώ4}tP_Ɍ-tu3 JOjL BD?<DY `ғ+-lq҇ϟzu]?N{2[¯ ;pu,,i(s8kdU B͎`nP;UbeytHC #<7.ȗ8N~tT9SrJO49lV2ozg3sxo +f`4S] yCtEG ;d[Wʰ <4",?";@ENqʴ9mR=`vze,LtB/ tTC}^сa9 =6$Z$@$|kqϛթXdFY .$߷mbjO>5iTC 1A#8 C8,g3A6+W5~Z,7 )N\d`2aG S[ԣ7$Xwi9ڶĴ]o-EP@(R'كdlx/CP \)nՁMʰ^b`gSM*퉘ZDFToICM`M c;n2Yq j֖ 1< ѯQ|1um3aR;r[ ȑ( ,8y7ڔ%exSID D uy-T }LJ43{B13J\e8 Ay^X4XT.eȉnq/sŕxd C/.@ 9>yo\x@"Gd2 :fzV}v!)-f'8y\6QNuG-I?o g3>>|P60Yo e ֐) ^5ѤNFj!_f6 4!ڍ M'4ٴi ZhƲ1ס($ Z|[65W,Aʟr:4/KmkӶvf\ۆ$D^Вe"(Cw&wǞ41,t<&;9z(ҙc!x$", :?g ~weUfAF>0ٵjd~%ɜV\CB ev^;Vf 2 |/qLԲe4 & O#q&.9)AYĒ6v'!=zqtS^m~pDywv38_4T_uѶlw5jN+ h $,<B^J"#QR12sT{R758$bG*Pr~*}-Ug5s.;[2NkmGtBoiʟ-`8_¤,i-Cf6!7$243P.2V^O+l;B,?}v~G~bUr!)\ܢ"hʎyA:ߨP;<ۀu,>48 3Q匚8IzX ˲k ML6ki+jӐ(A9x_b1F9C/gDmj]т;FOؐ/42Оw55Rj#a)ԻŤMKILm& w,.(h"{?Q=p`R0h9H 퍉E)jt^,P^Gin4¤'g]tΩ;mmd/J"NN FzExO d`73 <8Hnja8i60LQbr ߺ L' "pz偣^QT d; 8΂:K"sG)ˠcۋz!cS= 𴫋{ZW1Qp&-xb8]#t8&b/}"/@Q=z&IJɮ"bE=l/Ee|/&iJv2iz891 ˳m>kK'_o4M RMV7~f[2-I\"Z5,Iܟ&Qm=Oĕl J@=BNj?IUu`7 &Ep$[ݤmȆޱ'$AD*JOcȞ; z&F{sdW;/tdcg:Oz;$ =ĝ3!P) e#xЎ=DW d NaM'DD@ ƺ33@mBg1AZ^ʔ1U &+!"bQb:;$U+ Ŷbdh4 MӎFQ~Xk˻^_|n_lA~ l=6ipM|jM#=ZlbtDǘoO5@L9=GL7jfe-mu^=95m2\cuNEE{*RL 9 /2QړH@ޡ܌᠀'s"-53^_99k)8.ǿ,E3E??c<3H͈iS=c|O"@w tI2tx6xyNdeeJE-TǹmZLFL==39ܢ3yʃI?={bUG]1-`mf %4TzqZ8珺54 [u%7t|z]O6r])W\id}8Fik.<]X jCfVpMIAe~yt7ݔe2sW@m  _?eB@&*! I@*b}pT6ÙX0S ;ȧqm581ŅؤL:~V\S̬ \~O ,^ޗ^ DvhZ s*a[ GKph<>v`U?%W`8ӓOG>t+YQmИ Vn7+m%RrǎQgWl<.S@Y4Ni>]]iLd_!7IcIJL Ab(c`!?Zq{^s+Ŏ][)cÑ/ٳbfYɚ }`ڎ4 1f4Yb68j"AـAQ=Vƀ'$9hokt7'楨֍=|MK bFCDdXc̴`h蛷''49ؙ)DZd&Zc'$DFoc@$i`fx\ h 6u(DST*z*kݸr/ qVMefj"BdmLqsx>3,p[JI^Dq+E"LLeFLW D^?ɜM~);hĪ Ng7!ߑD|$3S ` 1$I1Id !LDYC@D p ʈ2cQTTށiaao|k5+wwj+}wvz^bɉ?2\ߝx̙/" L(釢7CpJ^ aRt%滠,$Q޲q{ !TY\FC8a<5?GI'=9QLfr"%O\6̜V i0ǡʌЙ IDATKlfulk+oGnm\*LBv f{,dQټTI[zFD4-㰝Zr4}S6BW)2NV3lahBa qWx~n /j㪄)PIc*FK @j:tIa\A{/d+&3na߾7!j.:Kz"=O ]n V3COl2L)`F]~uɗ{EXA,Q9wXj_u%=[̼|0K^/ƃL3LX-͠Ŷ^; Wp,3C I}8h.xa%S]g(䮟 ^'7CLƒ+?| + RzhـDb.gVO"ط0͋h-J-NaBaǜ͢W7)q* [Y ~= a 0êa~ɳ|S:,\T=kJ jW@ "q8!Kź= \8v_`X;_xIbRbj#/׃؝Pg=wqK;e"苹dID//Y3#^y8?2)pw W.r咿J܀AM՟Au]iR1gW'H]B:I-Pbī`YhAo W~ 򂹸D hf6O4wJ7\\ lMff"$s5#*[gEX92J= _@H< $$RD%_,.V4k^+>vXVo]Gu= ŅKccR=MS !*-[:;Lxv^:oJE?5aמ=}LL~߿C'fh@aU<>y87i\2|Ûw|i-۴}عp]>{{J4iLQ̖%4E5#BiuO^c-n3NIfs/ <7buh*V#Z Izgk@äܚe%3@\mbTޫg?;Zu2(k۞>Ժո!L@Tֆ`vHbTM=Hb9GqM䷏y^gG?tujA3LI]ysϟ)۵+Y ti}-:ֱx)D6tɕ]bF$cN:Ւ`x{Ӎ] V@p0 '+SE\\LNnY)ٱf1Z84&1G`9fj~װVp|ɓ* `bY|lX>lNsz]D(q+|(qgA3¾=JL'ԔY0|vdv:˫lאhd[~_uS¡ۢT +2(gH<&k g֦w:שϽt 4xOm{ 䌓^N¥DԢri9*Mg@&-9YG @:Oz%Yh\9۪ l‘/["61$&Y2yahnz:Wl2e=#&/S'/!8$ڋiz@4 $L%z: &";rZO /cn۔1/Iz%F1k3A%{퓙&<+L@? ԁZbXl^\\(J:hMw?'3|DXV'X c==IjzBV,-,,LM@l{%@5ڪ5swZ>rW/!q@np0Pyn{r8T@ZnZ$ӄ'{ er{Bc~f;jYV$x۟J3j:ݎ/Mfp@Di>^I4yFA/&&I>aD)Zڈئ|bƖKߣZˡjHl&H2;CR =%`+E䘞Rkn3#B?hnyRk%Ďcκ2Ml$Tm3rxPs*C Pa+6^l0uK-3_u#TĈkn;PI׀.j^ξmnYڐ!Sc>!FӴ5u6GgK,wv2@f7̊ Me%#=O!a0(jSp!$ p.N` nIc>Qa+;'h)]%ZѺpüMshU }=hBhr;2Cs5,-kc51M>޾MknΓ/Cծ列mbb"Ypr+Z;ҶT/%dF臬jKӢ`1uH"M$h:ʱ0|dݨa^Dy'2͑/@,MǕ3!CLU\qw\ۦ ZϚT azeڟ`r+z,)2NwbZ\tuuwtt gx:~Nd}+;;:jwwwesss;2!FGǻ F*JR-J2Q ;$TgkPH:n]0Q2]Q!IS=h=Ϝw֯w:1[7-W]wBR︭<֗?HيVUζ/p vKn9/_+H'U=Icczx,cqױs֕w"£w ]k~H^8}սnjy X󎍧^1bS`aNY{{G}F5`;6FG98襣<8+η=0k׮m+CYgK${.~ b蘭<.4kSwT g&S} Up\S ÷18uȵm} ݑ7#F{08{{ےd{| _il+.GLq⊶t]}?kS"YU}oV}T/QbG/8GN+?BapL)XH`d#~,{ v+w<{iϒû<߫ye׆*bXkO:7T$/;گSl敋{5SEzgϛ=rH e]ӯاSK<[uGš677@ݯ_u,|w9snW9=g'^3~s!Q:u0V= a0 5&##jOQ;0d `XfUSu2s5 1H5\6;"qOF Iǹ =J!eMvM!<1y- \nݱk4}`J|ɜwO/&Wcj|ĻV>ʛ:ni0P_93@/v桦0Xi恨Dq.SuQ4'?M}W(&M>!{FF ;y$jJD8m;d6]> SR8Pc>HB[)~Sk@.M֚\1E_tIN᤮#oMG,r}&Bi ǚuN)XCc^Ӯ2 Aux R.67tsS]ġ':,hɩɈWp*HL4A;6єiBN ̒:k$:i.d H+w*GRSZMD1==],{zzN=-ܙW_+SSS P(*Oη"ZTU+-[Gk Vlw;P`_:@[ʥ;ũL?3#cnd,[7IFB`⹯?R=t/tT~~;K3ycr=|_1op?,^o:.{ ondD}Ow`om?їRtTNi/]}$t5Js Ċ7z;t=9=GbY*;s#:WV\;r%IIWeU6KzvnoOH-*|t~P-u3w*DdM?xn-eբ^Rv\hMS O{|_}&z2%.~? 6#/[sѷK^?{oG~7WaRv}ʼn|Ϋš[Hbܳ|L&z2A }z~+)}D2YCVzH\wy9w1X/#P z'/|lxD6awg3#N<4Q_iU4s%-lH'~zӛ}i2",]G/\l$bk-#SaQPg1t=;[O?mU>sYGu̺C7}mmh/lomH_3o~SnޚoԎx9'>{ei u8yמּmOrrrOۧ[=Pͳ+F{][+ۭN>uԥV\9%㬏m9+^"!frozo;{ C(vL]6Ü޴s$`>y:* !=kS0cd_i3l1Xk0sP9\m @"p"Na%Xn(:wVze'yHrF"Aw<`CWdwWՎ*C*4RQۻY3e[$Ou6Xl{Ḍn=CY)ءn8vZFs;8$ -GhfT9!W񃼈'?4vȘ h`\fŸ#JM0[i$'"4]3/&9ϥ#5<)gb:müjMr MzT1(1 u#<\uq!Ib6X$ 9!jajHЫxIyy\ybΛ̯Y3=i$2Irnm0ts< 8E%YGNS Ƥ=|qr!*H(M$I&#&zhw}ĀEz$S#)a!!@+@ P*"fʖP=A!H~$,)LS =*7+hC-r>RTT6mtwdYVT7nx)G>{M B{ӦMORkn~>IZh4JB!MGƅzXMs3-<]zQŏ{L]\tttOCM\$UбgZewmi{𾎙 cҟlOsd  2Ȳ&SA&O(_ Ȋ};neUZR+VwۥIxiSYE (&PHP  !yBjfә]#vZonϬD.q;5tfK~./kQQe.o)N̥T"U[oh_X(V6bwo07mM d M"̵Vha,N|gZZhsh&BH"V>s~Ŧn8ΩZLgvΤOƧX%jϜx+P[al@t{tj'OjalT(lMu63yO۳{J6A#M͝,K e9űtv7w&{fmڬ6Y.,.'fRJSυnBm]NVVw̮fx6d-j"v?LڶɎ$Bcuud*?\3_ mwm,R<xw)sPI( R .u¯Ʋ#֘:Ug]4MD[DHQv/<rv14#zd޲XhX!6tRƃ&F =vJ}hd/χJl?;^Ԉu+&mf{!q2`p7>).F`db5׈V-"Mt #%K0z1UgBBu^lO8K$}ۆp#"_],3rUwRreVhr75ボÄo8$öNbZ~"AnJbQ&NglGi%-ԺJ urNs^[ˬweDZK^yw&K Gl5/;ܟ5pc{`Z<$B (C($DF""#Q`WhL({$cɰjw`4kq(Ă 4\'o)AJf>F,fg8P TSyȑ-NtSхT.UB7`HWHryW)~"R4x ڨ;`Tx,4??>K+W\\\kvlj$m4bW\M7nRSϾz/~t&.8{џ^-z !g/+gUFw=HG iʈo,@c7.zGnƮF32DM 62Q,:1M cY#$'e…BCߢ b:E[>hwv Ae0Ҙm&ڳNz%~f<7ePXұ24Xo_L*Bz?5y}X^]@(R!~i-MP!`6_(b2Z$KP,-7!am(hiٛo~dpo}÷ox+y uAB퀵}]PWV^BDJk^29w_0xOg:IH9x7;Eݹ-30K*Cv IDAT+R @?*+(+{D1=y {ń嵀I/l &ķ *4y 60АGyM"+7XTE#D %6"dMl"T*= +t%y;w=Ua.Egԅ ᆒd5K=Td7о|i/>h<nT$LͼCVʉhzRcW}^Ɖoyۊ?M gs:x2L/B8@ <mA*=|8C)P 䍨t ' 0w6*V,fDn{t a OcШ+̲"t)I:Xܶv k5"śx|x=AoAHbġhCLwʒGcf30y)C_ aH~414%{3a{lS#Hk^DHj`h}}_+Ln 25tmD:|h3F<}N>\f 8wZQvnDP0H1MlDl=rRސ ~lO#Kl; Ѝ9 uELyj@Eא}3aO6̖$ /˓)-#<; ^ )xyslִ@}j_҆ *"Ɗ7ӧtRdvB0]Y])| &=÷C'Oؿםu꾻4{bhb4sO[JGNxPm'2H?tN:cw=5v@TV?hzOcF7Bَ?>ĕT(8hݍUklC^e iY(K8(X?uvqHo`83ԷouUocfXBM)+z+W7JTXk)=ty{bzlV,=tbi:iQ;pZ_wccȭ#'N8:ГUOߧNlz6MCMCWdy/ZL^/*)߻ru䠝-->ZcYzV}=:F2U\[cn;;}~pzL껞k hL6s7,Sm B~M7D\0j:H3򶽖7f/VzL{ՙjt;L &^Fppt,15²@z~}^*,ˆ5VƝ!Oֹ'_$ [q Qđi3egyLlub2Wb7SfJUE9S7Gw5s7ifLwR˼ g4y)ح6/O@9m3%5F&o|r'yKF'j6$={Z fVh|nG-lȆ(4b%4H YSw6?;#uwuL% J%$1::̋23Q8ʛ:ừ(ƻrUu6}L…hu;3'F[WF>c}ƞ4~WF|=>Z\^4V,uw+vYW\zKN|d'AVu3b3O;p~Kϯj_/Vr|pd ) )Wݲxtg#8 Gdͷ6; :}vyx#E+9A`X+ ߟO{skW|sP&7q1.l7z6 j7-ŀ4pzf Kޙ* ~퍊feC~g}\ovOX/M 7/v~KGҺʝnWOX0ou/@_s.Nk:߶tz<o);@P}so[u=|v>jх$'0E]la~V8D-4IAoueܫ?0]ly8+om>3AdsMDM|Is`V)!brn9Swh [9L0٘B<*)WP1.9݇K[,4IB)pxi3| u5;4*X1)s3i;A)qnfrcB`3X@"@$%lLrGV0zw$Jq!($ONZbH| ri4!My1cFSN%=m&A \$2WϙiC!zd"G6wp)}*dd:zVjzZ}^s\_YB}OYR/4W~/<+_LfYhdQ=egF)7;Db@0Zz8j&X ̉, yb"~3o+"@u,EJ9כqcoNs&~G/\b_1O*hWלwS!:9YRKȈ8ɼPVDv&10"幖lF1tM.[ʭ"[*8^YCW?8BJr}epĶ wL2gO 4-%r1)O G|\8NyrSN5\SBjY]q̿QNliGE9c6."o++O%Eʡ?eMnj2_e+Sc,mLbl4 \eO~0"uo8Ѩ IvUFHe>W?.>K_($K2t(MS+AxZC;;;,Ob$mgo.6z̋s3.rz&M$$ۼ۩4cQF9z(QWrj"Wm6m:#?u*ϧ o9F'ź1et/ƴCV f5ͯ MpOs)YE.hcq7Bi"p;X 5>ak N"RQr"Z`27/o2Y"3|:,MzjвCީ-}aM'ޜMۜ,Vz=OZ" 2% z)˽xsӖÿ.6?׺6F+d^ߕJD==n Rb!T͉{1Dɫ/qdT;—p>WCMY%佞dlj I-_ȦqM*NpjRXg{#T`&JOT_|+{5xs7}~xhD}ZJuIj\}||>jo._s/5r?3-M^+;Ν^I0!tTj7zd8! 8k#!X&?Gt{5.{+}8SypI!ߪ~f}!L>׬X62jE˒q#沽8z8zfY0`t ڏ=#Em15in|? *"d - `f:^U,K= sCN~3tY= }]ga@/c%'s#D%$tQ{`/||u>Ky THIƴ eUdse9^Qσ0@<)Wb,ʋQhH) F{q'`kEXhG5آ[gUSaszˎޒEqD5~֐(` GK%h8pK#~q*,xӞ-=بŽW|~{03B^kGO~EFMKCKzQ EG-5r2ܴmB%kҍ*8s;6tix/|)Īx!cl \ fd'Ƽڏ Q0.}/tˮC[KZ\1aZ5^41s8'l0A̩b,<RGљ#k&3AsTz¥^:oJ+c 6u޺}{8)艑<朁FF<{Į]YKyk8x]F [圉A+gv`,3T]nThAGhKIWgmhWѵЕoX,4^7;,/t^3B iVZv塞^˰6m:uݖSvIOM&l,FN^+9!n>Uc86b\| ~g(e9zdem2t)!D=Z~MjD2FҫƸ#݌RGi7/L-1ėȐ-1Q 3T3cЧ0 "Hɦ;R9F5@*LYQ7CWi8ys{=ht IDAT'o犟@Ǯ WӠ7cg|9#~;.4xw1g)W6u퟇~ jD-um 'w}iPe\/Xq#yр%ZXS'7=zxVtdg)魫/Dh߷կ}?S9]l,~#^<1*r"uTתmдOB͞@*iƢ^vԾgE\c_kh/%\*xۃ8ŘgfC8nLoylgt} 3 }lfA"< nK'Z "d(\ \ - h4~}``[xn,D%ţ0/TΏYH cGE.z>GKc:q%ceGydq)hC`CBs}}@I[V 3Kp-U hYiZ7 +*@6oz¬v$!{e0$!/'yVm!$$ |d0 HWB:FfC*x̲ PSuk|/S Iq7zGy-/vxJ*0, ˴NG_Pm лWG@ؑ~xUsj, o-OcF]gTʸ.Q$IBS# Plݠ͛6T۪yPHd*5Qoz^7Z{hQmj/;slԧ3sٻ{۰3#(yڷR[-o*h1(U:q*ѧj蔏wv>wo;V_9@B$F66wڎW~xY׭:㺒2ϚV +o\Ѯ߼`q(D0i{p{Pbz5xE5;h>sgbohQmiǫ\Hz`_G"_Ol^g9-Chc׾29>0yȯO먩K/V\92Wb׵UбׯۇC >O}5獾ӯ8cƮ_5W}E:Uc_~n plyGرYݧqś_}ӯm],*3/9 o p97\ph\={ FrVw6b>=*~vޞ#LỈgghFY RTCg7>9fU7o_DdǘF^a~1(? &y?ǐSu7Ic+:5mghٺ^&;||*C#4Ϥ nk_ `sYfI?UT/f{!]Q O€" DHUtA$ ?%*20}:?*tUuuft??ovW8uԩs}0nBo< @e(qJɚ2.rN#L\M `7fsDcn:*\zݪ*biV˹!3$>N! P+p2je-8Zbruy%|63qjBW4TGّ"K\gA{?g6ARk,1~"Z sMrdj[k@T!>fEf6"ۑSv,mZL$Y벅cBMvfBuiп~$.v<$I0m'KL vY=/ij83vbWvЏ_u^kT2)dT&$ ƙ(2PSY{`fʩ!3Hۯ>TzZ6igVqScImPV^FSgĦbѹ?V3e,*$!I"zmˊUpg6NirN1dچ @!ܐZP-wSgj<}r繕̬}$f:`YLy=HQ$WwIoZZ6l,_luNt/^C}2kłp39t!ML<هEUMS'^k &)E䭛 [ jkؑL7H]ZJ|:W%9蕬.u\ԑΆiK=-8$wKysiP S mSE-J暥i(`%MЅ}DByvDkg &kvASI~W:Zi#0{d];VvuuZ^Tlߩ?wNYj_DL BSbK`jSgFxd7)BS'yybIgD@+|O=r.ŋ'n>w<`dSk;=':bMJ#@e/#m9?LPyEt5+DZKw)o(  ?yҩG.Xpd;"\oۖCm1㎮\ѥ|eKR-# YiPoB"Rmsefax,*MXEŬu9jm'"cr B+C)e2/[scgim)U,,rzy sUJ65S0ۍ 7HʶMo$d¬إ@%2X)!]| /k)P\y[bu2曁㊿`(#@Y6Y{L淃IR X ^%{}(^C@s=]uj$=(_vthJi`9K)nYIYlf***uWBrڌR$k0 uL(Bk֦jfQkPk} "?ӏd}+zߠd Q^1 B "Cvx$Nfa"chQeyAhޮE$1(XAcRyl|R;^;RdjS? &Pd..(kS(&}hɉgHF7ɿr "z^4^2~s!$,~χ?1|ew?;떢;M?8{ؿT{0d=mw;_ E};oRƢu|QsvZ_v\_OVn'=}}`žAV4=$Ꙗ-m'5{K}1)~8x_mG0sD"TM|,uE Њ"ɺ%{ S?h_b6dqjeihogbjT4W};jNt.M͛~d:X*%޻Ax&kKN!Z\cmV3S1gc>]ʅ4QssKfxpJx=|S϶.ݜ_͕̯\81JǢzZ}~+7w5ⲗԧr3[`*5XAڽnqGní[;/uYBM'tlPz1wV,xՆIM`JA+=]VȍIorSM*.H&_n3qZ`$!}^J`9-n=/3\"eQ~?:>|ް:ϲLL|KLLCY{w3da ]:*ҏ_)XoQ,Q4vB἖k4UrY˙9 k\ $Ti*͞eeCD3kD>Rs22l#$ !єtjDV6%7T"ki41Flֆ0 3lx4ev]ElX l'(?"Kd ofS1H .)a(͂ 1à $򦒍*@j HFW Lؔ%%Ɛ3V#=mRU?Xz Z)BKӭOo.qZC܉շGLm(~+d/|9 ?x"CK\ocۮ{ rf @_nW $ۏvW?T!ym6*F[N:}_%=#MA`/ 耒H##KV=h@L%Vĩefs_9dŏVɓ˗-lE 7̜{upv׿Su SO]pKdoF`|٩ y_:oK,%O̰U}k DDwt.:wxx_fnQ`k#6 tGWtU,B.s Qj@Z/p$͔˽l|zzFz|ơ z,6Ґ&`6)%S8O\RSU 1뛬)L~.#4+/Ҝ+TW+*u Ͽ zXHs]ùsn.왰E];Y}j PECR4w!}mѸի]8>^W36`i}^2C,T0Vq C;)nܸp(s;pC_h(ES qh^ED6D BdL#V4N6)YH!f U| ?vLC>6Tj J$I\[izn=7$3|&JޱХo/}BzRY2teFW*ĝLsȂ5ak\ߞ j,* =:ノ@',mr+^.|0b%R܅]@Ml/9+9yy4 I H&$ r8ʫmVYUKN7fRPFo:I#bŃ ThI)n;N~#daLfc/<­1jye6Y~U5砮ezf;@ěd@h5`x^ͬҥ./`{̺ƌ}l e 1k RjZ9`VXjs:q\'u1^z\nᓟZ*9(GV4LBa,-&?hL9sG5"ַ Сh1#Ϣ>f蠡N&'iE{eWHzdhSYwWSd :/vl6D{JbzT#j-dE,ACꕕ_R\E@dĀ@ 9!|eRH@$HP!c6̆tivI>R4u2)B/ҳmNz`3tbj%c1y7Lq 5!;*D]he"#2T'sf>;JD$ يH; UTl]|$z=1n1ϸPiyvWXڧOxS+|۽9C{G`X+y7_ ьd4c;b ֶ^za'~ZYw@j<%ubot 5qUPy)WW6sra^ʠ)6 zE!TITw/hl2"zȏ V9s@X37YGn;'!5+o9誂UWR)S.3}OL'%#D*^%ӶE+N-*TAc8VWP͙e^hTո\>c麪n|)Ba5/Xnz 53_SVϒ0MMGjRv/_\lN: Al]!OBh%j0 7d)zyX,~Hhsl`ף[Tgy)s|+%̟u1,7U:`1Żlx|CW@3_yTF;f "4y2|B/zM9Y*b՘C$C&w$2ƈ#ûP=˻Pւ<>C Q5hΧD$4&D&YrғӆmH+qiM9 B;N٭h)' LSP\J 29-.-x~V Z#O[yI_(_v5Qs3496OIÓ_Ai*C0Z ($5H0<^ q 0kO_B  C&uS&%,bq֫- r#3%¡oe.B!yhٝGk_ uAJs+1fҁ])Vi* fY#!@0/)IƢl @IbƐ τ&5:ZM(؋i@L/#k+~H@L~u qDD̄zIKOu2!.` iBRqseyLቜ7S CmY}3#~b.6sUC_lΘWv9ڥQoį$_6+xz{'|eH=mV?.XݎJMo9{/,s ߱='|e7Ǒ`w$u0JrĹ_XhvJb9ύ-skR۶ÿ?mL2_ko=2֊~>DZz^T;cAs?vQg:M*;3éyڶr8vޙwx2"E_bZdٲ\0''KTl˸~)yjaaXiaBw\9\22 r0oE&6h&V<ls*owP'3Ύ"h{)38f-S3ÒY jL{Z`!au$/NmB,'ev1u5 = ZYpγ!5g0# WtwH,Xfcc IӜ Pڝ?D (g KZHFmj5[3;l@RB3?5S>Űl5dӟ,- Z:xBE1r>`]m JH :XH*$zLs!!DܐFo̧T!i%@Y:R$N[dlP.Gd!@>"c 9c Q& TyfFI9F1iAu JO3!c &A9%MP dgȘ< r pWh.}3 wieP$|ϹC5ApRFls%$zoIjY9kg'(|}1c'i9;{o#ϑXҁPq9w~P9Kqzz AKD;|nh?|KρؤHJ"7\LZfG9}aOs߳O?vh?|0dTJ0; ^d ²eu0g] M*`̱˃4F{OD|r{]ֹ:eeÂccىZ 'Ycl_ir\&Z-XX od.GOAҦ%m/;P>gٶ:zV@ʭPV4UfN~%ZB퐪҉B͘13vC|!`#I >8:& W~>e3I!y7Pakj2-IN ٧ "q j'c$#!1!|/ɨ#jF$ gƚs|=DV0XhT#΋3[)N" (FD"!^M0#߃$XTx^jGJX|T@ tX"aNC!C"8$FetBS=~pC|RD}e+/}M)ǂ0Mfk,XwݤZ+ 1 O;ό͙r8{lad8"] %i 2e!$iZp`wW+uzNX*ȭW9FUlk ޼ԳOؼ=hԳ]ߜ{(,e_pUyq\<ˇyP(wЂ][t䠝j Ph9y?(%K~6mžka\)}xw^W/:鈑Jh|= ChBW.Qa*shW ɜOݹsE~}w2j>@.:ll>1wG\m{[[bw `cߖ&Uѝ:yER&o^T${1zac#;ҟY(z1M;G/ػ{tO߿_>1 5oy륃'Yߡew*k栃?2ăѳ0\:aƓ'X$P9o>XԿqjaȕW]t$B oW g5y co}r}F&sH[Nbέ:lxW=q̙Ԡm$]M*|x3;%(å&&~y`˗@_X|;!9r[xۨ=XZ}_?en?zFe7W;Wo1yC{m0Wwwvc/?Xђ?EwMB{8RLѳ>=nh@'n{l?>?]7X{X &ZKT!㧴xY紵,h E-rZA+! יn0CS5y FyM mQoCbsa +Jy؄볥299HvÒPݞ$Ԯ _bH+#)8Trlhκǚd9 PsĠwe"d١I+}b M< +2f')-,9YP*tE! 2B$D1A wzND!ut ,,ƒ& f)d2ì֥mP'x5ˀlv+@S2CP(}`NuiiOa~yUB\ \ڔ#@N&%+L -`B6<J)͎ iHEWTXi>g6oHZSr@+!K^h3:EvԁmHB>Pad@D AM2GS)9]II)$Po4 ,DYH\:$d "yH(8愷IFߓ`tznxͭϭVWz^&[ V`%K38DuuEZ{=O} '+ ?Et+ӾW1zǗzzc}?wwĝHR|ȩG*'2@μ^|y&dy=Mu7-X?0ՑrK7{oJ3d "`eomw_Gjyczļ[F,D_+;v߯3~WIoV&+;L~gIOw~ z.޺yr۷6%qKOO_| __X没;f#R|IwtZ}n2:vqe׳9mǏ\pK}&{͓[t ap;7l{|޷F㇬9o/>ڽȹ+{;Hyt=jlcq̲Sv_綷FP]-w:gQ=+ç|簑`Ḿv5> ߡa5 +~/Ow8/h58ֵu /ugC(ld5s׬ rl̒nhCX饒E>sXSМRL{# H,J-OW9\0prW& M 0u &K(ՠJD' rhf2drZb0}$C@dr5y DLmS@DI"NSgLhD$i>^PZPP% ZHFcl`L !0,gxrK&I0J65$e#8Pi?4 jbПt<9J*AyO:^}Ӟ>yg]0\s9mU7_ñ窏-pT,|r4ds~n=eܻ%hQgw{>%U?Ї/i-|rևg;&`%~h ǒ$edtE L΂l\u.n2`47c4+G; N䆔G;W[iJ5gg _~HuyEߝyϙ*?=lRG_>wFՕϭxsfVc } m3>9}г'pieIǼ}nIu[=s>;hoTw\=?_d7u, i5?K+s67]uήL7;%ff!l]{v/Ve IDATޘVvybH[Hx= J`})FlIYp!֙ _2кGn :|aR\#WY>c|Y$`Md\uXńRѺJ5F)d20mYGuL~_c!g!W^=dr/X_]MȔ{<$Hn-X(uvÇDۚ$Yu mV~TVelMyHG$Ls7bsqyFj {A^(t'E\)P/Q$y[JbW8g<<rDHx9,RG|kB0Eoꄇ2ZVVXi0WhWtĻ;xiC{|O稹Od]9rz]Y\uļX{{̚Sk;>#IjkG639t%NMNKּ ^;gJAL.\H9^ 6#u LJJOQ*c4=Vx8So MMMdþ4?€tB=M8hM5y.wޮe\ 3TC'ς=X.w,YU Oywk9~qC"z ~5F5n?(YV;3@j.o4&О|VM!qoe!,O'`evzR,rZ܏Q&K% MI*tғ7s\pmM(kJ 9WD#,uQay)\G}NrfĪGb-9cE#O.b76)>4! ID0L{I"dD߼~+^1H7 Aƹttr A@ ACohjKy)2|XA8Zb X#Ȭ *C#|?y_+2~]בV7[z9Â)'sȨQ :QPf$MS"I$Ib6`,%Og(8Is?iq\Oӌ4E2uhT#g92_#J/!8 O DB@E;C4 c3JR\*r\.QT*JQTJG2JR)*EQ$Z"8 V%;V֗lYm ^ܸ~ʱ{l/nQ{S{JGG#K¯=F J>%-uxkSM d-pijċHpǷV^{- }S-1{iPO:zh-sĒuj.}$w,Lz{mw Lțo0E DMoZ۲]'hOgP:;:~Õ1i_fz8S]O#IuX] yo/T?_;Om^$Zt߽n(M͛yIhImvLJ=6⃜3caۛe˸a.CRoO-J!} J>v[Ɵx=6K<ɥk'n~'iar*y*,j^e󝭢έoՂ<% pZ%EMOV'K6Rhj$vr.(w1Ѿwf_\Ҫ6Cwa.& uX(k}^'wVNfTe#a958(di&Wl 3zdqO]`?lkO\eU݄ﴃ`e 쐒VHViVٕ 9,+l")UAF|)Yb E٭Ym!9;v4+BM^N@{(%~a­;RyoB Ǿ 2΢rҞu_PBD$g "bVVgՙL^Xĉ!ǵz\k:dP:q"&uhu)HwC(8C$q"D2XѺVA2 Dl\)8n͏;" +)F7^Lq @ &kyawX_BMIy3heQ*`ٜ&\ϥ R`톜%WVJyXjDA(q[/$-%`4BPAd !DD Ә /h4*K x ã4^A( x<=!`<6r\f @|" #y)&T.3$D,EQTE !G%ntf5Ƒ3Js=X eFPt&h2 GxoG, s]tș''WگAg`M:QGCl6ֽ@9/]Q]īۏv6XW7vđ%̿FyΪ^X_:ؓ)af L3.[ү~s8j9':zLJ"upvD P}Gꔉҥοl``4l Eg;.yܕ'N/;ukCt|ziܲ <џtܓ8 Fk9ΠI 3e?P@tyA|c lq{YfQ#K{,e>6L$@g:/~[4Y|ق^@D09;?<(Яq>s;xԳ^e W,{K4z='}qĐs>7z'~ac(74'aKzΫOlOCy5T;˫Njv}튮Kk?b%@R uA:W] f~g%,nX] aNXc M$)4R(ѵ3P[q͙z[2"m|/$JՆ;E5!(WZ19aMWCg>3yPBT Gfq.;LB Cέ7~2ҩ8-ԑQ)4r'D^2Q8!5@$+A9!9szmܢgC%w٥>wXMnl7AWUzn ^f[\oM\rRP^2p$~I\{`<$9?p el(g!9_*E)#59}6 iFImDOn\}/ Ćp{5R5I>$~r e9_AQ(DѦ㷝9~7<-u8{\_F_xh'ֆROOj~;BU.^ 6"%r7`ʸy^'@K@`mEB7]0;y.3i^8BlD/O,\~9~iy!Z6}1Twz&y?ɕIGe\ĝ56;DШ)(# Yݥ%G$ZPIZC/s]'E). wcOxg|oIpλmK6 C[n͝Z*O8"P$"rdS'N8+E%q9 aV wB34(]MB$x(Px$bl1MUv$J  ?dOQW9+ꎬij1% 5 dq IASTDŹ)8IG%RGj5bo3`I ]BYZʜш1n[Z-  t*cؔ ޤNKuP]'~jqN `ɇ\RC! $V?Y$FDh'"!!Ly3)E`/7 `3G'AcKD@wPU$9+"$Dd> 饐gg Tȅ4e}Ẓ(Y_v~?ʡuD>_*9Mюt6d*h2(Bf5m4~;5?Eguжm!tWܯmhi"ak퐯cTD(>u7z9j*4LRįW*Ob}9|TGkw=gI ]pu9frF|ura w gA*bC) 97 ]]<`C@F"GXʒA@S@W[pUA/]nU%4((W%#P?݊_7~XCP <-!3DLm a3쐡AHd垈o[d2RItrzĻؑJA-ztބ,@뾰{zّL|W}lu9BqRޖkӫ-r-lܢr& HAx0%ΔdLIEG"ID.f} SVF*"TD'! NLd 'P.B9DIxosR)v 3"OGB-ow#.ui{it*%H5Vrm-lSqGŭڌCJ[0Ce@TtQQSȶHkahD@E;+pNp"I(Im[{I 2IZ$EdYq@~4SXUCČ K} C &$e! %4岝$qq`8 "!oG zI$P&! Ip #y3( u6aMcDՖӎ[rZqsG=qk74 뜚!^&p*<`nR?(Rk\m}xa}c(Fz#Ho7M7:rc?$s}fU8/IHFHIDZ 1! $1bU&G"#?1θ9- ʢ ^0aM Qo c$ Q.-aI&7əqݿVȌL&!#"L}m0%UZUss't $A92 DPCPdPT@y=pSE@3H;w:{WZjs; Y9ԮZ5Z] hWHf&FګV]kN! bb6Pe[VcҌAQ=P^#SiM4PKI ?wr.,"H9n"QBkI_ 9EK4UVra$r;pq2✘XJgV#AJ1D`Z)5=y;_tnEv %]GNVIH1XO9b|$0ë@瘔]1uxT !ѿ{m Pm*y='VXy^ IDATK'c&3Lf2d&3#?_U zCOI3e[;_Û6`܍gs/ӽ,J߶ou43#`m3 /ؖ́t 8T +{(@8$la*H*)W(sqG9e (n"V7QP!ŒOH)( CɅ0qm薽ؤuZkiFB){I٬-8AV̽( PL@ `BWOIw塑Bm* c Q\@:@臀ӦF:0C%:}Y) ŷSL Kճs{-7@;t@1pz/|MozSYu0\uU^pA#""z0Ab0O@1ʙ{ 'ƪ$b:( 眏W= ٮB7J{%h )@`KIa5A$<-' *<3H`h9.!ZLXB[c &RK[Skyr3'"0@t_I},zCH$8He<) =%wE%%\UEEPU*CUU!L21D D?9s|@ê/:'̩9@@DR9<ӑ"Še|:1Q9ƥs(Y1F{8i(`i#bd*ȧ$MA#E1 TޣLuw~VH ]؃8xUgܴ<9!p0͍Fp8؋j30MtĴHbmB ^], @B$Q ee1.eUVۧ*q9.%K`qfG;ܾ 7W^yeBxƘ1$="O_]1pwAYG+gw QOSI PT+>Y#ȁ'DD`8jSKxq<0= j|'R&X 9xЅ^pNx 7Β7b`Q^Qu$pWD!FeCh:Ŷ Z2)KAMJ !CHaeϾD|C`NU*4rB`ŒLA&uZ'$25JMJRĴBrkQ q)sR{>`s9Wȹ (@! z`8HB2yp8   p47d󣹅pn8:Y\5<: |{ګ~`ЎxcNG~alXz{ ^?kWeYZ˴6P N vQh~~~aaaiiiiqqiqqa~~4ycS3DD[Ln|Gsss0! L> ʪJ՗$P[X~w( _y5`QHs`+ 7zdNpS?F,BX5ol 3T諕e3*7pMOCB=Lh湄LP:\ ^&-[Dw2%7eE!2px)5]qh ?Ӡme Y* E'G#,D%:6I J+|x *PULB4ΊL4 +9Sj:X-%0H2D T)#u%E!h,9/ "l3wKNV;ҕ947?KGO}!CvDw.z#1UbrjNO(RL) \֘\b|Ѐ=u7cZиF.Q$ϘX%xnDRI! ~iHg$\C+WpuYM&SeE$Rϩ3H,F>-bWr^q97"@@琔ZeQ."wrZABxh&RLq(TF9րN5;$"$~mdvLE~#G|hh cbrZb^Z"!5…#,e\qiy],A OE)I =ze0uHA#CͿҎC`^|O< nΟz;ǾqNٶ/pG5w~v۱<նNjǢZ=' q{xs@\A LҞXq{ 5R?([o˹qU8Um&3Lf2d&3T0[cQ.|dϷsg2'hẃEB[>>ֲ!V.{ w ' q Qr :R@J3BUU&8maFsNr >ϨS1)  `9!V!Aj#E1,R2ϓMBB L8Z ׼(l+4Q:(RM=$V_ , @O}#e]ALH@ g:*eL wb[DćCJ.DaZ˿s?5KmCC"Uȡ%!JC<ח*tCRRjDa)  WT4 0uHc$b"g "X.GߤfE1B r3b (0RQx Z$w!:QQn`\ᡆs~oXsү+/l+;_gC4pGx˥c/ZlG;_?j/}_/ś߷흫W]w]wd s=ŗ_mY_ray"֟qѶ{cudwX8.A_D>4>{@D#v)3mog*tG>eB)Z+ c+}+ "DHר. %hnf-~a(fСzhd'|)OO9ZVBÐy^h  !'VԌbDIY,9 OJ)ʤ2 Ϩ h'CtP,bjʜI6\ QY[T ڒBO(<;tGD瑚:v1D2,L$39GXbʣݙυHa(N oy'>};,5GW~?[~0o|_;?kQ;ov_?pzw~=g= }npUzG(nKt41ލ_xOصى' 8OE:ҸzՉvhWxp]z/h ު;ˮ>={y3Lf2d&3Lk~k}Rw>\*j;,Ͽڕ@Kvm޴jgAd'b$PʪHbj$e`b  K83c !0*T N}CA1b{3K 4+@$L`A@dZI$(f$$p129 k&GQUՈ$y{1߈o[9w1y{ѩpX|a0`/&ԤL)@`UUx\VU9˪oC eYnoulK7ݲ|d}̷ݿ|ZkN:V=v-Ѝ"ww"ndf9P_kĘ'ytL,<}h_I`Nb!r>L !i2' fƙMd}뮨l*[egǤ% Υ9rB5  1CUU1bPv*(UUI%/20*˪,xQUUY bk%K7rͷK XCC9Vi" Q3T46L+"@NCT."T10]7GM&MuC$FxJVR` Rk$XN3Yew0%2ɡLE&92Qt1Vd\"U1"B4Vh\X 6$VH-` @d'C&6dgOȚCE$ȝcLe?;VHU3?x7f%8Cf2d&3Lfe%e/9}WgLs# `.0A,KD<߱'WV-$Mh+h_[(tktG͹x=O;&AĊDHOi]E2)PispJw J5GR C5m[:/ gB sG٘' B(X'AМٗb R 1&NYNeT6I#?Xx:h@'nr*bU`dnUM}2mjċ͓#{Ed&3Lf2d3T;wok'g;'":̴@Ņ(@(,eԂ'<5vn&GhMu $H"zp4_)-g,&:39;0D0ʙ'—@@UHK#1J"MP?ǰQ2j$ ѓŅ/x]vl_\X!8Y;B77=zw>|;dJR@.,pxp}K PV"|uk.֡$~KHKAF"TKUT> 6ZpVDv3^\FRUMPH6 bo3EDis=UQ$b4x `Pk)閨]B4FRPk12ML[ƙQ}!Z ,rµ"xr{1Rc UYU!?RNhc-q-ΥvZҷgtdK4mL;pj>V50 &ʫi Ҷh+83_ZVmɼXIjWߦkWwc㏚ *d^7$I=8ZKڴosT7V3!F:;}EtJZB~L/Bo陆ɺ/{y IDATO4ڇ=g~CkM͛-אY5l_ojXg:l›V\5wNШN-5fixA5egn6KsӬGdMH?Uu<[ϖ-sȔ3yͱ߻x8SL"|G{莑}iHB9KluRekwQ,ي'cgJI1@^Cd(at0[5A O?3xf%,HBC\xZ'-,UU"|9K.޽k8Â" `8_alyϪrq0/--s9aUr\~|^((VH{o@Y #l@>Xg XSd>4 <<ng&\ ͤ90~d `BvD VO²3PVt\suQxko.Nya,?hxugoaKۇl"SYӱrMIO]y6w{:UBIȦ[4/H45U`v+l@*TjV9'P#M,+5GfR/R`G@ЍΪ%`ȼHŴRL?(neHki,)֬u2˧Zѐd3B~aMMEk16RKY/[ =vRG̛[A1%]e׺ilSRsԪл//`p rwhߑdwf+L[AW)ke?Om ؜mט)틵gk*jo݆[{]PX%ɳV%Jm/j4wG޴[Zd;;۴0bfew䂺L9O&-8J(f pw˔&VB_̣fEO4Ssm󙑭wPO1=o[} =WAჰ2 " $\QxuĴ0|5!kB}HVPXe`{ b -z#CC8 /]Hqfݡ8XB?!0b0@Э5o=O|w +wyKq~nn~nn~8 pQ"Ixcmmmeee}mmn?t?!>]bEa}z5m(Rz9HeQ*mHM>D#,G 1z8DD=T!‹`7A*nNA$6Ə82",(XUeD ZH83ʙfZ|_n2  ˫GG''iH._bXJС'Oq=0L 0(GD$i,6;a?ˎ$v٭[_x;uoF)\yEywv&g_6`(*apgc_]_/^gw}໡ػǿq?-1V)z%gk{_mxF uճwZht{ o2vvcj2SzM\`ӂ@ߒ`Dž! <5uspn: F BiԸr;54Žٳ>ݨli_uT76XwcuQ:Tj3^!Ggu@VH kw5`%&oh I&WolNfTL[.k'AbNwmr}3i>%QBj9fWɵz"֧xM/[kg /B`j5UCu=/O}ˋi`SW2[8OfgE{>9imYj[2 ߦb0;:D/ǁbc+A"R f*(} a9s8wh!Fm/ w͓t"WaY- 9{tw3W0%t1TΗJ޻ά&1bd}O:aťK (cs(U\P| a1]7?q"Ƹn}hʏ^ӟ.Tos G~# Qb%@ÿxO>b}bPm n}#+wS姿On~ 仚v Z5gwx7}%JS`4=mԤ;(axàO>))6YA :W[oLzJC_jj&H<@Djm%6rź7\:۝tnL_Olb2_E`kpHQr" TʤAZCKigj/FQg-"y3D> Ht1"? )F Xq@vE"wEꠊaD̩*2 ZSiHW?m4XQ -r&#l2ék9b{`+%q *nTVJʴ0Q61,|A]k]5%qPmewliImɆ얊CI1 )>Q-v@cb'j\>6#ٴMtld>4ZoRU2շeA ̆i vAǷ~5@wWUfO+Q0E6>oԛ+R;IKvtf<)SX5A2i}Bt"  GADgzb++1)R DރQ$'9C 8V1eT9({y.QFrPc9+.n"g|s QR[1#Dl ȑ#ǎٵkW]~ډ'O8*r\mlGm@˅h4@ŠpDqa~i߾㍍յM7ݖz:!nQ6т(@@mDk+ؼ T۲~ƼÜ^"q,]` -y|/ɢW\u(w/ 8}^e+FA2Y;H$,vPHY1|I^(B{=hA\ /i D0ͮ(~{Ysk4f 3nޓ$kP-26c]TRw>¹5Nw{/37,^qٷ3Vuף^P;_e_ӘSFM1T2WC1cߓmҎ5wGP[xd6mGV{A56ZΚ­|zv+b9ĐZWrD?T==6uVM77X&FFԀN7 df2uTa)qG?+Zձ\`3m|VsX u`)c&zunL:m9͒t&})@ G㦗Tnӷ욻Mݣ֗):r>ŤȪ_{L)rg8 VT4}wg!a y&EE !T,.U)紗CxbHBUU:ѦX *q[Hx[G 1BtQrbPN3 )F \5  cرo9 }>;/xw/7_Xn ~]}>E o8:rY{>T4Ɠ@#jy=gm&EVkqaVOq[p{i>}bH `f 4OZē8MQ#uh6m,ҩd>M&eNtAW[^tu>?<^P@:"-DlJ層Uxhm JX#f2 Rۤ>iN !Hm?}PkhFuv 4`Hi*kM5m()d+wcUغ7f0N 0/K_{֌Mx4e6 kPDwvz؄ɏ-/Z]t07mc<7ee_GS&.XwMKDxwEKG_>)Ӡkr#^4&zIמm=Y:a5oUJIojQ?HY'ʮQp%iK:*i'eFd()j16 oFDT"*  @5ﲧ/"8 ] !~9.! "tvӒ@&nP+"pK#J!9YbHٙKLA<' q ~J.<\Ec4)Xan"@j}k(Er͝l٬0 :ʶLz-k $3m\b^Ilc=Y,. řN#mI))۝ZB^ƳncT F5F?i;X'R] {v UlJ]mN%Qѝ :6H({驖wu Gu܏)ycΟ;Ԙ|@=)mkF5jMhR{XtoIO o DX`kBS[ӧ}Ok[QXnj=I7)۩M)Nxmu]GyN3"q-?e% IDATh 9{Jk/AmUP3Ԍe*$Gٲ.酂MJ<#!E1Ȑ0=E- sԱǻ)ib#x<ܱc;B1 Ub9*P 1؇Ŏ;WV/PF,6tLQsGAvo7Mo7s@V A+{@ #KDTIrhe3;RIf I3+L P3(ct {}Ϋc*8Bt{1ʩT8tO s,qqYU<MF1DK bt>Cvp-́L#Vibڠ g*Kn<&,r:t>^q%_M?6yҍ=n//ywwGtqK{'*w_>#?rŪij zi@6ZR˴Iolm.Ldm6b*@W{׾l:^6}}B"f5߼^[I޺Ŗ\3 юFh㭪f3ne629+mt6w] ]H!tj[X2%"w[S>=I :FD @υ5 ?QV7tooեgPrLIM/4e]&G4 zZ̻^9OVЫS3&=0er)[vb]kjnegZcUhDiX7Q*m&Nw.pLOچ*SZñ#MVٞ/]C6,]<6jIucfьMFu龹I6H`lWzRwucX tm[@ú&f+k5%g4Bei(g m5{ƘJg}O[vӴAYTUMP 8A[5ZojA4fFUoHge  6Z&]:+gђ_zP[Gi/96lq]g7_\.} OC:ߌ[wMUf [7Ss0}H^ZG!xkPy7t )ƫn Wn _tXYm U 9oP9DCtBÅ@T*EcQv#1FTtL͇8p:zCPU_tMQ4?7sY۶m[_\Z\_f1 WWWO,ۖNw|d\E2-t*y>U`B;orCdWڨ!Lx/D&gje~F!.=kI4v4 {"4 N6@WZBҿѩV'/]d:`!ɛ=yEe5HVrIIպonEB]//gsZ]}i51{o.j+Ŵ\ӑ$|Hv#S{f\H*[̿P_9 A!7Md$J3%R0+E^E8tPQZLt{D& Ũ& D"/7Q_?~b8$( Omz뭘J" Gg1" yUm;nѫK A[T<B9 A3i8%ؒ/R1˳IϲcM2SS$\D"QZU٬ N>7Y琺6钙6XӨLlBFbku?8k9ݪgVПsڭnafzlrgA{;US+TwGȽaMLm>|LpeYN ;],aMb-O8'F]3,ɲRiOEA@^e4DE1/H7 PU_3p"J ,Q% bK16<ՏCq/ @Dbcb`|+CN˶ Օ 9vNOm?MٹO_dLOMqb{Vk*T;s&DHQIez@1*&w|d":LՌ#su$Zj|fEv$;#+-pNYRSiA|J(p(%/2˨z ZHsEQЅPE=Bt޻}#N$Hx ؅!C`w~;tIԸ楞:o^7Dt4)Q~a*/]}քV_bF(-E4}w8,5@̧CY{Ҧ&NRٺ}zCF7(&##;v|2ZO4 ;0؁ɏ2I#?ui=5-Ii k4Bk @?-1${u}bBbadMSj gḻ(l=t,({3_FR'gڼ vm݆>âP0Elx/تo^ti&٪|"Jܵ4 B&ϬWeYE"GP&]EzhmVc'JkSm+)/)R$̀Y[BvpwHLQ1U2Gk 19:q4Q6o*1Q%27ؒ{CfAnҬPJL[lq|+jc%PܔDTv"ZT Ha^U_nf2d&3Lf2d&w>{ y70'QI!ڵ M7x-w{ _J1H1a JL)`M^BG$֨ waTR/b!wh&i"2C0gpX&3EBE8맘C949V HoL*1P1s-ąC N IB` ?1Kd "U" ;Ͻȍu'Kd& gs6- l䶨3Mi]'[%6ԉtϰ1Cd<8F'296BZ#oTyfBRVp%r@q9޳wC!;!GCċ.!۶?w|s>s,ǖ~eFhKKN)ixhh8|b8Hh9rg*#&tP*yiǒ.[FScwVE$9 B`|VLF6r gCrMr %b!UBD>9缶xI^$FDy3HF#Q$ Bbl $X `qŝC9/@ {U:#z}#zwklKþs:n#ѧAa#;l!|yp7ٿO~t8dkX! cht9uN^sd1Zݽ{k9f~yY5Nj9SpzِqkbDY](NMT$)ILfIB~#lq!a[]h]@J~?3ݻW fR4VijW}kEU]@G)b`W8zAs'^ \bK+劉,^.+p'ĞX6ͤ*_bSM0'1WTnIeKyÆ@<\b%7C"\ ^Q Aż4[=m*Sj#6҃<^Eh l)ڽ(lŴ)YXO.SmEMm* [a=qS<3#`؏ ;99Cg{;sct¢8GhH7{i*(o-B^U4γW99TB;GfǸLjDDG٠'kqqDsGAs\皯|*="dFK㚴(**;M=SK#EGfm j/Jن}y{-d{?L툖Xhm([Hk}\u=0[s_TUjz޻V̿~ח,1|do/k.%Zs;0txh@#L` 2.8 j¸)2t@xTO3L^-%}ԫW}~w?q1p7}/ԇogyΝmS/Ľ0l݉Y~B .c(K)V$8K2,m&EK_@+⡾5)*3I]j)6.+35!R.Kɞo݇c(XA@k{z]f1koT]k.0pNڶ\Dv};qP(r%tzI@K+6(-;Cr#D pL,Td"& sf,>3/-O֣g0յZG2Es =ѓQ#0`K g,yή15p)4p*c A "PoFFokPm_\((6T5F Ti&qUQB ^Is5ԕd9sfH7l V)[rzvLE+3̓^${ӎjbڹ*~:RT0lPQC;:1y<'Y3JYL C skJ4ksX> ,U";YqZ1l%5 IDATz0JݱѢ օ>8~m#lwSQ^ë%eTo0^j %DLU 9k?4 #HLٜjFhH!&lc14P?/W{XlGS52U~zjpvh0y~^dgJY/DbT++;9UJ8HMP/;\Rtu{)i¦ۧKKg 4'x  +7lD2 '6hI$Qͬ"-Jl 19(.h3H bI28G6#-VJ48+8DT =})RPe/6jh_:b].Dps"TԎqЖwB*4TDL-:Z tqgY@)y2,zMڍT{K&-^xS `8;J)ia~}N9)yCU##IMQeDR.G$/+ꡪEvJ,}|[E>pw-kw=xpv]?[S V5(Te3u`}k|7_Sq P'Y{J,O}^PծkoXlPew+C-BDm˗n7l'}okZV$J6Fة\] 뒰JB۪.[*BCCDĔ,G6.͔'V/ .-(v_*o]RT2&"PfdNj,TPS[K%6-'5)B)=ԩSɖVkė!4 "!". 2̂S6#d Vw.񗷟`cͱOTBU+j+5zjnƬ9iM%}}@{"з%Ҫl;@s_o+v)mQz|bwHŰ8惧xq5S.o.RbZ&y喑VMƖ[/MaTe{gm[X%Zc7jhh#"LdrDٕ%-*JWc((K_ڿ~/5KIU}g~_D~?x"/?W>8?8MXamS-D TM_NkBj^uR@YV2sA=vd'+hɀxNDc==L`َQbat-)zC.N'@"]f($l_GQnWib}"F–DX `DLEsU?7J!eDQ6ds.:qieML]B؀p.ɪgUɓZ I՜F ҧi`e"LVRqt ,,X@}sֵד>HxOC?9rE6'ZX6eJ_$%-%2Kz7Y*R[\Jփ'lΝXԆ^|>%oU+W"а$W0ՈgKA+Ә:*fDA #^Z45U{0/.}EDaffvqsQ2:@;SKnL< YD3.(ajWvfY)2kw_ p7^a[L%֠1]uO޴\)JE&5ҝc|ypD0l$je%TME[pdLCY &,{TSU6jeDiFD-6)"]WUzDyS4*RJʜʌ )efOqT6M^"R>zBq-{"adB dӯz2Utx*[9Z>p ƴ3|l ^ȦMǕZZ"kX!%:g]"&noX҂ H8 yUBdL\=HmEd<{ uzo5 M([Ͽyq%;zUˎHZ >#i]kّNsZohvaŒ+Ufev [mW~E/#Rv1u&,Ք|*޴#e^a̐hP3btRhq=T~'A) P5N[yKLo};?)OO/uqO=wo".*%͛=]t};}~2Et}.mwgM} E@W{)(Ig8+݉il~޺bƥ24O5%]T|zz)]`H=>(c˕jYwT!tl%6ЭFu^}漈aԖmuXuyγCUebޢ 뺓~$ڏ`4Oyis:]:^z`m^)y?}*Uӓ=ݞO_a7jy}cyfן~D3R}4K#wl$n nƝ5) +U=%?iU Do#K=ʩAX@+ žkdGvw㲶S#BTGwZ?}XR3btڃiѺ:焀u@MN,S#M+0=| l=VdS ӫ#rq?$J;\v7 rL|ư( WagZB~XIw3z\_&2gaW`k9kXRt9׳x3R(ҙM*:"!!QRuy*j'D<9KE4ZN( )wݼZziece~m-q#Z@S s,Gm57o4QS 4Xz6Pmyg*U'1q1BOb<\ t'N~VkЈ%UeXQjo#N),w&ةhboUWzU;><֐>~9mff`,iDGOr`vܝmXG633;;k;hfDM!ER|273F6e㸐=1 ċOO`FJJ `ZvՀyvQXoqmVA7u1gge_ѐp K:AP %4-DUՕ|,3$1-J1MfXs7i<( vg1rKT&>leKla4*Wo-ufc]E.4A|Ԫm3m g6t5 |+NMTG@F/w2K٦|GH"[& /FE $~AwB6ng5= dI^5}5eU Zc5H5Mo%Z%{߈nkҲrKLU<c=AU|fHaghyRLEVXPQl#-2cjhi푗y9`+]̷4d9g1-OZv-Uo"xyUĺ??w??i>e//`̾W_CY2llMwW}P$$Bu-+%PR.DѓlQ^H,@E`"hB=XwL}UBB"e wRl᥸p+GTu?/uߤVE=R-7|ѡȃ xX(9bϢ,|kw O/jd^D°]J:.Un>kZTXvFЬ^7.E=_3bwCr"&a]XT'6yPoy !0\G 7 '4-gL!>Kq/-EKF?Z#v ^93͏8H2˫eХaqf$Wr~ݼI8!ftVW?.Q@;(|DĆUia ZS!-Q3 j9}H$ňT*tH;;墲FU+Σꜛ"?S59&'{Q5؛˹Ts:#B;.C00c4H`[BDCCZ^3u5&`cPKNBs/qN퍴l*qR݁0])dk"iffyƖ3vD@#PLډD1)'l(Ra4cK;IZmz93?%l"djȎ´Țnsl̅uO-1Dʃ}bC9Mx'*'omdMo뼮!udִ(C#8 d zXͶ_+ݹXn[^-P(MJ9#M^/=ѱ<j|ۗ4$MU'aӗ˔Hų$fe^*$Zk4WDw֒bXUpTHQHt83;ã<0lS54aQCzEVEpӚcsP:&FqHYIz̩TԀ*ԂEƧYF@דסr3gG v tA{d{Z1FoYQϹwWꊪ.t׭۞ݏU8U%LM67*v ԒLL[)5mH\n,ke5z-]LDi0qs[Q:Dׁ9Mp?xfMk`_l׻i㐕[P%#QAYIN݌^jo%O~vUV!hC%NFۭ̆<|]f4B%[QsN@ug`]tCa_W>_W/?x ^az7o߈}/Sێqc4=5"{?{>Ry_ˮsW#6cAE>J#KOU,M\7͗BϮP IDAT>ή/58VFۡ.gTq1 QL̓c xC}[yQG l C٥ Qh +;A&i{[SdmH{ڪzΓ_}ܢ!,YK6{uJ8 ft"~wQio3ʈ5T:%#)\^#yӭ$Hƛxbyf^͂sHI"RѯԭK]I&J. @lߝZp:Eu3f&lXTNJ#iUQhN*UW^ M ̔:DZNlXiꤨ~kkz)ΐ򗒏99u<ϻItK=jaEQd) G 2Elj"$[GQ̓U;yv×NC(-Dblv=dryzHJqr i2"}M۟Bz^1Qw">b[%ll_܉k4yq)#Y`ŇDc8Vن#Rﵻ+1Z[Z~8]O,=tOA\FxDi53G>s$4wy*vI CYJHG9T#yL4x5ܷ^D0MߛV6ZꢟI٢m9-!ڔm ے ߮YZ^ Ijv#!0!w<gl'7eStwy*A4S L_ ԓdc#\Sd';SK-ƔR uZ߈NKI#^l/Ǐ4["W|'/LP^dXRo [_V(Mࣕ~ގ>TY+eU&|}ѽ59ٖF8W^8vn/] }E9֯qYٚ-zGh/}^J{M7c-)!it! ۴E^!2q./8Pv i@|yD/~~7{O>TD}~+_1޾}/vQ7}'?f^﾿Kz^!-f/wLYva~Rs96]Rw2j27<][7 SRys3J.Xϲy!ΌLT%G Q@}D´n 5l%\T2syy5_ c."uj1m삖I%uBwE tOsCS0i 93桊& 6 VPe:!vi";Rgh+9]8V"jH喩IrMvϥ pMևgt*Y̷co1eX yPP4L]j$Ш[*G:\ 6F7TL1ۻ*yY!e9'*{U-{NDsw$WC^6s~0HZ`X3k-7)sRF&zR͡KϗN|_kJ~f=c]mf!zϵn$%eܮ#tl#;&6_٫ocST!dt}q5Ec&m sѭ#7T@, 7[ώL)GT\7q5IZ. B!:dl\1U>`<(RU@tX^Vǚ*bǑ{mq*:Ml?)ZEyRy+&ݰ9d"ɰݥI۰.vUM@b. 2&Nڞ"P]Qd#OXCJd 6 2ISV .H"@VbJaY=[(۝/!,HBhn@d栤ۣȚݜRQ .;0ը8"و$;Mte,kiZٺzAC.&bZ^@V^BGQS"xn%aG>,{_6LV\&WWRW;}kKgu MB2A8OhZن}?p}K?7O.v?'z۾+ׯS @}NZ.^{vRм<}W{Ts}6Xg u[xjdŰTj_|;mbc라!]j*E ,*R1wuQ&ֳr?VƮ~h0gC!%{ !Qپ~(^OHFO.{wbFK0Ԭ njtYM>9~yZfH޽-[uT UBx6/']9dWǮ7r]Mf˝-aj:W\EDʚ،{~}.ˋRGmNMT&ξ(~Mw?>:ƘSۓ~{}Ng7o^>׾|?~cثW/_ڇ?_{mzzzDt= #վ_.Ͼ+kK:QJ>R f}㐐[ Mm\%1!t ףw|'W?.l:U/dvV8TXcMC@pH]h>0W*ݔ&1̎q<ݞDk<ԫ( lY5]G3"VsIs'Բbi5V?Q1?*;Xf6pʪ z&e76`"1TΩkjWD fUxUttIql3F|F ul+<=yu}aǹZtc"w^u' ){wiQ#y= j17=B9Lsy/5X+XԸ EİCiv1 Z&zdcckgRʄJ'YK9Ra:du>s"^Lwz&F^؊B]cF3ցIfz.^;"@ -n:;JKfޤ_brŅGhNM7O){,)Wl  %몈 l OgV?1ЭH8w^mOrr`buQb"HnЈs\hfiM.n,6Te U"aI vH!%56)hIziĐ+UQ {(+,e @Edn?a`N~[4Y.XKxln7y*{I1ܧjHSkgQ)4"091r}_7~~׾7/ѱN3nr ^|泷'?ǟ}tDyv6OLX)+,%ymQ >GeQC:w?l yZ>et;H(arZ͡*>ZJ ÂGD-"rzC9YcR'{D'DlΏbN]"am,<QppqĜ!Ŗ8n7u9p>̓ G.G"YYRJ >]>nju⿍5-snyJ#%!3"BT; SA%)[Ĩ:k)! `N7jx2%j0`5՗u0=pDL SkZ^$"iǠY+z͔UAY)B!SQtU1:joFX8qV[ឮK& l5r5ZebM#>Ϙs<{ȴyK'Y5\Uv۸q)sNTՆ  tsT3/2QZ1fF`͞ϪՑ?RqmـHMӦ0g,7bcMkb Ų;DQ}"#ϟ˧'=ȳk0okmY̨(-Q57f}T2#.ޗEI:r03:1`\}d"u\U[LsFՋIm쪪PoVzLҳNJYLƍ\O5+/ɕyViZ r=~Nx U=ѫH8@޵6-l@͓k(OWSx IU$j&tQEn 81'D%neࣈn$n޲Kʐr4X 4m2ΞSTQ9Dqn+C"q?I,.Mci!".D$T4 (06Ր,8yMS)bWU/V4^Y)rS9CqJ :<q'+a T uܰF=HT<쏩Ytd)1By|(o[y4+||KqlYik{Uͱ>gLՄaMus2oY .s}u ӥص0~eQ|捪ʰq??ꗿz_?|gOgZATQp$% 󕸅*'T~W Oȷ[Jg=,u1UrL-_A浅؋֧i)r{~&U/ۯ;m"b>%U#Uqlk]QDV 35X44.څJ|()uSM}\ȜéS\TJ 7` gb=ڸ{h( 3ܳRH! +iJ/:V`GI3>rSrNwW=$% }R}g_@uдTJM] >&ˍZ\&/1AA{fya.K[maƑp6f6E$  }vd]l4X=tR"r[$"%Om+f*M0[Xƨ0,=? *> Uc1LCgVPc 2E5׆ٰ'<n1]QMKXv}uw^Ѭ 9V6~ -S["厩kpvleGJpEj9JTb%tum<@5Ytޭt=uictr拻rsCMJR D%( Bv 󶴎e_ʺ*ksJO=If5Ǫ>"<`}BDywļM˿(g@D(I.(Mvh82Z<?ۆ4j6T IDATΙIxke ZU\P0";|Sz8 eD[96ȵ7D7=fixn-@R>Ch܊va38mim9}^}L{GPEzתROjUA/EFra %ο b' *Gq+2'_O5L>|z"z77 9h%wsf6ND4Ԡ 2r"x%O=/!gRQN1yu Cg,tNog#wofvvs`պĕ'|j9ßal%X$͌`Ru!=%+) (ՔKdL *k:QHGD[DtJ̘j8FsP1n't{tߟ32CM!kGpy;Xgڝ2;'#gg5ixG^mΚ$\5;:K,oU1tvcR$ jsŚRcrHyZ U dj5[} T γE_`P}Us^nFE/*+ȑϝj^mR4[*b ޲F qj~iV)Rfix~.xK%Fw[]ddRM .TS-/K1@o+)""xR>"(JUA&}F ˾ŀuz2z*q;֑D?߾}/r:XZOw1jyvj9wUS씾"0DQFjMjw:~GDgVyj YVH@O*ݢ ehZwwRzѩ@v5"zS'SdYD xt '[Pcbw@.+ϥ3 8[>`t.aBgILZ4^aSM6 ATErF,y=2Z 徨HP\<ٲ,wXK*>rlUU9τ xQ%T.b+C̨ ( 9Jõ0Hf8.[o}]Ї$?TbR7eR\׺}u Ԧjyq /\3(+gp2R;`=j:ŸL^`/r3R3jm D&Y_"{1QZ4QprauWzXV͓{5rmw&e^ʁ[Hiؒ `N 9yweBuZ *n%wnZ3m ?^\@QA@X|ϐ &Ro&- *t|3;D/u/թ[IelB}&uwǺݤ+"9h[)n}aO߷ceIOznKP6V\Tnp@ջ܎jFMD㠮y'!r06Wv {H%@M5i(2^=<#<#%[|bV:m*:}fP! f1%Ph棚9 &D4dTXw9s&ז$s~p "d(-,wZ[D0,[,Rp3ݜ~SEDun7IpTeewDFDF[=F*T&2 יv՛G[]"(B"if-R<EzӉ9ax=iH3/q;Jir]XX8TMXȜoS՞TkC99[^Ufn@^a!0Ŋhd.̀]PtϞ2| m5{: Z%< ,`!0SliK[ c po 0FTԻ#O;J u߈*0u3ܖ: )z{ԞK ^(;aݬfQ3G3#BJ2C˫1I%a;S{+E!Z1o޿~W_'?OӾ 5jDue0WJc"G˘Ttu3@~[sjTTMrpR\w\"JϠt汔Fj.ZTKmۢv~JU`GbiRbV(D@:6d O(ӍJMJr6w-; c`%*PR `2 k?8LK͎,v3!+R,ȩ fF8-!BHg /UG<KNLR0=UrGGtLr>~u Kwnjef("䯺yÇgyG?1|G__}w?nG{,l0};~wW|)~ ($ #?,301)ɂ \W_T(֥Ru| *{јBQ0ZR2З\2lit#Z&,}N>MD`7w2*%Cpx@fGuHx=XV2ڪ:dU5oGЀԝDDQ^+Tʆ:جeA.&G #Ħ4>D$7vVo ڄD@T- %$48)*ey.Ϯ8P}Ntr踬I6Ql{ϹLrXdvY!Hs 0,\Hs B))}-:(#2C' `m=4 <2lT1(&(+a Oq,('SU^S ZԦmHddi'!ܖPJ3Y+mfVK!* "$ձx$ 1J(m*=_hu1R(q"t.m,kB|OuE*V`0<T+v}.,&mWQ3yg}{E2/W++da.d-4)DVnv雗@ۻz\T@boY,ڳTML)Km'It73lR=H Å0ۋ%5PM$mU$ƗabSS_iV1t+ԀH9:?a;PURTwePi!$cJߐaxsζsE$%S+]c=1`v(LneBE0&r] A<;^[)~}}"#'(;gr] 'GQiUBTELWr0G5LT'-p@2פ$vqI[A!ʖ)Smt`ZK|]zmzW i4|*QP6nӓ/EˇO]G`3Qc(TPԘC$:OSq4dLpP;DM?Ut:OaK0c:*mԒ˰K!D-,8TL%a%#XA"#L"g'ofP7n!`^yy#OZ$@f?'uaE˟-&Z7Qs,Wj1YB v'KP@I%^Œv%o7>DM;H -A{yQ{|v趣1%:iVFѻ㷐EV<4a}KrmRn5!6 9\_uD &*q?߽{ÛwaB8Xj2R.4&}9<~ĐSy.fvt ;+نE>yB =r>VjN8ӧ2UiZ|ӰVDݫ2QƳ4pDǒaliou䮫GtM>ێMcp+6Q(U;>V,Vа:BDGEVcTsr "ēk̎A;VX?]X^eh`1]I sG;S\8uB! 3t[NHXrDUIgQmF-OoTFz%gtmoj| d~NeJAU$Jh|Kh Zw]==_?>_y~m6gs&Çw>/?d.?O_3C_e7ȎW]&u6=u< 4 C<|JZ&+9dYfuWy憆vjiɃd+B8l$Ƭ[oI5%tΪ0gF.&|dϤyO57m}2˭h%'+逋4גRUb,p4V~'}>a,nvG5Oy_jv/!"~m-dŊ{0bTk Lbݝ jvu77)^0o%4앬~d!bݢ"9}~Ȋts+Aˤsl$C:9+"UU}:uj^mӳ@rk+Em&hs"1 C%fs"Ԁv>, 3ptwX<q}8Qт9beMsFaņ*'m2F:sl 3Y[wqtL@%wGiBɐk2ԣ 1Ԟ ͩ%,Sf48(3l~܂UWF:q"|q(*>;RҀZUi?E[ۚd,&JX$z\ɅӔ; 2|0TbSTvaJF?(Ӓ,.8,*%Ze2I[Q &&Ob@a>RԺƒa><.vbyJDE0= -~mf}ћ7:ּU?KH@Jt$HLDjEVS[rA$=/y+Lj ,;foK>:V~PY%hZetijo:#Дyvt'c*8^1=Hc)*zi{)ݥwȌjuA=$Lsy$"yR毰9+v$b:TzdJT$DFD j^[J.mJP. "ɍ Hu^)Ҽ^ِ,u٣tj!\v͞Ɣg BR#Bo{Jଏ/ج.4a#4^OM\`p\ŬSwyͮ NJ)#s+(Ḿs&%ws:FJU7v&[EwѪg.ٯSe,vTfmH7!Gno޼}aKj䄧~ IDATbɄTe#5k:!SqG";hOA7?$c&pFycV?+YBYdLUк.^ r|dŐYӢ'E>ӂr8)!__}JOp"#.@@c) ۠ Gz\߰2WIp"G{ 9(oTU>/oj!:_~v^4Çfg~_JrbEl}+{3 h E:[T{n.SmC.J9;')9)xūgremC+v jo+N]Lw6\tm.< pHA[xUYRr_OK7å.3Jqt"tsbjbqR;Ps~B^L7o]$yGݕ z72TYGc͎yd^^j4Ui`ݸ#P[O4uUd3%%"K.E2_T;?xؕGp3vrL]f%̔uy݂D% o} U`6( `z6X{/˜4/U4.{W9Eo B, "yvI=hYPJ虏1K3 p9^V (GZf8" *c j!^9fF}єmAI,##rEM ȣzV):2'R4k`I He 6vآ._#[nK?~.(!+oFYHGsҤ`-ܥ(Lba OȐ}&U!4G$yΩ]ʠ`N!y ,}V"B=پ(cH֫qM?WUB%"tĔ:hV(*aYQa}K:D]ξp寕^u̫?=S5Dd/GlcD17o^^^nۇgݦx? Z9澵b/2"aW*HGC.9Ё+֞3L#$,\?0+i`StyLK@L9R0[:%S[(ųljuhGhL0am'ۂ_+kکYonҨ,݆=ZF0bb:8D4=4|DjуgavF DBDB)$ϖdYS&訄<*k*v8*p5[E֪K3*3sʚF_4ϳE% YQD1Ўp똟]p$IjŽ;qUsѣkTA~8Z&had5)h.5^]VT&gS:4yw>_&q% -]XUM7X% 0iub&xm""s?cX *wyV$zt,ED"sΞ[.N">]$ϽVҲu/yclʨg[D$K] 齲FNMBfk[KA0`RdxIGKDQ roND}2Ag8sb𮩒uڅ;'QUebJtܕM.[Fq6w%<$vlDU29!ܫsR46ԝ A[3 O*!#1ќ=QjׂgD>ˋ=hy>Hhw0I<.$COŏ7ʞ]#BND 6XC^{D"˒dQ0x < &[E?.yVڴ[Ӑ&M>{GV!!0m!v*RXwִ*zSi, HR~^^ÿIc kYFbҌ_av̼Ȃ[;C)3/` >j󒞗 ft3 BzT"BErQ (M WZ<|8wM_/~ǿ:~H73dAt;>/93y?g_5W?V!j 5KZVf"F.aу$hCeO)ZU&\SeUt6F =e:!"~9q _~Ÿj妙f#5|mf,)CeJO60\DdɨxkL͆{Lq3ݒ)ݰ!+?=Oif=Uh:hzVG:6<"36)pϴ8l0d Vʍ54Vcޗ8FZbћmvU Ň\brtvqͳ@CdTWOVq$D\."Ymn 76]-H"*l1TP we9ڽ$=mJ0LE}= * 9Z#gfSr|{1"8U='"V} :q,L1Rl&\SU۰ܻkiKꪹy ~5K$mH^2ҀI)dmk +coA`ɲ鵡'++vS;۠ @ts2D򧈊EL>/,kWJ7':lk& WJO ̡gs@ -=BHu.[yF  <&}$;6w*RJa1%"SfjXjU k. G,#F %ư=p(R7[8zrVO Y/sy5%@`pfX ,, G0zTW%f*,w1P_DUF_A9жԿKT<сŧHQU&ȉF- 5sǜcZpjmJo>U䩱15c΄dm O<2RbͧLj21 c>Yڢ9{@%DO.1%²)W'ɂ%:z3 =jLYwt|ãJdX!*mjȠM1dAQ7]=Ii%3ShΈWT,=Ə3H\NaQvc*94P4l=bhj㶤@EYrYD#JGU@Z0ZQ1(Kd@{z.C!J=]0~]Y[Eݫ<[/1E^Z/GBFNɴ4Ma6,p􌪭hZ U`RƯwV~y05u?g{?o_~wߍ/}.BO>s_~">蓟gC&Eq G|׎mh.@uf+[$}w\ds$rE.uJN=<@{RGAqA;;m1,W帄TЇ1%RΏ1*a.^"2l ʼk[ssiSW~e 9W/s/HjU1;Z@o<===n7Qϗvv'ϳcCVW,%|V0|H8ꡢ𾐑h)d$褌鲳]NV\ WU4"ca)֪ٮ紽Ĉ89lMswbddoa0þqHqtwfjɯMXQKqRZ!˒K})ڜ 6fgĊ3"TFPx-I5LBacXRV%|7n[.orwD$OZPjvGDdf*S1 lKqG]7G-phĚj, 8$ [Ml" %Ju a8 SpHߨ}4s!f'02lZm*)5d ڃycBCZz-5rMu@EjEL0lUpfb(f 0Y[26ԋLvi,KEPX N>3ˊ`cLA+GqhYGeJǤ`?GQp:R G0=xTGrRE|9v$ ҃vT{TqO>Q}2Hu` ËT3eAQb(aQ饬!P^Z4L YD6 yνQ8ۤ," T$@(B .}/U=GP&?ރTTmiKD.&#B]&S% ^hbUĨ΢dM)Sw?{+,8RFϔ>U]7]T؅g3su}O91}hooc {^Ka| z&X+YM=oNy ޹։j2%܏Bt|1afZģ/LE; \5l?;A걩!lkg.|)QBpq(s(%?(ӆP0WG$H38YIKNX["Iʠⶑ )Pou M/5SzW_}///|9GĿ7?|'Ig?ɟ>s~p*ʮ[&_dPbŀY8%uÔV PXցŪHLu$psveaUpUN6{>+afJB24b5,9; j%L-.mbq#?_fi:hca*Ynwsd<$>_fş2@0)th{$DDSd)֒TU[)Ik2^lmF qi3눖(1i[ҒvԆԈmlBh塶ٻYKudXlYN6lı-ot"6HQ2`lpF.آ! w Wk ) ]bgAQqi c2u/mh.cT0<l /U2}#iL (Gt\C`OU22~zT\k5҂jR[g˖ӮnGvޘc٧ X?G 4F;e r!;<`ϘM "Wڎ'6x 22*}X/vor skz<F;QUr-$ %ibSn }B&c}+'VBDjpW0S6Zil07j\<1xǪ2,wއ n;E IDATs4UL"\2!M`&UP2r̆ ZZ5^P@bdz;(@ NCьU=O>?BB,U>R: [3&*}rT؃>^LK/Rm =HT<քJs-<j#g 3\NZWM%s^^gRŀ*>Yt1{IkC1v"Tu/RA+(b׹~O_'?~>o޿0TU,"ן}˯G*G??+BWTBG+m9("-C8 3 !Aqf(&I}c9CxDz\t `98|UL\^FR h+ DڔKvV:UquJp5eQFxS)\Y/}V2TgCӣ ʄ`C{nyF,-yCmQ)N㚋b'*lS2un )&&MP9 !b[wi%B]BZR]NyчhZ⪄~V: 1l Pu˪ٯT̨cb'Ut,\}r/X"< j99-RZvhG<%=VD#]'Gykn9J~de$X@Ob׃,`Δq%c1Ƴ+:2BSÑ=ŠF#D ֥z FTKzIP<[xrrCb%LWᰁ`.%duGtbW.=z kΙRXrY<7L;!/_4"D ުi.0θdh_nৢF!>40m_BfNap Ӌ^X-9#cp\*,#~tKlgP؋&L(Rrs&bsdc)"I7Հ zΌ (bǡhјq"i3lTN}Ίw (_s~&b*tIbPt"ƈSy'X#oɜ8$uVDj!_E2ҝ௒oi~*Gxdi*͆D߀zbtPОHZLUKe1t8C " ]f2̙%{ OVf ͋ R][^ppxL][MЃ)`0IzdU9(_;i #XǂҊDdfq!2w3RD4']LԾcKU5ݻO޼yzzzӻw}W?1|//??~篾oYuRfRENmW1hX6Dp`f6Jv*e-\!8SarS"*ZE[C qX2eYDx:#dYƇ&/s+pTמ۴Rz9ދ^ޒbA:<K7j̞l!ݧi?](i4rIZ(:-^䄓,dCp 82aeQ@Hf4%0"WRk>10"V ( f*T28a&#j`!2\ig6Dp?d0хf1 w2U|wʍP9$@؆q 4)KP^&F*aq`۷7ˋkP3+28n[K<-3nOOO\vN߅s>CШH2Ɋ[mt.*uYfGo:p3㝥"x$"bYF۬$Sͻ{q˚1N4KVȪa#":%@7YgRasW&|*b@L T50P#jqL?0N"eq Ap8byN0Z}fYw#nXWTYlTǠ.* 7Qvq'% KH99T-R*6̂L@QO(ssBpdW\-E 4Ü9j"w.,"OOOX&`@*aDW3" twSÎ~ٗ7繡8x9M0{CBCΝa.Sb3\cRXIip>+P4@c^N{4ѩ$o^h ϗxF,Ă^3lˬh]3RL_G3 0@H9T/dI@+N[+R}$z omOw327PGĞ3I#m1Yc. ~, Nu)Ďcbgj18k!9ԭ, t5g4u 1lt "~*qU|OOO>7'yj"Ç?|oz,@wqs<3*'1tG""R'@.ߚjfSr|*/vޅӖ'1NJ[4MĊ9%],"MJFZ'b.P_L i+Mu5ڨyE+鳣WʬѤR ʁf)utV}{Q:; Glo8Z/MI2*=<<LBcXuM&CU&u&*{v}!@T$UҿX,ٍ :0W1Et< :"Bյ0a&6zy (1{އ} B 2iIt* ܷFX،UU7RG-ZC"E8EbEJ´yV%!S1|a8\Hw}PE͛7m'h̜`PVkj:6AHP"H56Ьپl%qb]B ?jj/גznjÜ!1/?O`CSL~#~u~K&@;ы۬"CX;!U'@'&n#Vɏ_iM[qdȳe4)iZ \z-Vg[ks[%~YA[u˭[8h^/8*#X110I aߛW[w*)G 6#{̨yiםE\R 䊲u^ tK .Pb.෾/V3%glt>I ǹJvH벗) xGRFH^/J$qd0!D0f1/-B$ _>yB|K*8b__8DU=Ɛ(7~w- R%5 aυn>eoeWoq:?vXvRƃd.pQŇ HD<ܢζ=<$∨#|Y0 $DdĶYRs;4J!nm9E,Mn Tm{ ]yQVJLDc9V/I߅p)$QU wLO,k.ETq(aR.ĊӝT#H:kīT];NU, 2Tf=#a4.nީ34E+8epzdKdv>P'rV -϶;ND:lGT&{$@̆}Zkhtʓgl]bP UtOTB up>0c9~яdf3!gIlf尝/ED")gl90T5};wǖ`ۋYtH:< <:_ڇjB=?z= *Sum%-=_uΙYl$gH2, Jb.[iS `wv-W\*նD'i|" uW/6j>FB ; o3K: l *YS<((=1t+E_ `@/  ^-!/u._~Nq0>5{WKl)V[ݎ1eTT!ʜ~пز@sZ;V͌b=+I=]ƴߴ-̈8s8Pw@߫EH!o/Hhx%VfvܪA>*6wOGyI-@0sw$tf^`vcJV&N^/@wIkdv-DÕo^] ֦M/{|!|fl%CE X<]>4ZĨ˦\\e9ۑ7TQ-Y*b?﹨$F&HeEkILhEjv@Fho Q5H??]9ڍWf1|´ 05 Ԙʋ8LuMDBkZ4$oYl! ?pK(?5i~@xmiuE,!iJ̅=٨x <3gqXVX+=OK Al#ď*m{0c hK6S9fĄ 4xZVg bI743i~]]/;izr"j&#To|z? hᦎ`SׅY2O݅D$ @_FwȰN^P6(.k'm¶ED/~.\K~9 +zf}7+ 7AzYD L_RFWU,F-*k,!{JQ6H<69\ڷw/k"#VUzm0r]PsU |?PcԗJ!*ݭFC2y33l'"n#˞s2/Q 1gtad6SOTT2_Yd»sVELLW~iADƽ;E1V"\39Yi@[nWCZ;R)@,x& 5U(!cTwMB%џ3e,+A.:NaÔ lNlnxl$Rx;z􊹷,UdX899YgX HL>VWp ͖Y`RjN}H/jSrW,Ҍ`ѪQnn)jlLPhV9*koĆ`ݘwbb-RW( *۴ک=(>nF3 yk }/,?gh\XX^V6PEvt=1DV&.蝝 ӘQlHgJD9tIfWtb^`fa2d@ ݥz}k^q%]Hg#SV§{ zAIF^M#n?.D C/%!/K43"AN{ ~SaM1\DK\Z<({ѳe15UzV.3op̓!=#FPE0^d=H^0۞ҳNelBgUG0\?^>6paVJfrvwWWwl>yA,2g+}pG[< Q]TDWjTխDZ*s q7"hofE^25]t+BQ>˦y%D[fk:E$K}yyru@D“>Qпle,X35>\PX[iW򈤛3*.S O GyL;)#nٸ=','RFvVxSE;ϽcZulU8yx`Ah$K=IXR*qly)!EX 8Ҙf̈Ax]e3L8aؗn46K`4D 7OLwC"yvOI7sAu&1RK^IDATlɬdYW,:ot5MMC$<̲1(rE+e690g Ҏ o ~11{&V5Zm p hZSeqqsV@g 2t<ȷ'd!*Nň* Z(&jE1l*Ϥ&e-4A/=Mcb;)gMJ ]} @ל>b(3MJK@i>fPr\ez&`EV{' [lN%"+rm(HZ(,_Kqxh# @ɖ-Z MˢXQ3L6*QeФV'acfCD=bYRh/M֗ Y+#2BF:=n$K.`} hOwnF)(m xاy$!;G_8xe?ovt Se0~#CM]C.#6ᬚe^"" b4LCST)sYQ1V}A?yʃx1x2n\#,u?/Cm^Yi˔H;`\JDEoP{@]H`B&D a Ŀ R|zƭݼBDTtQ{2/|7P~~r/E dmbStO lyCH{dM~B*b %kUsieRI)PLUQ,pj!jRU (%uY ( !FߗMOix#G0yIvVBm.yʍuKV6hv,ٳh/I;OfieL̨JJ:!H:9_ېn$!>LUhfX4Գh0}f4{n5 XhēeX"gojX,>]TP0Pv]Et86&-r:#MĻDv I]#4fuoqz*']xY?EI53ݕgR۲Ai#3[0!>; ՗f{(}dXQ%>==edryrIh%Ug Ex_ꦛOqiTAEeyșy&<Néc j_"Kx1̓2EvPjg!TEˋWb͆˞P'Cpm![(Co9DFL EсEt08)LEuHg4$ gn"nBcDyb_/?5S| Q,BHnjXdb)bZTƂٵwŃEKG%),Cb\/ZPUpP]ZVR*!!2rLPmsHrLzy`沁+ѧ!7FnVj SʊQ`m[!?L,<\'ϑgR"g^]jH`>8-Tk{Ļ*no-h;˩I$!KgYonu v[;Hek/|CI<ܜ\$x' djf@ϥ*˾1poۚH$zNҼ(ͳ$j액%BH9kR9CuJ ThZpeZW]&V8RϸC,)RB|cnrOf)X2v#sf<Q'YԙjID]#D5:ZRf>޹E-%=tmHȾ-+Z,jRmN`ﳋ,plCF흹RU͈F}oJTYbw"[ "־%)E$ɦ.LL!*5:6$ej#RM{qiRT;ve֢Q-b`ٙz[0ESDj2SH"$䱗WTP5f6g*mP !/:R0[]5KXm+.eE \7yR5/EKm"D&%[6ҿa`j )@4 DYA2nw쥡R6Jw{AVYWzB-Bd)y'zMuwTy:հT %~jm.іhcAۼNi$cwYK~8I %1~n.yTn d㭛r4FLij-OIyv4^.\".FVK.\@q֡as '_V%CZ 2w' Ȟh"8hOb'lT?+."9pΜc 5W8&Ÿr\E~HV[_-"jr㶌z-YS9!os=* }\hgB2q{#p._w-pK$`|lpo-}Ao&RQ">qov/gP7I٢ UK3j%""M ~8蛼Ӎ9PO<&08_9w ?EU.E?<9}bnkr_jxEw¬l5UK˫gaB*Jlj#Dܩ Ԩ̰m@ t4Qpԏ_Ԋw!=," ~ipS+ܵ4VXER1݀)kؓhwʺ? % + lzqJtEZCfJ:0{jdL;%T#W!YSWJ|nښR͚YNGn`oSFtj:d=j ^9 I?UH $yiqf-3I$wc odBe<]fgN'JT-B|zhlzNˠg#WDz= L32~m`J˫_8F~~~~~PGOyO{9Ց}Nف4RPmDx]C؇q CVmJGN=[;Xg`tS:S@`UEnE2x욲S.a(E afbJ#B7dN)KM`TX#}|l3[$ @k{GW/*{hy<TtFH%/v_woz]9ND&TJw9DOie)QdSwRwj7-8޼ @=p ̙ʷof2>20c\e)&`du*`aBF5%$g>Q:nYKcbnf H5NyHQvO;j ".izp|+PQΜ9'ru3VLQ;RkQHG*^ZvdV>ĩH%:J#sj<Դ]mb< $H:f_`ل>KZ]}q sE*/ @7`BVDhpMJU. 9L2k搙-,CC$ˋ ۔-Bt|gv 8H=QJL˘CN i"@׺(!9oѐ.aj5(6[v005^{:㙡E+_""CݜO;qrҀ1' ׅEW~[2͈5ŗCBqN ]~ʼnl#C0k[]YEUT,{Uzg<A8)JvLb*I{h K޿U3CQvXϟ? qqXWb$rf usON&ٛWJzz]²j?IKRDS +B|'J](RtcY\O(b>2 1DӚVmGV? >@nE.7K}%\Ua$bhi9<=Gvl0L4tf"PÓᗂLB")9sŴH$qg6>C;<+r0Nf,n!-(k '/BoYjM(Ɗ0áǬxIv|.%Nw`\|Mmv,"pPYǹ8Esd({"9AR6$ y0Z׌EDoIԂvh,4$mH]<3!* f\BTщ!$ β eƃUԒ`TB2PͲ|'k~/F>'\g59J^StK@݅,RCQd#"Oe(YffD+Laɣ݌\. y PJVBy][;~bx2J|+d=:~6Y {2.QڅgSE*옺HU"e1Qba,~c1f;`<<rI +}&NT8u` TD탘P00^ß^Ysu?*`LԘ|xDŽAp4VZF4RXI'%m{$DŽ9l3y@ 1  j?%e*RKSZHM]{Tݟa7(YtQsK ނ)؟ HT2Yw%íEQ,U ByIFUs7lkyu2 F[3I+ޝ{KoYu1>) 9g&Cd>OEEiN_]ur`NMe-!܍>_O.ZEZ¯̧ ɃJ\==X)_oZw1]mãydV_Ԥ1vpsqhvݻcH2K *2 d?kٯ#^[%J:pDT|^u4fr|UMxZ ZWM@_X`_מA;ЊB#]D59^DWm; Y+ s ? +\o:(-^,zp8+: Ģ˂{'|n1__JS}#Rz~Qt&Mm `*AY3V,lSH+WRXf}!ppKYT_f@>&''iH"^<ˑX=S;A;S='1V"n;œHb5>yM0yQA?HXMwY:xT8]|J#*TNGH;*(YƘ}s#r ӧdl.赢6L"j,=QJ>pAJ8  p뢐rd7" +%5xNCb#X aFDGލY``(eM~>dtw|>u}."DH8TĒ1d#rͺ4/;WAf~9X {d/)PՊήA6k/PX0;;wQ<) PO XU>B{} 0Sѹr{ c G,㹻{&5Z2D"xME9Ǯ|o+-j%3MX^=zpVPԱ}HlRD.f~^g XvyJ.8x'gHlab<2Cxc=㸇%{VRڻE{KXn e {Ѕx[SMUO9W צgn)B"h 1I]'lk1IENDB`mago-0.3+bzr20/tests/data/test_savedocument.ref0000644000000000000000000000001511515407742021477 0ustar rootroot00000000000000Hello World! mago-0.3+bzr20/tests/gcalctool.py0000644000000000000000000000201311515407742016655 0ustar rootroot00000000000000""" GCalctool demo module This module export 3 functions to test the import of external functions and constants into a test_suite. It goes with test_gcalctool.py """ constant1 = "A" constant2 = "B" constant3 = "C" import ldtp, ooldtp launcher = 'gcalctool' window_name = 'frmCalculator' def function1(): """Simple calculation""" ldtp.waittillguiexist('frmCalculator') ldtp.wait(1) a = ooldtp.context('frmCalculator') a.click('btn1') a.click('btn2') a.click('btn3') a.click('btnadd') a.click('btn4') a.click('btn5') a.click('btn6') a.click('btnresult') ldtp.wait(2) def function2(): """Simple calculation 2 Set a value in the entry field if empty then multiply it """ a = ooldtp.context('frmCalculator') if not a.gettextvalue('txt0'): a.settextvalue('txt0', '123') a.click('btnmultiply') a.click('btn4') a.click('btnresult') ldtp.wait(2) def clearscreen(): """Clear the entry""" ldtp.settextvalue(window_name, 'txt0', '') mago-0.3+bzr20/tests/test_about.py0000644000000000000000000000426311515407742017070 0ustar rootroot00000000000000# Copyright (C) 2005-2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Minimal Test This is a basic test to verify that mago-ng is working as expected and can be run with various testing framework To run it with: $ mago-ng You can code ldtp directly in there or an external module The only mandatory element is 'launcher' (and window_name for now) set setupOnce to False to launch/close the app for each test The purpose of this example is to test the management of the about dialog """ from mago import TestCase import unittest import ldtp class TestAbout(TestCase): """Test the about dialog """ launcher = 'gucharmap' window_name = 'frmCharacterMap' def test_openclose(self): """Test opening and closing of the about dialog This test: - opens the about dialog - check the return code - check it the dialog is there - closes it - check the return code - check it the dialog vanished """ # Open the about rc = self.application.about_open() self.assertTrue(rc) dlgAboutName = self.application.dlgAboutName self.assertIsNotNone(dlgAboutName, "Name of the about dialog was not found") self.assertTrue(ldtp.guiexist(dlgAboutName)) # Then close it rc = self.application.about_close() self.assertTrue(rc) self.assertFalse(ldtp.guiexist(dlgAboutName)) if __name__ == "__main__": unittest.main() mago-0.3+bzr20/tests/test_about2.py0000644000000000000000000000506411515407742017152 0ustar rootroot00000000000000# Copyright (C) 2005-2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Minimal Test This is a basic test to verify that mago-ng is working as expected and can be run with various testing framework To run it with: $ mago-ng You can code ldtp directly in there or an external module The only mandatory element is 'launcher' (and window_name for now) set setupOnce to False to launch/close the app for each test The purpose of this example is to test the management of the about dialog. The difference with test_about.py is that the open and close actions are done in 2 different tests """ from mago import TestCase import unittest import ldtp class TestAbout(TestCase): """Test the about dialog """ launcher = 'gucharmap' window_name = 'frmCharacterMap' setupOnce = True def test_01open(self): """Test opening of the about dialog This test: - opens the about dialog - check the return code - check it the dialog is there """ # Open the about rc = self.application.about_open() self.assertTrue(rc) dlgAboutName = self.application.dlgAboutName self.assertIsNotNone(dlgAboutName, "Name of the about dialog was not found") self.assertTrue(ldtp.guiexist(dlgAboutName)) def test_02close(self): """Test closing of the about dialog This test: - closes the about dialog - check the return code - check it the dialog vanished """ dlgAboutName = self.application.dlgAboutName if not dlgAboutName: raise self.failureException, "About dialog not set up correctly. Did test_open failed ?" rc = self.application.about_close() self.assertTrue(rc) self.assertFalse(ldtp.guiexist(dlgAboutName)) if __name__ == "__main__": unittest.main() mago-0.3+bzr20/tests/test_authenticate.ini0000644000000000000000000000024611515407742020560 0ustar rootroot00000000000000[data] ; To pass the test you need to specify valid credentials in the included file: ; [auth] ; username=USERNAME ; password=PASSWORD include=~/.magocredentials.ini mago-0.3+bzr20/tests/test_authenticate.py0000644000000000000000000000662711515407742020442 0ustar rootroot00000000000000# Copyright (C) 2005-2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Minimal Test This is a basic test to verify that mago-ng is working as expected and can be run with various testing framework To run it with: $ mago-ng You can code ldtp directly in there or an external module The only mandatory element is 'launcher' (and window_name for now) set setupOnce to False to launch/close the app for each test The purpose of this example is to test the management of the authentication dialog """ from mago import TestCase import unittest import ldtp class TestAuthenticate(TestCase): """Test the authentication dialog """ launcher = 'time-admin' window_name = 'dlgTimeandDateSettings' def setUp(self): """setUp method. Click on btn2 to popup the auth dialog """ super(TestAuthenticate, self).setUp() ldtp.click(self.window_name, 'btn2') def test_password(self): """Test authentication with a valid password This test enters a valid password and check the authenticate returned True, that the dialog is not there anymore and that the calendar is enabled (meaning that the authentication succeeded) """ if not self.testConfig.has_option('auth', 'password'): raise self.failureException,"Password is mandatory. Set it in the configuration file" password = self.testConfig.get('auth', 'password') rc = self.application.authenticate(password) self.assertTrue(rc) self.assertFalse(ldtp.guiexist('dlgAuthenticate')) self.assertTrue(ldtp.stateenabled(self.window_name, 'calDate')) def test_cancel(self): """Test the Cancel action of the authentication dialog Open the authentication dialog and cancel, then check the return status and that the dialog is closed """ rc = self.application.authenticate(cancel = True) self.assertTrue(rc) self.assertFalse(ldtp.guiexist('dlgAuthenticate')) def test_wrongpassword(self): """Test authentication with a wrong password The test enters a wrong password and check that authenticate returns False, that the dialog is still there. Then call authenticate again with cancel and check that the return status is True and the dialog vanished """ # Set an invalid password rc = self.application.authenticate(password = "this password is invalid") self.assertFalse(rc) self.assertTrue(ldtp.guiexist('dlgAuthenticate')) # Cancel the auth. dialog rc = self.application.authenticate(cancel = True) self.assertTrue(rc) self.assertFalse(ldtp.guiexist('dlgAuthenticate')) if __name__ == "__main__": unittest.main() mago-0.3+bzr20/tests/test_gcalctool.py0000644000000000000000000000447411515407742017731 0ustar rootroot00000000000000#!/usr/bin/python # Copyright (C) 2005-2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Basic Test This is a basic test to verify that mago-ng is working as expected and can be run with various testing framework To run it with: $ mago-ng You can code ldtp directly in there or an external module The only mandatory element is 'launcher' (and window_name for now) set setupOnce to False to launch/close the app for each test The purpose of this example is to demo the import of an external module or external functions """ from mago import TestCase, TextTestRunner import unittest import gcalctool import ooldtp class TestGCalctool(TestCase): """Test Class for Gcalctool""" launcher = gcalctool.launcher launcher_args = [] window_name = gcalctool.window_name #setupOnce = True def test_test01(self): """test01 This method just call function2 included in the external module 'gcalctool' """ gcalctool.function1() def test_test02(self): """test02 This method set a value is the entry field of the calculator is empty, then call function2 included in the external module 'gcalctool' """ a = ooldtp.context('frmCalculator') if not a.gettextvalue('txt0'): a.settextvalue('txt0', '321') gcalctool.function2() def setUp(self): """setUp method We overload the setUp method to clear the calculator entry field at the start of the test. """ super(TestGCalctool, self).setUp() gcalctool.clearscreen() if __name__ == "__main__": unittest.main(testRunner=TextTestRunner) mago-0.3+bzr20/tests/test_getwindowname.py0000644000000000000000000000334611515407742020627 0ustar rootroot00000000000000# Copyright (C) 2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Test Windowname The purpose of this test is to try the application.getwindowname() method """ from mago import TestCase import unittest import ldtp class TestGetWindowName(TestCase): """The minimal test that can be written with mago """ launcher = 'gedit' window_name = 'frm*gedit*' def test_01getwindowname_nodiscover(self): """Get the window name using the getwindowname method from the application class in non discovery mode """ wname = self.application.get_windowname() print "***" , wname self.assertEqual(self.window_name, wname) ldtp.wait(2) def test_02getwindowname_discover(self): """Get the window name using the getwindowname method from the application class with forced discovery """ wname = self.application.get_windowname( discover = True) print "***" , wname self.assertEqual('frmCalculator', wname) ldtp.wait(2) if __name__ == "__main__": unittest.main() mago-0.3+bzr20/tests/test_guesswindowname.py0000644000000000000000000000352411515407742021174 0ustar rootroot00000000000000# Copyright (C) 2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Minimal Test This is a basic test to verify that mago-ng is working as expected and can be run with various testing framework To run it with: $ mago-ng You can code ldtp directly in there or an external module The only mandatory element is 'launcher' (and window_name for now) set setupOnce to False to launch/close the app for each test The purpose of this example is to test the __guesswindowname() from the TestCase class This test is DEPRECATED and replaced by test_getwindowname """ from mago import TestCase import unittest class TestGuess(TestCase): """The minimal test that can be written with mago """ launcher = 'sol' #window_name = 'frmKlondike' @skip('This test is deprecated and replaced by test_getwindowname') def test_guesswindowname(self): """Launch the application and use TestCase.__guesswindowname() to find out the name of the main application that has just been launched """ #windowname = self.window_name self.assertEqual(self.application.window_name, 'frmKlondike') if __name__ == "__main__": unittest.main() mago-0.3+bzr20/tests/test_helloworld.py0000644000000000000000000000415311515541545020127 0ustar rootroot00000000000000#!/usr/bin/python # Copyright (C) 2005-2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Hello World Test This is a basic test to verify that mago-ng is working as expected and can be run with various testing framework To run it with: $ mago-ng You can code ldtp directly in there or an external module The only mandatory element is 'launcher' (and window_name for now) set setupOnce to False to launch/close the app for each test The purpose of this example is to demo a very basic manipulation of an application and validate the 'force_close' feature when a dialog pops up inadventently after the end of the test. """ from mago import TestCase import ldtp class TestHelloWorld(TestCase): """Test Class""" launcher = 'gedit' launcher_args = [] window_name = 'frm*gedit' setupOnce = True def test_helloworld(self): """Test Method Change the content of the edit buffer of gedit marking it dirty The close action triggered in the teardown will popup the "unsaved changes" dialog. The application should close after 30 seconds. """ txt = """Hello World! A dialog will popup and ask you: "Save changes to document "Untitled Document 1" before closing?" Don't close it but wait 60 seconds and it should close automatically. If it does not please report a bug against mago. """ ldtp.settextvalue(self.window_name, 'txt1', txt) ldtp.wait(2) mago-0.3+bzr20/tests/test_minimal.py0000644000000000000000000000325211515564373017405 0ustar rootroot00000000000000# Copyright (C) 2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Minimal Test This is a basic test to verify that mago-ng is working as expected and can be run with various testing framework To run it with: $ mago-ng You can code ldtp directly in there or an external module The only mandatory element is 'launcher' (and window_name for now) set setupOnce to False to launch/close the app for each test The purpose of this example is to demo the smallest mago script that can be written. """ from mago import TestCase import unittest class TestMinimal(TestCase): """The minimal test that can be written with mago """ launcher = 'sol' #: This is optional. If it is not defined, mago tries to guess it by querying Xlib #window_name = 'frmKlondike' def test_minimal(self): """A really simple test This test verifies True is True. If it fails, then reinstall your system. """ self.assertTrue(True) if __name__ == "__main__": unittest.main() mago-0.3+bzr20/tests/test_savedocument.ini0000644000000000000000000000022011515407742020567 0ustar rootroot00000000000000[data] text=this string is different from the oracle The test will fail. Don't panic! destdir=/tmp/ oracle=data/test_savedocument.ref mago-0.3+bzr20/tests/test_savedocument.py0000644000000000000000000000534611515407742020456 0ustar rootroot00000000000000#!/usr/bin/python # Copyright (C) 2005-2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Demo Test This is a basic test to verify that mago-ng is working as expected and can be run with various testing framework To run it with: $ mago-ng You can code ldtp directly in there or an external module The only mandatory element is 'launcher' (and window_name for now) set setupOnce to False to launch/close the app for each test The purpose of this example is to demo the use of a configuration file and the comparison of files """ from mago import TestCase, utils import unittest import ldtp import os class TestSaveDocument(TestCase): """Test Class""" launcher = 'gedit' launcher_args = [] window_name = 'frm*gedit' setupOnce = True def test_save(self): """Save a document and compare to an oracle The text and the path to the oracle are loaded from a configuration file. The name of the configuration file must be the same as the test file with the extention .ini In this example the test file is 'test_savedocument.py' and the configuration file is 'test_savedocument.ini' """ ldtp.settextvalue(self.window_name, 'txt1', self.testConfig.get('data', 'text')) ldtp.wait(2) # Load the destination directory and the oracle file name from the # configuration file destfile = os.path.join( self.testConfig.get('data', 'destdir'), "%s.txt" % __name__) oracle = os.path.join( os.path.dirname(__file__), self.testConfig.get('data', 'oracle')) # Assert that the files saves correctly # If you set replace to False and the destination file already exists # the assertion will fail self.assertTrue(self.application.saveDocument(destfile, replace = True)) # Assert that the saved file and the oracle are the same self.assertTrue(utils.file_compare(destfile, oracle)) if __name__ == "__main__": unittest.main() mago-0.3+bzr20/tests/test_testconfig.ini0000644000000000000000000000005311515407742020243 0ustar rootroot00000000000000[hello] hello=Hello World goodbye=Good bye mago-0.3+bzr20/tests/test_testconfig.py0000644000000000000000000000436511515541545020126 0ustar rootroot00000000000000#!/usr/bin/python # Copyright (C) 2005-2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Demo Test This is a basic test to verify that mago-ng is working as expected and can be run with various testing framework To run it with: $ mago-ng You can code ldtp directly in there or an external module The only mandatory element is 'launcher' (and window_name for now) set setupOnce to False to launch/close the app for each test The purpose of this example is to demo the use of a configuration file """ from mago import TestCase, magoConfig import os class TestConfiguration(TestCase): """Test Class""" launcher = 'gedit' window_name = 'frm*gedit' def test_showconfig(self): """Load the main and test configurations and display it in gedit""" localconf = ".".join(os.path.basename(__file__).split('.')[:-1]) str1 = "The main configuration file for mago is '~/.magorc' and its content is:\n\ %s\n" % magoConfig.items('mago') str2 = "The configuration file for the test is '%s.ini' and its content is:\n\ %s\n" % (localconf, self.testConfig.items('hello')) str3 = "* The values read from the test configuration file are:" str4 = self.testConfig.get('hello', 'hello') str5 = self.testConfig.get('hello', 'goodbye') str6 = "\n* This value is not in the configuration file:" str7 = self.testConfig.get('hello', 'aurevoir', vars={'aurevoir':'Au Revoir'}) str = '\n'.join((str1, str2, str3, str4, str5, str6, str7)) self.application.context.settextvalue('txt1', str) mago-0.3+bzr20/tests/test_xpresser_opencvfinder.py0000644000000000000000000000260411516265061022365 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # """ Test Find functionality of XPresser""" from mago import TestCase from xpresser.image import Image from xpresser.opencvfinder import OpenCVFinder desktop = Image(filename="data/desktop.png") button1 = Image(filename="data/button01.png") class TestXPOpenCVFinder(TestCase): """ Test Class""" launcher = "gedit" window_name = 'frm*gedit' def test_xpfindall(self): """Test the find_all method of xpresser Count the number of occurences of the reference image in the main image. Should be 4 """ finder = OpenCVFinder() m = finder.find_all(desktop, button1) self.assertEqual(len(m), 4) mago-0.3+bzr20/tests/test_yelp.py0000644000000000000000000000325511515407742016727 0ustar rootroot00000000000000# Copyright (C) 2010 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """Test Windowname The purpose of this test is to try the application.getwindowname() method """ from mago import TestCase import unittest import ldtp class TestGetWindowName(TestCase): """The minimal test that can be written with mago """ launcher = 'yelp' window_name = 'frmUbuntuHelp' def test_getwindowname_discover(self): """Get the window name using the getwindowname method from the application class with forced discovery """ wname = self.application.get_windowname( discover = True) print "***" , wname ldtp.wait(2) self.application.context.settextvalue('txtSearch', 'network') self.application.context.enterstring('txtSearch', '') #ldtp.wait(2) #self.application.context.remap() ldtp.wait(2) wname = self.application.get_windowname( discover = True) print "***" , wname if __name__ == "__main__": unittest.main() mago-0.3+bzr20/xpresser/0000755000000000000000000000000011516265061015046 5ustar rootroot00000000000000mago-0.3+bzr20/xpresser/__init__.py0000644000000000000000000000146511516265061017165 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # import pygtk pygtk.require("2.0") from xpresser.xp import Xpresser, ImageNotFound mago-0.3+bzr20/xpresser/errors.py0000644000000000000000000000146611516265061016743 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # class XpresserError(Exception): """Base class for all Xpresser exceptions.""" mago-0.3+bzr20/xpresser/image.py0000644000000000000000000000471211516265061016506 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # DEFAULT_SIMILARITY = 0.98 class Image(object): """An image. :-) @ivar name: The human-oriented name of this image. May be None. @ivar similarity: The similarity tolerance to be used when searching for this image. Varies between 0.0 and 1.0, where 1.0 is a perfect match. Defaults to the value of DEFAULT_SIMILARITY when not specified in the image data. @ivar focus_delta: (dx, dy) pair added to the center position to find where to click. For instance, if the *center* of the image is found at 200, 300 and the focus_point is (10, -20) the click will actually happen at the screen position (210, 280). When not specified, (0, 0) is assumed, which means click in the center of the image itself. @ivar width: The width of the image. @ivar height: The height of the image. @ivar filename: Filename of the image. @ivar array: Numpy array with three dimensions (rows, columns, RGB). @ivar cache: Generic storage for data associated with this image, used by the image finder, for instance. """ def __init__(self, name=None, similarity=None, focus_delta=None, width=None, height=None, filename=None, array=None): if similarity is None: similarity = DEFAULT_SIMILARITY if focus_delta is None: focus_delta = (0, 0) if not (0 < similarity < 1): raise ValueError("Similarity out of range: %.2f" % similarity) self.name = name self.similarity = similarity self.focus_delta = focus_delta self.width = width self.height = height self.filename = filename self.array = array self.cache = {} mago-0.3+bzr20/xpresser/imagedir.py0000644000000000000000000001137511516265061017210 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # import mimetypes import ConfigParser import os import re from xpresser.errors import XpresserError from xpresser.image import Image CLICK_POSITION_RE = re.compile(r"^\s*(?P[-+][0-9]+)\s+(?P[-+][0-9]+)\s*$") class ImageDirError(XpresserError): """Error related to the image directory.""" class ImageDir(object): """Represents a directory with data about images. This class doesn't know about any details regarding the images themselves, besides the existence of the file in which they reside. It will give access to generic ImageData objects containing the details about these images. It's up to an ImageLoader to make sense of the actual image data contained in the image files. """ def __init__(self): self._images = {} def get(self, image_name): return self._images.get(image_name) def load(self, dirname): """Load image information from C{dirname}. @param dirname: Path of directory containing xpresser.ini. """ loaded_filenames = set() ini_filename = os.path.join(dirname, "xpresser.ini") if os.path.exists(ini_filename): config = ConfigParser.ConfigParser() config.read(ini_filename) for section_name in config.sections(): if section_name.startswith("image "): image_name = section_name.split(None, 1)[1] try: image_filename = config.get(section_name, "filename") except ConfigParser.NoOptionError: raise ImageDirError("Image %s missing filename option" % image_name) image_filename = os.path.join(dirname, image_filename) if not os.path.exists(image_filename): raise ImageDirError("Image %s file not found: %s" % (image_name, image_filename)) try: image_similarity = config.getfloat(section_name, "similarity") except ConfigParser.NoOptionError: image_similarity = None except ValueError: value = config.get(section_name, "similarity") raise ImageDirError("Image %s has bad similarity: %s" % (image_name, value)) try: value = config.get(section_name, "focus_delta") match = CLICK_POSITION_RE.match(value) if not match: raise ImageDirError("Image %s has invalid click " "position: %s" % (image_name, value)) image_focus_delta = (int(match.group("x")), int(match.group("y"))) except ConfigParser.NoOptionError: image_focus_delta = None image = Image(name=image_name, filename=image_filename, similarity=image_similarity, focus_delta=image_focus_delta) self._images[image_name] = image loaded_filenames.add(image_filename) # Load any other images implicitly with the default arguments. for basename in os.listdir(dirname): filename = os.path.join(dirname, basename) if filename not in loaded_filenames: ftype, fencoding = mimetypes.guess_type(filename) if ftype and ftype.startswith("image/"): image_name = os.path.splitext(basename)[0] self._images[image_name] = Image(name=image_name, filename=filename) mago-0.3+bzr20/xpresser/imagematch.py0000644000000000000000000000411511516265061017520 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # from xpresser.errors import XpresserError class ImageMatchError(XpresserError): """Error raised due to an ImageMatch related problem (really!).""" class ImageMatch(object): """An image found inside another image. @ivar image: The image found. @ivar x: Position in the X axis where the image was found. @ivar y: Position in the Y axis where the image was found. @ivar similarity: How similar to the original image the match was, where 1.0 == 100%. @ivar focus_point: The position in the screen which this image match represents. This is useful for clicks, hovering, etc. If no delta was specified in the image data itself, this will map to the center of the found image. """ def __init__(self, image, x, y, similarity): if image.height is None: raise ImageMatchError("Image.height was None when trying to " "create an ImageMatch with it.") if image.width is None: raise ImageMatchError("Image.width was None when trying to " "create an ImageMatch with it.") self.image = image self.x = x self.y = y self.similarity = similarity self.focus_point = (x + image.width//2 + image.focus_delta[0], y + image.height//2 + image.focus_delta[1]) mago-0.3+bzr20/xpresser/lib/0000755000000000000000000000000011516265061015614 5ustar rootroot00000000000000mago-0.3+bzr20/xpresser/lib/__init__.py0000644000000000000000000000000011516265061017713 0ustar rootroot00000000000000mago-0.3+bzr20/xpresser/lib/mocker.py0000644000000000000000000022263711516265061017462 0ustar rootroot00000000000000""" Copyright (c) 2007 Gustavo Niemeyer Graceful platform for test doubles in Python (mocks, stubs, fakes, and dummies). """ import __builtin__ import tempfile import unittest import inspect import shutil import types import sys import os import gc if sys.version_info < (2, 4): from sets import Set as set # pragma: nocover __all__ = ["Mocker", "expect", "IS", "CONTAINS", "IN", "MATCH", "ANY", "ARGS", "KWARGS"] __author__ = "Gustavo Niemeyer " __license__ = "PSF License" __version__ = "0.10.1" ERROR_PREFIX = "[Mocker] " # -------------------------------------------------------------------- # Exceptions class MatchError(AssertionError): """Raised when an unknown expression is seen in playback mode.""" # -------------------------------------------------------------------- # Helper for chained-style calling. class expect(object): """This is a simple helper that allows a different call-style. With this class one can comfortably do chaining of calls to the mocker object responsible by the object being handled. For instance:: expect(obj.attr).result(3).count(1, 2) Is the same as:: obj.attr mocker.result(3) mocker.count(1, 2) """ def __init__(self, mock, attr=None): self._mock = mock self._attr = attr def __getattr__(self, attr): return self.__class__(self._mock, attr) def __call__(self, *args, **kwargs): getattr(self._mock.__mocker__, self._attr)(*args, **kwargs) return self # -------------------------------------------------------------------- # Extensions to Python's unittest. class MockerTestCase(unittest.TestCase): """unittest.TestCase subclass with Mocker support. @ivar mocker: The mocker instance. This is a convenience only. Mocker may easily be used with the standard C{unittest.TestCase} class if wanted. Test methods have a Mocker instance available on C{self.mocker}. At the end of each test method, expectations of the mocker will be verified, and any requested changes made to the environment will be restored. In addition to the integration with Mocker, this class provides a few additional helper methods. """ expect = expect def __init__(self, methodName="runTest"): # So here is the trick: we take the real test method, wrap it on # a function that do the job we have to do, and insert it in the # *instance* dictionary, so that getattr() will return our # replacement rather than the class method. test_method = getattr(self, methodName, None) if test_method is not None: def test_method_wrapper(): try: result = test_method() except: raise else: if (self.mocker.is_recording() and self.mocker.get_events()): raise RuntimeError("Mocker must be put in replay " "mode with self.mocker.replay()") if (hasattr(result, "addCallback") and hasattr(result, "addErrback")): def verify(result): self.mocker.verify() return result result.addCallback(verify) else: self.mocker.verify() self.mocker.restore() return result # Copy all attributes from the original method.. for attr in dir(test_method): # .. unless they're present in our wrapper already. if not hasattr(test_method_wrapper, attr) or attr == "__doc__": setattr(test_method_wrapper, attr, getattr(test_method, attr)) setattr(self, methodName, test_method_wrapper) # We could overload run() normally, but other well-known testing # frameworks do it as well, and some of them won't call the super, # which might mean that cleanup wouldn't happen. With that in mind, # we make integration easier by using the following trick. run_method = self.run def run_wrapper(*args, **kwargs): try: return run_method(*args, **kwargs) finally: self.__cleanup() self.run = run_wrapper self.mocker = Mocker() self.__cleanup_funcs = [] self.__cleanup_paths = [] super(MockerTestCase, self).__init__(methodName) def __cleanup(self): for path in self.__cleanup_paths: if os.path.isfile(path): os.unlink(path) elif os.path.isdir(path): shutil.rmtree(path) self.mocker.reset() for func, args, kwargs in self.__cleanup_funcs: func(*args, **kwargs) def addCleanup(self, func, *args, **kwargs): self.__cleanup_funcs.append((func, args, kwargs)) def makeFile(self, content=None, suffix="", prefix="tmp", basename=None, dirname=None, path=None): """Create a temporary file and return the path to it. @param content: Initial content for the file. @param suffix: Suffix to be given to the file's basename. @param prefix: Prefix to be given to the file's basename. @param basename: Full basename for the file. @param dirname: Put file inside this directory. The file is removed after the test runs. """ if path is not None: self.__cleanup_paths.append(path) elif basename is not None: if dirname is None: dirname = tempfile.mkdtemp() self.__cleanup_paths.append(dirname) path = os.path.join(dirname, basename) else: fd, path = tempfile.mkstemp(suffix, prefix, dirname) self.__cleanup_paths.append(path) os.close(fd) if content is None: os.unlink(path) if content is not None: file = open(path, "w") file.write(content) file.close() return path def makeDir(self, suffix="", prefix="tmp", dirname=None, path=None): """Create a temporary directory and return the path to it. @param suffix: Suffix to be given to the file's basename. @param prefix: Prefix to be given to the file's basename. @param dirname: Put directory inside this parent directory. The directory is removed after the test runs. """ if path is not None: os.makedirs(path) else: path = tempfile.mkdtemp(suffix, prefix, dirname) self.__cleanup_paths.append(path) return path def failUnlessIs(self, first, second, msg=None): """Assert that C{first} is the same object as C{second}.""" if first is not second: raise self.failureException(msg or "%r is not %r" % (first, second)) def failIfIs(self, first, second, msg=None): """Assert that C{first} is not the same object as C{second}.""" if first is second: raise self.failureException(msg or "%r is %r" % (first, second)) def failUnlessIn(self, first, second, msg=None): """Assert that C{first} is contained in C{second}.""" if first not in second: raise self.failureException(msg or "%r not in %r" % (first, second)) def failUnlessStartsWith(self, first, second, msg=None): """Assert that C{first} starts with C{second}.""" if first[:len(second)] != second: raise self.failureException(msg or "%r doesn't start with %r" % (first, second)) def failIfStartsWith(self, first, second, msg=None): """Assert that C{first} doesn't start with C{second}.""" if first[:len(second)] == second: raise self.failureException(msg or "%r starts with %r" % (first, second)) def failUnlessEndsWith(self, first, second, msg=None): """Assert that C{first} starts with C{second}.""" if first[len(first)-len(second):] != second: raise self.failureException(msg or "%r doesn't end with %r" % (first, second)) def failIfEndsWith(self, first, second, msg=None): """Assert that C{first} doesn't start with C{second}.""" if first[len(first)-len(second):] == second: raise self.failureException(msg or "%r ends with %r" % (first, second)) def failIfIn(self, first, second, msg=None): """Assert that C{first} is not contained in C{second}.""" if first in second: raise self.failureException(msg or "%r in %r" % (first, second)) def failUnlessApproximates(self, first, second, tolerance, msg=None): """Assert that C{first} is near C{second} by at most C{tolerance}.""" if abs(first - second) > tolerance: raise self.failureException(msg or "abs(%r - %r) > %r" % (first, second, tolerance)) def failIfApproximates(self, first, second, tolerance, msg=None): """Assert that C{first} is far from C{second} by at least C{tolerance}. """ if abs(first - second) <= tolerance: raise self.failureException(msg or "abs(%r - %r) <= %r" % (first, second, tolerance)) def failUnlessMethodsMatch(self, first, second): """Assert that public methods in C{first} are present in C{second}. This method asserts that all public methods found in C{first} are also present in C{second} and accept the same arguments. C{first} may have its own private methods, though, and may not have all methods found in C{second}. Note that if a private method in C{first} matches the name of one in C{second}, their specification is still compared. This is useful to verify if a fake or stub class have the same API as the real class being simulated. """ first_methods = dict(inspect.getmembers(first, inspect.ismethod)) second_methods = dict(inspect.getmembers(second, inspect.ismethod)) for name, first_method in first_methods.iteritems(): first_argspec = inspect.getargspec(first_method) first_formatted = inspect.formatargspec(*first_argspec) second_method = second_methods.get(name) if second_method is None: if name[:1] == "_": continue # First may have its own private methods. raise self.failureException("%s.%s%s not present in %s" % (first.__name__, name, first_formatted, second.__name__)) second_argspec = inspect.getargspec(second_method) if first_argspec != second_argspec: second_formatted = inspect.formatargspec(*second_argspec) raise self.failureException("%s.%s%s != %s.%s%s" % (first.__name__, name, first_formatted, second.__name__, name, second_formatted)) assertIs = failUnlessIs assertIsNot = failIfIs assertIn = failUnlessIn assertNotIn = failIfIn assertStartsWith = failUnlessStartsWith assertNotStartsWith = failIfStartsWith assertEndsWith = failUnlessEndsWith assertNotEndsWith = failIfEndsWith assertApproximates = failUnlessApproximates assertNotApproximates = failIfApproximates assertMethodsMatch = failUnlessMethodsMatch # The following are missing in Python < 2.4. assertTrue = unittest.TestCase.failUnless assertFalse = unittest.TestCase.failIf # The following is provided for compatibility with Twisted's trial. assertIdentical = assertIs assertNotIdentical = assertIsNot failUnlessIdentical = failUnlessIs failIfIdentical = failIfIs # -------------------------------------------------------------------- # Mocker. class classinstancemethod(object): def __init__(self, method): self.method = method def __get__(self, obj, cls=None): def bound_method(*args, **kwargs): return self.method(cls, obj, *args, **kwargs) return bound_method class MockerBase(object): """Controller of mock objects. A mocker instance is used to command recording and replay of expectations on any number of mock objects. Expectations should be expressed for the mock object while in record mode (the initial one) by using the mock object itself, and using the mocker (and/or C{expect()} as a helper) to define additional behavior for each event. For instance:: mock = mocker.mock() mock.hello() mocker.result("Hi!") mocker.replay() assert mock.hello() == "Hi!" mock.restore() mock.verify() In this short excerpt a mock object is being created, then an expectation of a call to the C{hello()} method was recorded, and when called the method should return the value C{10}. Then, the mocker is put in replay mode, and the expectation is satisfied by calling the C{hello()} method, which indeed returns 10. Finally, a call to the L{restore()} method is performed to undo any needed changes made in the environment, and the L{verify()} method is called to ensure that all defined expectations were met. The same logic can be expressed more elegantly using the C{with mocker:} statement, as follows:: mock = mocker.mock() mock.hello() mocker.result("Hi!") with mocker: assert mock.hello() == "Hi!" Also, the MockerTestCase class, which integrates the mocker on a unittest.TestCase subclass, may be used to reduce the overhead of controlling the mocker. A test could be written as follows:: class SampleTest(MockerTestCase): def test_hello(self): mock = self.mocker.mock() mock.hello() self.mocker.result("Hi!") self.mocker.replay() self.assertEquals(mock.hello(), "Hi!") """ _recorders = [] # For convenience only. on = expect class __metaclass__(type): def __init__(self, name, bases, dict): # Make independent lists on each subclass, inheriting from parent. self._recorders = list(getattr(self, "_recorders", ())) def __init__(self): self._recorders = self._recorders[:] self._events = [] self._recording = True self._ordering = False self._last_orderer = None def is_recording(self): """Return True if in recording mode, False if in replay mode. Recording is the initial state. """ return self._recording def replay(self): """Change to replay mode, where recorded events are reproduced. If already in replay mode, the mocker will be restored, with all expectations reset, and then put again in replay mode. An alternative and more comfortable way to replay changes is using the 'with' statement, as follows:: mocker = Mocker() with mocker: The 'with' statement will automatically put mocker in replay mode, and will also verify if all events were correctly reproduced at the end (using L{verify()}), and also restore any changes done in the environment (with L{restore()}). Also check the MockerTestCase class, which integrates the unittest.TestCase class with mocker. """ if not self._recording: for event in self._events: event.restore() else: self._recording = False for event in self._events: event.replay() def restore(self): """Restore changes in the environment, and return to recording mode. This should always be called after the test is complete (succeeding or not). There are ways to call this method automatically on completion (e.g. using a C{with mocker:} statement, or using the L{MockerTestCase} class. """ if not self._recording: self._recording = True for event in self._events: event.restore() def reset(self): """Reset the mocker state. This will restore environment changes, if currently in replay mode, and then remove all events previously recorded. """ if not self._recording: self.restore() self.unorder() del self._events[:] def get_events(self): """Return all recorded events.""" return self._events[:] def add_event(self, event): """Add an event. This method is used internally by the implementation, and shouldn't be needed on normal mocker usage. """ self._events.append(event) if self._ordering: orderer = event.add_task(Orderer(event.path)) if self._last_orderer: orderer.add_dependency(self._last_orderer) self._last_orderer = orderer return event def verify(self): """Check if all expectations were met, and raise AssertionError if not. The exception message will include a nice description of which expectations were not met, and why. """ errors = [] for event in self._events: try: event.verify() except AssertionError, e: error = str(e) if not error: raise RuntimeError("Empty error message from %r" % event) errors.append(error) if errors: message = [ERROR_PREFIX + "Unmet expectations:", ""] for error in errors: lines = error.splitlines() message.append("=> " + lines.pop(0)) message.extend([" " + line for line in lines]) message.append("") raise AssertionError(os.linesep.join(message)) def mock(self, spec_and_type=None, spec=None, type=None, name=None, count=True): """Return a new mock object. @param spec_and_type: Handy positional argument which sets both spec and type. @param spec: Method calls will be checked for correctness against the given class. @param type: If set, the Mock's __class__ attribute will return the given type. This will make C{isinstance()} calls on the object work. @param name: Name for the mock object, used in the representation of expressions. The name is rarely needed, as it's usually guessed correctly from the variable name used. @param count: If set to false, expressions may be executed any number of times, unless an expectation is explicitly set using the L{count()} method. By default, expressions are expected once. """ if spec_and_type is not None: spec = type = spec_and_type return Mock(self, spec=spec, type=type, name=name, count=count) def proxy(self, object, spec=True, type=True, name=None, count=True, passthrough=True): """Return a new mock object which proxies to the given object. Proxies are useful when only part of the behavior of an object is to be mocked. Unknown expressions may be passed through to the real implementation implicitly (if the C{passthrough} argument is True), or explicitly (using the L{passthrough()} method on the event). @param object: Real object to be proxied, and replaced by the mock on replay mode. It may also be an "import path", such as C{"time.time"}, in which case the object will be the C{time} function from the C{time} module. @param spec: Method calls will be checked for correctness against the given object, which may be a class or an instance where attributes will be looked up. Defaults to the the C{object} parameter. May be set to None explicitly, in which case spec checking is disabled. Checks may also be disabled explicitly on a per-event basis with the L{nospec()} method. @param type: If set, the Mock's __class__ attribute will return the given type. This will make C{isinstance()} calls on the object work. Defaults to the type of the C{object} parameter. May be set to None explicitly. @param name: Name for the mock object, used in the representation of expressions. The name is rarely needed, as it's usually guessed correctly from the variable name used. @param count: If set to false, expressions may be executed any number of times, unless an expectation is explicitly set using the L{count()} method. By default, expressions are expected once. @param passthrough: If set to False, passthrough of actions on the proxy to the real object will only happen when explicitly requested via the L{passthrough()} method. """ if isinstance(object, basestring): if name is None: name = object import_stack = object.split(".") attr_stack = [] while import_stack: module_path = ".".join(import_stack) try: object = __import__(module_path, {}, {}, [""]) except ImportError: attr_stack.insert(0, import_stack.pop()) if not import_stack: raise continue else: for attr in attr_stack: object = getattr(object, attr) break if spec is True: spec = object if type is True: type = __builtin__.type(object) return Mock(self, spec=spec, type=type, object=object, name=name, count=count, passthrough=passthrough) def replace(self, object, spec=True, type=True, name=None, count=True, passthrough=True): """Create a proxy, and replace the original object with the mock. On replay, the original object will be replaced by the returned proxy in all dictionaries found in the running interpreter via the garbage collecting system. This should cover module namespaces, class namespaces, instance namespaces, and so on. @param object: Real object to be proxied, and replaced by the mock on replay mode. It may also be an "import path", such as C{"time.time"}, in which case the object will be the C{time} function from the C{time} module. @param spec: Method calls will be checked for correctness against the given object, which may be a class or an instance where attributes will be looked up. Defaults to the the C{object} parameter. May be set to None explicitly, in which case spec checking is disabled. Checks may also be disabled explicitly on a per-event basis with the L{nospec()} method. @param type: If set, the Mock's __class__ attribute will return the given type. This will make C{isinstance()} calls on the object work. Defaults to the type of the C{object} parameter. May be set to None explicitly. @param name: Name for the mock object, used in the representation of expressions. The name is rarely needed, as it's usually guessed correctly from the variable name used. @param passthrough: If set to False, passthrough of actions on the proxy to the real object will only happen when explicitly requested via the L{passthrough()} method. """ mock = self.proxy(object, spec, type, name, count, passthrough) event = self._get_replay_restore_event() event.add_task(ProxyReplacer(mock)) return mock def patch(self, object, spec=True): """Patch an existing object to reproduce recorded events. @param object: Class or instance to be patched. @param spec: Method calls will be checked for correctness against the given object, which may be a class or an instance where attributes will be looked up. Defaults to the the C{object} parameter. May be set to None explicitly, in which case spec checking is disabled. Checks may also be disabled explicitly on a per-event basis with the L{nospec()} method. The result of this method is still a mock object, which can be used like any other mock object to record events. The difference is that when the mocker is put on replay mode, the *real* object will be modified to behave according to recorded expectations. Patching works in individual instances, and also in classes. When an instance is patched, recorded events will only be considered on this specific instance, and other instances should behave normally. When a class is patched, the reproduction of events will be considered on any instance of this class once created (collectively). Observe that, unlike with proxies which catch only events done through the mock object, *all* accesses to recorded expectations will be considered; even these coming from the object itself (e.g. C{self.hello()} is considered if this method was patched). While this is a very powerful feature, and many times the reason to use patches in the first place, it's important to keep this behavior in mind. Patching of the original object only takes place when the mocker is put on replay mode, and the patched object will be restored to its original state once the L{restore()} method is called (explicitly, or implicitly with alternative conventions, such as a C{with mocker:} block, or a MockerTestCase class). """ if spec is True: spec = object patcher = Patcher() event = self._get_replay_restore_event() event.add_task(patcher) mock = Mock(self, object=object, patcher=patcher, passthrough=True, spec=spec) patcher.patch_attr(object, '__mocker_mock__', mock) return mock def act(self, path): """This is called by mock objects whenever something happens to them. This method is part of the implementation between the mocker and mock objects. """ if self._recording: event = self.add_event(Event(path)) for recorder in self._recorders: recorder(self, event) return Mock(self, path) else: # First run events that may run, then run unsatisfied events, then # ones not previously run. We put the index in the ordering tuple # instead of the actual event because we want a stable sort # (ordering between 2 events is undefined). events = self._events order = [(events[i].satisfied()*2 + events[i].has_run(), i) for i in range(len(events))] order.sort() postponed = None for weight, i in order: event = events[i] if event.matches(path): if event.may_run(path): return event.run(path) elif postponed is None: postponed = event if postponed is not None: return postponed.run(path) raise MatchError(ERROR_PREFIX + "Unexpected expression: %s" % path) def get_recorders(cls, self): """Return recorders associated with this mocker class or instance. This method may be called on mocker instances and also on mocker classes. See the L{add_recorder()} method for more information. """ return (self or cls)._recorders[:] get_recorders = classinstancemethod(get_recorders) def add_recorder(cls, self, recorder): """Add a recorder to this mocker class or instance. @param recorder: Callable accepting C{(mocker, event)} as parameters. This is part of the implementation of mocker. All registered recorders are called for translating events that happen during recording into expectations to be met once the state is switched to replay mode. This method may be called on mocker instances and also on mocker classes. When called on a class, the recorder will be used by all instances, and also inherited on subclassing. When called on instances, the recorder is added only to the given instance. """ (self or cls)._recorders.append(recorder) return recorder add_recorder = classinstancemethod(add_recorder) def remove_recorder(cls, self, recorder): """Remove the given recorder from this mocker class or instance. This method may be called on mocker classes and also on mocker instances. See the L{add_recorder()} method for more information. """ (self or cls)._recorders.remove(recorder) remove_recorder = classinstancemethod(remove_recorder) def result(self, value): """Make the last recorded event return the given value on replay. @param value: Object to be returned when the event is replayed. """ self.call(lambda *args, **kwargs: value) def generate(self, sequence): """Last recorded event will return a generator with the given sequence. @param sequence: Sequence of values to be generated. """ def generate(*args, **kwargs): for value in sequence: yield value self.call(generate) def throw(self, exception): """Make the last recorded event raise the given exception on replay. @param exception: Class or instance of exception to be raised. """ def raise_exception(*args, **kwargs): raise exception self.call(raise_exception) def call(self, func): """Make the last recorded event cause the given function to be called. @param func: Function to be called. The result of the function will be used as the event result. """ self._events[-1].add_task(FunctionRunner(func)) def count(self, min, max=False): """Last recorded event must be replayed between min and max times. @param min: Minimum number of times that the event must happen. @param max: Maximum number of times that the event must happen. If not given, it defaults to the same value of the C{min} parameter. If set to None, there is no upper limit, and the expectation is met as long as it happens at least C{min} times. """ event = self._events[-1] for task in event.get_tasks(): if isinstance(task, RunCounter): event.remove_task(task) event.add_task(RunCounter(min, max)) def is_ordering(self): """Return true if all events are being ordered. See the L{order()} method. """ return self._ordering def unorder(self): """Disable the ordered mode. See the L{order()} method for more information. """ self._ordering = False self._last_orderer = None def order(self, *path_holders): """Create an expectation of order between two or more events. @param path_holders: Objects returned as the result of recorded events. By default, mocker won't force events to happen precisely in the order they were recorded. Calling this method will change this behavior so that events will only match if reproduced in the correct order. There are two ways in which this method may be used. Which one is used in a given occasion depends only on convenience. If no arguments are passed, the mocker will be put in a mode where all the recorded events following the method call will only be met if they happen in order. When that's used, the mocker may be put back in unordered mode by calling the L{unorder()} method, or by using a 'with' block, like so:: with mocker.ordered(): In this case, only expressions in will be ordered, and the mocker will be back in unordered mode after the 'with' block. The second way to use it is by specifying precisely which events should be ordered. As an example:: mock = mocker.mock() expr1 = mock.hello() expr2 = mock.world expr3 = mock.x.y.z mocker.order(expr1, expr2, expr3) This method of ordering only works when the expression returns another object. Also check the L{after()} and L{before()} methods, which are alternative ways to perform this. """ if not path_holders: self._ordering = True return OrderedContext(self) last_orderer = None for path_holder in path_holders: if type(path_holder) is Path: path = path_holder else: path = path_holder.__mocker_path__ for event in self._events: if event.path is path: for task in event.get_tasks(): if isinstance(task, Orderer): orderer = task break else: orderer = Orderer(path) event.add_task(orderer) if last_orderer: orderer.add_dependency(last_orderer) last_orderer = orderer break def after(self, *path_holders): """Last recorded event must happen after events referred to. @param path_holders: Objects returned as the result of recorded events which should happen before the last recorded event As an example, the idiom:: expect(mock.x).after(mock.y, mock.z) is an alternative way to say:: expr_x = mock.x expr_y = mock.y expr_z = mock.z mocker.order(expr_y, expr_x) mocker.order(expr_z, expr_x) See L{order()} for more information. """ last_path = self._events[-1].path for path_holder in path_holders: self.order(path_holder, last_path) def before(self, *path_holders): """Last recorded event must happen before events referred to. @param path_holders: Objects returned as the result of recorded events which should happen after the last recorded event As an example, the idiom:: expect(mock.x).before(mock.y, mock.z) is an alternative way to say:: expr_x = mock.x expr_y = mock.y expr_z = mock.z mocker.order(expr_x, expr_y) mocker.order(expr_x, expr_z) See L{order()} for more information. """ last_path = self._events[-1].path for path_holder in path_holders: self.order(last_path, path_holder) def nospec(self): """Don't check method specification of real object on last event. By default, when using a mock created as the result of a call to L{proxy()}, L{replace()}, and C{patch()}, or when passing the spec attribute to the L{mock()} method, method calls on the given object are checked for correctness against the specification of the real object (or the explicitly provided spec). This method will disable that check specifically for the last recorded event. """ event = self._events[-1] for task in event.get_tasks(): if isinstance(task, SpecChecker): event.remove_task(task) def passthrough(self, result_callback=None): """Make the last recorded event run on the real object once seen. @param result_callback: If given, this function will be called with the result of the *real* method call as the only argument. This can only be used on proxies, as returned by the L{proxy()} and L{replace()} methods, or on mocks representing patched objects, as returned by the L{patch()} method. """ event = self._events[-1] if event.path.root_object is None: raise TypeError("Mock object isn't a proxy") event.add_task(PathExecuter(result_callback)) def __enter__(self): """Enter in a 'with' context. This will run replay().""" self.replay() return self def __exit__(self, type, value, traceback): """Exit from a 'with' context. This will run restore() at all times, but will only run verify() if the 'with' block itself hasn't raised an exception. Exceptions in that block are never swallowed. """ self.restore() if type is None: self.verify() return False def _get_replay_restore_event(self): """Return unique L{ReplayRestoreEvent}, creating if needed. Some tasks only want to replay/restore. When that's the case, they shouldn't act on other events during replay. Also, they can all be put in a single event when that's the case. Thus, we add a single L{ReplayRestoreEvent} as the first element of the list. """ if not self._events or type(self._events[0]) != ReplayRestoreEvent: self._events.insert(0, ReplayRestoreEvent()) return self._events[0] class OrderedContext(object): def __init__(self, mocker): self._mocker = mocker def __enter__(self): return None def __exit__(self, type, value, traceback): self._mocker.unorder() class Mocker(MockerBase): __doc__ = MockerBase.__doc__ # Decorator to add recorders on the standard Mocker class. recorder = Mocker.add_recorder # -------------------------------------------------------------------- # Mock object. class Mock(object): def __init__(self, mocker, path=None, name=None, spec=None, type=None, object=None, passthrough=False, patcher=None, count=True): self.__mocker__ = mocker self.__mocker_path__ = path or Path(self, object) self.__mocker_name__ = name self.__mocker_spec__ = spec self.__mocker_object__ = object self.__mocker_passthrough__ = passthrough self.__mocker_patcher__ = patcher self.__mocker_replace__ = False self.__mocker_type__ = type self.__mocker_count__ = count def __mocker_act__(self, kind, args=(), kwargs={}, object=None): if self.__mocker_name__ is None: self.__mocker_name__ = find_object_name(self, 2) action = Action(kind, args, kwargs, self.__mocker_path__) path = self.__mocker_path__ + action if object is not None: path.root_object = object try: return self.__mocker__.act(path) except MatchError, exception: root_mock = path.root_mock if (path.root_object is not None and root_mock.__mocker_passthrough__): return path.execute(path.root_object) # Reinstantiate to show raise statement on traceback, and # also to make the traceback shown shorter. raise MatchError(str(exception)) except AssertionError, e: lines = str(e).splitlines() message = [ERROR_PREFIX + "Unmet expectation:", ""] message.append("=> " + lines.pop(0)) message.extend([" " + line for line in lines]) message.append("") raise AssertionError(os.linesep.join(message)) def __getattribute__(self, name): if name.startswith("__mocker_"): return super(Mock, self).__getattribute__(name) if name == "__class__": if self.__mocker__.is_recording() or self.__mocker_type__ is None: return type(self) return self.__mocker_type__ return self.__mocker_act__("getattr", (name,)) def __setattr__(self, name, value): if name.startswith("__mocker_"): return super(Mock, self).__setattr__(name, value) return self.__mocker_act__("setattr", (name, value)) def __delattr__(self, name): return self.__mocker_act__("delattr", (name,)) def __call__(self, *args, **kwargs): return self.__mocker_act__("call", args, kwargs) def __contains__(self, value): return self.__mocker_act__("contains", (value,)) def __getitem__(self, key): return self.__mocker_act__("getitem", (key,)) def __setitem__(self, key, value): return self.__mocker_act__("setitem", (key, value)) def __delitem__(self, key): return self.__mocker_act__("delitem", (key,)) def __len__(self): # MatchError is turned on an AttributeError so that list() and # friends act properly when trying to get length hints on # something that doesn't offer them. try: result = self.__mocker_act__("len") except MatchError, e: raise AttributeError(str(e)) if type(result) is Mock: return 0 return result def __nonzero__(self): try: result = self.__mocker_act__("nonzero") except MatchError, e: return True if type(result) is Mock: return True return result def __iter__(self): # XXX On py3k, when next() becomes __next__(), we'll be able # to return the mock itself because it will be considered # an iterator (we'll be mocking __next__ as well, which we # can't now). result = self.__mocker_act__("iter") if type(result) is Mock: return iter([]) return result # When adding a new action kind here, also add support for it on # Action.execute() and Path.__str__(). def find_object_name(obj, depth=0): """Try to detect how the object is named on a previous scope.""" try: frame = sys._getframe(depth+1) except: return None for name, frame_obj in frame.f_locals.iteritems(): if frame_obj is obj: return name self = frame.f_locals.get("self") if self is not None: try: items = list(self.__dict__.iteritems()) except: pass else: for name, self_obj in items: if self_obj is obj: return name return None # -------------------------------------------------------------------- # Action and path. class Action(object): def __init__(self, kind, args, kwargs, path=None): self.kind = kind self.args = args self.kwargs = kwargs self.path = path self._execute_cache = {} def __repr__(self): if self.path is None: return "Action(%r, %r, %r)" % (self.kind, self.args, self.kwargs) return "Action(%r, %r, %r, %r)" % \ (self.kind, self.args, self.kwargs, self.path) def __eq__(self, other): return (self.kind == other.kind and self.args == other.args and self.kwargs == other.kwargs) def __ne__(self, other): return not self.__eq__(other) def matches(self, other): return (self.kind == other.kind and match_params(self.args, self.kwargs, other.args, other.kwargs)) def execute(self, object): # This caching scheme may fail if the object gets deallocated before # the action, as the id might get reused. It's somewhat easy to fix # that with a weakref callback. For our uses, though, the object # should never get deallocated before the action itself, so we'll # just keep it simple. if id(object) in self._execute_cache: return self._execute_cache[id(object)] execute = getattr(object, "__mocker_execute__", None) if execute is not None: result = execute(self, object) else: kind = self.kind if kind == "getattr": result = getattr(object, self.args[0]) elif kind == "setattr": result = setattr(object, self.args[0], self.args[1]) elif kind == "delattr": result = delattr(object, self.args[0]) elif kind == "call": result = object(*self.args, **self.kwargs) elif kind == "contains": result = self.args[0] in object elif kind == "getitem": result = object[self.args[0]] elif kind == "setitem": result = object[self.args[0]] = self.args[1] elif kind == "delitem": del object[self.args[0]] result = None elif kind == "len": result = len(object) elif kind == "nonzero": result = bool(object) elif kind == "iter": result = iter(object) else: raise RuntimeError("Don't know how to execute %r kind." % kind) self._execute_cache[id(object)] = result return result class Path(object): def __init__(self, root_mock, root_object=None, actions=()): self.root_mock = root_mock self.root_object = root_object self.actions = tuple(actions) self.__mocker_replace__ = False def parent_path(self): if not self.actions: return None return self.actions[-1].path parent_path = property(parent_path) def __add__(self, action): """Return a new path which includes the given action at the end.""" return self.__class__(self.root_mock, self.root_object, self.actions + (action,)) def __eq__(self, other): """Verify if the two paths are equal. Two paths are equal if they refer to the same mock object, and have the actions with equal kind, args and kwargs. """ if (self.root_mock is not other.root_mock or self.root_object is not other.root_object or len(self.actions) != len(other.actions)): return False for action, other_action in zip(self.actions, other.actions): if action != other_action: return False return True def matches(self, other): """Verify if the two paths are equivalent. Two paths are equal if they refer to the same mock object, and have the same actions performed on them. """ if (self.root_mock is not other.root_mock or len(self.actions) != len(other.actions)): return False for action, other_action in zip(self.actions, other.actions): if not action.matches(other_action): return False return True def execute(self, object): """Execute all actions sequentially on object, and return result. """ for action in self.actions: object = action.execute(object) return object def __str__(self): """Transform the path into a nice string such as obj.x.y('z').""" result = self.root_mock.__mocker_name__ or "" for action in self.actions: if action.kind == "getattr": result = "%s.%s" % (result, action.args[0]) elif action.kind == "setattr": result = "%s.%s = %r" % (result, action.args[0], action.args[1]) elif action.kind == "delattr": result = "del %s.%s" % (result, action.args[0]) elif action.kind == "call": args = [repr(x) for x in action.args] items = list(action.kwargs.iteritems()) items.sort() for pair in items: args.append("%s=%r" % pair) result = "%s(%s)" % (result, ", ".join(args)) elif action.kind == "contains": result = "%r in %s" % (action.args[0], result) elif action.kind == "getitem": result = "%s[%r]" % (result, action.args[0]) elif action.kind == "setitem": result = "%s[%r] = %r" % (result, action.args[0], action.args[1]) elif action.kind == "delitem": result = "del %s[%r]" % (result, action.args[0]) elif action.kind == "len": result = "len(%s)" % result elif action.kind == "nonzero": result = "bool(%s)" % result elif action.kind == "iter": result = "iter(%s)" % result else: raise RuntimeError("Don't know how to format kind %r" % action.kind) return result class SpecialArgument(object): """Base for special arguments for matching parameters.""" def __init__(self, object=None): self.object = object def __repr__(self): if self.object is None: return self.__class__.__name__ else: return "%s(%r)" % (self.__class__.__name__, self.object) def matches(self, other): return True def __eq__(self, other): return type(other) == type(self) and self.object == other.object class ANY(SpecialArgument): """Matches any single argument.""" ANY = ANY() class ARGS(SpecialArgument): """Matches zero or more positional arguments.""" ARGS = ARGS() class KWARGS(SpecialArgument): """Matches zero or more keyword arguments.""" KWARGS = KWARGS() class IS(SpecialArgument): def matches(self, other): return self.object is other def __eq__(self, other): return type(other) == type(self) and self.object is other.object class CONTAINS(SpecialArgument): def matches(self, other): try: other.__contains__ except AttributeError: try: iter(other) except TypeError: # If an object can't be iterated, and has no __contains__ # hook, it'd blow up on the test below. We test this in # advance to prevent catching more errors than we really # want. return False return self.object in other class IN(SpecialArgument): def matches(self, other): return other in self.object class MATCH(SpecialArgument): def matches(self, other): return bool(self.object(other)) def __eq__(self, other): return type(other) == type(self) and self.object is other.object def match_params(args1, kwargs1, args2, kwargs2): """Match the two sets of parameters, considering special parameters.""" has_args = ARGS in args1 has_kwargs = KWARGS in args1 if has_kwargs: args1 = [arg1 for arg1 in args1 if arg1 is not KWARGS] elif len(kwargs1) != len(kwargs2): return False if not has_args and len(args1) != len(args2): return False # Either we have the same number of kwargs, or unknown keywords are # accepted (KWARGS was used), so check just the ones in kwargs1. for key, arg1 in kwargs1.iteritems(): if key not in kwargs2: return False arg2 = kwargs2[key] if isinstance(arg1, SpecialArgument): if not arg1.matches(arg2): return False elif arg1 != arg2: return False # Keywords match. Now either we have the same number of # arguments, or ARGS was used. If ARGS wasn't used, arguments # must match one-on-one necessarily. if not has_args: for arg1, arg2 in zip(args1, args2): if isinstance(arg1, SpecialArgument): if not arg1.matches(arg2): return False elif arg1 != arg2: return False return True # Easy choice. Keywords are matching, and anything on args is accepted. if (ARGS,) == args1: return True # We have something different there. If we don't have positional # arguments on the original call, it can't match. if not args2: # Unless we have just several ARGS (which is bizarre, but..). for arg1 in args1: if arg1 is not ARGS: return False return True # Ok, all bets are lost. We have to actually do the more expensive # matching. This is an algorithm based on the idea of the Levenshtein # Distance between two strings, but heavily hacked for this purpose. args2l = len(args2) if args1[0] is ARGS: args1 = args1[1:] array = [0]*args2l else: array = [1]*args2l for i in range(len(args1)): last = array[0] if args1[i] is ARGS: for j in range(1, args2l): last, array[j] = array[j], min(array[j-1], array[j], last) else: array[0] = i or int(args1[i] != args2[0]) for j in range(1, args2l): last, array[j] = array[j], last or int(args1[i] != args2[j]) if 0 not in array: return False if array[-1] != 0: return False return True # -------------------------------------------------------------------- # Event and task base. class Event(object): """Aggregation of tasks that keep track of a recorded action. An event represents something that may or may not happen while the mocked environment is running, such as an attribute access, or a method call. The event is composed of several tasks that are orchestrated together to create a composed meaning for the event, including for which actions it should be run, what happens when it runs, and what's the expectations about the actions run. """ def __init__(self, path=None): self.path = path self._tasks = [] self._has_run = False def add_task(self, task): """Add a new task to this taks.""" self._tasks.append(task) return task def remove_task(self, task): self._tasks.remove(task) def get_tasks(self): return self._tasks[:] def matches(self, path): """Return true if *all* tasks match the given path.""" for task in self._tasks: if not task.matches(path): return False return bool(self._tasks) def has_run(self): return self._has_run def may_run(self, path): """Verify if any task would certainly raise an error if run. This will call the C{may_run()} method on each task and return false if any of them returns false. """ for task in self._tasks: if not task.may_run(path): return False return True def run(self, path): """Run all tasks with the given action. @param path: The path of the expression run. Running an event means running all of its tasks individually and in order. An event should only ever be run if all of its tasks claim to match the given action. The result of this method will be the last result of a task which isn't None, or None if they're all None. """ self._has_run = True result = None errors = [] for task in self._tasks: try: task_result = task.run(path) except AssertionError, e: error = str(e) if not error: raise RuntimeError("Empty error message from %r" % task) errors.append(error) else: if task_result is not None: result = task_result if errors: message = [str(self.path)] if str(path) != message[0]: message.append("- Run: %s" % path) for error in errors: lines = error.splitlines() message.append("- " + lines.pop(0)) message.extend([" " + line for line in lines]) raise AssertionError(os.linesep.join(message)) return result def satisfied(self): """Return true if all tasks are satisfied. Being satisfied means that there are no unmet expectations. """ for task in self._tasks: try: task.verify() except AssertionError: return False return True def verify(self): """Run verify on all tasks. The verify method is supposed to raise an AssertionError if the task has unmet expectations, with a one-line explanation about why this item is unmet. This method should be safe to be called multiple times without side effects. """ errors = [] for task in self._tasks: try: task.verify() except AssertionError, e: error = str(e) if not error: raise RuntimeError("Empty error message from %r" % task) errors.append(error) if errors: message = [str(self.path)] for error in errors: lines = error.splitlines() message.append("- " + lines.pop(0)) message.extend([" " + line for line in lines]) raise AssertionError(os.linesep.join(message)) def replay(self): """Put all tasks in replay mode.""" self._has_run = False for task in self._tasks: task.replay() def restore(self): """Restore the state of all tasks.""" for task in self._tasks: task.restore() class ReplayRestoreEvent(Event): """Helper event for tasks which need replay/restore but shouldn't match.""" def matches(self, path): return False class Task(object): """Element used to track one specific aspect on an event. A task is responsible for adding any kind of logic to an event. Examples of that are counting the number of times the event was made, verifying parameters if any, and so on. """ def matches(self, path): """Return true if the task is supposed to be run for the given path. """ return True def may_run(self, path): """Return false if running this task would certainly raise an error.""" return True def run(self, path): """Perform the task item, considering that the given action happened. """ def verify(self): """Raise AssertionError if expectations for this item are unmet. The verify method is supposed to raise an AssertionError if the task has unmet expectations, with a one-line explanation about why this item is unmet. This method should be safe to be called multiple times without side effects. """ def replay(self): """Put the task in replay mode. Any expectations of the task should be reset. """ def restore(self): """Restore any environmental changes made by the task. Verify should continue to work after this is called. """ # -------------------------------------------------------------------- # Task implementations. class OnRestoreCaller(Task): """Call a given callback when restoring.""" def __init__(self, callback): self._callback = callback def restore(self): self._callback() class PathMatcher(Task): """Match the action path against a given path.""" def __init__(self, path): self.path = path def matches(self, path): return self.path.matches(path) def path_matcher_recorder(mocker, event): event.add_task(PathMatcher(event.path)) Mocker.add_recorder(path_matcher_recorder) class RunCounter(Task): """Task which verifies if the number of runs are within given boundaries. """ def __init__(self, min, max=False): self.min = min if max is None: self.max = sys.maxint elif max is False: self.max = min else: self.max = max self._runs = 0 def replay(self): self._runs = 0 def may_run(self, path): return self._runs < self.max def run(self, path): self._runs += 1 if self._runs > self.max: self.verify() def verify(self): if not self.min <= self._runs <= self.max: if self._runs < self.min: raise AssertionError("Performed fewer times than expected.") raise AssertionError("Performed more times than expected.") class ImplicitRunCounter(RunCounter): """RunCounter inserted by default on any event. This is a way to differentiate explicitly added counters and implicit ones. """ def run_counter_recorder(mocker, event): """Any event may be repeated once, unless disabled by default.""" if event.path.root_mock.__mocker_count__: event.add_task(ImplicitRunCounter(1)) Mocker.add_recorder(run_counter_recorder) def run_counter_removal_recorder(mocker, event): """ Events created by getattr actions which lead to other events may be repeated any number of times. For that, we remove implicit run counters of any getattr actions leading to the current one. """ parent_path = event.path.parent_path for event in mocker.get_events()[::-1]: if (event.path is parent_path and event.path.actions[-1].kind == "getattr"): for task in event.get_tasks(): if type(task) is ImplicitRunCounter: event.remove_task(task) Mocker.add_recorder(run_counter_removal_recorder) class MockReturner(Task): """Return a mock based on the action path.""" def __init__(self, mocker): self.mocker = mocker def run(self, path): return Mock(self.mocker, path) def mock_returner_recorder(mocker, event): """Events that lead to other events must return mock objects.""" parent_path = event.path.parent_path for event in mocker.get_events(): if event.path is parent_path: for task in event.get_tasks(): if isinstance(task, MockReturner): break else: event.add_task(MockReturner(mocker)) break Mocker.add_recorder(mock_returner_recorder) class FunctionRunner(Task): """Task that runs a function everything it's run. Arguments of the last action in the path are passed to the function, and the function result is also returned. """ def __init__(self, func): self._func = func def run(self, path): action = path.actions[-1] return self._func(*action.args, **action.kwargs) class PathExecuter(Task): """Task that executes a path in the real object, and returns the result.""" def __init__(self, result_callback=None): self._result_callback = result_callback def get_result_callback(self): return self._result_callback def run(self, path): result = path.execute(path.root_object) if self._result_callback is not None: self._result_callback(result) return result class Orderer(Task): """Task to establish an order relation between two events. An orderer task will only match once all its dependencies have been run. """ def __init__(self, path): self.path = path self._run = False self._dependencies = [] def replay(self): self._run = False def has_run(self): return self._run def may_run(self, path): for dependency in self._dependencies: if not dependency.has_run(): return False return True def run(self, path): for dependency in self._dependencies: if not dependency.has_run(): raise AssertionError("Should be after: %s" % dependency.path) self._run = True def add_dependency(self, orderer): self._dependencies.append(orderer) def get_dependencies(self): return self._dependencies class SpecChecker(Task): """Task to check if arguments of the last action conform to a real method. """ def __init__(self, method): self._method = method self._unsupported = False if method: try: self._args, self._varargs, self._varkwargs, self._defaults = \ inspect.getargspec(method) except TypeError: self._unsupported = True else: if self._defaults is None: self._defaults = () if type(method) is type(self.run): self._args = self._args[1:] def get_method(self): return self._method def _raise(self, message): spec = inspect.formatargspec(self._args, self._varargs, self._varkwargs, self._defaults) raise AssertionError("Specification is %s%s: %s" % (self._method.__name__, spec, message)) def verify(self): if not self._method: raise AssertionError("Method not found in real specification") def may_run(self, path): try: self.run(path) except AssertionError: return False return True def run(self, path): if not self._method: raise AssertionError("Method not found in real specification") if self._unsupported: return # Can't check it. Happens with builtin functions. :-( action = path.actions[-1] obtained_len = len(action.args) obtained_kwargs = action.kwargs.copy() nodefaults_len = len(self._args) - len(self._defaults) for i, name in enumerate(self._args): if i < obtained_len and name in action.kwargs: self._raise("%r provided twice" % name) if (i >= obtained_len and i < nodefaults_len and name not in action.kwargs): self._raise("%r not provided" % name) obtained_kwargs.pop(name, None) if obtained_len > len(self._args) and not self._varargs: self._raise("too many args provided") if obtained_kwargs and not self._varkwargs: self._raise("unknown kwargs: %s" % ", ".join(obtained_kwargs)) def spec_checker_recorder(mocker, event): spec = event.path.root_mock.__mocker_spec__ if spec: actions = event.path.actions if len(actions) == 1: if actions[0].kind == "call": method = getattr(spec, "__call__", None) event.add_task(SpecChecker(method)) elif len(actions) == 2: if actions[0].kind == "getattr" and actions[1].kind == "call": method = getattr(spec, actions[0].args[0], None) event.add_task(SpecChecker(method)) Mocker.add_recorder(spec_checker_recorder) class ProxyReplacer(Task): """Task which installs and deinstalls proxy mocks. This task will replace a real object by a mock in all dictionaries found in the running interpreter via the garbage collecting system. """ def __init__(self, mock): self.mock = mock self.__mocker_replace__ = False def replay(self): global_replace(self.mock.__mocker_object__, self.mock) def restore(self): global_replace(self.mock, self.mock.__mocker_object__) def global_replace(remove, install): """Replace object 'remove' with object 'install' on all dictionaries.""" for referrer in gc.get_referrers(remove): if (type(referrer) is dict and referrer.get("__mocker_replace__", True)): for key, value in list(referrer.iteritems()): if value is remove: referrer[key] = install class Undefined(object): def __repr__(self): return "Undefined" Undefined = Undefined() class Patcher(Task): def __init__(self): super(Patcher, self).__init__() self._monitored = {} # {kind: {id(object): object}} self._patched = {} def is_monitoring(self, obj, kind): monitored = self._monitored.get(kind) if monitored: if id(obj) in monitored: return True cls = type(obj) if issubclass(cls, type): cls = obj bases = set([id(base) for base in cls.__mro__]) bases.intersection_update(monitored) return bool(bases) return False def monitor(self, obj, kind): if kind not in self._monitored: self._monitored[kind] = {} self._monitored[kind][id(obj)] = obj def patch_attr(self, obj, attr, value): original = obj.__dict__.get(attr, Undefined) self._patched[id(obj), attr] = obj, attr, original setattr(obj, attr, value) def get_unpatched_attr(self, obj, attr): cls = type(obj) if issubclass(cls, type): cls = obj result = Undefined for mro_cls in cls.__mro__: key = (id(mro_cls), attr) if key in self._patched: result = self._patched[key][2] if result is not Undefined: break elif attr in mro_cls.__dict__: result = mro_cls.__dict__.get(attr, Undefined) break if isinstance(result, object) and hasattr(type(result), "__get__"): if cls is obj: obj = None return result.__get__(obj, cls) return result def _get_kind_attr(self, kind): if kind == "getattr": return "__getattribute__" return "__%s__" % kind def replay(self): for kind in self._monitored: attr = self._get_kind_attr(kind) seen = set() for obj in self._monitored[kind].itervalues(): cls = type(obj) if issubclass(cls, type): cls = obj if cls not in seen: seen.add(cls) unpatched = getattr(cls, attr, Undefined) self.patch_attr(cls, attr, PatchedMethod(kind, unpatched, self.is_monitoring)) self.patch_attr(cls, "__mocker_execute__", self.execute) def restore(self): for obj, attr, original in self._patched.itervalues(): if original is Undefined: delattr(obj, attr) else: setattr(obj, attr, original) self._patched.clear() def execute(self, action, object): attr = self._get_kind_attr(action.kind) unpatched = self.get_unpatched_attr(object, attr) try: return unpatched(*action.args, **action.kwargs) except AttributeError: type, value, traceback = sys.exc_info() if action.kind == "getattr": # The normal behavior of Python is to try __getattribute__, # and if it raises AttributeError, try __getattr__. We've # tried the unpatched __getattribute__ above, and we'll now # try __getattr__. try: __getattr__ = unpatched("__getattr__") except AttributeError: pass else: return __getattr__(*action.args, **action.kwargs) raise type, value, traceback class PatchedMethod(object): def __init__(self, kind, unpatched, is_monitoring): self._kind = kind self._unpatched = unpatched self._is_monitoring = is_monitoring def __get__(self, obj, cls=None): object = obj or cls if not self._is_monitoring(object, self._kind): return self._unpatched.__get__(obj, cls) def method(*args, **kwargs): if self._kind == "getattr" and args[0].startswith("__mocker_"): return self._unpatched.__get__(obj, cls)(args[0]) mock = object.__mocker_mock__ return mock.__mocker_act__(self._kind, args, kwargs, object) return method def __call__(self, obj, *args, **kwargs): # At least with __getattribute__, Python seems to use *both* the # descriptor API and also call the class attribute directly. It # looks like an interpreter bug, or at least an undocumented # inconsistency. return self.__get__(obj)(*args, **kwargs) def patcher_recorder(mocker, event): mock = event.path.root_mock if mock.__mocker_patcher__ and len(event.path.actions) == 1: patcher = mock.__mocker_patcher__ patcher.monitor(mock.__mocker_object__, event.path.actions[0].kind) Mocker.add_recorder(patcher_recorder) mago-0.3+bzr20/xpresser/lib/testing.py0000644000000000000000000000171511516265061017647 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # from twisted.trial.unittest import TestCase as TrialTestCase from xpresser.lib.mocker import MockerTestCase class TestCase(MockerTestCase, TrialTestCase): """Base class for all Ensemble tests. Common useful logic goes here.""" mago-0.3+bzr20/xpresser/opencvfinder.py0000644000000000000000000001310611516265061020103 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # import math import time import numpy import opencv import opencv.highgui import opencv.adaptors from xpresser.imagematch import ImageMatch FILTER_MARGIN = 25 # % DEBUG_PERFORMANCE = False class OpenCVFinder(object): def find(self, screen_image, area_image): matches = self._find(screen_image, area_image, best_match=True) if matches: matches.sort(key=lambda match: -match.similarity) return matches[0] return None def find_all(self, screen_image, area_image): return self._find(screen_image, area_image) def _load_image(self, image): print "*** loading %s" % image.filename if "opencv_image" not in image.cache: if image.filename is not None: opencv_image = opencv.highgui.cvLoadImage(image.filename) elif image.array is not None: # The adaptor function can't deal with the alpha channel. array = image.array[:,:,:3] opencv_image = opencv.adaptors.NumPy2Ipl(array) else: raise RuntimeError("Oops. Can't load image.") image.cache["opencv_image"] = opencv_image image.width = opencv_image.width image.height = opencv_image.height return image.cache["opencv_image"] def _find(self, screen_image, area_image, best_match=False): if DEBUG_PERFORMANCE: started = time.time() screen = self._load_image(screen_image) area = self._load_image(area_image) if DEBUG_PERFORMANCE: print "LOADING IMAGES: %.5fs" % (time.time()-started) result_width = screen.width - area.width + 1 result_height = screen.height - area.height + 1 result = opencv.cvCreateImage(opencv.cvSize(result_width, result_height), opencv.IPL_DEPTH_32F, 1) if DEBUG_PERFORMANCE: started = time.time() opencv.cvMatchTemplate(screen, area, result, opencv.CV_TM_CCORR_NORMED) if DEBUG_PERFORMANCE: print "MATCHING: %.5fs" % (time.time()-started) result = opencv.adaptors.Ipl2NumPy(result) if DEBUG_PERFORMANCE: started = time.time() matches = [] for y, x in numpy.argwhere(result >= area_image.similarity): matches.append(ImageMatch(area_image, x, y, result[y, x])) if best_match and result[y, x] == 1.0: return [matches[-1]] if DEBUG_PERFORMANCE: print "FINDING POSITIONS: %.5fs" % (time.time()-started) x_margin = int(FILTER_MARGIN/100.0 * area_image.width) y_margin = int(FILTER_MARGIN/100.0 * area_image.height) if DEBUG_PERFORMANCE: started = time.time() matches = self._filter_nearby_positions(matches, x_margin, y_margin) if DEBUG_PERFORMANCE: print "FILTERING: %.5fs" % (time.time()-started) return matches def _filter_nearby_positions(self, matches, x_margin, y_margin): """Remove nearby positions by taking the best one. Doing this is necessary because around a good match there will likely be other worse matches. """ # We have to build a kill list rather than removing on the fly # so that neighbors of neighbors get correctly processed. kill = set() for match1 in matches: if match1 in kill: # Another match has already figured that this one isn't good. continue for match2 in matches: if match2 is match1: continue # Even if match2 is in the kill list, we have to process it # because it may have a better rating than this one still, and # this would mean someone around is even better than match2, # and thus both match2 *and* match1 should be killed. #distance = math.hypot(match2.x-match1.x, match2.y-match1.y) #if distance <= filter_distance: if (abs(match2.x-match1.x) < x_margin or abs(match2.y-match1.y) < y_margin): comparison = cmp(match1.similarity, match2.similarity) if comparison > 0: # match2 is worse, so ensure it's in the kill list # and maybe save time later on (if indeed it wasn't yet). kill.add(match2) elif (comparison < 0 or (comparison == 0 and match2 not in kill)): # If match2 matches better than match1, or they're # equivalent and match2 is not in the kill list yet, # so kill match1 and move on to a different match1. kill.add(match1) break return list(set(matches) - kill) mago-0.3+bzr20/xpresser/tests/0000755000000000000000000000000011516265061016210 5ustar rootroot00000000000000mago-0.3+bzr20/xpresser/tests/__init__.py0000644000000000000000000000000011516265061020307 0ustar rootroot00000000000000mago-0.3+bzr20/xpresser/tests/images/0000755000000000000000000000000011516265061017455 5ustar rootroot00000000000000mago-0.3+bzr20/xpresser/tests/images/__init__.py0000644000000000000000000000161611516265061021572 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # import os def get_image_path(basename=None): path = os.path.dirname(__file__) if basename is not None: path = os.path.join(path, basename) return path mago-0.3+bzr20/xpresser/tests/images/blue-circle.png0000644000000000000000000000150511516265061022352 0ustar rootroot00000000000000PNG  IHDR22?sRGBbKGD pHYs % %Tv7E)2"4e3lj2.'>gzEj3OjyEj6<Dأ+5**)@8ʈbuQpΫ BW fNp0J%McuO+ceR4dZL8&ۭ /cAa(oxA aEYsE*!r!] ; l`~/ *&m[{۶UHC UCqy1ēpƔ ՋUݔYF-@gԒ1Fm+c֛1FmOw`#FcN7<"'IENDB`mago-0.3+bzr20/xpresser/tests/images/blue-ellipse.png0000644000000000000000000000152711516265061022552 0ustar rootroot00000000000000PNG  IHDR(2.sRGBbKGD pHYs % %;c}##o(`j_E=8ȉQX,<5t? XtIENDB`mago-0.3+bzr20/xpresser/tests/images/blue-square.png0000644000000000000000000000041611516265061022411 0ustar rootroot00000000000000PNG  IHDR22?sBIT|d pHYs % %йwB+QD;R(߀r+ɢOi*.9[x,%9 [:3g.WDD8Aq#Ii`6YWuq}}:!h<j^j4Iq¡s,_7 ܁e}6,89A@v)6@v <Ͽ$"t:Q wٳ|:EQtZ0 1 Oisnc0<(  6m*ےC*0(f?x;Deoyav4<3BT.ۮyf/0 QGfWؽo6TͰ9NCl}3}B8 @}R G3/ B5b/sFU9o!T/2+ & VUqZa2*b2_~ZYIH#eYF,c,=OZ%8Ks^#{@$`iW?_488@n5TN:, 0Rm/zٶm0qqjnynyxIj.II G3/|V/Rk])S]Z2fΨ%ScV0jǨ7c6Cڞ6QG8:TsǜL9x|>"g\IENDB`mago-0.3+bzr20/xpresser/tests/images/green-ellipse.png0000644000000000000000000000153111516265061022716 0ustar rootroot00000000000000PNG  IHDR(2.sRGBbKGD pHYs % %탰A\nB<{fm3L߂8]u_>&Iڶ<`#3pAt_zӀRp_@n>jH$3qA.t[ztl6p@ܼ.=l6t0Z*qAz,j@M.H74, w X,tqB T* XdY+ʟx>V"xL8% `X.p n_X-mX5sJ)z.oZf)%9q{%kڢwvj*?F-.DWWaNhK߇}_]3-w 'd! iT*e,0J`/WBA]4-Bƿ,%(JjNP* TCu.EԆUMŇX/Ţi| 8EXC 'Ga8L82@7XE{IENDB`mago-0.3+bzr20/xpresser/tests/images/green-square.png0000644000000000000000000000036511516265061022565 0ustar rootroot00000000000000PNG  IHDR22?sRGBbKGD pHYs % % image/svg+xml mago-0.3+bzr20/xpresser/tests/images/red-circle-with-blue-circle.png0000644000000000000000000000206011516265061025327 0ustar rootroot00000000000000PNG  IHDR22?sRGBbKGD pHYs % %hUҦ@UT"V ZhuaV] Vj5k\<)=OIENDB`mago-0.3+bzr20/xpresser/tests/images/red-circle.png0000644000000000000000000000150311516265061022173 0ustar rootroot00000000000000PNG  IHDR22?sRGBbKGD pHYs % %>f/!$Id<tING|ߗx,INJVضs W K]i>g۶( Ht5}k[yng n+AH2N~Arm/e׀zLa(eU Af{hjV[cYa~(d4U/>nʶtHxHQ2 '@h=5`0/VzOyDz@h4`6e'=_z_KyBO3ܜg@ L `3H$Ռ=<@a3Rg 2UJu$IP0W,drrd2#WVZ"}ʲZ]亶8˲L(X,=. (ŠE g84 9MBwY A zߩ  Crgq\m=+ &W¼*)2A|. @/f &6Nx;e-^<!_;d,p2Dxd%L' gD"w8r|rh-\_ P(с嵆B@?ԇ7Jưnr)pwH40oGcHD(,azhXIENDB`mago-0.3+bzr20/xpresser/tests/images/red-square.png0000644000000000000000000000041611516265061022234 0ustar rootroot00000000000000PNG  IHDR22?sBIT|d pHYs % %\]pG200+W5κud޽lٲE^`m>GzfZm|'|j(yAVqƯe¿;j(>}g>(Aj(֎9}@D켝(d/2<<}b=<<ŋQ`o dOcx x<<=a``@֩S*YKr';\P!377K &&&P<傂A:11K 4_N7K>xEE=6\z5ȒDX(ֺ ,Q`M\v͵MD%Q`K>EE6TWW6(D{X" ,o.*(&xo\T7KjQ` ۳&_\P/gm" ,hjj 怯]PTUUԤK غukɗ.(ְul(iΝL 1gM" ,q$ _??P(Dgg# ,7֖}A nkkcƍj(~ΗvZDXr3۷o!{&#`A3Kn⌏8|! ,;vodϻfرC,Ommm{LgjkkyQ`|g "膝eOcϸQ`ɝyg Wpv `?g}V ^Xrw^{5>AY iK k. ,7:~!_?O?_ׂ7|H$@ ]_qg!W_ojx!1j\:fDk/ۆnr7| Ām~ }8tpX[6@ Hl:V΅ 8z(\reY[N˖-[J ,m ,5dd2N83g&H0== @]]7om۶k.*++F ,}KAwQ`(DD%"Q`KDD%"KDD%" ,KDX"" ,(DDX"" ,Q`(DDX"Q`(DD%"(DDX"Q`(DD%"Q`KDD%"KDD%" ,KDX"" ,[X R)FFF8wd2?|lذP__Okk+k֬Q@Ycd8qgΜazzD"4uuul޼:mƮ]ʿÚL&㌏dhJZZZؽ{7mmmԨ! ,OpGe``+W,ku޽{ٲeRi+L K~x~Z4V(: hX/+N~hm77ߝ÷@ H;zo>:D8V:pR1p{0qM+JŞ;XnxfcZ|A]fsښڵk|hP f(555.%* e֬J\zG\T#Kji`y:5 ,YZ뢚*]YGXRT1 Q`*au`iֆ ,?[s5~]TӏKjU`nZX]X|X^j(<~/w=W\Y8֭{eR)J122¹sH&!w 6PSSimmXe)p Μ94Diؼy3uuul۶]v9+X""Ŧ;?KDD%" ,KDX"" ,(DDX"" ,Q`(DDX"Q`(DD%"Q`KDD%"KDD%" ,(DD%"KDD%" ,KDX"" ,(DDX"" ,Q`(DDX"Q`Rݎd8qgΜazzD"4uuul޼:mƮ]^ETΝ;G2=6l&?ʚ5k c̝p=W\Y8֭{e-"I& sqd2w4~ee%---޽6jjjPoV:fDQ ǁMv÷@ Hggo>:D8Foo//CQ;\Ci4C8p@ n~XfD"Cs!e>?~$1xȽIRDŽaGo0`sg8&J4bxY̲qV45v=``vdTTTh4.b1S]]_C`$9!arl(&i/0taHAH+aR?~7M   sCN L;g`~m3At' >56 ү);m㖁544h«npN3Ї/C:6v=EI;|M:V?N!~a?nX& L6& Q%m6Eǩ.BXKKo577:F V!r_K?~X. ZW;LmmU2݂0W1ru;o; W1r_}ԏVww]k \]ઝ[tc$ΰZ(AX内%cZ~ Ukaqh{?ؘ *nCcccJ(X,?X=i5:U~X=i5s%3ihhPJYT*|j9Ǵ;`*Z1ߏO>$>()&''9}N<ȵk88) 5\vnnHY#\/ݻzoK߻|rVY-Zg`_|E{VKZ˻č4/fff|X]]]3ا\XS3⻺ʾtRJ\*~`163PրU ar ]\VGԩSv{ d58kjgxx᥆c?sssqt JǙe`?~F{lY{9Ë )~'&&l0TO*昘]XR)ǁƼ"W8T,ņ[?S\P}|yzHʔ^ L&HYË )~']TVBmq9 {a`kvrꇗRN^z>|Eeek)d^Ek5S?ܐr#ֺ,/^ )Uk &w:/V5S?ܐr," ~>Eeek)6lK^C9 )~]X#wL/V93Z<ܐr\x0i )Ee΃W΁ᆔU`=7.*+[K6'`CuOښ冔S?۷o'_\P/(TVVPݹZ+++imm-~x!֏`SSUUU J&֚5khiil`f͚RnVUUuVKa֭6Hgf_W0,0l >okvv_j灩5J[hoo_ZKg v#ZKg;9::8e";i JߑNMsss~l\cZ٤i#LW֥Ÿ~Pou^5pcvٿHHW鿇's~[Ó~~Ag $V`Oie+J${.TN muU01;E:tp_~! 00xDQw)n6XJiaU]]k?aXJiKxD"B375Z[?x<R)S8q|=0g qǩrgL >r r        r r> >%%HHFFKKSS XX == .. WW    !!##%%%$%%##!!   RѰR## 55kk ee [[ EE  @@> >  """>$>|$|$$$$$%$$м$$|$|>$>"""  > >@@  EE [[ ee kk55 ##RѰR 22 Green Circle      22 22  # % % ')++--///.//--++)' % % #  /JffJ/2΀2ccLL 22 WW WW22 "L$L$c&c&2(2((*/*/J*Jf*f**f*fJ*J/*/*((2(2&c&c$L$L" 22WW WW 22 LLcc2΀2/JffJ/  # % % ')++--///.//--++)' % % # \\j jMMyy   " y$yM$M&((**j,j,,\.\...../....\.\,,j,j**((&M$My$y "   yyMMj j\\22 Blue Square     dd\22p22  e W*W _*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*_ W*W d (2 Blue Ellipse      (2(2'   !!##%%%$%%##!!     !!##%%%$%%##!!    WW .. == XX SSKKFFHH%%> >r r        r r> >%%HHFFKKSS XX == .. WW  RѰR## 55kk ee [[ EE  @@> >  """>$>|$|$$$$$%$$м$$|$|>$>"""  > >@@  EE [[ ee kk55 ##RѰR 22 Blue Circle     d e22y22 # % % ')++--///.//--++)' % % #  # % % ')++--///.//--++)' % % #  /JffJ/2΀2ccLL 22 WW WW22 "L$L$c&c&2(2((*/*/J*Jf*f**f*fJ*J/*/*((2(2&c&c$L$L" 22WW WW 22 LLcc2΀2/JffJ/ \\j jMMyy   " y$yM$M&((**j,j,,\.\...../....\.\,,j,j**((&M$My$y "   yyMMj j\\22 Red Square     !22"22""e W*W _*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*__*_ W*W d   22 Red Circle     d $22$22$ /JffJ/2΀2ccLL 22 WW WW22 "L$L$c&c&2(2((*/*/J*Jf*f**f*fJ*J/*/*((2(2&c&c$L$L" 22WW WW 22 LLcc2΀2/JffJ/  # % % ')++--///.//--++)' % % #  # % % ')++--///.//--++)' % % # \\j jMMyy   " y$yM$M&((**j,j,,\.\...../....\.\,,j,j**((&M$My$y "   yyMMj j\\(2 Red Ellipse     d+=(2+Q(2+a  WW .. == XX SSKKFFHH%%> >r r        r r> >%%HHFFKKSS XX == .. WW    !!##%%%$%%##!!     !!##%%%$%%##!!   RѰR## 55kk ee [[ EE  @@> >  """>$>|$|$$$$$%$$м$$|$|>$>"""  > >@@  EE [[ ee kk55 ##RѰR ,, Background     1,,13Z3f3r,,2.2:2F2R2^2j2v222222222223333*363B3N                        KK%%,,Selection Mask 3,,4445,,4444444444444444444444444        KK%%mago-0.3+bzr20/xpresser/tests/images/yellow-circle.png0000644000000000000000000000160111516265061022733 0ustar rootroot00000000000000PNG  IHDR22?sRGBbKGD pHYs % %>>*qRy)! Ȳ; 8y#9aHiVv끆C~ߴ(IaR? ~,R(@ɤ|al,ˢ~Z(1}x|srr9p`0 ϳI>g{{}Xtjfl6Z~dݵC\%I*o‹ hdO0-#RuP(tdk .@үsqahPPӹSod2)@OQ?P2뺿l4,K^F0á eYj4=ϓm=}\+3& ۶yfSDB޽Cfl@DBfnd\.'@oޠˇDž4srL&ժml s0A`TV }fQxޟDžŢ}R$@ kRVU^񁽞P?R`R/p4VNOW<=]vFXst}:1$ XYY1|ob6qu/:l&8h:]=p:5p5vW`}mn ˗DBKO -A, qd8$eg2}*d2t:Y`:ACׯL&],%:R,Blq(|74e17ꝝ>~[$cȿv=[<[,60#MXC ' Gaab,cWuIENDB`mago-0.3+bzr20/xpresser/tests/images/yellow-square.png0000644000000000000000000000042111516265061022771 0ustar rootroot00000000000000PNG  IHDR22?sBIT|d pHYs % % # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # import os from xpresser.image import Image, DEFAULT_SIMILARITY from xpresser.lib.testing import TestCase class ImageTest(TestCase): def test_default_constructor(self): image = Image() self.assertEquals(image.name, None) self.assertEquals(image.similarity, DEFAULT_SIMILARITY) self.assertEquals(image.focus_delta, (0, 0)) self.assertEquals(image.width, None) self.assertEquals(image.height, None) self.assertEquals(image.filename, None) self.assertEquals(image.array, None) self.assertEquals(image.cache, {}) def test_constructor_with_positional_arguments(self): image = Image("name", 0.5, (1, 2), 3, 4, "image.png", [[[0,0,0]]]) self.assertEquals(image.name, "name") self.assertEquals(image.similarity, 0.5) self.assertEquals(image.focus_delta, (1, 2)) self.assertEquals(image.width, 3) self.assertEquals(image.height, 4) self.assertEquals(image.filename, "image.png") self.assertEquals(image.array, [[[0,0,0]]]) def test_constructor_with_keyword_arguments(self): image = Image(name="name", similarity=0.5, focus_delta=(1, 2), width=3, height=4, filename="image.png") self.assertEquals(image.name, "name") self.assertEquals(image.similarity, 0.5) self.assertEquals(image.focus_delta, (1, 2)) self.assertEquals(image.width, 3) self.assertEquals(image.height, 4) self.assertEquals(image.filename, "image.png") def test_bad_similarity(self): self.assertRaises(ValueError, Image, similarity=1.1) mago-0.3+bzr20/xpresser/tests/test_imagedir.py0000644000000000000000000001312611516265061021405 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # import os from xpresser.imagedir import ImageDir, ImageDirError from xpresser.image import DEFAULT_SIMILARITY from xpresser.lib.testing import TestCase class ImageDirTest(TestCase): def setUp(self): self.dir = ImageDir() def test_load_empty_directory(self): dirname = self.makeDir() self.dir.load(dirname) # Nothing happens. def test_load_empty_file(self): filename = self.makeFile("", basename="xpresser.ini") self.dir.load(os.path.dirname(filename)) # Nothing happens. def test_load_image_with_missing_filename_option(self): filename = self.makeFile("[image foo]\n", basename="xpresser.ini") self.assertRaises(ImageDirError, self.dir.load, os.path.dirname(filename)) def test_load_image_with_non_existing_file(self): filename = self.makeFile("[image foo]\nfilename = nonexistent.png", basename="xpresser.ini") self.assertRaises(ImageDirError, self.dir.load, os.path.dirname(filename)) def test_load_and_get_image(self): filename = self.makeFile("[image foo]\n" "filename = fake_foo.png\n" "focus_delta = +1 -2\n" "similarity = 0.5\n" "[image bar]\n" "filename = fake_bar.png\n" "focus_delta = -30 +40\n" "[image baz]\n" "filename = fake_baz.png\n", basename="xpresser.ini") dirname = os.path.dirname(filename) self.makeFile("", basename="fake_foo.png", dirname=dirname) self.makeFile("", basename="fake_bar.png", dirname=dirname) self.makeFile("", basename="fake_baz.png", dirname=dirname) self.dir.load(dirname) foo = self.dir.get("foo") bar = self.dir.get("bar") baz = self.dir.get("baz") self.assertEquals(foo.name, "foo") self.assertEquals(foo.filename, os.path.join(dirname, "fake_foo.png")) self.assertEquals(foo.similarity, 0.5) self.assertEquals(foo.focus_delta, (1, -2)) self.assertEquals(bar.name, "bar") self.assertEquals(bar.filename, os.path.join(dirname, "fake_bar.png")) self.assertEquals(bar.similarity, DEFAULT_SIMILARITY) self.assertEquals(bar.focus_delta, (-30, 40)) self.assertEquals(baz.name, "baz") self.assertEquals(baz.filename, os.path.join(dirname, "fake_baz.png")) self.assertEquals(baz.similarity, DEFAULT_SIMILARITY) self.assertEquals(baz.focus_delta, (0, 0)) def test_bad_focus_delta(self): filename = self.makeFile("[image foo]\n" "filename = fake_foo.png\n" "focus_delta = +1,+2\n", basename="xpresser.ini") dirname = os.path.dirname(filename) self.makeFile("", basename="fake_foo.png", dirname=dirname) self.assertRaises(ImageDirError, self.dir.load, dirname) def test_bad_similarity(self): filename = self.makeFile("[image foo]\n" "filename = fake_foo.png\n" "similarity = bad\n", basename="xpresser.ini") dirname = os.path.dirname(filename) self.makeFile("", basename="fake_foo.png", dirname=dirname) self.assertRaises(ImageDirError, self.dir.load, dirname) def test_load_image_implicitly(self): filename = self.makeFile("", basename="image_name.png") self.dir.load(os.path.dirname(filename)) image = self.dir.get("image_name") self.assertEquals(image.name, "image_name") self.assertEquals(image.filename, filename) def test_ini_image_takes_precedence_over_implicitly_loaded(self): filename = self.makeFile("[image image_name]\n" "filename = image_name.png\n" "focus_delta = +1 +1\n", basename="xpresser.ini") dirname = os.path.dirname(filename) image_filename = self.makeFile("", basename="image_name.png", dirname=dirname) self.dir.load(dirname) image = self.dir.get("image_name") self.assertEquals(image.focus_delta, (1, 1)) def test_unknown_files_arent_loaded_implicitly(self): image_filename1 = self.makeFile("", basename="random_file.txt") dirname = os.path.dirname(image_filename1) image_filename2 = self.makeFile("", basename="random_file.unknown", dirname=os.path.dirname(image_filename1)) self.dir.load(dirname) self.assertEquals(self.dir.get("random_file"), None) mago-0.3+bzr20/xpresser/tests/test_imagematch.py0000644000000000000000000000307311516265061021723 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # from xpresser.imagematch import ImageMatch, ImageMatchError from xpresser.image import Image from xpresser.lib.testing import TestCase class ImageMatchTest(TestCase): def test_constructor(self): image = Image(width=40, height=50, focus_delta=(4, 5)) match = ImageMatch(image, 100, 200, 0.5) self.assertEquals(match.image, image) self.assertEquals(match.x, 100) self.assertEquals(match.y, 200) self.assertEquals(match.similarity, 0.5) self.assertEquals(match.focus_point, (100+40//2+4, 200+50//2+5)) def test_error_on_lack_of_height(self): image = Image(width=1) self.assertRaises(ImageMatchError, ImageMatch, image, 0, 0, 0) def test_error_on_lack_of_width(self): image = Image(height=1) self.assertRaises(ImageMatchError, ImageMatch, image, 0, 0, 0) mago-0.3+bzr20/xpresser/tests/test_opencvfinder.py0000644000000000000000000001435211516265061022310 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # import opencv import gtk from xpresser.image import Image from xpresser.opencvfinder import OpenCVFinder from xpresser.lib.testing import TestCase from xpresser.tests.images import get_image_path class OpenCVFinderTest(TestCase): def setUp(self): self.screen_image = Image(filename=get_image_path("screen.png")) self.red_square = Image(filename=get_image_path("red-square.png")) self.red_circle = Image(filename=get_image_path("red-circle.png")) self.red_ellipse = Image(filename=get_image_path("red-ellipse.png")) self.green_square = Image(filename=get_image_path("green-square.png")) self.yellow_square = Image(filename=get_image_path("yellow-square.png")) self.yellow_circle = Image(filename=get_image_path("yellow-circle.png")) self.red_circle_with_blue_circle = \ Image(filename=get_image_path("red-circle-with-blue-circle.png")) self.finder = OpenCVFinder() def test_loads_widths_and_heights(self): self.finder.find(self.screen_image, self.red_ellipse) self.assertEquals(self.screen_image.width, 300) self.assertEquals(self.screen_image.height, 300) self.assertEquals(self.red_ellipse.width, 40) self.assertEquals(self.red_ellipse.height, 50) def test_find_perfect_match(self): match = self.finder.find(self.screen_image, self.green_square) self.assertEquals(match.image, self.green_square) self.assertEquals(match.x, 200) self.assertEquals(match.y, 0) self.assertEquals(match.similarity, 1.0) def test_find_perfect_match_with_low_threshold(self): self.green_square.similarity = 0.7 match = self.finder.find(self.screen_image, self.green_square) self.assertEquals(match.image, self.green_square) self.assertEquals(match.x, 200) self.assertEquals(match.y, 0) def test_find_all_with_perfect_match(self): matches = self.finder.find_all(self.screen_image, self.green_square) self.assertEquals(len(matches), 1) self.assertEquals(matches[0].image, self.green_square) self.assertEquals(matches[0].x, 200) self.assertEquals(matches[0].y, 0) self.assertEquals(matches[0].similarity, 1.0) def test_find_all_with_low_threshold_containing_perfect_match(self): self.red_circle.similarity = 0.8 matches = self.finder.find_all(self.screen_image, self.red_circle) self.assertTrue(len(matches) > 1) self.assertTrue(min(m.similarity for m in matches) >= 0.8) def test_no_matches(self): match = self.finder.find(self.screen_image, self.red_circle_with_blue_circle) self.assertEquals(match, None) def test_fuzzy_match(self): self.red_circle_with_blue_circle.similarity = 0.9 match = self.finder.find(self.screen_image, self.red_circle_with_blue_circle) self.assertEquals(match.image, self.red_circle_with_blue_circle) self.assertEquals(match.x, 100) self.assertEquals(match.y, 200) def test_self_match(self): """ This test will explore a bug in the Python OpenCV bindings. It will handle the dimensions of the result matrix in a different way when there's a single result. """ match = self.finder.find(self.red_circle, self.red_circle) self.assertEquals(match.x, 0) self.assertEquals(match.y, 0) def test_opencv_image_cache(self): match = self.finder.find(self.red_circle, self.yellow_circle) opencv_image = self.red_circle.cache.get("opencv_image") self.assertEquals(match, None) self.assertNotEquals(opencv_image, None) self.assertEquals(type(opencv_image), opencv.CvMat) # Let's ensure the cache is *actually* in use. self.red_circle.cache["opencv_image"] = \ self.yellow_circle.cache["opencv_image"] match = self.finder.find(self.red_circle, self.yellow_circle) self.assertNotEquals(match, None) def test_filtering_of_similar_matches(self): """ This example would actually have hundreds of matches if there was no filtering per proximity and match quality. The filtering algorithm is not entirely trivial, and likely has other cases which need to be covered by individual unit tests too. """ self.red_circle.similarity = 0.8 matches = self.finder.find_all(self.screen_image, self.red_circle) matches.sort(key=lambda match: -match.similarity) self.assertEquals(len(matches), 2) self.assertEquals(matches[0].x, 100) self.assertEquals(matches[0].y, 200) self.assertEquals(matches[1].x, 198) self.assertEquals(matches[1].y, 100) def test_find_with_array_image(self): # Reset the image, including the cache (shouldn't be needed, but # just to be 100% sure). self.green_square.cache.clear() filename = self.green_square.filename self.green_square.filename = None # Use gtk to transform the image into a numpy array, and set it # back into the image. pixbuf = gtk.image_new_from_file(filename).get_pixbuf() self.green_square.array = pixbuf.get_pixels_array() # Try to match normally. match = self.finder.find(self.screen_image, self.green_square) self.assertEquals(match.image, self.green_square) self.assertEquals(match.x, 200) self.assertEquals(match.y, 0) self.assertEquals(match.similarity, 1.0) mago-0.3+bzr20/xpresser/tests/test_xp.py0000644000000000000000000001660111516265061020254 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # import threading import time import gtk from xpresser import Xpresser, ImageNotFound from xpresser.image import Image from xpresser.imagematch import ImageMatch from xpresser.tests.images import get_image_path from xpresser.tests.test_xutils import XUtilsTestBase SLEEP_DELAY = 1.5 class XpresserTestBase(XUtilsTestBase): def setUp(self): super(XpresserTestBase, self).setUp() self.xp = Xpresser() self.xp.load_images(get_image_path()) class XpresserTest(XpresserTestBase): def test_load_images_and_get_image(self): image = self.xp.get_image("red-circle") self.assertEquals(type(image), Image) self.assertEquals(image.name, "red-circle") def test_type(self): entry = gtk.Entry() window = self.create_window(entry) try: window.present() entry.grab_focus() self.flush_gtk() self.xp.type("Hello there!") self.flush_gtk() self.assertEquals(entry.get_text(), "Hello there!") finally: window.destroy() class XpresserButtonTest(XpresserTestBase): def setUp(self): super(XpresserButtonTest, self).setUp() self.window = self.create_button_window() self.button = self.window.get_child() self.button_clicked = False self.button_rclicked = False self.button_hovered = False def clicked(widget, event): if event.button == 1: self.button_clicked = True elif event.button == 3: self.button_rclicked = True self.window.destroy() def entered(widget): self.button_hovered = True self.button.connect("button_press_event", clicked) self.button.connect("enter", entered) self.flush_gtk() def tearDown(self): self.window.destroy() def get_button_center(self): button_x, button_y = self.button.window.get_position() button_width, button_height = self.button.window.get_size() return (button_x + button_width//2, button_y + button_height//2) def test_find_image_name(self): match = self.xp.find("red-square") self.assertEquals(type(match), ImageMatch) self.assertEquals(match.focus_point, self.get_button_center()) def test_find_image(self): image = self.xp.get_image("red-square") match = self.xp.find(image) self.assertEquals(type(match), ImageMatch) self.assertEquals(match.focus_point, self.get_button_center()) def test_find_with_delay(self): self.window.hide() self.flush_gtk() def show_window(): time.sleep(SLEEP_DELAY) self.window.show() self.flush_gtk() thread = threading.Thread(target=show_window) thread.start() match = self.xp.find("red-square") self.assertEquals(type(match), ImageMatch) self.assertEquals(match.focus_point, self.get_button_center()) def test_find_failed(self): started = time.time() self.assertRaises(ImageNotFound, self.xp.find, "blue-square", timeout=SLEEP_DELAY) self.assertTrue(time.time() - started > SLEEP_DELAY) def test_wait(self): self.window.hide() self.flush_gtk() def show_window(): time.sleep(SLEEP_DELAY) self.window.show() self.flush_gtk() thread = threading.Thread(target=show_window) started = time.time() thread.start() self.xp.wait("red-square") self.assertTrue(time.time() - started > SLEEP_DELAY) def test_wait_failed(self): started = time.time() self.assertRaises(ImageNotFound, self.xp.wait, "blue-square", timeout=SLEEP_DELAY) self.assertTrue(time.time() - started > SLEEP_DELAY) def test_click_position(self): self.xp.click(*self.get_button_center()) self.flush_gtk() self.assertTrue(self.button_clicked) def test_hover_position(self): self.xp.hover(*self.get_button_center()) self.flush_gtk() self.assertTrue(self.button_hovered) self.assertFalse(self.button_clicked) def test_click_image_name(self): self.xp.click("red-square") self.flush_gtk() self.assertTrue(self.button_clicked) def test_right_click_image_name(self): self.xp.right_click("red-square") self.flush_gtk() self.assertTrue(self.button_rclicked) def test_hover_image_name(self): self.xp.hover("red-square") self.flush_gtk() self.assertTrue(self.button_hovered) self.assertFalse(self.button_clicked) def test_click_image_match(self): match = self.xp.find("red-square") self.xp.click(match) self.flush_gtk() self.assertTrue(self.button_clicked) def test_right_click_image_match(self): match = self.xp.find("red-square") self.xp.right_click(match) self.flush_gtk() self.assertTrue(self.button_rclicked) def test_hover_image_match(self): match = self.xp.find("red-square") self.xp.hover(match) self.flush_gtk() self.assertTrue(self.button_hovered) self.assertFalse(self.button_clicked) def test_click_waits(self): self.window.hide() self.flush_gtk() def show_window(): time.sleep(SLEEP_DELAY) self.window.show() self.flush_gtk() thread = threading.Thread(target=show_window) started = time.time() thread.start() self.xp.click("red-square") self.assertTrue(time.time() - started > SLEEP_DELAY) self.flush_gtk() self.assertTrue(self.button_clicked) def test_right_click_waits(self): self.window.hide() self.flush_gtk() def show_window(): time.sleep(SLEEP_DELAY) self.window.show() self.flush_gtk() thread = threading.Thread(target=show_window) started = time.time() thread.start() self.xp.right_click("red-square") self.assertTrue(time.time() - started > SLEEP_DELAY) self.flush_gtk() self.assertTrue(self.button_rclicked) def test_hover_waits(self): self.window.hide() self.flush_gtk() def show_window(): time.sleep(SLEEP_DELAY) self.window.show() self.flush_gtk() thread = threading.Thread(target=show_window) started = time.time() thread.start() self.xp.hover("red-square") self.assertTrue(time.time() - started > SLEEP_DELAY) self.flush_gtk() self.assertTrue(self.button_hovered) mago-0.3+bzr20/xpresser/tests/test_xutils.py0000644000000000000000000001456411516265061021163 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # import time import gtk from xpresser import xutils from xpresser.image import Image from xpresser.opencvfinder import OpenCVFinder from xpresser.tests.images import get_image_path from xpresser.lib.testing import TestCase class XUtilsTestBase(TestCase): def setUp(self): xutils.hover(0, 0) def flush_gtk(self): # Why do we need to do so much to get the button in place before # actually trying to click on it? :-( If we just run until there # are no more events, and without sleep, the button will simply # return (0, 0) as its position. while gtk.events_pending(): gtk.main_iteration() time.sleep(0.1) # Why oh why? :-( while gtk.events_pending(): gtk.main_iteration() time.sleep(0.1) while gtk.events_pending(): gtk.main_iteration() def create_window(self, child): window = gtk.Window(gtk.WINDOW_TOPLEVEL) window.connect("delete_event", lambda widget, event: False) window.add(child) child.show() window.show() return window def create_button_window(self, image_path=None): button = gtk.Button() if image_path is None: image_path = get_image_path("red-square.png") button.set_image(gtk.image_new_from_file(image_path)) return self.create_window(button) def create_image_window(self, image_path): image = gtk.image_new_from_file(image_path) return self.create_window(image) class XUtilsTest(XUtilsTestBase): def test_type(self): entry = gtk.Entry() window = self.create_window(entry) try: window.present() entry.grab_focus() self.flush_gtk() xutils.type("Hello there!") self.flush_gtk() self.assertEquals(entry.get_text(), "Hello there!") finally: window.destroy() def test_take_screenshot(self): """Verify that take_screenshot works, with a real screenshot. For that, we will put a known image in the screen, and will then try to find it in the screenshot. """ red_square = Image("red-square", filename=get_image_path("red-square.png")) window = self.create_image_window(red_square.filename) self.flush_gtk() resolution = gtk.gdk.get_default_root_window().get_size() window_x, window_y = window.get_child().window.get_position() window_width, window_height = window.get_child().window.get_size() big_screenshot = xutils.take_screenshot() small_screenshot = xutils.take_screenshot(window_x, window_y, window_width, window_height) window.destroy() self.flush_gtk() # Check the basic attributes set self.assertEquals(big_screenshot.name, "screenshot") self.assertEquals(big_screenshot.width, resolution[0]) self.assertEquals(big_screenshot.height, resolution[1]) self.assertEquals(small_screenshot.name, "screenshot") self.assertEquals(small_screenshot.width, window_width) self.assertEquals(small_screenshot.height, window_height) # Now verify the actual images taken. finder = OpenCVFinder() big_match = finder.find(big_screenshot, red_square) small_match = finder.find(small_screenshot, red_square) self.assertEquals(big_match.image, red_square) self.assertTrue(big_match.similarity > 0.95, big_match.similarity) self.assertEquals(small_match.image, red_square) self.assertTrue(small_match.similarity > 0.95, small_match.similarity) # The match we found in the big screenshot should be in the same # position as the window we created. Note that this may fail if # you have the image opened elsewhere. ;-) self.assertEquals(big_match.x, window_x) self.assertEquals(big_match.y, window_y) # With the small match, it should be in the origin, since the # screenshot was taken on the precise area. self.assertEquals(small_match.x, 0) self.assertEquals(small_match.y, 0) class XUtilsButtonTest(XUtilsTestBase): def setUp(self): super(XUtilsButtonTest, self).setUp() self.window = self.create_button_window() self.button = self.window.get_child() self.button_clicked = False self.button_rclicked = False self.button_hovered = False def clicked(widget, event): if event.button == 1: self.button_clicked = True elif event.button == 3: self.button_rclicked = True self.window.destroy() def entered(widget): self.button_hovered = True self.button.connect("button_press_event", clicked) self.button.connect("enter", entered) self.flush_gtk() def tearDown(self): self.window.destroy() def get_button_center(self): button_x, button_y = self.button.window.get_position() button_width, button_height = self.button.window.get_size() return (button_x + button_width//2, button_y + button_height//2) def test_click(self): xutils.click(*self.get_button_center()) self.flush_gtk() self.assertTrue(self.button_clicked) def test_right_click(self): xutils.right_click(*self.get_button_center()) self.flush_gtk() self.assertTrue(self.button_rclicked) def test_hover(self): xutils.hover(*self.get_button_center()) self.flush_gtk() self.assertTrue(self.button_hovered) self.assertFalse(self.button_clicked) mago-0.3+bzr20/xpresser/xp.py0000644000000000000000000000747611516265061016065 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # import time from xpresser import xutils from xpresser.image import Image from xpresser.errors import XpresserError from xpresser.imagedir import ImageDir from xpresser.imagematch import ImageMatch from xpresser.opencvfinder import OpenCVFinder class ImageNotFound(XpresserError): """Exception raised when a request to find an image doesn't succeed.""" class Xpresser(object): def __init__(self): self._imagedir = ImageDir() self._imagefinder = OpenCVFinder() def load_images(self, path): self._imagedir.load(path) def get_image(self, name): return self._imagedir.get(name) def _compute_focus_point(self, args): if (len(args) == 2 and isinstance(args[0], (int, long)) and isinstance(args[1], (int, long))): return args elif len(args) == 1: if type(args[0]) == ImageMatch: match = args[0] else: match = self.find(args[0]) return match.focus_point def click(self, *args): """Click on the position specified by the provided arguments. The following examples show valid ways of specifying the position: xp.click("image-name") xp.click(image_match) xp.click(x, y) """ xutils.click(*self._compute_focus_point(args)) def right_click(self, *args): """Right-click on the position specified by the provided arguments. The following examples show valid ways of specifying the position: xp.right_click("image-name") xp.right_click(image_match) xp.right_click(x, y) """ xutils.right_click(*self._compute_focus_point(args)) def hover(self, *args): """Hover over the position specified by the provided arguments. The following examples show valid ways of specifying the position: xp.hover("image-name") xp.hover(image_match) xp.hover(x, y) """ xutils.hover(*self._compute_focus_point(args)) def find(self, image, timeout=10): """Given an image or an image name, find it on the screen. @param image: Image or image name to be searched for. @return: An ImageMatch instance, or None. """ if isinstance(image, basestring): image = self._imagedir.get(image) wait_until = time.time() + timeout while time.time() < wait_until: screenshot_image = xutils.take_screenshot() match = self._imagefinder.find(screenshot_image, image) if match is not None: return match raise ImageNotFound(image) def wait(self, image, timeout=30): """Wait for an image to show up in the screen up to C{timeout} seconds. @param image: Image or image name to be searched for. @return: An ImageMatch instance, or None. """ self.find(image, timeout) def type(self, string): """Enter the string provided as if it was typed via the keyboard. """ xutils.type(string) mago-0.3+bzr20/xpresser/xutils.py0000644000000000000000000000373311516265061016756 0ustar rootroot00000000000000# # Copyright (c) 2010 Canonical # # Written by Gustavo Niemeyer # # This file is part of the Xpresser GUI automation library. # # Xpresser is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3, # as published by the Free Software Foundation. # # Xpresser is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # from xpresser.image import Image import pyatspi import gtk import warnings # pygtk is using a deprecated method from numpy in get_pixels_array(). warnings.filterwarnings("ignore", ".*use PyArray_NewFromDescr.*") def click(x, y): pyatspi.Registry.generateMouseEvent(x, y, pyatspi.MOUSE_B1C) def right_click(x, y): pyatspi.Registry.generateMouseEvent(x, y, pyatspi.MOUSE_B3C) def hover(x, y): pyatspi.Registry.generateMouseEvent(x, y, pyatspi.MOUSE_ABS) def type(string): for char in string: keyval = gtk.gdk.unicode_to_keyval(ord(char)) pyatspi.Registry.generateKeyboardEvent(keyval, None, pyatspi.KEY_SYM) def take_screenshot(x=0, y=0, width=None, height=None): window = gtk.gdk.get_default_root_window() if not (width and height): size = window.get_size() if not width: width = size[0] if not height: height = size[1] pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, width, height) pixbuf = pixbuf.get_from_drawable(window, window.get_colormap(), x, y, 0, 0, width, height) array = pixbuf.get_pixels_array() return Image("screenshot", array=array, width=array.shape[1], height=array.shape[0])