pax_global_header00006660000000000000000000000064147312542030014513gustar00rootroot0000000000000052 comment=7118261bcf9bba26fd0ebfa5025b2908b3af1783 icingaweb2-module-toplevelview-1.0.0/000077500000000000000000000000001473125420300175315ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/.github/000077500000000000000000000000001473125420300210715ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/.github/dependabot.yml000066400000000000000000000001551473125420300237220ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: monthly icingaweb2-module-toplevelview-1.0.0/.github/workflows/000077500000000000000000000000001473125420300231265ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/.github/workflows/php.yml000066400000000000000000000036141473125420300244440ustar00rootroot00000000000000name: PHP Tests on: push: branches: - main - release/* pull_request: branches: - main - release/* jobs: lint: name: Lint and Code Style runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: php: ['8.2', '8.3'] os: ['ubuntu-latest'] steps: - name: Checkout code base uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} tools: phpcs - name: Setup dependencies run: composer require -n --no-progress overtrue/phplint - name: PHP Lint if: success() || matrix.allow_failure run: ./vendor/bin/phplint -n --exclude={^vendor/.*} -- . - name: PHP CodeSniffer if: success() || matrix.allow_failure run: phpcs -wps --colors test: name: Unittest runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: php: ['8.2', '8.3'] os: ['ubuntu-latest'] steps: - name: Checkout code base uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} tools: 'phpunit:10.4' - name: Setup Libraries run: | mkdir -p _libraries git clone --depth 1 -b snapshot/nightly https://github.com/Icinga/icinga-php-library.git _libraries/ipl git clone --depth 1 -b snapshot/nightly https://github.com/Icinga/icinga-php-thirdparty.git _libraries/vendor git clone --depth 1 https://github.com/Icinga/icingaweb2.git _icingaweb2 git clone --depth 1 https://github.com/Icinga/icingadb-web.git _icingaweb2/modules/icingadb ln -s `pwd` _icingaweb2/modules/toplevelview - name: PHPUnit env: ICINGAWEB_LIBDIR: _libraries/ run: phpunit icingaweb2-module-toplevelview-1.0.0/.gitignore000066400000000000000000000003771473125420300215300ustar00rootroot00000000000000# Exclude editor files .*.sw[op] *~ /.idea/ \#* .\#* *TODO* !.git* # Artifacts from vendor parts in testing _icingaweb2/ _libraries/ .phpunit.cache/ .phplint.cache/ reports/ /docker-compose.yml /*.phar /Icinga /Zend /vendor test/testdata/views/deleteme* icingaweb2-module-toplevelview-1.0.0/AUTHORS000066400000000000000000000002441473125420300206010ustar00rootroot00000000000000Johannes Meyer Markus Frosch [.::MDT::.] sklaes icingaweb2-module-toplevelview-1.0.0/CHANGELOG.md000066400000000000000000000177251473125420300213560ustar00rootroot00000000000000# Changelog ## [v1.0.0](https://github.com/Icinga/icingaweb2-module-toplevelview/tree/v1.0.0) (2024-12-05) **Implemented enhancements:** - Add restrictions `toplevelview/filter/view` and `toplevelview/filter/edit` - Add Service Groups as TLV elements - Add option to toggle `notification_enabled` behavior - Add validation for view filenames (restricted characters are: `! @ # $ % ^ & * / \ ( )`) - Add CLI Command to clean up backups - Improve error handling for YAML editor - Improve CSS for dark and light mode ## [v0.4.0](https://github.com/Icinga/icingaweb2-module-toplevelview/tree/v0.4.0) (2024-07-16) **Breaking changes:** - Remove support for the Icinga Web monitoring module Future versions will only use IcingaDB Web. - Remove `notification_periods` and `ignored_notification_periods` options These options changed the state behavior of the module significantly (when compared to Icinga Web) and thus caused some confusion/limitations. - Rename `host_never_unhandled` to `override_host_problem_to_handled` Tried to make this options clearer to understand. **Implemented enhancements:** - Add support for Icinga DB - Views use the display names for object if configured - Improve the View's headers styling - Improve handling of long View names (uses ellipsis now) ## [v0.3.4](https://github.com/Icinga/icingaweb2-module-toplevelview/tree/v0.3.4) (2024-06-12) This will be the final version with support for Icinga Web monitoring module. Future versions will use IcingaDB Web. **Implemented enhancements:** - Improve CSS for dark/light theme - Add confirmation dialog to deletion button - Add Icinga Web CSS classes to delete and cancel button - Update codemirror5 to latest version and add code folding - Update README to include php-yaml requirement **Fixed bugs:** - Fix CSS issue with node collapse icon - Change unsaved work warning position to avoid breaking the layout ## [v0.3.3](https://github.com/Icinga/icingaweb2-module-toplevelview/tree/v0.3.3) (2021-09-10) **Implemented enhancements:** - Rename collapse feature for Icinga Web >= 2.7 ([lazyfrosch](https://github.com/lazyfrosch)) ## [v0.3.2](https://github.com/Icinga/icingaweb2-module-toplevelview/tree/v0.3.2) (2021-03-19) [Full Changelog](https://github.com/Icinga/icingaweb2-module-toplevelview/compare/v0.3.1...v0.3.2) **Implemented enhancements:** - legacy: Add cleanup and IDO migration tool [\#43](https://github.com/Icinga/icingaweb2-module-toplevelview/pull/43) ([lazyfrosch](https://github.com/lazyfrosch)) **Merged pull requests:** - Fix typos [\#39](https://github.com/Icinga/icingaweb2-module-toplevelview/pull/39) ([sklaes](https://github.com/sklaes)) - Update 02-Behavior.md [\#38](https://github.com/Icinga/icingaweb2-module-toplevelview/pull/38) ([micheledallatorre](https://github.com/micheledallatorre)) ## [v0.3.1](https://github.com/Icinga/icingaweb2-module-toplevelview/tree/v0.3.1) (2019-03-06) [Full Changelog](https://github.com/Icinga/icingaweb2-module-toplevelview/compare/v0.3.0...v0.3.1) **Fixed bugs:** - Implement Notification Period ignoring for TLVServiceNode [\#36](https://github.com/Icinga/icingaweb2-module-toplevelview/pull/36) ([lazyfrosch](https://github.com/lazyfrosch)) - HostgroupsummaryQuery: Ignore hostgroups that are empty [\#35](https://github.com/Icinga/icingaweb2-module-toplevelview/pull/35) ([lazyfrosch](https://github.com/lazyfrosch)) ## [v0.3.0](https://github.com/Icinga/icingaweb2-module-toplevelview/tree/v0.3.0) (2019-02-28) [Full Changelog](https://github.com/Icinga/icingaweb2-module-toplevelview/compare/v0.2.1...v0.3.0) **Implemented enhancements:** - Allow ignoring a list of notification periods for handled problems [\#34](https://github.com/Icinga/icingaweb2-module-toplevelview/pull/34) ([lazyfrosch](https://github.com/lazyfrosch)) **Closed issues:** - You need the PHP extension "yaml" in order to use TopLevelView \(rh-php71\) [\#33](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/33) ## [v0.2.1](https://github.com/Icinga/icingaweb2-module-toplevelview/tree/v0.2.1) (2018-02-13) [Full Changelog](https://github.com/Icinga/icingaweb2-module-toplevelview/compare/v0.2.0...v0.2.1) **Fixed bugs:** - UTC timeperiod calculation is wrong [\#29](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/29) **Merged pull requests:** - Don't use UTC timestamps for calculating timeperiods [\#30](https://github.com/Icinga/icingaweb2-module-toplevelview/pull/30) ([lazyfrosch](https://github.com/lazyfrosch)) ## [v0.2.0](https://github.com/Icinga/icingaweb2-module-toplevelview/tree/v0.2.0) (2018-01-25) [Full Changelog](https://github.com/Icinga/icingaweb2-module-toplevelview/compare/v0.1.0...v0.2.0) **Implemented enhancements:** - style: Update handled colors with material design [\#28](https://github.com/Icinga/icingaweb2-module-toplevelview/pull/28) ([lazyfrosch](https://github.com/lazyfrosch)) **Fixed bugs:** - Undefined index: unknown coming from TLVServiceNode [\#22](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/22) **Closed issues:** - Apply monitoring filter to views [\#25](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/25) - Document requirement for Icingaweb2 \>= 2.5.0 [\#23](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/23) - You need the PHP extension "yaml" in order to use TopLevelView [\#21](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/21) ## [v0.1.0](https://github.com/Icinga/icingaweb2-module-toplevelview/tree/v0.1.0) (2017-10-17) [Full Changelog](https://github.com/Icinga/icingaweb2-module-toplevelview/compare/a7bf9bee8ea768a7ba7afe7191f11f221475f1b1...v0.1.0) **Implemented enhancements:** - Add documentation [\#15](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/15) - Add badges [\#8](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/8) - Activate auto-reload and show counter [\#6](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/6) - Add caching layer [\#3](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/3) - Integrate notification\_period behavior [\#2](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/2) - Add documentation [\#19](https://github.com/Icinga/icingaweb2-module-toplevelview/pull/19) ([lazyfrosch](https://github.com/lazyfrosch)) - Add caching layer [\#9](https://github.com/Icinga/icingaweb2-module-toplevelview/pull/9) ([lazyfrosch](https://github.com/lazyfrosch)) **Fixed bugs:** - host\_never\_unhandled should affect service\_handled [\#20](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/20) - Host down should be visible [\#7](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/7) - Auto create missing config dir [\#5](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/5) **Closed issues:** - Make notification\_period an option [\#18](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/18) - Fix single services in convert [\#17](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/17) - Add de\_DE translation [\#16](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/16) - Config option for host handled [\#14](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/14) - Add docker test and dev environment [\#13](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/13) - Config Files should be created with group write permission [\#12](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/12) - SOFT states should be ignored [\#11](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/11) - Convert in downtime and notifications disabled to a downtime state [\#10](https://github.com/Icinga/icingaweb2-module-toplevelview/issues/10) **Merged pull requests:** - Add CLI convert tool for sqlite database [\#1](https://github.com/Icinga/icingaweb2-module-toplevelview/pull/1) ([lazyfrosch](https://github.com/lazyfrosch)) \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* icingaweb2-module-toplevelview-1.0.0/CONTRIBUTING.md000066400000000000000000000141301473125420300217610ustar00rootroot00000000000000# Contributing Top Level View for Icinga Web is an open source project and lives from your ideas and contributions. There are many ways to contribute, from improving the documentation, submitting bug reports and features requests or writing code to add enhancements or fix bugs. #### Table of Contents 1. [Introduction](#introduction) 2. [Fork the Project](#fork-the-project) 3. [Branches](#branches) 4. [Commits](#commits) 5. [Pull Requests](#pull-requests) 6. [Testing](#testing) 7. [Source Code Patches](#source-code-patches) 8. [Documentation Patches](#documentation-patches) ## Introduction Before starting your work, you should [fork the project](https://help.github.com/articles/fork-a-repo/) to your GitHub account. This allows you to freely experiment with your changes. When your changes are complete, submit a [pull request](https://help.github.com/articles/using-pull-requests/). All pull requests will be reviewed and merged if they suit some general guidelines: * Changes are located in a topic branch * For new functionality, proper tests are written * Changes should follow the existing coding style and standards Please continue reading in the following sections for a step by step guide. ## Fork the Project [Fork the project](https://help.github.com/articles/fork-a-repo/) to your GitHub account and clone the repository: ``` git clone git@github.com:jdoe/icingaweb2-module-toplevelview.git cd icingaweb2-module-toplevelview ``` Add a new remote `upstream` with this repository as value. ``` git remote add upstream https://github.com/icinga/icingaweb2-module-toplevelview.git ``` You can pull updates to your fork's default branch: ``` git fetch --all git pull upstream HEAD ``` Please continue to learn about [branches](#branches). ## Branches Choosing a proper name for a branch helps us identify its purpose and possibly find an associated bug or feature. Generally a branch name should include a topic such as `fix` or `feature` followed by a description and an issue number if applicable. Branches should have only changes relevant to a specific issue. ``` git checkout -b fix/service-template-typo-1234 git checkout -b feature/config-handling-1235 ``` Continue to apply your changes and test them. More details on specific changes: * [Source Code Patches](#source-code-patches) * [Documentation Patches](#documentation-patches) ## Commits Once you've finished your work in a branch, please ensure to commit your changes. A good commit message includes a short topic, additional body and a reference to the issue you wish to solve (if existing). Fixes: ``` Fix missing style in detail view refs #4567 ``` Features: ``` Add DateTime picker refs #1234 ``` You can add multiple commits during your journey to finish your patch. Don't worry, you can squash those changes into a single commit later on. ## Pull Requests Once you've committed your changes, please update your local default branch and rebase your fix/feature branch against it before submitting a PR. ``` git checkout main git pull upstream HEAD git checkout fix/style-detail-view-5678 git rebase main ``` Once you've resolved any conflicts, push the branch to your remote repository. It might be necessary to force push after rebasing - use with care! New branch: ``` git push --set-upstream origin fix/style-detail-view-5678 ``` Existing branch: ``` git push -f origin fix/style-detail-view-5678 ``` You can now either use the [hub](https://hub.github.com) CLI tool to create a PR, or navigate to your GitHub repository and create a PR there. The pull request should again contain a telling subject and a reference with `fixes` to an existing issue id if any. That allows developers to automatically resolve the issues once your PR gets merged. ``` hub pull-request fixes #1234 ``` Thanks a lot for your contribution! ### Rebase a Branch If you accidentally sent in a PR which was not rebased against the upstream default branch, developers might ask you to rebase your PR. First off, fetch and pull the default branch. ``` git checkout main git fetch --all git pull upstream HEAD ``` Then change to your working branch and start rebasing it against the default: ``` git checkout fix/style-detail-view-5678 git rebase main ``` If you are running into a conflict, rebase will stop and ask you to fix the problems. ``` git status both modified: path/to/conflict.php ``` Edit the file and search for `>>>`. Fix, build, test and save as needed. Add the modified file(s) and continue rebasing. ``` git add path/to/conflict.php git rebase --continue ``` Once succeeded ensure to push your changed history remotely. ``` git push -f origin fix/style-detail-view-5678 ``` If you fear to break things, do the rebase in a backup branch first and later replace your current branch. ``` git checkout fix/style-detail-view-5678 git checkout -b fix/style-detail-view-5678-rebase git rebase main git branch -D fix/style-detail-view-5678 git checkout -b fix/style-detail-view-5678 git push -f origin fix/style-detail-view-5678 ``` ### Squash Commits > **Note:** > > Be careful with squashing. This might lead to non-recoverable mistakes. > > This is for advanced Git users. Say you want to squash the last 3 commits in your branch into a single one. Start an interactive (`-i`) rebase from current HEAD minus three commits (`HEAD~3`). ``` git rebase -i HEAD~3 ``` Git opens your preferred editor. `pick` the commit in the first line, change `pick` to `squash` on the other lines. ``` pick e4bf04e47 Fix style detail view squash d7b939d99 Tests squash b37fd5377 Doc updates ``` Save and let rebase to its job. Then force push the changes to the remote origin. ``` git push -f origin fix/style-detail-view-5678 ``` ## Testing Test cases are defined in the `Makefile`. ## Source Code Patches Top Level View for Icinga Web is written in PHP, LESS and JavaScript. ## Documentation Patches The documentation is written in GitHub flavored [Markdown](https://guides.github.com/features/mastering-markdown/). It is located in the `doc/` directory and can be edited with your preferred editor. You can also edit it online on GitHub. ``` vim doc/02-Installation.md ``` icingaweb2-module-toplevelview-1.0.0/COPYING000066400000000000000000000432541473125420300205740ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. icingaweb2-module-toplevelview-1.0.0/Makefile000066400000000000000000000011411473125420300211660ustar00rootroot00000000000000.PHONY: setup test setup: mkdir -p _libraries &&\ git clone --depth 1 -b snapshot/nightly https://github.com/Icinga/icinga-php-library.git _libraries/ipl &&\ git clone --depth 1 -b snapshot/nightly https://github.com/Icinga/icinga-php-thirdparty.git _libraries/vendor &&\ git clone --depth 1 https://github.com/Icinga/icingaweb2.git _icingaweb2 &&\ git clone --depth 1 https://github.com/Icinga/icingadb-web.git _icingaweb2/modules/icingadb ln -s `pwd` _icingaweb2/modules/toplevelview test: ICINGAWEB_LIBDIR=_libraries phpunit lint: phplint application/ library/ phpcs: phpcs application/ library/ icingaweb2-module-toplevelview-1.0.0/README.md000066400000000000000000000021331473125420300210070ustar00rootroot00000000000000Top Level View for Icinga Web 2 =============================== Top Level View is a hierarchy based status view for Icinga Web 2. ![Top Level View Light](doc/screenshots/tlv-light.png) You can define a hierarchical structure containing hosts, services and hostgroups. And the view presents you an overview of the overall status of the sub-hierarchies. Example: ```yaml name: My View children: - name: Section 1 children: - name: Tile 1 children: - host: localhost - host: localhost service: disk - host: anotherhost service: ssh - name: Tile 2 hostgroup: linux-servers - servicegroup: http ``` With a caching layer, this view can aggregate thousands of status objects and make them easily available for overview and drill down. ## Requirements * Icinga Web 2 >= 2.5.0 * Icinga DB Web >= 1.0.0 * php-yaml Also see [Introduction in docs](doc/01-Introduction.md). ## Documentation All documentation can be found inside the [doc](doc/) directory. ## License Icinga Web TopLevelView is licensed under the terms of the [GNU General Public License Version 2](COPYING). icingaweb2-module-toplevelview-1.0.0/RELEASE.md000066400000000000000000000014221473125420300211320ustar00rootroot00000000000000# Release Workflow Specify the release version. ``` VERSION=1.x.x ``` ## Issues Check issues at https://github.com/Icinga/icingaweb2-module-toplevelview/issues ## Update metadata Edit and update [module.info](module.info). ## Changelog Update the [CHANGELOG.md](CHANGELOG.md) file. Uses [github_changelog_generator](https://github.com/skywinder/github-changelog-generator) ``` export CHANGELOG_GITHUB_TOKEN=xxx github_changelog_generator --future-release v$VERSION ``` Check if the file has been updated correctly. ## Git Tag Commit these changes to the "master" branch: ``` git commit -v -a -m "Release version $VERSION" git push origin master ``` And tag it with a signed tag: ``` git tag -s -m "Version $VERSION" v$VERSION ``` Push the tag. ``` git push --tags ``` icingaweb2-module-toplevelview-1.0.0/SECURITY.md000066400000000000000000000001721473125420300213220ustar00rootroot00000000000000# Security Policy ## Reporting a Vulnerability Please head [here](https://icinga.com/company/contact/security-issues/). icingaweb2-module-toplevelview-1.0.0/application/000077500000000000000000000000001473125420300220345ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/clicommands/000077500000000000000000000000001473125420300243255ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/clicommands/CleanupCommand.php000066400000000000000000000076221473125420300277330ustar00rootroot00000000000000setLevel(Logger::INFO); } /** * Load all directories in a given path. * @param string $path Path to the directory * * @return array List of fully qualified directory names */ protected function listDirs(string $path): array { $result = []; foreach (new DirectoryIterator($path) as $p) { if (is_dir($p)) { $result[] = $p; } } return $result; } /** * Load all YML files in a given path. * @param string $path Path to the directory * * @return array List of fully qualified file names */ protected function listYMLFiles(string $path): array { $result = []; foreach (new DirectoryIterator($path) as $file) { if (str_ends_with($file, self::FORMAT_YAML)) { $result[] = $file; } } return $result; } /** * Remove a list of files from the filesystem. * @param array $files list of files * * @return int Exit status of the operation */ protected function removeFiles(array $files): int { $rc = 0; foreach ($files as $f) { try { unlink($f); } catch (NotWritableError $error) { Logger::error('Could not remove: %s', $f); $rc = 1; } } return $rc; } /** * Clean up older backups of Top Level View configuration files. * * This command removes the backups for one or all views. * By default it will remove all but one (the latest) backup. * * USAGE * * icingacli toplevelview cleanup backups [options] * * OPTIONS * --keep Number of backups to keep after the cleanup * --view Name of a view to remove backups for * * EXAMPLES * * icingacli toplevelview cleanup backups * icingacli toplevelview cleanup backups --keep 4 * icingacli toplevelview cleanup backups --view myview --keep 2 */ public function backupsAction(): void { $keep = (int) $this->params->get('keep', 1); $view = $this->params->get('view'); // Validate CLI parameters if ($keep < 0) { $this->showUsage('backups'); exit(1); } // Load the module's configuration directory $configDirModule = Icinga::app() ->getModuleManager() ->getModule('toplevelview') ->getConfigDir(); // Get all the backup directories for all views $configDir = $configDirModule . DIRECTORY_SEPARATOR . 'views'; $backupDirs = $this->listDirs($configDir); // If the view is provided check if it exists and use it for the cleanup if (isset($view)) { $viewDir = $configDir . DIRECTORY_SEPARATOR . $view; if (!in_array($viewDir, $backupDirs)) { Logger::error('No such view available: %s', $view); exit(1); } $backupDirs = [$viewDir]; } // Get all the .yml files and find out which to remove $rc = 0; foreach ($backupDirs as $dir) { $allFiles = $this->listYMLFiles($dir); $deleteThese = ($keep === 0) ? $allFiles : array_slice($allFiles, 0, -$keep); $rc = $this->removeFiles($deleteThese); } exit($rc); } } icingaweb2-module-toplevelview-1.0.0/application/controllers/000077500000000000000000000000001473125420300244025ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/controllers/EditController.php000066400000000000000000000056361473125420300300560ustar00rootroot00000000000000assertPermission('toplevelview/edit'); $tabs = $this->getTabs(); if ($name = $this->getParam('name')) { $tabs->add('tiles', [ 'title' => $this->translate('Tiles'), 'url' => Url::fromPath('toplevelview/show', ['name' => $name]) ]); $tabs->add('index', [ 'title' => $this->translate('Edit'), 'url' => Url::fromPath('toplevelview/edit', ['name' => $name]) ]); } $action = $this->getRequest()->getActionName(); if ($tab = $tabs->get($action)) { $tab->setActive(); } } public function indexAction() { $action = $this->getRequest()->getActionName(); $config_dir_module = Icinga::app() ->getModuleManager() ->getModule('toplevelview') ->getConfigDir(); $c = new ViewConfig($config_dir_module); $view = null; if ($action === 'add') { $this->view->title = sprintf('%s Top Level View', $this->translate('Add')); $view = new View('', $c::FORMAT_YAML); } elseif ($action === 'clone') { // Clone the view and give it to the View $name = $this->params->getRequired('name'); $this->view->title = sprintf('%s Top Level View', $this->translate('Clone')); // Check if the user has permissions/restrictions for this View $restrictions = $c->getRestrictions('toplevelview/filter/edit'); $c->assertAccessToView($restrictions, $name); $view = clone $c->loadByName($name); } else { $this->view->name = $name = $this->params->getRequired('name'); $this->view->title = sprintf('%s Top Level View: %s', $this->translate('Edit'), $this->params->getRequired('name')); // Check if the user has permissions/restrictions for this View $restrictions = $c->getRestrictions('toplevelview/filter/edit'); $c->assertAccessToView($restrictions, $name); $view = $c->loadByName($name); } $this->view->form = $form = new EditForm(); $form->setViewConfig($c); $form->setViews($view); $form->handleRequest(); $this->setViewScript('edit/index'); } public function addAction() { $this->indexAction(); } public function cloneAction() { $this->indexAction(); } } icingaweb2-module-toplevelview-1.0.0/application/controllers/IndexController.php000066400000000000000000000017211473125420300302270ustar00rootroot00000000000000 */ namespace Icinga\Module\Toplevelview\Controllers; use Icinga\Module\Toplevelview\ViewConfig; use Icinga\Module\Toplevelview\Web\Controller; use Icinga\Application\Icinga; /** * IndexController loads all existing Views from their YAML files. */ class IndexController extends Controller { public function indexAction() { $this->getTabs()->add('index', [ 'title' => 'Top Level View', 'url' => 'toplevelview', ])->activate('index'); // Load add views from the existing YAML files $config_dir_module = Icinga::app() ->getModuleManager() ->getModule('toplevelview') ->getConfigDir(); $c = new ViewConfig($config_dir_module); $views = $c->loadAll(); $this->view->views = $views; $this->setAutorefreshInterval(30); } } icingaweb2-module-toplevelview-1.0.0/application/controllers/ShowController.php000066400000000000000000000071621473125420300301050ustar00rootroot00000000000000getTabs(); $url = Url::fromRequest()->setParams(clone $this->params); $tiles = Url::fromPath('toplevelview/show', ['name' => $this->params->getRequired('name')]); $tabs->add('index', [ 'title' => $this->translate('Tree'), 'url' => $tiles ]); // Add new Tabs for the entire tree if (($id = $this->getParam('id')) !== null) { $tabs->add('tree', [ 'title' => $this->translate('Tiles'), 'url' => Url::fromPath('toplevelview/show/tree', [ 'name' => $this->params->getRequired('name'), 'id' => $id ]) ]); } $action = $this->getRequest()->getActionName(); if ($tab = $tabs->get($action)) { $tab->setActive(); } } public function indexAction() { $this->view->name = $name = $this->params->getRequired('name'); $config_dir_module = Icinga::app() ->getModuleManager() ->getModule('toplevelview') ->getConfigDir(); $c = new ViewConfig($config_dir_module); // Check if the user has permissions/restrictions for this View $restrictions = $c->getRestrictions('toplevelview/filter/views'); $c->assertAccessToView($restrictions, $name); $view = $c->loadByName($name); $this->view->view = $view; $tree = $view->getTree(); if (($lifetime = $this->getParam('cache')) !== null) { $tree->setCacheLifetime($lifetime); } $this->setAutorefreshInterval(30); } public function treeAction() { $this->view->name = $name = $this->params->getRequired('name'); $config_dir_module = Icinga::app() ->getModuleManager() ->getModule('toplevelview') ->getConfigDir(); $c = new ViewConfig($config_dir_module); // Check if the user has permissions/restrictions for this View $restrictions = $c->getRestrictions('toplevelview/filter/views'); $c->assertAccessToView($restrictions, $name); $view = $c->loadByName($name); $this->view->view = $view; $tree = $view->getTree(); $this->view->node = $tree->getById($this->params->getRequired('id')); if (($lifetime = $this->getParam('cache')) !== null) { $tree->setCacheLifetime($lifetime); } $this->setAutorefreshInterval(30); } public function sourceAction() { $this->view->name = $name = $this->params->getRequired('name'); $config_dir_module = Icinga::app() ->getModuleManager() ->getModule('toplevelview') ->getConfigDir(); $c = new ViewConfig($config_dir_module); // Check if the user has permissions/restrictions for this View $restrictions = $c->getRestrictions('toplevelview/filter/views'); $c->assertAccessToView($restrictions, $name); $view = $c->loadByName($name); $this->view->view = $view; $this->view->text = $view->getText(); $this->setViewScript('index', 'text'); } } icingaweb2-module-toplevelview-1.0.0/application/forms/000077500000000000000000000000001473125420300231625ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/forms/EditForm.php000066400000000000000000000132741473125420300254130ustar00rootroot00000000000000setName('form_toplevelview_edit'); } public function setViews(View $view) { $this->view = $view; return $this; } public function setViewConfig(ViewConfig $config) { $this->viewconfig = $config; return $this; } /** * @see Form::onSuccess() */ public function onSuccess() { try { $this->view->setName($this->getValue('name')); $this->view->setText($this->getValue('config')); // ensure config can be parsed... $this->view->getMetaData(); $this->view->getTree(); $cancel = $this->getElement('btn_submit_cancel'); $delete = $this->getElement('btn_submit_delete'); if ($this->getElement('btn_submit_save_file')->getValue() !== null) { // Store the view to its YAML file $this->viewconfig->storeToFile($this->view); Notification::success($this->translate('Top Level View successfully saved')); } elseif ($cancel !== null && $cancel->getValue() !== null) { // Clear the stored session data for the view $this->viewconfig->clearSession($this->view); Notification::success($this->translate('Top Level View restored from disk')); } elseif ($delete != null && $delete->getValue() !== null) { // Delete the view's YAML file $this->viewconfig->delete($this->view); $this->setRedirectUrl('toplevelview'); Notification::success($this->translate('Top Level View successfully deleted')); } else { // Store the view to the user's session by default $this->viewconfig->storeToSession($this->view); Notification::success($this->translate('Top Level View successfully saved for the current session')); } return true; } catch (Exception $e) { $this->error(sprintf('Could not save config: %s', $e->getMessage())); return false; } } public function getRedirectUrl() { if ($this->redirectUrl === null && ($name = $this->view->getName()) !== null) { $this->redirectUrl = Url::fromPath('toplevelview/show', ['name' => $name]); } return parent::getRedirectUrl(); } /** * Populate form * * @see Form::onRequest() */ public function onRequest() { $values = []; $values['name'] = $this->view->getName(); $values['config'] = $this->view->getText(); $this->populate($values); } /** * @see Form::createElements() */ public function createElements(array $formData) { if ($this->view->hasBeenLoadedFromSession()) { $this->warning( $this->translate( 'This config is only stored in your session!' . ' Make sure to save it to disk once your work is complete!' ), false ); } $this->addElement( 'text', 'name', [ 'label' => $this->translate('File name'), 'required' => true ] ); $this->addElement( 'textarea', 'config', [ 'label' => $this->translate('YAML Config'), 'class' => 'code-editor codemirror', 'decorators' => [ ['Label', ['tag' => 'div', 'separator' => '']], ['HtmlTag', ['tag' => 'div']], 'ViewHelper' ], 'data-codemirror-mode' => 'yaml' ] ); $this->addElement( 'submit', 'btn_submit_save_session', [ 'ignore' => true, 'label' => $this->translate('Save for the current Session'), 'decorators' => ['ViewHelper'] ] ); $this->addElement( 'submit', 'btn_submit_save_file', [ 'ignore' => true, 'label' => $this->translate('Save to config file'), 'decorators' => ['ViewHelper'] ] ); if ($this->view->hasBeenLoadedFromSession()) { $this->addElement( 'submit', 'btn_submit_cancel', [ 'ignore' => true, 'label' => $this->translate('Cancel editing'), 'class' => 'btn-cancel', 'decorators' => ['ViewHelper'] ] ); } if ($this->view->hasBeenLoaded()) { $this->addElement( 'submit', 'btn_submit_delete', [ 'ignore' => true, 'label' => $this->translate('Delete config'), 'data-confirmation' => $this->translate('Confirm deletion'), 'class' => 'btn-remove', 'decorators' => ['ViewHelper'] ] ); } } } icingaweb2-module-toplevelview-1.0.0/application/locale/000077500000000000000000000000001473125420300232735ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/locale/de_DE/000077500000000000000000000000001473125420300242335ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/locale/de_DE/LC_MESSAGES/000077500000000000000000000000001473125420300260205ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/locale/de_DE/LC_MESSAGES/toplevelview.mo000066400000000000000000000053051473125420300311050ustar00rootroot00000000000000 +$&*9? P^ c o y    ^ (EYd`!#!93mr 40E v.   .AJ\pr #  ? F  - $ &- 8T          %s host%s hosts%s unhandled host%s unhandled hostsAddAllow the user to edit Top Level ViewsCancel editingCloneConfirm deletionDelete configEditEditor HelpFile nameFind nextFind previousFullscreenJump to lineLast updatePersistent search (dialog doesn't autoclose, enter to find next, Shift-Enter to find previous)ReplaceReplace allSave for the current SessionSave to config fileSourceThis config is only stored in your session! Make sure to save it to disk once your work is complete!TilesTop Level View restored from diskTop Level View successfully deletedTop Level View successfully savedTop Level View successfully saved for the current sessionTreeUnsaved changes!YAML ConfigProject-Id-Version: Toplevelview Module (0.0.0) Report-Msgid-Bugs-To: dev@icinga.com PO-Revision-Date: 2024-06-14 16:05+0200 Last-Translator: Markus Opolka Language-Team: Language: de_DE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); X-Poedit-Basepath: . X-Generator: Poedit 3.0.1 X-Poedit-SearchPath-0: . %s Host%s Hosts%s unbehandelte Problem%s unbehandelte ProblemeHinzufügenErlauben dass Benutzer Top Level Views ändernBearbeitung abbrechenKlonenLöschen bestätigenKonfiguration löschenBearbeitenEditor HilfeDateinameNächster TrefferVorheriger TrefferVollbildZu Zeile springenLetzte AktualisierungDauerhafte Suche (Dialog schließt nicht automatisch, Enter für nächsten Treffer, Shift-Enter für Vorherigen)ErsetzenAlle ErsetzenFür die aktuelle Sitzung speichernSpeichern in KonfigurationsdateiQuelleDiese Konfiguration ist nur in Ihrer Sitzung gespeichert! Stellen Sie sicher sie in eine Datei zu speichern wenn Ihre Änderung fertig ist!KachelnTop Level View von Speicher wiederhergestelltTop Level View erfolgreich gelöschtTop Level View erfolgreich gespeichertTop Level View erfolgreich für Ihre Sitzung gespeichertBaumNicht-Gespeicherte Änderungen!YAML Konfigurationicingaweb2-module-toplevelview-1.0.0/application/locale/de_DE/LC_MESSAGES/toplevelview.po000066400000000000000000000136701473125420300311140ustar00rootroot00000000000000# Icinga Web 2 - Head for multiple monitoring backends. # Copyright (C) 2017 Icinga Development Team # This file is distributed under the same license as Toplevelview Module. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: Toplevelview Module (0.0.0)\n" "Report-Msgid-Bugs-To: dev@icinga.com\n" "POT-Creation-Date: 2017-10-13 11:53+0000\n" "PO-Revision-Date: 2024-06-14 16:05+0200\n" "Last-Translator: Markus Opolka \n" "Language-Team: \n" "Language: de_DE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Poedit-Basepath: .\n" "X-Generator: Poedit 3.0.1\n" "X-Poedit-SearchPath-0: .\n" #: ../../../../modules/toplevelview/application/views/helpers/Tree.php:58 #, php-format msgid "%s host" msgid_plural "%s hosts" msgstr[0] "%s Host" msgstr[1] "%s Hosts" #: ../../../../modules/toplevelview/application/views/helpers/Tree.php:54 #, php-format msgid "%s unhandled host" msgid_plural "%s unhandled hosts" msgstr[0] "%s unbehandelte Problem" msgstr[1] "%s unbehandelte Probleme" #: ../../../../modules/toplevelview/application/views/scripts/index/index.phtml:13 #: ../../../../modules/toplevelview/application/controllers/EditController.php:53 msgid "Add" msgstr "Hinzufügen" #: ../../../../modules/toplevelview/configuration.php:9 msgid "Allow the user to edit Top Level Views" msgstr "Erlauben dass Benutzer Top Level Views ändern" #: ../../../../modules/toplevelview/application/forms/EditForm.php:157 msgid "Cancel editing" msgstr "Bearbeitung abbrechen" #: ../../../../modules/toplevelview/application/views/scripts/show/actions.phtml:19 #: ../../../../modules/toplevelview/application/controllers/EditController.php:60 msgid "Clone" msgstr "Klonen" #: ../../../../modules/toplevelview/application/forms/EditForm.php:169 msgid "Delete config" msgstr "Konfiguration löschen" #: ../../../../modules/toplevelview/application/views/scripts/index/index.phtml:38 #: ../../../../modules/toplevelview/application/views/scripts/show/actions.phtml:9 #: ../../../../modules/toplevelview/application/controllers/EditController.php:33 #: ../../../../modules/toplevelview/application/controllers/EditController.php:66 msgid "Edit" msgstr "Bearbeiten" #: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:9 msgid "Editor Help" msgstr "Editor Hilfe" #: ../../../../modules/toplevelview/application/forms/EditForm.php:111 msgid "File name" msgstr "Dateiname" #: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:17 msgid "Find next" msgstr "Nächster Treffer" #: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:21 msgid "Find previous" msgstr "Vorheriger Treffer" #: ../../../../modules/toplevelview/application/controllers/ShowController.php:43 msgid "Fullscreen" msgstr "Vollbild" #: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:33 msgid "Jump to line" msgstr "Zu Zeile springen" #: ../../../../modules/toplevelview/application/views/scripts/show/tree.phtml:16 #: ../../../../modules/toplevelview/application/views/scripts/show/index.phtml:14 msgid "Last update" msgstr "Letzte Aktualisierung" #: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:13 msgid "" "Persistent search (dialog doesn't autoclose, enter to find next, Shift-Enter " "to find previous)" msgstr "" "Dauerhafte Suche (Dialog schließt nicht automatisch, Enter für nächsten " "Treffer, Shift-Enter für Vorherigen)" #: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:25 msgid "Replace" msgstr "Ersetzen" #: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:29 msgid "Replace all" msgstr "Alle Ersetzen" #: ../../../../modules/toplevelview/application/forms/EditForm.php:136 msgid "Save for the current Session" msgstr "Für die aktuelle Sitzung speichern" #: ../../../../modules/toplevelview/application/forms/EditForm.php:146 msgid "Save to config file" msgstr "Speichern in Konfigurationsdatei" #: ../../../../modules/toplevelview/application/views/scripts/show/actions.phtml:30 msgid "Source" msgstr "Quelle" #: ../../../../modules/toplevelview/application/views/scripts/show/actions.phtml:39 #: ../../../../modules/toplevelview/application/forms/EditForm.php:101 msgid "" "This config is only stored in your session! Make sure to save it to disk " "once your work is complete!" msgstr "" "Diese Konfiguration ist nur in Ihrer Sitzung gespeichert! Stellen Sie sicher " "sie in eine Datei zu speichern wenn Ihre Änderung fertig ist!" #: ../../../../modules/toplevelview/application/controllers/ShowController.php:24 #: ../../../../modules/toplevelview/application/controllers/EditController.php:23 msgid "Tiles" msgstr "Kacheln" #: ../../../../modules/toplevelview/application/forms/EditForm.php:56 msgid "Top Level View restored from disk" msgstr "Top Level View von Speicher wiederhergestellt" #: ../../../../modules/toplevelview/application/forms/EditForm.php:60 msgid "Top Level View successfully deleted" msgstr "Top Level View erfolgreich gelöscht" #: ../../../../modules/toplevelview/application/forms/EditForm.php:53 msgid "Top Level View successfully saved" msgstr "Top Level View erfolgreich gespeichert" #: ../../../../modules/toplevelview/application/forms/EditForm.php:62 msgid "Top Level View successfully saved for the current session" msgstr "Top Level View erfolgreich für Ihre Sitzung gespeichert" #: ../../../../modules/toplevelview/application/controllers/ShowController.php:33 msgid "Tree" msgstr "Baum" #: ../../../../modules/toplevelview/application/views/scripts/index/index.phtml:32 msgid "Unsaved changes!" msgstr "Nicht-Gespeicherte Änderungen!" #: ../../../../modules/toplevelview/application/forms/EditForm.php:120 msgid "YAML Config" msgstr "YAML Konfiguration" #: ../../../../modules/toplevelview/application/forms/EditForm.php:173 msgid "Confirm deletion" msgstr "Löschen bestätigen" icingaweb2-module-toplevelview-1.0.0/application/views/000077500000000000000000000000001473125420300231715ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/views/helpers/000077500000000000000000000000001473125420300246335ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/views/helpers/Badges.php000066400000000000000000000025711473125420300265360ustar00rootroot00000000000000'; foreach ($status->getProperties() as $key => $value) { if ($problemsOnly === true && ($key === 'ok' || $key === 'downtime_active') || ($key === 'total' && $showTotal !== true) ) { continue; } if ($value !== null && $value > 0) { $values = true; $title = $value . ' ' . Str::prettyTitle($key); $class = 'tlv-status-tile ' . str_replace('_', ' ', $key); $htm .= sprintf( '
%s
', $class, $title, $value ); } } $htm .= ''; return $values ? $htm : ''; } } icingaweb2-module-toplevelview-1.0.0/application/views/helpers/Breadcrumb.php000066400000000000000000000016761473125420300274240ustar00rootroot00000000000000'; foreach ($breadcrumb as $crumb) { $htm .= '
  • ' . $this->view->qlink( Str::limit($crumb->getTitle()), 'toplevelview/show/tree', [ 'name' => $config_name, 'id' => $crumb->getFullId() ] ) . '
  • '; } $htm .= ''; return $htm; } } icingaweb2-module-toplevelview-1.0.0/application/views/helpers/Tiles.php000066400000000000000000000031611473125420300264250ustar00rootroot00000000000000view->escape($node->getTitle()); $status = $node->getStatus(); if ($levels > 1) { $statusClass = 'tlv-status-section'; } else { $statusClass = 'tlv-status-tile'; } $statusClasses = [$statusClass, $status->getOverall()]; $htm .= sprintf( '
    ' . "\n", join(' ', $classes + $statusClasses), $title ); $badges = $this->view->badges($status); $htm .= $this->view->qlink( $title . $badges, 'toplevelview/show/tree', [ 'name' => $node->getRoot()->getViewName(), 'id' => $node->getFullId() ], [ 'class' => 'tlv-tile-title' ], false ); if ($levels > 1 && $node->hasChildren()) { $htm .= '
    '; foreach ($node->getChildren() as $child) { $htm .= $this->tiles($child, $levels - 1, $classes); } $htm .= '
    '; } $htm .= "
    \n"; return $htm; } } icingaweb2-module-toplevelview-1.0.0/application/views/helpers/Tree.php000066400000000000000000000100331473125420300262400ustar00rootroot00000000000000getTitle(); $type = $node->getType(); $cssClasses = join(' ', $classes); $status = $node->getStatus(); $statusClass = $status->getOverall(); if ($type === 'host') { $icon = 'host'; $url = Url::fromPath('icingadb/host', ['name' => $node->get('host')]); } elseif ($type === 'service') { $icon = 'service'; $url = Url::fromPath( 'icingadb/service', [ 'name' => $node->get('service'), 'host.name' => $node->get('host') ] ); } elseif ($type === 'servicegroup') { $icon = 'services'; $url = Url::fromPath( 'icingadb/servicegroup', [ 'name' => $node->get('servicegroup'), 'sort' => 'service.state.severity desc' ] ); } elseif ($type === 'hostgroup') { $icon = 'cubes'; $url = Url::fromPath( 'icingadb/services', [ 'hostgroup.name' => $node->get('hostgroup'), 'sort' => 'service.state.severity desc' ] ); if (($h = $status->getMeta('hosts_unhandled')) > 0) { $hostTitle = '(' . sprintf($this->view->translatePlural('%s unhandled host', '%s unhandled hosts', $h), $h) . ')'; } else { $h = $status->getMeta('hosts_total'); $hostTitle = '(' . sprintf($this->view->translatePlural('%s host', '%s hosts', $h), $h) . ')'; } $htmExtra .= ' ' . $this->view->qlink( $hostTitle, 'icingadb/hosts', [ 'hostgroup.name' => $node->get('hostgroup'), 'sort' => 'service.state.severity desc' ], null, false ); } else { $icon = null; $url = Url::fromPath( 'toplevelview/show/tree', [ 'name' => $node->getRoot()->getViewName(), 'id' => $node->getFullId() ] ); } if ($type !== 'node') { $htm .= "
    "; $htm .= $this->view->icon($icon) . ' '; $htm .= $this->view->qlink($title, $url); $htm .= $htmExtra; $htm .= ' ' . $this->view->badges($status, false); $htm .= '
    '; } else { $htm .= "
    "; $htm .= '
    '; $htm .= $this->view->badges($status, false, $level === 0 ? true : false); $htm .= ' '; $htm .= $this->view->qlink($title, $url); $htm .= $htmExtra; $htm .= '
    '; if ($node->hasChildren()) { foreach ($node->getChildren() as $child) { $htm .= $this->tree($child, $classes, $level + 1); } } $htm .= '
    '; } return $htm; } } icingaweb2-module-toplevelview-1.0.0/application/views/scripts/000077500000000000000000000000001473125420300246605ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/views/scripts/edit/000077500000000000000000000000001473125420300256055ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/views/scripts/edit/index.phtml000066400000000000000000000021751473125420300277670ustar00rootroot00000000000000compact): ?>
    tabs ?>

    translate('Editor Help') ?>

    Ctrl-F / Cmd-F translate('Persistent search (dialog doesn\'t autoclose, enter to find next, Shift-Enter to find previous)') ?>
    Ctrl-G / Cmd-G translate('Find next') ?>
    Shift-Ctrl-G / Shift-Cmd-G translate('Find previous') ?>
    Shift-Ctrl-F / Cmd-Option-F translate('Replace') ?>
    Shift-Ctrl-R / Shift-Cmd-Option-F translate('Replace all') ?>
    Alt-G translate('Jump to line') ?>
    icingaweb2-module-toplevelview-1.0.0/application/views/scripts/index/000077500000000000000000000000001473125420300257675ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/views/scripts/index/index.phtml000066400000000000000000000022561473125420300301510ustar00rootroot00000000000000compact): ?>
    tabs ?>
    icingaweb2-module-toplevelview-1.0.0/application/views/scripts/show/000077500000000000000000000000001473125420300256405ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/views/scripts/show/actions.phtml000066400000000000000000000032571473125420300303550ustar00rootroot00000000000000 icingaweb2-module-toplevelview-1.0.0/application/views/scripts/show/index.phtml000066400000000000000000000020231473125420300300120ustar00rootroot00000000000000getTree(); if (! $this->compact): ?>
    tabs ?> partial('show/actions.phtml', $this) ?>
    hasBeenLoadedFromSession()): ?>
    translate('This config is only stored in your session!' . ' Make sure to save it to disk once your work is complete!') ?>

    getMeta('name') ?>

    timeAgo($tree->getFetchTime()) ?>
    badges($tree->getStatus(), false, true) ?>
    getChildren() as $topTile): ?> tiles($topTile) ?>
    icingaweb2-module-toplevelview-1.0.0/application/views/scripts/show/tree.phtml000066400000000000000000000012571473125420300276520ustar00rootroot00000000000000getTree(); if (! $this->compact): ?>
    tabs ?> partial('show/actions.phtml', $this) ?>

    getMeta('name') ?>

    timeAgo($tree->getFetchTime()) ?>
    badges($tree->getStatus(), false, true) ?>
    breadcrumb($node->getBreadCrumb(), $view->getName()) ?> tree($node) ?>
    icingaweb2-module-toplevelview-1.0.0/application/views/scripts/text/000077500000000000000000000000001473125420300256445ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/application/views/scripts/text/index.phtml000066400000000000000000000002551473125420300300230ustar00rootroot00000000000000compact): ?>
    tabs ?>
    text ?>
    icingaweb2-module-toplevelview-1.0.0/configuration.php000066400000000000000000000033061473125420300231130ustar00rootroot00000000000000 */ /** @var \Icinga\Application\Modules\Module $this */ $this->providePermission('toplevelview/edit', $this->translate('Allow the user to edit Top Level Views')); $this->provideRestriction( 'toplevelview/filter/edit', $this->translate('Restrict edit rights to Views that match the filter (comma-separated values)') ); $this->provideRestriction( 'toplevelview/filter/views', $this->translate('Restrict access to Views that match the filter (comma-separated values)') ); /** @var \Icinga\Web\Navigation\NavigationItem $section */ $section = $this->menuSection('toplevelview'); $section ->setLabel('Top Level View') ->setUrl('toplevelview') ->setIcon('sitemap') ->setPriority(50); $this->provideJsFile('vendor/codemirror/codemirror.js'); $this->provideJsFile('vendor/codemirror/mode/yaml.js'); $this->provideJsFile('vendor/codemirror/addon/dialog/dialog.js'); $this->provideJsFile('vendor/codemirror/addon/search/searchcursor.js'); $this->provideJsFile('vendor/codemirror/addon/search/search.js'); $this->provideJsFile('vendor/codemirror/addon/search/matchesonscrollbar.js'); $this->provideJsFile('vendor/codemirror/addon/search/jump-to-line.js'); $this->provideJsFile('vendor/codemirror/addon/fold/foldcode.js'); $this->provideJsFile('vendor/codemirror/addon/fold/foldgutter.js'); $this->provideJsFile('vendor/codemirror/addon/fold/indent-fold.js'); $this->provideCssFile('vendor/codemirror/codemirror.css'); $this->provideCssFile('vendor/codemirror/addon/dialog/dialog.css'); $this->provideCssFile('vendor/codemirror/addon/search/matchesonscrollbar.css'); $this->provideCssFile('vendor/codemirror/addon/fold/foldgutter.css'); icingaweb2-module-toplevelview-1.0.0/doc/000077500000000000000000000000001473125420300202765ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/doc/01-Introduction.md000066400000000000000000000050121473125420300235150ustar00rootroot00000000000000Introduction ============ Top Level View is a hierarchy based status view for Icinga Web 2. You can define a hierarchical structure containing hosts, services and host groups. This view presents you an overview of the overall status of the sub-hierarchies. These hierarchical structures are configured in a YAML file. Example: ```yaml name: My View children: - name: Section 1 children: - name: Tile 1 children: - host: localhost - host: localhost service: disk - host: anotherhost service: ssh - name: Tile 2 hostgroup: linux-servers - servicegroup: http ``` The files are stored in `/etc/icingaweb2/modules/toplevelview/views/`. Example: `/etc/icingaweb2/modules/toplevelview/views/myview.yml`. **Hint:** Top Level View can use additional status logic for its views, see later chapters on details. ## Installation Top Level View is a module for Icinga Web 2, and can be installed via git or a tarball. The only other requirement is the PHP YAML extension. **Hint**: Make sure to reload your web server after installing the extension. # on RHEL and compatible dnf install php-pecl-yaml systemctl reload httpd.service # on Debian / Ubuntu apt-get install php-yaml systemctl reload apache2.service You can download the latest released tarball from [GitHub](https://github.com/Icinga/icingaweb2-module-toplevelview/releases). tar xf icingaweb2-module-toplevelview-1.0.0.tar.gz mv icingaweb2-module-toplevelview-1.0.0/ /usr/share/icingaweb2/modules/toplevelview Or - if you prefer - use Git. git clone https://github.com/Icinga/icingaweb2-module-toplevelview.git \ /usr/share/icingaweb2/modules/toplevelview git checkout v1.0.0 Then enable the module in the web interface, or via CLI: icingacli module enable toplevelview **Hint:** This module is capable of strict Content Security Policy (CSP). ## Permissions and Restrictions Top Level View offers the following permissions and restrictions: * Permission `toplevelview/edit`, allow the user to edit Top Level Views * Restriction `toplevelview/filter/edit`, restrict edit rights to Views that match the filter (comma-separated values) * Restriction `toplevelview/filter/views`, restrict access to Views that match the filter (comma-separated values) Restrictions use the filename of the YAML files. Example: `toplevelview/filter/edit: myview,anotherview` ```bash ls -l /etc/icingaweb2/modules/toplevelview/views/ myview.yml anotherview.yml someview.yml ``` **Hint:** Commas in filenames should be avoided. icingaweb2-module-toplevelview-1.0.0/doc/02-Configuration-and-Behavior.md000066400000000000000000000041211473125420300261410ustar00rootroot00000000000000Configuration and Behavior ======== Top Level View (TLV) uses additional status logic for its views. This does not affect the overall status behavior of Icinga 2 or Icinga Web 2, but it is important to understand the differences. ## Worst state on top The main responsibility of TLV is to show you the worst state on top. Worst status is defined in the following order: * critical_unhandled * warning_unhandled * unknown_unhandled * critical_handled * warning_handled * unknown_handled * ok * downtime_handled * missing In addition, counter badges will present you in-depth details over the status below a tile or tree element. Similar to Icinga Web 2 you can easily see unhandled problems by the color of a tile. ![Unhandled problems](screenshots/colors-unhandled.png) ![Handled problems](screenshots/colors-handled.png) ## TLV only shows Hard States While the normal monitoring views will always show you all current states, the **Top Level Views will only show hard states**. Which means, as long as the object doesn't have reached a hard state, the TLV tree element will be OK. ## Configuration Options These options can change the behavior of views. They are placed at the top of a view configuration: ```yaml name: My View set_downtime_if_notification_disabled: true override_host_problem_to_handled: true children: - name: Section 1 ``` ### Option `override_host_problem_to_handled` (bool) This overrides every host problem to be handled. * `override_host_problem_to_handled = true` * `override_host_problem_to_handled = false # (default)` This helps when alerting is mostly based on service states, and the host is only a container. Only applies to host and hostgroup objects. ### Option `set_downtime_if_notification_enabled` (bool) Set the host or service to "active downtime" if notifications are disabled. * `set_downtime_if_notification_disabled = true` * `set_downtime_if_notification_disabled = false # (default)` Since downtime and notification settings are essential for alerting, Top Level Views tries to integrate these into its status logic. Only applies to host and service objects. icingaweb2-module-toplevelview-1.0.0/doc/10-User-Guide.md000066400000000000000000000044771473125420300230230ustar00rootroot00000000000000User Guide ========== This guide describes the basic usage of the module and how to access its data quickly. To understand the status behavior, see the [chapter about behavior](02-Behavior.md). ## Creating views Views can be created in the TLV overview with the "Add" button, or directly in the module's configuration directory. Example: `/etc/icingaweb2/modules/toplevelview/views/example.yml` The module ships a very basic configuration editor, which allows to to edit the bare YAML configuration within the web interface. After a view is created it will show up in the TLV overview. ## Finding problems Unhandled problems can be identified based on color saturation of the tiles. In addition counters show you how many states of what kind lay below. ![Unhandled colors](screenshots/colors-unhandled.png) ![Handled colors](screenshots/colors-handled.png) ## Drilling down When you click on tiles in the topmost tile view, you drill down into a tree view of that tile. The tree view is collapsing everything that is in an OK state. So you see the problems first. ![](screenshots/tiles-tree-problems.png) Everything can be expanded via the arrow handle or a click on the title area. Deeper branches can be opened in a new view by clicking on the title text, but this is only needed to filter the shown data. Every Icinga status object, a host, service or host group is a single tile here. Counters are meant to give you an indication about how many problems, or even objects are there. ## Viewing Icinga details By clicking on an Icinga tile you get dropped into the object's details, Clicking on a service ![tile](screenshots/tile-service.png) will bring you service detail view, same goes for hosts. ![](screenshots/tree-service.png) The host group ![tile](screenshots/tile-hostgroup.png) gives 2 options, default will take you to a service overview for that host group, sorted by problems. While clicking on the `X hosts` link in the tile brings you an overview over hosts in that group. ![](screenshots/tree-hostgroup.png) ## Using the TLV Cache Please be aware that the data displayed in the Top Level View is cached for 60 seconds by default. This can be adjusted using the URL parameter `cache`. For example: `toplevelview/show/tree?name=example-view&cache=30` Latest state changes will only be reflected after that caching time. icingaweb2-module-toplevelview-1.0.0/doc/20-Editor.md000066400000000000000000000024721473125420300222720ustar00rootroot00000000000000Configuration Editor ============= The module ships a very basic configuration editor, which allows to to edit the bare YAML configuration within the web interface. Please also see the [chapter on config format](21-Config-Format.md). ## Saving You have two options on saving: * Save to session - so you can test and review your edit * Save to disk - it is stored to disk and visible for everyone with access When you have saved changes to your session, but not yet disk, the interface reminds you of that. Also you can cancel an edit with a button below the editor, and return to disk state. ## History When updating a view with the Editor the module creates a backup of the previous version. These previous states are saved to disk, so it can be restored. ```bash # /etc/icingaweb2/modules/toplevelview/views//*.yml ls -l /etc/icingaweb2/modules/toplevelview/views/myview 1722014991.yml 1721917992.yml 1721915691.yml ``` **Hint:** There is no web interface to manage these files. However, the `icingacli` offers a subcommand to clean these up. ``` # Removes all but one backups for all views icingacli toplevelview # Removes all but one backups for a specific view icingacli toplevelview --view myview # Removes all but two backups for a specific view icingacli toplevelview --view myview --keep 2 ``` icingaweb2-module-toplevelview-1.0.0/doc/21-Config-Format.md000066400000000000000000000106731473125420300235020ustar00rootroot00000000000000Configuration Format ==================== The configuration format is YAML. It is an easy way to define data in a hierarchy, and still being able to view and modify it as a human. For details on the format see [yaml.org](http://yaml.org/). The configuration is structured in a hierarchical object structure like: root object -> children (array) -> objects -> more children Every node is unique in the tree, but names can be repeated. An Icinga objects can be inserted multiple times. ## Example ```yaml name: View Name children: - name: Section 1 children: - name: Tile 1 children: - host: localhost - host: localhost service: disk - host: localhost service: ssh - name: Tile 2 hostgroup: 'linux-servers' - name: Tile 3 servicegroup: 'http' - name: Section 2 children: - name: Tile 1 - name: Tile 2 - name: 'Tile 3: The return of long names' ``` ## Layers The first three layers have a special meaning for the view. 1. Root Node - defines the name of the view 2. Sections - defines the sections in the tile view 3. Tiles - builds tiles in the tile view Everything below is only visible via the tree view, and every Icinga node should be below the 3rd level. ## Nodes Every node is an object in YAML, while the object attribute `children` is an array of all children objects for that node. Indention does matter as far as it defines the levels and structure of the objects. (Please use no soft tabs!) Every node can have multiple attributes, they are partially validated, and unknown keys just get ignored. ### Name nodes Default node type is a simple named node that gets status from deeper nodes. The root node itself has also only a name, but can contain options mentioned below. Attributes: * `name: Test` user readable name of the object ### Icinga Host Brings in the host state of an individual Icinga host. Attributes: * `host: localhost` hostname in Icinga * `type: host` (optional - detected by key attribute) ### Icinga Service Brings in the service state of an individual Icinga service. Attributes: * `host: localhost` hostname in Icinga * `service: servicename` service name in Icinga * `type: service` (optional - detected by key attribute) ### Icinga Host group Brings in the host group summary state. Attributes: * `hostgroup: linux-servers` host group name in Icinga * `type: hostgroup` (optional - detected by key attribute) ### Icinga Service group Brings in the service group summary state. Attributes: * `servicegroup: disk` service group name in Icinga * `type: servicegroup` (optional - detected by key attribute) ## Options Additional options are available to control status behavior of the respective view. These options are just set on the root node: ```yaml name: Test Config with Options override_host_problem_to_handled: true children: - name: Section 1 ``` ## Examples Here is a longer example from a testing configuration: ```yaml name: Test children: - name: Single Objects children: - name: OK children: - host: host_ok - host: host_ok service: s_ok - host: host_s_soft - host: host_s_soft service: s_critical_soft - name: DOWN children: - host: host_down - host: host_down service: s_critical - name: CRITICAL children: - host: host_s_critical - host: host_s_critical service: s_critical - name: WARNING children: - host: host_s_warning - host: host_s_warning service: s_warning - name: Single Objects Handled children: - name: CRITICAL handled children: - host: host_s_critical_handled - host: host_s_critical_handled service: s_critical_handled - name: WARNING handled children: - host: host_s_warning_handled - host: host_s_warning_handled service: s_warning_handled - name: Hostgroups children: - name: OK children: - hostgroup: HG_OK - hostgroup: HG_SOFT - name: DOWN children: - hostgroup: HG_DOWN - name: CRITICAL children: - hostgroup: HG_CRITICAL - name: WARNING children: - hostgroup: HG_WARNING - name: TLV Missing children: - name: Partially missing children: - host: host_ok - name: missing - name: Missing with problems children: - host: host_down - name: missing - name: Missing with handled children: - host: host_down_handled - name: missing - name: Empty children: - name: nothing here - name: Notexisting Object children: - host: notexisting ``` icingaweb2-module-toplevelview-1.0.0/doc/80-Development.md000066400000000000000000000025531473125420300233340ustar00rootroot00000000000000# Development A short overview of the TLV classes and their roles. `ViewConfig` is responsable for managing the YAML files that contain the views. ``` $c = new ViewConfig($modules_config_dir) $views = $c->loadAll(); $view = $c->loadByName('myview'); ``` This class also handles storing/loading the view data into either YAML files or the user's session. `Model\View` represents a single Top Level View and is responsable for parsing the YAML data. It also contains the tree data structure representing the view's hierarchy. The `getTree()` method will return this tree. `Tree\TLVTree` represents the root of the TLV tree. It store and load itself from the Icinga Web `FileCache` via the `storeCache()/loadCache()` methods. `Tree\TLVTreeNode` represents a node in the TLV tree. Each node has an numeric ID based on its position in the tree (example: 9, 9-0, 9-1, 9-0-1). This ID is also used in HTML links to show a subtree. This class is used in recursively rendering the tree into HTML. `Tree\TLVIcingaNode` is a tree node that can fetch Icinga data from the database. Each of the classes `Tree\TLVHostGroupNode`, `Tree\TLVHostNode`, `Tree\TLVServiceNode` extends this class. Each node uses the `fetch()` method to retrieve its data from the database They use `Tree\TLVStatus` to represent their current status, which is determined with `getStatus()` method of each node. icingaweb2-module-toplevelview-1.0.0/doc/91-Custom-Styling.md000066400000000000000000000013631473125420300237530ustar00rootroot00000000000000Custom Styling ============== With a custom theme you can change style and colors of the Top Level View. Here are a few examples. ## Blinking unhandled So that unhandled problems are more visible. ```less .container.icinga-module.module-toplevelview { .tlv-status-tile.unhandled { animation: blinker 1.5s linear infinite; } } @keyframes blinker { 50% { opacity: 0.2; } } ``` ## Dark full screen When you open the TLV in full screen mode, background will be dark. ```less .fullscreen-layout { .container.icinga-module.module-toplevelview { color: #eee; a:visited { color: inherit; } background: #333; .controls { background: inherit; .active { color: #333; } } } } ``` icingaweb2-module-toplevelview-1.0.0/doc/99-Screenshots.md000066400000000000000000000012041473125420300233540ustar00rootroot00000000000000Screenshots =========== Tile view with lots of objects: ![](screenshots/tiles.png) Tile and Tree view with problems: ![](screenshots/tiles-tree-problems.png) Tree view with no problems (all collapsed): ![](screenshots/tiles-tree-noproblems.png) Tree view with no problems (expanded by user): ![](screenshots/tiles-tree-noproblems-expanded.png) Tree view problems on a host group, and the host group details: ![](screenshots/tree-hostgroup.png) Tree view problems on services, and the service details: ![](screenshots/tree-service.png) Overview over all defined views, and the open editor: ![](screenshots/overview-and-editor.png) icingaweb2-module-toplevelview-1.0.0/doc/screenshots/000077500000000000000000000000001473125420300226365ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/doc/screenshots/colors-handled.png000066400000000000000000000163441473125420300262520ustar00rootroot00000000000000PNG  IHDRT z,ksBIT|dtEXtSoftwaregnome-screenshot>vIDATxytLɾȒ=da nMQׅJX r^[+`zqDRfaIKIH d1d$dHfR:'gؙh~;lk|Pü<=3Zjz-T`` bu]Ӑ!Cyۆ;C{N֭[b 8P{)]Z`޾pB}w{j{խ|~C4v$dH 1|߷0%I*E-']6||fzڰaM0AǎO?\=䓝ֽT~'۸- CݫwX7Mk3)NN<&edd(""B_zqq.]sjԨQկ~yiϞ=:x K*((HYYYZvZ[[umiժU={&MԮϜk*))QJJ-[޽{+S\\O>D]wzIRFFϟ?O%IgΜo[jĈZt***={v}i*..VLLΝqJKK%:-_\󎲲T]]$yJOOWw|jS޽uȑNꫯ* @3f̸hgos8W6gKjm貈Ow}W/U[[l@@$iZpnvh*++K/ \ΩSOjzeZOw+77Wݔ$]}hɒ%Zhrrrn:<{~)>>^/+VRO=$iƌZ|>^{M?j*i^_ĉϪ@߼/F/*))~g6Ҿ(:l0o'\ϿoԆO*,,L>駟ꩧ]wݥ^Z,IRff'JrMڳg$SXXOjʔ) ɓv;_PPl6jjjƏhM8Qڻw}nkʔ) ҥK+W^޶?g{Z|E{ァӧO_߿^}U͛7OQQQyԩ ̙3}޶TV]P`۩lPT͸KMMC=$ݮ|O5d 8CpIZi8mEEEyף>nӧۅvva3I]B?|kMT__ <5J6M7nTmmy-^}MLLf̘[O>QSS ׿U o߮ m޼YMMMuV9fl6mڴIZbnv( @Eeeejii֭[L4h^䋶;wTr:^纺:_m|&O3g?]wݥ:p-[k;~-YDaw޺UXX Zh{Z|ܹs;?#GGUPPZZ\+Ǐ?z4qD͚5>*=*--Ղ t!-ZHqqq_رc5n8=#7ovءe˖y5]x3g_~z'e-YDC>lyڽ{-[TIr o޳mp%m+Q#S$M yٚI*,U2#Pi S{HťI\ Q#SS륚Չ*Lw=&T]v*3)I:~JrJ>@;E*!LIRu$s= PөM_UQ_ r8ZoiX\fI҃ nn,;屯ߓ>Pcs{֭mmc{{?PTHEc3zn=vw7uęJmvFkDNFep:} \>W 5&$U^Hsۚ;WK|5W-thuh۵a)Wide\w{Ry4I҃+wii@\WN>Y{Uq֮@ctD%ņSz=[pى(CwlmgqMUTjC.'Ux^e1р^}ܬz-Z6mVتucڵ)3܏`f֧Vu %UgdU!:RQ/ntLuwmg\_d$GjYw*,QhVUjTzY%Hq$k{F**"PTYmkѺm't˔dIRUg4id{w9FoɯЏP055;@VtX>LAߤ7gk:>X?kѮ rxʍJ =1$S3dJrP0NG.km 4:y[jڷG d5J$Uݮ~z&WhNԫ;jle߫@dD~^m.V`U?sgki蘋gޖcnTJ\‚|j3_k -.np9] wVe]>/:>NSN~)_'OtJ4GS룼ݒF7GN7HAXT^S-ӡn2X#I:UuVYԢI7`iʺZެ[G^z#gOmtJQp| J WE'%IEUxlVU6HUz?á]+56FVnAZZ:~kSYmyմ[é1}Too#gcWfs)o54p413ZXTЬ׽j}bS'%I~~VtW;xީze}~RfWౚUҭSiJFg*nXo3TWYAA^}oX1TsgtRcb{F&%ԟiCdZ5$6Q[ JB[~.OE'ԡXmG\>]}cԯkZڔTE~KO*w%Jfeo>xCVJtD#">=) O)/RDh4*o%F*hl~:UiWj?EU~-;њ9!C߷MMk(-9k\|M]BjgsΫOSGǵtZtxY, {\gBZF9*e疟WO~l,\m_^;|FzkGDkƣC~QR5dUY$7D Vt`mޗC\:+,*4Dg*۶^&Je;v8]k|T!6YέXpNݳCɮCѱ[v^ l»P}SKOjn&KcgpY, J ׮ Sbt;@elw{k@նI׽|u;NWBtLQ.y6U5/o$OZ;^ԤoY+# OF%׎z5J#jŖz}6MOzz Q5upV#K6?ݐ1\%A!؉ZsU)>"JsFM I{H,5)&%7zPߒbQj;RǠpPJOrMp\^Z]I#:^gOyqqږ[nO@r\gh-QOG֎};Ӓ|IhPMoo UR1$Yfc*'XsSS2\k2 核gq:=W9t&I_rݨIҰҺ-g\6mǠ zv@O_R駮u"rwtx׷͘WqFbTW]6K17~[C]u?lW:[|KWg~ޙruVp_uRܬ^sHjK?>.+qy5S.炕7X3u1x˛DpysXt                                                                          Tz4 ˜==3TTTTTTT7/0,NӃ:c   u:fIENDB`icingaweb2-module-toplevelview-1.0.0/doc/screenshots/colors-unhandled.png000066400000000000000000000156561473125420300266220ustar00rootroot00000000000000PNG  IHDR[esBIT|dtEXtSoftwaregnome-screenshot>@IDATxyxTU_UJe! ªl I؂",jۂ2,-6ȴvL<-n 6,:D @d&’,?.Y* Iխs9I._s-v Fدv3A-=Mv,}&jոqA+ "lD0`P Ri5sHiRhHŶBms$I7Ii_󾮸qRѤ֢^lٳG>&OI&i֬YJJJ$iܸqZ|D](--Պ+kĉ:u?̙3>5hIg_K_v$HvTAKRI^lj޼y… eo?V=Զm[-[̷N6{Ok׮#<~z״{n5P7o׻.ߗHT]/nܹszԦM;pB9sF ,$5JWjj,Y_Ժuk-^؛_3קQsoH~^Mբk_ϱ|-zU ճ>X[N ,ԩSh"xl={E0`$kjǎaÆ)44TÇdh ѠARL^^^y*s:r8)ַo_EEEi Ν;n399Y\إK͙3GJIIъ+n:uU;wRIkua/...?eEDDTV٨s=l r^?v]ͲjJLL֭[OǏu_K)hzUp%[z+R*Ϸ~p:ի4{leffVSxB׹s-WΝ]^Xvm۶M~{^zo+ dpڶmuǎwm|AM8Q˵l29^).FǫF\~LD(//O|$[7zV'%%)//OkV?z7ph՟'͘1C.ˣ\˖-5j(mڴIk֬Çm۶Ӕ[nUVV6l U˛6#á$j…4i ͦ kӦM4EGG}+_.ѩԹ_ݛ֠AիW?ZnYf)..Niii^5֪U+M#M6Mm۶˧$+2e6m>LBBBt-Tū^zIǏ׀t]w)##ë6fϞ]Z5}tnZ4|p%%%̙]viܹWV4k, . M5DnRaa}$iƲzqD9}H>њ^Y 9;6R0եoթRo9rDO?~a5h[թ|ˊc^\5|Q9Iv:OA'V<0tE?1;;[=,XmܸQvݧȆ%ɻuqEVXXƏ#G衇Rrrf̘v]nH?j߾wtoGWoP~qV]:tz}Ztחѣ$;/~ue$;VBAԗ`}O#bUWf Ѹl\o[ "lՈwyt?F`=ύ*[q"ܐholZ F "lD0`a A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A-[l+אuõEOp ,9R|L ]m;ג6{$@EfJ 7_]-@xr"Zڹzun=.;II~6Bu@:wAմtHϺ_5 WRϥ˥SӪ~q# \-@F|=9I{$;8A\|q6Gڱڟ!eM:}N3uɦvePr9sOMymv}1|y:]-IMyιrOoV<'J?nI [S*);Gzy+i|ޫҢM[m^+}NZIETOYcT+JcXpHY9_deK@.A~6\>:=WJ2t> / mo(iϥqշL*?+[)(Pl̹| y,s5NkD!HTTRgVgꁛ6W[|{GZH^NRaq~?Ey]qhSVN@{y46! XT엙rK:F{UvCyt4_Y }SD74 mvkЗUV)~U1.l=3JkUj zz׫O쬇b["hTvhLO'ߨ8btһ-"Jʡ} "ڔ*[\jⴗbm6;:Rf:\~3yZ/Sr5l}Psդӽ7wA' 4Wu حmiZszjH39*t־Fl־ hIjaszLJ uBߒM٦G'hc~Uu&3|}ֶ;vHRZ;!IJ=Vӣ[gS'v3W߃Il9E6@&ҽcj>k9i_;:}FVÍW!In6]ܯm֤e&6*P3ʟdԿCgʷp)EE|V>TS4pF*߮&N? ߏhXOT5գi'eϑ xj4-7JYiWXYH'3endkރRhtC[뵄-m=P&YSxX$tUn)ef?#"Bd2+K'k:Ե7GJCKjȶm6_oifkw5ِX(U[+%å2rT⢬Uvk{ZnڝRqpguhV1WR*!HyR;UXkk+vHNFTo2rln:Ҩ:>-QϦʟ1Qv\ yhMˮִܹFQ+yt< a=50X#c-D6Y\~gDp%[zP5czŊ.v u/صOC\)4б )2@).9t6Dm,P).9l:S.G*T Y^ۥ:*m߳lQlkչ\RVJ5cՐhΩQM_Iy^kTa+WZ&kLLg s5:{RGsO^nBZuƚJND5* ]JΜmo#ǭҀ#ұZ5-,FuVjԻek"­ -kݭm:Ұa WU\@d*iWln' `SpX~PWV=Vٚqmu_ա ӷG+di ]og,,囙TF<}BQAnҦk[̊Q#9JI⃉K;vXQEԱu1zKvYwbnqֶ.QOG)9R˖9w ZmIcI&Mf}=0]hB¡YE:Y֨QL:S]8*.ro޸޸^g[Xu}aXv ݗޮM@򋽛C|pk*pJRkԨ9WVۨg~"rk}zwO|'__"¥n Yׯ^+.tH"X8/gq>$=oMIz2sYgo.aKKߒna}chXX{OhƲwվ $/_,Q1;ZF#[Z B_BZ]pZIctuoR t,nEg׶E_0<_vH+T\Kk[uiҡ/%Xt Wo %zw9B*D^jdwG4c)9ҌjW^NFũ_+@?F*(_go+ܲUsMk{ka5PHUulL˺?_Y'M}Qn{^+E{X'._Y8]5ͪrk}dl].5S..oX+<^jfc{KocMi۫y/Bxi7/Juv6s=${ deXkp6M]Zh)G0nS6אUک_UCrPFņh\Vڬ1hy+G\e)0fzb`Ӫ mv)2w6lJ&L|u[;Rhif'Z'L<6/jTӈ@}BW7IJXu苦RϺ_5 WXsتOe˴E2ڷhtӈ@}ܝä1wY;RA5}wպFnmK]~Y૆<*lØ1vG]Rqtp|PfN*5kȺ_qZfU#Yu)Ky{\CoBT# Za (A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A-[ "lD0`a A6.6aKߺ0A-[ "lD0`^z-hPL#D0ިIENDB`icingaweb2-module-toplevelview-1.0.0/doc/screenshots/overview-and-editor.png000066400000000000000000003757621473125420300272620ustar00rootroot00000000000000PNG  IHDRgY IDATx^ MUǿq`2T$o"颢 .ӛ荊jzTTROʥQri`\f0.3?>̙3]go}Z[U)/CID@D@D@D@D@D@D@D@D@D *I (oU&" " " " " " " " " @mjh[>Y,CE@D@D@D@D@D@D@D@D@D@(7q:'#." " " " " " " " " " 9{N:/{'.}8W5 ? JE? TK$Ir((%Pna ?9OwiQ׮}8,(Pjvt,OQtU@YzRk(7q&uЪ^M,ٔswj&~"i?5= DHu"I"j" " AN8mjwjS[#g~[I*@(.+SEש/" " "@('x!`[]7mjao9:R[pfbRci,Bq1HuYD@D@B@(' %+E@D@"mqvs_wG3K'ş6 {׾ȠV,P\L,22ӭ" " " J דZ[P" " "9M&u[p5o:*⵳1_MkWdz߯eȄv/B)>-j/WC@RoV,*ƨZ+" "lhY7 o <9-ݜ>yJmq::,{'.}YpuaE a6MD@D@D Bq=U*|gYZ1X|Zݍӳ\^;N NW%});|6ftQEQR%:|8Z+SD@D@D@B@('kmuU(\*" ",|gp51 cO['m{~۾կm]0tޯm޵<^ h; 5Qx0ݔqY" " " M ד^[i]S@(#Y뀰}GVn߃?wb((@0v1=zhk)Sf͚>7k/">>rܸn:^(/:w/9>S۷{W<~xqs&xay6ގQq L; oSVuKg΍R|^]7Vn|xy;tiZe}~ ϟ2Omjm̟+2y|l~Ѻubm'}YzlĈ;vJ*%P^%Y;e[v}e2 Y,Z}֗W5 $'n~ݍksmlǾC)sۛR23Up뭷bذahѢElnqv޼yꫯ裏kC=dDۮ]0r|W̔~.-νޚ" " "z&6\ ~K׃ OA`B\r @ku`'0g66Y}T?|0 :xҺ[/" "s8oZ]ZC&u0G[#QK1s%m9pu.ڸ,݈VbצgY%g4m6EjQ^kn+ot|\\s'ѕ`,^/?TkOqvɒ%xc4oo4i?&LYgYf^zЪUb.|o΍v5&ғN:,)x}5/0~b K[oݺ.EӧqQСCMy\7k̈q' $%%*|1ѕf_hcn݌K;DG.x5~J7GDW%Y?e," " D eFE 8T: t%2މhbsVSO~6wo~Xy%v=IݰaYS2?+)g:xҺ[/" "k8Ky 0;qYLw,V^C%9Nz`Ɲ8۳y޺C~wxl^CNkjQ=%żZEtmia0b.0f+޽{q 7Qz9r8pW_}xZ: |dM7݄7|xR4iF'x˗/w{blDxqCoY wu s9vx>M ̹ ',ڸ gv K7aCޘ" " ".iiGlЃWǬѮ8;p~\e]5 x675!Y_fޢ~#oדbrwK/>|ɓRպʯCIX/Iw낾p|l .1! u%![w ,&L EgEsg :mJ)1*~t3Y 5Ήi@GFɝk c1lLv1pgqa(xCJ_=ys֓O>iHDq2[T8KU4(B{5lQQz-QQQ,zl]!ΖV6m-x/}i'7xO|&O-]w O 6hP*.ﱥ@،u5DD@D@J#c9gSux1fM{ma>s+-\Bޮ'=yrwEq= s8uUE +" "PkT&q[m?K2*a[m~r[~}{J k MUTAJ׫s3OPeX={v=KO43vq ?G -(88bV@kW۲!.?sHGcŭMH>x$~fC0eeeX@* !"" "s8{fbRcl3o}"v%ζ_ 䍇'qdZg,Zw7v8ː c9DV!N}c1x +]L;7YehTsh։'3f`3f#,evjb.X6*Ν;c[h>F1F ưezқ{<6m?h# gq֓=ܹ)~3m 1M8[R%eԄZx0/Wl|Tv`'0d ;1ӊ1s cgT79;w%r̿W2W-В5&A*r]H\GrMGQk,?4Ȅ] e7kmu]'" "s8˰/vk>-[~E>&M"Za-2,eח VԆ %β#qJᒇQmذgBW?ԪUYc`y1LcwqFLNNvذ5j0 y+Ǔ8ߖ^Vy,fg@0l||9jժ^@XqKۦ]Odë+6zmnP&#h >X1kzmJ:fgi} h[lۃa Vc]fGnpn:O zHޮ'ݭh w+]uUxw@ZxH+R'N,yh??#fi7smu]'" "sdKmWi₍a N܊rFܻp|*β}h;㜜"sb-dɉ\|k޲ }{$;c.B^By^D@D@D H UD@D@D@@'q633}nfԪUaig̘ugϞ;n7EZUQEط{+Rz͒Pǽl;9$ڡyMƸIK_T#"kӘ|Ph%u8' q6;P拀;ٛo 7t3:vx&O~ =gaÚmn c8:T6np  rrwcè\-5Dmbl+@!JZHhqU+{`mAԬEup\:@م}*!F=4lT1=Eعs/VډMX+ʳ(>=i rhN 4rf- LoPtiZ8(#D@D@D@”0X5KD@D@Do|g/2o~!yyy9r$ƏoCػu6,DtU jŠFр㯿P5)T¾t.O^M !!BezfBt$4SYNnju"ȯjuhFd嬨f꣪ %8hl 2CY!" " "$ΆgU" " " #8ۿ?}СCc,Yn&N'xҶ {ݳrhJ;vWm$'Ձ5n6omM=6ϼh~\]DQP&XN,⎔c% '7B-t * y^ƸKq_j>#J7/q_7aî}]w?.8 gd@PI3g(tMZCᣏ>BQQj~h/߈樿_jH8ECޖ-ض-q頯[GjK)o}Vw9ŘuֽmN׈7y3bwA,wۼ? sV`:&Oi*ZeAaR2Km/lo)j5#gao9rqkm~E xmFY ^zmF-G#AD@D@D@* E@D@D@B@lyAA^y|bL>#$`#Hqvϭ w?>< [LzӖMbҮE^" " " D@l(l&VDcTxKqdCs\s5: cTx0ZM\w&>s ߎ{5f0+6m{_D@D@D@I@l i.P$ q6{M6@Y 6t4p_оA,n\=fٽ&8sn r qH" q6S@YƩzZ:A1gيW}:o7sz3d,[odv6+@V=" " " J@l =_%vaLU:lإBD@D@D@D H ^TD@D@D@ʓ򤫲?٠o  "PQԩSSNcZ?d{gQAD£ZgY뫽M,+T@$jD4j@9U4hvֺmbԨQng)R8p zyLYiiiX~}.SFy&СCqgU.M|DZl2y CTXXo՞P}$(" !K@lv 2D@D@D@D5`gKZG7ߔ8-Mhij>U^Cj5,]O<+F>^*zيo."  q6UG8]#D@D@D@€@YY;ޢFBtt4;l}To,Mhw7 =܃;:z`{뮻%*~馛 lj'"!!lj_m8d_(J{1e˟2e RRRp}?wy'~g|w1;~m7yJ5AD@BِB5,$Ζ B?~ǜIvbSoBߏO?\[}vԯ_[n-l^\´+RDO)kA>}59O|gG}_~C=EEEF:ey'4B;oL.(_4"'q8W3 ]n[lРlɈ1y"s0`.R69$" "$Άv28[F]D@D@D@J!PVq]?0Zn|r-8x w믿֭ã>z ѣuw(߿?tb<`Y/6WZf͚!==Fq޳j24j]%;,9Pd<)^21|)[[bbbꫯoWO0$'qԥ'2=Cx\S0<:=g_7^{)+vƍcڲ_9<.BxV;v'ioذ!n<9NVX)ҋqs3y " "T$UwȘ@8hOD@D@D 8믿:3HJJr\=^=a"K;KoΝ;-Æ 31KtԩSת;q⩷С1d3޺%وyl" H@lv " " " "P~[uxt/YgG&g`:{r=ÖK&;UC[.=pYΝ;6|`YFv˱#6ӛB07oj+YO`xg\Ywqh̐ @=p_=g)&yX(*Op~%zE]% q6tNY?@T" " " "@yαV)x]wu&*c2^NN VԒ)-,Ej8H!sq'[,211cQH._YEѕW_mBPu}bkRA]Lv˱#β<ƼeLU :ղeK[W4ELj)c2SO=#OzIȃ׮]kBS6sP z;ծ#P;} vo#" "P$V|Ȃ $ qj'PVq4@oCZdIoߎ;: 222xb}p*g P>ƏeSN9\\Uݖ;tNI&FdZa^+16+Ⲓr슃 , /``J]z:e٩1 '`ʔ)weG* \Ƥu(~w.Qi"1) 2ʖ! fbLcznw" q6CWu" " " E ޽{8ù>]QgeJJ9Xpݲe K/OW1_yoi,S㏱aR}A-mPܒW^+܎ ,>/ĶmیgifEggx]JoL+)Ǯ8J+vǴdYv7LlY7ا,xg̓dwr>R=?C.c~@jЭ[7GV{vfj W;.zب" "$Άp8[v*AD@D@D@U GBWC_PTW q<̐! q6dJ tgu뇍7oj^ u" " !K@lv 2D@D@D@D5gCen1c12s=Pi^godYH dU!" " "$J Xf_|["..Z_PiAgCd8CX$"PXIχ򤫲E| |lg[g؏!ΏD @( D¥jD hzg" " " G@lZD@⬆+_QzWD4wc8{D@D@D@D T x5(ażXS -Bm0w6-uwJƬ+QۡW6 U;l x;a8o)@@4e]qֻ[D@D@D@B2L:ˋ4y| > @lcf=CT; 0K*BF$>W, (ئrF6B| Da!.νm$zKE@D@D@"s8D}O?7|@ll,7onݺC*Rz,6effbƍ(,,D:uжm[\~hҤIPO !RGZZ֯__\p8vчe 8={tYA{nq~5+#秝~;p ܍d|g#+֭Czz:^xRd!WqDT@08̽#ʝ@ݺu˵__{7l>7})|ϕQ*((?k׺lStt4 %%\D];e[y|#G}7|3(YoX[^;nm2w@"qwSOS+W6:,~^QܴiVZ;/vSJ}i*9gCd? 83`ɒ%B߾}ѱcGc۶m?>,X6m`^KqvѢE㏍|rr2zN;́TN̵?7pe;߰gc \y啎8QV-x׌wpjՌ_DV^mi-vL0_~ơC@b…ؼy3j׮]⪫ru7b׮]sm`[6mjm*J*ᦛn2uM8 Ϭꫯ6}s믿]w݅s=ןCZe@ ėO?a̘1P,sN3'~GCzZǚ5k-Y/ZC5υҒ5ǎ >L^xt5_ucXG5;܌3tIxrJLMMʼn'hl'vl/~ *H*q8u8ga;|_{R`0k,ԨQ\sw밒)o68 [o5;|s>׸f7o{=qkiׯo[K#U@8]F Y z>lĊ+c'H}7"_O?tsͺAزeKg{ꅢ"Ӏp饗+U[\M%J-\2u]gD)SO?mhHwe.K&.)3q}vlxlmS~I{'?7&srr/G)B|)k*?fNLG"75[nmLdӾOWs}Ўm)Vj֬O>[ IDATY?~<'vl/7Ǣ!a%gqr4qe=g^\3r)KܽJP/QFfMtA̘1f5 w.?a?7Slۇ~hG`}-D{)\C%EՌ @AYe'?͜98%C!1¬{a>Q6;/>$nM?:Pe8H`h(ҋYLv;g_oХKfWzkRi֬dװaC)X,)*LkE6.Xr%:HWir{1,_Ǵ"K/zꙗ.(~W0 k z>#Vh#=YG!mOř+EO3zܥW! C`]^c,a"zs!w,{×jnw=3 A|u|^y<,ͶM!Efk. ^h_~efOWl/֠E@D@ Hxh(rhyrkm6x 7.b""_)t21\&K#E."7/AD\Z}Y8*BPX3rHF U@VmA!]z'(juכVT~6<{Ѿ}{#?/ZlՎA@/eÝ8kwnpnÈ3/+h3܈숀s%: nѢtg:?x@ @mvBI-^U" "$FfG 8K/5k%&,S.Le"{1@ACcLL&M21f ː%]qe-\LL͙37B[7[.Y624C|sxT~aH\ŦshذaC14'ug {3AzFqЛ֜|V\&zYجbtg:}zj||b(K/6~&zßcA.;v uڭ'\I'gf"w,=?|m\#6Wa+g(fw(ON;ow{qĵ2Jl3q g3Px H/Zt:ɓͺw5:`f)Q+" K@lZxY|y Zp>DNzr+Y.-WnKA5Lt\rAm ۽{bPnQL;S,\[91x݊cC#b=5A(pl=zJf{(0VZ)-د~C /}'sXe tR~Ď8ĕ8tgv `y6WO,'vNx;>]5GN7,PHrW?J+JY~*wܹsѭ[78p.@w2ط98%Y  F/[~QNg.2uN J_qQgGn墔x.Bnia &_7vMJϼ<Ŝe^񆏝~ ƗuynY#UG 0ש\WV[C/`ZRP" q6zK@l(Oz _mjuhy ?6$)XO>+q=`f.nsx[p˸^L2z+ԓ8:B v0SV`||lp,zevT~{gf`2aD9V~#u&~5 Gk8G1Sy溝ayvĮ |xMt HC*q6z88Rn# q6\-81 " qVc@DGg'q;^},oVXD@BVL@gFs6;WM2:ʀ@!А8/<g#σŕ@>Aըm϶-8\r$X7@X:º8 ށ8/<g#σUڈZ/ʹf㡄z}K?<2% "%uU1"$4wRn# q6ǎJG-~`F0Uɪ@__QGZ&G@s;g" " " G@lyжEE~pa!ww]*'J}~4(L K 갃_-bjyzFI XMs+<  " " "$yEyuo~.-?2 @d0|JٕݝP?лqgm &46TJ_QƸq0b;UTn/  .qЫb!q6o̚䠠0qhץwIF\i : +Zj']) @̞Q"}]-Wq@ 0H!puHx!@`6OjŋU_|{%E+Wbصk5j. |m۶7|Zjk͛77{,X{AƍqUWN:ǔ_E B|>}j _5իk~!6mڄۣgϞsc 6EK/AhѢ?x̜9wu)oÆ 3|UVk|ְ_|7o6b֭ϰsNwq֘ؽS`# 6D@D@D@B@Bb/41Yj胴nHrqvZn WU0irLǨ 8㯘xF(TǁOu5g>r߀GLw.F?L,-[zoF#M(gq6//?=lWm1k&vz,.DB@ qX0i2f)1xP'4 P Gu+G^ ./7[^v$r1/sOMD+8݈L+Vyg#p6ߏ<{W̟+WB<裸ךs駟l2 0@lND!RTm gݻqWzB19x饗<2g}6~LΞ,f̘anO8DG KgA*zF=ލ7z?Lb|Pl$." " "`@#"ꌵVLxt>W`rx,{N#]x歚 VQQ4f"p Ms0z\Z-c=/Y-67(ΎB|% &`Ddgy;f!߅-ff&tN8(dfv=?:!ntZ;#nhTs&LBNޫ@ v'#v>Ș/C)U8}xl3@`x~$vgKz.Zlݻcƌߎ`ڴiƃJg um})p{qrrوmj'_|*e_~&?W_}5so --Cq/ٖ-[0'LΏCq)EEEqY>cP6 G.E[QCgd@0(8 /x8,Z{aϳJcbQ͑k wjh# #wBzj' intɟQy~ ژ-N!6>3iYed"}D"%g&FeAhciG!#a7#k& qd2Ƌn>%> (ǁOoH-җ:~ %q[׮]k2&lIqޮv 7|%=g_}U9K:sv?W_րeg2UHKvm۶)S7?0-[}]aߌkŠyE{I',+Jv_nQ"_Y^~ckNnfcg\`B0񷧞z \r d%kcm3 C%~%~*>>]Ю]; w\o$" " " ή˩E t+„IX$ږ.:ǜ- +MsFc\vodB6DQ]tD8kf nh55g4zCm/+GȞ9 cl_75 Gor!6e¬yYX]vPusUq@jґPyN4 \L[ Hm<pʝ@j`|*=go$R<7tjԨ6,K |Ɯ]vvϊ9{O7m˗/waL[Y_>Da&77{E B|,^szb2\:xSLk"{)+ L pFk׮ ~tf0B{@g|M!v0:qD#; o]<\UKӀ6>^2޺UzrGiΝLJ" " " G ,P@maЉYs,6qHY0aE; ƜMjbIHlɘGj̩CS 8iXL鎡}#!:YƜ$Ζq<eZ8܂GP:J" !%uj"]*β?6m2+EZ֭[gFr syfqy! !VZefك_Y4\sˆG}dA\ Fq G[ћʟ|Ij9b~\gq'YƖr@(8 26m|Yc^ŕHK~1ZRE!6eNŔYX6OAѩQ4f:FM-D9`5 bTspYYS1if&nmн@tKf>+0s[Xf[v="|' q;n5glT8pebXz8O^&0nl)ZE IDAT ?Bh? 5fw3^r]vКIq@ _QGXt!AF@s׻8evY(-a~ W_}C_|abވ,sԩg[n5qo*8ė6mRRRLX,l)Ͱݺu8Rngæ+à!EE}YTz =@T$#%u_ϨE"P4w/?|ha<3ׯM9˰P&.-z,=oG1sg.ڮXbLahӦ .s]q ض܆-ZPQ@l(@]xaw05/4D3rP#|Qg3(@|v1Uų)@ P(| 05T)@@E>LRZ i gyl P _lG`@ g h9U (P#|QS|vb8 gS(3 guf)8C`8k9R@}(9r೛PϹsVϦ(@ Pp$pրS55P0eJ h)gWKW1Uų)@ P(| K'evk—(P,"`jL*(@ @pVS0U@p׏#@:~ APU)|vYe^<(@  8 %jTEcg0>2/M P@ 0-5(ool чh"gWBr8+^v u +0Ϧ(@ P@rx-/p(jǦ-RI)ZaI$&W]GaU>hspx96Dbok7MT9.VގqpWnʼx6(@ P/l2տOc<Jfgchtth̊\P/bc}X hԵm Ƹ>FM~م2 fݛcz8u<fx~:}#GU s ƎwzV,w |W5O >ث*ȠU8jܞXf7-#{N`UMxKĦ-pś,Qw/GI_xSP@?xvC?9j ]epVϦ(@ P(}b"*|<QuKO|To;g_}H9po亵b>㭭>%df>95ҴA?0o#aH4dAW&FSdgWBH)V;sXP/epr8[71ه[ثfD#%pxpZa+$ӫaAQ G5]5q<P,gWYe^<(@Уp6Ail̿s |rla=Z;p񾌆a<֮ѫo,tqU6ؽj{1[70{-> j =n߫dw3,q10vh~W"fMsBv l}K|qV1C륩i[71GZ_x7P@?xvC?9j ]epVϦ(@ P$}eǂ@ic o%1$5npsρUja{_5 ^);gG`T\8#1u]ӴK}kjv:g/cFŖѢ,Rvj&˲9w$\`/qW;ӄ);g5}ܬ8#PBx)¿9 [)ƳFQS@*[ʼx6(@ P/lmZq_yu.?(] {-oWS+-TG暳}|Ѧos|U8tWaz5gvlˤ֜=u'r9q5< .MfYԘaD+kfqMloCTG":JrL5gSrx߄߷Q1W% 4 o 觀Ϯ}>GM೫l}*(@ cd`SY%*c,^ E|q.U`Cc XAx xetyүgW\_İ>op5\D+VWcT6a)|WξW_59x5 :K g²Ӄ xLa+bY!֌lެ7[On#8] >Lu5MJJ™3g%JUVhРAEEE~&̳)@ P{g8@)4nO9@qT^ Ē@rK(^P- -@ G"q ]e q54j ؞={C gCBBЬYԅ~)ʔ)ۣcǎpww'\uZ޽n޼5j%(@ d%'l!. BgJNϧnчnhr(Z|vig l޼ BS?*___ƢiӦ/2N-gS ?{ _~%~o"1%9`nYWa9/Q Dsiw,>7?u=Ѻm ?*_Xܰm6pp$$$m۶r. 7OժUj*|ᇲ?Waڴi077q*W:W3vǎ?L"]Q+W<_{?'''߿_<44T9uV 0 e C2dƍnP\9={6u<2 0]A"$-&Xү%=4>{M>_&ʲ޿23MٻxgaPS?X1чEPITցnt5 >uRTV;p|; l5!X<''/Dٲ%1m![nI'MǞ8\vcwdplKJy1i~\:ۣfrXօb_#ʔ-:܄bʒYF/S=͛#<<իW 7mڄ]"amZ0zh\rE}%7xCi܄Gnϟ?/rtIk׮-|cqm߾o6F!/'OOO,[ ([,!vzNZEollbŊ~ʘD+lv?Ng%ֳsx| Pțټj ZFeVO49</BYk]b<-% Cn҆ibaD~GɡƳFJs)?]}j8{-G~Yvlz1sn'y8tj~²a(>;e\\ Mʳv`/ g`a`5p7#Hh8TC gk[rlϾ8{&^OB]83vgghYڠF-93w@T\&uErSsV\;f8p-ŋ=̫ڣgbU=]9% ò/8}!߀VhSWU')? ^1-D|vM P@抍Q@7pTI@gW>r'? UfpVϦ(@ Pp7~7J6DUxvCU4vF೫l*(@ _&/pFɆ(Ϯ}(` |v-4Ye^<(@`8[kP .(TPUU DϮf8̋gS(P)lnFrkNѥYD IDAT*,/^uL h8O5]5O}-gW0Uų)@ P(|M_ Q@U5]5PQ@*[hʼx6(@ P/p׀#@ \Q! *ƳF3 ]e pVϦ(@ Pp7~7J6DUxvCU4vF೫lu9=Sn U>AٳCAmʑU8;rش1(٪>wЩ :~>u5ut{s/(@jM)kR@Ϯ}pu)@೫TWٴ>ۇAL8t&6>Elv8!w0p65Yr #|(@  gy[P \ZLNŠxvàJ|vAr83Xbر#,--M.mެ /ma(8Gs8}&Yf)p'٪N!5x (` g c9K8YhN G[N: gW"r82LuppI gO$ʛSڡ{ 嵏c@٣j\ _ i"q;{4O%|5Z!?t.w5t!VV#lC7z8rwG¤\)lA4׋>: >u936(6᳽8<ʤ{u73A??ȸxkaJi~'p|DbK4kU s:ܲZN많?orղp 'J-k2ŵڶ|rXt،h!ȟ]95~䋟v߀+_팊':&ϱ^m!Ѵ*?Ĺ-wjAAu*Js)@ ᅳO[q'0jo;i5*u_ MpjWJi(3.gV? ߺu 0eChgRyK(Am;)*jn&Ze?ε^?%L}[ze$iS뚾YI99O|Lp7?¼Hz~)Sc?G8,^bŋaW6s1i?b<иs6%lm-4AVrJx9?;mspu༓8/% I(MNpuUE &"zDp6 [&Ns'H@ #9d'cbP,/pxtB@gW>t@೫lAu5MLLĩS%KQFh޼ye֩W3vYߡh`Vn7L˗IhdfAe, ;͎fTՔ5j|uæjx.Ɨ5[;V.>]Ŗ_y\qB4m-w*= geCSfylXu?xbđ6Wca={&C{m*O=?pVU1#O{dsj<|/ Jީ-oaҞh:Q^k)@ &`XlJ4¸E#aqҖ[q'涃Хpj^&AR1n#qkx@0q|WTӴSUS9"8._i)r1>b|'JP9.3afK 2.&C2Ԏ'}*>Qg4mQ*S02 z@O;|+4OL .AqA0rSqB*ЊjE?~+rK Ϯ}rqPUϮ2nC gEx'j \,V,>_6&K/OE2%ph8 ގ=>@MpvӲ8E(z#Y$*#r9>QڠF-&`ߝSK,}# )S~3[mK8/҅{X^L¼oO`/a _[jb(I5@'^&^6=^$&۩G՜ORsvG5 &k^} ^*퓝yY%vN !کx}_)K{.o~9!Lts P:!`P,ea\uڌ1l-Ɗ`3pVB#c8$`:կhb\p5kiu'۞hԤre rxA>t\k|4h;^xgF0uVn㿣`Q|ith^:z"/y g67FR%Py5:ٻ1m_ǀz`M_ 'NB\v}\Bܽڸ2vuZݿ<.V8hO&CՌ$*GïOc$;-k 8Dp9Qu,k}zc k'<"ӵ%bJo8yaW5^u-S@UG9B^c'Oo|fLf7q)<ƟY Wx8$ K.C8pVmԎl8FUEoEp] x gtyP(@ P@b8(@ P'``ᬨOuz47f!v0hyw ^xK~n8 X4썉a$sܽkoVx$`h3l= g8n#q'0epl[M\ǓpYijڊR qv0˴s6Sl5Vgy YYe(@ PI,ϟ@KU6?;YOU}.rL(P0#[(@ P Yl!/(@ P@Yd(@ PE*(@ P 0A P(@  Eb9 PA 05d)@ P(Ptݵ(@ PEUlQ]Y΋(@ P&pӥ(@ E`9 P(@ P`8˻(@}`8o+R(@ PƠ(@ P@ۊq(@ PY(@  Eb9 P(@ P@w&$$5kDv-XTTׯE(@ P؂s(@ P(xHLL̷pviWc&vYᅥю;qZ8ѯ믩1J)e[wЩ :yQT`85;(@ P R@H$%%!>>9w6lNR( gדQ(@ P$'O"K.{8͚p&O gNj)@ P`8k:^H P(@ 蒀7Q5i?˪l\\"=[Al3X60ŧlB^+4o] QWaH7-/CGI'cY go|[\,ǴIR O66'ސM88D=x8 f_bcyU̜ U |] r0v-}8___]8 P@晐 P(@ P lZ;gE~)Kɰ3 &Ve8oX <tmظ&?x N(SdjW"g3՜)?oa*+^ 3:?wFģ]x[ze!7K,Ic{5k`.9b^ 8eӌ.) kw7;(@ $pV%hvC P(@ >Y h*kp35]ߝмU,Yv50fByNmѰq<Ϟ&jl8n\>YkX v]jcX4 |{{8}\ڌ`N P(<gϞ)@ P(@|(jeb,i'yjCp3e D8;gIԝOd gOk`=:um¦(@ P:%pV(@ Pr+PY0}! \/{Tn䋷|uew6t.<}+"1 N=9U8;(mPs *U.Ys6O(@]`8+Q(@ PZ pV?+7#I,qSwfs֢)h׭9y!V+_}Zժc=}}Գ .فؘr._ؠ{Osy;j$ PCzh2(@ P(Y(\g P٢(@ P F,5'J P(2hxϼvsY5SF{#ca U{#m]8.~|8ވp'/);b.jn;.H\ O?yqp ׅIU[vY_c8?%G(@ PuB(@ P?ւް2K=oO(I9ހ#,ۅ8O ;g350Md.s"a7i"7 XwxD;aH+ ӧcBWX*k?D;Xcu]8OuFK(͙`;0۪0 L&1q+J qoDq0Us~(@ P(p5(@ P`8 g,ɭ.SxxlE|C[mkVXJ\M8UYЕp1Ǭި t ~1 Lw㢑?X$ѦԜ>fpX'bN }?B!Hs"`3PaXgw5 bXxW XEqE(@ P)p u6(@ P!p65tN޽x3<'ĜvfΦ@Jp(ǩ0@"a g\1I)ᬦE8!<°vg"3ަ"Ĝx 6ij6)@ P(p6(@ξ*k'wWؙD7"{`w3v¤V09Sa1q[0qN,=GJM99EP1uƑeD{Y7.D]@ e8^Whh:4o_vH P(@4w<&+S8y$ZhtfTTׯ_@Y PtU\'q'vNj4/31n5LCruTѰNf99 Ըs"(<\"'<%E8+^&_y܁뫗eUzhVmvyzs\(@ P!̜$(@ PH f8[(@ P.?#Bծ]ݻwOh9{(` g s9k P(@ 9]gW <8KsEv4 ۣcǎpwwYfc{)ʔ)c(@`8kkϙS(@ PH r8qF+V e˖E6mPnt g5ߊϟ?DŽ m6 ,T'844[/Up}?_|!w7q!,^[~5j;z8u)ڂᬪ;`8%O(@ Pt[@Y!KܼyƠA`dd pV5i$رCjՂ~'?rX۷ ϟ($]|9f̘!᮷7͛Xh\s} gs[oӧUph0( gMP(@ P/]i IDATlşWXC=#aRNŠ˾o|ɇWM$&DV>-+ 6:%ܙhx.EGX'Z'`IE 6W̹Ѱ빉~D'v`Jʕ+cŊxe/^@jհf^:zٳgyrhK\?e[6!C0tPd*vu;w6m8=c?>ds}=>#[NH|!wss;}ZʕmbѦ ,p/!vފݵbGC[KKK[Wnݒ! иq촇 ,&!|>ׯE?Yf\ P`85^C P(@ 蜀@eΚ5 wj3smڴ1>Gk-`06c7)_/K$&y u}κO>$wn񽄟ןX}:umi:&'͵b}.]!m!JBVi;g_:uzMMGNCŮQcVmԨ!rd޻wOw~ ?S VA'd(-S,mioǏ/$vȊݽ#?|8 w҆ 0eőovE?Yڬ"4L P  gsK(@ P(@(l^ gGup>k ~U8t]4X+ѩ{ݼ 3k%K∏;JEUQK54}E-ִ%D(>;bEQU;>E=הi,o j^|YLGv;g׵kf9+xSSl٭[b([!Yf@gu6>مr'1cAJ ^&1G8+Blm/ Z((@4 gy;P(@ PEBle.il=Zhx? !wq:~3۝"v炣eiLp88ߝQr欸믿͛ˋT6oddpV\,j" h,C!¿?Xt?/Ț| hE)v b'(; ^v%#G@؅+^rsDQTRhѢ<_O'Mšu^.NᬸF'|*y gE͙3.k׮]e-ڜ]5ŜfQB9"z8{ R@s)@ P0Օ8(@ PVᬶR< p6(@ PB,o PMᬾǫ gz8x Pt\ᬎ/G P@&)(Y(@ P'p(@ Y_BN@jq(@ Y}[1(@(Y(@ P'p(@ Y_BN@jq(@ Y}[1(@(Y(@ P'p(@ Y_BN@jq(@ Y}[1(@(Y(@ P'p(@ Y_BN@jq(@ 蛀.8y$˕+㍊B(@ P  g)D-K P j8 l޼-Z@ PxL+pviWc&kՌS xtYu':Zla0SNl P@`8[S]6(@ P/5޽{glNwGH ~g3$)@ P.}pp6&D˹#v<X8z­s1tV. F P@pʕ+|2?~G^zС+^l7kK< gNj)@ P.; }א`C]QװqFC[bP\([-;a@{Xt{3tW-TZcZaCe 'wpGo&w".IR;>hv[|9[з!ۧ(@ (Ыp6ZD1Eh8xaIX YqxYaS_ܽ\FFx2 0Uœ)@ P"] g?T-gx.&+~g[Ua1Xkby '/8LْW"g3՜)?oa*+^ 3:?wFģ]x[ze$wɒ1i~\:ۣfrXօb_a?.s]lqݽ=Z~= L|f~a{l z΅K6JWnXK.?*Xbp/Ca8xMt~Dijc=,Ns.cFT$ĿM՘^n֩W3vPX64M$MX=ZʶΞ^[ҽIdlk5푐6 VsIwxu}R`l=ܿ$wj;~>/(@]Пp6!+',Ʃ(gQ >;M5MZw.psL|,vaѵ=)nnZc7Ps md˛=f 6cc1+8wfb6,.k bJ7k5&t6FZ7xLlc!l~qi`8;(@ .9ͺ j޿ vMw4oU-p֦] F~u[`4l\)O쳧hek+Opl%V]Ƙ2MN46ɟS K@K1a!0ͼJYؾ9qO`k6 LѬƥMk+^ׯ>djՍ1qZ{w>>YTfΊ`w@]Fls9~/lнV۝ g )@ g )ʢ0E YO!-Jg^.hiMpx@`Y{AVKu˔'^lS5b B#gmd6;\vF ,m4ln׺+(FX["7ld[2oügz gz8x Pt\ᬎ/G P@& g^_lke+òew j:;u L7{ޛ!PvS{qpV6FpVY .h&xa,7ӷW\زެ> gv8p P@,H P@: gyP={(@ P 0-kR!X9v1N-(N_FFLwSVl|h4Ev05 (@ P]6(@ P$Qh0-YP( gus]8* P`8˻* 0U]Q(`p g n9a P 0%I>J P 0շx)@ P`8{* 0U]Q(`p g n9a P 0%I>J P 0շx)@ P`8{* 0U]Q(`p g n9a P 0%I>J P j8ӧ*W,rWL A RGA "ۤ6b&nxOX;*gtl,1/ 5P&XT4@A?k)enkfysykvy <9_ P(p|`8-(@ Pj8[wW^Ş={O[5[SLEᬩ$a gb8I PTٜt?Nx°aÆF{}?ė_~3PL E PqF+ph(@ P W_}wqN|j5֮]'OzX߿_jp>@ PΚنs]+pk9:(@ P- p̙3jYb8S;Ow) K̟.B:}1Pngcޣe]? 'b_d|*܆J퇡w3Zz5222lKT8燉'"++ `cc `̙8Bm۷gEbb~ o6oތ/ k֬x_ш%,~'x+<77DKK3Q@ 0Tnf g )@ PHv킇ΆO݆.ὥ{#Z:++ (İuT_FTװmUbB&?_Oc٧',"x)S特أ^VNiSBPGATA8BQ̘1? w}Xd VZ%˗!`„ x1yd'-,,-:}S@0mGBF(@ P )BH'¹.)lR8 @>'ex_gbN5?`7ӰzW,1x Y%+1>H.%} /=1Ƞ:9+r\<*\pttĉ'0l؍M:}ARRݜ arpp=zk Ø?MIcǎ]YSgM_l^}UpBvǎ7nmMp񝜜S-pV7m(@ HWt33A&\(@ P`8[\8{}6qK݁az'אXI|k#Y{FPW([%|6 gpXv)@ t'%po(@ P8o\8xvIOC-'rJM 9XY!UE bi=?=k߫vAYs* )))b*Ԋ={, "^VK8;;cΝIo۴%էo{(@`8ޢ0A P:Nl۶T ~e6}-3/2NIŵkŏ5W@g++"0voK@>y?p`ΆaÆ N mΜ9S!z#Fx7yfujM4v̶`( g[Q, P(% gR(mhOζV)@ P gbK P!pVYY3h.(@.`8%(@60m@k IDATζV)@ P gbK P!pVYY3h.(@.`8%(@60m@kζV)@ P gbK P!pVYY3h.(@.`8%(@60m@kζV)@ P gbK P!pVYY3h.(@.`8%(@60m@kζV)@ P gbK P!`Dl 2Lf";:Kp B͹괈J*@(oX'CDBd_EHSBOi#ga$ gd8M PR@ѣGq TWWLj#?6JwN(@(B\*;Ƞ+.F%,`#ު (l\!**ΖMcšh- gb[ g6P(@j8{l۶ O>;v`„ ;k15 ^e[Yw`ߺ'/bsvsW&B|G|ǽ}:eb(@N0p6 &GGc%*`iYMb6fwTh4'{rVWC9lAV-rwQ- 'OH L2KXDz]D8cr;i9L 0ZN Pi H5?@t v?;lٖ޼_1uB ζ$(`jF Amō-vۑ2TE O"E;Kg=ke8kCt )GZ\_˗B>/qO "5>?Ο {wxј];ڰA͍_Wa =jdi;3Yr[4uXvo/W6Tj? uKl7cV7sJwiQs1aիW###|(ицEjS ,&7mt(Ҧ"5]BdA sŭpV¢`f \9XyJW@WP{*B,d{@o=5q&\(@ P]* pV^{1sv bBc%,Y9V ;3vܗb)rߩKx#㈤9h:^VÙ2|q[ٖ٨v/p8t ypOu㓆]ƶgER,[G>XsG;]l#?KxoXC'aUg gWS0i# g+PVf c5S,nUIU  (}N5srVX1'g녳8,z#LT((lM 0A P:N@~8}'gb8:Ub%lRk>ص}_Cz ^W<]~ȺǷ |F'^^:ux Y%+1Cl|ӿοZL P.`dlPkm盅e+ ICґR΃*T.CZ  h"e( VhOE:bi BOC\ j6gQ5 RQli 9 05_A\-(@ P+ pV)K! H1=7zabx$֌:o٫Ug[&Bk+\?녳nGͱf.M|1{~3}m(@ PY8 eb\6NΐYP\xU4DE6lCV~̹,)_JXA [!])S $$hQP FpX(|-Y萳F(|s Y;Μ(@ 0m=Nz Z+4䍓 /}MCckO~wOpӔb? }mʲ7 P- gWg"%5(YF&_;+ ~/H`8k6[ͅR( gñ P؟Q(~x+yd s䩡 i²Opy^Ya٦YUqBi=/~ w}/ϚnG P!`ᬱn^^Kp @Dfu' 7Y$(@ PhIlKB/X0RS~DC+#kO6wrv;<c{K㾡OMsAL8w77bw[1]ةy!6 ؽ=/!?5//ֿ;|`8[Q]ζ #;(@ P 0A P 05|ZQo'O PJ|8= Pn`8˗(p9(@ Pf'p출 (@ YB.nq(@ Yc1Η(@|(Љ g;CQ(`v gn˹` P 05-I1J P 05|)@ P`8w(p9(@ Pf'p출 (@ YB.nq(@ Yc1Η(@|(Љ g;CQ(`v gn˹` P 05-I1J P 05|)@ P`8w(p9(@ Pf' p~- гgOxyyaРA %SSS_~&Θc yD\oLyf_`ptg_싁r[d>Cp,|o81#"ÕuXvo/W6Tj? uիV-_uV|׿B?=zÇqF?C=~ o6oތ/׬Y777q~~~;v,k.?>r/"8 _aB/ {9۷2 +W2<@ )@ P ! &p07>E Pz8{uOb0,v5֜ ?]{KG$8t2VVP*a^a> x)l'V'MݭĿR#OO,XgER,[G>XsG;,j};*9s&K.Ųe??4io.III w}666nj3?/OR/YVӧB)cǎ? 6W^ٳgf͚%5uTybX,\ӧOG~~>K\v ?]~3 W|~ŲOאuXb_Cl|1Azk,T%ԜN[ LPT+VX8*]n3!}w߉n>}oW0Yp{Ǹjӳu&=~c0nIy8~(@ (pE"6@ 0m?KD P H9mi.\P<[s޾%^e%OS1tX_'/% c`[xZ g'ݒ/6GXQ~w1}5v͝?ak5j%bLw|qlgǰi ُkz,$>֞ ͅYkBBm'gήp'h'L贅PuXvx_89+*裏0qDgϞ B}'jr 53!6mFk֔5hid_(иYD͡(@ P0;Y{Kx60H. nw8SoffO *e_KXA$F_^ UsVjz %bbbzkξKBiggg 'kUg)))9s栰z`gBz!,X@u{9X[[㩧?Ti&xB=ښpFqFLO)W$aN(@`8+-lAl8[,g0I9^xe$k׮kVVVaEaޞ˗|"_z ^uAkEEF)~kԨQbR8+ŋQUU%֭zGŏ 10\.'2nnn✛_zogD PΚޞrE`8+(@ P0zF\@!}1vB^L&k> (@ Ml4Z%pU\lL PZ%pU\llm gr‡ń‡„>p@mMZ# )@ Yb.PJ g (@ P&pvik8+7jnܸbZcb#F .(@ HDD60\%(@ P]#pk9*(@ P 05܎OR g[M(@ P gbC P$"pV"iYg(@`85(@3-JC̢-(}TݲQȭq2'6\K,B:2,x6;:L"T!pҹ goϹb P:OlYs$ PG hm 6u*qN灗ճ gᦊF++Bv 6#m6tšh--밉cA, P(q g;Ζ=S(1VdarTX޶iWJa9ED:d?~ ēٚEi*,*:СH- 'Fp[MB|e!,,$D'Z#R|$j~?@{!R ,Yw{BjIV7i_ʽ1-,n]\Y:', HS-A0hGBjΉsFHd8{՜mfMc^NS)*D PTJe'8 P0pVRRA]gUNĭʆsD$dD~zp%iP)OaBl^kD$]QX+`8C(Q/&~)2]@麧pVSp$B},]r hH t,爗)+*BH}pd(OE*e2V?v<4] (LU@Iz;,붫[֠67o`8(@ tَe(@ t%HQbS͢ M<5Έ wmE g+4P+4Q#[l| ˭"VhxClw랔ixr6 p*[6 pOHV GXTB[w\ Z]j5&CCXL(uC:m2mMf+of܎yMW&\ (@ P]( pv۶m(--&MTqihZϣF AI?B=M P@WW8+\MHYAA, <T8+-@:t#v WDac޻٤pV RC Yt euF0[1jB̚@x"&>g z4ׯ*;3;u#w(@0pV$%+mbw,v'l#"]mMiVuaXB$ VGcjkOFt" kr@  'Xlp*aL8몉EN{wG[贱Pdz'g w]Wp]9(@ P' p_~ѣG1n8q_5p=03mUS'lKRO PR0p6IWP@M%""o$hشa8[Q<&$[`_EY<2 r ?5q9.QQr@vRF@R h RD" ƽQ6%$k]'e7K2(ࢍlő mIvnڄ2o cv>P& Xsmn\F2FQ&(@ PF) p̙388_Xٹ^is>9;AG4ǫM6a PB gU@v[KX`D0D6N*ȭ)Yka{C'9jC& )Z6 GaS8Wn {@ELub9  'i<9+T9( }kPP 8#04 ¼ I^|k09K8C\gɐY7~}3Fp5ζ;);(@ PR glEEV`W?򥫐 xa7j e g]acw^{c4&mx?=41sW7,kPsp+xobBlOڲY_|> 2ܖ9M,{pw/< pU C]͘c yD\oLyfXիW.K P'`D,PM(FK"XIn<$ pV)P(`R gkj>cݻl5gǼKXr` IDATvf>/]S0.1SG=Isђ#8t" ,j3e⶚-Qƅ_*qֽTlyٟ=,' cBuu8Ew>{/b8:l|=ba?]{KoZ::g8kÅQhQm^-;@ 0 (@ Ytٳgk}}}8rs///~k/S,k:Ub%lRk>ص}_Cj14xA7ȺǷ |F'^^:ux Y%+1Cl|ӿߤ8 Ph6a Nlؚ(@ F@ lk[)K! H1=7zabx$֌:o٫Ug[&Bk+\?녳nGͱf.M|1{~3C >G P/p+Y mB P 0֖ L=K{IᚙnzrVg[{rC}?LCֆאXI|kS,l(@ P@J g 05-)@ PB]se_:.B['c'O g_MCee}kUxj N6ΪJ-#}{=֜޻QYa gbH PHl73PZ`HMWtË=IACs|?-F?51߈fm*3wai d+>\8++bc|\8׼8P|Vߓ gnrF"pV*;yYf.(@.`8E(@L)z7(@ P@_J(@ PR`8+A P`8Q( R ,Κ6s(@ tm۶vvv4iRDS?ipy <8,(@ P]%p9Y 05m)@ P$)Rdedd gpl'$( 1NǴΚru(@ tٮ 899{+>>={Ɖ'н{wk"00PgyKKK{x'1|ۋm]J 6nnnxPWG=(@ 0m!{ gbC P(j&, o^xFG_|֭CHHH3bٌ#G ˗/NJ+ \X,\۷v)@ Yf.R* g(@ P(pvu;n`ݧ'zc3RtPpBV[ gk]t ̙3'x+WpwB`̘1zmUlL P 0AN`8ۉ(@`8kz[>u>1HZkqd8,T֥P}Q_ú%V}{ RNN [7>GpgXދX:N}>.'bv:zYYԂvd8+0׏?X Z5hxU(m  /\RO?$K'nM (@ tَ7`8˗(@ tYtٳgkA.yMC~Bg@z#>}!! "2] rI|lfV?e<!d?ž؀b6VsG'&&ɓp;t:כߗ_~Yf᫯߰lGf,v@ PLΚsٷ'6oe)t/dussA'P}G&`8k/(@ Pz H!k42pVzU~Ъ%/!-l(iyٟ=,[3b谾8-9O^KTU]H;ΟO<%9_l8,bbj; žZU!}1p@lBhh(5kxrGŰaðj*qj`ׯ͛1j +[D` PhV,_q<\K.u}t\Fc8.(@ 4*p^{ﳁ["tG| 6+8q2X%ΗTJug8Nk[b5`u^b>e?(@ P@OzB(@ P0p$ iٖĞ}Vvd9 ¼vX @ _ K1mY-(@ P@ 0mWNvF P@'e8[MBJ5|Bn 9Qk_J{J]1] ?gՈS iQ&/Ev|ʱ 9C~Z,RaoFP[E5tKP"Y2[yI\]>QB\2Y2B\-|`+j-#cM{ P@EZxC*+tثa35}*)@ P0\%(@ P$B\*dWVc^Fl= V*wbBz퍮,9yũSŰPO8eB ~Hx[#):9+N@tb:θBᬫF (n+4PGk᧎wq e0%b˦A-x BgF(p1(@ Pb](@V I8[MkQ,oԒ%AttN _-lu()Cmڂ)1j驃&Vl"eP&eEC6Z Bh+n4޹Qi L2Nqa qPĄB20?T(@ P@ 0P^vN P@I8+ir VNp֡@*+L6)?\R(n*J_j s/U@V ;~aa4GA+aHm>Ꝝ: ي5gv.[ gL?6;Ջ]w}(@ PQ|1(@ P06 g+rChs(l`Y\ K bO سvQbOFtl><kPsV!X(+P5 RQli 9 laZ  h"e( Vh.1pD%J4I׺"2 g%{b8k(@ P@ζR(% <e(EqKY#mmʀ=DG$*G$:(?K(OMiZ+Gld `Ϛq鐳F(| -AJFd既V",bEHW/EJ5*&!>ER!8vG`hB׻Aζl(@ PXn۶ äIDjdeeԩSѣ<==1dȐzϟ(@ P+mnI^AEdrB`V?,o.m;w_leT6J5z\(i9_r>Y֠](@ P' pV𗬌pŋ(,,xo׮]xaiy Y^5ZيQvo!fM߁}Gg_[EL|ߵf<;zh_/TwgH?wǰI) P@ gKm Jh6zk+j-yMGݰڱ]'\X\8>ζ+5;(@ P֝kא)S{2ζ{N:! g[} Pho g[@Ul]z9E "N(@ Pj48::bРApV}RgG=舗xͧζS@ζ@?= ZussA'P}G&Yx(@ PK@Pwozz6UX>_˗B>/qOpv87u6vw7Fcn?faYM]~þ"f{Ֆ5Cw`goibك+|!^˗mx?~zn;n`ݧ'zc3ꁬ^Z,Q05LM@ l"@ Pd ߏrQ?VBc%,Y9V ;3vܗb)rߩKx#㈤9h:^Vlg m5g[ gۍ TõЭ{7; j?1zX:O$~N¢;^yKlu`}\6>Ot0.ὥb- U3pb,p̈́ 0ߊ-)@ P@k Ϟ=[;u___XYY{M8uݐ:Ub%lRk>ص}_Cj14xA7B. ->v=׺Nw^CaJ|u50_oS05LM@ l"@ PdpvW$ gF0[1J_sukT ַM*x-źア^8v8zĩk燋>7s( }#ЄΚfr)(@ HN䶤MNz Z+4d 7 =9+W=ݡb>OS&!kkz,$)\n$(@I 0pr&pv(@ P@J g3wDz/@~w[cF1^/ > jz5gU 'g gU d݃H?kζ^(@ HQws2Y&\(@ P`8+Mh)-<ԔQqE;ړ͝487:⽥~q &Q;|lOc.<lg g`wEaޞ˗{l;XJh38`8k{R(u gΞ#S(`Y `8k(@ Pz 0Ջ(@ PY mb gMB PNlsd P `8kA g bC(@ P@/z1(@ P`8+TL_1WH P@ 0:{L Pa g sS0HAl|(@ %pV/&6(@ P@B g% 05= )@ P:]gϑ)@ P0Lan| 05Q(@F(@ HHᬄ6S1}\!(@ P]'p92(@ P 05̍OQ ! P(Y؈(@ 0fp*/p+(@ Pn۶ äIj1?t^^^4hP=c]Ǒ)@ P]AUᬹuF0[1c`(@6 0m# @kζFm)@ P@]ŋgL2lנ֝j!i1Įg{ Bps=<#G"99O=TϓR g hV P(٫WXnC.[Oͭj(tKsZ\k *p /蔄pDjj* Oζfsٖ@'0dA|(@ P@ H9Y0qлwZ ^qoػ4lkoĿ ?laoeX_yk WeeD7gpw\__{#"=gMi.}V^-\--ݿ >k׮e8ۚ `[ P p9(@ P/ pܹsbY#`ؽ{7Ǝ}2Bg%xqD|C/+ 78S<~w[#aQ$>~VXwŊ5>=mˏ_mн{7q=5{rٺ g;}c `8k<9k (@ PzH!NG={$/q)ƺO4Y6P}ŧPa bOZ,p,n~cOD!'`7}v/;D IDAT}}fO8kG)ۣGTUUu g >G Pcv/{@=|!(@ P@ H!5tu g[p!=Z@joou5c* |S𺻶 M4Ͻj`'-Gd  Q#k\ᡎgRs^ QR]Mᬹ8K P@g 0Lmpvk_x ^vrVx!װ35^ދqӝ}.p*`l6bl!@9,/C~z dL ӂS-o`"` 'Ň#BlEHSBd(щcͨ f\*(@ P.p%?`sa}Tñ p8;X)< s2a/;z_@T<{o/_()aeelٰ_N@ }8[ Pe!è pE3XVvBpX0]`YV<&lvF"r<$(66m;܉a/. kVςa=N`8I(@`8k[ gÒbOZ*+6p'ߡ.Ɵ^À6xN m"v#/fm}YEkʔ)/I+/ԙ---cΝ|a(@ P@F!M X7Z uȣUnHE$$hQP8y (<~BZeHME|¢Y;Y, nEi !1=e A Ƅ@DkDod(*!;Rx$8/oDۡ09WVsr֐4mK}5)05-(@ PY oF P@FΖ Mƍpaa@6 9.k [ C#)JjvFaz,bP(,1ZG OXhR9HPy^4(LFH"5>ވJ4 ci ᄯ 2 h! aPr:+۠koKG 0(YK P| (@ P06gKҡ"u_[As[y M,nhAY>PG<[E"1+OR]iYp*[t p&=ѹb>ᬺՑlJN(a- ?6c{g gg8S POgL P0w gKk4ʜFϹy(Y#!~7V g 6"J()0o8S"*ʸas'g-TXZ u~uAم()FLǒfYalb~g˞)@ PY(@ Q5썲p T :X.LmJD^Bh_ Xv*N&#:N js@fمz/ ih V8ʓ%H7Tᬡr|(@ ,pe#(@ P@ZFFBjuOZkquuE )HδEHt\KHyd@~jr<0O9 S}N:%!:"cDdԜ-IJwȌCJ *Blő mIvnڄ2o cj>1 ֩w[dZlΚnr-(@ HMv(@ P% g˲`ѦRȬ{No$PT ?= {rQXZ XC (VE& )Z6 !,ʐsuCp EQ5砳uAP3{p$mñʲ9l]0=D@=KLR[7~ Dq ]KK *pP9>G PZ`8۲[P( -# gKz[Jep@KlJ_+g9-ː員o̙Cve(@ P gP(`lF4DGBakE$#E{UVwƴPx:9v`8Π(@ `8ׁ(@c0pp9_ 4`8w(@ tَe(@ tَqehT,_ P(qRgmۆRaҤI}v8::b?8L P$Jr[8)S`8k;uQ( )𗬌YVޝ@tm!1F"DHAFJjV-W-U3bA'h4""J#"uϑ9$ΰyZߺ;[ .T(` hժMr(Q3ȧ|1 P(17n@ZZRRRCur]~ ux]Cm}Xh6oެ}q" Px%po(pV؜(@0p611ϟK\x(6}7_Lm…8x Y s` P 0B= 0#6(@ P5™3g2ԣnݺx7?cYݼ#oneܷOm\_ǔqf[Z#C=Y*9Ģ})z:?X>F-r .ڨ89+Bׯc۶m9s&  8qѣGWf͚ɓ'e㄄c޼yhٲ[n{gUViNL P`8;>IjM(@ PΦOj\vwӏ".6!/ {Ւ={YͶxw(.cn7U/c%0~~\yްZ+Uw?,Pp… XbZnŋS< ӧOW|ܹsezTXgFXX6mڄ2e`25n8lk^9D P@+Zqf Ll4(@ PMYq:֭W'5^6Y9b%XG.L?8B ي%64E՘UKt| 1vUfyCWuY''',]T_6&&...(Y$V^޽{_xc4h|_m۶]0ou(@#p8r h$pV#&D P%` lm +s)Ѷ:N! xyWû"mYLhWjl<=qG/_&'Lq9Ҋ ѣh֬z$@Ǐ_B'N݊>~0W a2>6ɖ%JlI **Lp ^4p Kʕ+]d y kJNN DOk׮zs:)(Yx# .p(@ $pFv?̍ĞtU܎K@uDz[E0۫c0zu0~S";N5(O my+OÆ CRdkѣh׮I mٲ@%d[g_xƋt/pVƜj|(@ PV#1 ۍK(Z0\l~o-͜z 4/*W-L5kppX~13O`kxO2ghשFu&$$[nœ'O!qr7o?ġC NΊuҤINՊ{Dڨ(+V 4(@0Տ3g`8(@ NlM}!.6 gتg=Vq/N^(@-pرci{JhڴRuR(@ 0U\ 8v0cڭ>SϖP0/Uo g \NO PI 05dslO1nJ3tU+<9vJ PuSQ(`v gͮ0(@ P@ g_Bn@I gT-(@ 0UZŸ^ PSQ(`v gͮ0(@ P@ g_Bn@I gT-(@ 0UZŸ^ PSQ(`v gͮ0(@ P@ g_Bn@I gT-(@ 0UZŸ^ PSQ(`v gͮ0(@ P@ g_Bn@I gT-(@ C8xX[[GMf_WZڵ5k*(@ P g )Ymx/(@ PNYb Mлw7pVZkzCٴFk#(Wzd.p(@] s8vZ*TVVVhܸ1Un }'pY׾ qZ@ :Tss@PP|}}_:9 (@ _l$`85(@ P s8+6 ܹs-YˬՍ"m9mn^x,K/6G\3O=BQoQ"<GuXzS|ꕭ`ͦmŭXU68sJ7^X^T'g7'(W9-ڦf gsXexn gͮ0(@ Pz`8GlL[8[SEܙXl[Eqm vzcPdQ|< Sw1wv*/FbOuVVEp;.36cY0\&(@(.}t&+9î3*MŃ} pϐQ+KZ_w"Lweg&0V$~]j=_8 sGţ'/D8gO3)}Y9w*:ɶ b)5=BĊPv~a9+(@ Pf"pL 6 g?쯎aߎHJJ;51'D䉿kO<2Qhab6 ,H8+Z^dyl{Ί{U>Yر#vܩ$o(@] (,}q^Niz!MrL^uè^^RU]%#aM'FK\O^%_e8z'g(@ P03fVpn(` g#dqp^kPc}i2]"ТB2‘0bƞ9<݃[ɻg_"wqlɢD mPG}'*öH"aG[+c=,S(GrjŕR(<ʫWL P0wTxyqqpENQ+rӂ#`8kE(@ P0Y&[Zn(` gMܘ1 05ƪpM(@ YS$A P0SkA PLVɖ(@ Y--7f g*\(@ P"pT*}PGԚ;5FP.(@`8k(@ P&+pdKˍYc D P05Jr(@`8k>N@K(@ Pd! E||<㣶{.?ҥKG5klm1 P`87z`8GlNE P C8+ϱe4h(\p05X P´7QV g(قi P(ɓ'ѵkp!z,S/^GӧO1vXlܸ hܸ1,X W\UVxwUhQTV Ǘ_~[n}APPԩSĤI_ɑbС_ ;v@Nԏר/ IDATQƍk?C:trÆ ϋM2%=V^7njOŏ?V^ | '\o"pV/̜/M(@ P0p͛v?~,.̴h Rc0{slRjժlo#O'OAŋQB^98q|}}1}tt ...իWaii)CY>\p6U6˔)Q8M4Aڵ1{l0`6mڄzK9s`ٲeM+ov͟?_!!!prr… 1c 6kΖ#S Y(@ P@w_8x t"E`޽hذ!TpVw9))_M<{o"3Ա-Ѥ\lؽ:>| 7w;iZ.O°h?Lco˟gcܨ836ꝌW3R'~zy 'gk:j>2DUPՔ5pѣG2XA{{{L:}Ye="uuu'gdFnݺD'g3Eț[?"p^fcnv}NLa#GмysF}0YӛY7wK P~5MIIѡC~ٳᬞ^K,mR!+ W .҅x }X 6ƾaiU>JASוx8}GM8p ~\-[WUG,=gE{?}[Tq(75ks} g>VZ… Sz/^^^%3@Ϟ=|rS"8;aȖ-[˗:'sӏ/ټֿtľ}d8*~ׯ_?Éx̿D`-sqRdɒ gNC 0-  g(@ P@KcgEkSu Km "##35в}1a|Z 4kU6N>{1v&- hY5R^['1e)KƎm׽gæu12Me>KyZ1Gof4]_A|r9+c ;v۷IX%NA枬T:dSUIIIh֬z![ApVV̟~|zZXX 55v풽d[gs,zʛ7oq1byjXܧ 6ڋ5v[nN^>yo,(zξ^OF\(@ P0p6c[7\D+87kZˠNSٍ<]~Ve)낖o: zxs-6nFR}0lvhYo5zQ,Pk}˭ٳgѠA?^~єh˱hѢ '3ݻwwY[f͒?-=FU8jky|1Gn'gO> l/NaaaܹzK)_@/^Ν;!N~?~ẑKVX!s՗SRW@^8#PU(@ P^ojJ#$?ΐk~= ^UήM_|%KC? NU eΊม2ҠC'w3_ 5-_`gkk~CӈU|,qB4}xy]yRモgӯQ|y6'gUdŘ*U$$+"ĉҥK˟OpVw}W_ tΊ{_:(N 6rA#>K Ll4`8o(@ PZ 0Պ,n27(Y--p] ]GJ)OH8+zX=zT|c&) (h: gM (@ P'pjb1'D䉿kO,[ \p۷GHHZq (@ 05'po(@ PНYrd Pt#pV7 0A Pt'pVw(@0Ս+GY(@ P@ g (@ P(r h.[N P(Ymx?(@ P`8k p~`8kVf)@ PгY=s: P ,p 0܊wR(@mj+)@ P0YCWY*77K PQ(P`&\V(@ h+pV[1O P߬ΚUY P,` lhh(amm )p o4u[[[PfM=q: P -pf%p֬R(gcgŖlzOb߾}ڵkz~Y8V;wDΝqTTIgy3(@ .po(pV؜(@PB8{y.\ue87;X.렧9 (@ P@s[N Xl 9(@ PQٴ4lݺ]tA]^x0Փ7(@jŻ)P (@ P Wcgo޼ ^^^YyG؁0oژ vo)c PGǕ\{lCVUs>E%R=1t'>~3˱>| 7w;iZ.2 []i'O?ۑwww̛7-[㈟}ƃ鉥KM~~Bի9p{qy!NXB=z(\\\dڻwo>SQ"E~! 4jѣ1bĈ<{B 8~84yzPuj7PPYWYeՋ(@ P@Y gU/}6pV!`)SsQ(`n spu8vM$,, ;wFR%b8ޡlZ 5(P@F6Z(@ h'`lJJ BBBЩS'*TvB.]PxqڕXΞ4k ˗WF%&κ{T@ܭue/{Zr )7,vMe+T|5콉RGJv}2˷Om\&d qrU+5+V(OlϜ9XlYm {)@ A9T g.P(@ k8+SNpV5ػwB0{"?f[x=֮8ų*/>91X+2,vvVX$ na(UB >(\GYCy_0 )@ Cl>+p6r|(@ -` 8y֫^^^Q;7nM_"U]<9w}sg/Ogl Ggk4rZoE/^yUƟcüh֪ ll-,Cp6?kdSrȼ>O?/VQЭYrt d`8(@ Nlr3f@TT?V#_4u]maWƆP_4ӧ6~ii@rg"cMksCg sF o(`P&p*R(OV\.63rrvosM$?ΐk~=3UƻUR0VZ$ΚdY) PDᬑˆ[8[SEܙXl[Eqm vzcPdQ|< Sw1wv*/FbOuVVEp;.fP`Y#z) PF&p 嘶YӮ/wG Pag+M| :};#))nvfNn? "O^ F|Tg̰ݸE pV|a>}f<߱cGܹK5Q0;fWrnؐ g Ϲ)@ P0u^a(`z gMܑ 05pi(@ (^K PNٕ6YCsn PL]ᬩW(@ Yӫ)wd g8\(@ P`8r(@`8kv% )p֐(@S`8k(@ P'pjY#.F P*(@ PΚ]ɹaC 05>(@ PΚz? P 05rGF,pֈåQ(x/!7@ P0;fWrnؐ g Ϲ)@ P0u^a(`z gMܑ 05pi(@ (^K PNٕ6YCsn PL]P>>><-- ǎQX1xzz1C9PfMS/G P@&|%(GzT(@ 1]!+<<\Ί5** ڵCjj*vލ]ʠVu15X P´7QV g(قi P(x兊+2+mP^z!888/^ѣGӧ;v,6n܈4n ,+UBł-jժ/q-yBO> :uJ4ik.cٲexԩ>L+.MWdIĠp5~wL2%5T^7nP֥K:t'NkgrZ؟7=:t(?^߇dOvkTD \Ή9^ 0@ Pt'`hkpaܼye˖jժ%,œ{/8r"-UVZM)p:88`2x"*T CR#G"99Y>}:uի IDATQ8 ڰa<<|˗o߾R:uRyΜ92|ߛM6ň#c̚5K}K^Sݘ}o2, .\3f 66666 05pe&(p-Q(`4fAJfdhpVORR*xDgpc [I%9DZ{u<|nv\O#a~8&ߖ?ǸQ{qf m,;r7`mgq ٥,s['OR*N':t}ٓ8!QU'T5U-}|GEh9h 9dRR1uT VU8SĊS䬟lѨQ#ԭ[W8*Nr.%cpUD{9< g:EO?͛7'-,,֧ Ŝ gE"E哘(#Gȵj> P@ gu)A,_ P(;cg_x!O={Yݼ˗D!b-,XJCW.\Gǥ  blX}'Ҫ}+f[tqF. g BHw Z_n?j?錖_y:%KY^fUJ#|M|~C\j|]wVpN@u5j5k8ڤIn߾]̝0a dΊT8zˌ̗A8? SpV[lA [oaܸqTp^K^]Mbψv guJ-pur< "p(@ PН1mY௿*{vP'? O1{0w|>W'\={O};t|I. - hY5R^['1eKƎm׽gæu12Me>KyZ1Gof4]_Ar9+㔔toߖ'aU8[H sOTq*V2d*YqV=zhI8+NYa:i> v5t g/si9Eh֗. gU=}U㉿_,ڼyluVZ\G|(قi h%pV+.L P0pVl~rN."t5em'F|Zs .?rKuA˷^U=OSB|Q~ytk#f6pASAa=(cX/Vk}˭ٳgi/R]"kذ!-Zd"{ARKDV{bԨQs{Ay7D8+}Eۇ޵{Z~}Z+ l^`+V}<9[|`8?kDyR(@ PnTFMI~!0{?*W-O7ڽr-e̗hMPT1tp@XYp[v:.- :t{yr7 RYWСC4"gϞ- +}w]yRモgӯQk׮/%ƏD8o$kΊ/_:&:`WuӺ;wƘ1cr]LUYqޓ_6(N قПYYs& 0;@ Pt(pV zPdQ|< Sw1wv*?Ν+[T\c nW8u ޝaiiqSGͩY %" nOF=gŸ"ݵkZZ5Tμt'REOhދV g3۶mʕ+WR࣏>!kz4Z*a+z?yWjiÏ?(E֧pV{}y--_PpVNٕ6ORsS(` gM? "O^ F|rT,y__l>DNNJΊquۊ?zJM}.maUGC}V2MNNa/"{&~ɋ/˖?qU=(]4,YRpV)O޹sGTO&S~qwƌرcGᬇD]qR7%Z}}/_5jgggx {L8h߾ݻexŞyロ~q YNξxoaԧe n3f-j7:ޡpoTnS#cVv!!!U\/2"kYv-jԨ!4h"##QN<ק7P0n]ΚXA PJ_%,ս{w]~HnLފ^Y1Ɵc-2n '`}Z~`5]8" 6d8]zNPPYWYeՋ(@ P@Yg p z?[8mÚ-T w5;e[6O&4QO+sC^ue>9p/)+VG Z{>$~*?*R<}B߿_?5jc1bDa gUPǏG&|TN浾#q P `8r`8zq(@ (KᬲꥯΊ5,8GiI$(QeKVq(絖'gVa7е3I:q^N)Y(@ P@w gugk# q X>VYϦ0z\cS'(@ P@ g iSy֝(@ P@? glJq3lnAz gM (@0U@D`8k:N(@ P0>Wc_Q6S {ʲ\5 r}/pV5$pVAR)@ PPYŕ (@ YO\(@ Ys8K PPYא;PYK(@ P@q gW2.(` g >SsQ(`n gͭ/(@ P@ g_C@A gT,.(@ 0U\ɸ` P 05W`8OmE P 05s(@ 0U~  0UPT P'pVq%)@ Pf/p_S>9(@ P&`p6-- O˗aaaFY!44񰶶Ošf͚V2(` g >SsQ(`ng<Кs<~Ggɓ1rl/>'BBBd\pk֬a87Sȟ) Kl(@ PHYwرc(_1sa ? --Um׼>X":uꄙ3g˖-c8Mx/(@=02J, P(;CQZ5899e(Y>E8Fs{]qg1aiU_|r1cOaWVDaeY:|I"‚Qt1zߟAo}Pp!9wӏ".6!ד gӻ0`8w3RKl^BQkP(@ P ٿK~ X{(W<5y֫^^^Z5kdM_g/9Ogl Ggk4rZoE_/^yUƟcüh֪ ll-Pp6ʮRSSy}~^([ p/(@ PНقlz3f@TT?V#_4u]maWƆP_4ӧ6~ii@rg"cMksCg sF o(`P&p*R(OV\.63rrvosM$?ΐk~=3UƻUR0VZ$ΚdY) PDᬑˆ[8[SEܙXl[Eqm vzcPdQ|< Sw1wv*/FbOuVVEp;.fP`Y#z) PF&p 嘶YӮ/wG Pag+M| :};#))nvfNn? "O^ F|Tg̰ݸE pV|a>}f<߱cGܹK5Q0;fWrnؐ g Ϲ)@ P0u^a(`z gMܑ 05pi(@ (^K PNٕ6YCsn PL]ᬩW(@ Yӫ)wd g8\(@ P`8r(@`8kv% )p֐(@S`8k(@ P'pjY#.F P*(@ PΚ]ɹaC 05>(@ PΚz? P 05rGF,pֈåQ(x/!7@ P0;fWrnؐ g Ϲ)@ P0u^a(`z gMܑ 05pi(@ (^K PNٕ6YCsn PL]lZZN>˗/53ryzšf͚^"(@L gJP@ gͩ(@ P0;C<@ll,\\\ k.;HHHEU׈ibx0DD ]Y`8o@̏OS(@ Φ_ϱepr9YۆիLxb=O>رcqF 7Ƃ jժ﮸_6TV Ǘ_~[n}APPԩSĤI_?C!$&& qƩ9(` gM܅B*P\&(@ P0pV=vʗ/Zjsy咒RC8&?KLM* 8ۯçpsX IDAT֨RN~~1 18vyo}}>ƍڋ3amcؑ{k;ch.g6\G8A#0׭[W&'gEf9FvWp3͛k]tAO?'c^jvеkWi%뙘(p4b}y=x(` gM܄R*R\'(@ PJ0t8+fqN├[$ na(UBppB?z?.]ǼoW-K`êh;VE4u]7:3wq_&>+T7]GcrIW5qMgl]US_K`mQš4wG.?Ԭ].&E8{aj .\@:u{B5dhlDDz˗Cz}@GU &)=HX@@Prr^l^6Ď*E) A.E*D 5'w&323|Zzo2Ovfw>S6=s// g͙3džڵSÆ /^<[7Y Gr+5lmhѢ B3Mg:@S ޽{KΝ;*ufwgC&'NԻWZtpMI9 #;m3azZtYÑzWW@}jA~}/rv&Φx gV\9[ωc0;gNkR>ڞy>'pᬻh].@82|@pᬣ:_EԃO\B~>if.JӀ釵+¹;ʋK4~G  g7ۯPqzٖg33g|ڪ\"Mu j|P9k59cҤI,es^i&,YpԜciƍOMXkݜ+Vy9y19o`ZlLpCvhpodc2_x)@8κ1j κp @\!@82uw&kS j^ap"B 2ِ0g β*@@ ΆΖ@@ 4qU| β0@@ ΆΖ@@ 4qUgY  @g Nw  k\ s6x+D@+@8]1G@H FS1Un& a 38! @gsMH/@8w"  ͮ# @g#])٘*7E@0 Ά@@ & ފ;@@ fW@@ ǔlL" @"Φi͚5ڼyԴiS%$$XQ6lPռysըQ#ή]TV0 DZp6 r3Y@@كjǎSh͜9S={TJJՠA=z~[nA" bl ̘1C]w٣+fYnF/@8 A aĦ+@9HNҤIԽ{ ! p̙s gC\W,٣1#~ЛۅZF@ 91r"@85A@pR8xbUT)Ǐkʗ/.rլY3ägqN5Zp6'x< rِ e5  pB8kΝ]tʖ-ڵk5Y`flvTh gC.-C]o@޼ZgkTqe! Z^~7Тy;TR1=E3g INٶ:ikWvR:tΝk\_ӦMÇըQ# ȑ#z4n8%%%nݺ߿nƠƗ EUp6Z+˼)@8Ȳ0(@H( jժvܹӞ5k^v1͚5K\sJ..O8EʋKkvΞ>NW}4WgӺh5*ڜׇUvPDO<6C۪{k56/>O?\%Jg}_~ن;CׯYw_۶mS||:RJb&h5@(Rmvp?zXM[reM2E^{mMk~ِ95˘1cTzuܝwީUV^z2 YԊFl)  c"ݻ׾ܹ/+W_U Hp6t*p8atYc&w0;`LT|lJE߷I.tPSFw#˭ծS\O0`^u+W.M9L0ڣG*T {vݵ/Y4h&L5kφ aÆΞNDȹlxl f@@.^_PF 9rD6lMgho4E-+G羱,Z5Z'dlկ_?pgbʔ)z?jԨQ![ 4Lp6gn<@gsC  @PNgإKlٲ]uv s_.qlP%M&mԬvvXܦ% _ϴPgj|\n?;I]P:v,U/=HfoבթWZOJ.h?w7? z7tP͝;\(| y ԡC 4H5 gSE @8d@#@8Z@@B'pepBUZU5k9QvΆZ6/޸J_ZIc>ڠ_]eU8yx7\rʖ׈i4kU9 {gοY]qH&]#@8 GyI3  H{/:wRJp6KׄUЀZێ;֍Gkڂ[T#u:p&L?}:MDOLfщzwJ=B+<.S t־Δ/3WϽ%ixlh}i ,@@ tgs335ZoheO-SLPܙ_ן'բzM*W.m0RcvUۻ r&JK&IS'mUFP0<p67gL lD<gc@)@8Nmw/MSZk7>ksB&d4cV=w6U>pkQ"N ujeWT FeY 8Dp!p0s-kTl>xk&I7zdBz*R|b*MS4sq/U:L8_5jRg]Uƹ8sA  uXANt Fw} DVp6N=P8{$9ETsUǎArzٖI9;;5੅Z|N)3rᬃ@@/!@@ gcL8ԧo@vh0C@ g.CC@ κL@ 3H FR@@ g@ 2# :8 @\/@82@bNp6J΄#)@8I}F@h 3?@Op6jʌ,@804@pK@9٘+9l$@]p6+@>)3rᬃ@@/!@@ gcL8ԧo@vHiiiZf6oެ85mT }ԨQ2W6m2c׮]UV! @&Ya #6]! @ D:=xvء:u̙3ճgO,XPn,kB8uw;ۦk;T|,CȖl Ώ@@gv)M4IݻwW5f˗O袋Tj S!emGJ`ܹ>|/ի_vwzoԡCU^]=x/zGh"9rĮ>}O>iUVM۶m}'LÇ۟!Co>Qnf?޶zj5o\mfg'5l0{>7$1۟K .,3ozmg>~>s 8ϸ;vh /_uOO>|N+!]xv}TXюw9rYc+E*11z{z^SYM.P}Ϳ c0F 4m6/#G<@gCJd%@8@@B'pvŪT <ӧg-\І&\[СC/jرj֬Lkʕ*]tpK.\W_}?o<~vUW]kf~)`Lj'J*߿ j}G˕+Y&<5p<ӯ_?4'Nk׮v&\g~6opʗ/y_{gE۷/%Phmz>yyܸqG6$/UT_1º|/;ᬿvLSLQ͚5o`0ѻH FRcNp6J΄@@ Ng͎Klٲ]ٛ /nΆf;^yHr+^lfge5W:t\ Ӏ׮T:g5+~Wۧk֒^zZnSh IDATo}`*Yp7۶;tu6e>TJMq\5JծәP?< Մh]*T3Ɲu |lCsΫR\sgmד~3ANY?_dZlyV19;М9sl8֮];5lкd|%ŏ?hS\[9: gMfCʧz{GvYu65;9Mޙ`o֬Y؃ѣG`L(ygnf-#P7nlw{ g6f>{XwߵAj^ew웝8Ky#@87@PA1q  #H{/:wlTᄈ69Oӄ;gsTMwԓ/RS2ᚒrZFwڨ g4鲆#˭w֯>L=yv@[k׿=#?Ah_W8rokCW f7 2ۃ g/$n/ o4 Lھ}{޽d\fl &5iMxܭ[7c̱l3EMg]{.`sDjR 4>sC=s*4.YjBӧcp6x Y&8?דO>5Κ9c*&n8믾K۬Asɓe~_7^99Zp6Ei?,@@ tgs33e ['IS'mUF6hpC]~Kջo#Q>ԇveWe g$Uh씮߰:_5Asn~f} GjnjԴY 4ܹmvfNSXK 7XdxĜ,Qok@2 4?o0W\>FҚ6;Y_f7 ͙fk/wl}lvYpMm~L}sssBp6@, @@ tO8S巩<#A[nS5)pvԤj9/s4Ab隷ppMj Gc0L/1)jvONXz\fGjz[oU)))`W8kv)SyLk^e^0fvzY̟X}Ygv{?}7/ʪ\ݙjKem~8l#ʰ>rζmֆf֭[e^4Ywuonw̚u}qANup Ά[bZp6@@ !va>:_EԃO\B~>if.JӀ釵+¹;ʋK4~G  g7ۯPqzٳo_`*W߄uSe)KNΜ5}O?c{?iC /о\7N%JЛoi-[@̼<>͚˖-S=v3p@̙fG9/~ܴiLx4gnܸ;+YYgnM(m^9sonݺLMj$0;A5M8k'sƱamvE8kvgd;.'!Gli9Sp֙uaT  QǼBZW'OR%f5vsX ZYӶڗyL(tN@i˖?4yMvGRSOaa>sMz:~,U.הI[tH f|UVٝeuf'ٱy9n윜7o1ցM6v^Yo ٰcPeu&ikÇEFi۶mA$5޽=7s8gv 5AtL?5kfoS2GvWX~Aw}Ykt6/D t`gp|mm7|t8U}M{9ذ7en:<##.pIgY  @gCgK  и*>gY  @gCgK s6o||;} hUTLsjٚѣGukڴi6oԨ.̶c3hĉ2j4o\~4h`?7$0;g[}ƍzjKwV2eegڝ:u&O|9rD/ƍ$խ[W׍7 @ Fia3gYF !pe`BتUf͚'OZvT`A}a\rDv>kitxHsuq&HOI9+o]+o͉Iz}h[5jZ^_NجA~nW EiӏI<*_\Vc?٨9+nSi8ꫯjUD }gzmj.;~zugm6СC*U=/֜l^Dg~PHs۬G}T> x+W)SkM w/2&5c3fWn;j*իW/¸ pcKQp6ʜ@@)gY0s63*%%c ¼` g0&N7k.vTfiž2NpB[WҤVԿ_Lo #;m|~YÑzjשFgjv0@+W.M/n=zTB0س{5..}饗ϠA4aY~6d 6ޗpcǎͰ\5 . uygU/F t8-Μ͍g'O5}Q:fmg0lSwҩx:@-~'_T6.׏>]dԩc֛n)}WN<avߚۙ/*U6m P߾}3+ݿʗ/e˖Kyгk7rD g]^@.YwՋ" gUp_8k0tjyX]|n$(Ȓ&=Jq+vlO?S5OHo|VT tN8a7뮻Nlb9s՜ck-2ytM`ڹ[;wx_Yfn}BG g^ ]UOf  uV=2w__ojw]Uƹ3l:JNNϵL̄װ^~a殾]ekӋ}hj2a7t>}Xbhs٥ڦMmٲx5/ [b=|=c =ct#渍]ڣ LLWVgΚRJ7nN )HoL dٙ4 Ip6L.fd=g6mLRUA}u b}>&QSܢֺ}KJͶǎjȠ5mqB5Jj6gh?mh" m_eGگ'N$խ[W=t9sVZ)11Q֭/3Wjj}˴?yd;vLO?>S%''6l91\@ gZpՁ Np6t+j׎zsصjv6oQQNDȹlxl f@@.^X*UR5o=P:tAQF>|8lv  @gÀLxgY   @"Κ .\Uf͚gMԜAۤI,E8ua_6q.|AoR{p|=<%n87>V*C5sI/-ӂ9iȇתXs4-ZMgʋKka;g#z_Άf* l޽lO>YbbZh%%L܌@ FQ1  8N ޽{KΝ;TR:t9٭[7nYN&Rvf}GպhM[pj$TӚ߷Q΄O쀝0:Q^'_he 5`ٜיqqqJMMMܻ_ٜV@ 9+̚QΆ6QXT t8٬u֥`O-SLPܙ_ן'բzM*W.m0RcvU|Õ tM&MNڢ~WZ%faDܜ9K82&@ Yk f g#Z6:w[+Ǹ@@ nRx/MSZk7>ksB&d4cV=w6U>p657@ 9kڬYh[ ',aa@Q-i gk-[[#کLx}MoTRUhA=*T8NWSh^tޙpWjԤΊ/ݻZs33gY Y B0a #6]! @ \N8P8{$9ETsUǎArzٖI9BZW'OR%fv՚{3K6&`Ӡ>kȋW_ uo} g]X4 p"urd @ e2ᬹa/ Ʋl,W# @"Φi͚5ڼyԴiS%$$i[N2ԯ__7k.+W''% }@άK0Z`$< #HA@|D:=xvء:u诿̙3ճgOdnp6ׄ4Ҥ{9Z1R@pjƈN.,wng[Xl,Ws5 Pp64x:Ǘ(d!uÄ&Ά&#YԊ" gW3Fwtyg鶖s+F8gc̝@@ gW_?iJ(YDO]RCj ,4i m[O稿k>_nH?<_UbrԎ-U5a.\V_0~ƞF'۵z?@fC 4L}4}^z% PJ񋪫y1p6GBp6v: @P lOkumVs$cN~ p uצL1ϗ$P"YedͲ_=9RV=ݝ۟1_g'pv]TX!vWCVoMtis-9FKՉp6GBp6Yǔ  @ 35;e+]Jk8uZۯ?ٸ[ܦRԴ|q}pm}U-^XWMXG/jMz@oޮ9=m_vGLAo˱#W|ziV=rRӐREnej_4{q^>n6$%ۯ'\Hߤ> ׫+dzzJ)y0c2MܲO/.ECzp YIZضV+{uƛU&2sNEbӻm*=շTsm,NNs5cVڕT|~ ;g'g#?yc~fg/_9{ݮCVwb |~Ud|2؟@k!/kΞWPz/-ݪwҌw!9f?/g"U@u1= 89JpQ`0  e g i^^U+6UjeT9Vj:ftmjA$[޼}nGmh.^6(SLkSϖid uiWq³*Uu-BӤ-g %4xv zqm>_Z%w*6x}w+5to-I37|rMJ߿QV**2<͇f#'<{ZixYCsw2Ne>\Cc;5 A7S>ouϱ;[ϼ "'gBt?=?cLe#2͍T93GJ>_{lY:^??ѻZ8΁C8H#!@8 utcJ@@@ B-IKҜKvGe>=#5X~J\iJ}\ۓ/5sc[NR *Oc}65S֧v&Vj[gf}Y:m6 fLhשQS| XǗk}oAgkcH?s]_{~U;H3Ϝ5<#Ho+qN\:QV/7vI˟n9 g fe gH9׿]asV.s9u25DZ8΁C8H#!@8 utcJ@@@ "z3I9e,ԶZi=/ߕt,E<>r|e8}Zb0:_XYw+U.?/67x ? <PO: @P ͟6*[,רG *~N{ƹbioz8:zJSOJºw# V?7gm~|ﭵ whr˾]V;{f_j53g3hC`Y٬@5/iզZi=Դj:[W*='eWuC^tBϮx;g} g?aCc;3j~YkhyVkV0k /kU8-Q}qCcVykou"g"Y@! $ :}:Fp1`    gMijӦZLPw=pr=_p/`y_gfǘ 9̎;\Z3֜mb3g/x} uM?ToJՊ31}&|1|6s=Sb3;l vL|؋?]sXY5-bϺmp6؟`e8I{$م<[3Acg]ӧj9΁C8H#!@8 utcJ@@@ > ۴鏣'-]TO^\Cm2u6HV+.PkteRG?'k$=g+^|U5)WH o:s6Htn lXiNA@h j2 eW,JK#6髟+i]Z޹*='>1%e g67yH+. ui6 Bpeb!  -sk##3wβ@@ ΆΖ/@@j>Top6yoJ. uQ* Npu%cy(@@.k;`έM,p69@@B(@8B\vKRa\@gCJ`{jH@@}#;t[K޹#unmbyd\}Y  BҴ_ ڇ6 暐B @8Tt;gS+F I8[s"}vܩQF'9V_!S4p@;B '# @lXĩN B@hI8kW_;U`t _oO?T? g,X`w~ر yK%&&RJ*]T%Jhʕի[zu+V̶ѪU+-^Xݙ{Wl?_|+@800@yujҥ}lѢEo34q樄k~_؝3gT>}r~pZj>[^=Κ׸3eK)  1[z&ngY  @BΚ77)SƆfj3LjJII;l5aP]|n|s:w\u]l0JHHsք5/vCW=ZF@pΆC>+@800@Ph޼yڿn&{ 0MZhQM8ўkB\c L'ؠlٲvm~dS3f~Vl0ݽN&5^s9۬Yqgn, @L t<,k@@8ǏkȐ!UB-\WN:ٳkMPi&Bs=kиqc21.󢰬Y#ʕ+]UV vm>ۺuk <ΪU@@ P :4 @@ ټ"1/ 3Gpvk^ Tp6r<QQF&  uha 8Fp1`  :}" @85  u~agCK  1@@, 3y@li@\/@82Fg@@@@,+$gcL@B,@8b`G@ κL 7Y@@,+@/@8 i٘.?G@ Ά@@/!ȍlnx@/@8 A@ βBbZp6@@ !y@pKr#@8=E@ βB@@ 3y@li@\/@82Fg@@@@,+$gcL@B,@8b`G@ κL 7Y@@,+@/@8 i٘.?G@ Ά@@/!ȍlnx@/@8 A@ βBbZp6@@ !y@pKr#@8=E@ βB@@ 3y@@1c諯RV#Yw}:pq]r%!y蚏yN@pᬻhXp6Ai@i8{w+999Kˆ `YԚwԩSH?]}0Ν;ճgOu= gF@\!@821P ΆJv@@Ilz|=z4, @]1 IDAT"*@8Q~:l+@   g}8uQ >\+VPuUW[L'N֭[34e… k…:u՚?~լYS7x7n~=ܣÇݻƍ9RfwӧeB WզM֌\wzOkѢEZr;pL)cJ"2d{CR$ TfBEJB()$!"TIHoj^{vk>vY;>ߵ=Y2u<̲y6@@!@r{ g+ @@ |QF9oA5gs=g&M*^z~֭[7[b駟::u &ؓO>Y[Yo.jղe˖mpl˖-١ $r6aj@Ϙ @(]AgZʺvj֭-ZXNlѢE6p@[fM 0U_tYcĈN6t ;h}ڵk[*Ul՜Ztbʞݻ2rN;v#5sZsP6lcÇ>vi'A \Ɔr6 %^ 6~x'&ƌcgI.X ο{\Iw}^e曗 RSN9%0^l=9;|2dH`_7x+$gU;ה)Sܜi $r6qaVy"h @$ TTf9믻l6~$s*,Sխ^gW\qr.Kݻwwc\jΪ쭷WϞ=C =z;̝z*à6n8^zI? @(Bsr66t @,n9GzGڟ9RsIξ;m,Tk*'H+Cz~}&sV/G馛\2g%i $r6qaVy"h @$ -guZUsN mڵ1jE]d=۬Y3S֫s=t ʐ?yڵ֭[[ժUu$g֭VVnSɇ  @H.lrc@9 @@nN^6͛5j԰+VؑGYV Uj9^y啲TR@ٳ7To߾>&gձ2vgΜ~$gwao5o޼d  l!D9F9Z: @.kFή^j Tr@2RSucUUZRE\VҥK]ڬs̱'x–,YJ ֡CkԨQtȜUʚ6m{]lӦM]F2cӭÛJ.<߲eK;م $r6bz@˗!@(mQ3gKZn+s땣!@lH3N" g&@@@Hl 'lt; @ gr6~ƌ@r6Nxć B P9?cF I9']N<lC!@(`S @ /y I%Mjd @@9[ Qd  I9']N<lC!@(`S @ /y I%Mjd @@9[ Qd  I9']N<lC!@(`S @ /y I%Mjd @@9[ Qd  I9']N<lC!@(`S @ /y I%Mjd @@9[ Qd  I9']N<lC!@(`S @ /y I%Mjd @@9[ Qd  I9']N<lC!@(`S @ /y I%Mjd @@9[ Qd  I9']N<lC!@(`S @ /y I%Mjd @@9[ Qd  I9']N<lC!@(`Qm޼y[oʕ+m- qg5jpDNڵk9:=v嗗_e/5kڥ^Z'N?vi[U漣9Xnuر6vQG{i/lvmekWhB_۠Alر|38c-ZdCu²joW\ax+V(}7fϞm۷YfeLH]_>9Y… {ﵯ֮]kճ:ءjrی3*9u_T rP"(3t:x {ꫯvBT7(ZnD'g%{8a(!3٧Ok۶iJ{NHz}C4;8/bzĸ_~&A=V[_nke5ʱM޽{;y 'e}8pfw#G6ldрvN({e 2/gGwMϽˉ߉.^kXRr(E9e?S,"Ac\P31$geZ~.ֺ9t~qRI>׷?;,ԹuYsA~};ӾLkT IV]S(gIztc㡇:8w{e4?ER7̸IMjdW^ gA @(QQ2HՓ0Y*<@j85j7= %E,$g.'$c?VO>d#SOuHePM7je٩5g$#%ɩؿkNQS֜/gUS1狚nHQ67wel9e_rH_<.ߠX^D~&alh-b֖n͹Eoqdÿl3  At}Z.dccu3B '/A2~>#u]]ٍA!/l| &EqP= *g'MTv_J.K5e'Qq=>-sjMa&9lY/WRJYESSf^%,;=7߸,"uޥLTB{!I$JK**k 9s~+k}!Xclc_IS ZHuMr݋k}SI>Roo|?LRAδ^kn*\-9럇j+C]7?T%h]a䬸FWlK8 g0,  "g-jɪVeVΦ+FN:zs$jcfʜ&H69TMԖWzor/xc929˘al1U#hm+ "+ʞKeJrzX|xfJ+ϫo,T9i~Y+:֟,I&~֣G7mr6Ӝ21'~ѣQl&&<~S5MX2.z$V:,ou/}UuKnd_Ufwd2Q}(3]Wbu%gusJY!R)D{+$g WrƜ+rP @(G U'zىmժ{2$LUsRr6Q0ךay=W9i߅8Fq|RܕM<t{!~8*A k^mm4ln8 g,, D*gׯ_8TdkzፚGj*C2VO Ԗmna3g#T^drG?Nӽ 9m]6lrV*L7/$*guARO7!$%$.e $T2%Œ:zZ1֦udָqc'LԷnv(/]4 ˡ$u"dmkHM/gB*UM6Iv4ǖ-[Bo~zDZE⢬:u긱AX?ΧS[М8(.ahtDe#uwY2)vAZsl&QS.Rw^Z~^r6ӵ7[z'}OĪ?]c]}gotO{HeC 4u2{rP"4_o 4M747y9vZꪫ. p&B8lC@p: @'M|`dGf͚?lUV /К6mDŋz-Y^[t5n.rn쫯r}H6hРcLb$uf`ݻwwcu̙2Q3U>#6c O<ўyr .1cGᎭQ֤Ix뭷ҮW^.w|7lvym9;o޼#G_Kjw?;ꨣ\&~7gϞ @ wܙqF@Q0Y  @#M\HP%&gkӧmZh{g7pZSe˖W^DԩS$_ՇJyvqfmV?{~ڲ gu 6V\Y&;3U2W0j׮ħZAwvꩧ ' /`F*+VGo։l5뮻>S6L$g%t~iMVZnmxv=cUTĝBW2@βCJr!@r6ftQ ՜Uرc˄ɓ]f_~i7|~^{5kz~7;sMIRJ$~1rVcՇdիU-խjNArV8\}YSīNǏV׍YN?t#Ӛ/_Rm\.]؍7h?Sʹ^O> Yۖ[n]u]g;F[ liśզ@β% @@|O LHԪ);/V{1xjy 8r?%%/䒲:uDdݺuC٠* W/v|#ٛnɕ 䬄Tȴf=z8>BL 9y){v̙?NPYkPSJ11@d gK&,4, G9[z*KξK.5]SM]_Ϊ^ܹs7ȾUIZj ,p TUٱ3g;32g7Ӛ5ƴiL+VZέ_fZ7|2l%hJ~{5h=8W@ٍ]1"l)F5@β @@|O"r_Ν;GՏFNV=ڟIT֧Jamj *k9ZKYʤ 9l͛zh:TfWVJ<ύ뗳*}pe]ͯIDAT~vERիWwV/SUƮ-i&ժU+jnK@d gK6,\@ l|ly9u=в2^ T~;.]j 4pd^ թSrV<^զMK$6MwСÞ|Ifm|M'U6ݚ>B4ez/gu$vz'L`K[v ${/I?U֬^<UVp 捿ۘ P]֖r6+" @ g#DOΦfB$%UWR@ X#M\H @ED9[Dd)Bjnֶm[ @ yG΀I"MR4  @F9[le= T6le"-p1Y@ rt!@;lޑ3` g @@@[DY @M9[D鯠 g *\L #-1]@N9w $$E@ PlQ@@e@V6Q+(ق  @ g ,`L @9&r6I`. lE@ PM rd!@(0 Ӆ @ yG΀I"MR4  @F9[le= T6le"-p1Y@ rt!@;lޑ3` g @@@[DY @M9[D鯠 g *\L #-1]@N9w $$E@ PlQ@@e@V6Q+(ق  @Dׯy[oe+W-6lhwըQQ;k׮|_~\ߚ_*U~ּysW^s&NhNe?3(cQ9 [:vX@K/Ԇnv[|G,ZȆy9 _s56x(r T"l%¤#-1c@ @T9/;cZ]v~w~jwm&6d\JmY>-[;l_nݺ9ok׮#GW\Z9n馑U4 N EwqլY39ʗͅΝ;ۄ MC@1d@&;> &Eo6l0'њ3~N;^xS˄=餓3gW([nPpKeۡCQu֤I;wm߾=cwفh'x^W_}eyN2PH2/,sVu֬Y3{ᇭjժvZӦMݸ<͘1}_{g)9{ז.]j7vgs~G֫W/7 7`v=sxb[o5 'A@FY6HI@ΖtY< @1"g?{ꩧ\jPգ]wQ*qr:DO<9$va׷ћW-lsLc`W^mcǎs9ǪWe(N˝@X9_[>}m۶ a{9Qd'N `kvWK-ݻەW^nL:/O5kָ5p@_\)Sr_8g@@@V*N:+4B @DMWO[{ܔR)Le$x 9r g\7=Y֭~fwu+ ;!v'Gazq*pggNN˜2B/6נt3^YUɓ'=*~7n>ݻ[milP[|׺>t}{n7܍'٫J6hVZ- |!%-в0a(q  @F ꫯlڴi./I&/jzj>.0)qw@zY4%g-eϞ=e.p nQFYvl…|r;S{衇E%svРA.CZMZ% [ϴ$eRkMy7UCΆ2Ar6~ƌ`A PYer-AX9zV=[e*{qUr?tufadn:urcdj˜uʐ3gδ Մ}7mĉ9Y,VlϞ=S6^~|0r6{AE9[Zf)l @ (rV3g+?ЪU+kذ]$J~m2d~g5ef*kryY˖-mvsJ^|E'H=Ij|ՌMmbŊPzv I??ҳTՋ*Uʤ%svʕe5g5jJ%HڐUnN?]/7nm 6Ψ !MH  @EI ]~xV{լYӱRvW We:Wىk+ZJ'd{c/ҥmma3gիgfrsb-裏W^y% ο(7UUrV 촇۴iJoK!_+;V7)}sDS>l2ejke*JrjS g @ >Ql|3g@ ,dŃr6 "-pX@"@F)C9[k}_VfM;cqƶtR4i]uUX~_~O;crֵk״ׯ_oͳzV\i[n5lЎ;8Q;;L{o<@٘^{-UT[ͭ^zi3qD;mv*yDq28gݺuֱcr])^z >nZh :4r$_|EVt\· 3, gK:, Drhk/7>̦OnW\q믁r6u9C >j׮m7x]s5iW/:۪U+e]w_vy&lb+dY>-[;l_nݺ9ok׮#Gj\%ɦniT6H<9{w6 D#ƍrH2 @H$(rVkvgUIZn.s{?̙cUV֭[{aYe,.[̝v٪Uܿ/첲lX}oٰaìs.5]3fGv VN {I'fJ$+{Rnݺb_,:D&M4s:۷{e<xv'5K.sYYGy^vJ^tP&9Dp=z5k~ag/Bkڴ# gI @(5Q+lVezmdJ _;̕ J-k.b'uu]W.|=S.S5Iz{!T@U{s;18(ys"P2~%t6vX;szNJQxqa_m}mۺp{n[d p^j9 ޽{۩j'pI0j(S XbuݮJ'oNꘫȣ>a5뮻>S&gGKןo(g%t~iMV7=tD@쎒&-x@b&UjZ?)[p%U($9+% ߉(rwuAh5T9+٨1} 8e&J\$IozD^Y^[ϒDrrRPqx_~O>MyĈN$J4<g/.NF}Pك:Dɓݞow*񪦬ǧ}5#Vk֬O?nW'YBTof.iq׺>=\˗ƍ~֥KWC{˛Jq|q5 v_xeF˕ؘbl@I&Mrt[#f@J@ED2}!aa/䕚 Uvڴii_0!Ut}+SQYMٓ;r2M'.SL^ٳ0TԔٮ];'%R65졇rr6KJ hIz_++UVj%.snr^UJ覅JK(9i|I=z8>7e7K^r%e]tɉW :Xٳ3gttnL\  g%M9[g L T_jVeyլM]Y-Ւ} +g-QqUr?trN[I)RЊE.b޾Y 9+`WB@7t?s?p˜_UkϞ=ӮA7#td2rV]uguOeJzjzJ8~  lnH9ˎ @"gz=/5ջT- .믜^D5d1XZr/(ҋT~UVG((};vYߩ~.ɥl–-[nf7$l5$%ꚊCY=/(z!2Ev^.۹z 9Z?VIYe՜Ul͝־gj*s՜mԨNPlM~qrVzqJVr~vERbK$gKԅ6|]W4@&ew4lIC 3(rVSRvT_VG/J $ze tlFܹ+eoׯw[{լY/ilǰrV*Rum%4%%d`=ήͷzrI30-Ž>h·L/` +훵ʐD/ӞhӦ{iĦIt?'m XT9TV\qRֶ?3\W\U/gj9zKufuqN0tw+$%{uBRY76$5Q V@ gK|򑳥X? @q*g}C xr65œ!@`CYvDI@ΖtY< @1@ KrdBB!$-O9n @@ǖ!@(#H9A ! q @%M9[gY @r6> @@q@GYEDو8   C @(iْ?Gβ @@|g@r8*"@Fi @ lH@@I@ΖtYv98AY8ͷGsÁzn߇+РM@ {gWqE^^9 Wڱv xI:q\uZyz keAR¿i{l̏3;;֙}u[4ԮNԧpq- reć W7lh7;,|֟fqa~Gwr{=S!+ƹd% !wBXkUgOCǛ۬{я _6˝6??Dk peÄG`.wfQ•o!= aۘpaD-U6RQH07,8F8)2 lcm*˦<AVH:U:=̑`RnI]qeiĆ[(Ӳ"2Ya4xk<KH VW=> W0C0'O뗠 AjZغv= ~O$L x&?5= 렫N'7l,H(Lo"̓}R KTw -_GqtT]]? p NC@ kP](ߥsNkgB˴HCyN#Xĺ*z5*uBzIF$[l7o\TD|) fmuDZ['/DcrSK$_8ssGGRls2URHnݦbI]tМzHb@.ϜLxjܧ2`lJ6Sj+;5e1gr|A]IN.jt6oR_=fznDbԡXŚ4)$MKl*H%nX>"ǵrL[Ov\~dy©d?gh.-_I*I\"s6 /N-@3^9HI2Wb?$aY3Fz Oof/l=Дfc$q'} ^88K3j\;_uK)g+5q({Q =SQmf-5#Z+FFԝlpe]G]|>l_kdzd~y8pFNC9ԩm:U2efV\O5fBًe^o쁤V$|Fh`'4{'uDTf@3kTpAm\@NCePD8`X}YHj m5`3RS4xRsf-Zԕ75m=䠁L-)|F/I@q)ZE ʭSm))MO+RWTj"wIENDB`icingaweb2-module-toplevelview-1.0.0/doc/screenshots/tile-service.png000066400000000000000000000033501473125420300257400ustar00rootroot00000000000000PNG  IHDRUbKGD pHYs  tIME  uIDATxkl[>u$;=s6]А2E+CĠb|6񁭪:n cJ qJfm.u\[cǗ}8!$)'Yy X,JQ@%^|0v@O%/L;- $|.{>ރ ԉSYKcT WE!%&H宣 ՉJ7! tf0V-f "`Y:S'SwsX&LX80ǖݧ?ፓ\(UvdA=^[˾[et m<@}>$Ü :%a35Š`QŤqo7FeyY[g4? A+>7Cj.}}sNLz. M癳}>YbЋXt]c^d\P~nq,j KA2gONb1BSF\ے,JmYQ4$30:_HNxt}qy ' wo.e"&O>5y~j7Z\//1r͘g@Pٗ;E(ሼb>|IiY30e%, +d%}G%G"Qs 4m-dCY)\Jlސwuokݼy҅Aۍ%3DEYqODMy.Pc0oR#D$V*LHVx6~!8=Gne{};_7\x̃WZ $IFSu)p b}xSqPreBt^n *k,*t#rMy\,7Bd&,Un[g* KFv<-17SWI+1, (©1j(0F߆#TV=A@ QQ"XgV"}lL.LZ N9IENDB`icingaweb2-module-toplevelview-1.0.0/doc/screenshots/tiles-tree-noproblems-expanded.png000066400000000000000000007712631473125420300314050ustar00rootroot00000000000000PNG  IHDRgY IDATx^xETBB!@R! *X*XX\ŵłbAEWEґ;!H)s&~Mr{Irwgܩ{3wKD$@$@$@$@$@$@$@$@$@$P\(*o6F$@$@$@$@$@$@$@$@$@n!~glix~I"'         Gk -'HHHHHHHHHHQ"ӘUo[%t          GPjtB'zE UL-r$@$@$@$@6pv{v Ϣ$@$@$` kp_p5#]q6݅b;tU81Qm5HHHHnOҎdHHOa tŶlHdFg7)a    ۓgm|%  ;0[]C,}sH'ɗH.81Mq.V $   JnORj&  %`8y\,ᛣɘ^ DlxޏKѱu0Aٍi\$@$@$@$Pݞ8[뇭 l¤ꂯ󗮠[{}`{|s H5g7)Α 4nORmC$ gEaPDS"툯|6e I0ksu\ue|Z181Mq^+ uݞ8kݼ ؋n^m$O/ݴ;%wمF _g˅,ܺlzH$g7)Κbf    pv{C+'  gM}>tuKhS/zضy~O0if {pvcl9WkY   0ۓgiKؙHH!gpz%b"۩/:5EBN>fheǤn8[kuVh 81ٻ;ɘ⋢2HƬ]gBV]8 @pv{1%kHHZ.3<ʼSYB(L$PXjL+8p@wK/?>Μ9ٳgFjFk㑮x?.3횫[;\ F*u~psqC§/PƥzWcat j7˭uBυ-_]ɞ [iv-Yˌ @'`NZ5ٛK}<9֚鎛C n%H_ͪJťT\]݊mK)f9P=}YtСF6M#B.<;俿s 3M $@$@$-Ʈpuk;Nc0;1,(m?`sڜ0<])95YY݁'kk]6Fqdm.C$@$ LiVŪƒ91dEanJlV̅7wqᘴ|rBZU]'  AMܫt;!O=-q1*t*kJtq4'$e{MgO:wyGݻpBSNxꩧb̝;{Q8p yZF>Q2~>*pâ[aGRU*.-'vaŘn7%  GM3|5+[FJJ ^u!mcY2Ǎ͎6%-Y!K$@$`+Svt.QKZcI]@Z᪯+UDXMwrb_4.sןnA-T1-1-=1$Φ駟V^;wƢE :u*mۆ+WbڴiJ}1zhӢ˨6)|"i?K\ Q~p̏qؐxѢ~+GUlf*zB[Tm޷WY 8@u_kYY鿹lv>|(+btP<ֽ,bDWGT#{ٓgϞb4hC/-Gc#mIKW Jf8#޳r!qVWLXZŋ StuK=q/& Pᐞx/" [ׄIg兽؈nnn0fCnذ}^56;RxЖ4*9 #lgŻuh]ɯРF;kU M0]5芦!6̠8+"^J(iC"*)G'TaVD$PFA!F׮\f`(#O^ƴnHTH飏>Bpp]z*߷o_˫<&^F'apOr 7)? (m=h ҇ wϧ35/DsoO\dR |$@$@$tcDA댃3WrMkܿ]!v^I(IZA"x* n:^#||eO8k?V]1fCn޼٨}iXI[Ғ$@$@"`NI*ǟqLPKO>q6E ZVM yjZ]VCPʝ;y p*,U5'Ix`3{CMgs=g999*fmLL m`IQ-Vh|{L2M^ƴdHʪ֡C)Wry}Lw^'jZy:C6;KkԩǬ6dTGe:}sZnƋ!33 s/Ƴڨ^j1fK$^Hv\q'KU+9[w\\AZaҶ(++?Rsz.!}f76;RsiKZRHHZ4Y ;x%_IS7F@P}g0 g%֬xJ_lSZ;,ggG{QGRSS c6::xq!*ɓ'iX]>xM~GHBg|ze IHH ȉcb "q1f'~MՇPTZT#5WAX_mp82xqi4ͼ1e$T.M^duYc6,#Yi>ۑ?ڒ% );,q6*[icO ƲSi8~`ߴK8l:n02ז(t/"b5VdL6ZNcWQFzlB~$zkѱ&  0!8~1Jaؗt¬#ۜnO6f;RVmɺu h,i&YPs /6~VF %gg& LUmAZ~eKtCTuƲ8ݘր6v-,vHHHpv{vdY( @=%`RbVM6YY#+"ng%xȚJ 6S81MqA Ւ ݞ8kD3 8Iq֐!7ns􉳝}>nK.B0kc궩+u 7%c4Bf2g͞jf$   pv{C+%   g yΎ1/ݐ0O8Pczه,ڥ:RY@g=ݱjB:H^}I.M$JLOٍif" pv{,3 -⬾"61g>qVnL{ZU\vW"~'QVc=h:ohAW20}PLZs1}81Mq>뀵 ݞ8k̳ ؇IqV/ '@8+؟~ v#20Bn]V.[:uThKDbn"CXb%IY9+^ݿfB40뛻2EٍifM33 8=IqaK YgͪLYJaTaCIR $9Bu=JI,G"bKXcIr'bpvc⬵3r$@$@$@$`nOR:`-$@$@$`-:gEѳ9gXm0"|ދcv#¬JHm^E+egJ#@ڹ;C [OTxJ?_e M=˸.a91Mqֶgi   ۓgm],O$@$@sq֜yUSx/!5Мv: Kqbvm9g4X1 EIfM33 88ѳFOٍi~  @pv{l/ 6O$@$ PmKqpvcl^= @pv{lݯ!HHqp,k8LiӦy; $c2 %%%e5>$  h(6I fHHH8B$@$@$@#@qqlY8. )u 4pgsx P !   (r Pu[(:$$@$@$@uJlg$@$@$@ >qgBHHHH8\!$@$@$@$8gǖ5;N0I" @0&=zVN'  ( bKe$@$@$@O8+¬ g9   8X8['#  sY]a֘@KqΧ   ( bKcv   'P]'h):s$@$@$@%`8[XX={`ϑস{0dP8׬D⬝@   K5ةHHH+WGnn.zpb& ۃ>W,^k恞p52"B)¢A9u\4{B,Mq#u1@agx< @'@qO;H$@$@$gn݊;wG_śvEh4ri,Bs?Op!m"dXS3]99(ΚC^9f߆boD>S@]s :Š@Kq^O/;G$@$@$PP. 4XV<0~߿'O?믿aZI6Ν΀GDU/-\l) sR~ WJ$-D_LFrFJ&~i@OW ?%GNqZ \;a-S$%/FVV>J\?<~o߆b7FǀZYI]p1~lFvHHH8[']#  pzVv{oڶ ;;/"{=3"?g>~~ 3ql6<[!iH*lAp/BxEDYR&EWM̅Gh$ZyUI,B@|Z < #1mڄӌ3K PU aVrRs^ _gܰg$@$@$@O*qvSOw59sf)-å˗yp Ed%">ёAP~JVtUfél_Dn wgYt\z 4Dۤ2E1ٳW?2fƟ{>hYc    M@g~ sSLLZRR—Bc>   FI*qvʕgiii)~G;hi>RΣYBÙW!m ؽ٩ȸ\RI.PDkE_i 8[جܫV1gֺ9R:1f+p9[ 8S0m4=Ǐw@ xꩧp]wvH#r_ر<D-Iǯ[lA^^Խ mڴQ~5miVRUlHH 25!<222 wa_Z0PJ W /JG_[tIƙKjUU9&"Ze8W9#_}jԚ2fUL$@$8joy vDD//_ƿo\pqׯ)SꫯUN DooõHgbI  Z$@[K?K.ACU/>ճuVbS AoW/g̘,͛gu{uQ*qV:*7o $qf}}}ЫW/$%%+ف`hKRpB|Q$¯UI\x@ sMᒙ3ѦU /!#-l Ba 3p6RħM> ̭umj3q *?c$/rIX̤VBd8+Yyݤ*o 2r ||g`Q'߀_~swkVk#D )S~I=Dt<5kl2^Z} ԩ|I<0s̊1:tHr~ذaY틩SbԨQ8z(ѣG!++<<{/ I["~'xZI CޗdՆ'Ϩ?(++SK]qܹsJ|KUa$* D69͈M2 { ^"c[| b'D*1B ".o۶M 7:$98+!3&K˗bu4K$@$H oki!Dmٲ:]//ũf[Klgynnn裏Cx劭6f"]قdk]_~򞋍 /Hv< ZىQ#Fy#Oָx]󑛛[c*Mys&?1ţG[͎$. r 7(xUˆȏε^vSF"o$Vқom۪K~A $-Vq xֈד\ꊳA~h5xfee)"a&RWG69[+6B$@ І-OEB8vyru)S4⬈6EoEnE01kQDĬsz?E9(GQ<4`D􉳚xP>*vx]hU<>Y/ƺu3z6kIg<$cmhYV ^OPNi?_"JهzH2ǖ.O>]eH"Ԋgnu'kGzEPb >ԏ9f'x0u``Z精nȝ-%kyIH֒SL*V %Ih'Te%̕gX~~~xsؙl-~} -ZؾT!Q;>'7QMfSG]u$5# LIzǐ6bɓ'M{OI6`RV<-$sYʦz2v&ΊgQGUU#ʦP~('݋k(:ɗ$mDhH<e%mEM"bK@yq&bq*.g I{ѡCuz秡~VˢEdɒs[cG.OYf]v婈3Y,/qEvqc~RV7!ֺKVw% ?3SEx' Y8+QdMK cHDֵkHBCKr P /磺esVZq[K9$oL&`yJI )5i$uJQ%BZg׆!,gSHscUoE6Irc Yc#2^Wxg.K.:' ('`làoKVY)/ԥ1ݫEPX3Vq*"-<DВ疮笮<~Vg5Ry~ɥ\YiW;\gpZ9jW=c-F-/cb"'jZX̷$wqV"Á5]DwI#kE^ HL[yA%s#v2r]6"""'%iHHm-s(R6Ŝg -mX#Ί!^@V-S8h2d7[&p6Tݾ}{|cIbɛ$I!U&ʛq$+EI6Ri^RqV6 "JEB0TO8+9:*G$ޝY'; U€ldc$oDY6 4z6 @%"r-ޜb #W/Dg7O=D \$B~Шi_3m\0/ @ @[K%j|4 (/Ű$Z)K=gX55;t*L-U9ril-{^KY<;V/7PMKN ?b | f-TIڏv+/l/>Y lMĕxqJMuY&odt^Vi?R*f٘d/j9L-6K$@NI@0Tr]XQ)LKİObg'b KWncI i."HGb, )ٳgU}r<!4)'/'EXcSP? ,kQ~rݤ]\VOUk9$Y^ 3i[g%i^źExXk}P8s]ˉd%L;@>׾#"~k4/"K3? @#@[K%3%6*68bY+jޱWR ŎErE]֢8[Q-T vldd#Hw{cELI_|lEhuqYriWdmM!:r26  DclZ,cXr$PE9[_6E$@$Pw`Sxլym HmoD0^K73'h"|f8FF!eS)6)HBq^ Kl([s UbI2H\%?2/r|QeD\ 5"7+#ΊlHhxE~{Ib56!u*^LRV˧CyjSfc}[]<9> !Ő8+CKiX/"z׉:1[^NbIH@7 [",rx"W qVL%;wV1rITI͠+Ί]&唑ZENI JBc !47>8kzHHl!@[z֖EqqsȚ5r-!!AœT6sEܕRKgqݗ㦺IڒuY  GOu)#ɱL\Y -bĒ PI'9>o+|E 07 f@!<,Yb7g qVB`$G% !/4glٲW|KBN-kcQ*c]$@$@e-9ՆEqּ`JqVPȭ֫VRU% $d3$ާyH~B$ƪrClTK抳AUI$>_]UDdP8";VF޽Exc#R\!^n'J]"I2@J^Yoca"! $Qm_:HHԅ8+$F(rHgWײeK>J.Utu2)55U//tFzIB)I}rIeT{]Q-evHH%rZة"`8[[3TL.|r[3 ؋@]?!   Ll}QcGE~p;D?6`HHHE⬽H   I,WE&w}.$4l΅^z9x   P3 E(Zgg%K[nn0*6yxHHHٺcϖIHH> 9B#Q儒 @m8[ @c#@q8[Y.   0N,W 8YDZeN@LH$`?ǁ)@zma@ /kc@Yi t<+? 8HNdP{ ,05\Wl,K2Odm=6$`]lSvmeN\d梠TYy[KWDl:.ܦ-ÐkHD5*Vac! HųN[&2{xONslBBm-wjgzy KO6JJ,)e:pm,оuͼہ3 "XzST`В MubZ_W3ڤ?0RȂx˝. hhkezik9֮uhk&hEq4[h,gxM'W\Sts'7v$̿ B=0=Hi1~N d4Uʶs6:ήJSsߴ\9-'Ǚ*f9nTQmJcuծ-t|idffRYes6::Z}Xr"ŬruI8hSvmgGYSB׮]U_,cjӖ`}-Y[,ZLm-m-ڕNm-(Κ lυ۱wg'Rĺ#J|6hsmUM=.0$t@fydM"oG+mkFO5v֮3H\),GLV3/W6uIO`Dž4z L{w^r+Pjt E i_h6ڔ][}޳gCChسzm>o iH.H}Z0׶8K{E I>eY堐`v!ZAZckQ5͕90K٘Wxbav2Ob*#ξ'ǝ.(,'d8d.Ƨ7uKE?Ń`ҡ߻~?^azWDuAY84/Bn~NGy>ٻ@b|0jS3xi)$_@|vS4bx5jG ev|vxp].UbХE+pݏYjf>!< Wyg'k;쪑zT7@̣@P4p% 88ԼՕyGZ_ڈLd3}|^ݛ&`R h훁B_,9yVfUn҂bw';4*ѹ|%)^׵Ear yt~Xu_d3|y(΁mh[YE^{?j\*$Ǝe5ƠyO*[q{h f\a ^Iཽg)I}%p9ݗ>3VNX&d ԟ/<6 دwGozn3BY[,23 m-Z XQ?C8 # ~jL.ŻנM_{2j"vw=^t!"G' DS/לĽ?G#>%>|`pt+v|sKw P];{)?zŤnx?.3j58[~#*{x)W#ˏ2 XI! ^{k30w<1DV^-8a-"^+MgثC*+)-}wBV_ Bq+@@Йi@zMR/psِ&9t|ulOkAj%xf GoĖh7YDzuniq#(:vJ-+.EտĶDQB./>{-ħJJ.m+Cj7I>u;lO;Amjωxf\$gӰjz~7Dk?>A¥J \mc㕸p*\̔L;ѵif8e˖!99}8ҷ 吏'<GuM?^~ZDꏥ␘[`ܾ򗴒޿ †s8ǯE϶ =߰3A#GUAm-}_7Z(:Gk4ϽzY`(l _O0{WXu;V/LQ,<5Eing Od |CJ>JQz |VW2jYt jM)u7ߝل?2N_hg:>cgQmK;o<7JR!1.:8&vg7oތ}b޼yѣYymQ~FK[{U/&GF@ZZWo|z<֞0XnX7igzQHx"gɩ!t l,o-,E'@[1m-Zo Qu4lg&uxvxSrw*69+! $aU=)9xvg%¼} IDATkwFg)M1GY!8tnٓ/ᕷA}탂Rc%',T6O>b"v5f^ ~テa3ʿlqVkG 9 CWw #>~}Ti9n.%zOv On9ʫvᩁؘx%\+R=gK?SQsEQ|"(')\='Js {W5% K.nOv'+9U x 5W߉_/Ƙ6PTRm7ש2^Ig6<!^vgN͙3Ǯ`%6h]H\X\)AvZW.k;Wǝ#K~}}l:YPOSTt*gA#Ge0m-V򠭥b8kV!.YKQXUqOkAW,FvE /xvq-1O>KTިfeYYM0o9iwqVhe?~?w5&\\n zzͺR 90USYXx$ ߟH27!!J6$.:Լ+^|qb5Vۦվs>DwpY|n;ީYyi WCmQM"~78OPwufj6l/?~!Xxs7զLR}gio29Iw"hkcU<%:e8s'Cܟ0G"ƽa^وWǗ=ϝտE0g|wG`許]5E?K1cn&!a|`+iQ6d6mnc*j8;dTD,I[j)q@%\~{k(7~؛Hf {Wy\TC%$5eC<+b-ϛϨ] "PXRe'S$WT< bގEP]*TԭS 1g%.c\rx!N!7_lqI)jWZ\TzyلrL%TRIm><6"/FO^>=+OvȐHZx4WI]q`9̬9.%+L`EvX u _Ce\C3./=T^Gڶy+O"~?Qžrk#OtRVsyixYc{nkz{ouu3_|s4vPl?~-]0qA %c|@DVpSEZzڎI8K{_^ &@[ ֢e+I[K?+Y;UgZVW"$nWĹ U,ME8s8x9@ر4qZ(q6C`c ǀ`|@@y lx>:a2u EHں Bj+&NHC<1DZ1c^>KbaphOziz5 \`8Q~\5mAţe"h@ lP!hZ5VvצϿ'"%U}YPuF|l ;xZg;$av7xcmؓV>xXrzHye=,??xJA]ٲ2伽[I#o}4J3Ġ퀡v;ؿ_cO ='`QMEǒ㾾xCꥫn2VNB&]-թ~9ꔸ Gv}s+wq/e=.@{OF$@[&m-ZƾZge8s,OǴ:ClӞ8s 6o+漺L<|bf?Eb6u8Zʹ<L Y3ɘ04ygc8c$BDH‘q.f  څ&clG$9:bꌱ6gnEi4 D :Ce`9X3k1=4 ,jzuaH+?/ D$ 0M7vp5UK--)S1(VOwq}wd8j005J?>0X戳M--ى( n؇Dsyccr'|zZ5TT$\}C4<hG[ ڽ.<㢮E f-* u8~L܆Olዩ]Fvx%'l)Ζ{6 {׬Eѻwo/5yUQ޸x%ۅbʋٴBP99ɢ5Х%l~Mp6PsWR5kZ횉]q2hkU m-ZտLdY)3leXm[;s*VEL)`ԡ99/b@HjQD,g?7KǠUivg:޻fcz̞2*m.̙13Gj/Ϟ@~h8fO-瘺Sj3έgg H3.  إM Y{i8k:g٦UW2[Xۮ1q:Y#n FI]]qڽ2ZZjkY)fUK.<˰L\U$ fX$Kx,F j:+` klKk+x ZhSvm*兮]_zNfU^eV}v_5l.P5E 4zhk9֮uhk&he8렰y8u1HG:_Ŵ)/ƚX8c,W#0y\OxcoaeM3w!|L5s0km$59k+'Oh􊹘{0f~_@#^s1l Ls(1gM/AqE : fp*ѱ l| sc DOhc@F69|erYզmtHXw<6jMiڵnO>L[3lpp0;&>e'S*WWnoŢ)ZI#ZvuZ+m(Z ZckY)ּW1owe@16:?/F/C*Vwo404ZEkbzq:s0 y`t#0aHDg kpzf,,X8|0|u$LօXtsX0ZH Y#WuYdࢹX1^?tD$xM#s"M Lu@icW98&PV6]܀Ne=jv[&wXv"!4N7Wg2:hmJCuծ-SVϗ/_ѣGQVV -[ZZ:u`OJF,EkӖ޻;zUCq"\L$ ֲˬr]i$2MZ[JqtYg%H.vKU5*tP@bǴy76FG>sL1֬{Q|~rC}㭸u;Miڵ> 1q^㑑 w$mʾ1=&~#c H.lUem:1M݂F橫vmH[4=km-2G&@qO.F$P@E`[_ qfM ו$~'6ƽw>m yD!'e0@6 M2\׉OHK65p([ofsg5>U#99Ygn ^YA7w('2arHwLګy`"  KP68N´ijpG}dSO{A~*}wPRXӫW/a&   [b05b$1O% ,ȽQ7U)w9ي.hʺ(Z<@YȮx2~:^֨yڨ FmX X+Ύ=Ǐ7{⬹n8kit7@#yHHHPVlݼV_(*+w/,UٳeYгgRg-$X{bɨS؝S:Hz$bLOĆ4s$@$@8k+Awjge7 )) xѬY3]lV^DFFbĉԩS戳R; ,k_O>$RRRT[۷̙3z>y  p(0M+O،)s]uì*Ywmnz]7VsO<ݨxÈίO]kT}yXsg/Dz7qs$@$@8k7j )J7 ]0h %?Q,AqG>}:D$߿?Ν")q655O<}6oތ C 1د<馛9@4A$@$@z||2^yxf>xr{gciB,:5`gwء^N< \+uXuT7>jܵb?2 'ihyy4n= IgM"bLZq:Z :c t k֬Qqh|1gv^xХKTC2sV~Wğ=|0^z%%엔8ېW8F$@$`WzSr xLǿ$Dk)m-ڢů[JmiK[UZTR[ZN $$5yO̸3{N2!{Oe}=w3}%<9aP]q̳ƕY5xECݻwsN\a8kQy8cZzId敪U(ŁeE6ϕ`XVDΚ(W/_ f[@~r\R5(V:5_~EiۻGaqTHଦp$C) <1O g3Xia\XV`X 0eQ0'DN>I+-J9g^NN'N%K5a *E)и8A^&BKw]d/}0߳MN7Ic;c܎:%Kᬾ^ҿ"g_nR'S3K-4H鯎_Ɵoza[_xV۩x{W$򿣵ޥu' ~Uſ)wf"wߐ`m*۴`* +PA`8[A]Yd,5wؠgir`ݺuHJJHiСCYV`X mO)mK{L3NgҠN;:tƍ&ۢTJ:?xDJ ҏTUᬥb;tY|+!+/VŽAA,?slqg\dS~-2%O66>9gW [N?/#93G?6;/W]T | I٪Ip6~LT[ hGc3.pZINƸwGM[SlMWһ:v9y82 }ZDOl.cbgs#c55^N|u@jpEV`X27*o`Հ/]HNn@_ ;o5yO|Y';{8[fXV`ʚ7U?r=}faMunEAAe>S Cyb3BCcQIpv xφ7}=>EV%rRŭE܁~d8;Q sG? "g+Xj- :7Κbۨ*tjP܆`XV(P,8 S DG30;+'V< 374[Βl=g , QؓtAX!)s@9] 8vMwO eX wyèڄ+|m(b` 1-Q1l"jrˆ[L.qسd6GvFxud{('qM!I?`t5`@4`Z;  MdD˫/+ + 0N^ڔuo,{Qڊg s7]%8R;<6ҲDS ꈎ Yg[+;u?g8K>vRo`}tlrm 3rz/,,,0hQp|к.zrJ5 .f^x^u5|6ƔGVک/cw6J"7R8O0?vt'-/rƼRڕSMŁ`:yKl6* ))aXV(' @ԵeP1w[ D&Gn…|*zl9} 67bƜP4|u,7tD7١,FtDڞf46a;fޯ! ma>ÅP?[O9% G{9h .Ĕ~xrwȎօKp3dF0)C9YBF!84Z =p9ƌ#K.@Fj{A 0M[bXV`Xr@t“qzd|rP~NQUǬN n?\X/5iY<&A 8K66 EY*rYb]tݜp]/<{&(0goJAp"PwǥBpnz6'Q[_wvGݠ:guP0MYS⺬+ _gO`vbd¯w4l'R(,`].5`#`M;=Ŕ;=M 8{ Թ<5G%)棭vp.&Jm)2wondc$E TO#_XSa pa&k+Dζ]%;w5pېykYyt+ti_g8kV`XV( a8[^]RR2̖8*]}YVx@1lOX0M,|0 ',A*YiY=] _#XJưnOE;bQ[6y-\&оGYoiuT gMEt/#f؈0 c6L]3077B7cPˆg`_ E>.8U hO`wA*dIӚgՇ:} u?;[ B[sٞj.\< faY!JE[%8RV.xt/mj15%2%"F̚,7`XV\+P 8=s`U¹n \^p (&5Z="piڨWm)N!)]0wlpr6쉱CZ&a[ gyM<65ΚIGl/%xF AKJYeѽpyd`dt5*YS+ T g4qbA k11Q7~0yB/ '>E6n\B8 FѾ SWfsÛgOaY +dA&Ҙstz*#gE`ÒUt8aOx+pڕז |1(){+ђRQlpl(e0[߆5e+  gIl$D?;"<&Ҳm鋦]zop)/JݐS 6tWz^嚰մXyq;>k|+͇c/t}<;nu^!5[br"~l40[Äm?Sq%Tj (sW ,-,wYtEnα]&x+W)tBZPi8y"GoDS̔h]zvǹ?n kB{ڹd=k_:mބF34C>\3nbI7ߖl{*͵vJ{tIC݉=7Oп'YU`0[:<`tG @iVliNE>nUDڠ%9,:6n1^7YU{U$j'k$=ykq8] \p0htsQ[OΐKcT8[TM,ՂNGRV*>:W "K S58|m7gt< jV[OM]yP;璨vk䁉M"yXEMM1c 4w2Gjۘko46^jB̵v͡Zگ~ ꋏhjEjWT٪`tl`XҮ 6>,83QLSU~H4leZYXϐrG oZ4O""*Rᬱ`tl`Xٲ%c)`n8KT vфKDhB$2S]D< wcb'P\ Jm09ln䦃@I?y|+TtF5EE*oZ\w; sm[!*[;`iwnb\OO~NzJV.- Mɾ_lMMgrpV:wSZPBௐ|z,V^ulu{W,i?qV/|3X?-5(F}Nttdz;`Zϰݍ+evsƇ~B\Z"~Lv-T&֚/J0YM,ڂU6ǹ?l_zA{~*iYuR*YƮkX:7ܼ\,0 #}&~LJk4Gmr\l0 CϗΆrן)kT8dSݕ֮$wS=ȘSJܘlMޗ3U|Q{h>rdeL[ju fKo̖?(XV(+ 0-+q%giZUC*u: 2R1]u*zz5MdkFxQ_pE~%P⨿t$8;7 V!3Qñlx(rR䰴Ҽ˪\1|:NӡK&/𣄳Ei2c}-9+HDh}x|@PU@vNE>QrML |Iސ-׻r4usp<1y٢ R%ڻ7YZԮ5Jɠax EYkN4y)rcžOahq ȭzU:WIMn dVuj0KO ?+YqPJu Ei {{me|ur/.(*s-E?Sଚq\L()+۔'k4soZ$Fvϗrc*ʾ$眥¿s~imiݟA5ᬱ]|`tl`Xٲ-()8+ޤ(<x~w ^nww6^ ,{"0'/3[эڔ$GNk^0*n`l R=^ٳ9\lA_. Yw}&rYt`βcT|)1o \ 8㋈F)78liWBRE|mZr8P3 Eߞ߄gݭF Ԯ䮽F4c-j⼋F5P߹Ρuߵ} ߜ('18&1 f&^cIb\9Rx@?ONiIx³9Bj,g [iŅu0J*V Ξs̀kR_zJ׉6$)kq@=MQ'zӕPO_cZHHkriaY<޴Ԣ' h/.iƠZ6(]]v+hU3sYck"tR?HIѐQ=CI?iݗLYgJ%HY Yc; + @Rl Ί4^Ǽ3p<1J @QdLAٕt͊ [ IDATXN50"'E@R=Bk(,٭X  xt9cy07tQ.IkR޾[ϵPs{͖p( 8BAg&xș[#`wܡֳ%KΦd[SW['YYFYi"mPIsjRMDb;Li2"@~]kcr"e` u8:E-㹓BCao!}3+ + Eœ<")`n8KHUH!U]bP.Yd*2~!ӗ=mEo10nØ!]iyaNV*V_܁}#g| iuj8< zovѠ|1AA{%|'zIz .6dm E9KfTgrpV͝ਚPJMlT^bW瓯n'gijwDp{" 0J(Tq5J@IXb8*#7KhEEZn&]m:))8C:-7C@{M[,ENo1Bv?PԮ}yǞ'ucC#͵ Tژ"Ώ$Ӧ(QڧIP:]jaլ]{ܵN?*݃}TD?>e_hlGR!w4vjςs07D^`8uXV`XV(9Ζl (Pp L[ Q KMydqT%@E[%&RVԽ,܃W} g#+ + Rz 0*q-'(y\>.V5ZR_R2}<ʖ^Ζ-hYV`XV)pgdΚ cZǶԊqE[EHC^%l酳gܫ!`XV`XV*pϽ?f>f6T͔{Vc@UoMºXp|g + eGeW<Pl jF |1(1yD*-)Yy헔vYǣ{ili`XV`*.uq]+<_V@Wu*8ɼ"DoPҴԍQu^׾隙n˾ e߇<V`XV( 0-ї2pc+ + Y},`YS^LEԼ6c8[q}3gXV`X*pּz[m7FZ`oe*usN,2rW!I8/W$`Yjt16w,m +e{S׭5L!H9;ꄊ׎l9Ϙ`XV`JF%+[ 0-R $܌CE}+."ˊ4Wuh @9B:7< -YڙR( YS`8K`XV`X(p<:V@%fpjrR.*UwG'1-o g4x b, &G ْToΖwʵ]ڽ<9V`XVx 0}bsW@#pwePwԝo=~WNCZxů7U k +\MVǨ_@^0T.WȍMior~_6dgõ'H߿-=Ϧ+(rv՛) L_ahdhq S]M8Zay)Ԭ)kͨF*^NPZp^z6>Xx_x$"gƸzn(筊aF|=,aPq8b Un U fp.aDpvYH4!u^H֕`MqkIҾ9Hκ rQJ ˍMi OM_ŠԂ5?}!u:R񥸚 4E#Cf}SD8r %_19Vd1'aql~~>_x 2ìL7Ad)/5ug8LEJNo3e(f)c0W4*ZFŪ-PJzq#mg7t)xWjQQá*9YK? TG_ C- 8kW"Ys+XV`Xҫ0b G3氫?(ClQ*er{6s܋T bKXń NѭT(zz% )~ѵbcaL{3.\Dt.1~OTuđՙuqFJ6JhCyk~nW$xy?n'#PqMj:;o DyD҅BKJ 9rǎرce)pn3uZ#SO,6lJ^t3w/aHNZ;M_<^{PEi/GFBF2rPr |snO5~s% d|}f="^5ckcP. iXuq^$^'Ҏ+65rvΊӸ~;Mxrj9"19D;~z6U' (ĔL֨}9yX-WŠnu`i0ڔ oвQ5ԫ/%#|I09 /8{mL dଚq4>x{i٨]^UUe矗Y]lIO>q<-ܖsF*VoAsjvN6x)_ԫ Y9RmnmGC{O(.TQ(Y w?wu=4f}Snss_ѿK}eR;c/=u&v7GG iIN?J{FLC>!L}M}F쏚_hJJ{;OJ* ~Zl% + R^[:6aWP(N'ubnN;$͵[B6 H(&uqĪ J@jowM8H&D")3Uԫn%'q>9N|1 ZoNusƇ~B\Z"`[x-M w[7`rA/p׭auwP<ТZL}D98{-ܽ{;wĘ1cd)p:|z,V^u଻+'W!n,^$<+VxvL 1VȈ!8K)"uzoyXaFL~~#@~w}ۡW0Fgx-kMimP/Ip'+5{n.sOZYS8/n i :f@^+z^NZ~ 6@=/g}*3ʳ~JĞZ??x2&?u@pxD$`db ؠ ~Ud8Mޯ@ΪWFV./=5F*XO fvA]|<+ױ54uA:hREDSIKϖC`΢w;/t ľ[8t6>zMJɐ+yϠg[/tn! x5gi/zg< NDIӄ~9OZd%+;,. ] 9A5ozDSA_LT\~ ⋏_CEİ}@*iIx+w~@|]MJŞt/WKG^yyyؼyLJ*> pqyC/^W_}oV*^oԨ3K.aܹ/Vܘ`XV+ ԉhj.]Uu㺪+Wl%dDpV_3Jq@Ona[UC*u:^A/l 9 U}fڻ7pWZj#"hMikFxQ_pvA7ΩG>W/4 6V,}i%1b>u_*he5]+}mZ ŷ6xb42 Y.gڵb5oBQZxXDZZ㏐Opwp|9Yk*ӵڂY=D~dc=.8Ū} 4pD`Y^cJf#CcQR1*eJI?ғ,?_WwCL?R J}>5\o Wя+W=ꫯ X~ ׮]N5pvѢEZ*n߾{bӦM5Ga8k+ O)DͻEΕdX8±W}6.&yҷ"?;¾]-1Y;Kax“4]j7\އ-W(c:X["tX[Lm Zb`Og, ioï`rg\YPnPV1Ϩ(5gBYو%Q[P>N"b A\ֶF,E֮yzRԮd^ -_P }-%g<{H4/Bv^*8Km)Z:ooBfCHk,Z1g ̔÷ Щo\5 /Fn`1!sw{kM-Hqpή nY,EM8>{&?pNF؁tӏny|n?z 720\.z}x\+ۊѽp}U:y4pv6X=FDZ;"yG+56.XDdH@]kTouk+ E[J7\|2F:.v>~pٜ4?,\O^/I+8KRt!%νC~>(UJgpq“.J&5Wu򔍜U˔Iu5*͇;Jmlt=OE~;ܓ)5JX_WyiNN-`ѣϱ?~<>3x{{kS4IЧOCڵOqZ "ʖS%8[Z5m+Ξ=O>D}v_R|뭷Pzu\p .D۶mE/7x7َ;b˖-puu믿DEE9̟?_%4$):1*$W`XV( HlT̀MȽyOZI퐗ep [+I$M3ՏQ{R8:ti+^8Q[_y8c88fwl9v/z n#7?]<S4noTpfR4cgm498K_J9Y_%rRdcQ^DH)8}?=.8Kj=FDKusVRO:Vh%|0 a Xwy-cpT8KQ?uY<.xWL #)~gáLƪ#5֔3мj}|ra׾\Gg6J}{HtkXd In ::pV #g)w&BVc8l>6,+M"$v\R8{!.݀Z7>.*Dt9t <n8v>gpV3QK_'VZF3PkϢUjn!_9;HGJ~Շŀ:Ugi/"iIx³9Bj,gMg躗WN:c|(Q{}QtLۥJ)5}8K~?y$>sdeei]JvU}aUڵkq <SLK/ݻΝ;!CpD W8iz¶moCuVvxgѢL(XV`̩yȾ=QytKdDvd"rR ǧ0"g)ȋef { PR g:ošwpVukr{W- 8<=ʹ;v7jkE6-{ǥ*PL8KNe~aLfiygOxbLgD;ڼ~0YLzص6&*,"FXKn qY-lZ$e<5 8[ש~C䎥_1M~;sY8/#_/!(9g56(l{&".YW[W\thG')iDIp`W8+V4֏%`Ѽ6#**N%Ū&Z9۽fKx#~fl) Ğj4&.½4Tw6'gH% ^OðpqED]o & n,ΦgDlL,ٻY$^!jTw΁t)ujVBxT%b̀FK:$Nw_fiX LD3'rЩx_rGFkP9KJ:^D$?!19 08hHkKY[SB==E&bˢ+ɲvn&tFf"ђ IDAT "ߩdj.8?FX?GI[E#J9ۻ`dq\R}Sns3;g>C\){R;ʽ)|R=O'Yڿ:S##!=&]$p|tt{Jտϔ(tnHSN?hSN-1j(.ѣGkb,>>Fe˖IG%ƻv"8Gs$=l0O"ESÊ+83331|pQ͛ϟ@:RBpaXV(? w톅55umﻂ8;4\ӂ)Yzru?1Ng8+:[T8&xw_&сrS_b0:dXïQD5Yp6Qcnnx[# n܌DyY; _IA3Fv>z+ёxPa)gk)z_cw D:Bѩfm'q{*f8 }QՠU+ӛI,9/b-*DBJFReZ}q&R׻ȥ[. E mn8֋Ł>bi })i_Ulʇs!*8(0C<vrR чt+I(0F4"tBjvfZ%Wi֚WzCfǻ ,-;pN Jm#k8v>i9QOwF>߮=/gRذ 3Ѩ+5Jts =p?-+ :. c;[i M/#'7CꈱΪ)^TFpVi\iYX1[2tΣamgcp99y_͓b/tN_H¿GFbж8[h\1um)[5vQʕ1O}ԩYYҜj.8?*,]s6òf!pK-F̙;}䟘Uq7 zT}I>r c4J󑃳JmyM%%zlO{%x5:Y|"##_vک4Q~)rիங3gb?C0 ,-٘S)=ERZ`m֬R0Ej Ya;==]RzJ%G(\ZK9iF5P$2+ cQ@.r6=5[#M%gI_1Br). JcՠʽQ8lpƪ7qzZ8+r g x1&X|zpet_O}/KW5G`,l[g"#Vҕg f!Va1*BPI=ؾ0vk$ȶ񐃳cNޮ G>h'No;bƨ+@bOVo mзx<]4wjΖ桗ֱQ9A!ݦն^5(Ȓ:qd}C9gџ<Þ6(:N&r[/Tru);@É@伢$ K hQ }K]K}0_,4A>DPǒK{xyݻw1n8j EO8=֭+CFQKi T8K7n) 艢]KFG~(r"l R  S@ڀ + @W@'l\2s`㊼4,9.r'g8l{YYJHKB̾'.EkN^5T뻯E{>x33p ֨m\QN9, goECؚ8շFAZ@]v!C[aTf4:m´Mѝ p69b=%a h) w~fZa6w -XϠ~[~pDm|4Qp˜G@Z8W\HoUea/W}h '̻K25}b$2n)j:KwܜDʇj\ž(I?#G܍QIE1g Y v)gUKSzW·Zpt[?RP giΜ{8Y]\F޽{" =+III0a{=qHҥKP VsrRʂ7bƌRÇ 8KQ4-夥k׮ KѲ!!!={D_rR*Gw&AhR$0Q^_>yy1XV`LR@ gssȽu_5pVv=Jm `c Ǿ~mӏRZMEi䬴uzx^::ㄊ~?28_i䬴5\OC5H(88u9?ncNpvg~%uHBw.~{kp0]8u"GCKb6x5 _j-{JRj{ԙf1")\q~Ԇq4inQ{ >[s0[+uQ)zYcʿyLc@X?G֘}U 0U%ڸ5>]p+$@Q pUw"4!ᬩs}+.{Wv zOKpV8fYp֌Nd7o," ZR%Z V\Y &Ԛ,_7y|Rҁ`^mmmѰaC :T@P*:g\|5ȑ#}&ر#l"Ӿ;$K XP4.GƻcT t*F)[9sF䴥ٱcrZ,YV(`YsȩΚ/u,TG g*! sĀn=c# ѬQa;q:VK{S M@l'N{u5/¨ht+ _lQ*"g#07X(^I×g1J jM6i sz" c:=$YM1%UQĖ:8Jp+p{Xl@%n'aRh?"=7 0KI1THs-Iy9rv, K fwY*_y5.L 0?|#>xLl)Rl)rA_g raXV`LU\Vٜ[Ylx0[bhq^]M?lSDVŪכi?(sϚx Sv m1_5]}0(9gc<,q%: cϻbi?;4BǾ0 +NrбpB9gTs?^wqCaF*Z9vqj7<ؐmc "KG@)p SSؙi/ X,R3bxQlpbEif\"L15 g(f b8[o g˷yv+ TNa֩僀aLdž9P?/c6RM\}w=Z8lD#,--@[Bi` w<혆-LcvtFSs@PlF1(lՃYMAl23Dg8[f]W=%P0Pɲ+ #P# 0-N.,,Lr5/uy(;0h1rNN YU$8k 8XV`XV0INk`\\0c kިW&-p56V^܎Cϖ -h&0bw~qpb١/by Q?Sq%5+:k1jh)CſCwMW`Qfv՛) L_hV:鿍$TpVf.s2p. ; 7ғPz(ސ 7N`:j-1~1PL9sP9wy*iߧzj H;KD 'HOiN8x' } *!Cm7a?ZJF2q/1s /JɓJ:ybǿ!)5]J۳En1Jg7Ί޾o=9ak1`1&JMY.Qwf*6/5qJkHLEj =^1fqqJb;e$ah]OsV.ts$0nj6 ֢i@|qG1RqV^[|"ʚ+b?ܯ_jEc5=}'[}||{ppEޔk.G-65잌z*mvHk515thp5VCqVi{6tYU[i޵#~/JuѦt}!N)?;9\cbٍ8qS&֟%k_i]j5K=9ki\`L 0&@M=WeH[iA4[Ҍe,8k5.d8+C~;qFL! SSQ {u/1oٿo):Rb|xKOM;ĠKZSk|jK.Kni~:|]^BSػ@1 =MYU)X 3O΁]~[KM\s.`ƊBng3f˹~Qg&ijQq&,ܿ*ldD%AݸD596_~\ʕ.}BC^iA桐CAƃ֧)5>CIos&p?5%<SS0Foޑ(fJk̈́{YY:BLˉkYCvfdTg>6٬du+1qVf7g-McL 0&[v9i\@7!MSrmgg͡e,g :S!\~p3MЛ]7g-Nr'k}A&qvV딼 λ'jK_r$e Gظ?<ˍ<tE3D1"y6.+:ZzDw3y o6v~bNi!)UWW܆6Oꋴ9 ORTsA6ӺT]/} Wt, Jv%M m?S{ V\܆ū6)޲*Ŝt ї!?fB ^-Q =kjqVw,7\ڎbxZޘI;hm/K۠>t.z*;iPc} 73퍭$kgK(fuMmx~Cb."4`h؀n8Fa(SJfJ IbqZd^&`yfC8 ~|FT\[tYsq&D YYakq^ݫ%E=`mc"Nn\NT7E|.y"j!+$T(qW IDATi:Jg}(|t[Kq;= qp?#"cpjp1li;k J1wi3jFk2ShHhUH͔-Xj1HɣB_P8ØjvHb.$%1gu)&sb$RJv$Au׹z!|hC96'Of5yΒI!>|OpTg"Z^i~uhz/5Eah^i [6v:avAkڦ9soLfw$ײ}xQw6tP&mm]ӣG}0 WC_C%v>:v͕PI%oȉ{aXtL1ӄٰ]XDnk/ÕWjTB4V^ځCĜU&b8Kh{UkI%xj됮ݹg։@rk1{0wKIfhg/G)޿kv VbçKćL£ 926/_)*$ۯ85+ zYrY *CԗeTh#!a8wU5 лyFyٝ@FvΊnclJ xL)kJZL.o^sYLfyZ9Μ`}a _#99Y _ݨ8۽{w 4رcECqСC_eˢBDD,XƍcڵB Um-Hbi\ .ԠAИ\bԻ9`L 0Rq6;_z(ZO!A",FϏǰ+MMP ]*8K>O ]=q}`& G'Wtxهdq͘ d7,f1?uT >b<%*/;pa!Rzb p;fϢ˗/c̙iҎT=wd틀PJsVrF&08;~7lmQ[UzH<=VAj<\y n#&hMK'QʎR;{Gω:WS(sD@rm8\Ysq&D\iVw$Z,E2wlOK KXMoϟܹs`Z^=D*RyB Ћ6lG&o[Okwʔ)ɓVo]- =?AN:"ATT{Κ4Ü 0&PM= ׏j#-%¹E9Qm܂(~|Q8Ke]JI{oGw|1ǿGbQ ?]&>w%=mK8X5aJXeD,d"9h2fd2\`Cє۱ mҳ&%>ӫ]CO1F}ceٍ8ݺaL 0&EгO<-)kn2)Xei %0/2ˉ?b((Up}q(Xxqְ8̟?aaa"-ϠA89e`L@{LZZR~S5 g`L 0Dټ4?LnLò(!"7g4\jFqjB=MIɵew2Jcle}?rE_ZySo;p/ ̆ 0&`{1&4҃fu_IeNȵeNs,ZUav ܾ{wFuk`NLg ᜊȨ:aS81&`L 0F2&8C15t ū)::#ז9ϙlY·]*°8 Ɯ[T.-hQIp+≅m0&UO[T-e*m=Vvt.BXۥvEdz&'bՆc_.ICg0t<©_e}oE#k 8Z:\ _^x{Tz b˨ڶ:xubLWڪ(⭿1Kyc1\ 0&`L h H 0&HC Y 9߯kTrFGƨSlm[NaI)9FzQ1S A6!o Y2=6UЫH2o>e5fu&bsHl^ӇI<~o/#1 Gwjvb}U7Q:ǰu-N8cvR붅bw s 6!2D|CC=o}tLWO EcwVŠsa[ +߫s'1^5s0&`L ],ݹ3&` Lqq4~ DZ"?y8H$&WľF#Ɲ>ZQ^ߎEZߛcٶp,J@dR*a^o5Ȉ!-.#޽u5t؜*Ka4ht"AYU u:7/_^SJPht+Ah4'?6IApN&`L 0&`q&`L HqΣֶTZ a nGCqQT)8{mF^"o].{k2=SȊP<+B+2Fx Ex:P qh7( k4GRqV*>^Ѱx鱎ڡ%E;xRGoc`L 0&@6#l6`L 0&- PqJje,$ }Kat'MTr ة}1,,Gղ尰yc 1=2 nCx7cK-jUxv(8bE¯t*cle,|$xBh_ "%DqF$m8li:UaYN9P^:>zw]=*V] Z~5ϚNSL 0&`@^gu/Xg&y$L 0&@ftqaT gfwkrݐx@L 0&P%п,β0&`L@;gL@8`L 0&+гiRsԗ\a<&`L@@8d,f2pn 0&R,ΦlZ$7`L `q6Mw8[`q6[Ow 0&0gYIquL 0&gڌxKYڙ`L 0EYgEro`L 8,)gk,f1&`&,6) 0&@^#l^qu 8k]\;`L 0&8lH `L 0Н3=bk.W4:iE+.rJY0B H(.]ѣˇEYfh߾*¨( ::t蠘Wk̗8uj֬SFe`L (I@yݮV^pOSve]ݧeK&ps~Yt@0&`L d)=B1*0.jvy]Ag3+`F޽;vZlذ15j9ԉqȕ:u*+>}h1&`ZBLfuuVN}VWKi[)}Yr,ΚlV\ 0&@t\~p˻xbAݏ.lqL@FqJ^zÇG6m 0`4o:N:Az#G ::=lllpY|xD:5j`ȑB Axx8T"~wttğ-[ >>*TQpa\rEvك^{ ڵԘ8"/R_cv4HnZm OaÆbŊlvL 0&.kToozy? lRLN`q6ؼy3v܉;w@ » 77t_烞̙#[kJIIt)(Y$:v(aՒmkm[.ߘ1c0mڴTe`L jn1"lrL@B@8Kk֬M0j(899igI\jf̘ebʕظq#,XO:u1tҠcǎaٲe›q7[o!CzE9ooo/gvc_~}1113$JSFEQ8KCrr2D[_}<==liqٳgի~Gcw&`y7WWaMN\Ęߧ,nL9۪U+!VlE0%O?C@*֭[W}ڳgO!Awzj]AbI,;w|J1gb xJq=O??4i]Kf0&< qn{*Vq9UۈNqX~Pvl,ΪOa ?.L6}ҽ{G Q>=w3#}ZׯZ$ҳ-9{!믈NWnU陔H4&O^EϨ&Ϊ!ƍa4AZjc>L v39wJK Bdž'E]hyD+؜L 0&tl[_-Lx҃sרaYz߱n:>mїz*R1 @ӈ:Ԓ, Zeq0&`25 6$2K"~p, o,S_g 4AHԤpjN?#Byi۶m8x hyy;Vd!Qm(رB(Ǐ )E;t0,DBWo.\J y.ޭTU+Cb) Tں|ɻU*ΪqE!RڡEa#('NgdJĉjmIÃ`ُ1q^}+uGS>'Q6G9l\\뇪U O%ʊ1%WݡZYzH$៼+h֒%Kw/é09KtD``8XGc.9"3&"qm]-llwA,W_"dž3l8K{ 5EB($Z),n뽴,yΒ#HDB%g(nذA0 DaH$U~(a*'Ϊy!L*OujuxxxgI̦g[:lݺU笱LC`K8k؛u?'#&'g3wθ5&`,ULvYJB/VS<& S ipM}H*Uxcf­[PV-gqC(qVm޽yw%V<]}􂡵]g`L 0Uk@v= NY \KX?!1cq6{1./`q6/: 0&@0sVY`q6%KdQ;wRݺuRĖ~{{{o^"R*R>RWZ%G:ۢZ-)[z%^%qV8K3:aĉ"l\<+KqkkvРAsVʆv'KR,^777qp.7߈ߔƨ|L 0&5>gM% 8km\?`L 0KYչjv#yT<>0&% 8kI\.X.3`L 0& 3}\*uҔ_=buuiZ,G>^sԚȋmKwwwZL.ª%a9U8k\)`L [|\zp>xa~ݗg[T/\;_F}MccyL 0&#$9 Zz%!mO]T1:m BtlvxOL 0&{;SCWfl@74.^9PŶLt2 0R\0ɮV۴O.@߭`(`ZIΝ 8g`L KYg͵.`L $?K;gս8wMso*yOc)Z 65SʘYP6`Ĕ軰AtsDvH#8;-ԛS(??;8+'&`LZXeqZ2&#r8 d[>-Z]1tpSx=:%3b@!?wN!CBKm)RWM [A[Kw_} D rBGi==nh-0 /[gK0[ǟS7;8+'&`LZXeqZ2&#r8r WؗձX.Lو$Z];&*5[A+0ejkaKaLu'Dۼ^(m<&Dt^M!9/+w5)3 f<?,ʍ?^8 ~ylQQݢVzpo*w (SW$% ^;fk¤ / yiY@1_PgqV܇emZ`L 0B W#BiC7W@0gOTnCUF0,1^ŸPY*Φ9b; Zmgbf;)th83 ˔\5xNm]@~JuzC~źb,Z:<[ eWDۥc]?5=ާ< +5aټ?M˄ٙdqYX`L lq d7,ZlFb({c}^Mu8?\n ,ξ+ N^ք4֬Xe8'](L"HߵE;(d_hKlFq, vsqjl.xZ`qbb("UP?81/vVP<$]ZgY5ɘrXf^;a2|Yl}mQD=ƪ+;VI\0&+z{":1>M9i}\JjM[s'T2{yZ ByOv{Fyxaycȑ& 6 +V{ʶaw`(3PiØ@mH {r6+1߬/V+h?9׆J ri<BW!~DRѵBX!m,c2wKNftToFǠt:.q̳ܜ{XUUKƜĔZ͈1lGuӹpg)P㛏c0^z4To<,jFf:qr{7A󳨉Z8K1X|n3;/[H%|Zz웮*eYiD&5agÎ'O1Eju4*^nk(-\KkmZY00 NDL|~b~-2E50K`)TqZc*-c-S8>HŒ[p6.Bn ۱z'81dl'K}ggW~yrY*yx.^^SCb. fg;M2Ԭdu%]QqshfNَͳ=%ynR{bqCqI+6{&qJ*t-k8nJ޴ź}|t;ͼ ]5}\VÎ̏!R&{$J6lj6 ֢i@|qGwCqV޴^AjX厠(g7)ZKCFRqV:Hm%jQ-c O␔.%ٍJC3w'&chy$>Uu,J8[ ghE1/vXx,LU(](Ï-ƭDZ^J,N:oRVRYcsAs$| v Ƥ=fWB~³gcw\|_lvH^@jL :Yj)5`RgQUՇە]/tu)Wڭ8KqhN:s^5,{Y[',k4#.Biؤ 'ڰ8gh},_..gMѰXq'§ˮB:q6#а%lG**qV+/o4))XS8&-}$ؤ:!pʩͷ%mo|ǾÝnRZgٿ9`PIUC}KIU>bqH?iy 8K BoFUyEnÔzFAE*gܔSA0]ʈ[‘e ԧhü:/1ےIT8k5kguH"ϵaSBG⡜~{+Hx~vN$9^_tBa_ztΩ5vpgMͿDݓPX4,^X&&M@j'.dL$,쏪>ۂsTYpUzQm* !\֥/Ma"1bYqlc&T%o*Xmww3kſ7)ɳZqhV;'nJWԩPKg)./qJދKDp%G.rRu_6L4 WŊzJыoM-s4Mk5/m$<-,W:xdǺj :jpQta"TxZñYC2kT@ ϚJt<9wNdTV5. j"Ct¦9Ch$\ oY**qΤkܽ0?}GtIrR)]ҲlہgBScӼ}TRL3&\ɏn_P<1LkF6 CF]Ai_ǖi<ŨK,"T.P .psƸnb9(zn=҇!uW6g?4ϫ(Sf^#mpp 9g@/uM~qwS/1\4(VE40LvNN-T!HŐK,ξcKvgwj@*bq^R;͜;]]oO"/bIiQ  >4@XsVjq l4O~WDdgj6ӏbTӡ';w &$'*^rOFmGzm+qVU$`V(igDO+!yO]O0(*YƕWm EiO, ]_t]Qؿ+{;ȒvoVվ8t-87$ʅ5<>H;>(ѤV|D<E0];9Ph4 D;F bJD-86bADOTzocc'zfԎiGrdx7/RBҤsV9a@66虂BnJ( wm8wдNgu}6.ǜ,AlN={%`EqMNo7M?[c2$¤/pC@aX">S[I͙=h G!d҉DɆSP꿩,'T.X\|=؋# IDATßV^..RcEڿBuu:&Ml_C7z 򄤸tΪK;Nf -J=ʷDuEL.BM{KBG/^IL ]Q?5qO'1'ǖC]ZY;qF2DIݪTu@b|R(>Ѓ=AF`?0f_qܚ=Vg帓WvaW9q†,k0B:Oy%Z G"H0FeŜ5A.AP.3b;:kVb>eCtqݲ*!C蠿Iq V_EwK؎taz! q3\?xR9W֕1jk4\8kc-%qVZ8sI,$8Z:Ar`kc߅B0*J_%y&>JY|BS"hW aΓe J8M ;VxK!NT`S]qD9k(:4k 1d;NK̔:#vL iͳ4ѡҏrJ⬒=҇ [ڠZ3cdRgRwX5 gfi 8k}g36lZBH"w؇1ZGd0I_u"p4Kde5&Xk+аxU@}LHvLZ7;2fXUk WW)/K0N+&QTH 6XkIߣAyQ QXIH]'’.b/ 9aiOqWqhѶL+XR *RA_~o;EY:xSV맛]E8kʒQq]tƄKVڅ32!v hEY QV vمӈlz=piSys6gH̥4CÑvmwUrZ)/^5Ow{L #)8{ {#F_ԧ[iscLL*ʙoMYW2+<9N1(Py:zNܺ{}P؏Qǖ^& p|r6^C:nÞYpYOY<[qf@[ /*eU>{Er'n漸f昭&ug]2|YUUGڢWE%܅c~q.=Cչ)`$Ŝ8wo=%?a{ϫ@0g7ݡ T*~?L~{hK.7OKdHۏc@KoRh)òčtB-:#@Jq(h8K!H%UfYCʭBDFE-؀šQ5hPxR1 kxp!` =^c$K:ti"~ɕgŵdEX clȇ׺N&QU$q~KA~۔'< s &g@7u>/LN#?7!--R[ ; !?C T<Ï>*]dsrk܂iܺ&JkurړyZr(g?ql}Y醯k¤҃xVeż[ͼ&䥱Z6LJL>?JB[ii+I}ϨCsrƸ,!"X8/gc"o9aP!`-9~:0L'nZ\%ludGF9Վ%udk\1b;`q/g[`q6W{gs5;֝Ok,-qd8[+K7|ilvl-)3`,β 0&`L8,!*xx Rr w}qpE5zs O\':7u?Dӱ`dY8-v5;6jKe[Jۺ@1#Yq95H?yiy^kF4[^3RQ^, -/Ē͊mSKXM%82=Kʆ..Gڢu}`5`;i"`hO,jƙ@Z,β8#3^g0 &ogx}@ɢw "y3m~g@L奱n ,jaf qVK 0&șX͙ƽb,β8[Yf.]"xEMWZMi?"h8fCQ5qJ/hYЌ,-/1Kc5XŒY-8`L 0&`+HC(jcaϦ8yXeq6Ƚ8qO0TnO.Gg[5LfuJ@Uo ,7/1Kc5XŒY-8`L 0&lܞi Z~ pˇ¡xlčg d[g!m,YlakS=H~zy_s˜fp4,-cQ8]휱/vb۽.f%cş!GHilq~OSGڡu:h},ʻCt2sԣh{nGs~#.( ꏑǖʉg4[ѷA3DD{Eev6L7bM'՞ڦRe}!Vm^6LwU+#N=|eaY_cW&澫fe ǔޗqh]kp2Z8kq^&`L $\;s z q FpJ7.՝No_;pc6Fu˫ŏ@I]Pm(O8[@q|R#R%l\d:ƺ6zNGqGw4>b܉eQqc*t<:h/5qv} ⠎Q/zCQ^ r{7mR?Lc33òJ숍 6G1 TR)m*qS HLn9ȟ1,osc19gئ5ٌ9u9׮[̟L%32V~i<m{OuT§U:ǾKzSgMص5H&1JD$='c8+mRlFp2VYeBg'=hq8'&S B¾h >r7gΝs5q6r| ^z?`k0]?ڢl(&/_ba?lrE8GAwG05ǜJlV~daٍ0x DUr~tq:7jkfp/ 1jyr_$Vwѧ 1=W .^vTYJKE^ޓXx.;Dyx|8)8$"xL ] iPPv=a;bS}+ n{ChbB> +1(g~ݏЧBk.g;4A2vo +QuF@OGy5Z˜ɇ?O;v6ԸS)ڗi$ֆ Wwt.ytM2*M_)XgkH" I$$%EQTV*J-)[i~hZҖZ- b%!A }sͽ;w$ʝ9}ϙg5^L q?/w1(ٿD|Vub &Ii9KdGޘ,@6X=,?[b,'AIKkC|x[-r|uw&i6&GcPta$n#g=n^c$RK~~ y;6W4Y[k cD\<0rv8!i$࣮#r֐kƥ\BԹ3ӱ+ cnh N"godeNN6v;IǚlûX<3FxAxWŌ㫌"g;Vgk La8| 9&ΕSLV";9{fh殘SK 1,es҇IKp]Li*\ih5>q<̻;[MO5%*W7m?@%H˹Ц˱>~RZ{jW6ecJͺ/m~Xu_uN{/uW{Q#5I;)9t@-q{Vb%{9Kx)b5qYGsx\xkг ?#P >rp2}i^ٷQ.>Ss2N|.(j? ׿gOcYBy2NrAKd. Z,ԭqoł䁘=6E0l򞊰8̞^??$_i1!.>;æbt;ҷF`T;Q,_at8 ~E `tF"zA8;Ƙ'qzwnv3ʮH=q oya#Y v6}WYYBMyeE/gƁ4+h:aٿy|.ܽYXjWv/Ul`e=yDO}*rV2`Wھttjf-,e_F`OA 8ЩκMADf#g/Ě#ј|?_K՜k+?*T<;A-?V*0};䱘Us 7c( lDzpmL,ݷl=ǚXP>;xҜU"kVi_7d[g%H_R6>i}l?14r#i`~J}4p ќ%Zk_l4Bs#1M<j|"_ͮ ZYz쿴n|{/E0,S!{#ӨQ,!gZrV>~)StoQN9Ks>aFi>eu 6 )*Ⳁ7j皮T8~{Gj⎓E$g8_P!o9A?`9E:qImJVHRՙQ-Czqo"t:O rF4,׳'gW!td !G'EB*ņ 24Hfmvt$B0l,X!G/7+6kjF"46ȰXDN@PzGa@x04u+"$Ts֍'_c\>|-rg13,l# hy+}9Kہ5dwY"(L$&٣\l`]"2.hY^)l֠;#.}I$}f&gcu4L43d %bDP3PA%2g)Pn_ R5l bbVQxIX_?:ͤw[NQ*F,YO[uTw%gu IWcj> qA0abrV5ʞs dBW] lw9+8Y1!IF1B&e "]?o F2Vce|ʍ!K ĄɜnWDzMn*#1]Wh5>Z(Ӟ2b)ӞA;>)bHE4j49+Ele ^ ~E;ƛ[g29KcSw.3"9rVp ;5(W͚v6{>rV|Oѕ ҷprV՜#|{DL-u}'ģzyg"1K^^M;juD-\㋲hIYgN& Ì"]G9;Ixt!EKn.Ƅe3g\ưU[Iaݑ5n(fybptY1{ُ$PwQA0kax7]a#k1n-,|b)V(ry~1Eжv" FGfӂ.r;~}Kc+0/H@VEⱐp6ԏ% ۋiiCf`RwZ8~O IDATT_Z_x^'F {#AΊ_蟯 !hFY~;YZ go߿ʌ}?IW2ұ@{̲U~9Kٱyya5{9F)^=|1QhQeU(Vl-wJu\A0$i_D~y'1akgM7 9K3rcY}Cj :JU&rVuŘǠF񉣵=WAT0JcrSFpkw_M >l8^rV}J%Gժ\]vj>˜%+`~qlgC ?]AN"Kl+X3]`jl094ȷrxNI]j-Y22yZv>^p5yژ.9Wq04w`LL~*~1+XasYgwj<EtR& wF4uԤ)+,:Y";?u6C@pt2XDsvB"$sc$uweֆŅ0=" $kE$9K! kW!q=1{*l`3Rx6_ gF@c }ſDk#bYW['3~|I_H2`H FdŃލYZU>YWrNSER6i69K`K~eQ̴V "kFGZEGM,4#<~Y…2 h;rbf2(q:]ZDsVM,9۳q|dwM<;- ՜N '&Q%~Z!{' KLs֘Y5ǭwRV~=:nn9t`K޶v9Kp: :h.94(4k):8Xbf !gQ6>ŶQf1ٳ!TK 1,en6&.lLi6nvΌ4u !5ݿnG>!<#[܄q>0Fs//G51;l],Pӡ;4.}g[{#rLYՐ4vxބiJ9ùzrܽfK2լ!JsE϶xʠ*jN?)+HNp'=R(#~ yOO߹Š|pG򲁮 Y;AE }IE5ƞy+mcD.5]}G0&%PE9F#.<]R[X跱~}n"m]sa^ $CP+L>!-'Z\/Z/O:Е??EĶ [ս9{9#Fÿ'v; {޺U7U*v?LeYNJ)jYm쾫KRGM_ItI!K5Gk;IFDΪY 89+$9KF~46{\iM}F$L\b(YY䫾gS4%h=cg3]I4'6$%IZ=JΚŠZҔ}Kb!g<> R\~R⫔Hܾw$ V`n8;5:l#"; UX>oΞ9lIR,6CL+]9Lnrzr3؎ g 6N0Vs†ʜ:V""ɇA/[4RQ[IVV@.][9 Hֈ52cx#ϙjF]4Hֿj=&BFfąZ3ҊIy)>+8>יIЖuvkWvKчu:ʊiGrR{);)>h\p}:qT&< 2J?öN8$NgjVKa3d–reN(Ƀvהur֔C(+:,KܬeC>fKOcrq.oJLֆvvh+J4y%ev4>775dR+"ϧ.+gk7_5|Sl?g’KQ5+h#nRk-~c >wPNݏUլ2220W>EE-܃wcot~y5Zmop@E 9K <q^uӿqrp 8>^|d+(hmUw. 4z,J+.i$9^+:MЋ3itOK};z(GoC5*!i*.n?o읃OHѵw7 g]z /'5fȼ6u-HQ$."%l  6=Wbr:.5'C΋w@ Xv\I[-b"Y{!od{=htؖ"gܖ{">ӗJ$yy gM{Yxۧ7&w`~\3Tl}慾x,M̠yuHgqR&w( m<> )#gim-$wl[}_]_tLNC ǿ#~ګ4Wl{bS; "Fs[',%Dcل8-pFIIJUY1Myt-*'g#Ҟ}m_Xi/d*4*拁u;a}Hh劜Sh8 $@1ܷؽ"*b ~Noy¬!C4IHڦJ)Ixm&D߈GCM:M%ҳz4(` (Ks[Y[.") <~̶cύ_v"뚤+tBxߟݢ%=HGIy\:.H;+z>Ξx"FΊ -j)L_799[)qOT|$n_ƯeĉjQ¼l9kʼ"rVj|bOwNȍG$*' $XDΒB=ؙ'*9[jڻUr_ffCM}GE~ G)- -{3q@YFr9+v?i ڱJat'guBqpxfiGBї NE,_ɒ[G9VaTJ'i!Eps̖#mY5QePX>rtZk-0Ư+pKM!g);8P}{}彬XwIW/Ie\0&z,z ]?.Ae{,{ ü3Y*Ÿ6Ɣ7%1KIEj]&Mh2S/-L@𫯋'>j2K rYplN>[{抜-4W(f8"'gMyr4prƾ4iTnYs8@QNoy¬ q1m_I2|jbcIԗ¶aՅZ:̴uNS1hQ$2^ʝ>hss+){m*T;iiKK}_Y83+>?<5yȺLks,gJYynv1k_lWETqVԱ(JsEΖ|(H>r[;5O-!YSm~>G20 G#p̌5(hIbc(u~8ЬkXa0*["@zDlkj3j>1q飝Ne^= 9'~٬S´MY+sa@89k*r'g˵9G#Œ_8"/JΚE\]L/oV&p1VS!s&ڥUt /dΚGKCVrv\r#ɒl*I<>[3PQ0NR^99kaX)os].ID%'gq7'9;зHL.'Z<DJ3֮h惯u9N- ڼ{s [},ye Z|qr,G+[!bu\^99B]ͥv0Ǜ%99lم7mqco¶CؕvREäΣY*ӳ-?,zg[|xg'g zFpprXé\w^RI;ْAN93g/K{!|9= ý3Z6P HKT ۽kh^KAe1>/߻w,D`iEG&>89[|kqy#889[cRGPRIْAN9Yچ+4oGpJ7=IZ㾔9 :Ղ_ pSJ g}֕{;'-}_ǹ6š;U-git?Ng^DjN]b{⺆.!kG0/7PU=ۢi(x\zJWc؞YHZ#gye?$ntӾZ<_5>Y:]zMnLSXsq'ҎC0|w4gr}cu tm(y˻>)4CF%{&^l:d.ݸ"g=1ʷ78ՂUEdĪ sAP O.t i,u~.*~8oKZ\+9L^dɝ^-8s!\H~P/N,mݙt PeI͜/js]kKVhVӏ:Y[\אz_g}}XCԴwK;F$ }Gw1HNgYJPKr VQCUsWoLo?+TTE*SJH7C$\_XLUa_pB}p8G#`pr2­pL%gt䡁SM,:'Rk/Ɛ]/@Bء55n[1F􂇽+\k&Qk9Kta_)E;8SB@tIM_cano8q'>Ӟ٨4V T/W1į@4t35%2WN;C8?Zi2g;h7YWzFYk4͙?Y&>faJ~SʜqK @ #}Rc"r6"p6^]q7/_'>Ř!$2ЮZc8|{/sd Y,:^_{q7DL.q.+_\dc^<>;7|^'t5pSraI}Ka\zmSK*_ݹCYkߍx\3n=d$7[钳yo] h< kS.PjŻUl6aG׬4vLJ놜b*V¯!`L<\pDچ;:_ak4ͩ^PaR9|x[ٹorkp]*jq?m>jU9+K} u;!;!V_؁ {g{ڡ-pryG#089kaL!g:NYq|,0 #~^Yհ|x)naQ%,Uy|5\ zþ*f_g< }w|72J?9K׫=z¨P6_ykv@7. FhWX]XOe؝#b㈈?c1|l~tWen3~'<_fXÎ D'1#p$#g]<IJpmaaflz$1%/M㦱o3.#)r>|:i6%Ǡr+mg5;VKu:Ӹ`mU.fپ !,Yͫzcz*ڰؑ?vɱp-'F-y]YfWb%k蒳jbT?9,L813Ym g\-/*Hn9#;>; Y1WeQvnSݟ*m@pukL/w1S- g[pi4>!NzJ/ǤHF4|Um0T!Id< ^c#g+;NfbyDO}#0ik/eO}rP-6t},j>A/r԰*)b vQR@=bf>ӜSJNZ~&󫸉Y5lZ5 ߜGoÂ\֝ OjHV!)p,E97t:5p䰔EΝȠw0hg,X lmyuLT;jơ9+lRZ#zSQF)kz%`-Wq Y5פc(_`8{H21AW+Wot'-b qACΊvQ!RRrX>ϕ87?O/$YL*f`BsLlxHG#gq@%,-&LYk9+/eqC"^ou~4}$W3[Ŷ7to}E7փ {d a9;^ٵڶ%a}X_UٹȒ54+i.NnjrVi-lɓwU?qbt%2Gztku:d9PjUj\ex7K#b2$MEXr;~aQ4ZŚ2X)Olj3x>)am[Ѧ3澲t0vs]VV{\\羀B,??[2CNRH_KnGj`F#@/$Bkd7F#[<'2Z_ŃpKginqr4yj1K@[ҢҎk ʶJe<^XԆW;bEgIW }zwesf+ezع2Ra?qn~zY# /eD#5];ʐΪ;~BE2u>j2HxŶҶxk{IJ}Vi&gGfrȮ+Id[>@g2l">Y`'`*rO9> Ӗ;|>蒳JcW)rVT>`P/ŸpCTܲ-y&QpK܈9FBP.EijۼrVb ]bټ$oI,)֥0GԒ.9Kρu;nn6fXͶ\leKΒ}:֯/_*77~jWvʀ7v#gi)ieqZ٩/.l z}ʣhԤ2"1VB[j9+ʭij~^׼xU"gRY *Ƕ__ޏ>^'>u89+5C fW$(;4v\ТjU,D,lJ6H2'Ѻ*5/c}E27x4KJ#T]k'gG|QcYs!W\~8~Y>ֲSq%8~cqL1%Y&e_4u5 'g3'9KS uO?^G–~QH[$xe Mcf;wMr='g%2pģE.6Ypimi'OOcn4vlkw?|V)TqsYd뿃FxTp+,_/^xX/ʛ%aez%^89[ޢ,49kAN<'gy\*F(Uu. DU N?9KW:õOqvoSDZKWU[GIw×2$&%P#7y:TzK#[%K8FGhL= 7c`NјrdsR%ژ FeJeW=%i ~/~%{}SeȐ]$xI -<MN~&F5>j}̠-^"THZluz1՘_JǑF[>=*M:S{Ôأ^>]PwD_Ow@)Di:&yNΖT~xǤdSPr^46{\P*HOY\;,iS}3xѡ`#ҝH?SYc>~P@WkjeȐi +$z63M2\攃@msrkG޷CcYSwiZ]#кx`YT?YZO%+K5`1RKVv $M-82W15ǐ{7'g]ODe?f-um.8ޜ-YyO$9KV}xz{ez\= ?/^nAiK5%rrjPaXu=Vݗûx˷d`{_sY},ߤ.]K<ʢYS}3[lrU/wM dLrx~߹*GHwdr$q,o|&>i1iHS _`qN@lz"Rs2$*}y۷7>>UlF'J~ѳ]DK]_w@6p%i'ObLh2};ߴe~x -aȹHR~ϟWkpDKkDfUrݦ9KD۾ѡBq~pufҐo6|/cmOڎ/&ߺct<8ArT9KccJW>\#g$"mF ?ʌ#+E^9Kd l^7fۗpYF*Rƴn0#ɯUl$ ŊH/av,ˑ}f;}АGbf$t.e$N]ºY #({zO/-7%ǰ2Rs-"WΡg] >eZkCyT׏}X*9!Q6lù RʀTeI+e꒳RC~Z/n>Ȕ$g HEV"IN,Lo#g7d|˜L=G_R#Ne?JH-לՇL#2^>8G#p""H:5lJ%2OU3}#M9K/DQ{ǯ/59;Ի+ND`(ۉHGY"Ipoo\欩!r2)srs,BXwEg"5I;P }J"(ÒYO:Vk4'c<-9Cq5Yܨp8c\d,]j?m^]LsKA[}kj-gh\LER!]\LR'I +brV.) ^}YS淀ْ2Y\ѮZ-“d!9~X%g'13Er#g;ĬV0b8`8x$WCwՊ_ˆֱYZgJX{ YoJPs6Ǣ(l4dMCo7\sc`v4CwoX0!6Ik1^}bk&xAP~Gq$ r8G#(prK/[dɊ#?G-,YyI3puNT}`[цmӦlY-GaLb4ZԐo:TljM0aPfؚrގ5@kw?Zv:˒$΅iYxn,9KJU+cyD ;94g[tLCj ʮzdy9Q6SEDX>}W\JxA߿H$Ttyt&F<ˊ'>ytqy/ %0&ݝS [C gNYR@RקHq+/)"5NGUٝR돚 b[Ⳁ؜|9kNX"_ '혐{Jř+k# K8邿Ө/V$e+lHmoH\4/aAR-7MI HEj=Tj] K=CrҐk8{x>Ӑ8Ƅ !ԐjvsaYX,"99.~S ͜5c(nneq#~< ++L2=!|EVc QԹFsKDU&JA@p9Yҩ tm*D5Q?pm7Oc͸ XC Ш>".m_Irv# ^|oord (xo!gS13p$jWmoX"hG D "OELק@XyR#mav-b L΂Bn&Z+ ,E%RHvUX' 9h9?eĝ2 a\KW}NiR"h =0#Em)CжZc&GAqp%P&!}r~BHr u}q5`Nr, aE;O÷g6bC,|ɗ}=۳QiǙ4ώ$K '+?N6y-ɵQ)c?ģ bt=q)[cS_w9QI NܾhuCjP{J}=89G5֞^^6̄MW.[p<  Ϫ!gřɈZSgx )6Dy.8{ȑ!8y-Wd#,nCW՞1>Ё a0)jknQpr(I'g-ܔbCmn-iC"P~,TǗ#89+멒̜إ=O02 QᠲЌ!tmh:}7Re(֦J HV&U3/jPRwLYғL^;G{czSl^>;æbt;2Ɯ=1>Ep852Ka-.,lr'g˅ bx"pk{y|se䬬-U/Zf۹ D:@SifNrV5q_ ?CK½kJx1_).r֔#^ 9+hX!gt[6:O0?9rv9uE4g=W le>^pq34wT$9!ΎłLÀs  $ [ Iڣ> IDATN'KDn!prNΖVYݽ;p<jo*gBRnMpz"vMW@rW :"dzJ ڼ+zM񗡾"b^)6{x> ~ԇUFF -}#ݎ[Ȇ/F %g )Mش= ɹa#C9` Y@-&p [1{oو^؄n ;DQlv7'gy89[ Hڱ}nMiygv'ge6g%3ski顾 RaWqVFM&ߟ݌YLNo4u^4/c}ERK<Nj%z|dL2ƮW⵪ldfE*8;#f`[d q $UȜƂh-̜"g)v1faVlr| JVDv~ӊZ@OU~MM꺓/ÉIFDQZY#g=y%ndE(gŻ\sM8FX־,S ,[7#HǨMZY:FCv%#+D!F!>K;:^۞r;?28F)L=Ty>'ge4'9K;yeD+֜!~u^əQӨSiꐳ>e36!!B1QQgrvs,=_ST%?DM{W3DY"f5 {SsYҝUrVQAp?ԑk-qoUr600 Ma;0dfcq v*,Grn`/,9g x`EC(s6"p6^]q7/_'cO;h7J8u NGJMIM_cݕe΍MsVÞpu1?wvN`.뛶&Ϧ5q&߿'$q?mY<4|Y$g 1xKT{Z4/?+2wE'NP oʎ5³.v&&n<9-8[۽:F c%;F~>Au5*Y[㵠hTV#gl~biku}J6<'^kԬ;_mUΞ=Ou(_5#>P۳W}Ҳ*ɐ72q''Ν؎ 'g.)\Upn dy+^\+9^*{e޹ԠďcP#g (4d!}7cX|rNH'%a~g@y&g6~[a։5 ¾'1#p$#g+W;MeΈyձ?^k 0vm%NE0;^9K[}bU۹02,O"hU1*88`uiggy@Β_'o_c,m_cпNfW˃'⳸p&3 oy_ykv`cr4@7.{%|!>91\I8|Ϧ5q_,kƖ,3' 4Y=j ZUaocJ".܌Mѩ^8K1-r6=Oծ Sq ~wnc-٤9:7lgpz*>|;Y%aο0SwTwv2|{h4^MZs{!1azl\%D;1"?FFIvfpzեvprV YY$b\M-p8!P䬥֞kGctwopjV-reN Vv1Wψs,IYʪ}vkشJ=Lk9':,05⾤YI′ii;qDQ\9FYXP>;'gKԕҜښr?$8d]= Pvgob9xvk9lmkhЩ՛jJJ)K[M )sM 9ƖR~Y*9K}Ӯ8}*<<|9 /ǻ!3rvmPIVcV!Ⱦ!8)5.2w}6Ep#+ ; PXU>z7>q4g,B^mT"g$ÉkW0F'3UWsvX!oޕʽp:VvQ q٧pYٵys8G#`5 /~4G!PYʎ%ۗXFlMXV,!?۾٣\l`]"2.0reQgO~ߜs%ؗ2g)Bdf2rH@gr 89[ 潮]m$peJQ{p.X_ůӌvcL[٦V!1y;qN<%rVi2gMkjY5˚XY1y+4?ƱK Xf{!/0rLDNZSz\ 9L<6=YwcݎL[r*¶JQAaFT_U]hY?gOn6&.lLi6nvΌbDsvNg^A#ӏ`T~hL}YZyМucwb5g\P̜u;"JѸJ.Us>_}SV.?{Y+ fԺ#gUNꅊz!p8G#Pls(γAhް`g6 䬣>4=n_w1heǒĿ`4ꍂ"H~gHݶl_-RB4tzq'A6\ޏ>^0.kvXF,ΕlNw߈%mΏ/e]Yh停%? =j»cu X:> U+9L&ՑHyu=֯/(:됝c0=c*@od? -]r֘FCILqzݍjl)^Yes$RB+t[q rsپz6k |U|ǘ]hUΞBJ0mW"g ޹EYtq xAE/ *^0%/V%Zb^J*)%RJBL2J+ȴRS4 *xPPA=gliY,pyzvޙ393/{jv/ghYW [>` '@_#I% /X>R+?Z1uz{8ux`qVWr|`qTf0$g IM{'h\3@Q1t4jg"~p{P$to}д-z6( *CLZԒU4p:v g$IWb8=&ZǾڷYʕ2x@YNٚ>l,Jut&@9h䎕ZOgCBg"Rjd떾O<DpY)ޠu쉑N}šy 'q0|a[}ܰjczfqVoL_,β+t,d`qV %t$YJeA n_?7N8Ѧu< '4d0 %nzS f C*Exz͓6WE~#/Fm\do+mɸ*R8[fmUFY@ٺ09BmLX1p$h4Z2`Yw$RkM :#LDŕ#ha/!:9W%t^M;atrlvd*" Qw A߽q{L8\e}\T3Jrm|VSڴS4u%smQl}[o8+H@[q1&`LV|g'~ =gKJJTRR^J2;g逑oG#Kk\4UTV"MqR ;E ̎,xS]ǩ[-MȵS~ͻbX#-]umheThU!1hEܺo('Za UgLȋh^~׋m[8>|ƫύ)^lմ_S}C|vM{=\ST i ~ =n Tg:w`L g+͉>^]YnVxܩZa; c,++e]vfZ[ k|=84 /_&t];),)qCoWxq/nƋ#q CnJmbN[x;bqV˝BW!1hISѸ%4b@ .ݹp. ҲRyNoAfx¹?%|-}u/cv=."g' "ɟo3[q(L*g"/<gw&tcv bPD-_O§F턟⭣_^}wzL|VPr_&S5#)m }\VUިNT7ݛtq"Ewb#3yʫ|8'_^L!=Zp(^-FJnn|tru7'uª=Y-ox\v,֮ah`L 0&P,Ł'9m#adWj9kho(e'{yp_ל$jQنxs8^ƴ "󈻞n D,L)z7hg%# xN[GN=!}{~b $q ;3Jgeڥ3$Zk*~I; ?סv\9ТVNnF B n 7(~ RogiG!s ; ]kPt?$RB"s;pizMoD.zMKE/ Q!HE^J󮈴ї_v%oz]{Ѹ1Y[i]8[}\&ϫ1FUl&.Jz-,|odSogU~&mlZY]Mۿ*݋Ņ>xsǺ'iF5=Pu"jåh9r&MT5wHl9`L 0&JY㋳"0 W$@QY=SDR8UiE8!ԈԖEP CZy3yƘydbxrG1Zb @ϗWQsM_e"Ž^jDaU|F&ξys!OK0 !Β`OBj]Qd- >e\/O >O{MA͋"&=V(QԶu||*ZT#qQw l-ޓNvg4בxЃT3ݞ¥@Y[bù+*r697MǕ/sei ƵXw`("ծ |bY'L{_{1! 3 |} Cd,1W)Y6ygŵ@&L 0&`L@ gcYZa!Bѫ+~GH+ٙ]O"b!r>;D~N ?Pu3_Yt d cn[R~PA5T4\|!޿ݥUU|F&R4- īW!Bun*R,O܌"淩P }nWb$C]YGS nD?e/ۢ8km^+ثٕ#q6uPT8K 7j lէ("rKfD^MaqVWKge~ZdpꏎYpS)g@.bU>ʺ)(g3ESYPz8{)Y\5ggW0r9E0E IDAT`L 0X58K_?3"OHGӥQ\Z⬞6VUyqv@n}$M].κ;Q+f=gwj~dIoKzMgwg)?]܋ֈI/9_eE8E9fi>血+[)znc1H$]IؖH~y#amQ_pj\Hd;Du2qP7ӘV?+x w=QRL~7(/J(ۋ)/uH{4=dZ6hP/0B&&ݺt]ɽ>Avhz@u4 =mFkYj#gk`L 0}`qZקѶQKСG-{;B0{ر*Kul.OgӎB@<)pY b.p_Ax©Z4h8}|Ыt X}s `BcJs%}>ڐb1밟6n8{ %,;Ru6D~6t.Yfg<(`L 0 8[3gW~{H@ъlfR)Z&5ygܸ^mYB;vpCaI~KxZľ޷9rV[LL 0&PO٪V\\xc<g% uQf7(-+b1Yʼϵ!S;޷Y5UeL*qV7&=H6 0&`ʏlONoK\|/vWqIYʹ;©֥lҫ4;ì+>cJ3-㕙kGxzfqm2yRYm9@&`L /,Vt euN~*\\4nvxeR CoM5¬U=K|UkزKwᕃHq >Đ6lQaxo4Q`vEߖY>VW3gy{&`L$8[y)R[.ɿ|C൮Oә'jϫƏ6][fX5aӘ`L 0`q,p6 8@va;2-MlEa@U$T}ƴ掭N\:+Ymgk\&BY6 0&V,GIΙ`L 0`q֠xJ:<.&`L@,β8p]&`L@7)cL`q< 0&',"`L 0ٌXl .TEK%,Gx`$|famGO򃯋MՈTǠRk\MLjnvlݜw5`L 0&P,`L 0&F|G#2G~f*ҋ<1+lqv'C1(@rlɄgBwSV .: Jgpvڊ*]ڲeбc*r ^uL0cƌyf͛hܸ1'iРv"`L 0&P8kq;ryfqaLnpsWN!4H#;4" Lhԭgamg8ofѮE΃epH@)W`%"ggefl 9ybԔ)u~ fG!2:r-1  6{*sZ4BaGbv=abӊ9S@f†H]1"L$! >蕏`K:uы1H{c|x;dT7 ~EΪ~'k|Gڊ??L8$89s&d\ݺuraL 0&*,^+3᧢q>;"`L@h`^0S%;YiP~M%!-0:Ċ3w 8Ocl\TU!"k;BCR02<ep?7 GxBaf\X9qۥ^ _&X .|1b<7s"|e\؉y, =Ko:}3K2 IưʍCXbc>/C6d~MWM*}IIIxw/cذaE>3ܹsAѫW/aԨQ8s .\={ [l<8;;cʔ)ҥKx7caڴimݺƼyp%l=z4TnƍSy;`L`qְՂl<1 KꨇPEhmӬR;oiP\$faloXEf֞JI Tq x&!8a>q ϥL Cp/+-)K(FΆb\x C6DR+F!(^87,ޙ 8YM(҉p]xG 0K|aBU=^<5ug}||pڶm[۰Hmڴ)/^SNaxgE*YZlA qҥK+0ݳg~٢NPUfŋU-lN1&X58Ao\L@WxMآgiiʎGVabp&74VC[yaJޡ~ yՆʯg)sdl 8t /%cU"zFqg(!|T60C0 Ahg:.B EDD,/~BtH$C18"E~q`xA4B")q,/e ~F$!+Bv}g-_~knpg(֑#G_E~WZZ^x;wY,X@D2|X?7"$$ݻwW LFJoum,f*`L hKd_?2mъ!=?Kk" qgJ- b@$uXfu쉑N}Ev$@+ WRJUk_ !9*faw xW֓,E)P)4AqTU+$u7E٢ĵ A+TL`EXBT.!/*,'κŅ#xG3V(GPWDΪM+kgǏc B2qVw3f̀~?,**J5w,,,@(u|ٻw/VZ%"t) VY"Cm[SZ)60Was`L j,V^}!E?EK-I8w*qVau nu{2= 7t=_̰ATe ]^;B@~V8؛4rG\%@8`ѡ_;tY\D "CFU免[` F9#arOGT;8Û!62>BoG>u;YqQwC@/ԉdYXau ;6o\o, C+z>ٛԍW]5}(өSbĈ"… EYYT 0f̘ |,,&rʋtAqq1~ ǎCdd$7n\NR̚5KDR[YtE\*FYT%5\\eL 0&P 8k8qZV&jr [-l-mvqf*BfAHм^6Ga}>ONE#PS׺ƙJַW⇋Jۓ]u/=cjI窌:e}{:D$FJfe>1HVqe&H@Yd{! 7{gITޠY絫OVU op?2Xº#l">)H$RZX'F,ԶqQ y]oOO+gHϳD3>n68 q(wŨΈLHZ +ڎÅl#&c8٥V$ΰNˣQĥu8Hr{I+;&eqgsssARW)Qupp%Kp ORݻ\utt_|wyNNN#~װa Yv-v-Y=wVX-[o웄WUmӦd> `L 0&g+cW,B|3h>YZfI?⏫εe= |69)鰳TqElKGgwxͬմ3-Wڞ%`JZk}n=VkÈCj87h ̎L)i){6S?MNԆ6rݺMY X"7'!H>u{x&B@_, g֭ܯ֘|8W^5 _~%:XKTW ::"J}5j$kc-???6L 0&<g+@udͬS?Ǖà5ʱXTZ{^yVVl-`6k: m Dę_PVV`` K>4rAXpK>kte*e?_ޏ' s{7sQKO|+D˓~;X}f+e;=QPPr_&VExq lyW/pwZú4$X8CQç;bqPUqPllĵ{71*Q7h"֨Y=vpٛH\+[tjS'J],ޯJ*"5],Єop. "/Cqi']ܺ1B=oJfMXuc"PUqPL1ox+K@{;ڿS|]I?W1d(ݗMkhZRjr%lz>8`L 0&P 8kZ⬼HC"%FeLtkN;Vv@X4 &$ i cjI; "eͭټFξ1g"aoȁs01}!*^^q8įhW;;BPVY6|)ou)ULQ ILs+|@MםET.CJj'03G.ܲ;:9ՃyW֯8K/ER(۴ׅp\Ϭ9xdmiVYX*jߠuNU7\+ Z &U"ZD[~IU/94gqXTUF e%e%SH$м$d /t|D#[?] -`p?&m4?8S?<Բ{J?ں/iqJg)nxyDD4⧋{>1eB y#amQh٪YR3ǺG5[ih,0_ 8[`L H$,]UtG&RL䵜w$R&PNY휁׮va 8kXz-'l-``L 0& g^q1=ozd)=(:zw(i -1( GxW*{)[cܻ*~e)TW,''GG/.V0ƨlM6EuqYf_̓yV`i3'W빘:##<21Kpu)۔5ѲEJq~ut%xP=cvM՛]ٺ7*5lY .&~Yk$gkU2 c][lX/bqP|WK.dq8,>|~[cLxx©qQ㧘P (_gkd GYñ5fu45,)eesJvX`L X,ةcëى{GWՌ%IaÐw_Tժ[,BXxKgYPY/Ӳih]@3+;,3+(~r2nUsl Sؤ5^"gŨꛧ}Q’Lnk{/v-<韑Q84̃(-+kԘ6Icw]J8w`L 0ZG@TjSV(D-kS;uS$ݺ'E^Q>HT 'al{_\²uw?tm?Fę_V؝q Ϻ 5s(x;?V%A!CNb֡X#Dȱ #UXoUۓէ]kѵ>eW"ӴaJ#gdvfm||O]: _Ab>\ڇQmbyT c3qqbtmU [媩 _FՍQY=2l43Gѿ\k/e& .vhNzbar?VdޣiG<2l^:>< R٬jE.cCuI^&ױ'^4mύXX :MigBl< :="*FL Sw٪'W;'hDi7م8'$޺(Բ;&wzL<;w᧢E4R}v I fD* LZ S@u)Ugi9S<#xc0h;Uܝ6ǧf!dD3pnB8<ЄԃWBIi ) Nyдd 5 Zv5e8edg%#𶨢#/utp5|/Q >%_kq KLZ9VƧh9V%Β~5=9$"kzH.CDMVb\p gax!p1V8muL̔fo޿-">( S8}sOĤcmC #g6MJD҃Ϧ^IW ]9T!vҁĎѾOmyB9O.qVWbqV8-MX 0&=8AK JU8WzRTMCBB(\Ф-VQ"⵳6K++C:ٶF$Z6;߾ZA *$`m,fXD*9޸=xmhY'UHS_xW"rT1iwF Yb'>-p_O48g uz7sE&vl>֎*r]Ky(ZXJ^V7ǪYC=z B|%'5:(E쁏-\*[Zu6 k >-܅(9K⮟Ria@mNړ;ev8t4}.9D01v(E׳=KпEW91eh(v֍k>8=R?U~l!Kt΍u?!e{(j8+/VmHk1&`ay F'`(qVJY 5BkT(JF&~^7p>8>R{ Q }Q8+zTVEuIZ@0}];O [<҉!@85+w=' 1[V]?9uNQ`ml<$z5dzE1;m'ћ!ri!Bg⺰2QaG`)?~yqV"zhNI= ~ٮQ |3J[rJX[^SA=B('4SwUƢl )Ϊs⬶;E]S>YEAntC-_slEOdqVɿcL 0&T`q} @:Y(hQו,*97l ), 3=Ô} ;(7Tב"T;ԉjʾ3չ?0/$HyJ .6 Qw|Ă"HZ=SDwFB. tw.:qH>sNyvgyH/zc/J\)"]8KQϻ #?;İֽ8noia QTCYus.Cz%l(=NPvP'Ϊk[gNbn\OhyP)?~yqV"gK7 hu!zK$z"M*Oՠys3{;}6_ŹW*\jk8KcNg"ﮬt{ VT4! 9ӹ1ew<艅KEoUۆ*qDy6v ,DK:t%mM34ÔOקE7gUQH'ʵEv!`ɹ8aq4z%} "qg)wgcCx[5͝*/ILEr}7<׳KyJJ{cRұr}?_H"9n}0%,OGSG6fvyJD8).ѷ8KkfPih7ɋBηeQH9) sJ`Ws4'o^P*pΡ5হǣ͑:>I@6nŽDMtԺAx\)j~S*+|V]8QD0;~ c^gETHNyYe>PRS8i?I,Wv/roK<"V4%97M ҵq[^eCar/β!>."g)6jQAU5o2>8 9K}KgHAMzيlν3&P$@0ΑU-n (3}ZX*AdއO`zN?׶6k"wWyeVU^n(qVY9OrkؠVYDi U"!M{}"j5ߞ߅ .CA.!/v( *J8Kr`أ9x8;+~Z$J5Ϳ⡬=دg^;Q!ʑ"pJtۇS'^ NI("ԿLS_@Bɖy>lxU|DUEWwaml}S7޶QKtԝp9MIgɦ/ YQؓ;J-AB# I7/_tEu-ISjeԆҩO8!us.=E_i/Q EX6 ,Y%5=PP7^uH@nݿ-Ib$"/>o#9D,EExFq_<tpؙ̂,];`t+)* _!P@Uy(wq7*V5Eos2'm#7rΕ8[n⬦s&`%yKO>8SEϋU-,V _o/_AQ/+G/:4ŝϣm[Ջ܈Z7uo]|nZc|mgK{4i/^7/,)TEpuoxۇKӵS\~,V⬾cL 0&P5?ABʫꎶ*7lr@/z5ԣ,ꕪi5VLs"ߺ4fc k-m8.r odٚOcA@ۨ)4j,?&` (7닙ڴ6 ,W y Y+Uj.~6 Euq)f_̓yVg_}U\vMeVVVXn4hv0uT|7_RiWy}YY~Wܹׯ_ sQo^xaaaOqy\R%88K.5FW`L 虀8վ8%ؖ荂%(?֢C?LTizm9"䡬38j.&.: pwY+Uj G][lX/uf_̓yVg9"bN6 =)Nq~/ܐ/~>|0,YsssK /J:$>O26lW`L 8Ko9t`4-g!vpC[1to+/fKx`^k '<_݆GE1i)nYf5ȷ.ٰ^⬡l]Yjq0sL 2DJg/\իWm۶"Zwٳ"a'P...5k7o^\h:u͛7ѡC!i$!::111¶'x;v9+ko߾_D믿5kրL ) QQQ"·K.Z;p҃]gϞ甔a?&+1&^(Kk@^-gw</w}(C@+)D͋K͊B1L $nx; .|`0;iҲQPl;GxDo&.b4^:\͗T?⬥;H8[Sf/_1˧~I3OYU,Ϊ&kSNݻz 4HTIg/_ z=ҤI>|8\~cƌ#z ,^w6B쌈 ^~ 6/g]htVVA͛Ν;ד'OMlHOOׄEB)56z-L<7|$rJ79sеkWlڴ 7n"1ey1VQjGƍ%+WdL 0"qĐVXv;tm1~b-y' /x"XT$x.q#[u(8%Ƶwġ'rTG? V"6xVA>26᳨l Eǰ68a,V嫧̬gҌ.V 0&`%@_vTZ#AJBBd#<==Eݒ4iDuTQWQTn#99O yi)ՀLINMMG}Th@1wmllfUu׮]8xa1~W ce6"ҕW*bJم $~u떈+Ԓ , 9hm,#xZ"f",d#R0 X,(vCFR,lQ<"c`]cjsbX/ "8s=1ȃ0}J$-T ;3 6#5w8"#Ң<3E> Vo̙i{bqsL 0&@'leЇcQ+E%"\e??#Ic)ڵk{g?ϥAHݻw$&%%Wem*}˖-"^+ [bH%є"x;wN"gIEn޼YD L%00PdHLL)  CqV;ve&Бqp4,8z@&.z>rΉؕ\Maߕ q璍Tka;Ps ;Ox{z ڬK,eB`"$&Yr؂OEad Xx/x7KF#"s8B}`OlX<0q 8/` %Ɨ= `⬲fxy^3q8?ec)qU8KbĉEJyRJԉ4":"N)}wJݻwEs⭲BԞ|* EwyM P ug)EΒEyq+W 2H%`qV=bL "b{WL3nO(KKdqWJ^8ƽ[̪%> I@tbEEZ"1)IIHIɄX-NohmR s᛹pƿZ.@g@q oX 3qaS@E 9Λk)\ H F\^GgyGY%UgiUYn 0&@#OpUm||v Ӓ5)өD_ tdvNN̄( O®TGǮ]o)d%uSQ`\oBDT:CGiadZwNHM۾3G `,~9;Bgi|vbxM(7KdE!2 p`qV)7EY`qVGp2g?,H>{Mf?,V%,V݋&`! [wV1|tf|qE=27a^Xv@.G"3 Ga(9aVH_ؼ=y(|F4"$ BDx, 򁈛MDtFĦfpt#bajߠP ˎBdt.dp1ņp6eĺ5YgV \=I?TZx©JJUum='}ztC6~o`:eKge~I)oj@nxM,Jڠc?q*̓ܗ.s jtkR)E?*.+YnfWfv*S֗Oh.c&}.edǝuSZ-+Q_Qsʼn: 6-ӹ(ȩ\n>O  J mR;^yӴϴk w YI]RXJ,Ϊ\9g {6`L 0J~ ?\ڋܴ*}[m?wy۫qV٩Q^\b;Ƣ ¬1gCtf- qZ5]H̯g Rڦ>З!"0/ǭDQY~fheRYmEDNi#n9oc/?8Ðw_6̏٣ |Tce)[&[ 5f)G=2 O$Ć Ʀu}!)T8Nw}ͬ C85Fl(E)&o#+pkzFgIIc)}82Rv=`L 8u ,Yx;t{EI^p]*DТZs4X[<>zTig Ş㈻7N>{5!xum9gM~1H8Z7EҭXz[':oE]E{2V;!c\yQ{ ?ژa(^}l(Tw /<ll{_\²uw?Pޗ?Fę_D7(-ڈ4+~ĐV9A"/*rƷ;u*.OrΉv|{N#`[8I?~iqj:ewLl]AhP̗dvfm!"U]ѶL@y}Є1 |P smDta_O*_RgQҵxgɿTVw6`97%O[U>دsZ!U?;K|3(sF$޺:>G&X|< ; _¬H).P)ZX׹as|oAfM?uHTRwGlm^[o;pi;5rz:l1 ŀT^ܺ1V{MK9޸R\8+klӯԼ/]_'?NuЩas!d+[M⬦}ֽΑ~uC:Zyax@h3L]R|SUNL?_q9eyM:z@(BYk/߽5!0FzirT Pʞx.7Ld<[ ڊĬ*L,mdou{T_QN]R2?֖w-g3&`L@L@g)O#EKBEҗqAޙEUaE6YDPpPQ@J-ҿfedVjifZ.暥[.!(.(("tyz s;0|=fͭaVH-YAG)Y3P_c"9KYIrRe k',~~6}]S!Q符:C)=>x\xp.Bd\uu6a_EF<2>,Ctj+J4Cc\Y]];3߬sqE3|bNs0.kun"{5 gTYzMԆ6wqAsI.$}RK:5K)ۂق ʰ[#9%mW=,gZ#nN2rL^,(sDW+GDM=Q̜,`Q ب"whV'*{goٽSPjG&3= G%e!*2R3IevP=ﻪ?sVzqͷ0&(X-ǃ]ן@aޕovHz}wU!R#3'gĦ%:WoO'2> IcC댦p:DZ[(!_ԑ݄&yʵKYb͝g*y?M"^Ԇ!IAsI*ZJce⬦uilg5]\#9QX=џux]e,h#[AlOq/i*4Q쉚*"k=> g{@U/ٽSP*ҼY} >`yg0&(WX-W͝5gG{tE qXo.> h&^[G,CޯRAwtr;aC+=BLtϗIS|Ex"!6\?u;)K]z,~Hý!V(>mYMul:8KCn9Ka1ۼ/DEfwMEc={蠱\UA^4$h U,+!"鶰и(y'7 z,wͶHH d@E>xZF0 bn8[\?RW64aAcFmxNEU'h]k;FqH۵7y1dZ-^qojVU83]dѮ򁊶EN)9KQVƛAcRSPV{)ArsˋaJqV]ukV1C#y8+ęr/ 0Mާ>/4#JXs僀5lK#08kиB&8[aR4~twB8!ޑ݅—С+O, eBksVCBŗe:&;UWx(s{\ [,Ζ1苉4~X*zl<NWѶZ"MtBbFQ'Fe%k J2gF 5]L &$,o5QXI i9V&5,&gVFnE?,H=scgtQnmI4㫙 l,س U̍"h2Kdqp,8KVZTS=[PP.T8mߴ'ߤ-|]!0 |aHl{D!/yMigKpD` )Dg jY*zlx4X8k8Kg _.|6}'D#z ;>:)iY&DFȃ,*aC6tYjӼVאވ]EucjuQ\D?7rmeUeL?C0W}a:eD>;'V4^g:$hL=J{# ,R{׺j# p8o.mCZvV~᫈H}w(bagղ_(9ǫbc_mҼ !״VS/R^uIbbvETJ!]RE 0&` PDrr?4T{T_gggg>$:!S9%EgW}_';o`9xع qcKhU!愭W"#N8t)4wO}W(ϚDjV:^ Oe_zL)^$GK;ܫl߱ܜBg\z3ϮA|FR>4Uj'ʤy837 2d_ "37[Y:<7"KX>{y3C||n-&#=ң(sBQg|UtBVUT\4Auc݆0 ;״3/dqseeh0+L 0&X͏VCVNuaR=V`aԱEHJm6cN"=+CdUXlp@{aXzyo`] LLLp,]fÏ},(IZ A߸XvyUET付qG<¤F}ֹ`5))xٽ> ITMלxCHn9 2|gOك2g팄d4Edr f]+ Ƽ">l:xF|z3XZ9`?MDUn%WPܰiS _($ж ң[\]}rss-mc}ka`'@TrfFytaes[|?Fm$Jm N<]' }MgխԬ'~ 1J^ӥ`Ml $5sV߬K#cL`q %O% Hh^([dn4UxVvċ5p%)#ISeg(sgOL<-Ce%[TGILlYK&XY߮F6KYOGҿvT2{˯BJ"uG7L>VagOJ6 2ZI8KVH=sKzڻJ|}9YWagN|gۭl8.>ޚ$tQVTa'3'0fȑp`Y E.lH4~uGm[ %q]Z7D5A1YUD*uľW̩+]S$ZZb͵g S )sKkE*~uX4Cu1Ll_]ڂǰ8[q8sW 8[LJcL`,̈`L@l+svwy868k)wc$ltvxEؚ[[ ^̊֓, .*ET%_Y/7q~[R[WaU8K׶2@ IDATy"3:5-lA$R3 W!mI-(Fr]%|QD&'*z ">qVR531ES 0!d)Hf(&aSg }ĞV\|?$UkGDgq "c WN^"ukʦ'oi*ӛ.P=Lր0u;LnHҼՉľHْU#bqGX 8[CcL@+,j/bL@%O6z3%VֿN4wJ~{bN >M٨jͶ"KIB(;m^%zj|:PgR1ge$rpkGVViLkC#5+g"Ol(f7U!MIGDm=JٹH}b$-$\OeK[LoRg=Bȶ`VPǾ|< p)X-=cGң 8+]hAۼX9oƑ "ݏ)[vȯ>u?*fpGAYP\)ڷV;CJ !83ԆE%4E† OSJ6H'/ o֫f@lےVho]<٥1CX5F%[iq<q/kZky6Kl`q .:pEҩ!~M<^Fh"'f,&ݢ٢cmhK qsyHWofGo˗ѦO̚m? fWv*/tr@dk>SX]\,ED>QeG7VRu7-AxÞxh'M!F48y 1'4KN7oۆTe{G{tGtj2Yţ9*B}']zRr"Ζ=B1yMS Y׼K:Fl`q a ÿw+~XHHͦxǨZ?SЪjCLс6' BBF3N2:ї2W( Q'5G/h@~ATt>\:5[˜urbTb l1@׳I]Y,͜dHNNzbHUgf:]Y4/TY=Fq<}cO~ Rt%@v䳭жN.~wl/.n PvoiB^ª7d].a '>k=gKpD`N%8pEKgP$ζuFmq:ToxLoɋN}FFH4 |W}?)]ӑI0(`?rj~Yw0 K)_s>qV.jc*gQj8Ϸ1g"j[Tm vcޏT?:Ŭsb ;x9wt(0AVgFvʅ JvѠƜġ{aZ?!Au\|խ%~w#׌g].sDY-đ`,Ζ10+MF(6\3ewSL=(M;x)y3m5o!d)ہs[;z TwmJXu?I`fVDzߴZ6ϞzQ#hJP3k^%h$igK8qT%%|R]uO$gPsJ6sñ,bjX;c!zl2`|:7AG 5)D*I, աC̦6}]`b"6u(DJTHC"g %s[ȋR8BطF(aڹ\&Y#O"Yyƴ5V>&NC@%@/R ;/祗fq%G^X-FԴ*FJl6CrWÏ-#=)=h7ٙ[cFAlb$C Xv2g3͝<ѮZ|SIXUq(k䡼|nxVUӖ[GIc% xTdq&aWl79]N~kY֠C=Grw:[Ҳ`3Ms8oeqYj)2~܍p=.L }jMg%Tx({X hZ,Ζgz!7),[p6h/yK$;kM!K,UQF~?^#DX:pJR %F OՑ{)9ۥz3 -l{<Uk"ܚ~*klٜ,Ζq7N_{ }ICEn-ˉ]kH8;ڣ;h/Z񻸌38l霹5`L 0GĈc2sA>0'eyeƦ9X> IC1lJ[5S6~Gw%t9~ O""l.H)] gr@`q"n`L 02M3cl1 _O &Ihԝ>}dSZ3kd=G{\a֚Lt ]." &b_{Qfhܳim9${OSgya+9zfIUN茏GUX+1" ?Npë}.α8[DKy3,Ζ,8[ ,`L %DǞ36~|MC9~<Uts+1e(Pu??`)OL$?>1 /S= 5Sv}ttIX DoEH:Ch,ܴSX2e?|OGm(79PvL ?ueY1b, |p3-ǔ페8^]4~j\2O-D˔gK͛r_1~ 0&P 8[ꇐ;E+>zoلHЩ\`L 0E ~jͶpi)vq6J,^uIn=C >=0`p{Uo7c"Y ȌE<~~E8VNi'kf-O{.ƒ8+Y}ٞX| ^2gmeԦ gb |AK隨)ZgKhqL #, & !lщbɥm;0&`@ES Ll]|)VqV!&pu +2S5 Sfc_3gdJ0|Oy98kE]Eenxʢ𕘲B{1l\x#e9m_ ɯKY}}L ,Ζ8@$lшw0,fL 0& vyn(^+6q604S{k>LٝL6N٣ϰAtuZ<چM1`xσQwD ص}1mV7dκ_YuxZ_UkqX9gB)ëc[B 'J[$`.?7cR>iX4% 0Awo_x]ŠeL 0&@q V5dPC}E *S|.[IC߂ 2g0C 4pX >UiU]Xug$cWt0"/bL 0tr"&[7'.d%h:)iY&DFȃ,*aC6tYj|_`Q MOᷨÅ>}o(68ČўL:mGW` %i=^FtsRm[ GcU5/\1**໘`L@-s@tc2ILLY&P Vp`L 0&{G[;gW}Ov0ƞg96̳P6Ĝ;Ӥ?]Wg:hi?PbU3P:r/غ`Bx ٶ%ΚbA1xwmU0̳k:ҹ4AWAyݖ[G./dȐ= /l5u d 0&P8[k\,'`L =,8[ Й9YgtcxFƞU+ZV0OA0"d{61'WkEe [|;.'QGq%6f yн0,ME05 DÌ鉘v4[ПD7p&*>l:xF 6SAXyOݯv,/xҳǫak=ԶOn9 > tYrT321uv-Ҳ3DFmw ߸Xvyl+'m5P/DŽj倕W&auhq&>h\7\zQlۣGL ?g 8RLR;J*at xoZNrյuvty܋{!K,-Eٹ9u6VXX XEݶ՚,]Eyzstrgɚl^+3 k6/ٿڗr![M^W*!itxڲ"KS69CN%{r~zfd!3YUQ_K;/qg`k@cH LD|zX BH% W2Ysט(6,zn,`q," 0&(L,G(,g'ʅ B N_gam\@}qquL 0&PO{w,iJ񷃮_$&&(X-]`L 0& &lኳ\ގݒC 0\  aoI\-3h)cWrɏ;( D; _eq0rcL 0&f,8&,EVn6OE&`O;w'K;HTiXu?I`f 73&`oZM@-j,``qV_r|`L 0&P8[,վ1|史4m/L 0&5n 5 a[r=w[lǘ~!* 0&(*)i!luT&juڣu| X^U|?FFt$d$k=f|!`L 0&P2С5m1ޫWZX-cQ2ׯ_ǴiPbE,[ Nj-BTT1ʹs0o<CϞ=UN:úupL4 D߾} lV /`L 0&Wwc˭#:zZ%}9aa:`L ,Ζ@K}Y/aÆq\ggg5$!X`L 0B$cڬ"uY cl!N\ 0&@$lTRW_2S1_3g/ 66uɓAQx2Zj"Ey:kCp}Q6f|xpatE!ʹoߎ pwwU-0&`$1 auL 0&@#5 {ΖI=Ҟ,ׯG`` ƎG%A۶m+  77sGo_ٳ \Wqxᥗ^111BY&>C V!vY6O5L>&L@֭|rQW2&`F#N@43MnՑԶa`qhӔ+bL 0&P8[;k(}Y9Iݼy3,Y"Zkb֬YhҤ /DXD+V`ƌ PqV/ۭ[71B#\lfΜt7:|?`L 0&ubKźkAp~[8 @Jlk\䫙`L wlkPg_/:~x"++ 7nmڴ [lg}0!{xx|̞=F^׽ǚ5k򈭪 !vׯ_>q6''G6MS$D'O`ffW_}׋?`L F@8?p|Αq9~ގYg h|7`L 0&P g D0 g۴i;wbÆ WRRR8o>\~)5jQkӦMr%..oVCHP=z]pV,78K684ůׯc֭"xժUl\.L 0&@P'Ύ 0& ďV/QܗԺg1ܵ\IF6Emo:13wb^,[mх!? W!}/8[F`L Dtg'L +UñvZƼ0.;v,{=xxxFy48[:0n 0&PH[s?Eou; &V(3"}MffêSTl'z9qL0q_uFܓGX 7RbŽ]\aX45`uꃫxٸ#XI$J#wуaOoJ=%/ ,O&`L <`[3AWq̙3"5++K5j^z)Sp-Q|M6f͚B(1bD6l@JJ 7oqO///L4 vvv/˗/J6m@P~WS[a˖-B?~<|||D]bm۰k.q/{ܫW,Y"])Kť `L@֬)y}jk 00EtU٠jMѥz3,+<ѫf &U,l1>>OWtgFM&C GMcU GlkWTOdג' -T/4GvbϙHqG`"tBud!. iuU/t ^bl5]g"ò:|uYXy3wG=ˆWW 6>j_wOYL 0&@!lU°pB<}TYA;vՄUIݸq#n߾-, .]A||A-в憭>G#ub5x܌ET5M5yUws}oIYMXჷytU3O7%C/;u ?+o+ϊ܁a?۬XVcrnE9{=X~[Rq|7ԡPƖԎMi)KE>LYrL 0&@ lA'sVQ˕+W_ ֭[4C?~, T/k?&, ޽cbM\,45b&2g?{ XPW)m S gMM*`j"K߸p4\Î-DwpOu.k><#*Tm B7ahdUkGu,$FG!:1D=@\0jzb~ =HܔUqvGcI<e% ~G!)-١e]0Y =QI9+BWa@Î0 GV# *L,@Wq'(ߤf.]$}cae.M1^y|(,٩Rq311'N&FmXt8PF+,Fb1yAѳgOgb PzRG}$PF/IK&$$୷‚ Pre!RRv*U≠kcL _TnSmX!AۀyXShr֦o(kjr8G޾пv{ddb8N}Fl nbҭyfUk6c:9솟"޷/3pm&ۼ^y=g2Oa$x7+F{s֒k^x?l"q!G;dh4x Vn}7&lD,g3WK=,Ζ08n0B*`Y&MY-h>)n8[2Yʐ;1p@3!Qu,]GڵkET d@/'[[.RRRyE!\R, ƶ5-66V)5X@>}c!S~8pׯ=Ӕ9+e駟A- 0&t"`'-YQQE#xf-핖pO `_dFP +#}["AlBGgoك(W0pH}p">-}/g2K̽,Ζ0J (uYȘSI8/7G֖],,Y2`Ld`qV8w4cG6aXdԺ6:_G+$܍Mep4KC'Fn&A2Lٲ5xƓ#g9x8[|9R!^gqYf _`L@o|)w@J5y0^uud1jaݓ=He[ [*Κ}kCWTrtxp kԿ`UvwNtǾ(p4[xف ,r=0ң;U3SĤ=q%c6oԺƓbbE5Mj~_A7-'̲PV7C}YOVr}H(u.e6‹5П46ihƞWy#M$wu 7XTֲϚ#K%y}0bϘشΗcvS+9qv}t؅S WD-=0E.uIeS 6`?q9QC*h.a?#")Zc*gwOSՈI8kLKwc1r›.4Ţ8+Ӓ6h7{*"cp ,sZ|e Z[,dMu78k ĉm?ABF2 ~EIpr@&j36kX'⬮gL 0&@Vn6B.[GKih_jeՆ"JZWSĦY}=垀!⬣V},íJM"pF_1egFNAdr ^؄'@k._oĤ}D wOcyyƯ 1OC9mh#t.> 93M `9^d?p.(ڠ27l=5xI-}njRwg~7ML GAa&cqȄ$|}q+EL^盏zvSN9kۋl l~C꿀G˜, JP[(9YWK/e|.MMUT4֊rZē ܸZUm(^(S8l|yq :bֹ^8MM"ܘI44#wE% kxp_]:rrUW-'M]?axV[Au;!%+]WڟJIGt 31&KPdiUmsCz|K.mO h;kkvbt+|F\=DQg־\{_xK~N{a}]F3+3gxjTKrmiK?{]iB[W`L 0Lr~FZAsl 3Ɔq`&4}ԇ\, vNSW"EJ|}vEGxFFi1wNɚ4bԦ1bʶ{4S $J-MsS:~B ,g+k} !Km (jgbQ]RQM79S϶U >]3 ap:CN\!|b<_߇3 LDӼTwfi=@|x@qVSRfNlATYC_A&)ކz] ~yHJlJX{/ |>PN~8+][67] SM{\-rHtg5}sJ8KwֹuxQɍK 7\ 6~)}//_h,0`L 02F26ܝ!`8[+-22U ǵ1sVz9IpEIXTW״@dJ${aOC`[C¯LlZY$%K2<ؚ[G~ j24!=pG^ţ!e ޖXJ";7 cƋNs0>dЯyFMiVsAjMg5M]Y.Ijg9Y:,z _~&$5x-a`8i̤5+Mu6Xr6'O!tr›BJkr\נllI H*yDqOm6!m3߬YiE3 Y-6-A}L8iokұU4f\mm߫ u8Kٱo7QI΍2z qV^Ň}JWч G*LW.;;UT>hICL 0&@&l>"VOݓq-n.|8oFtj[(^'_ɑ݄*y s~FlZ":Sa2ԝ hn㬱mYjmfVp)yƈ9* eAq"3hYz~S5hOӞP_9*418inj+RV+y2>O_[GKڈHW-aݵѦXڔSӘI44AٌA.M:gK9=8j,5I$PAg㺪?boDDŅ+,-Vj;5iZ4sTZn;ZijÆ3npPQAPxς|ϙ>>!ށV`GOUA@7s.Q!"n.ΈEFᡕ#[ ΪٙFjcJSkmlMn抳jcd[PlBxz;ܺle%qJ<{WuJV8[ioY=rL 0&@`qs5,u^i!4qz_n ū&# Itv+Y(+y;>8KT%avywڇ7cnƋ7$ҋ9kxzJ%11nO_,P뀺㥍pV,H3姷3mR%Zt( G-Spf6ށ%Y5t0I!BH[ @)!Hfgr[b,=ո)j<b5O?p+,b>'ǹKBUSjc& /D9V:'K@O?Lk3혅cΉs&')jƜU q7S1gތcqgdS#\Omhv$'.:ƊT ^X 2Xx5;ϭ*^A"%뛹k[kmXw~I[e864SUZ뀱8Kܢ"qP! Ȼ_im7a\>k@lx.0&(E,Ζ"lV%&ضBiuO P'L@ϸN(`Y17'Yxl.ʔ8kjt+oS>I +x#C2i/8tnqV+Cm0 ﭭSǰ)>gL[cEI:D#lYOWk7s0v0-gT9>aea/y*WM*-?L$V/>kΥ3I ЫF'|gnW3*ظ-/Ը)j<<|Abs8aWt{~| =lh%ovuCZc&qQ*wo1w^~*{Κ&a2|#0>ge BZqHnZ"@(]$=U:.78VHs>>kj}ӲSSkmim`lk=U>@ `|QlujR}zUZG9+^K k4 hUZY=cqԓ8+'։X8V/L 0&#w&kضK~8H#m)7l!J%UX}JKTn9k.3[m(BBpu2HqQ&b5NS"eTŲQ-ylYkퟫ7'ή:*>Hl;\`L 0&P߽Ej *UǓ5;ۦٙ$Я8y"ެXЄؔϥY:yh|{lYELL 0"`|j,4ܔR'`8[ `L 0&P H^qp9vCؙu:3p9[zxVbȻbr\>iooE. Kq~;ز,Zù`CY nI9$l94n2`L 0&`s,ΖDj ZqvF۷W%'6<_kF qix >XO.5?a D38p{c6zubp9ڿ3cj7P?o\+'bX'6¢B:I#d^9VjvoMq)CjgNx{w':#3/#`)> 9y£[tK!򮿰?oMT1FtiH|{7m"@n׷.\C½(̅{J^RN7i /CyReyy`Xh\CgP"۵P奭1~Uv^x9e P;qQؚ.4t<R3sX||=._"9CnAF&>l&{[)rCiF4~ 7%dBܣ׳ .5 n5Y9Ơ=ƒ-]żzY5oL 8.gwle倀⬥[ 5љb:S_f0P0Ն̶)پla=+c*,kF=ch$* FZ,<9n넚7jNBs/Va+yO|bP(_NMÞKD X.z Ѷen.BtpɼRGk+y+SgcȾ! c{A,>8K\//N>~VE]7T+łuRb ]C pgQ k-G\@$ZVq]f,n-璘([,Ζ-`qL/W[jpVAlв<"ۗ6c,:8{gdS`X}.a еj<|1\ɿ.bFVF-~$f7 EgYbO [%Om8Kaw74 C+)@9Km-v/DVUvؑuϣ.Om%qJ#9 /js }H=yY*8&$39o*\+HXp[-S~(ç[-X{~n)R L n +@}FG!b-],cU2( ,Ζu`qCL/W[jpVAlв<"ۗ6c,:8c^pd]=-b>Z_; {D<خIUkΥiwmMCq:'4%<^/_ǐ"Ru ck~@m/lVk8HyhP><>&7tV k0a/ց.o7Oct\;z#^!K`8K޳o!/o'7!\7yJH3H$Nn@Q\$N\A /^Sq .0 .₌WD|Y{,\&`eJ2ϕw,%ܙj˱_ *CmZuV[df쑓YgkuYq c5@ʵEC&xRUq`]$xJe ݨ('50Ŷ̃"cyc4|o N"[7ӱ5Btu׭_Ř4yN$LO$оkӽD^9Vj76pd3.bs:kEUT)vj8{tkq ]ZIS&#GN^;\C}pcIݸ8O5Vњ, vNxU>'|ݽh6:Pr=gsL g˂:Ya8ktpg-~58 fQeshYYmrGNg[mgCbHMC_8ضB,\u.UD|ݼA]{G>mOi-bQ+3./mQ[g;tKX y rGaV."׫Yv7-6~=)R󮄥'7t\M67&{C YaL ,Ζf:&kYzgOltrBxmWV%rP^*ѥjsC,(xOu@0K_v\zXUl9>鷞zxoDN{qv\+YCo yМGW k擭A+7JVoZ&4jڧBz)ҙ:xN`4Q"ੜGۙ/S!͹Tk{[ 'nbŽyOgM5P=C$Ѧ7v0f稗%sYe*utt=yl\!A>!ld_՜TІ=" nS "fRNmu o ~8(e"с\'g`͊ m!Jeز,ɍaL X@Y q& pDqǎU$z[qxP}Nd2+8kM%\Ky-[f(D!M^80C;F4~ S&@e)ّ^[6(vU}zJS/ÖtQ\zhJ8USm]{> K}CBt.)PXTXXkHR,_YEmws6a]i,a⬲u8K-"/D 3@/GWpN[tK39ଢ଼s'…C5+bڲ,si`HYGnS!`oq^$w JAWx=A _&,"/g6x1R IyARO|).A^t/cH+geoռqĩO] D )S)S$܂< j𨈅F^#t?嗞ʽVX8+hۭ6a'R[&l/`2eԿHvjʦh,7\؃;Gh+ FV|}+իNMZKS)WZ[Ò8v>!BR*V&{$kRH@hԺ[l<}ZC\R^9[z[}RlxSE7W,BXERhW} %֌t]!0LSD4, IDAT-*K&\7`LZ.v%=;(=S)咕UdmC8?()Rov_>j%N mBMm:Nd`h}<߷+J\LhbpwqB£5a(ca[`8Kf![ř !]uC0.kkrhM!KOn@jѤr<oR:= J !Da' fWR&߶D@JmXu6դ tDQӦET>ME?F͡EyOt)Z%ۣ؉ oKxxlM'wB"[8H| /m BGH66Sh8LLz ?7/Ef$I+NO- pR Q^62ڧ׶/w[Cdܝ؜[3ӱ%#]DC:Q|rW1x˽ !]:F$1q|!tQ*K>U+)^tq@̿(>Zեw,=tGR㬗{%̹WS-ى|1$@]f:"ltGDc&b۲du3&%@;Z^(Ykir~$`Oqچ'`-jH(%_S> dM _{L.TҵP,h=Q(E])JlsYES+C/ǮAbeIN` Mh,;`NMiY%'7;<Ζe% 0&`)/WLl (,],ZJ95{D! '֎E& ø=?Y8K.L8A/|otŃ5,}9-##W.Y*~ش8t.A_cO;S :,ِ>Q1[LO|Sugo<`L 0D``AlE]K8K,yJS?G/uW@.<;zu)A] 1hy5zBďZC]/|Ez|&fgzfE_j#ݫYU~:aq֜'7N`L 86, `8kANEKxEL}-cfnWKζl)99-}g'Ny⬽ǃgL 0&?s޸deeIi@E$Gՙ^ଂ9Dٖ͡eyZgE/m9Yeqve2&pf,:s&L/W 28 f-Cjl_ی=r8k8k˖=ƌdL 0&5pqV98g?@L}دg!ʶl-:-}Yn3,+. 0&3`qGl5gFY3;S_5ށ8 fΐ-Cjl_ی=r8=dL 0&XuQ>[MYjL/Ẃw*3$lв<"ۗ6c,β8k2`L 8#gqԹV0WB. 0&`H^&fggnybbH[PP-¤zu2tL 0&@'lB@Y`q,sL 0&`qBuq0&n`ㅽ>ubУZ{R)%dqj\30W5lggۗmm+T3C#[YTL]yO(3cq|{L 0&ʂs;ѮWn'.,Z pF,Ζ;XuncQYv8;sƀYgͱN`L 2Gi5UW-g&lَ3,Ygk̏Y,s;zWy0>'Ύ=v2ٰYfs"pAݻ7"""\;v 9&Oly! 0&ʜ-vWTsMP 8[Lb cq: *δޕ%m^+̧W^yϟW, ӦM߿? ڵkS GZ :u ''GuV3nnne,:YD `傀8[/(âSTljndE$lَ3,Xgk̏Y,s;zWy0>gm&0oݺeо}6kY;͛'S֭_ 񫯾BRR.]*U)Sѣر#C믿FVl2_DzD6n܈~.]B5ZjUQ+?Џl 0FBZT޶MmѢE${X|sVf 'fL 0R'`JuwqC:ڭ\dܸl WtTuuqw-Q˩~%w>C\@$7~R/Z ;۩bEwQM15}`BxmWV5ZBl{~,֖½-aYuѧv7PZi /}6 *ƖdvĶ)zLI_ff*ѥjsJSlN5p|ش\[rN}Ԭ/~|d~F zm1-eZuhnig`ѕXs.M+ſK}/uzpvpܼK18iq,ɨdkVَ8G.p#tq/fWkucz+{.GV ݌ӂM5mSc7RSSuJLLi T-*2駟"??=!^@j%g/^7xCxҒ`п <'Na3ϠM6裏@[o4| ._,=B(&arʕ8q"222;tP +PYT;#~wyg1O-[`ƌ|Kl=mIGR?N:%G#„LFa hqz&(]ja zY-!ژ~֊$d~a)P$L)/`bcQVu좎#3//nE=< +GBMLٿ [2Eޖ0(Q<%^ڭ)Qڶ[_%3sⷸ(d_ň3p*'CH.ʻh qV^޼0&m._9: !ΚTck[٠$nIk*}(iU}R9nux{"3D5Ǘ{ƾ+'-nYekSjjMX&WN";O*2jQMX;sM4lCew^!h޸qpڵ,sMIIEY:aΝ3g`Ĉ$Ο?_/H/ ~tgm#'A"+!}3G䵅8h> oWVGLjDLsK;;ۦ &^ǒql3%.i; J4$(RYBmJ:F&bY ZͱMD\'ۗ{~ƎCkdJZ6_-@Pwcgjݍ^8}.t{+ 53~`cqK-_nŵj(V݁^qp vh?=}:}[lYzዹSU=+ۅ749j}&f;JҜxFG+E;9>"02G>6 L?(yNI~†^;'>8u?6^3i7gjuA8 -ƛ z`݅xZ{d]kLm8[|ٷTR_ qu֚ϤJ %KDHkԩvG%Յ  q^ë*UEg}M6 /ҁ~ !RoD{ L&%^xjzᡫ;wTkÆ B&. @DZP332&*g+`rW=wh7C|3⅏;ȡ&Ȅz1|tЄŋYj֡b,mÝ{,=cZ㞪-ge Km^l }hÞ8~xGv/(H퇡Pow%|&Ƥ}ݗ⩚w!'~8k1c6Tm;rߨO/A4%;7eTgGV`ɍx0 Z)E.g$qVmZAmw%|&O-ΨkZkX'0")gZBe˘dXijR9^bznu|e/mKmUqgG8ud7/ɚw^w~7#3@~lfg}1py'vD@gm,7kYKL呋k׮C )8%Ss6//O>%/̥0 s(, EZjWÆ MvS+[OB.bH9(]-L,HUkaL 0;`qPH&PZgI'F/3D Κ@#X4%<=!Vxz`Iш۠Ru k[lܞyy7M"x/nĒWݷ~EjaB%6<÷w#((*8{ߊvUX D~;j.AU= __zUITjqH9_q;򲌅gmj$+lRxW*ŜU;^BypHHxmtɅ'5;'M-񳄃q.g9|LĤŝF к]ękZk6㘝d>_b>C"|jDad&O辰ΑM=&YJxTgڥeKCbG)wXUrzYT̑{[݃/KNOj9Pd{zk)qBU}<1[+;Z<]Ž1T=@0廸@9[vmqxEqғlΝE8 K0~xdff [-K{Y"?HmРn޼ RxիeRTb]tF6ah$ʒ'-Wz8 `L Slz~b"DkZJjedeefsjLV5s.[G4F/]݄%ΒS_le,FK:})_D tl2.L sNB!sLg VJ^j>QH뉵cEX[yΒzbcKuX}Lkf6/7Ln𠺔Rl/YHўJjoR-K.8HmS%qq 84w<\݋0f\qVm\-6GvM1 ӂ~P<P7԰>6g͙Q?}/uVޑW0,JxxW^Ť}A\{6}5zY54G#Q_{;MZ⬿J:rl!hΦӥ"Ϊ)ٓqż+ʒ8(m%),ӲMx9s';*qVΕD/@m\-6GlfwOM OEFᡕ#))6eZ_JZ9bo}k+֬<*GL:lr}T0`Umބ녇ZWutrq,H%On76CWc=5 ,nOEۅ)N#O-@ϸNKw۽UB !y\܇c"+/[l3t)ዷP<=:SM]H'LS "Q.#D1ҖR}/%SbF(M k@e.ЁhGW[tf5WKTSj;ق=MISM^tj)uH/l?j;->UBU;ZB6>^ΕYK%$i.]W ]Aqx_9!ƒcZt18Mm ۜZXrOo'[qEΚPl[ yf}/a.0cj<, )!uX|_Mq]ć+bM>\7s`*X.LA$<\Gzӎm{q0>T_+8k 'fL 0&PNߔ {f Eř.nVYrHRqY٣zڣM*XTW=\w{d\t6g~9zgkv(sĜ6|bYbqKL 0&lL,Z͆YI( ꢘVQL]Y.k%-QfL 0&J˛k X-ہt&< ekkg~%:m8zWcksV-^Gs0&`ueJ2o`ezjg<^ƩYPfqtƀ 98V9`L 0SXe``qh6Lb cq: *δޕ%m^+̧,[ `L 0&Xe`6"⬍@ZX3,Xh$ec~,ZgAeֻۙkYeq|L 0&lLFgmT-`L 0"@ⶼqTmNLLi T-b:JqB&`L~eAٲu2&`Fْ#b ׸װ:l<٧ =L 0&ځhRmJR8, 8 `L 0&P8kqvչTLػ7 +p`L 8o7OVat[.g 6!`8kʃ& B 8.# H*qEM6OL̝673 df33w8欲sLn&ly7ʹPN`L 8*hn|+8먃r|,:9Kr*p_tkxy !tTxzr#6e/M6OL̝673 df333w#~ YJ@X4⴬ƲI]y8`L 87NM0$qg `qz/$ `[!pa%ZttcYBgbL}XXlzߑ8[:lTNNd ad ֜߉";Nڕ!1F'a?c`@o(lEh8k?/c9{.͍d=Rnp\Mb?q%r왐mɋq~-Ao+F[_w/]?P|ΘkjV9ZMQ>i?jrjzd~FlU[v{掱Z`l4QsOiGZ*o]I .7KE\jsY!Kh܎[E8}=T^bN;R~9Sҗm]>Tm.J_4_gwS)Śܵj:G5eJ6bNӲ8L,Y:`dn[Epq YT =?3[M6V5ve*_@f^6󮉵7tkV\ղJ=٠x^6uT{i#0&0X0C) E{xt(K碎7tѿOi:"}Bʑ⬼~K"W{,gm0y/HrAxVV 3^"] Nh^(l0YZB=߂R/\4ߦ}WN4lF2KHk!cjT쳵F%^UPqB1Ookǥ<}V{=aw%Ѡ_=i~]($#?)͎5t5Jg"-qvqQʿg!guVc2=UpWTS Dg7{paqVyRVZ!tn:I"h~wqxӱ7MxgE9YٮJkP:%<*>?o$xcנ0Mƴ2|L{#[RUfܞ1q qKāTsy"3arXI5 eL 0gJC%aZwW eƄp*AhZ}6M-)&NE< `Ž"-mX[wE53x dNSt\q_zPfQ[a9['8<: qôB1 L<$`bL'El%co@}"'Dxo͜VqG^<ه#2_b-gR?O/9mv أԱ!B̀HLIsgxZ;Âcx;̿@*oȾh^s2zQ+VzR('R14G5ySg=E׉Hazе{[{0 +sڽ-bj#ʠgiSuJDE#Yә2&gD-V'뛿BmO{,=Ax$tC-_5pLLz wo|~^mX8$pwq!]]lv;fKfsFXwa>hgܼ0 -flFP-/-0gŗI/c_jѤr<yLo_Ry'Gur1~U&%cC/O&1icx] /%qOjx]C밃xs9NKxw!s5D PݙI((,m?^J,Ė1dT\Ƚ,6NGuV"gbkɜ۲)1OZ'^8>%;7e8ah_;]%=jDۈfU~+nn"'BaԯTM`ɍ%:$z AewSdŊ9Jh\:&g*y*ٵsgxL 0&`}c`8{wvutN-^Cۻ\=aU ʧ$az3"71s7o8vX1gItX{B8-#Β*~\+ #~\SmxhE1uɳəJVT哗C^T3D!H.qV* ؠjHWZSȮCq^ T#h`1K0yCB*H۰G4F/]K^qVO[$k4Giq]/[*^nվWhIYQqYQͣ;_J/ݢSz n[{VCAkgzǟSSyg}Ps+>9KT*Y;0o7)j&ϊtǕ9 |"$8H+y\qV\qV8Q:-"o|7ŹOgK/:tGiM1:3aKqV9 MpB0hP?Bq,/s8sYKܖYJKbEL{ҁfgN} yd#j98[Z,{X򒕷>~}FPNR%q8H<^sf\7.c))xXUxƒ笚8KaLKq,uO\ʿq֋bR [cw4}3.7tn}ZyiQy.aq2&VLlfwOsrQQxhHDVƸ-y[:؋Q|a>5qVaJ3ؚ5 \KTTo[7mB|Y}"3>H9Y#8EqV-g+ycvÖ@o`5hjB\%%Ƣn&Z)J⬏[F&.FhkxɉkiY%^mi!?EI|xnݧOZ6@r5c іKɣwAl tPMG #(&v_:*rBxHL"; {+ng6zLI_fVJgw&p^,:sm@,ԛf K_m 2sv?͸?&wF6QC7Z3o.!_:,) N+=K,m%O )V;#=< mXQ:$aբz%gJr$%A 3 4|QB84PmKK-qVb= IDATnOWs'񐋳j6$Ϊ13NsV$RGCs/_q|c]z+JFV m~0mE@R>Sik$ozuT/HԢYhNƥK9KF%!B/tب& Aa?nYT[[ -Kb,R]`M \܋͜!D*X,n8oyZB'Q|ɛvWg\'].{ØX5Ҋa ^5:xYJt.JV^||y@ş5&8Gڊ.Iu/8K)8DϺaaCj*Q¬.b 0&\=0+s,ZC>y%ٖTYб%M}e9sg꫾ѷ_*fm?TwX-qjC/j_ҙ`L 0R#0ރ7>-5\QE"㍦$rDXб%M}e9sg꫾ѷ_*fm?,rY5벥TӘ~w~y5n. 0&9᥺/gm t抳`L 8zP:";pDJ[Jm!:JgIc&`KY{XgeL 0&* gK- c &`L@8(I\qC:seL 0&@y%L1gq`L 0E@i7R/\WLvXK. 0&(X-c-fL 0&=>:#⬃ 7 0&(U$ΚT1&`5(C( ,Ζu 0&p,:Hp;`L 0N>2!l`J`L 0!⬃ 7 0&(X-C( ,Ζu T<.αzLI_f`*ѥjsJcNk? 휏=+. ?}f6pL ?,Ζ13&`IYn`q gw}Nd8[NN,Z pF,:s 8h|'tLJub081]?N&[5x+@NQqĎC"mx=Ŧ0~O/U#rٞ5:jD9C9ka@ lF`L 0&N|k mڅ78bq633ڹ&PN l4/.崫l&H_;Aa|Kwol ؎\%=0`hY!欖8;1Wt6'׎!OZGw@_Q80Sz8kB@#1}Wpy´iiXlV\ .͛7G^?~<&OY=:tѣGq-DEE;8703m06DJRRlJDRȒʒHID"wƾ3u;޹s{߻r<9yN6mPZ55o[1rHesziÍdF  4!'ΖWX7Y4:JY W0g%ջa֑P'oY %п|{t\*R TiV+gs^hy >jUyΆjL$%8늎 @gvm0f%DZ:w&Ms o ""111;w.Ν;> 2d0d'-u*U/%0wBB:v숙3gBLC$@$@,>ѥ䳸qr8qCt1 sqVJƨ1U\0n?8 1w)u3uSܽ{7>>>֭6lhKDٳ'F &o{͛7GXX&O &:sTbCE8N:X݅ *\lRW_%en[~ߺuRJw J6)^QLݻ???˱`ƢhѢx;wn٢Eֺuk%LKݴmӧN8(PgΜQ?簵 &" +r.Yl8n=@$`I͜3꼏CXmqu9m6BuczJ.%#ou=' 8j:{ ĝ0J.R>V$@iJlRS[o߾DP wPn]}f%Jhk޼y8y${9CxP9n8hB`Ȑ!g2Ϟ= RK.wQ"qҥO?A&B%QreTXQyІd7nP\P% k׮8uꔪٳ+:::ZM+Ί+޹?xM?kkSHH P.f=YO]HHH 1 ̼$(κs$@$@$@8,eD*Fx;wN&n=0zhUD .$gU/PrVDD q0h UN4ITٖrM1g^*4"**J "2WPA}&ogaJqVc5l0%Ng͚UII3go޼;bڴi*KŎz험HHH8k/!{UK)KIY   o&@q6ez_B,]TAAA]6ڵkN+V@pp0ZjוHw^%`׬9;w\ SLxgϒ֚ml۶mKWj=|M4ěWtiUvXXZn ^"2[T)% + z쩄hi͚5S1rǎ+XH\١C*Z7?b)kJ$@$50&FI1 Y9   "@q6ek*l!6cƌ./P<]nj(κ; ޹sG &`&w%^)>HH q"^?k8yˆfO2si4gL$@$@$aBcD<%8F/+>>9r0Mb7+lUiwUxAZ Wzg   W8 u(z]$@$@$@v8k'0&'  Jghg Pu x:l +PuE:g`   ; x8kz x9CVDG$x936ߋ PgIHH 8k "@q @qXLJ$@$@$(>v{r$@$@$K;v8mlqen   #'~qYxxHΗ_~ \uQk#Gڐ6Xʓ!C+aWzuO;wb͚5XjU笈"ԊpR3BPP'N|JoMFc, x,K⬯OFt),nܿ˷QgܞY~tRȢZdWΜ9{b֬Y6o޼SVF=g,[L.X2ŭ-Y=qV! +zm߾}ն͛7ɓxgT{kȢwQuE$@$@$(&'{=gM䧟~w&QbkÆ -[`ƌꫯt[gem&:t'|RsJDNra֬Yu 6XSR$⬬Ůx*LBֆM[tiOtfe]+?cYhh>2 G֠]FwG<\)FEE?O?g}z,`Ez*zB TB l߾Ǐǭ[l5PZdZV-OY:*޾} ^[N>EQuH :ivB0d#l xgʾ}MZZou53! 8q]yGYsF=2f&jcךT^͕Go R aÆԩS6m7 %HHܚPJbݞKv[~9TK%J\Zm~<XFżxFr-5 +eW3k׮hݺge740YA\#⬑ØiIH<YO8*Z  ۲&M%L[$|_|9a޼yOPD$"ʢV"Be˖hӦMqV/5qqƺm1el5j+$@$@KQ* R5JH@C⬈cǎUlXF8"Ȋ0k.u˕+ I ixJ|W]9@LZYK0{cJMD8C$"lg%6^[$V 8)E$@$@OlgD$@$@$zzl:\`D`|QM):72bIHH<Y?B  O%.5 (gŴ$ $@$@$@$P8y@$@$@J~B<6^܇'VSQ:8 Cܥp>gFHH7:L$@$@$`N,Y    Pus{)^l6 @g)rJ 8GsK PҎgIHH(N~vIz$@$@$@Ig+[(Φ0`'  p MMgb貒$@$@$nPM7][+ @J8Kq6 8-=vY1   7%@q⬛]VHH +Xw"@q֝zu%  H)g)Φآ]  gNW{̥Pc3/m:X{x7UFV)M9̾raWHÅUXQG9 瓄^l7Zl>ñg$@$@$@iODP*@Ǒ=S$8!i|pNzx`Mm8J+hR Wk}HLط:iM$@$@$d̄^_HEq6ͻpGgS:)>$~1--s+mʱuesD)Φ8{V4m;0&  H7Df/Iq6 +v(ΦN9u8S8#ͳJ}}}\_QMqvY^Gtp8+X!YQ!G1C sSq)CyHH= 4W }{vkPM^sp8Kq6mGg'ʹ8:lucp:sܩN@َş6bՅ]H@:dVa͡?p0!pLD$@nH , Cq UN'g3dOHlIL޿nŠxP/ Ea`)uFR5Boft^76IS&T^''kރ9oa(xlƞVv  gJ}S8~^,TMê!nܻM#pM,gq#m5ɢU+cx@U иӛooѹu?!gn^Ɯ`V}H=7/ѺY3*DXlދ+@}k^J*jǘ=wn F慹-q}5Pէ滛k#bӥF Ӹ@m~kS8CX5WI|'ՈfHHy^xcΦa}܂ٗWP[f%AA$ ybjQ(k^[\h5GhrhjLfɁ'WB i. RzyZш`i^wG&ؿB, B 3܍U䗆Cs:mɤg8 F`tndDT8ѪVjGl|S[~nS;g͖(Iw3sUoO[mu<8OU⬔`ɖ~Ϛ!˿]WߣrV_Ȕ ?eg&3n?tY9e1xLUP>W5FXܸۢc⾅c)I>׳gvUFU[!1> o߶i`.   `}.5c{3Xcp3g`^d%/T +wcj-WܥѩQx7ދSi@ cǎ#*_" BᅵXᵔwnSMwwU8wve^@D`uv+<\.߾X`>LڿH bW.)_0]F$SW#BEg<[3A+!1^]3*'m?NV*󑘼pbAx?K_\d2Ʀ}FΔcO?m|)ψ`ix{8qB9yuX'o^FȈk' ø?azzcp`EoxW׎=[sK:/\z0yKW1/0_|`Qyw{?n*zTbF4Q/ǎĞQ'}Tq}-^~/is5=]o8{+L}}oY[*sN=~ؚ붾+Ms\ 17MiِЯG4E`)ޟQ([^q?O(/^RFfq?|2KW?w,]"~V+49ѣ$ʚ//혉CN#/J4þQXzz]Rlu_=[ֽvMsDLO$@$v(Φ{\-ΊgCR!N,=( [2g]_OGд@5tZ7ydbqCyG=0 Uz. f͍/j>[[WЧLk̖Ǧ8+6.S-ſ"1kˆa;CBUz$ܽMۺ}IuC5Ճ,7W L62sH`hèxs8ޖqu+Vygʢ'yʢEx|9 >6 Kvp@_̨}L[" ~7#eA~m{"tyؓ(-?G2$C6:F*}h|>[y艳z[KJ\e_;g3d@E1+agjH!r@.ʱ$Bekګ9ugk65gk52۾WJ9bS 'gӧ8+ztK4 ^Huf+JT^GB%艳W~lAX@n|u wsٱ{+\{ L>/P[=ge~W:3rϺ=3?^>>>X{az/G&>/0Z N@^TKzʋʶFsW~]9"~Czś"gd7ԚCvYg/ܺb'ciUS5Bc lg=ٺ&*qON,^rf J2JT5]}nǫ7ziMR\"J~S< *~gUzMK<E̘vw:a8{&IDAT{m_=@:$Z<[LI{L偢o'sK< AaʋK7S^nz^;YB `fȈȘ⬽K_,}H?ٹx3>!q'K~z!qV[jY'>;R}duƾvۖ8Ҩ %N6&cDS~ܳ5GTϙ_\8Յg{%sd˒dռel>ndG:(QC=}sF+:[W?־cCtF՛FeqGƱ5Adӈ87O(8>TK^< `gQ.G#֩)a;EVkfQ6%jm&;fY. rDl}x|.Bg^}13=J/^O/)W<-}X I@qʌ w8VWj~U?\y=y[(rE<jK)/Ӷ+msb]x+VU"1Q}J؅Rvǵ*seSU ZGDFZ/䒭,KHyp$Ί_raP!$ʗ|8k+/aDڿr4EY6J^*jlkZO䯜j⬣=S6|WH)pE1%GzGY6ynʫN޲j>ÆYGkǞ?87=W~=KirQqxYmmT*ZnF  E,)%6W}ܨ/f{98W9}*X&Yadi. yam\lliL6O(/2RoivW.0WxEoXq:ҊYr>Xi3X/o9ZBW>#pX[⬌QUT/\?.Qx/Z~*v*,]J>~T27٪v: A& 0,"ջ7ѷxʁ> ޢ8W_9OS}t7?q%E+kY1rG8'PIKJKM3F$@H;nJ55~B<]GW`]IDy̋0χ?˖EN-,zų54KZNڿG*JŞB5'c+ѺHp~rx֜+жh#u#ɵXu~g4BMp*o)QO"e(bs rb-XS Dl 9Me9Bndv$[-]CrEXmﰡ^PU u̼U).:q5nV]؉LFFhKx̨wޘFH{z7M/>, Kt qi>/=[UI^j^i!VT1ܨl\f\;gClǍ2V 8C}>sqZ}~oY2|ǘs}I;?[Y[6+KEX8vϼ$1rv?8,MKY9g-Z3JX)9Uˮۦ'۩bj]K%6yګ7Vwx@KCZ~  ^%;.P]yOuv2eU &_3^}eybIΗn_Su[qv:|bsZÊs;,K^[.4dGG;$&]%_`}? 8.=zKΊQRF<ЌT[ɖ>+BnT\|FlyS#y`_3c9Ky˘LҢ)#v]5mi҂!si>GCZUZIJKqVjZZ*ſ*iSb\M9LDؿi+UWp K$@$(Φέdrl]m}QgA{t7T\Y X $$E$@$(zn߲e@l*@:M7lN- ~)וWѤ8:l͓wט;_z VtFP%gq|wCHH (\r\HR#-IHN! @q6u:ΩYo,gSv^񾕲|]i}M#N ~?ɹbT' aތwҡa*%rp[Ӱ~hiAH$@$ۥ[RMq,c PMsp8htKKr=SEM9̾r(gn['~BsܩNdPA<^2BH1C9˷af c" pOrhĚoPּgݳ Y@^q6=ԙu    WZz[bccUqƷvWXQ剏G9쪮knL/6 ZL9.LL$@$@$~ ,< XA5H}Ścgq_ IDATj$@$@$@FlrԮxͭ=oS7/!Cћ yнT 8>Ț#ްM:uB$@$@$@pJ)ܝ4O$@$@$(Φ!|(κo߱$@$@$@8KqQD $@$@$@B, 8@ИHHHcx81Ɔ kIH-bH  PMA4M$@$@$ PM] nan8Y: @&qN$@$@$nzM(Φn`%H  +tx"euHA@͓Q<o~f$0`<`܎q*hon x>l! @8:Y8a搀 M TGi7v,;5]1#^9:Q38]φ Y9 @q;$cxs8\}E9W LW ǭ4:!{5 #wA8 ̇ʴ?v]F#usDq46Bp8{ o_ŗ5{2:|Fyd;eZfGbxG!䍈qCŁEVۧWO. &@qֽ'  H?(Φ`M܈Y7,V\D_8q_,*TE=?!OZ] \=W5F|{ʖc+*_U(GcFݾe*޺ћoc¾*4I<,ZG+yCҞ´CK(5nEB3$@iDlg$@$@$@.#p?!.U8{ڰݒs8e5O/!YҀ78덽6{;J!Z9\թ 2(;e1p xp0_1aYs+1S& 1btX3|}0"*PUńgd/=0~pwgݽY   'okp~No&@q֛{mfE4AF / wGR8嫤ޘ.k.^:~hT |s6ŠAh쿷z .\̙3cȒ%OHH%K|r\x(S ڷoP*ATTƌ/pѶm[ Y&Dȑ# ń$@$@$G89y/t!R"4"@q6XHV@ګzRTif AԍK36LGJh`>QU@d|gFV 1;qB/g~6(+3nMҎL|Ձf UD6_u#˰#Jgs[L* 8HCp۶mS"-ܹ34ibrJt%KD\\}֭>|82fhNj'rF믑3gdUֳ)vǎ1sn&# @Y5Y*8 O8}&yЉl (>BsN|駸{.t 64866V:t("""tlذ?#\"E(!@1sɨ^:~WiۻwoyqUN:N'+K>[p!~73?Ll0qV9ۧO8qB4iR(6LD$@$"n+QgӴX8 8ˡA$@$@$(&}oF Tu"[l3W_|\ŋ+tݪܓ'ObxWQN7|}P,ؖI'ze>}Zaذaȓ'oZ sT -5/  p8ۯ\[|yW.\⬳Rٔ"K$@$@$@@l^:x Ə:VZvuUX+Vƍ*۷nRe͚5K RE3g^ݻ=zPF0رce]VZW. *qZ%ҋ9)S(_S[,Y `I=|3㯳zg9H 8^{"  H g]Ky޽0aNk_~Q={LL#7NTay;o<+\zo ???Cvڥ[qY,ב#G(-⬵:j5k 8F8i79ګgpc\$4N#   7&@qֵwMt}Er,֭[0 cwҥKDW⬄I+kՈT 䒐 +⬵:'k 8Fځ`bqe.HgS3 !  H(κc,XBH[Lܻw??וlաa{!͞=nYr@B#H@DYui9*ΊݱcGL6 *//  p-qֈ]z4$gS 4I$@$@$@iN@jJ$>\eiXJ*]9fS,=` vUZ8!!K.Ųe˔'l֬YQlYmS)7lؐOVñrqXbeI=Ν)S& XhQbH:jŜ4*UX9+AdСChHHHQg%|$PM* 9i zl:,/j>!HlKeG e>pwgݽY   W8 A$@$@$V_؅8\/^^˱1JqZLK0* x:5fHHH3 OƋ0jvp#KUz4|}2Χi 艳Ȃm&   KsHHHl8kS@2g9(HHHH:!$@$@$@$`Yی(r ( IHHYv6Yu x:l +PuE:g`   ; P x%^l(:KIHH<,O_HHHl<.>1 v`b g=3   !@q6E( 8f ]qvʼ)VIHHH b(>bVzj֋HHHLi guVH$@$@$ 4$=m)Yo l# 8Fcܘ P <$@q6H8A$@$@$`bZY   8ki P   Y{h1- P    G9l4P!  Y{h1- P    VYN  p>̏ZC WdpA*T5s__Ru! x#5^gIHHAw7PP9ӣC… [o .X,رcѶm[̙3ݻEZn6m8dHHH ظi0kjH@u͂ &; <CF֮HCQ>5HƐv+f   4!}D~᲋o;ߔi 8#6o:tP̙_~E⬩MBr-/JJ1bɃΝ;JY "0gCI$tlOz 4>I?Ľxmf†_,l2i%ǫ͚5Cǎyf۷˜1c_@݃Fg m/?7^[>1 NN$gsȁlٲaܸqHz*\(.YK.Ell,J,=z gΜ*˖-S,XP-K*e3k6ͻ8z\;wġCPlY%K 9r.VHHEdkGU$HX=lY۽$62gΌӧuKDOqȞ=;>Cϟ_%O3t|0' $%`m=9y/t+Z2DYLplڵ~zL2ԩjժ 6(qV.YL?xgѫW/TTIGA! x_*1RDHk烞MKM%֨Q>[nŌ3|ֳgOTR]tQܾ};Ə[n%uUCDXyXfMqV]~}+JYHHRqmء2ǴlL~`@=s&f,9k7nżhQ/<~~ E߲Kñ$(Z*zn۶My޿o+Z5u8+/ϻwU PY⬼TnsvX`r(Z(~mΝ[y؊=y믿"44Tk?~ 6T]e^?rb(RZ[(P zVB s  HB8ZD k(rܐ@z$8oooL2)_ԩS5xS{]%nS3]>>>֭ZDO?bǿbŊN7nPIWYT^A%֊XOSs) ⬥e{=glaHHKlGHJB̀8{.FލqѢ^A*C JFF/)/E]e)欣:Wg[J 3g*1VS]*V<_MzX7nT"\Kz:K[y?{lرcj-E$@$@gk/օQ(Ӓ@jpFS7y`g׭[E)Y(;wY#[D@;vi,}&kmԲsFxJ%9+#}geKx7xC8p@-3,,HHi:7a@]φ1Cֲ|}3$i8x^=+;><}ŝL(ZbUvCɺPH dϥ=%. 3Ty/r%"(QyI/[ %/+#sN>e. sĻX^K,D n3% nSmxxS=DLqVHxDȔL??CmNbJH10w\Klmӳ)3!! dxQB^t ؖ Nf%T>rhmS1]vjX&żHHH ]g<Zpٟ>2E#",>J!KfA;Rgpv ng'p#{g*gYgƫ)[^jKYY98rmٲE!W/欬ϟ$ڵkzj)R_.qn "_t3yIH X(hJMǎ#@0(H#Έ"L-F&qVϫزVb)%k%cYl!\AٳgumJqV(1d+W.vAڡaY~ ^/V޾,Eܕ<$ڐ Rز aˋHHqVBB!i@=w9vX֠r>⬼Ȗ"p8+lhժ:lkĉ`ԨQ8qJ*;bذajS-\"Z2ŰCtDfFg*ӑ "`K_>JLC)@l @I  Tg 'KA\'^ln%  p@qY2,/j>!^'::&BܝYwA֟HHR]@ P YQ3 sb|VmKN-T٣|"fVgn   $(R   pY18=v P>րsHHHgŴ$ $@$@$@$Y    {PӒlEFg)OlSBz~9ۣpS{Aa3-GL٬c)1K2YpY9 pq+Cr%= bB!2cjyQI\+_?X7v _x]<\4daL(skcA*l9btxp]zr!YG殫殣0#EjX/֚I_0s6hq8|$&[^"{dɘ { C 18ɴ$pNqqDqdiPM.oVW5U/LkEl,1.̚B&3?Xpc f dÿze EWz Oh¬9KEx x8uռpudު@Y 1E j̘gIhƜ gފF q'Ĕ$! "5{!@$\88LH1zsܭt9׎a\jgn 7E[g슪ƃ{lԏ(+HIl:74r,;ؼx%㠹0:5>c@$v{l"5/(AF,,-[s}P]4 !w; pW_#tFfߊkk?uAп|{d /[̞&T^''"cGW}oa`;/cvA߭SmƪuFlos>>b M_&˕MJGCWapl]W[#VQSկ&|){$0[,(/ /V~~);NLqvWx1x/o^K-C57#wޫQI{o8Oޕs!ލ|W;ZBBbP9wb۩8p픡.޾ _xL+H V=zj竈R?v]F*f=xzDSf KޟQ([$m4xK_NEZsTpA)׍Uun\'%v^ŶY#kg܊W*%M-ٽG._@O'\߅o#<$'^^!YX{/^o67ШchVRj`ޏYK`_5ԯ whj3/oG+^4iK R?덓 a۩x~$DpCJ"h]&NF_[&zrG]^ 6?؄\YѠcv-.g-W# g =bl޷7OK+[5=g)JP3ذ i-Mm~{~CUXUsg{~r(d6Dk[~Yl8rZrSds=<)#׍'aJ+^F 5Yb"^ʋE*ϦN+r)Z* cʺ~:jvd7 m oa?KRXI9ztd"Q wsxg1+TA"%!CĞw~ :`܊x(@qZݯܼ׽MkT,U6h~1ފ'~`s WomѥeIv aș^,wh^Lj'ڭsxuh)oaڡfd͘3E-Sqe%ZSVO(r|}2Pч,g{`αz*TrG-_#W`|U7n._a(DIg f͍/j>[[WЧLk̖Ǧ8k\7W Lk5g03,[ߌCOtqX/bݹ, BlAꥌBhWL{yeEhP0&Kk]m/ąxNAD_|잻Y6)}˷Q赩CM{hP֯F~WܸsǸ_9N=kjgVN"FªflKo&]qV/OƋ$ay8kEl,19K:bHzo^Ri|$޷gc$޻{o58OU⬔`D[y9ڳtK}u?!Cw,~#!ˑ)y@GYtaM' $HBHh.RAAATD(m(H/ "@ $^Hϝeͷn$dܙyf+޹pp-clk꿃Ϯ@񑆄il`J CUUkyO[TsIwp>. sNW÷ ןu=/WzaE}v(sj;cϽ*/S7r~^^qV Vu_=6q! hjNuOY29KϵKQ7nDJ5ZLl' :cKYSx:i\կ[ƔR-_k>guSOqo$f*RiLw1j^~0!j6#g<{#2`gaYvw߽hϟ>ո;b׈]qi$s(!@N$\+Sklrzdh=YWlg\S5BId5Bk{'xs\P6o8k>l 87_ AykABck}v#3z.v޵C[+g䜸L !wnA|< lMcjǞďG`v9WgKؗ2A)k;BxCWr*8+k{EL=osU8;U6jWbvNApl}Q)Ë!lH_!EmPݿ|+1?tFY$vP)uguH?֨':IG]lԓh|3D-QFV|T$S%Ķv\gМwzŻA] F9 qv[-JX9cWk8KE%㓺[1-h 26_8o\%u+lmeyƧ$cktQ>8QMbqVA5?הqV9[؍0U&a՘\{ #&-f]YX 1)y)Ξ!Ęw/$.8  +kkgdxsz nbLˎ>yN޶_zz`ɑ{ة,. BP{k8w'Rs8+[ÿ~o9UKoP/NfDdct>,SƜQKB#WO=gP.M?ƞ\ڑ5Jgs뿃_ƓIqaz?55sV~h?|A i"<@F47|%n>k[9>֮'10ؐ7+_\gst]C$n1'N?ԎOMQK'Oev CrlڳC~Yϊs2RMHMƗ Ѥ| Gpb8K1g{Ԯ&oE`Z^xٻ=rxߦ/W%H((ZT49U[6? .BHzY:fm Uy=Awy'xk|ap,u0 t[Hx!)oDbQ>E^Y maY B7_iYRu@[`'Y2N%4^kciەgbV3 ѫ\sx9S顏 Mfgi L"cpeU EKc~C6y1`Yz; "f.ѐ8KtCqșN+ǧ k@17=~ iOx88K'#cO%o @]t#OHӔ$lx1Iҡ;'zή?wG#UmpEcݦe`k0ѾQ黕=ӂc\=pOƆF"D)VsиVI罂PD,%)=ƴ+KDYez$R@v㗼`mu;B#T8KϮR"O\Dcj[g5# (|=RtYOIGzޗZkwehMQ^CJ 3͙[q67kY}G~p-.>&!qkǦ%t8(Vbf IaJ)أP!0̺o?G-ZA[/ {$| 3V^ݩIJ>uWDREȮ'6X@yƦŋ"hK8+UH,m2A8@y׉ʐ 4wW_%W\ rg>iŻZcqV0%g~)s[ )2, q IDATK0-Κ' qvfWElW&Q,mMord'RNKߚf~i$eab֊RNxRwJߢ%1`$sӭ#A8< }FV8KljMlM?!ۋnfbIz,hiwV"@1cW_Wx&.b0Q4|=PLQx.$~l -Z #2`L 0&`Gk1%Ύ \5r718=eFԜ,³<bu*b-by_˵߽{yU. !XP`ɭDg+[*YOEb:`ZJU$,&x @Q³dU|@0{MCH}O˛0"lbF*6FRV֘758Ѷ}aVQǽ.=bwþ%U2Va,y-i5 oB2银8K[u5mOf}A5kJWY@0CPx$ LbM^8"J9 w黾[FYfƘ`L 0W9F.Wu k9D s( ls+Ϊ3o4^ Ю(v+{t`6^uJqQI)ss(LH9Նhm( +g r`L 08QƸxy7 Z]0sS-=4OX5̑ה%)ss0<[ ~-c-,X-McL 0&,ξ6;""?0%Q|R}HD-=Ydc^S x% " 6w 0&Mٗ*Ύ?# #KM pxl^_ ]oRRZ1_,lFw,}n5%&##gÔXg-lL 0&4g_8sbg4J{4<ԡKRpcW;ː:'[-K3򖾦x8kl8kaeL 0&X9y Xd=%5UsEM+28l:n¬5rΥ4ܒ5 e&^SV]kVCr\y~-n<eK C,'P,Zs`L 0M9cFS%[nŲy1 4,s$\ `k#gXea2&`H`^Njσ e233nMsņvǯŪk;1i .\7֘=U^Yy 5e0L@1 ClQ \ˤ\ 0&t05L и`L 0&P8Y,%DU\1FodeK{Hfdg"!#E ^tq^"csnJu ~m1EC}&aqc_${]@M-'eo^wȶ2m)A+L3`L@/gy08k4.`L :,,qo$fbsmLwu$e뻅XXYCxNH/~9y4~`(Uz=<үKk )#Ug;qL 0B@B0܅#l皙`L 0CWO!Ou;vTR=cBÕV}YVCD=L; 6vVOc6fUh^e G^Ēە; [)Xuu8 mYPh)x pluvΨ^ /oF%2"ؓP˭aI|5zLt=߫]wwm: nvEeg1[n 71-h%cz!8 n%>aH/EyPkFVG<0mR^+ gdL g-lDD>c!kkkxzzm۶ӧO źup-dffdɒѣڴiwb„ 4hom䊙`L !@¬5F5|gq¬t.w/ ʂ5lʫ;aoUr)Β)mQ7%A*OJ (.vXumE+uV]n%=DHl7 O"q6*? ޵˷ˆ*]4ui ۖB*''Oe$~pz}7{r-PzP";mqVz%oS|0Ab*9N𳵭 T=}}/*!N=XH\-&].R؇8@0)VW{ڃsYc/f 0&P8[ȭ8K='oI&{_>>3{h׮khذ!&O Cо}{TZUgw݈/ իkz*>P~=g8,+Wܹs_3&C`z9QjLUPSMgD˫׫|X9"% rw[vѝZ(䋀ab?[}+⸾W;~VVf?L Zg(:),$o< g;Gh!JxےIb$ߕkdggc|>rvm19P8{;A, <]J Av(Qf+ξjfbѱL7R=>Zw{m0?_WCPݤh|?]!s_@bT+zH R@A+pLN^9kՑ1&Ǟk.r+Βm6L2:֦M>@ٲepիSbرhҤ ,Y"UmA8oW@"ٻ4SㄈJʷuU$s. e7 _CubF )#A1$CY9ijB9, !9 ŭq5,L 0&<5@.**TƜڵ+?sYf"@.]0|paB_~YO.q)%$o3yܢeT|Oq2t~B{[Sg%O:C![pu G kq5N!FJ` g_A&ʘ=#83(R5kֈE޽E]Q͛7ʕ+7n*Ulr&k:,;ONE^31aSl8L"m'Ӻ⬲ >̀T6 yRY8KCP_,{ipl^//Y襰 =;qȼP lJ)BYpbL 0`qL٢08Ka uĈܹJg̘!b*=g } +E، DDD`ӦM8S;v9;;߿,bRXʻk.|pqqQzdˉ 0&@&`@=u]Q ?ڍ mQ8{A".\nuĚU•!κWK&c聘4|U&yϲ^Y?).ExFrbxëtwNWN"^u'+#2A` t jXL `nq@mݺU[oo-ZPJY}իWHII )ynܸǎCll,lllPtiP:L@0w8pw0{lq&`-qčXtBՁ1󧐐йV!ή{GC|3_x! T=TM!"2M q5>"48SL|'##;Z<ԂD/zm W-^IVBb#mQYE31&#@p.j<K,Ǐs3AXq1&`z!Ce2gؒ9+aq6YiX|L 0&@'0F/XJg q &g p`L :Q8,v-.V]ۉLjI74gCL 0&@(%1zOlތR8[`L@ @p\V,ww3p:>@)]X m0L@V]ۅ 6ֿ|KUUn}'@+We|BD ŷ wwwgpņQL 0&+MWzE"2&# q6ـꀃf#3xf:/LO2N1wѬ:Y2yohkΑY=#iWDL 0&NW}B|Ε2&`%x0&`LP%V11r2r&P 8[G`L KYcq~&`L H`qg0FL 0&@%` ⬱/JvcL 0&K!a ^ V6Z 8[G`L !J 0&` 8˳ @Yq&`L`q )w 0&c,1pp0V:pxyPn!>NL  حl^_:`㡾Y1I^>vj犏:733v@jkèFsf&`L 8kSBYSWYxme dgg(5''3ƴ8kxa +dArP=,*h0hhֽy r2fq; 0& ,Z8s/LY30liT8 {tLz\vȢlˎ6g ]9{@7&(bc? z ]|r;NE,HdqY(`L ٙ826D;T/k z]NWFgs X"g_8;$^KWUŪ!Vunp30ѻWеEUBTᛀAMPpmB4&;>Ym}VKm5gu,ƩJz6ŦC.HUѧ| l}L@,&SdbqbNm0ȣMX5(0;`86>s1Ye- JTEϲ0ϒ8 iҜx ral 0&cN.{&W]ɥ ~l?+ 8kl K[$WDgHH*ޘZu ?,;V~>;TexDG<7Yv̑ɐ8k l c*(81Vh:9LѢM*@i/I_N8w;R喒(qd#md2ꍃJ$k xY#[PL2ڌ@6f>Tmz'ȴ4ژ]Z.hT^9욖K0B>[FaF1|v0.<)krR},Mi7gKƩ5$*YR OnlG)C\}0jWC $?ƚ8Q*Ct^ J w4W7^ D׽Ӑ%'ڤ{DŽZ}eߏ/CFc%Y3K^Yfŋ8;;~ASbܹ_^K ~:֬Y7o"##eʔаaCÅ͜Cf`L 8l8[H&w#o KUo0;wEmgj-m>Glzf[; 尰6[^U/[ȸl5;=svv,vmR'ersvOƆ6xS2JqvшNs͕-ºDLM}e劳CAtTLkZNҰ8P~1WKOCapsgي.蚾v,gMӱ'gCOA~?b;>9rJ)RDTĨQ0qDTZUv6lHD  ’%KŊ˳'<$W`"F7o?wd\ fxlbB0|HCkb@p뇵K[%b t.=yu}PXM`xemk; ߅nDy^@.k S?ۊ_ڀcP; _%inَ?)(=w땨6^PsbbUJ8z],Yxj[~*yAr$- .o}u-J6^Qh) zZxoݼy3vGGGO?Wz.\(i}Y#T^&L揀Ԟ7x3gDZT}{ߺDFF[l7 A{̘1[rc !! 4ѣ1m4?֭.2G1&J@=Qպ!1#ѩq,ξ.SEbi/Z #`G tmN 1ط/K؎ [+kҽAyqXnx؃kYj=80DL:S  Qј7Pt*> k@{ lZ;,BVn^@ß(DyJWg+5p.B!V  XMag_B8϶'yB\ j J$3Gqx.cTv!llcRnewagk X &sd~@f[@?dX8E9|?h0sXh ۣ_3(Igހ]2hMB"qXtf¥>xQ!~圣(7L<:;cJ(GG/W15+λ~iH5N>i.qV8(mLY}$uіWUm+Y!!;5\c!wٳ'*U$;O>}EΝ||zEGGvL>]PXhh#W27] F `L 0W+E$g_ZgC[Tۆτ-FIG7l-Vupe+\CZֳrG/b?2次_mFe2?TlX%D9ܞ9j)z< T=ip):z%M>+"Q;g.m~:}{ gi?G)`sǖgttc" 88  37${P/(sqs@+T!p$2+2s(effR/Xn54˗E|T%;hѢf#%ΒFCl ;#:u(P"Rs 1yRC޽{qI!RJNNƈ#DlmmsS+W7iD߷oN;$pL677^}>|OVIuY] M<.`g_2M-Ω7o#Eu⭣T 9N/=ۣlSTqчAV2_/wdlJAp+~YoE(0<:|jt- @1dV\8y 8j.uEk jL;4Ndv’l@ V]'Rlk+ R;`( QI9,?15OĘak}O8{z,"$GK_"#g4< "Q!x*c(V2_M8<\a E|]]Lg+j9ksvP&,˦bΪ_I쬀utHB\qu{ewqu; X@uSH>GvP]`)uZ%v\^$R(٤dMf(W$"5f8v6о|qM28ɵ8kB}W?C⬮z)ʹ(ZbkҳlN2X`p%1$%Ξ=˗/&"ݻwEXg)$Sû͆m۶iٲe*X]%zʔ) y겓/dy*W#GꓲrY/И85cL 0%lڙ@lqxvkN:jV[l qv~Ux7K:olt86:brGo4^J`LJ-꨼ !q>ۀO0.0 v(9WҲzrm1scT!A'@Y}wʶOSTA}{)D n;99C1M!Ψ qD\ݚKĚU![VdUgۖER~ޣxCO1l$'kn(*-R޼ʭ_89 k]qIO0b[qȗ,EZtw³d̹8E  @"~ ]FqR2I6>;*//mn+yEm_Zd4jŲӕC*soQzVh:9LwZ 1iqWl{]Qap[8KyJ7Tqk~xUlϧv(-e[ٶ:Á"@LC8ANB:;R0xGd_ ^TݏN4[n5@7}bGd99_ڛMMSOqeTU9o\!J? ~M2GX@[-%{M1~Ů"ŏRlEh:ocaJVA?FS]agm%aۅ)8Km6ët nRbs[Z}q*i" QgklMgɞԽC[W?SQs=tvՓc@e)-wY՜ƾ(ɹc8 P^fI-fS}wqFҺuD{{{tM[şŊC~@a-JAAA“^A)mŊst 733QF=A6j4gfL 0&,?)X5aL 0& g ۈr`L 0&l^ cY)/BB;[ [Ҷww%4 `^֨z!eHm^9k L 0&`qRG+, +_^ YL@4+2^grXeqV9  /o뜘`L 0&PkA/ gy^0FUKZNc؋/В)Rѥ4GAWoLJV~|Fv&&EϛqAj6zOh0 JRnUFW;'o=xP>ږԠP/Nw GcIvnveaҙ= V[:4D)H|S/gDr 9<ifi95D|5KՌHkZN "iFu\'X{cF٣رh[YU2g`&],dg}^ ݠa\x']NCVvum1=M8k^5,:m1w#t(SDد}aݳ+wBRÕGbZ#Q(woђF_Ƭ0kR/Ɩڣxs#v%mQQS\8(ʷh|ua-&.Y, .ʫ.W {'z|߇nDzV qg7akWiE{}'`nxGp|_/33҆u|ja6y[?(AlfU邝Q'qdQv+нO# ,К4\ 0&$ 8y`eI;gy0*RU˷q:: gcq&:i %DO3AUC{#6A'Eܰ釘.=7+u;YrEKr؇Qѯ\K"_gO?L:R`RBkM/ItG}z)^3Ę M?g Oz/^N(h9 M76 kol>\]Y[Gn1,ǽh!%e Qme_~YF1Nsace#==h1o]A5Wy@GQ}a @$!{R *UFQ"E, PĆQ齇zI%?Y&ͦwGy3}?G{ףmv$ _>-Qhe sߚV߉21+z8 n\Vm9kfsEcl׏;ؽ6NV>x-Kf,Fً7kf]X`n1w; !A6o4we)lL-7.G û3qvc1|7P>mx_nǘ}8p=q@ot~fk}6Oxw־YWsA })YgqyCD>nvmi? Ȫh_[o>t-/W/C%O`HnN@"ގ).eB@8$@?ڏ_8+F" q (+fHӨy?,R[yo|ҭe~x^ڍKǢihua*pܻM#báBP+0 q4OFEnY>}N&PpՒ}G q(Oaoj퇹mG#&.g6~wY5K yӊe5,h0n!)1Vk%#Usf)Hы^B+Q\h`ALj6q{o#q;YlY+ q/fu5IYc+uUΣZWL[o`!Gf/*oa[:+I_񙀻[exȕ]-uy=W9;deuߒ_! bB g^:/H:+Zr"{C]=c=Q-VZaBk[*Y>s =Ll&[AJrs7F'[4r3Q@":JdG𜶣}p񱉳;⬳Q_x/n ^94|7}9,c.c~W:6EsI-Zײybk}3BEOثֶ#q0Uho 3{0 kP/?m^ZZOӆ׭'+ΚCDs}9Gkb3{5[ZK3{nYYW7| Wl^?wVeE H,ˢGE?798˵h=}LKu9[cg'u*hfܽg6nzqH&6v4f=gͮm:"?qUq5=W;hU>K1So&%QJluU3!3~~^9e/[ OuQ4f|>w [;b܊IS| J[ev5'횋J6=WP}׼{(poR }O|" ^._LZ[ڋfxMz(7CHYc[oB }8>\\B]qVmlvb3UVT'cz!v%˸y +q, (=b%n7mulzh3MaV GqL7QbY>rE'6NJ8O Ͱ WHƪK .}pXx#hb6lnk4f/) DPsE(^k);CY"YF&[#IeǯbA:3-cZLwn?FG~b]F,mιa͇*uAD"xn'(wwY3Gs9 bֽ!;g8kƒ^eLf1g&kfO! ثlkazfɝ9a|f+"t*/T˖ǒq%!=/ |O *zro[;-Mڼrغ+ØFI={ٽAN{IsYh5 YP?fQ=ki?z]gLP|G%r_/SG,?#Xv=Lsݙ(F|T;]q؇5`XaCK|^}&Ν*_f1wr5(\ɡ8{ڹe*_y+ׁvW!N\è:}sx%]:ikѬ8{v'EunΒC! ҁU=gIްv3z`bL8|;wfXʵU{1ث5z);F۱y{_閸t*mAĘs (IKLYSlbtp /{!k'z:+vVD]8~dC6+^8p]shKދ1Vm~̉Dgwb+z k ;^F{~wh#FuCװ}5>f^ax =Cg]C{q״*;vX=RcڽY5x_uucq,,j~;&UF,_2^?_SwW= >N"Sb^tCKqo$ QTU%$h1g;* Xdxq <|q/ ! @$ lTv!qct&*y=ϱH&\5s=X-Vèop$#q6.d=d4i 8mmbeE Hn7I= #+_@d%-$h{p#`_¦BPIa 8NO;"" Uq)!мd-evطg"dPM pPI|1Kb<@Kf/v,lIܽNր>>u Re[/P^A%E(r|:g[k;쓳-K! H"ΦW5Jl.A)"Y֙".Ygҷ'K5ǜ2І+7sTkI )s۽AYZ/ z }j܍*, e)w uۀj,㧿^!wrů^O}2gغ}jޯhongNBBrbNl;JRPĿj*oi[ wtI&! J?/>n,J q*4' 8+6!B@@Ys+{d%&]LE! 6ދJ4-bB VY7"B@! V$tx _GAlPB@EJ *듈d"`$zzF! ٞ@n9'P B@dg348fT#B@x&* ! 99qVeLN@tG, ! ٜ@Ng4HB@lB]Wll\K%$ADA)CB@! ҅U*B@! r(gsʰ҇UjB@! r"κC)̠D!  #(K99nJe@B@!  8aRB@!# 8#UDMoRB@! 8gP/B@dg3g渱ʀB@!`J_/_8+v#B@DuHrT,?VB@! rq6GL B! "fwi5q6Ot_!  g=QjB@! 2@Br"֜ޅ_aW.[IѪcQFgӌP*ȍD͍.cB@! RqVB! Ȧ܆poꍖa5.q6:M IDATH@82f! B@Y! B ctMsiF'f"ٗ ! 69ciO<;\d VXÇ^u)|7ЪU+t1/_1cxDÁ0qD|'ZB@!cեBvj?>-UYM3B 7q67κY! @&l lc#u~)$\N.Nc@x''2\}gq)C/S2[gѷo_L>=E/.]cǦ|ĈJm׮9NFcHfz!  hhA\Rq0eXsf*(?k+%n?^eDDq6)) +q˗ǃ>  ^{5[yAѢEѶm[w}9v^x<hҤ=zqHB@! r [.UFvbf&ju 6\.nڴ >O>ʣQF++Ç&MBxxիWSO)/PYllz>2e qF|8}4T+P駟*w֬YJD8p j׮qٳg*W{9ëoVyΒg}dj޼9ȎϧB@MexЀ傊aHwQpE4)Z E3삈5;RpBqܖM GG}ooo{ț7or{?0nܸΝ[li؟gǍ~P$! B$}, ٱhڀw PYr8K[nŻᆱM6ˊ8<Ï?N>S,Y}޼yJ3^|E˨Z*~gR>2,_w ǶmT(w]|(9r +V>5k`8@>Q֭kdB@!^BBѻ|;a2Z£:o^\OOa)qRFxlLLz(n߾=~i[֮] &(qB !~ ?zz\2y.\Ca!Ry q%O,C<Իu>}(3fĉM3q֨O?b݋5j( m $R3pBł?DO=5BV5k5k&#U! H; ~RݚoqVصkz~~z8i~ZY>[1gl裏>sذa;zjm?2-}A4矻]~ltN15g KZj $ ! Hovcq%:FE~BP*('Qa^>Iɷ_8޳$ o yPFlFWCΝѵkW<ʓ¦&-[V=\;!22R|8/][yΜ92dJ(oѢ?y0N=)YnA3*b*mrӦMSwq,ɓ' ٿ*=M6U㥰DhM^ܒ-[ իW7˭|F@! @!` Ξt_Y˗Ѷr5tЂ8aY|nɰxaPgĞ={|Fq%۔[|MTo W@v|Ym&O ˼7_k[}azòHl&βm33Q7n S ! Bl٠p 0I)w}9kݸd^Y+%HsQ[PʇS}ݻ7/هpTw;bX |r9˝VI/;[j~ +WT}p&j}3"=ԩBHB@!^4qJpIX +AaV54^ xHuIW8!8t@WzjI`WY23 S(X} ?~xpOR_uQ9 kxdAkMA1с`RP0ыfmWTIyгu;{* | XkYzHB@!%8 k@v뱣Nݵ 8Vm;+ЮA1tjZEMs@2CTQ-S \k=(((aY|a ___%j?s5P:tb8nKgy0?"c>jcgYzr'j PW Q%I! @zRBrQ6.߼?b!,0k kIԯwkDMّzܦO,%nS |eTzқb,co͛7믿*Yza7>>>]Yn FBjR1 kSq&ΚuB0feCeÆ }rM1{Ĉ!O6@FA! @!`"n?vΜݵ W.[g糣0WUzKt1 |AMOS EW>h;糊+u(nR' |MATR*+0eywN<ˀϷco4h7srKwܩDgzRbjRB@G>;`Du 8&ʓ}Mb#Rʃe@"#V@%( ͋Փt̘i C@}2#֭[[*c/R~Ճ8==.\`XدJO?8egSB@! 0% pn@"B@! @# 9oNeDB@! @q6CqKc99e&eB@! @8&|RX! "Ί 784)"B@<"ΦSGqksˈB@Op SظdOwBمeB@! @qVt50\! @! lk8RB@! 8kIuV7 B@!`5JJ WYޖ{G%s{<#F*voP:E5 [NY@J}ZS4pz!psz˷1N-"⬈֭Lr ! &Dnq hhd3xbW\a- .WYh+ V0(v]V@Yg؉B@! $$'b]%z^%ѳt+4)Zy|,3(lJ@zy;ٰr8v,fZe't0U ^ިUެy3DܿdTwv OqѪxiHJv=2gݬΰ;"+J̘X // /U$$aʞ?9JuVgvTGH1w1W`tۑ5]-.%\Ç;gcK~C"/]E(XHI၅|46o^gMWޥL#|>:(gԆE]1xd1LV1|k#g؂˵UhvI?ZէwDmj8~+_SmM`Zz2$899[7pwDde6&p+tB_^;w‡=Kuj?c~*vyV .WjR;IJ]pHJ@bW[ʶisDRMޫRJ]yzzn zq>:E>3NXЃ]6Uv2wG閸,B w\Z:ݱaxz8ujLm Z6%24j^5ZAar^`,)V÷L]zY4\zǮm?BPq}|#>2կUm8]}3ȞgW܋(U0iWMo:roƕ7P# ΟVbX*O3-tׂ8aY|*_2,/^}CYª'갼hd2d_>(UeGoȗڋ_ovtL! ҏ{xuEu2RʃZ!fG0pGUb8a;.'Z SpY%\IOI7zS?W"͔f/a!y}q Cj>".pǮț|J`uT6s]S+Om7gkۍEbb?/笳k┽`H}colro܍˖gk3lv]{B-V F-Zw@Uà ܕ| ly'B u+PH* sYƲ}QxE[$&%aښh_& 1#/XohqvŖ(Z(UJ4DU|SǗ_~KѣGg!On X:m'pBlMeZʓ\ssw 8ktM5(Rp~k^X'PͯQYu{,|BGa[/on1>`qRf}7[0=!ǜx E3wtڃƧ~jݻwoF~Cxx8^x|6m'PcP125ogŋQ\9y=$FO94OfRB qV_ά }]מ֞#U5J{;nX_=>)bڏq]&힫NF[ `7+,HʻK5C%bIԯO.Һ#7+Gcd3Eb_RL^j?Ymrn%t˺x">V.PCj=PQ;t^1#uȘ08#NX؋C~ ,l cp2Lm9Dy'$%blǕ7;_j2Zg9\7v?Yh⬳^PSn/w}Y3+һd[2Wl-j_ؕQX-OvY{B-[$n݈-Gqu$$%Rh8#ځ-Rt{] IDATq{v(EѫncYGO]QU糣0WUz.gWUGvN[nŻヒ7n(S VmgQuy{{_'|___={ |ǨZL}#G`С3"뫯 }ؽ{7,X^{M |TX9rv)͛~7УGt Ƕm0fC zqPlgΜ9*ȺƠO>;q%RuJB@OYXTll8Xg)*26&;թ8(kIa O'okkܭXwCD}^GLޝv/SqWdL]n7G2Z76݃Y[TwfhL<|h-*ͫZ_^j?JwU5zUFꎰj_uڵK KR-[ Œ7oҥKK/rf!ۤI,^ׯWB>}e~9|Mb3pyD-=S)>SUQZb,YÇNq8x {=%%8h"]V L׮]Sb7|XuS`siR$B@dYf,ö ]rZDͲ+8xcآ[ ̚H _bI~UXM7|ecQ/c=z2h?X:0m;wPy ޽_6EmMs(V`)VʙCIz C6NAlEӾ1)cr;^ Tdݯ.PBs!Y%be4E'6?g㼌2їOǯb6F|E]~|TAk'0G-Te8څBh6?{/`[!Lh_ %CpQicQO V枇9b̮1g֮uq+bd ή9?nZc= Nزsv|\.͊u[~J9+y={?TbbӦM]~-T~}%HΛ7GKW>w&RHә3g*QfzU˫,\@ƍUXR`~G^5kִ 0y-/% AыsELL  dC)cǎŔ)Swzq֕r.OB@,IH^e[߱fI,9ҩ@ U1%></,8ybNz1R"ܤݿb[[)(1'E'+egЇ'{ZR|JcxBԅ#✊,W۶mN ߼*7bA`zp3F-Ěq`(Ve9CYe'@>;[&*6OwzQ◜}[3E|E,SC߸W1U]Ii+3a$3n/lڋ)u™8kup$i_UB kK5* V*z-nsm t]D5 硨صkWu@>[NEa'dڵʃ>g^b FϞ=U=Eȕ1h|TvJ]F]qVYf-لB@dUOmøm3Z*嵂"ΦT 8gژEDIrF@5^i-lZq6}fj"Ί8( ! H;D= ^=Zjp), VUg58VR>WpU͕dB@! @'0y& vx$222Ŕqe:\dB@! 5gI3E^B@! gSM',5! B ] 8xJ@ٜ:2.! B%"Ί8Hf! BbB ."){zH|Fo+#/,Vbf\Kcorn4VW,̶8++#yB@g4Xl!d99rZo tP +|O quf\B̛2f8k\d=JB@! 3γ'}4"fmXfVpf%`>Zgs"9Eͼq6؋8+⬑ @x̕B@3JJn ^ 7mMt ^dafkxfቓe]-&%%ߥu2#qg1}2 10moFZc_699KªC{}|QPt^% v K?FP)8+smxahxp\QW,Pz|% V2p؂?b֦޹x#W6|ᰚrA0iG?uUV8k?gD=z =ߞ[WyGk)vawܝwE?*8O%#q%zFV߼z8]<\هGGbu/-΅~|YǓ&M|ܵ73im3|KcK2KYY8d$>5':6" !:o?<_> 㰰\ˮ3B 'pV8gZƔ2J}WƠϣq[t؂MGLGb^+|}]nщ>zGw:T&_DX@EE2i.t*#e;OcщXxlCFgi3/8sZ.CZYmXeh@AX'\:/-Yxrtw^"i}X6vwpjw3-U13:艹`K K{" Ippq޴eYQM s8klg_ŀ5">kC2 !y(|yDM"r͉,"B٬8Kҧ,O bm|:J*GD|l:roƕ7P# '.w9Walj[Eeq&9k+k'CاKm;xA^ wσ;ѳ8v,o/TYo)Ɯ?1 OS/_-1Zw\xF/^2+O@ҭ磡/ú0+VedPOzR~7P>&Gv|Z~p<1VM`BרUt4f]giyR}gO$\ wlBARR[/, J2yw ʵqV:5_+Du/gcԂ9xu_@~xA3r-Dh`|n CpldL4-"1) ,E*5V(O6{N-f' 'ΟĽyJ~ڎS.w7Tn"a~p-Ϸ+&.WT`A\rQgCua(n ki-c)8~oAn,=Co~ yg8wr dCj>×OCK=KB٠bg=Gנ[ɦX!\8KAVCm0KS[H ߻$xReqCm.~8H1Ts4,RYy( (^oʶABOU9qp~;ZEH_?XM_ճRJ~<{J5LjoGyh)6r&ձbm\ AP/Κم"?-;؊~~YL<%5%3"uxv$$&%bJw;hhD/sIկѓxC;1 Qin1w#s#ҷbgyt-چdGsFj치wa1d<y毤hX匟O(k'(JFkb'B %wzb]~\hZ]d\` >:|OF1gQDoZ:"yZ5uyrǎ0*Njc;s?_wLMkOW]{yw VGWp<\N%M/[OۖCw%fl:*;يFqD>xtvk?Bo%ql\zQ2wq%XMig00n_@0ߌ'\:(1ڍE 1}9TPLK! ?HoK5C%v]^ЙQy|笙] T!&]ݱc+x-Cx^xcWf{eg6dvX-_ZK jhzE3[ᓕY#;a(G[ᦞV~6c 8'^VGuC ]=8J ɉ6>W!ʈ0T`Y߰zf8^o"ϵvdxw OKOᵍS|;2բ*W20SiK$s!^]Yoo[宯z+bɋ^S^KG[I߈+u]tֲ4LQVB~pVWll;2SeLٿvmM[Ht 6>YznVSP*j._kZxqTԅDWӮJ W,o劆ǏWXJlſ~٘][q3)7Q(_>X-8rv:mW O?kZqGx%1wNQx8BC Yzζ e͓9] IDATm_Yg:X KdxBԇ50 -q;^/GT>$o{By+3ِsA/i-^)q&% z3#b3>YI5}kFUԋΘ_y%3Ƹ2SdS\NN;JܣPD %47.يS9igU!%C5L5zØkPFɬOQ*Z,NHN{&Y\O\Si0ٟw<6|ҤeƵoAg}¥)nq hRDh2Sg֘J= ~۾W.cHnU-Q$jFts^<랚//PHacގWk],-ځ%wzMUlX!k+nVűՋfcKv&ꈂygŇK֝w߯_PuVw vG\WNyd^e[ U`J,m/;)5!"_KX:OSё߁`-`IqIŷe>-_6wFSŒYMಱ#זyEUx*&ZQ"ɓl^Lo1om9_/\7OUNlaHkԪ}mg)iD5'6;<̊B wh1͗&5}^ŘgzӥDc%:SV4ziE3TQn$D•Ts*(ʣLRN=9yX xC7Ɓg{~Jsx8u-m^< .RsAY+qD ,|jwu]M6rpIez.bGfהfHY+wX7xH0[e_ƧQlT TY..zSHdc z(b;wj}o ?mCkVjɭ{.&7}w텼VDMoR&,=V\cϡ\0F-!̉܈k Z7lO_L10moG -%7Rݠ:K+kvXm㋊EЩZ-/X<L/:omnmMc VWvb]=`nUе50VnnmߗBZMigf|ׅz_J`ҋU1th|7"cf2Y3au"-y%8k?!}[ͫF:T1M{9k^8EBJ/:S|gYiR-Tg~RC =`;PE]8t;y-Ω@G~!O6Ä3ՃcnH|2zh0boc֡G[FVA=gw"UڅU;vl1X̴6 OHxxLgyf>\"sAreRyl[nsG^pp޴v2V8kd'f`tZO8k"a RS,=;F\(0c)3?7"Y%j/*7<76M'տ+k}Gyݨ/[ǜ+q5UχbD>K1L!c`x>Xrb =9$9z}JYWVkO ,ɗ W/AoQ-('_DO%xF']wx%띻64/ug|VKfz?}:tS;xUc=ʳߑ8߾ϵg1''C3ճwGV,k\M@&,h-hxYyp[1']epFE` ʺ)κH̭jf]q6;15-"Yz)qZydŹH똌{b9Ns2S)= k@q/2(\p'ː`Qgqڷ@Z S1M&zU*PNnss/b/{Uѽ7$!Hh] . "aC"`)"4"O{ EB  !$zݽ[B6wG{7gf{^h7/\rY}m\^pJjD䆻&KvDUqV^DM9 L)RZX=qV/~%*z=hh`K8;#0n7"7^ܯ"~V䬵sڤXg/??bM#bIE nTz-"Jd-Yۜ$@q6'ڹ\?UY s8@+lL忄ݓCqVtMl͖;D2w[E7#OmƹĻYxl3 xֿ>y# us-WY6%!)}z䖵~%*iw_FW7~'FH-_ j)YYG i71sX|bc-mQ8 F/;J}6m_,*B"UjtpGlO͸}1>.\c8\3U4 PYqMHX̣8(f?c+P$9W:ag=OWIT+Ű3ɗ9T2WZg-뛧YӁ`K7Q{k~FBeVe}uPz9zA^zy'%}?d7#gE")-:DG=>HLMB1*<0y ʳlJu`IښC$D[څ+Z]Z}.ߧ5yu8ZywVA/_Umw aLٳ\u"&]99PVI2$3]pN:gA{䬉QuxP8$=…+J]!W5S#8SySJBS%at TAjmrz3~C;5W!@q.B.pXuZlJ$@$@$@K`BstK:f׮]ͯ]p;>L}TŽޮ]ê}SkA:_^[ e,\˹sjWy-Vk v'!!c$Pc 8G]!:|pcq/Ƀrv:; $ҍ0r_v؛xt#Ts=ev{cX1ڽcXGYk% x:3tO{uE]d_5ПkwrZz)n_\U QMQ$jET0Կlv5,=¬!bW) ?&7!ų k9;wl^Aq֓gy,;54̍(Ĺf>G&0Nü3z$g8+WYrr=f߽b^H =J7ڒk lBy^Aq6N4(f/_(yop-{Ɯ   91#f'@q6O!`8 }"L8ټ395Fq6%  ~g1 P̓!EB’}"ټ395gsx]  k(x *V)P+? a%ɗ0tMna%0֋xyxh]@) y^^X֙5eC5mu>Q_dž jߡyxeO͡y-= j|wϜY35PO1zNDE}fyK(q7pOg?YSδ}Ҡ7Vۉc4iW!ڔ["cύeS'\6G$@$@A@}Ȉ}3Tdȋr8;PL? [Դ4*R jtDuZMC_L]CqՇ4]LNM}zd 3൓#wРrAeOgz)b~̚.D0Uy8tTv Po4q8#⡒u1BWU8fhύe\m)S8c$@$@$}(zߜs.ȍ⬯O>fn=W43͋Kۢp@M:I~TѵF#g[FAX`lt/Bi_W}I{Vjk`Z xst渕%'֣}TdTvstkUw¾3QQ\u iwP!Iճh#N*_?֍?|tk#I1nx몺ؼ~t(g/=ObX)~vt_SOP['gS LbYJz! V"LHHO/ƾ#o!2(BEJTnd.s{y[[??C5.ʹ<'LkY[r-ӝo~#oY..L=ߌOg=5=I5r[#BCoiIۖOpQl _3Jݫ i[~gc"*XGX+Z~/ps5bk  6Lkm3@nge˵ċbCؖ㐘z]1)Xv}"n툊xcTCl J5Sb֮ģfq0xW )n )mq> Vj)ʗOϧ6CSS_5SۺJgŎɍaжrUE)%< LcòSоL-=6|b0[{>]=WxA{ b .lȏmik\̭m='0*ZSkg/VOD5O>eؖp8 NݟWy8kdkغ_X\NܸR=|X =`뾠]˶zܻ-Y%C$@$@N⬷{*ΚDz+fx9]؋m*rv؎ Xz^>"#}d}4-V]ڢ7n" jX*zUmoU1ɕÑLT +ᵻ4 A*xd=޳@}$R.tYC-bgg-*6.U_E-0$%"<&X~A*N;ygkF؋/}ܠ:@EE燥mFQhR:/^v|PK4)~J~323`ԏ%Z@ wέ}yOh8'XP!å᝘#R3n[ŨgO·+V1w}>Rg%ƋkFJCI T ǧm-% m0r\KNig_tPS ˫h2UԸ_E>z"M%ɴ}F+Z$›| "Κyy'lE'f193մw(eugkYDVNfJ%ͱU5[>c)ֻiײ{qoAqV)Y{$  Ll^]-FqV['&_H| 6zW}}6M­Tn6PvJEtV+[g9+IwA߳ t,n&Pw^3 >~*/k)HL .%0a/;V\ΈVD91ޮ,'+ǭ&;lT9 ."x 9[_rJ!-X*=zm$ )#!#g._{sfߺ&gY)3[UKUB~眝NEuί6ǶԮqegcO֚gmOk|kb_pkˮh$|ά&uAGk><ЖX9kmՇv-,f:0V2t7t@q܈] @5J0Z,/@2|~F֣82Bvr8+$ѩuThqSF؞pDM/Wj9е)Yi/M=G_s¾(R$K٘z= 6CEJN+iױ tn]ҥh_ݟб|K3/KNǚ󻳸޹|kU.HH{~Gr>YgɱW85ϋBL^6 >M`s[9=]8۷o_\pAÀ̞=6$N> vDn ;KϞ=1`T\fgI} wgRgxblYPI NB\#uO)5lޙ˜ Y۷oWwܱi=жm[SmD駟l2cǎ矫mۆyŋZ*x (P@5m4R5kiРA8qݔ)So>,^IIIFQhQ:&KqV.=qØ:u*&M7=[Bg  \M8ΗCirzi|^&@q6/.f"@!`I>w|lޙ˜ Yݻ1n8sȠzVZf{S0d9 ReBBJ p%*bZjM6j+'|'x*T~-nܸ J F^tשSǮ8k.gYb<+ ZIoR͵K<y~9@gPͻs{FFqֽv֭[HN;7onxJrFDD`ƌ߰sN%Jٸq#,X?6l,99ݻwܹsqQ%Ⱦ+Y"&quaժU>|8:d:}՜"g0|V$ ȕ(i$GYr#   }T"bN(~wL0A5پ}0Q5**J嘍ו~ Wf%5%WJ… q TZU6ڵn{kj#gm٥'J9sq,X:ttb9 @#`+rhTKq(m# ]qHHHHUJMM*za_rUk)REnLSIHH P1pn&`TNIHHHD@LPoB   =g$N@c   3=NG$@$@$wrku ,V0 i0 `݉p95 Nmġk a%  0Bu:T9F` X#8;i$Ƣwި_>0qDw}2dG6m֭[=zq8y$d<?~<=~G$@$@$=(f8c8|9{&ϋza[vT,\؃L;>%|2ڕn/qIhm8T V`vg2;gO>7|m۶U,]۶mcǎa̙J C 4h^|E޽F5TDDoXx1~sQQ5k|^zM60Ev>,oߎ ܹsV6.WXl衇ꫯ/B M+VԽNfͲD.YDٛ2eʠ[nZ?y㏫ky!98  !gOTOnXH!\6_>w;e_ ީlD$@$@|<dZ 8AQqv՘:u*z-4iE۷/T_6mRBB J81sСJ/[NkhذʕKիWM[hD_ cǎEff&F>RgϞYSu#&&F z"VU_$$"… 3fJ`G>}8֬Yq81lB$@$@$`ggk)lMIЯSȴz'3MxP|r]KlK8k!"n>~_-c뽂!f!ᦪO&QW0x,:`+  Bׇ>R8K '8*Jc*Z3f(ZI{ y^_z%%֊x*Bc=]ݻ]vJWR#H߷+jJX5da6ķ~k^xJRvg%wذahРZjcSJE[~w6'MHHH8{7 wuT}Lܸs +:s}>v JTgg4} Ϯq~\P8DT+'8l|c٨h5U^^?7V$@$@$,݀\ 8vZL2EE6mu`T\YՑt"JĭP-SԪ(ROMΞ="oEJEE{}+}JlAX/g%E*h\i燧zJXtbt}IпÅfS   gs8[gN [323nL91h_ |}^XWRp!%CƵ7ѩ|+< >>>Xa/Ax7T)XWSo`ꡥrUO@HafrvRZ~Jz8izjD@Ūcygӑ Sg)n^,pTWEhhQ\MEOO^\ӧOWe%T"g%mDJd8[|yYI# e#СCx}P2ryeSټy3>csVr]2笴sʯ+yrw܉Yfa֭: xyK֠dž 8|<@|Ұ7]__ >[ENk:[e7ax.Xun'Υ$*UۙxSz9Q`L:#*(1|Кѣңx}T<^)ʇE6u"*W}6 .xiXJO{Qc8  m  /#@q&u/GY+WTD=z| /޼yS*URm+yW%j6**JWFArJ~XSY9LT ҧVY9 LV*+9rD LDUV-[6n8 ElջV_|..]}-[~wu8$w6lPkF$@$@$@qֳY"Wݝ?OP )+hZTa 6S|2 S {5mJZvj~:#v+*Ƌq;]@߮,$Q Ŭfxls%9݅Hq."V  gs:/w8#ΦC!W (X-۩S'*8"؊HzI*9fESH dbΑ_V\OmR>3Tq= x 2g$qV(`-ZDf@H\(٣$@$@B爳sΌ^䬑>ч 8=s͑fOgaHHH8Kq֮x@^Q$֙>SoLs!  (1Hg]Ǧ$@$@$@yg_2qNɩ]9lUw9eB:W_T{6"  KU _՛Z|{h GLOM#  g(f8;rz=ϼz!krv:#h%bZxt#>r (κ&Ngs9j   (f8LneCS5uH    5;oۗ>٬}d    Jln9ڝ((\qO o=oV?iKg}$@$@$@8Ko 'Pu PpMqYw1~oٟyoۗ(:&   vIHHvh8sSp 8.-3mYWk 8B#X Pzp E&N⬻zk?ܷϼKggeXHHH `Z2=%qh(۷19Φ$ӱغؤ-ScݎLn~anVE~<*(1ϫ*FYÕ&rɇ_NnefMއKLJ1:ָ;ilhM114uu'3gn^Ƃ+nhoK_p-m9hLvX]ۼ`̞5>}Z~doF*J{GQ!$||q:.pj^{s2bQqך6b+ }g6#nNKp-[e4vb,+mJӭ^ψR՟*uf x/; \g_nKǧ൓ T?7*Z om.X羦?zW}hCuT68ު̸劍bKkzV"1:%N'_V& qV's%ξv4.&)1-&"7N635:ZqW}$Zl6jzl'XW8+f8l5V{ͼC12lMSiT.>+嵽+;-{lviH=]+E5wDTpi2ajJ v\WvfYAq֑ú$@$@$@g$W|(mӺW/n/Ulp4 &QEmɗ;b幝0aؙxTQoVE~W߅/z"vA*Mޒn'z-#k劏 ,06_:ӆkI2ŬusQkת``gy&vq%"mYzT~o]CZT+)2WT$XƻzjrWl>Rxj9Y.JWc}J,37ٯOݼ2!Tw#v}US}Bq֖OkKL!M=qb6&kLɇیD0vf)޼Xz,{ui`쾥Rճ\Xm#~cZSﺯYulL}Ո8+/c?ÉÕhMu8yiw}maxu'p늺^l _3 1ۍ<83Q.IDATuff  ^gw9r"Ίpڻw vZs¬o]_еS/ܵ#*-S!B \OmD-Pp%jjfxɧ.<'o^̦oaw8]!Dcy(P7}öSɗ1sJVoگbtۋlgK=a_:rWtp>7v 31t[7V eBF1ptO;*2|6sNmB2MжTqqVS VYJ&!=3g_ٯ>Ff|ߞhi˧K턻[M}SwmLu8k-o " \>m qz9BCoծ)[g_*SK7g֥-;}Kfl7Ljlr_Q:wrd_5"ζ=7M믐+et]jnq\hqݵ88k"+\5˩/M=T_ؚY&V=yءG9.m!4LC%}ˈl\SdOud_5"ʚۖE5hjzDhm4Ӳ:=ƿayTXoBqV<L?!  " gCf}U Q%?Su!;F'Q,/rlh1߷\G^q"}ݕp#E@iHǣRXa/>;/ThYĆ% *&!ZAJθcX]ET1S[b/TBDI.>rHVkuKI#H􉝤 KqVY"Y/ԃjvrX#PiLD-"k0bW18;NWsDD`?/ f0vw8t& c[YtC[B;79k֕?g[kY[>et]jnqfxyݵ88k$RS {EґY[BG_OEݟe.K[v$&g-#n$rr~d GYGU#H[VGp⬩Cމy5ܴjÐkZjcն7EĊ^+b hT7/{v*笥CH׌6rW#DT6/O^;RS%[ zc*"g]=ѳ8I^k,iZ1r\ս}Nnbb*Yjҟ&'KNiۦYGD̂D~iC9ki3#Qq֑oOSFץzgl8m7kcn4_./HEy\ Uv4 [}a~i)pZۿRӜZ;ڴRھeGgˌ M[FBCM!xk4xaF7Hk{Nkr_IuͱY{;sfEh+Ygwn#  {KOdi7#YSwպg]F+\:JsO/Qj+$gV( θK~!%*qRvZWy8x$Z"k㽝_ZU>ܳ :i׌/az7T/OD;E ’dpa⬈}") L>vgի{cB^*D랦뙭*%*W[OfEYrEJDz=q;kv50_r7-vʳ+⬌G$WpVu]2rܪ8[>[C|%qJ9[w8+]WZPi@d-D-}_$Y|JDuzZwwwRuצ#7c՞/=|9>/Žsxʾ){0NIO_Hky ^ϖ8I*g֥-;ged&qЮc['ȾjDF"JZO,Ɓk'P?T~T7r/Ym檔/xQ͝lRRws"00|СC1f̘,LOOGN̿E%СC4k g9-59;" *: ч8(u'Q^AW*Eߕ0*ED+Cx@];}-k:Arɡ _[i*GDFF(vp_KL*! !T-Drz%fn{m=攼r ւc+):VKN-Q~KѾLcG?WcLKqV^6g:TM['k,J1$Ί[!vKNlPs,c9/jg%:]!__QW -_㐈 .jM[FkicɉxLc-g;wFud]I]_"ka|tXu4fsVHW)[Zk}: .;w`J;v, CA쥍Dde^Nu+?Zu@cqn4B͑qxb]>e{McyYcKqᮯq53\;'Pu8}v%| jm۶;Fفĉ)S 22RR5]lxꩧT=mŋChѢن 0|\~G޽?~l۶ ŋQjU(P?S"**J׿v X!`K[g>$(z*ZսVS*G/]="Sg1!9^;cԧ^3q{XqpvF֘357^m q*mMn)ggYi7nP5%ljʐ[gNϞ=fZ0~x%ʦ7n@}?%N6 ի._ P %KbɨV6m7| P?t钪{IjK.xյ׳ V"   zXDT3JOž+g9$(z(r>WΈ _5MMcI){۾Dqֽ&b䂽u˧͛wkC5]L/«mҤ͜VJNە+Wb˖-2dH%666VRqϞ=K\ukYS5H$@$`8;f'L;3:kfՍIENDB`icingaweb2-module-toplevelview-1.0.0/doc/screenshots/tiles-tree-noproblems.png000066400000000000000000005732341473125420300276150ustar00rootroot00000000000000PNG  IHDRgY IDATx^tUUƿTBB!@R$@B/*b Π8(/ *:(*t !@zH$>&//シ%Ye;e߹/wKkB$@$@$@$@$@$@$@$@$@$P\()oF$@$@$@$@$@$@$@$@$@!~g\Sx~ "'         }@[JsŴ HHHHHHHHHHQ#m|>7/C$@$@$@$@$@$@$@$@$@$@g=ݱj ~B'E k=:k ݟi) ؁%o owW+Đow"& gw5twM'   #-Ym%  p8;$"]}593.rHv 4Y;\HHHl $YMIHHg%EAL~?mְo턷v'"e gw)U1IHHHgy5 @0[46C͑L\sؤwvj!4Y^$@$@$@$Pݟ8[G'   C_.^F/$pY$0 4hLSmЗ#  hݟ8.RNHHA0[͑_p_O=rb٠AOٝh 9<,r F/fQc%{pvg⬽C$@$@$@pvuV$@$@$`/fvng{WϾQÿtˮ\^=8ٸy{͍@ݙ8[ 8gzys  Uک6.ٗqC4Y t E?<׾  $`/LS ₲r{]HHH&$Yf_H$@$VZ:SVar"vi.-|[#Y8u =C1{bõF:;mݙnݝTl[t EqY9'`z>^Ӝ8 @pv)%HH Z3|̺BODh,u_yo8^‡~OƬYuQSڠx4&'a]R]qk*zA$@$@ ѡ*(m\\+8yjʐnŰ6 Vy.`ˑ1,'ϟ__:NS#0}:8 4y4Ys=iyx7JmnS9Z9["m)1:V%!ìt(,)ϵXƶYFM̹ cԩS*gmZZ axHɩVΰN./V   @h7m?Y!Ę+Z"!jkrxpLͭL*NĔ?YWeSgKqHH@m~즱qmbNAX0[sԊ517+qU+R=qJ_ԾQk6j^ļB<063Z+ ө ն6Um xG/Sk}^uCɓ';ݵk,X4tO?4PRR9s`jƒ £> WWWө7 [b_\Z7,;'*ߥ<$@$@$(7kFӭ‡xc{J+&¬"RSv9Sg{gw39;}^T:bDmGEPS_|,xɄ|h۶-RSSØ)c̒5nj~/iº$@$@OZsa^ ýD5Utu 4ݟȾ\RMP+y'gHlfN\CJƱq5]]{\Rʹ\..N^δXbLMOO3Bpp]jj߯_?˫"'^N']pO LUl\{ބYa} t D.ލ"s1 85r:g']/Pc]oA*zvB6?LjoIg_{5|S>ML̥%-:XHH^Li6UY%cЊ"81pi8㉣RHDÊx"g5T\+QKo`,EDU E"EAl"m[+&9gWΔqEKIjK[O H8kʇ4 Hϥ/i$@$@OJG~=d.9JX48I8+f%ZVrbJ5g;ԅ8+޽[m=KKKS'Jhꪢf'NXi t j1kz_n#Ia🝧s]M$@$@NN@v,-"R^_cV;|L_ueN5SsY. 2/acOSi!!rh|('#gM}fɼ! ُKZr. -jgU&q$A@o,=ڦ5o9c1Ugd6D!ݢ{  er8Ӗrgzn %yO4^͎=   <f͟ytv)rЗG' BV8*@ve} %O@qRrJԨl!isH/J{hn TIi*b;ЦT7  4Oҏl2*'J$@$@ *jX?=%i98+ydEd-⬤2Jb^!z~jAݙ8 ݒ ݟ8kB 8@1gCNB%!f ]}޾oK@0ksꎩ+u 7%s4CV2;g^jV$   pvC. vJ$@$@fU59{ۏXt쁌U4$ΆxA5ah?,:}#ُ Ѻ) 4q6{f*5T4)үRݙ8[ G$   ]ORL$@$@KVqPY~w9g͙!qVNLj\vg"~.z:?X9wl')o:Tر8R^+N|rb,'9X>ݙ8k뀽 ݟ8kʳ ؇@ #Qvh _7WKb!qV:M /"fH@nQ nW6[4d\r6 @h0(ѶR2BZ!(HCBJ)|= [킀'e.FX`Kl)K]Rf@{F ["DFq_0+%<ZV)6e$@$@$@ 84HHH X%r-xh>x̀S8] o_&4(™39 oP'!9G$Isʐ|Ct\%"6)h W'"ZG ȳ9!+s+hf(>s??K(T"ux\ Z%^D@TVڪqrd/6g":L @td`E?ZQJ ~Kmr9¢Øks|swxY= wOb2,نvHHHaY9_eXHHHIJ]bD}GYcZVV%%%;ZVs(ngqe~!};"'- PZZrhM9(=gZTDs9h[zoc dl/  p'Obԩ[1n8.ϝ;~wun "@vR]`6oތ|tQЦM%L~וEEEڵkgːuޖl#$@$@4㋻k.;eddsx'm~k`3f :g 7(c V̄@0p@vX!>^9^K\h풂F/U&!ZyI8W9#Ζ\89gf :?0\j9h+ 3<2Yx kִ֠1cV" &@QNo-[*q[.]*رcvg\{> 6 /Xn>cL4 W^y%M~wa}RuZvL$@$ O3/^Oɋ_ۓ'O*1^}UݩY"6mqH%Ϭz=;h@LmY~*N/o0;JP"BK79rAQn R|*9\q?ڵ [Edg BU$}!,:"=AQ[)g сy1r &-WWT gؔ 0ԕPX+VQ7iii*Z<$$CM7'{;~x7 >+/{wܡ~ojM{ϓ 駟}LD7-*EjK.ŪUg]tSO=TUGCg̘QJÇگ_?L2GƑ#G={Y1W!n-5f![vޭgyڜ4C.׭[7Y9+v=sJdݱcΜ9?SX*.~w{Cfg͚;woQZ/Y^EWr8,sWkp7-)u-WÄ% IDATW&Y=zfk{E{Q /wxպ+6lؠeg+ݻ[uIHH* i iJ(O?իW_!))*?͔'W^^D]*-SW5;O*r'Qo֬Yo2#5" KQ5 +4d䡰pFpX+%HIJCnq9ܼ޲ϥ!+ Z"QWE SyK]֡)qM ?$ E+FVi\ Fd^2\ld6X0k6v'bX+Y@;$,?aL8th8{=wݶm[+5{VQgnP!qG{IH r%58FRBDuK9 ѝ"~0sQ;b +iL R}+gСCcelj%'|^K0f-)))j OQ-*]qٳJ| a sH,D6VD|g憏>Z5QjaC2ZOX0gU9rZGenݪZDXRA*yx3%Ke˖XuIHHb iY^`@ۺuk3_^K@XqqM~!ON^}uJq429h =^x⋕ Hl"#OaVkt ő1ё5lSٖ(y 7oj<ʃDȃ8#od$rH+_T[ 叄䱻T􈴓"Q*iD$"ꫯVQ)#Hԏyo}gɉ?#*EqF.5$6>B]qV8K9ꏮ0{i{ofXHj-"Ck HEX|9My*Qr7T.N!Ν;k׮UmKZD ?YC&K/ɼe2+mz!%[R8+sEZ-rɵ#zE4⛌1r׏9ɺKD\\oIw!/.$[r8g!  i4I%ZU˒FK~߽[ŷO3OM:+ ^-r4U\ " f,\>h,gEHԶɃa-zMMȖBy))&++K=#[&N{J-&m%H"v+ì<ShDU{1Յ9<;{p Q$@NB/BF"(+%,,Lh"/DhU^ʋ3lgǎ[y`3e/e믿N:=L"?٩o… x)qVK#J$̙3ѡCTc$V^ NPrkMג%K;/& $:YvC%"N3\ӒT1?|7ua,>JxxZwKSJXNK$@$Uf,rVZq?M2o>J]q֔O?as|%heS'`8+!E)_pye I=RIȠ A$ST|}p$I^9-V"EQXFĚ#J&LP4?6˗_~Y$7_4qV"@i/փY7S+[Fe+C"tyXrXS9 rm)Ѫ^S8+}H.uC={hQ24@.xG*/d܋rAK[r_-gR[{rOMhhtwb-FZ/S⣈";j$ZXrϷ4tqV"M5]Dw)#׊B+G&m%bY^-\Re,$@$@M4/gZ圕(0[8111W|bGig߄&?{Km۶UFȶ| 7U$W ""JD^0}L|Iapmzڛ#yp~VG,gADQcE I "[Ge!6qVINff&BCC0 G`W9#gדHl `*S`9Q`qڴiR'666V ~]I䨼<|6GEuY//8%BA^Ή+NֿuoXӒvrXiQ_"neD=Ƚg@3[{lrF"JJSvczI:"'c.ݜ"K~Y^/k"鋤/a#,)EFҮ"i,t<CDms#WvSiVY{ҕόEr[K$@$$M&iTFK?eY+IGFΊ?Z~Y^s6T -ӜYI? [jy@ӊhT4!U}v)<0kP.YCrA5W$XѢmL[M`)!&A)mVy`sՊ<Cj ̦$@$hNEP-OrmJDD=MU<ɝ)gH=O֭S$\"]EQ_c=du|"L9sF'YQrOvrRUv.9Ս)N-+"XJԢE;L'5"J"ѱR#/k%"b' Lqp)"JIC!~D\|nI g%jZK; Qrmyy /hl̜Y>$ܑY~ځ$2\Ho$F(+/ t)h@g}  E~a?MVY9I-$}YE V5}q4;XHRqVa& E~$I(ekDɶ)&B݈/Bb(RT_&rV;Eƕ(Y[g5;NtLԍmh,#Yo+s!9L"Ubfu hjf0+!!AE5kQT]bY"J Iz4Z>Te#1 I!P|#C Y{]uHH.O c(:pHRqV 9$RȟÇm*"FDQ-,_;tP)?+,ZDk8+Q@"[$E\ .KN7p ҷ$mz6Tݝwީ~O66l$]`Hc0-%zX-Q'@lx)6/ M" +MD4E%Y0DH[IKaRDKnI %)+v"Re'R4AWL.#W"> t!.)$)ǒBC|yinDq^W! /G?ց=;kYqe˛2e$`E@;YrXvp9!$enh]qVS"$_blՐXkH"H,Ř8+ %?ث_donN$@$`:f@/^H46=lZ⬤?I*&C^Xkeؼys%i%DX](b$@$@I~cQu:NqV$Z\RW\pN!>=CK"9VEILb8+H"J4瓓Hԇ*"DJ\XnjF>}䏆DJr(D;Qؐ8+}I4&TZs(u%Wf%zV4Bqyh @!Pn#%\֭U(9,DVӧΤ4%Rʿ-I%I$n&R9uEms#M+ C Pu(^v X+6yɡbrlӚYHHHH^KHHH2 yuh 88+9WJtDir ؋Y{d?$@$@$@$PY^M3}:CHZ9i؜s$@$@$@8k.V&   P+76(J4ɗvZ#00P`|}Ukml Ǟ# 4~gs&88%   $@q.is,   FlS[qη HHHH4BHHHHq(:-{vg`h" \*ΥٶD;*rglӧ-h9lnt2 5>aېAXmw2.`i؛u'4hGfF2H}k ,sl|2RRRB[Sm}||-[`.^Ƈ{Mht3C#=#̪(ZHH2,~ZMd-^iEEEHKKrȹY4<;5N|4HRKZ^ :ضfm@yqXRz[Uj`lȒk = f5`%(*+# jxnw5 T_ZFUC6#99Y]\\\j]{4O;2{iS^nxxyEP eYK6 mY ceff&N>M? Y[0uzg~ 9 s^$w^UYs98Png1XY1/VN쬑V\?k]5xQyzybNIhӢrPG)׸\,p_y[nh֬""5!}َ2za8Dv70Y{g$@$`4\ںHL8kNMRqV'Nx%5O7|r}7μIƼ!éx FB`6)jC!W:)V}.яTm&pfm]Z"gOb]J|ml\"g>bLƵͧNBVV-ݙV"gUG=SjW_$r믴hgoY?SRV Z~[/ پxp?{0~Akۅw{J~fHϧґYX^K+L50y$ ]=}@kƱ vg>{ UӁBT^a@+cx;iF}Z5ƣ ' R9F])׸ԵYfc6{z;Nd۞/1mcvϢ.ZEˢ I O OsOjBO3N⬭W;5K^ a80/9'VBWS[kjhu1SҨO6Cl.7-݃k6h 2/݉h ? >z̝d̾3[T'cLse]m2IO`bǥ4Ьuu&Ye'r`A 9?UvA) Q<\ܰ|땃Ř2X}k@ݻw;4fݻel˹Q@Shz 퉫-\,-[]LN~V~҉iIqNqN_m`՝6ǀAXv" 3\hSYq݉x? |DHFow@fũoq8i'όCD o|zC7T)DcN~t[/ 0pxu)\*]Щ}ra9v`x53ҖH-DVnh G{w\N6y]pMnaƪЭU=]~ZVA8 Wue'j;WQ|TE7Gŕ@c@P4p98 8ļRUUuG@>-N/Wl@o2 Xqp1zDf/_ J-/)C5 ŵFqb6.-:'-ħKːNR7Y>u;lK?Ajxv$d!S1*zn:D?>ATN= \emcp2B̔l;< {2OMҥK}Mm W E{wtN!=4n;v ǒ[bqH+4nozKZ)_Za JuwuAWgQ`<Y[kN @C&@?ruO3Um ~نG9Dx*.c{JAaV&a,l+_O~x>;p+Ng⻛{9Kn:nwq8SW~\z[[~+\~oH^W݇/%㇓i~tOU=oę Cqb! W >=~ُ TD?Lǒ[*çTTf!?0ΟŀH7W/ǐ.}`Yvd?BNA]"P|(z\ܨ8r9d^}7TdX(6 ZVV6ɟXSg[4Csؘڥ>w!!/}[Lݾ_aXy~M-:gѡ98[t<?Ch狋*aڨjCK@مSeT06nfSo;dGЮXyngg{ ?%mÎ#F?ۚ~ }n EUq!16܀Eai1^R$Vw8o=YcCD XIv9.WLn IDAT_?G܂PHdñid\8F܋Ex}xwn Y}>aȏ_.Vgm8ہK)S]SBn]pr6tE^j1&m+RSlYA1r? {h_r/+qpkJN\/;ԋjGBYe伷 WkkOw7 튧ކ˹j>[g|AZz+įwvQ\Zn7֪6^)g:<!^vg5fϞmWqVwQXI4lN$_*B;Uzj5wƝN-Y{~Xs&K@*,'Ϫ]*Y[UG @C&@?OU]OR+"ۥ|yhDe ۧHO5ΫmѣbPB 7 :F$oVf[8+Q2𿛺+8F'.J}粱޸2طbkۅP\ٗK 9g;inpuNӰT'Hzl onB$`'f8"ݴC:vЎѓ_mߌ!ܱ VWkOcng 8C_NXn>kKk[s1?!ɽb2 .0,NgS"Ň~J|ق Q\]-= % ?l6R8{m^x.f,r/݃C_u^5˓>2q/8 nUj_0>Xq( ~> F]T⬼+!f'U~d݇#bGJy3OJq^ o;,Svho5IfpU`Vuy8Jm~̙8u*Zb(xbDIp~ܽa`Xt\hMZsq2i!&2ujCsRSKہţ{"¯fg9OW 3.bԒ?˘T]}XǞ<_uP,"i'p/^0/sRq)f^RJ^)kuuZ6x.2,=%cW؅|<′ˈzS 6sGvT ҷ*rJ^>ƸXbB$`Z~9l9U>p> Oġ׫Kq {%r֠`8+M V{6"0b8+s`2v_Lkoƾ h响zO Ids冷8[,JNdU]ҴK6{f<n-kM+:Fbj{ؒvP"Mq=6yO5> >N;-*c%r ǧ3ggfۻe>m>NUr?$ۉOX6^UMW5t9]#7tq- " 4j"NӪ_gf8{ *P^=3ޮml1xMY-bq87X(qv52 #Bdݹ_/OA1'Sm :'PPRfо[8 L*9+_:T!7{O:KWm9^-k̉?cZC"mg]R)N\ڻH# $ O j!Bhtv@شd:^z"&Yi'vo9싷Pkv$@B/}}}#C>ڼF/-¨ s}zV8qK7b q6[0 Ct'c8?Q|Nu]72iQmb+}{⭃7fL$r/Jeh ѝpi0Ǽ=WWmD_qAh܎owW[۔P%*sm쳖^A?9ܱ((d[QZ^V*u~9Gگ5Vvԯ`o__W7GR*z{X'fҺ*^ WPZ1.̧/dzՁHʻWwV~ȔZY[, 83iV~4c_Y)/8?L#i<|m0vxą(N†ycEčJ9:4kEO8? z*5ebSİ'bl$](Fd'X=~uk%jX*6&rp 9nkd9GB$Јq/UPZ=W2rߓU;ƪX(κ{#?2*<-.戳1+ΌB,{,L菓y-}K{@v$¼r^KSR,3h9P7roogVh?%qC[_{q;j9hu 06n6Wk<6>!xXkboq0txyL*(R .c 77}=Y',Z]#Wڤ,t Ʒ7;$blz[LTE7rv`@k_>%Q1pBe.Zl o5ši$PO\ iL}--6$?Jq@쁙xo럑}t"gb#g+!c^~ fOB\~u:MQL,ØX w՝0u*>s!e+glA1Ho[bQ!u?? G9&$B 2s':O1}z6f) 2Ǹ"؂qS1a`qǵѝ&l!j(yg*>7Gzׄب*mA^7%_ώC9\pC^~Zz"RWՠֈQIr<Ҕp u2rK;|n2,X|Z +18,qy/2ٜ#? SbFp9'n/gKKKƽkEѧOU/u5yEQ޸p%vUi %?6vE5x[kLLn!#Z䮴8kֲڵ-dg$иO\OiMORg٪lA܌)w6tÌ)ssLHjYD,g=s+r*43ݸ0-~ fM6'fOYLK&zY*99,s۸nW Ye$@ M\ eL Y{i8k>g9U_2[X;)q>َ#o 4 N?ͮ84Hgsp`Jħ-mD&ʃ-bcD$,xR%<#Gt Ik"v";~I-:;xs0J˱|NL*Fxh? )zp_aaE ĿIc01->!ScL ;rJZj@0!Y{d?$@ ~.~{gtkGJqvFA$@uF~]QO+NwF?QgՁ`4t37)݆cDxV9EElҒ阕4L-1me g3:~gAS*]c`5-0um>p mά^^^x8]uYqA>u%[,>>ƪe;"-" @S$@?nN?ͱ> E?8A+#g ?G,2 c"= Bq:i3`EXAɊES+ eYDmiIm](i Z)<lW1wW)`΋U-c1rX VZ=X0{>-F`l$;MX>kl8x#H<Q1a: &a_ @@T<<[I"YvJ,rp`ߐ62Gx`^loWg튓 4TiYk2X6 RpM1c]| : }( ;,C\ќ$L!J4O7Ww":c@5-KoKpe(ۺK.UN%qcb ~7joQ7g-$@$`i2R~c}R[~iV. ۓ@ @qa {;;f@N5N]$-r̘wak}x!3 8iL;&'V:d;ߌѷ#ǔk\[ 955IIDXXX5ٝe*k3)Z HH2%-Nsk7q?mOҲ49Fqּ5eFJl#]XNH0 x ;(l%/@B+?H(HJl{x"|q # 7 m4@Wx9||'$]JGvE Got30ڗ=ǔAk\[`c˗t[l3۶m[Kۑ Y*Z(: ՋؾCi":Fq֖+mY_BNHHH(:0'  h(6)    ( !   88 PuE$@$@$@Jl$@$@$@Figy igy Pu[(:"D   z%@q^sp   FNl#_`N4BHHHH4BHHHHq(:-{vg`h" @8[98 @#'@q/0gQqvDG$@$@$@M@ ΗlӺ 8[   %@qnysFlqJ!   ȋiֱc+   Y౩8k ؁Y;@d$@$@$@$`93cFDl#ZLNHHHzggǖ$@$@$@$`6cS'@qא3   v.HHHHrg-gF (Zώ-IHHHgmǦO!g@$@$@uFH!ïGmm:|~l7 cçZp?ww& H `Sa? {Fb޳dRQ XB%XT=y$NZCpp0>#|Ν;~s_waScJcwfJ$@$@$@682aV( ʁ?9 'nؐ{Coٳ &j(Z Ay9|w,?hH5)[\PCԼ9Y  P[;9k[oƍ3{⬹n8koe˖xGͩ:$@$@$t ~(/|n@w+ۍ^/Z܏\jvލrQ,,nnnիWU+lxս\xtO{IJmx6d qMdƜ& (J흚Yy@oh<3hѢLE.]VBnn."##1~xtҥWsYGii)ƌC`5fSO=T5Vǎ1c ^OO$@$@% O܅cn+Y]mZ^>}~Gqj az 9 ɴ&e;{#:лI͛% Y븱U#!`OqVrI+?dyW={Ĵi "0g%ꋤiiix'ѷo_<ϰi&u]:tQ n`l#9   0 ΦeǑsǍ4C =!;K5&c8}vrvĉFPuR]Gz]!-iC:@ˣiIHj%@qVDИ X+3+0*ѪӧOGݱzjV9^xqqqkЭ[7T?C2sV~W=t^z%%KSmW8F$@$`Wٓgsw1C!%r;\j^w<`8+/zvZ;/"DK /%j+m-ڢЪo)U-mQU֪־ % Y$!'fܙ̽s'!{O99{n3}\a8kQybJ:I(ŁuY6ϕ`XVDΚ(W/] f[@r\R5(V:5o߾4hc6l 7nq]qլYlZ<V`XK*ր IOᬦ!AڶQXR(8i`\vo_w "`zVb>4<ÊM`MqaXV` (pEVpV:uTP$(圥z":rƞ8q/F &YY#E5(˟' +`2pD\g;zZ&BNE, MhWOQO!mMk@ΚẀqu¤ѥor%hFYꕠPYV` gܗQ22~ D:!h} +"yv g;ܱÇDzeٳgΝ;#gO?5jo͛7(VSYw;vXjJ[d6lHH_|xE.V`XVQzN]HB2f5Tz7#?_(:MU`FMMǂLmͨaLS#cS+ %G%W~6We*X'mpȩYݠMsYꀢ^qW1rH4h@@>}û=*}dTGbMDNϞ=EJ@ E)v׮]SOn6+ +P0gn'Sjlm N]}}B!=GGf5pXz1}1쮁ApA#[~6VVH;x|/rXSCVпO+m=Yyp7 _]ƆGןZ{;@Ⱥc>QkWaEObsl`XV)p9ONOA.HAYB/]$"aGݻ[6 + 1rUB5j8)mpArKw RJaR= (l nm;. qN*&hQ4ŧ."Мc_ |JQ*j4BKO<6L;Z^ե{_m耰`/עᶬ+ L̡%y:g&p+;FU|<`gSRR׷~k׮Ŗ-[0g. + + AEITrrr ?Rݏⴶup^sr{Bl}rsDѯJvR<<w,PuZӗ!8Kܨ*DHKC]YXuF}irmrp>Y\J~`4ot[;cP}O h/zI_+EξҨ&ՂNĥgiN?/u־*瀓wRHDM+g[K%*) ~ſ)wz"w`mzEmZ[ aus2V?gXV(# 0-#. Ӭt2ه舻~jni49JMn:$&&C4h׮d+ @U6ӧ _ ӎyɶ(%ѽR#0p9p܀W9{x%.".=nŁw g)rvӍT5S=+HȖO͎EKU K5ͧڟgFwB_yv&Vp~b0?!fdݑ:c9[~~;< C>-"ǷAuݱwsŹmpKH߯vN:zN~ @[N"+ @UlmY7?|8WN'7swY(/ d@oYΖ8YV`X@}?ՏWAYiXsi]QhtĠڝQN7ڎ"S j YO g! 0b!Âz9^DT5( gV3xqnTOr>w KA_nXDbWl".ڨR=wJ:IeH,K(zzsyO5'?$?c԰*O s.v6zGx/ڋu/j)hCzQ'[kSq]V`XRYlrlgcn!-n^=:MIPg NgI#ƮkJB)il(`H0{- L7H H}%SAcH%uUYV`XV(P|]%8@4\~@|>YMԯTcvөo*?tѡymTHQMjGy'Di I{v&zc5R8K}/~J{ g)uѷ"ƞkI"5ȥyyMP7?7;ͯGAy^7ΚbTVhҁ + @Up6 1[gcKx[snE]=7uepv;O,Gn?q b8[WY[2E88Pa4Pn-$?^J!s4Ζ`XV`XK*Pᬛ- QTsۡ#pg`*[FYjd%p{crXի;AgNn+ =VOEj>(=IwV5Iԇ] |~$}|J圥ܿK[O<<1pvh~GΖXuo*5ŶQ! T ?P0M + @)QHp6-b&;$@,Oaw$VNq o8 %;>s2tq^0yY'!Lꄬ+|C(.5gt"+l4N=1HvFc0gjO򵡈I|1h04#8Ke!? ˫-˱'6 1aD3ebeA5mQ,'5GpV2F}QKsi̵/0f2MdDOʫ/+ + J0_WЦ4轰kCqkI:pj9{m-rI/;C"-ɗੵ)RnUGt\hκۈܩ9דt,E:b"JRqɵ.D]{I2:~8|#l<jgCC0u͘??NF < }ںVLAΈ>sCc~&8;3N^H3vxaaFow0b6[]1m\[`X[[6ah;+LBK1i>Ubub LJPJQ T.dv1@peN$p Ws>dFW??CĖXV`XV*P,4d,6D8T ӁsT:U0C=`1!5+3ˍNZ& -|Β1Mb/t\Up UtFh_rWПRs>Sjlkcx\Tźͻ`_4x\KIQ` Rߔ.EJӡ`:),\ (3O־AС`jmuYV( Ξ1 6fcDw0l'R ,`[6 ǰUa'`-==Ƥ=-M ܉8s:4uG%)95x9}.f890omv?Cc̸NpW gFIJ[=0fp3#tl~l Ѧ9Y3 ͔5Š1/03tW֨$3h׾U˺?݋[ gG,3T fMU+P6(āZsnZ)%^;q=/p pYyp%oťv0 U퀘52 ?{\]_']R= GW_2rr6,^=1 x'xRx^ڲ/%%o%5j)ڷ g%W%_-¨f6 fͯ)[dXV(PD8K2d!>bq1e7/_4}:Շ[iQaq\'φM\pGʴVXpwMZ~8ݣh/Tw}F͡!-,'ll򗩣e0kb`2UV`JfE ǓVNA.Hc]kU^Sllp-V^܎CwΚ47Uqa+v_Ǝ'a{Voj11tl?r6M-¸?m‚?SqeTjkuL WaPY[Y3,ܬc*Эz0S*^5ZөҲq2"GoÍ h]zv'?n '[{ڹZڵ/üVo!kCsx?le?0ZrrͽF`ZSS=_gy9~?/Ğ['viklߓԬ`F}T*0-c0[<`XV8+p8{-;SJHt<`kkPMKDή8 oFhB賕{CLBr}^=՚c2uyۮa.8{)kѹ'gTc*-JzfjA "13_ki疀C}CЭZ=璯xݪJC]ܼ\qTPzjl-9[ڵۧ'7\bQ65Ő5lYmcژ{rj 15FjmiݫoGΪ]Q%/< V` g22~ D:!гϭ\Y3scn8kce?Ccұ%8Yy95AWS%I)YijwE)dbSM(7gc~kNMĐ=≉d ܼ_T\k?.}:"!#ߞY!mCCz*.p/kĥ߅~=oy9T#ДhgrQYsWaP4|}f:W l&xnwTvpŅ{vqOh<;o]z;N$^q3~0 ȔkQa!h^h]V8~8rxtju{39oά÷-YrkM'Wbxz'}.ݻN6}uKQ]څqgkgpx? D?tmj׾(^OOFfn6ꔯm]{Y}Zsnjux:+muWǿ70{v2%nl*3eAJJcܞ/$K]ok.ƁjjϴUU gP%sg fx+ Ζ/-, t`NG#,!HHspEmcU{ /y^Nɕ.W߷zփ$Ll<+n BeOG.__EQRH&9xAu` v:~>;>Fy[',>]. ҼՀ&KcKgSYӟ/lݔū+d:zmߴñh8[űOX+>~u{PfHAttgʾ/dQ~{㹚0%gZYG^ڍdvwpÂc?!6-?&l]JkM%Dk6Gm׏*F“6]ݯMA=? P{NldcׁڵOvaeۇCNn?]{Y5Dc㋢`pLk>nv.vr {gVQGϔ5fI7Ewt=]/w29R8+7&G{%댠v@E_|\}Y=Siv9[< V`J gKxQpJEe?4XKӠ(3*k鏏/(5'G`lo6c6TW|oY/gg;?ъֶ#3{::WUESS7}Y+/}8[ųȚz9U}I~~p{`o\59gWZ_&dq.oTq ;'#y[&,RoHKHfV]R~Wsp^}PTv=:]Y5㸘zCQzStW)]Or:i.wjѸP=S/ݣT}Iz9K=9Jv2լv9W< V`J gKxfWRpV:P;IQx3x2t ;cΙt/VŠLo>RD7hS9;xe?|1碼*8KlxqGps}$@g)Jn ?j) &kY:ʎR9JQgk "6? zջKfYC{h$ZJk-+7[5Uyuj?k5C~h;QDyCoP R]hH_+6oS !A:&9'18&1 5&Vcqb44,cUڗ0cJ%JT~J:5g+ + &Ζ&o\LVp NzSg,tX׮":(0gjF3zeQ=2IA+.+lR.YKSԇsGHJv"rvi" )!EqS(vR99R.ѳPۥ*|SHBGh %՜+f#@рN:W,N.%Iu Y۷4z+*rv\%G4LG'9s8aDuh.ml`m38oKٴ"k&a IDATZEgrpVQjfHTҜG#`*pI"MFdr,(¯acHY%b.`::,#@QxЅ"b0Pd[)jjtOd5y\Vo:،rb9.߻%i pe&ȏj:}>僰E@n Bш́rׁڵOi%_mJBT5lq\מ)p֘jdu)kT8g ܵ~"1Z5t298t1Y[Y/gej׏cE٧ox {&aXV`XV(pxQ( giJi5]IK=xpk=+ + U,2aj")kI'oY[}K)p([ze8[ţeXV`XҧS e8kLOjY_ R+temZ(# y[J ǧWC 0u + U՟{ 0}P l)9gGǀyy|k<:ju7UYl+ϊ`XV`J gKxPD5ɲq<&SemZJV^RV.dt/n2-n+ @YStػNV粦ϗU A'bPRV5Nk7]3s`͡bɷpg + %[%Y^ixJcZC42J@ + + ETlTw5) k^Yei\t gյT\z g-TV: gJW gK?y6+ +P`8[|#~ 0ʭ4Dmhcs:s2W!?/%`Yjt1هUh TXW45 ɧ35[akCsv eٲs1+ + //h g- k>[qpJ/uA<{z+-K,Uj(\-{ /zNϮ@ܮ|@pVv,}pŹCR`XV`XV*pϽWZ3ӛDڝd8Wf5W.T''1wJQH1jk#3ᬥ.GNpT' + %@%I<'8kme08TR | PN}xկꔯ[+\KН-_7\cR\ѯ#76ڧ-E!NԒ u@L\]6]=]ݪaj F#CFVȞRVȏOafM]kF6R~h ug=G㫱ApD!ln0yTU0Կ޺=W9jw EڣN5]Sq`\&3+ rvW"9Zo# u-B+7}WqvrrQVG m2.4<’uk}y_|I/'٦/aaa^2AAA{ԟo<R\K}g i@a֊F3>) X璯~+И~Jp6//?/ 2ìL7AI/7m>g8 EJNo3e(f)c0_g4]AU[/ך|9;YzQ#mg7t )x7jawQթ9YK? T'M_C5}+ᬹe{+ @T`ϭSyzu&C s~6D 3=:impHqR@Dt+h ALǤcKDtYh4FJ )1]6rWSq9|sf|\<ѵұM?uF^6pDA/~>ā\Gm|4 bxѷ;'wHP`y(#Gرc3f2e>b¦>mU!^^Npe<)YiP}ݷù?Kk1(V4@(^OOFfn6ꔯmo~5>oϬG:Uflm }: -'.u+1"u]v^ۦFZq7 =W[^G5wg$$ghcy5:1ڰAą$řߪ1O]8!;']B$aEJإE]7:P/?d3F"g%g x_m]ΪAョncUᥞuPQvyEΖt);ۣxk`v~rvLm1hW;n^:5\9+W^cۑpƐh 8k? pݷN`+Cg@<]6rGnr _^:ܾ)Wйg2L:Xsi7EG iI.?J{FXsy7~J꿖}F쏚_hJJ{'ObŊ aZl% + R`yIQ$sѱa2O5Gq:^>  pwm.1-|ܸ*PD8jU?B0߮8a DbFWűOX4R]{Up ھشx|?X Z8+:rU}w01l!n=HA_&,o[1;gAB01۷q]ܹG]VٿB M1Xy?KցxL? w/:O˩">;j5jjÔake-_{i7s0 1g)EIJ!'7M}_oo\cwtQfY9^wZSZKdBB$e&/ѭ@zcY}]9K0w'-q3> W.C'@RjSE@OadzS £mO{u[_~[jƕKO❁ Q#V'<柑cPr l=t}аV4&=ȒC`΢W}q|jS8.WZ'sVAѱ$XΪpѭz 8^#a4>k6Blx?tn<?N?J1}Sn#N*eJi@E_|+"rpVI=O'FIj,q'nj"L{R_8rV͛$qqq(W_|nn~17ŋ7שJ^оG4hnݺ*~.˘={v7fXV( ȥ4U\eWTaCU][U5TlƥVpV4¶&k}?ݫ/l챱49^ΕV-m= +-HWrR&괥{٠A8;x~d!uWECRZ җV}+9KQW=b6Xy2 :jҗjᣀ!&OFFnV9LUV `"MZ|PS7ĀH_{k[^=N0_nj L֠yhjGŭ;٘~O ~*O# <SIx]rRfxt"ϏNƤ0{\K\q˶DcpH-{Y5pqI|4<66V ߈xEBYcOv.G"ୁ qZ˽Im'%d廸x=.'#^% ++݃ v]{_BD0ge`¼P)Hi%T%? WXGHZEw|F6v<^;8[0sji<טҾXTT iJ{v$]e(ϻRr{[IӏT~FFR_9s 8o~+Xd rJZ_ 4ΪNubpocoãNɨ$@@0֟7Kq+1W0iכBy{=76޺@JR v kLj[G{$OߙsYcio,ND&tMFEn޷Rt+#зSM4&k愹%P8%>|KiA8Kѱc>""G#K }3۱~zPJ wA*Up̟?[x|M4l"g۷o-[B x7(1s犾ICORi׮H?iBrV`XRfHEtխ[uH]aANIRP%u~'*S:(ԢE+柌ՁY[afzҋ+1!8v懨աOVori (yҽ0:>ۥJ)5}8K~?y$Kdffj]J;wV}aUڵkqU 4&M/]")) 'NQժUüy(%@R ^z5ſ?Sxyy X, ,E~GHƇhٔX1Z)wS31}I|}T;/ý:zj?ԪVQ;/鐰:)~80+$0̟O y&"(N.i/7zQ494DD2ٻs_,3KMM? bgk-kQJ߼0;•suEy5Yέ4shC=z6^;~_gUHZ Ƕ ?|Yzd^)vG7C֡"׸&Tiߔ+ о#o z DԎrok18498FiϓI6¶ԿHsH Go2՜Ş*fK IDATx3@0<9s7С?4 `RJɓ'h9rHq@`ѣ=i1sV޿ÇDzeA]vqO?9:t(~'"AaŊb6lw- Ki@)!+ !84e7m2 lkȊˋMJǽU~RL S:Yi\nEa\38+>UliH-4OUNgsu<Gh4*6Htؑ5$;bD|8{5:CXZ.<ܽ0[}tuk#yk,g's>0YJqCW\C96%$bM?(rH *N"`\=uibDp֐N(_~US(:׬)#r6VlVQ/#DE8|Ubi })XIlis!9(0C>9vrR чtƫI(0ݔN4"t@jVfZ%Wi֚zCf+ۻ ,-;N ܖo囕\۔Gq|<2Q3i_ |*R8K_{17S1/kR ذ*ddA 8$$Rx{~ZVnAtl2DPv_AvNc- U{Sܥ=Ҹ2shc$ǥFyםGs +k륞霾̈́B۪N.:lqԹn]D)sňuQZy8Ks*tYۊ?x5 [_Lm6\g$]Ƃ?1k0Wi1j#o* EK}Ai43g#g7r?J:Jxe?nAKNcjt*-DFFomڴQu i*ѣ35KSk]ӧOǢEHa@ XZL111Rz*4bڤI-at,gQz/ȥ5/jCVDZ5zM++ 8"gsný_#:%2OBnrK!.᡼A%B)q #Y56 gS.vXu&>mSG gUl0<뛚oV&]AuqhV ցqMqLztƪ#X]%8+ 4 ;5oud EZ8ڽ [^lO98,l0fUlms4L}GY1yXP=ma t}zc7mE; 8kK}8+ud^|dyשAiSM%9kLAi+BtuU^<|ɦڕeDٱ"~'_A m\Zyy]&K-޽zK}}!#rM@ m wo3hփ(27Q[Mp>0'R e+.r$췩}m21k:G%ΚWχ>k6wRt_t5=p]DKK5xu,5Ws~/&iWȥDw/Ș3چ,zc;F*P1P3p{-c8k- ofvL4g=ᬮ`.J#@]p=JQD7|8$lҥ9K9k)eƍ1m4)ÇC(rRthِQwϞ=/C9g)գHݻwzd 4EAaii~g)M(g/E֭[>lxT+ M)͉!}K-8.B 2] uƨ@SQ9+m,}Tm:CGOvJ9+ }uU7/@hMi?rβr~gfap$~٤;LF:)^`{C4:l?<|K:R|2t&/cHmp W۷LC!g(!`\@0q[§6uk6fj|%nJq7cJO[L73C{(Hr>twp"m/tF8mz9ݳ V]ىHN6p[H9ᮍ%G 8^3,}Ca8kF S guLQ7og-WC˗//YjMi/_۴iS>) V@0M_> " (X5k\ `ĈRj>}Ro[li{=p… RJ[@X٣BݱcD:=Μ9#rR1c8Ax+ (*`'WYsB-5G_8|OX,ѿK݈{ [4ija8jWuTC19S}B]MK-02-̗6raTĶ>U ō:WuYL:AmklZwc4#%pV9kxLtU2[cKF-%8U~{=s(YۈG+6KxͱbhRy\-)/ه v3.yj4ٝf<9rָ0a Fslbb C@ + gņڷ0y8kS Fgs1ps?NwP 4H/T|* ox>!,]wP Y:,LaLN"`g&,`Hj#7k7ڀQd,\-ΚQ]fZ@ml/ώ`XV0{oŒSdDdž9P?/a6һ|] W+Eb Mj{fml4qNÖKL:oy)LQjEn T@βT+ + Jo͏/zTUOrRAŊU$\`XV`@v^ǝW"29${ jb@hU8ZZbWJda;D,ۦ(%4aomҾ g2"e8[D*Ϊ++ @)Ql)q$O`XV`J%Ζ4y%S%oi0-9^x|ÏG %kw̜sG + eCe9̢3bbQyKq%u8LupL' + P)#l3*RzOJ=+4[j1A~:v0Eg7b}풓%#% Ouu~,}*rizJϙ+6E=KOkѡ\}RpIa*rͦ`~4uXjYy(9Kbw3q}f>{h3#gUr:VC"gx֠=NfbE6S2Rk_(~k;.E(? A.u*7ם+i)FJ_(!gw;Gk{:c(CTzn隓fʈj@FұvCZ<%+b:Ӛvj5\\3b9kj\`L 0& #r0^|%9KxWh>-p4<ݏFx|4R %,3L;J-f焩V|2%lþ[R/JXÔS xߙp*Z\_/aU=W7u>m;hh%2t >>-3ұH;rRĥh Ѷܿ5@_mI, "~ PÏ.kJ65b[}iO{g|WS:>jAC;<$YErvXPgV_ډ/d[Ê1 7 Mӗ>rKǐ*q?% ?I{֖wѭ|#:^ϫkW TXu$rVTFj\M=WrZʭJ=օ$_RHZԜl/6|3 )V_ه'w%۩yt{.{m>>A?>))I<""BĹprrR\OdL 0&`9ki#UF ,5>lvCu 9El5,㏯NhuM'(PIw}}Zɦ8 P m$!dS 4MC}j[t3Ak.ң6f^+GawHY9KVU3Չ"6l 왈v%!.}r~ wb }M(rZrΒ9Ӯl]jRUEszY%1nP\OsYk vs9-g5CjɟENO_skGΚ(`L 05m)rYjb.ZZDQ*}GgUGBH1l0__d`bבH4!GrϨt-]}mTF_wNHW)\~TVSt勹bNz9 `] r풓z?_l$9 9CϞ.걦>N9KsBje<+gi0)k"Fv,E ܍j= AD¥)gUi Rh]0$lJ-r;.7ڑR4H}m73'$Y/WkƉT% y>hQ5zJ}$N%+|j)f],gEeL 0&2,gq,@.YDsa^#7q 9(^CsvصQ!rr𭸰ą-"9tWŏ֍@Դq]q5D9ryEK`~!:H97r#4 IDAT{}errзS$u޳DܸS862)w-A F/R/ERb/*is}d;<0'=("Y}w 0&`ق5S%9KͧRz\2"+m.NlK -( 9KQpۥ|(%c5b-}KYwcbSF$O*>Kw3 %9r)YCP^~ |O2~ +gYANaej hl=rrRP;3Uj^D.Eū龎"DkW=㴧"K;ytH DJ@cc0?jʶS󪄵v?)_s嬩 0&`1Nʜ&r]΍)nK!lHD>BV5ܜ-KucLNEΚ0i ,qԹL 0&@^"r6/%`9w"-R5pߩ"g\lfv1KaѢwH,9:k"L|B,gӘ`L 0&`&,gX|A@JJ3$-"Ya9[Ӕ5Ô4.<`L 0&X.z^%r6Ll9l#,Q`6W:r6WE`L 0&&r'E,ϋ$%aKGM5#˱-cL 0&<y~B@BJ[L 0&07'WIJJ?P܊qnzz:`L 0&`iXZڈs`9`L  ,g 8r/`L 0|G lJ"V컈c#6(Q ycfmg!עPt)vS`žv)v|0jqؚsX m9u&-g `L 0& :-#cL 0& \-ܹwjaAyZ@lMsEao<8t$&`L 0&`~ L 0&]9w5ƚQJbԑ~,Ɲt+T/%<'0*RQK:=k!V^+ZHUAH| םFlI'`c8Xag1.2 1Ԯ'CQEr<«TE׋tWp&K=ŰreT^iظ0yۖm5{V_9`L 0& 53` 0&h*g:Ӻ ;k$A`~*hX1Vn=mAex96m=jaWmu< Ҽ>fdM{<ztsHCוÚu@8tݘ"(ZVe\68jae;;ֈ=|C˧Kag薥傰7)z!'J+]b1y}y61$"]wn^"GmbG KFljR`~C:hN!gI]utݚ+\k1BO$6*5D챱[y_$.ʩKkn vUp+KOBP Q  ̝gL 0&0/˵3&`M W,nG#xGi nG#4#gC4%g&9-/v|NLpr^5p_=IR*ԯӈ_5z:QZG>.)g5峺 $aK LĐR𽒌jõ;{`L 03`9kf\=`L 0&`rW Vl>*`Ac74t,EJ-Ց"~`~i vU c;Tz0?4z'ycWHoDzXa*ǫ+iJjCޘߐ6&@쵗h%/ hSk0ZfvvEby\V 3b*9_z?a[ Z#RϡֻxVjks;`L 0&`F,gfL 0&,@.Y (Mڃ$Ĥ%Ч,q9Q Ĉ$+zcIs`cVl*JxOm+!8>mV⇉N7;,cbR/ů<}}cĦeJD:> R.#z;4rڦ FDFe6Q.KDyahqz2ÐUն `L 0&KyrL 0&e}9kyj˸]L 0&0A=tr 0&(0X0&`5^ڜ"r6Hu`L 0@l^n`L 0&`XZs`9`L ,g PrG`L 0El/nmN`9S:L 0&@^ r6/ 0&@,g-pй HK.aر .ҥKYfҥlqqq>|8~mtU\))9Ν;|п5~]W^>Ƣ]vmK.E1UT)(3`Lp7~Sv}eoeMM'5`L 0&i 5-OP(g)rv?N%IvZ̞=+VĚ5ke,^iiijZn]!30n8;v +VѬ$*.قp`L2rL\,.ݻ5PP!lt?4A 5b`L 0&rٜQ"KI;w.(R64440nR40D[۷ `ҥbS0c9bU!s~[oO>BݻW# 0&0@J*p)<Ų9˱C/ ufpl t[Lrr6j1l@'}XsP%Oj'^%(,1E~N 1_Fv:끀䣸2s:ʅXhk2*^U?^]![,=]gm_ h.ul.2&`Bl`2&`L Oٸ50\¾>|;[:u $N'Jk Cxbvc 198'š~(c"&]EF9FĤJ^3S`QOvLNX*\w$XWɭ f+pe0,wCN&uVr2YS`L 0Ll^n`L 0&P Q9Ks,ĝ]YMl2yz}-b o Hg\Tu= şyI],% Xi5 G 0&`ȓrx5xYK+ b|!uᝫ!5 FOǾ&r@TӔYrξ8l49<9Ca9emr6 <{ڼL*UAv/UgorYl2^َ^!xu?'\TԞڥХB(=SZd9 XҚ`I}U $k,gMÑkaL 0&5\ Y&CM bʼnĬA~x\?2KXξXҚ`I}͍:YpZ`L 0&`,ƒrY/x6\~4× L;/h[%O-YM|v20k,gMÑkaL 0&XKl… 3@|JRrywW5TFȜseDz{PH՗v!YkG0>gQvtA5ڕϬ!Kf׽3ړ'X)UVNݷNbۍ#g4Q$%^е|(ڔ FRx;Orekkfaާ\9*%FoU_ _՘{C_]W73OEë~-5Φ;]+ު(><4O)NN4Tov Q/qƌܘgvX*U> 0&`!r<\N9$k#FrYiY U98,=EsTHx,YQΚl~o:N6hLɓӴS|uڐ'hvNv,cl:hQ #$적}/$es[x.%O+xڻ`hآ,ѽTF6]sֆM'#!ƟX^ x)*g5w 塤jݐ ,ކs;fo$g}(}6ɔ>YcF0&`LtXΚ%TdCΪ0P$Ժ+piFV+oݮ> ^}Zù#.&aM"bT;2ux7ϋ'6b24rv߭S\!<³Eԝp+%(J-)-YD*m) ''*?Oø?AuX*:)VJ#g>mP;QPXuz@u1jmjR {vŦR>Tkѡ\}l̸i'M9+5NwЭBc%c0ZĎǰs,+dZ$baFD:bk5)%X߇ct- '\ E_a쁨ץ#7^iz伕tϭh8מQi ƫNqמ$zy7C \Hgb)m@ٕsͧ%hm̏ڀproJ BjDn w;!)KmF j IDATrV>,cyoKq{)~m,Q;=ET=ݽBc5v=xzIf?;w.8=}uWg&&k"g9rrVj fHoH}"WԛRb%GٷrX?`/L 0&@~$r6?!gI8pw1$l7u>m;C>äE$} (Gg|$wѭ|#:fy9K(ziW} FCsj[B>ôSk ޭnvNzjJۯk`  }[hyh$<U-)Ju)Z߇ Wx|SʈX tr(~QǖU;fJMf䬾1\ nE`J(a] SN/ ޿3T;^ډX Ƈ2T_Z)L*gWmbqw̉\';olSq [earVe4^XJAA_?% qJ/OskˡOC]_`A!X}i'߿I7FCWĈaUH>sַ&*IiO$Cr;rVI__)1ȷHHDz#)9qHѶ E?H}$'9/WNnM9wh's}P Q֡ڧTY5@CsKJJ݋iOXΚ/G`L 0&&rht\@0BΪxТȵ/;g'gw=D4W'^\oWMA=eT^&'^WP;sAt;Qhak|*z웂W4,㏯NUSٺixZi)K''|PݩKsJ}PmjBkREzuE*K|TN9K2[߸iGSR4XP.MIKdS n^p27#t3ID/ciZUr+iu\YsYK~)S)zqY_H9Vtʱܮl=e'9Yd/oJң.4rVcY#a Ҷ%ϷDoh"x8@:rVs?JMVoĥ-%q}CM&9+PA~,:6A&?Ou{[[H`,Nig$;"g/d|^8: 9Ko99kQ#.S_j1rVWXI=cFt-g\6z[RrV^E+劕pi5wX)T"UbVy3sHrP~6Y{i7n&6ҢJȩ{ѽbc)嬾P"(r^.C(-3N1bcA028TաDҹ? 4歜 *"IV]?=SEprroE3ƈSu'&Fѫ[b(g9|ڛPyrV =$X=709g~&`L `9G۟-,gOQaIO2R5p"R_KkMii8r-L 0&0YcqA?FʈQT=0e{.&`R斳VEy:]Pabw?EԃnD'?uĸ9&TeaUHL@=kGm4sĸ?-3Î.6T_U}q8GOvFuvT]hx"qO}ʠ63?렁e>Tʰ:/h[SKfdd`_ا U_t\,z4ClB=cגuHWhՉ޵vGK6׽Vr9ly2Z7d ˢ\bl"l.>% el#=*4'V ]9k(7{'KNnj: SH{.ZZ8J= AZ{\I(5'Gxi7cjG[; n/lM9nSYC)M- zc,]^OF_`ک_q>5)g3ϩܻ*XrM?KfWYhߊWu]bww`S(nTv!m뻒8Qwd$>+뱦ռlvpW>B{&`L @lɕ S+G@R"B?BΣOR&#zT,CϾ_FUtCAek-9~m,Ed-T' ՝1*|i6u˻J8B >w=dd8|7 *4F\rST%k1)R0l>Mk]K"9.oWl.CڰAt(W?["gAsMҷJ= y^IWߵ5x/T~~4uĸ닜w:o)F1>9;%/ Cof_Fm̲&rI=w||%嬢?$&`L @6l2—f? aayc;$:gwa?o*[>e*"@f.i'a?;pr5VDw0z@ad`zh=UGF#r6^g}zj80j%g0fb.٧+6sYz|e||[gcYwkkUl;'l8w}[aE _OŇ1zD}HW 0&`&'`MIJQWm §s_GlZ" D&7 )zMẃF"VS׀Oѳ5.oZ%[`ʰ f[S0OW޻_5 Q`\^6+Ǩ\9#0` l4_cWhV撳ጢ+UREšY>QYK+[ll:If_J2,EqR<grVק5lc ${ZKn25싧KwU `xN=3 8<ZP$gU)ycmOD]]k ՉpfSeD3Uap*/S;kL `29{5?:"uɜ nǜNpH}\D>=cnwPpav=.<֔Jyo?zQ6VVSvpplbhX_X!h_(5NNj+笜V ߝۂ/ %#-Q #}G-I듪m'Շ*%l`Ӕ~ruk5$,]zBї!t4*S}}[ >hC\|iےNӺ#aHQH:.UQFYjTY畯cY9E}_铳tїn vR9gAz]5h>=MSBdbRYdvOj>S4Hɼc9k?5r&`L %`^QERrh4r.tfbc,ɇb`음EFϙP9-+mqQ!;UØ;.CM06:LomuHzs֙'Q_E3 V AOL针eQ|?撳$Eq9 P\*rE{<*9zE"kj= AD%+UBH1`$>?\H(SY;(kHݺ IDAT4+e$$klA剟$JWERd'U;!U\ LIkjMd(pb:)Lnm3Yg6I9KQ%%嬶pi ƶlJ?!arV5y&GWy9?sYJcB) #P9KP\r! u|w~ R_KZ07)B[j~Z٨FR}ͺCK%4Ttw;gW$T[HL}5ZɘZ(Ҟ"b)Ҟy)􅠧 Đ6;FYͶhU_ɭrAU:}+z@iϳ-g9}5HJj ?M# AJd"'g5)i,g߯b&`L`0Z^_7Swkuk9ga7}$ܚǔYJ _a+JFκsaהopLI[q0r\ m_f(3&M$}g%IZƆ`Vrafλ.CnyVs.ͫP6>sYYp4쟡Nc@tx^o"%g?A|reDozWJN@hQ+OY;9-& A+sdǖS12Lbyp(Z n2/Y]+ 1q!M!g5?зnB4AQMF=P֡t<Eƶ 4h؄x:vѪ _ERtly fu|O"=Nya񆛧]W+ˡ`C0sY{J;kROu@FoƆk)y @nﬖ% ʅK*9ѫ>j(RoJTrk1)feWVi0;h ފR"\s `9 镳%ZY/W*RN_,Av)Z o64(/i<[k cQ3*'g.ajV_6lfbF朥/sήƹX4*SM4RrV~PYSv!hs(!gy)bSm%mIA=U߻nNHO4#g)tfYRx +/#D.&&UЎ̳j@DE_ч]sYUn/&ҫk/᡹T"3MQ]iGl-[oTr(ڊWSTkYocEOL.gr<Wh>OÔ6K9{-!GYp%;KfK]I3? n"yk{ Hr7R6=(%g/h#:cIS3?RKOͶQR}k&nRui7$,߮}m!'fǖ*]k ]( 劕cGݚ˻ĦUr߽W:x+6VGb=ڠk^Jn[YJ۰hՖ:ZWPjN"!%ITY{-F)'g,g<&`L @.YX"wæQ~)` ҳy\_Fn)Z@B >|5o:+Dzhӧ/ZP!]rV6ЪCSΒ@r"Z.3 9L`!|曡frM6{5{pWḇ6;h[@%g8*Thغvh ;R$khn+F2ߩHB_k+srt0˯L,#١e`L 0&}y@f\0٬ 5G r_ÖC8hHDJ;9K}38sq[)yrp0FїYl(hU"^Q ) r=fL 0&>#l$ y h\Aѫ1j޿HR..~?5Y*-Kt,en`g?t)M>Ӣl9w/p:n%1[؍̉imXגYR_ K=.`L 00Rf\ Xβ-rEW}ʶSE[̃+x2Y*dQr:L`mֿTݺ=.fT~~8,%r6;̸,`L 0&LI)ir]YYΪFqgUTT*FV;Vnu;Y , kI,ae`L 0&`J,gMIwXβ9blvQy(Y7Z3K3lvqY&`L YSCl 7 0&`J^II/wPR8' @zz:$R\`L 0Kl[,g@S`L 0Olc!`L 0&' ͓)6;T: Xk |*f=%TP9 (8f8%SWX/ÑfU2&`L<,?aޒ%5/܉v/6sr6,gHp;`L 0K%rRG-% KKk^-^m̛lnAyeL 0&`9k3r6OK$,-yN{)3o=Yv0&`N嬥 ??,MpX;fμYd9WF`L X:>,VEyjU>:zb\^u,3Î.T}Bw=y cz]5Wu m1?Ljg+[mw}*vUϿ3ZNm=[/Zyar/Ǽ|2^?rהKv_{W`SPn}^1G Թ"ӻZSs6ʵg̱e^\[Lvi]rcYkJ=`Un$KvATQczHtиFֹ#%u%H)=YZ(m6~<)d冼e^>w|]gs  cqgy;\*E_aǙ~GEhaFL?n Ɖ,/; Zt'!qwQhcb!'D31њq`E}d`}$L5&uBsō6ŧJLĔeΊy5Fw@̎咑YSsllp|wl3ex7 ʘBL}C6ņ |[BSin(egщ7Hߩ-G}q3(>^SW*Ƽz{sgx۝q")a8/=7KbT?%oSY,g֯Y_Oe.PxHR# M:4/knТ;~;d}- pf2ڧy7jߍ?{]4ImPِ{&WlLO\:+?j⁥ã:O{XS>C䮣׆?m}ԒQUqVi_iM5f|g|,Ws⬒/-0`ʯch%q֧Y[7ENQښ,5m%AbQogm_Jwqx-w?/svum#Jb-F~YDU)lYؐtm؝5à8rAԗN`חWz h7*Y!. zof|&к ~Kߟ؊[ndOuY5mTp~zbbn @ҡ{UqVzYxpzݔmW1GcngpiP oپ2 Ugշ/< hUƎ)[ӑ0K'K h$nXez3n׬Q1YKbT?%BL28(׬mgMG|q'KboSM?)g[*jWO5R(8sBfRMӦx moölh qy@mPk} HUbڢC)~Ǫ_ح6}/w%*^)JZ;94wiZq}5-W5qV͗j⬸[G"jyS %N-)LG$@$@$@8k'gX%0z|j6TgE^=8%9߽fK3?foTO+Gus ;vDȮ54{'0~+ooߎIb_ql!,/5\CWUO)\Ps_E]DQRB-Ξ"0g?)_+#f 2!iߐRۯxpk"l\uk(%x/J|ڻ2YSX틹?CTRjzqV|bJ(՜US&-*Ù'_ Cq֒1{o}ܻ U쮪e 6߈X">E"Efx47s1j\ٰ?%J[bYZ&Dl.royx|skYv,[?Yfj_ -1< Ck.RqV$ÁmzO[El,T?)ƾu^l;#Idaqƻ#H_ٶoyT8{WA{ƽ=]/~Cƈ%TsV(r(EsPC>~GwoowPu?h9-   &@q֮G%`8+D&rzҤ9+3;{aэU}1+X,&Qxl讖Y9+DE?W2lԣ⋸)10c˻_qnj|*5xkUKMSSn 7Y!x<{D ȒDXUX-ŢNk#,4_q⸩ja]BD6=ʲJ⬱kCEƠ8kɘqv_ t%#ĚNz0kZd2$4qP8koKכ߰JbT+٬r$c]yj_֒͆bjfv{Oz}=CYĖ Eõc*6|LYƁmf*`}߆›5{ҸUg +"_C: ~(4>Pp5Sn+メ/!A%P[z`>"NvŽK~Po#xWg֟wumz*"6;RY}IUۋ(ΚR& )u5ꊳBt_0%mAE-@q`HBԋM3bW񹜺ajP1׿DЧ{5ht/3} YZ@aߢ֦^ʢ2kTd !W!cm{*& ù:od Ֆˮx()N.88ҡ?5H4"9y[>ZU' j@EJ˯X,Ί۷{Ef4s5div 6ᜫ+ΊQw!gٻgly.a]?eLs뀚ͦq*V.|~Ǜj !PqXslHz ld}TEU+;Q,Y=WxUgu0kMczOv&qV5ٺ˓ (2*@uYE_kߊzDZalhsu|0ά>K~u.| /ny_5:loKޢcվn`Ύex#iqJuX_ qq;)nw7Z=!<ձվ*ϊMq\m) k׮laF/ζneD=N{[Έ~$3Ԍ&QԜU`d\Q8]/Yה84's">ލ3g͍)DO?WeǎZgES)4̴ɇ=9yUu7)Cm QZRl~,6h`+WgԚ6KYsx:XNh% IDAT#QCevb⬨5-qB>f'K YٻYS1ozv>/lׅR뀚ͦ."o;/b3ԍh#2qEVmKdran߰d}TEU+ծij`7MVwXj⬹k"#:n3xUt%x#`7zRcݸM3T\W>Z<;߅ n 疗C-{$@$@$@$(:o93 TWbc"-gQD-Gʜ'?q*V _!ϊA_Z}Cl58x˚mIQDԉtENdA t3mx}7s~ĮYZny[nzqVbSCXWtL=/=s8ǜ8knxȑ?ۯS`-џXU97%Ϊ)J'~!!tY-VpY"|&HZ%qvWx=3)Ũx͋cuSER_z,gͭ_cqVVd~u,صB>p(ƥ+&wfΊD~|CeBf^2ૻw)iS"csrwIvK5MA\)O&S{G[R~Ih?.s%CIUGJs4K~C7kKUM5K~!w> ?k(Κf& Ggm5!٪gGMPr+erHvTk{kwFG#u,[duQw˚:c;    ^Y;uel}AM%g5U+R Ѿ\4B3[e:Y1 XMف=kq֞۝<yg y28[79* Pe,85~g2OqcR])u ǧ8[_ h$+..gddX<ynyyJIHHHq Pu\rf8k$B$@$@$(:9C   zI q;ל4!#':Wwp(B}6m ?O,HCLV"ᚳ1ˁiWƧ@5%fU_ P]$@$@$@Jl`$@$@$@$'`8"K]~>JmP2$DFU%%h-)ZI츟^'>WX^Z% khy{_gKP_~5$@$@$@NCjq6 7&DGc+JZXQ6f"vL곖\-](0mjWdgޘV4'ayN`D̲h#p(`=NCDwp]D'`fxtppRun;):9s(Κ#ϫEKGw7С.Nʁ<gSHHHA X!fbYT"%ɸOŜ ~IAG.cᇂޘg壊lm"S{t`mR䏍Ttdclt[؅ZM@;rSCTL|r͔1- EqXb#:d/JKOiAiQuO;<):o9? Pe4؜^ݙ }4@@h)ZI$@$@$@5@ q֔5XY!y1C F͌?%qv)D{M5g5c C#_e!869H^ ok9G(#gДj8[-lldg(ڙܻGUfmw`/0S6R5ψg @ 8=7TtӦ %U\425>%XqdbId2^AXY2bK7' #(ĬlB`lDϮ gǶB⬽xNcCohPM lVm5fgk 5"   Sl Ζiar;?ۮ Jr3_%s6 Q9[I Df-RD"*ؓDUmؠ!YOo{7pZmm vͩM Gݾ>6t4q֔]NÇRti4l\P]R&[5G'D}OzZU=ZxϝAkhw>:Wٱ3X% 1w?X> ^z/M}k'd }'?{nfP!HZp9k۔Q ugK2ZOENCύ²%HOJDҶBxzS|m@0òq^.[>/!&0T-LoD$|D$fu/QsHE,|WwόYZ;8+Y /-Vd.U(.EH^i9(4~>m<|9QIXbk § +`JKX<qQA`ެ YvL,6D,l>GbЦ;FkpGǁ: ƣcٸwĩKҠ̆Mݐ~+^S_5(e}8;`6sCn?U5#gav NHab%)vh;܌Ҡ!fU7i&.U0̉]{C^Lbry^M=@%2,;W a<~и¼IpuNJQo tlogg_w='YqkuH݌:GM[biЫx33+]G#u7˜u.7um#J^MN)&l{+++ t2Δ\8EVkuʥ+Wũbį< "l>N߀yj}xih8%v&gEX%E][6bar'ڷOȜ~HEF8cqp=+m8 /a4Y.blO 97W[&74kΚ],k`O    I, P}CWp5DlNx^{̂5[6䃶ߜ\?ٿVZ.]t\bk+WgԚKܪ?̉~ވ ^.] ^4loԜMޢcվn`Ύex#iqJ#Psݥ,]+!Y&xxbv,s<ֲ3X#1}2Sw߰|kxq8s弬ѽgEX Cqkq#׊YTcMVx#YlxwDqVda-4=5%o2;B}*;ҋnv^ ?/.5g3úv5g=7zRJ}'2rb۱uMgEvB}o0+^hM(p^JJ0ղ,BϖfVx5o>}n9+fߘ8WrQo+~v@׶t0~fQQ5' Y P.Nq7\ qw^mo5=ai8sOBVz*CZc ]2TQ}~vGzi]q> Ō{58xL6_}$;G8A~y8oyS̀>cTG~UqVYB(sJ/Y{e=c/þc̦xpu7ʯT8[&ևaLbMƣc8k-( lF^94l3vY&:$x$Ί1NݿEthI§uj6>>d3"=<6]}Cı#032z)qBq8+2oMGol8nxlpm'+}% SIkjP@v /6?vݻ   o̜oz+ 88k%:mޤ+[݂'d}ۧ{-d\+NMEtʎ88[][!Ίz6 8NlNfg/*D&K&`D>piˌ3dl`1Y@d.8kصȭ@+پ= l`H=l=pM   pfg;(2Y{ YK(*mn Сy]uqY1k}3HHHH PA8[}D Pe8:AkIXKϫéTkhF$@$@$@$`+gmE%v6m@,Pu/suFl$@$@$@$ Pe85N~$@$@$@Ac&f$@$@$@EC!  #gY4(ڞ){$  ?ggHHH1Pu ?r$@q،HHHPu(wr2$@$@$@vD9ڞY3e$@$@$@G 8ۈykp5 ť(DN `:-""g.n 84 vJ8kS308/g%bb'NgmfSWn   [8kKHHH,'`qh,pc./OWgS;6!^(X IDAT9gJѵ|rurnDkoF: ZUq^a… q뭷Z ĉx+W`ժUHOOٳgѲeK 2DӴiS$@$@$@G3&  gKv`İV6ٮ:u Dxe T{MZf)?[yAtKOd-:>ׅm&p+4o~#"6z&jd,a.RRs!|Z/_\1sjS v$a*-rO@L ^n1.0))Y(rFPx$/عX}\ oER,Kqi{ &GLEW^3gU81\`EUY:_?LR/-[`ƌ4h;W^V$@$@$@$D,cHHHꆀRG QpEYH0>"IKGȩ7g*(Xؘ@ZM@;rSCTL| R0nSc&b֩ZxE`J !8a3 HXEh q6gK27'9! Ih6 & Nؘx!>&cQ:楡Gd$kJ]IGtgX OejMgoرc~8q"1k,!$$ @TTBCCo>>|2gW^(..N={Vbq+뮻3T|b۶mxp*8a(6I&)HHHA PuPrZ$@$@$@lRbu ȮHKATT@I-IG|T: GAhhd#Z}fʊ6ƙ E?2 6 E?Uʘ"h-#Lҗk]DPt5&"27⢂ z)7Xezjgpڹsg<<,))I5t\\\ ƍ ]kD5G4\?#V s8~IHHꞀl6ac$DIHOqŴ% O5gK S 0ЯT-LoD$|D$fP jPd,[i-&iK\*=ĸk݆ = K~ a8{$CP\zh0/#G`~X EDSڸuKviY}O?q:s̑ufY?0|Jaxk(Ίeee!oc,]-[`.JK2VԽ܁OElEF605O/plf M$@$@J⬃:"  gc;9*­X O 8Y.nhqaO!/= ˓8\ xt DXu^liNj]Ѧ8O?"HJy@8hSE&AVÅ?M GKU$Cj"$# ЭY:xc} Y=!~i鍬n7drgml%Ad"{U駟̊^^^?>v%Ɋg5 >̝;^f*Xd ֯_/Y={Ah߾k{*ٸi&ű4N:YlIHHEl XM q(ؑPә4U0*i`'`+qVXB~ussÓO>x);rț2a5gCBBcǎ=8uTOuVB"Wk|#99iii2K 7o\^\:R_aaal -PEA$@$@$@U'`8[؂ꊳB/:O'   8[]rlG$@$@$@8k?sg܁4HHH&(#;!   *8[edlH(:79   8[]rlG$@$@$@8k?su%96O$@$@$`(:C9   !@qn\ECkٚ>IHHY{%  pgœGP66"  p0g̡ 8k75AlMPe$@$@$@F⬽y 8 IΣZ(V  8PNHHHnPWК @q&O   {#@qʼn3u9lQ)UےuFgmCHHHJlU|"@q1_ks\[1E%Mi-d{   Y8ka>ʼn3u9l;ږ4y(ZKIHHH:gvNl }Tfm[ eo uN.a3XslgT?m/i=:!,9G߹ℱ.]ޢc`䕞do5C0zo pwig6-oKc| l፧{܍[[tKF8^rIRDKv ہRicl(;R[ʼa|Ue=UulR%յUNif^Kl3n3ߺi<a};2ޭ5.J=Xv(rbs½is]U1տ;VRS8c:GC| aIHHHf( %;G5%Nٸ?-1_|5z.&%V!v\99?PR\/z4sii=A&cY6KxCX_)FKc|-p)Ix_ !^aD<*2յ94wtŕX;2J>2ҹYʶ68gW>< KrmmM{8 o]\x5{[ؒ׮t$_W}1x;kGJ"+ahy3oqGGٵ12=MwDl79!o'&t=TdVᮣeꣿ"0Al]glq7 .2ڢ߻F~dbKF ⻱eakF]+(-Y;j{svo oKge^M1 /nyG/QȦ]?)wi޾V'OS`8uq1DqVHHHHfPNԥ8ۮiK, zw@x;qky; H/6e v@8<]#vv 0e<1 ]Txw2gMC]F.bb]7[UԎW.T;3v>N} @ҡ{EqvD;y8f| e)U7HwƿLpuGDPx&qVC_07Ü4ky Q#,zOOvfA8!`Yxa(Z%gb/a [  Zvqkoölh qyy9Ø55K,ھa}gٕXk][t?2WV)C-\Y]R` Jm~ƶXIqސ1kG8UzNf$ ܏jvT[CpKsϰ}-L<)t-0Ս!殈HHHlO홲G;"PS1Q@h(1{trt X7G %(nwUxgdkwo>ėVQ[ xB^q;?YI *BxC]klV:WUjY*/y)39jN`&9۸]?\+%$.|#>:i) C|QԿ8kRa(D؞sGJٳub?Afj- D9*s1g\k8[]d]za?hj̜5S=   Ygk/{R&z+(Y*4kڇ%f>]!j>c9kj⬸31e!H1l+γj\ՃpX$zp֢2KlBxZ`۞.2y𹨳;FƢ 2?LI[PQUrٍ"S̩&2wp4wqC;9Wiml!];g"]-V.K|~Gi8+y;@^ܮ釱HqVmo0bQ&8c8 3g|fWM?KlY4}+N0u9RgVt0kMVOv&?@M48kkg K; > 8]"c„1h֪GCcl| 3~wg> z+Y!;3ʺc}hI8[y$@$@$@$`H, ԥ8+x^9E0}ܮ ,EO_*RCIȺy$m>4p/CW\9/k_vtoc3qVԮj,ΊL'Qkk`(]tjAb%}Nb(ΊڥX'> t ;`d_I,nY>5ApZV4/OH="_)"+f˜UB,e}GbmypPVjڱ8+̼S!2Hc3x(dƴœ}|0Mq~x&Y}ܺX>iV%C5ŽlOy%j6O}<< sw,Ǒ 2~N:C-fV$2>WqAW<"ErQU5`*7rTggdu qVWZpB+kΆt D9\y'm-;#JQ;:L?B/Ƹ(<\aZefK$*|=c~59+BxpY_ɺCn˽Vu$3gbNHHHP#V@Wᚵ ?6ރkM+6)qԀ"sb8Gܶ)T5M[Kkd&PU2VP B<^#'|yh#R; cAEܒHQXaVx;kRsxOd9()OSǮJY"3Bx\,o%NމP29?cb ~EZJD G_)htTa"uxmjjc nq{xe\nI31⬰iQsR0ӯ;QZBB:{fA\CĔ*JC,F =I+e^^|nh88(m# nKEp|$PIS!,MAB$ybeR`Z,&Xd>O!6ɮT K|gn?$K۱8k=K3d$@$@$@$` jyHOZTm50'z-Y]vbm;A0^:ëBA5c.qGDbM bVKQ!yj& SçOqV6s8081iA BJCxd879),_!9f)t᱐/y*۩8[ Um9"g;di;ggIqzHHH!PMqV xܼam9HF!0Q7JƖ >O*Az|m"iY6 6zJXI.R{&bWʜF|D ʚgkkV6 oJ۩j M~ E\^gS}\Gܖ#IcIqzggHHHHgK2l{^%Ǒ_ xx{5?噅u9 ,u ø@%GJD' <"jW"18c& y)wuG(m6wmCr-v"y 1(RP isEAzj /L5+Vst(־s)H>s[Hَ&Yڎ%YYR!{    kT_+h;͉8"pP9X>/ >ax)2X? jNjQB'!i\:d.BbdEAe"y nCuCj"$#8*c 49 pqS.0s֚,6l߇,'Y_Umpܝ^HзE7OlءqKNMZgX*&,NrX^ yZ(\lXR Gݣ>ZD2k8q_^| ySm`ӥy{unMIm|Kؒ1(֤7 '`8Nȥ e x+f0k8qFI$/]]LwkY<ˮxģѩ\ űQ&eY%)y(\߁ZSxqxq"M]Ϊ"ή\99?LWboUS"HȥA#m9Nj[ޫo1 35- sԜ-1߱w&`UPEEDqD9qʩ̡kiiuYW2ӛCijjS89 g}v3w?OOfg[XFܦMx>#=_z 3,mC߉L) 0Z7kUc9*}̈zL@ɀBgͬ(ı9(Κ9نHHHnܰ dŝoL>7e'|SƔthqaA!h1vgZ7k_H{شw^kuBߚ{oEz~ވg-ד cL9w;F3{=ݚc@ )W\8U: |<s.=Hc]b`]뮣܄ڨOf'7uǫ_B-Ӄ! 0ω> K 1knd<hhwtj-0՜O7=ЀҘaF%KiJUETӊecF}>RtGTp}GZ\(J!,<.\gZ;FnbdQGD%~ZFb? _IDѬb=LJ^ d᥸r86n#˔̄z\8xvӇ*gWy{ŴEj0I0'S[|wlck+ 4$DI4Wb%86HL'|yh[)-ܬ3z5;3{/7;_Ĵu:⋄7;יM{dp/$M٫RPLݚ3lhxz:{A;ߝa=^PKI{-3ڽG~[=(WGY}t@?XeG6wvhU{3YtuK&=]i(7C  bGĕ^-RdYVǥw"t)1cK-}=o]Kv/1+0sݵı(HHH^7AeNIv5h]6J7sV敌j!05<~nm՜5CnJQtS"=ߩUF<^mΈ2d8wX=zkVվXFq|4gu+j?SwxUL`ĄCƺ1Hɡ'gb s3^b{g=1IO+ze ԥ֞8ko k=ߊbJ;3{,g9G,c+^ufb^U+I$6jf_q8k9J D}Ty2a޶C.2Nw4a=f+򅣈cJ wTd1\g_ّ=l=]O2֜?Xi" O88W6ꀬXq|_-d: sNdQM5 lTɟ.CnZ4yvz8Q}.=UMm7dT?.y4yXaOka4Yq6&4ae8+29USUnt/gG;*[?Q]%zI7p걨R[ WY+Žb/@_dpŸ8kWf"؋%hiYȷfY}[f}' ;?hu^l?/hfO;-FUwԽMF\9>j _[o8wPw4a=:*Jj"2M)5 Yȏ'NQ{#ɞgكƊqݥ8k/@~N$@$@$@Ň ZR<%R>Nxyyy*I^cgQQ8ڱ˄z= 0Uy"/UZu;Vi[[%G~gi8'1Kxz8sgRQRsTo꒽ UU2BqRyU0'-a4Fth%S/g8cYYMYJ q7?ۍkЅVt|)2r3@o*_#>ί9X~lI@)^~h"o~pxDQf;#HY؋%8t@Uֹaf8ktV;YjCK c}"TY>ڡ7%1=9UdM^((/P/^dDJ)O =_Ħ=qV1<4RUY֗7GX2gElQW_*2Vwgcv٪{{M#bKXxwd[!Փ#{{mD*7V%5puWq&B"cS =~ w(Qbڮd8+/Xz %=y3[-">,>s8+}dFP❼zcM.ܫx]&@lfoқWX6Eկ5_*5`qh֚gXgxE2,fVh`ln$Xx^[) ᭹ZCjEp\'*.]'/Qټ5 y,w8s%SO rWڊH%utT&~z=*-bӿi'={W{YzRYAz쵱nx⬣][%mCFHqVoIHHHs(z-Gg`4QC8Kh#`Frl _ I!P-u]eO,]eH_[֜u{ PuI(zb4o݂ѡA(H95' ~h_1K At™+b`&nU3qc/   p"qYt[M[0:4)p\Bcs\):ǍHHHH](κ$Jgmn17n Us Y%YYRu!G    WPuz=^B@qitNw 4bёs},)κΒ 9 B+ Pz:Ns#)@cIqug]gHHHHg]Ǿ^OQq =V &dU\ez06$   &@qև˥'@q>#   }g}\! @$@qxVGYqA$@ʼn/Nޠ-$}X|FIHH|Y'W cs bGls ""@q֫EcIHH|Yt*dYؒHx8[ PhVC߁:X"GNcpzG]plx ^O MR1Ls;i8 P0`7_DI|mGm 9inۢ[bRB7-G,x| Me(,ŜnݏtO'#Tj+CxtnY |K)z] IDATh2 O8Sb%@qQbѾN vasn$ƙ+ocqF;<%JNj g{gW`ّ Wk~21#y>)ou#*>O &D*Ȥ #7OKg1QĔAճL@)q=z^7eC"dZ~2^#/1{Ƀ6_f˦+6m;&A=⬞^z0ّYy@oo(]Φ8۹j3GYy7FCBț1ub){b)xh1 o8[j$@qA`^мl`0"}09+QVC̯Ak1Mzf/&>_SK~Cx#hXkq균ewgmٴJ ={ 8mD& &]6=4HO+_}ku@Ve8gS-&qg%$@$@$@$^g˓y^0-EؚG5*ލr%+/YTzYDXyvf:kr|,I՜'NARe8;3@*|n] SZ]*&~B՟My Vxѳd6m]ub=gM68=NsD5[ٜknߏY !//OR򅙳ZK)zh5 8c)HGlxg,te%X*G/amA fO iNn*Gnhq'-Cahv`A!hlɆ5Vk8|O?[?.H=dzW@lrrA!x1>4mN߃wS)V^&}jv,Lm>veQIXɾ*CNK1CqV szܢj vqVϦ6m{Ugǯz5ges_vF1[Y]HZ^4mתYE+ZM$@$@$.ΞX9o.<(0q`\}Aqbar Xݘ=r>Ÿy}b9goÌIh5i97{˧Ѿ˗B}Yt*DHS ngO`Qὑ 1žFBq裛Қ0gIfaGI#K0vv6z:eRT fYX25|R&D; =?s6 LÜzE!i0`=0`ĸ>3l?YkӻѝpiL^ʮVģhUIqc K3kїѮ8:C?x{Hq{}GI88[@HHH4,78[1F B<`^2+1{ FZP[8JB#ЧAI 0rlĈ8;1  ŠNQ\9Zan 1/FLMi# 0zt9Ž`̙X 䁡8+s%"j ZB00iXDt]Z5pz-];Y$@'@q9 2]HHHUM۶IIX r4n4IAVT\Gw-}vF''`3ef%aȕ82`47irdNƠ#Άѩ0VnieE4#N:{'@3UYNgÜ^7wHq;FIG,Hg]Ǿ$@$@$@$:iI30yfdToN1i!tB)3p<#%trb8uE f<^>9K0vZ_bڟmg.'`ң}aY\'`>%AZbtOqVvn-;#&@qA$(zi? -E˟ [Y0xz'VeR`2T9tucl"LDđ3gge{a[ 0z0Bh%6eF.BWĠW5I`ٵϝ%@qYrG$P\P-.$(zh5 pYA8#,_6,II3a$44NZkq m%&ϠO,p`4LKc{`j&s6f</@Bn,9k-5gVb$=*ڙӰ$=&\i"&tCx6|p!Vf«cjV"&LDđHHԻ=Z|'JgHHHANJajTJNN6=U||j LƆ$@$@$@$\g3[ |Gq^6-ZfyX*G/ =VUUUXH9Kp0 } @|8 l7"+úU^Jv9G^z idZϕ AlAH?EaXr lPZ|8xigHHHX8[,@#HHH l/ӣP=< 99!48XT @ʂɘy/ƍhf2۷l#@qch90 8E΢$@$@$@>Eq>S}xf@½ $Ξ%IG[AЬWO#L8i9 ;,kP\BHHHK}k<    9 8kg\< gM@b   pY'o8~*HHHF⬏9!  pY L978ޣ$@$@$@"@q]$9 8FcP1r9$@$@$@N86v"    ظqcˣpRmڴiܠhKLIHH ?^ipN(߇i|lH$@$@$@n%@q֭89pTݿ?^~e)S|Ւ'MC߹ضm&Lo|饗pI̝;ǎó>x};$@$@$@EN{âڝH):LHHHH(κ'G2Ί; *6⬈xǼ 4HHHYVrXK:Nqar@$@$@$@%@qֽ<9pV[n~lŊoȜݲe >s8qx HMM|R|mݺurfήYCl6lFcڵ֭Cikd_~%~dff"&&>(6le$@$@$K19*m&5pے PuKgE7og쀈۷Wo<8w~ihB㏱uV{'8+YRoWGUp5 SEڵW^յ߾}=z4z)mӦMSN8 OIHH gKbtѲA|u9fB)z   '@q}@YqVDNa.\S*RsoŜ9s0vX4n+WT"'1f4kLrWYK}ٞ={bjmadӧ+UVܹ35jLW+ lF@#Bg`.$@$@$@$P(eQl "J#8p@lXh k?۷+AW]~}].;ƍ{o/"-- g. ZgZAv횮F"DKY˗/#00{/bcF$@$@L8;O(}m#bt\ W8pEm׮+̟?u8b ̘1on&Z>{UiԩSx' tLաCڵ)qVqV0bŋU6̙3!ٸ|x˿l;#;1z֬Yشi)** ѯ'  B `K _A `[|q0s)HHHH,c 8*Β% 'YQ5KHHHHs99 P'D   ]g$@$@$@$(zh(κIHH'{CkR~"j3ifffԒCˑ *v$@$@$@$w(^F]8 Q;7].8[]DIHH ‚ky͎vg 8"   "&&q".ovg"WBew|5f}5 "ZiSXOƬokmKq8y<gY4HHHc91HHH G=>݄3کvЇ[ ܗ8KPArI$@$@$@802v    p8{d9-HE֤xtpGT42*4c |.'."vzh3Zu3HL<ף pG}[bh "+> S`yAB*7D=P)F]sٖR:M[Pj뙾Ҽi$n9܈8.|O"a߳Bk4- 8 06'  Ig}ҭ\ p8{y/ oa.0<.3`}4 o`{x$fJ9:ޅM#pqbiS1ci4 =oaņxXԋ)X4w;bE+ص|>V'@$Svi412"9K] ;F.=T,||-.Zz{Ag}ѫ\ (:JIHHH= ^Ʃp ڵ/5@d8iД)װky BmQ}E<]ú#||8"ޥ0omήx{- ?s=1kU=rL[S,.󈞨-E;cDOV_/N.9V⬎'GqY9 O8nHHHlFZy(ʵ":<g‘3Wgp/{/Fx u.>?OqSsXK(1VIϥg:%IǮ5+2\iYL7 q6ikΪsCMSbiNw ~ºY `t8c?٢9[gƅG%}qS r'1^0Frs-O%33Slzx677*T0ݏ IHHH(f׹3i=lc8騳j9L[#-0[mlX"$vPZUlYl܃њٸg}\8n_o؋Ɵ!ms'1Y{Gȱ):ƋIHHH\gb Ԛ60@ in?݅}y/@b]pWzGV` ~7oc_5gKp!{iUv#hY1cix/ZA7挦,3g>BG yQS8yLq^<1Frsbk   p7#")+ͺ]8Z69c,E]+RNJh-tl[Cq+}9i#h9܅]5zƑK| \)]MDȖtR̜uw,xg& Lq;#1Y{Gȱ):ƋIHHH\gsp|,tWlXR 6x98~"JWF8f_,Pp !@q{|eRް6g)κ3xSO{cؚHHHMEq2^:RuN#+4bsʘ\gK[Jp.d_¯w`qb+Y$6朣6Kx ^BdS[?g6}v;nUǐwNhѬӘ%6v5?~iǩV gOWX#vۊ-C6]:.\rU]můKw/mq[x#S)]qmfI 7=[,[h>/-sj8V؆on,ZktsLn3mwpvo0kڕ/rg--x7ݞ^Y X9ҰO;Y` $@$@$@$4gf~LUqvPѡJc|s)vgA2X6T '7L5]͟ލ#76ί7>8;hLߵ I՜m*݄convivO8[3 op 3v${4ve1Uz엝Y88N˲vw1z›#܌l IDAT1+j}ZG/XU'cmƻ#>wn9peo(,q K:+x"q r>ϢjpY=mhPuۓ { Pu/Oe\g+ì/?\i'<Ň~ȸ3YnR؛y.@Ш?O_N8~muUÏ7cڮ ж'Yߔ|뉨;},7`l\ν)_`ۙ}v3j9oAnnJ]c㷳ȿA{~V] Oo͎HR#!5+~>x᤺9>|SoLN*;+ _u㑟߆u^lj'Y/H}HrP\UsZ#[-[ kQזrbSkTIMd|/eٯûйj̮T: 3ۍCkǣexԾcczbllkϭqɟ}BosdX=r8#zIS*{/O'婍sTue>^+%  9g}Υ\#\gڝ)7L9N7*Eꊳ1(JҔH'[M8=|ƒbO|,W/7ecF}>RtGTp}鹃J!7X$_͎hVz6,(;AUfz"HMi9}7v̕;XT(]#+-n 2jfT kHD3ِihcĒmwy-"V2MNJ(Fᩍ#Z.f{(lb}2jE5#nzqF;<%J {z7]+!fJuY5򙖉Q\Qtw^ d᥸՗gg8ed_tHZ=+$dj0I7*u*5! U˭ő& (Se]*3sUƸ\#Mg疜z{iIA/־8iqכcIU8+;v\V&Zs7˗zf=!4k|fČ}gˑmIHHH(κ)G"wVĩLCǵs`9'bԜDRS)PT9LٱH<(u!jIJ=yY+>IfYda-<WꡕM]/r{X!uEcl@UFqQF/\Xb_ͲgHiuZ&Sv"+]:f$ z⬑ϺTmf3^Eاoꍔԓ2m#oVOz3y4F{ZbŇ>ݫey%kz WE LcC   7g\oKŧ^a&U&89,<G.RãQJ]!{RSخxsg8uF5UoٶdΚHgfT2lެhi8qVj1k=ql`0"|//Ys"Ye;Bɭ4ɢfIGo$ψ1m499${ Qlg%Uj2X;!WtYS_ře 50 (eL9m7^>2##SZ}?]8uNͩgϴvŕ1I~eL⬥gmqE{NJ6"ˆ2a.!,< 9rrUɛOۢ[STr<7 be,;B/c=)z*$   (ΚgŖ>HO7VGfWAeGh9_c|x'YOP$@$@$@$`Y *Ζ,Qu& J[Mm$cYl[/{Yxm+ߌ۪ɟ[*^i:;j7:>GC4za0CjMz'ZD_mBH`i[~<v}mz'ɞ &ma)-  Ę^oo KpIT PBny&lrmFlY/RСJcbz3ŀ%uA%~64w?Rǒ0ZJTVGZ\(=o+`JuY-YFaT 9cpUsI֟X$_͎hVF&M/0j=il)`? pTвυ'2gI{-3ڽG~[ @z69l3?{@WY {O'1 Ÿ"/j&QZ6[bO6'^{3<8-w""[ x5oa*a1IF[ÿZ?{w6!4.3,ue]̄z\8DxvӇg?R;QY٫ ku€nؔ w#)m7\90bZ;Fnbd1ܺKx7LaPj}?莥A2u}o6|8xu`"T(d8a̗ \9՞IHHH(κ'G2g%[}8uP :EUkHl nD!r->빛aT37|ͽ']w"6^=yCr?P=֫=̬W+$1tTf-F>x='bKJ =&2M2_7ɂԳAFVwjAuoGR0e"TxRv[kc"JڋgOsu,8k9pJG5gkclT<ѭ"j-U+[g&eq5 AwT-ll?e/|-*G %>ʈֻJ'&ZWj'A-j [ۨx2@o,j+6m+skf}hM3R ~T7,Z7=6fyvyZMqV7  Wg%IJX.UFh$&~Qctϻk$^Xuw|k)OI?G]g%PA!JpI>ߣ?Q/]CDfkigaJ&sVbq"DXIXxz@g5'y"^ۿ{3ٌس 8y b³8F{lP0&4g0qV~}nEͲg|$hS YL]Q֠w;*'f6b/TdF˜zq _^fȋ^j ⬈C߉7PO?;vO5K,s^YbFsf1ftccT]6fyv9#:r8[\J]$@$@$@B⬿xIAF7-qrSgɪ4 êctwR+vH5h}4yvcusY#SZW{)Ы9+T7YgpkTStn^Y[{ Z[n=PY#FȋvfNȯc)xf+Vl3Z37dƞYgy8+OzkF{B-:E~K{WEP|q֑5h8[{3m .QNa"Ą5F2b[VRu8[TY^Ye~\2F{Y9?8Zپ~n"+]͊Ftu٘QgG2 -E˟1Or{.Xz{Dؗ~)BtԆ^g̊gםˈYEYBq$@$@$@~O߇p8kMQ2b\ȨdFP";b7x^(XFkrBH]-S/Dzq*+U z_b_&\PDGm^1JpV^VHc(^'z>(8h}zUWR{H[H}XՋaM[]dn-cVY[gs8]): ے Pu?SE\ghEf"3Z݌PsgWL&c,#5__fg8kۑ gP W%(zQtOk|xn!Xvm5_nj'zRUI$@$@$@ P5ϊ-}Y;՟niூ#Dˎr"DO1IHHH<Y8yM?Us(cZηXd|93IqT9& '@q<+Ag=T z>r<7 be,;B/c=)z*$   (ΚgŖ>HO7VGfWAeGh9_c|x'YOP$@$@$@$`Y 8* .HHHc~aE~LNN6M*>>^ͅ[cC   ag}ع\}g3b    '@q} Og_hU!pT#ONQ??wO3q>8Ό=HHHH(κ&:ge$VP0p-ȏkTi+J+OqqfA$@$@$@$@q֝498[.'kF~g]O]Q^8}3c   p'ɱ٢u? \58Z}o6 Su{ ; Pu'Mu(I`ZY"{~WW8N؃HHHI;ir,#8[DI|m =u2٭U&a"\Utw[ ǪэY5F7ǻ! ~l%3\+,~E[^Y X9uU-`aR)ۿNk ~-K\m_0}e|3no$ZFNͲUC0`ݍ紖YD]Hys.v^wp8as=5'/.󃫱v{ݝܲgmw}jv[Jp/c{9"6@ =R/d_¯w`qe:~\BCρU؝yvlj=d뉏WmsssؐHHH|Yv.f⬈9iW߰qGZ{ts4@wZê[ñ~E.-ί#J&H\e(Oo,Gca$p8w-CRnշMB\ n]Y-QU]oY7l8s<^: GԊvg8]G P#lJ\+-eO/JDզ_wg=Zwvm-tHB@BHB:( *P@"EAAE?EO4! HoJ ōegve۷L2s߽3~{ W?7*q[uR?_9G.Vif 51q8{Eѣr;,vz&Ǣmr]t)^Z?[sKd8떮b!(@ P!qq@T8+AgmP4v~^:E``.knTVnH69dV٥G7rq:zceKlи Kû۾D6rr4PaP<-tZ>p >l6ݗF"%r^,^wWf{4Iq k JmFa鱍X5U^WAܒ\plUx񷏔Z z36[ᢙK7U+K{nV7=|%S0|4{3gm;r0: Wl6~,s3:kg5h}6ɱp6P( gXG x"0hdxBᓯ;Ka.>M\_YکyY=?᫃+ѱL/=WiXv󄚸l3Hs.ź;Wou_]ol4D f¨ 0sq66ً+݂Xq*7mGchW>l}Fy;^e :o*ތ5'cX{bNeShYmB53u/RxBa6[fM'VK},o'wz玄,W0u'qL8kt:`tjubsx9m,alJ\e)R4?/Qpf'c+bXʃxbյz0E(׭ū@lۭ:z'~ ^FafI򲄎 =̈́f#hYo#Aޫ]G@Q>* 3,;OÝkm~l&MΟ"Pa\~kYOM(@ PpMk~\ g/eoPٙF!|iB h_֡O%#TXQ`(l ,⺳rk+!t? Wl٧zG^yM̪c:ԶWf 5O맪dvEÐpEC1 5jv q[9n^E@}#wp"lCi-̄f+9r{>$`뗬K.3dz?Qu g~l}ʹ5sVe׾l-~Y}%`w]: |@`f܆(@ xNlYZs W2F"`!n geS" k`+:4+z<$d1Z2Af=Y)ĔcORnp,{ u  FOT/}S쩙ꎜ$uW[uհ,mP&/(zˬgĥ޹Z0$< L<sYp֨_q0:GZ,76=-dYϹeRmϽ>װ_n8k`mTNThnm{~\g;,cVz/-dbzȃ$Uzv?bB౪dDq]ɀLݏczdY2HBwO]76-Bi̦|P~M>̡[;7(@ Pn`8FΆ^_3g}=FPW]_qІξ0>tf9∁'Μu-(@ PpYD?`8 GY_%wkV0uW P( gXk7 0uSXᏁ[G:9 7 9sq3A P)p֝,z˂)``XYF7yp\f܃(@ S;5Y 0nSXF? L;ojZ>Y͸(@ PpYwj,`8. kc~ g]A;wq}q P(NdY~'h8w d)@ P _6~LKK3QҵMRRRgeeA[ (@ P pi7(@ c(@`8Z|a(@ Pi>=(@ P,p6;M/h8+o\e cv\{.7&`jA07לupps P(fneq%p+$7.q(BQ3^\ʺo¯'_=n ̃n(Hk<;Bp)@ PκY`},eb޾enS?*-_Xq]@@46 &`jI8}p@f(@ PC g=bCSI]Q|qg?i>^UqWf<@'w0S[$="=za8q)@ PYf]@ 0n 7ɲv^`On(vsxeN'RV-R{8:U/{3osHk{n\ee\z麿iy>Wgʹh]. u*ad {gnZѸ[_ԺԎZlh]9Y8|]e6:\Ght߱kbJ5Pʌ6o5EG7CTCTMv|羮7Fi g](@ Pu?p#yH{Bt~eLGp%'K!] gw.ց^L8hhP-^=*Cms։ِYxWhP|/9wUZS[(q1l}= IDAT΃8aF pv~8um8J]ڗJ-0@9yXtt=~8.=p֕(@ Pu?ȏpV*ߊc;0e4-=kә0~l^Nfɛxfͻ*h':4Qo{xFJ;OÝk-㢡yހ7O5"m:B TK(ݻN̅0㛶1|t+Uc6Q{JGT8[PaLm1NƑ'l16X1SK̆^~"w_[ Z>Y{w݀x({1-Sn!}#o'7}73{`[W6κ.zl*KW<$‚ 0cO pLCF1 ~b\=YYljV^8+Ny  Όd/[,=QF(899MA_R66jS ges&5O@GVm|2Sᬙz gջ) \7 .Q&*A1G{mK8k{1m rM|"}=w/T jVİĪQPh^bt>3v,ǖ ǥ>Y{ⷓtY=W..;$}q|w:~V!$iӎ8u]Y^(@ P g=˲}^쭥C," a~Qw$Ea\'pϒk ˶Qhp~%"aBcHOBfEC1 5sbMc+ۛ\sVBYkOfd gřpVBjqA*G'cxJGqa/5=}*6뤽8:sjDzpV˾ƫ`kY=_uie=iOW^QfO N g_{ϙ>OWV(@`8&t8ۥM(76ͭWmG]CrCy/ۼǣyB-B `L1LpV&3x,UbJc!_'|z+̊7i2[H װ[&AH,4 gWTbl)OBǪޮf̜-[$XԺ,2QBMԒ/;YW go+WZxgLWYcJܙ7QByڷmjY-kvUcJ솳rT݇"|5Zú-?-k`FGY1&K8:s>*U*{ jSᬙz9k=Xs众ch g-kƅEf 8qmY `ֹX!*I/\8i+ΜR?{7 ԽP3ٯ^{ -_=SٙbI> ]Quƈˑ{u^w{/(@ PzeOUR ^Z?E1/ڌ=ddqmW͢7`aC >cv伷cY=f,esW_p2^qһ])ߙs:>I[|WnXSxzn8k3]RK󣪊1~9rn?Y_W+F P@ 0 ԞeL x:5>j6P}vكj brל{|x ,7F5 =nF#)<6w6̜M^pgaN8+`VWze&Z"(^=JV(4kSᬔPvhTW=pm -ǪކԯQ6*t8+kY$SSmgeb-ܔa-s}酳32{AuC; Q6qrdqΚՉ삝BTIMk&dY /$Gƫr.Mk1f3A=s{m<xhY1'sU~֛%,!,a}Iȹ?>6S/33gY5eƤ,aYz?Gm\{Gל WKռi66Z}5^rٱ4ݾp2^qһ g=~xӄᬞ&;\+ew5<*mfHhs_.ap]Q(@ 0-Kw͕uF[=Zb GcjyjzF'W.2ײ_ ;۾@mU( ,E6-O9 ,C >2sV:6*Prz  iv%,~jƖ3u| ^43XT%:NU+8w%%B *,[v M þ0a5SWq@+g_i/'̳?F̲O_>9{k6MSQ4r,;1CӄVZV8+4Vk+߿iyd/=k|])XMoY#3 sU~;_owmqr_1m4m(e^fY#/z}tJ}5YOf1pVʺls~srLrM#KsxqIk gfS=>4grzX6 σ-gZƈ,"!}̽}3g s? P(Yg# je |n̘Zp`~;R<P2j/xxU 7bdt|A}hė9G͕ʭl2 6S(m߫ go6;6~o WŽZ˱Ď<0͟%e6L _6W*b8{M, P(]ѽ,p` wiBa[n2U7F_;{ n`Z B`j i!ؿ Yώ-N P05mVumI5hl^ccO&`jGc%1/Gg::b=(@ PpYz4?`8{o# tܩi`2}mEkJ~a8)@ P=`8{o# tܩi`2}mEk2嚳],(@ `8k߈[lSi(@ M @K~LKK3-ʂ޿L )@ P@ 0 e 0o-(@ P|l!(@ P)p7'GY>>:(@ P _l0 (@ P@W,GP 0 g)@ PA/p6(@ PY/w])@ PY(@ P,@P 0 g)@ PA/p6(@ PY/w])@ PY(@ P,@P 0 g)6 ⻛`rJ5ȴn;^AZk`˙}y6]Cc)@ P,՟l gM gSa8qBmpuC(@ P.p6{3`8B C@/ی[[>G)aule0fZ1VMnP3݀nRe6ڭmTVnH69.g_SuٮZr-T9/GDzM8s2( gS$ PJɓrƬ,(k _{7EQ" 7mG㶟`\g!~;+Yp\T"ƧÜ?᫃+q_[ E~g0)8qk g gӯ\FOaI8v42Q gdpYw< P(YǼu 0 es(%m8+!7އƣQrלξ$^<9Ad Ov 4^Nn:Q긖ٻѧzG^<,|]ᬯG P@ 0 f rPІRZ]~tt8jx1:2sPHnT8[+JEn_-4p2( gS$ PJ_u+neyNpV"wf512mƔƋQH򰰞U;5hau8+3g[&SM壒 :WlpMv%(@ P g=}]ᬯGgVMnTJP_8Z Fp9vcQa?đga˲W316ZVfCJ)p?kI|`8< (@ P#p"upppPLm}:$MLLT3eSSSffΟ??*L2xGPz<ۚ9>8~[ʕ!?[!e޽4hw5kU{'M gUu(@`8ZR(x gO"۷/:t;O?4֭3gΠj)޽{%֯_ŋv:u_Tj&M{`^s:t|Azj6$zСC*|P%--MY7p@+W/=M)@ PYo(@ `}Άt7x#Fl˗Uh"5tȐ!*վ̜Y& u֨Q"##U19+ ^pV;׺-u=z_3f`ذa]6F?(@ POIG(@ ـR6gY[Kr&L֭[U(+/Y`ĉ0w\ꫨZᬄfRH{]t-k`r-m{L::*Ufܹ#]m)@ PY/(@ ٠~6ޝٳ`5c^z*]p!&O&Kh_ffZf^zyaÆ jv k)Y^["3 IDAT(@ S(@`8ZzHY֪ƍCDD eeYY/V4ӧMUV7߄,``III2e FҥKO>Q l탼̆YYY֭RRRd [K9gϞmˑ#G3g=48Y,(@ P #6E P4 g9Zᬄcǎűcڰ͚5SJ +M0sLvjIYYU5k֨IX۵kW4j:زԁK,Q77tESІ gb)@ P @HG(@ Y2V؝<6ˢ(@ P"pWz(@ P [yr@P(@,G(@ PY>"pG:ՠ(@ P gσS( gt,G(@ PY P(-ޒq}BOt+A P8sS( gp`8q@ P8sc(@ xKᬷy\`8JP(eΜr(@ ٠z6\rP(@Μ(@ P`8-y'D7(@ xY3g<<(@ PA+p6h GYy—us``j'-w!ˠl]25Q-5==]f`)))j۬,ƚޏR(@``8l=`8?oY(XS[zu˳,}&Y7(@ PpUᬫ߯Os83g&XLm[;h9[w̾rMk~ܛ(@ *pUA g92H ?ɾrκǽ)@ P g]~-p6oǙ,Y::[ӟ+k~ܛ(@ *pUA w75p=w-ыP%^.Kbh{ǐIDFc4~xzͻ5O߹>Eؑ~H5t͕2\W_m4qvVG Sh_!#pEV||\un>Yp`&:^MJ܈v`d SN|sWfL̞[Wsp ٻˎm4 33us|u8R:[W=Bݸ6iːf63ZEsFz9/˲[~(f:Df a8kFP(@ 0-Kw<'2Q$$U `؆8Q8F"x}F6&VіgGU^dK ER&~Gmmoys6 ,L??\VH`ك/ۡTdyF-[}wѩg=޹n^i9PqCzزQ_چq[>GD1s40z(@ ـb6Hlth$~'Nf㣝] W2g _\e}M$a|f/t "bY~"}Zn**,S&6z M±1FgJJR;ңiUa ¨35|>_A-_+9Y Cq #bqA󧡨fTfsJ83`$|kuU3% 6rҾqmPwmiR ]Ba6ʅޛs6FD`jAv2\<M2OD?NJQ^5(-3Ѻ;^̴U䛶qOC0. ڳܥGfZ]kǞlQ;"<'VbaELa\g$Ȗ%Ly kNpdd놳/\(}%sx9m*c1%2Ynupu57pܳ_\j>3 ͞3pՋF^m,{^tc\w&5fY2 U᡿M\_*O;n87' gZ(@ PYp_pW8m  Q[>{P!DႡ+t&DĚ~**Pa|z8^4 P!݋#9)=q{Fjƭe_j|uT8Vþ%_G Ƹ FGo=†pKr}4G^fs+V٭,1jȸ7n 0jXW57sCb1vw'w!3*K}%qM/k9#opKyfKqgRO뗌扵0}Y0s=1Vmx*̳7އƫs֚z1ZRu$}a1k\zK,3ǧ>n^Em5VQyYsxШiYzN˹R ԒC_[N&P{@"NpVfA]͜raܷe HXut4JF?fm8j}$0lUqnd(Lg>w.:k֜]sb{}۲Z.&ȽY1欙{uΚp P(9e~ pֲ_*^5;xxLY./l0Ýߩ?j6J?JjJ }kz&yz|@ˌƻ ޒsCdyS=VpV:䒙Ewm*1}2I8Qf'˒-hh$B Bک=ᬣǗ2Xjԙ~`WʼX|whpV#{3mՆRzfZC`#瞽{zui6)L6CHj-={yL:W֩.76-꫶g8 sպ2:nƈ:=kfy}o#:4B1{hYW#Q{ctҎ%#+W] gEqGFب qroi& F,;(@ PYtpw8kiMƬ=?uB_]nlþj&̎ WڰDu5Ko҆72[A|dǫݡ'kʱYUٳja捹6YKƨe %_5LWSmrfVpO*tiߌY U+g˚|>eYX!Ǻ;s鵿xzGY6JVh)ܔTm[8l? Œ/5aՌ>{?uǤ,Q>һ8WǥUJ%T瓙?T8lڱgg{zFk\&O7sle}%G~*F}Egpuzjmh8ۦd]븙k2Y9L8WL߷Uڱddbd\4{.h qmv!3g[&6Lᬭ{ᬏcգ(@ P |Fg%WY(_KʚSv}el][sv=pSR '„ Q%16ZVf2DHX_8Z FSeNN\% ,삝ӑ'iw[6.gZ^fgŅE]*܄~UоN+\H8+3d=);W<lC(Xors8kƤҔK#Uګ[6;K ,-}J?\yֳZU ɑx׉ ֳl(r=nZSl8ko<+|lշn(V~`fYYsvk՚7'S>g gcھ5WiǒQ2hY[sA{^kˇr,Iʈ + Ӱ1~'d꿶]sVo,]O(@ P gϣ{Y]ᬥWsp8fYo gkt,pw8(_+3[ԛ `ÆףR;t,XKйB zW<Ppֲ,- ǻ_yY`Osy߿wip[[[;i9[w̾rMk~ܛ(@ *pUA g9Le0g+^ssȴKf_&p5?M P\`8 k}|? gzwyd_W g](@ PU rp4Ʋ(@ P@G@m]FYzz1--ʹ_JJ6++ (@ P [yr@P(@kK0H(@ P/p6yDp4 5,}{X P<,e < )@ P"A-p6(@ ٠(@ P gwzǝG" [ +KU5 f}h\̺F%n@*-gMs~%Kb@X|tUlf6ڭqv? WlaE+iuLyJ^nW3gC ³5C7-=w}l䲚 g+E'= %#0q[}R`8GB P`8 эl\+?O.QW%*D?EBx1LnFogJ )"lrQsXT-^E-~!b#OpKx{uv!hhe ']eaDt(uܽKNYi;OÝkPH !|nL YV(@ `8d`8AW}wDTe 51tT7ii{0.RBkrP9:Sz/;~+@ (VCjwm .df_̜pvB=9*|kQ=o,՟l (@ P'p5vY7b( @ӫY]Q<˿Uڹ|+ *4~,agg+U6L)XHF[fY)Ĕ㿫% 2 ieW{qRnsgkST iu{6t;I 0Р(@ P`8] g<<$p[Q@A\BN0cϏ&mJEZ6㺚iXZ%╍3q4nJ솳 !Ǻ;s,aꂶ`+pV `/Yzz yX PM gb(@ P gn!p60ɑJGp%*Fđ'U¢^sv=pSR m0tveYmxJ{ ~FXP5۲H d;ej<lC g-VI[[>t4QYz^rS>$pև:U(@ P (e ^ Pa_=v@Rx? `vLg#>%>+^1ڍ76k{A֘}g^ gC#|.[Q+{k縔u9O; .iSvF3n;r YC(@`8ڻ(pE@N P_ 0c)@ PЉl g(@ YC(@`8ڻ(pE@N P_ 0c)@ PЉl g(@ YC(@`8ڻ(pE@N P_ 0c)@ PЉl g(@ YC(@`8ڻ(h8;)?e IDAT(@ PI _%`zzUZZ麧mkz?nH PMl8ۛG,(@ PrP(@0;# g}#X P*p֫<8(@ PA,p6;M̆(@ P.e > P|Q/ ozlU(@ P>.5g}X= PZ_w+YW?(@ P.p6{(@ P gc{]׻(@ Pxz(@ Y>VU r P]l0G P7zSYw+@ P 0b(@ Pk~} g](@ @a(@o 0>u^V(@`8Q( gXyWtZ4(@ P%л2ndm)@ P/_L:oV\G P# L3=J P@P 0 gr P(@ g9 (@ PWz(@ P^`8U~(@`8}ϖ`8a@ P8sc(@ xKᬷy\`8JP(mΜv(@  x6Y PL d^o60 TV c ͗HjɳϹ+d+ ѡpִ7(@ P`8NMw{ /9|pԪUK-[/~7P|yY<8~0cǎE׮]ѩS'xa<36˰sҥSs' P lt 4 @3ס f-;G;v[xpaC@ P!p,o\ g;v=zϙ3Wp h۶m~ {3+W^{o+N P& ޚol)@~o8-Yg(@ PpY˄, g6m+W>@HHz&M`ժU*K/:;O?uPsx!> #%4۾}t˴FgUgݺu:u*߿?ׯ޽{v_Ǐŋs-ZY!!G}_~n8+~znժ|Ar?];(@~*cgnc߼;BBop08{2Z$⮖e/N8۶fJچ:M-TUƮ$<1 1&Q(w gXaw 8>2e {1Gɓ[ ;;[S{enرCUG[nfFF^{ ߴ.әpq*dY2K\\9L4 C Q9,ĕٷJۛ9۬Y3cwޝ;9ˢ(@ ̜t ظ4}<uGVaҼ@Mґ'Q<<:[pF,6`N g74X(@ PpVᬳr/  g%\dZ@fΞ={7t _el\\&L[PV^4ĉϚ5K-kp%=ܓ-IxjTu؛9k g-Ȍ[nl,Oꫯjժl7wG⩧2:˙qzO fz4,[1Ŝg_3emP8kxTU8ۥjV: 1a1o_*f,Oy goE(@ Y3؍7oMNWK8b ,X@͘jfffn8+\zJ6l~bŮ7Y^ZW *RY@29+a#T8[N5CXfo۷oǰa,3gκq0( PN8{e|~ l\&f~ *$Gbh|N:BB -Ěpr1ﱋj[WdfpCG(@ PZpV# %A<@.^z H7n"""vV, !fҥ'믿VKKKۧ~[`~J*kʒizo&dI$diel'Ӳ+>jRC.\h70[nHIIQ |Q|B@'^dAJ..܋rhv: [g=q1+ ϯ+p'F+A P@ 0 w%`RW`t*رcq1l+kJ)Bmh xkh]JF}ndvvlW|ݽ(j[ CPuV-/(ΖOq$@$@$@%Yq   P"@q(:x      (gK;-+(ΖOp$@$@$@Jl$@$@$@K+@qa@$@$@$@(2 HHHHTP-8[V,ǜvu*qVK۫͞:lJ-)C~88[   Y+El NMECdy< 68}5eG@͖Ҋ(ZZt j!:a,rId3;3Se|ל,c~1\77UklcӠ8Kqֺ@gk   H+t{_pCn V:5(m;1 FvRZ6aimvm;kw߾EEcsV(jfkφB% '9^vUcTnXyz&gm9wu ܵ8)lhK~s50V< @ P->CZ((Ζwfuӫ%F-.u4Xj}@H[4;kVpaNfM.ꆎhᵻ`fwgsۋ:otr`@x3aMufY͖$@$@$@$gA6 GlZ/eQcʒУaSnQ?NcgB<һuVl*hnX/`֙YKu܀گ=p\t |W,m5Ж6fΎ ku@uȸ}Wckp>3ɺukhFѦjC-/f&ねokRI#.<"15} G~´ }?H+zYZAiE^ XGآ_-mg/\/QQF@jEf1q5#Nߣ0k?4n=xk{ܵy+lsVrůֺ@׾/ o`d0NxW%_O/Vha+N^+׫e W*[8k -%   Kl gVJZ=x V߃iX t!^MϻuH(=j~c7g\KB: 1m'JN/QкVE/oLAV#6)vPݯ ^M‚mY_Lz~겟qWD>}u+?3g.9}լE؃nw%cEܯQ{{ب# O|ǚeȣE{n/bK=kv5\8~5Jv`HU7*Wcgq9*c jc|zxbF`*T1 јP|qּ}kx@V+~bn9;^/`w٩Z̜mZ9Sm VNOC|.a0ؒ8ſZ|f8|nT^K:9M4^'^”^dDn?qkGzVjW j%g|c#ѻIs nѦhj8os8mcX6])—!#+Ow=6=oeG+Y%jpJrJ3DR8q{Μz 0\/~.ƶIXUɝxERt {䋞͏T[;ݪ  ᡥ8qkE}_MM>oxJ{u1sV %!   88\8+uס41.\yV..o[l<ܹ|"͵1H{"HMH7",#Qj@ܥ xˆХ^c#nYY#qVmW=ޭ̺qMÌ#@rj ef`ñCԵ7엓3q-=\ĤM(NBg:F׉¬1fmY+h@BDtY$DϏ:_ۅJ4L3*@ja~+1?,%FN:j־8+:<ctGF=*)H;qZblh |)L.f^cS͢86Qd-jVj-l~A^k)\kVj%-)= W/żQ|JAFv6^[O ?(0!"R>=~"]WoG5E B۞É8u:t ERJjz[}3!1Ywާiy+;jguSVgga{-ƉطعcHX[#q6l6;GF^~>ݱ[EEqVOM" aykT\,q^;AUUx5ԁKë6Ĕ]/ k7OeM?'&tl{?(j6$@$@$@$8gǖgE6[Sx{?I&+'/ SSxkTP܋Lվl+DEW|oHVCā s4&|ͺqӖOՌxgxwF¬m(Ί,_l -]YG%񨒨 ߺXn-ln>5`hhW:Ĉ̖8!xqhQ.^ju>9{!;٩& AY4Y-oʒ ZHa0̼VGYaVIxPMҸZ(q6YJ8y k Z֨:F̜lL_6k>uBO/Y-L-p v߹3޾h\igWl>9=.S+k0@=Roӑ⬚_?}5IZyㆪ8kax)&>~۹ w&k' 3e-ßqJy0kTRbYzN쀐{ _"Zzƨ ȫ~moYt:qOuŽU˟bgPb   pcK@I92B; _Wl rnbǜp_npǫw|nϘo=cW. /ܼ<|u- Wd|CqV|(2DKQ2A'Ϊ]Bv 5YS\}Lo9wox qvnۉ6X7Qn.I>.Yqa#ȯ^:O,GvyVMqy9~[jWyl(ΊL@}&~0MҸUCK%qD~5u,[{!GI,q`X3ǝʹ{inXQC8t)VFX|4nҮR=/^܉܂BgxҵESljfY܁ :/trR`\8b欰aOE7wM"] 9yHHrۉDjxB=} sp߲g[S[)FqV %!   88\8ucһ7B`j3b* '7W֋;NI<޽/2so g[CN5gE7amdi1_wMg+fqV/ⵘ/Y¨h 꽊'\HFS^K8,>٬m[Y9=fȦql'D6(h!RmWK?xpA1 Yt?GqV|3{2>dA^~f/OO=C%qvIN\NKD7QC} y:Bb#lkgϗq D"lGl_7<u7nv8kɯiYKi) k:Rp IDAT0gu|vlB4,KlCNA#aا6 IWv525ČΈ$Sl#8/Fꁥ_P_Ep߲2ne+jK}FqV %!   88\8[R&us|WgEa-ۡsFSҀqs,eay#tAҾVqVMHi\Ͻ%[+hyD^7ބz˲>]WOȗFu 碾@Mev ȳ2l4^UĎ1NW{㛣e9rXbGqV.SJHH(kHWky5jR jU l6O1sd\FK['l ՜_->欨y%}IڹUGT%c푃xȄYby+EtL7WR5Z3g[ΈᮒEpfepR:w A5_=T]Sg,lU*f`QBrD-줡%6 [Z!V9Cǡ>[ٜy#GyS4^(N[(l2ċ^k _O/ iRUӧ(PYzG$Ί=L쁢lK\Ӡ/UQ|doyTp×]t:q6#7[qoY-؆HHHGr9 P{ V؃Qӯ ƵЪV؀vcC;gGNW+_&"Pj8{^:L_uE91BpO.X84dΪTv4Zבd ս~#Sfp)zfL< {5ǭě/"<6\xx{cvd C&C!^v'\JzqVA $vb٤&C000~o<]Yav˺/Eݡ&j#yDFylxQ|!_D7/1e;ԹY~P_n]s׮~`uoO&A5ѷI MVqV Cܵ ZPo?ٴ'/㩞Q7 HNO)zC\,v:}̵[/%_w(MCpwD)/م'?GȗN1׫Y1F#) /f&L ʚ.E'^KP[-g-$@$@$@$Xg˗8G^٫i!jQ\oVm(/l{6[!gdgwm#2gæ*(Pq_gdш(V#x>jdi? wekF͜yBѱ箽[v;֞q4S,n+ftqC;Mq̝I 8dr X- ܎ėĆKLMM?h^yxxlؐHHHYg8kD,HHHnfSe( @8[9`Y"@q,ys!  (5̜-5HHH Pun;):} @qq@$@$@$@Bl`eٲ ΃HHHT P-UHHHy Pu^s(2 HHHH   (-gK<-(Ζ 7p$@$@$@MO$@$@$(:Bg $@$@$@$Y E 21[NHHHH`8SSScbb4._s?6$   g#@q<PgɉHHHH@8@    88\P-NIHHJRIHHnsgossy(2BHHHH@YF 8YDZr@l9pH$@$@$P(Ζ*~N$@$@$p8{;S'@qB$@$@$@(2BHHHHq(:--gˁ8E   R%@qTsp   ۜ\:   P'@qB$@$@$@#@qqliPg(IHHHƭ1o! 8ːpjZYœ 6gowr!$@$@$@r,N(ڟ)- ?g˟8c   ۃÏ\(HHHn+go+wr1$@$@$@r,N(ڟ)- ?g˟8c   ۃÏ\(HHHn+go+wr1$@$@$@r,N(ڟ)- @"= >ϣqŵmn}rҀÿqi:hz'P׸Oڍ vrڢؘ:=pgu8 ] P+N+og?^xALw5jT-?66N:srrrxb,[ O=uV1i$4iDB0/q̝;Fs?\s$@$@$PZ [?lEw<Zo h!@ ͈Dבˌ e(ȳژ'z؁HHHK}yZ9#P\qV,WdN:CEvꫯC>}YcǎE1m4oڴ }Eƍۏ7Nk֬Ajj*BCCiӦF=_~mzfnذ.]M6l7xy%  + _he=v[P[ [cs[OXk~oԶCw8bbb4.ۊ'z5cC   p6g\⊳"sv…XbO///E522< j׮-T???)o۶-^|ECΝgIaTP'OF~~>z֭[Ek5g{0`3gy. 83쮄x=Ǻkjdd{æ֪-.əf1$dw` jq'2 -b*jʒ8ۧA>YcQR"f/CG:Vn{8WI$@$@$P P-LVqV7-]C'j*evE4hz!iBYg̘!3nEX!z{zq!=+j {B}y\xQ_s⬃IHqrj ef`ñCԵ\+gUpwsAp>^tf8eo랶N坄tYcV rݐW,;8["3"  prg<}wy'ƌcQe ,X dee #G NԚ]t)>'| 48 3P(k0:)ΊcgB<~ڎ #ѱnCY]c!Q=,: V V%MK68+~5`JX{g̜uk'  (+(ΖOpB(S ]'NJt̙.sv=z\Z{Ǐcɒ%W_}*U:q, ԩR.J$@$P&hg<ӳxpsu)فd?aC+f e D0`7@Y+ 3rxiϝ-pOlPNHHH Pup[MII>-[?3֮](Ϊ 7|W^yjՒe VZ%WR%֯_&L5gEYvxgG!ۉtl\$@$@$p[ F9~O6^zA=}1bHWZ:YF@H$peX#v~ Hś~sQwFk?:8   rBl9qg,/_._vwߕݺuӋYF·~]v!332cǎF0Dfŋm6$''5jԀ( ^BfB01_~ 6rsq XZ%  BDq(~ݳC?ǻ;M0E[3 .$Γx+;UqCo t8e RMO0/'EXbdlY R΃HHH PufsV%2   rF@!sV*4FY-dj#PJHHHHq(:--gˁ8E  (('ؗHHHC}8J9%@q:&  vbhm}]@V-.VpV@űk"4 zظ7VcQ& [80}*yQ^yyy܏ IHHHPu6sF(2 HHH6'S(BlGEc8yׁ M[/In@d,Ni72MX|J@;Nw ^g{-IHHH!(:+gˋ8O   G`#6 (8pjg\< Mg $@$@$@$P:(ΖwZFP-#4HHHJRIHHY'v>Pe @qQ@$@$@$@Clpe2NHHHT P-UHHH Pubsg\YI~o⦏ qk G9[Rf%}PuZwJMMp6//! 8q׈.,>gmfO ߲=K,}AK;-m=K,}n͜D[R T@> Tii# P-HaR9s(c;@$@$@$@j(2>Yǻl 4zA--ۻWvjo/;¢lˎ)DEfR3<]_OЁ'?#m)R="ۓ,YF @ P->CZ((:ygXGgaTI=صMߢ)byHVڹ3.Q_v2#?pb RP -.l @Q::ـu.[5cC{ogCg54j(aX {5iW1F톕) g)j hDql     P n(:ޣgǸGJZՆ}!qKlH;Q{v!g#aK {6%F#ӂ? s25@qjÜ6a؛MՍkwLqmi^g)?hHHHGlw9'`/qvMՆfi*fT#.<Mv\*௾s6|JߧsPsk1?jcFي~E!:}M/U3,Qߏ*:;F@n37-m[IXu7v~Ϸ-⪡ج7qHl|&p j͖7p8bNZmCkszs˳ژ{'󪜓:Z?!Z-?#us,n s~ C[Vģx> Blʴ"&a/֩$,s P9CMjabh[n\q6 ;C}Žڒ0=x/vO6;ju_B7{I5McJњGeVg| =([Mܭ=.Flk(ΪM  {;7kPnoEor.FNL{g0V[_RNjџgΆZM<|Q~uz $;9Yf±No~jiIU-| ?] {&u닋 H@M1U;O8{99߬:ln]BYBAO7Kl#0fELY8ZZ`Bʫy!:>^C>Q$abJAyz[~>]' y.ܿecP~ |/ɱO5<uq֖1Mt>_?C( g$QnX2_1(4 ?w#+ӵ V|m^U/v j!ث*b% F3^/MNmڝ9+AA6z_vn[sRkzmrͻ>W%rZMYsVn$?[Quz" wp>3ZҼ~j~)ܮLq%   "@qHs2I4YqQ᫣sPק:>~:o{k0YVEt/<n,JgXp|-$,ΊrbVَ1uM@#Ly d$bz؝R@^ɬ-Ί2~)Z} 8'P-+9Bѳ @R̭6Հ_~>Ru`iY@7 rpd!pqej_Gfjmuf3M˩) aR>r Ɨcj!~ ? w7xE]aE}A Ӆ̭GVgky'!3]gÉKML[6 u73s0tTTL`ξ8xmU:Q\]S [Bg:I|'|u':⬭cJ⬚JBUۓ BNoBZ֫% D aZ] \qy#KM/{>.|M5qVvݾ@h7`M X:-LJe o]'YqLǯQ1}$:5}A &D}W1g : V f9+znXg{{B ^Ĭeod#qv`>t{iyf^cĺg00d?1gݫ6IqV_JrlCaVP9{6?;jE4f%ll!Ke Age L#JR:ܞd*ξ~2DoqٴSz ΞW1Z:CYVd+T]^5bѭz^U$쇅A몧eq7,Y~BQK⬭cR@77GgΖ8%N8voG< b "KU웦:!"3Q &C"ΆUu!#7 kALq8۷F{SvޯaY2M|fzmOe!W0+ػYkq2?[QgKݿf;7[5⬥d9 8Y2Nl6O1sKjz(NܷVsQ.`ߚm1iF5gE檨wR/K9%*pY(Dkfxs'j~e*^ 10Hr-)bfpvXuTirǼ8+^5²Nm/J=VY* ]CskDx>}qOGCMUX8-38Že6L-JTq(~ݳC}{Neeo0 l؈qv'u_KΓjlG8ƺC2&㳦/%4[#}xuGoxs=,k9[- z} +Ewo8=cfX4;7._~[5gT~Vm~gmpMi9^ǭLi~19(kP,)1 bc=yN9[B|>3;yœ *E\G>9QF9[܇E932CYژ57Vc]5bklRҵ+?[Q"xQW0ad,Sojvh[Ok?YIHHH8[v|GbI 5 0~o/s^"SK;FY0χC+~x{u;]Գ,/s3"d(|<\ sEYo hb^BS:DxW/z 8}aWqTDzo- G̋Ȋm\| %Ί65:.bS K ^Qn@Pŋ:qt]hd[7V@ґ Rʜ|hg5 j[%!Ίy7rx=SG|Z#c@~\˩e"0$4w<$?xl?-9?wï'#mtMq)5CX9{_55ܓQ@< S]/MSUR^5菡do'6`l eT15.nJiJ'Ί965_I9-\L.rmϴƈ]*0R7|k8+왻VT 4Ug5vCg~|)^@-VSr5a   (]gK?G/egm]C[ j T֠ MME=vܪ+i$t/=r&Y]J8G1 l ށ~N^zfC?USI禇ˌy@.7R玉75bppҦtA(Vx1 /HJ^LÖbgw 胢X@C 8Y¥O}DqxJjՆR AkY>AZ*^Xo'?2j]B>^b!9W뒬n1_o ކ=7:%1{sB*FERu\2 h!@qV %m %qvLqx Jv6r5E v&Bڔ~ _*I;ztump{(2T{u,: Z!Cw SzTl\vzw la`iE5R,KOoET8KqVC(HgK$8 XA#@q>8[|B /rZZw į*Auڲ6'C2%9k+姅hvkES'Ugv( Ye 8Kq"A$@$@$@:g NMOq~E ZsUMG e^vts8[5hQjHKR,~\}@q1$@$@$@$`ogMwY3E P-[QBP,(Ζ~r$@$@$@$`L,#© X+:5,.HHH%pbtW111._s?6$   g#@q<8ˀ    ,HHHJQkفk_(#34Aڃ}l8c;1L`e5-5,?Yk"mIHHH>(ڇ#Sg˩4mg6q&qqg9) /VSjl,GPZ89Jqx$@$@$@$P\gK5}Ş݀ 8ĸHaHtuG=`\=qfv&ѷw^٩g84C$@$@$@68k#8v=P=h*VN%ϙ%ƝrxH,I؄=lѮjc +Oo K3 ;4ts&HHHH(g˿g/+Gu&qqg9!yKOo$¬\D@c 3r^~-8kء%   Y[mC8lZx0ք[W͸Ŏ+,50=xh;h[%å ;Wo> '◓>~ 5bjfWƪ*`tnX={UELrůAJ#b.t="1;.s#&%^2a#_A|nf"j~=qg=eڱoE(Ų@SCKegk f m̎7(S %ߊ]!-bZ.+V±Գx︜uM /bL87)-Fo9Y)#5j8a9"N_Ž%^M<_{åM2wmVU(ƃ.;ܐo>_$i% [p%VtwõJ79Kj1gΗtxBٷ4`~d(TkWS~rd꾤RKZ3%7쏖J{Z$q=cVXW=K޳>@DGۀF˜U-K~ Ѳ*iWKq1͜t`95/ދ]^51+{iTr] qg[kXVƢy`Œ 6<<\6//! 8q׈02nS/v%8D%!9;MWgV _n\d'7ʬ!t|-Vف1 =.yVbξqI۠S]:<ctGFRxO:>̫b9M(ӵٹ~Yq>MqSʿ>fߋw|||,^GR@Wm)>z?w CͰy6)k[5_6ERg}ݼmi%g&JznE,Gٿ<'6^fSp7ZU{ƞop&#_!GGBݛqgK=VmNrt4mfƟ4Y'Zǂk'阑8kQ'1m|\μ&ЩU)H^m5`YqL$@$@$@KlL8⬘zg hu\:OPajQ.^ju|zo1dߐMØǫ+aE1~t]aoe[U{YnIb_Z4Y etlǚ-"*I"Ii>Bp5w>3 ?#Y 3˵"Q_^\ROmjU C]إEB-2QuWp1~xbDrBↇ?O8~,N1C 6UxPP_^'˜V'Gp2=yҵzK)*eҌZ֬/ c_MQ:ǭWЯ:ܾR-tb@i_39[Kz*KDVoW[m-eΊ,.8;d |u@ϓ_j<};lYøůmjvj^UumfƟYI&u8@>y2u5g-]Wĵ[|+oR!Yi=E. %Ug .DfȨQyDFҰڑhW [/xXԽ|}[z+zP/qqQWQB,2y7_#^2/370a5uGE:>>\gE-/8[Wi.Qa%ކDf:jë$^v%D—~B0"F֨-EzqvvB_篻<&kW ꆹm'BĜ8Hbkэm.SRt)JaiNۇQ8+ ”!8U_gSd/T8ҿLi_` fJ{y]I"[f#pj̰\̲cDJ~bF^- ;nzqkiYkP' {≀CN!1+E/Ϊ"J;p:ŋMDqV-J 8YDZr@Vq "KDUm!bַ碶ƃ5uR!nF&üe֨Ȁpq6FD`ej"l'>z3FֆsZ|j~}%cĒ8ۿf;b8DFޯaYpwqӋBe|+2ۈ *`y\ vM Z(Ίw }jJS݃[3usSG5/#J$W51N|&E9܂'7ˊ=*Ϊ4}!XBLjlKx9ik2T351o[|bzI,)q6J=M~eN{~b8_-ׅ+)lYc3;\s񸿭 ?+gjCCqV"ydIa6_aڹf\,Q-r$@$@$@ n IDAT%[(lg壕0/v1ެ38T}xe-YQwgE6R/܊K9c޷VsQlߚm#BX*9SN{ qAM"ܼ"KGdjJsrP\]ث8-∮x]ʲ ^`lV6F͇xXdN4pX~CapKJPmBmW.oT SZRY"kM /{bLJY)Z2gEmd~Q$>SqXx$ΊFǼ1?ɲj烒8zcZC)^ 4ށxj'ZGw[YS[G7Y Ԛh3/qVx8jff+kjOՊ2Sq\x>jMmR[-> 5qv`>Li OzbS^1CAP|QPP OlN%=u 9OZۛt~ Ƕ hhGLWN^lfZ#Zc՚ZBUܮ/BSYBMZJd;   (gK3G)lgrD6(Pۧ)^\>!j‰oWsu_|7'_%8 J<-2oG醴g,qs"6س>>iTY14mۉ [|4FViN"{\r& q3PAn2f\s=YjyC kݡ5qV^;#jN9ti?F]w1ZY8usJ4<D58 Kj8RWDMteZ(ݱq4֘7]->1YKBY)։WOt]1d˰t_mU%(^'Mt|&MYQ.8=VI-S[CWͦi,9v3   pcK@qY{/ϒdhϼHF.;^͉qfb[ zSx-\˹.()Ü8[RcqJ:J(fģ{C1 /R + r`G{;JK,#Kq =D$@$@$(:H%g;6 xYt8(vI;ˤK:,-D姷a8֌XTR3CqYk>%   8kX%qamJY%C!Dvt5œ!:6Ű]4a $Ռ}@cYf魈Js*qV3b6tkb @1 P-&@v/(Ζowv^\^ br$9K<vHhgxVD=`\=̼l:C/ -"Q‚HHHHa(: - g˃7Ggw[v1PHf>v)Q6_NPjl,q*vm8[܈a   (rbNnˡݝI\bY%g4, /ˌil(YkmIHHH(ڟ)-#֊hi* h&p0n橩򃘘eۼ   $@q4sR'tTU׆ߐIPB:ҋ4D b/ bRTҤz H¿o3w&LkL2s'{u{8   '@9HHHW/$@$@$@ElQ0G$@$@$NϱNr!HHH<嬇#  j^>N>tY wxRzW9[   "@9]l]Leaw$@$@$@$iY$@$@$@>Mr֧Sr Yn   p Y`砞BrS"y [sp   %@9뻱Pr 3gHHHH](gEzY'A$@$@$n̜uw8> s Pr' :WM;-ݠаP<(9G+  YؒHHH\Hrօ0ٕpFbܹXd N8P4n}ExxxCطo^~eŊCrбcG|ϣO>hѢ{IHHgI&0 kŔ611k:|w ?>P   O%@9멑 3r>1`%4SSSG.BBB eALrB~p̞=?}YiFw>!gx DEE)>>#GѩS'h^лwo/X`233QfMunϢW"$   o#@9m|]JQ9?oUzff]+b ~hlokѣq!|V釦vdN:z.\8*gy8ג%K5V;???%hE6¤@pp6g2sԩSJ$K]W)C {Qs2g۷ooK9+Bo߾HHHP7;{n?"`+%].w}) ?;wy4oO<+WT _yZIHH3'%=wk?O5gSC g?&޵@9,HHHH /Y&Zŋ###CIYɂ}Gxø$CVīԠ*"SX5n8,*+D+G2RM%uqe᫗9+9RΊ4,ZJ1;V) e֭[jĠO>J!jEJZ@2"g_9_o>ѹx  "#ggmZvCs7 g7 !J.nk[_?3g=k_p6$@$@$@>Ir'E8#g\AJJ ƌ+JV q盀lɤ5|wHHHԜ95r(g bC   ((EzǏ|ݻdCO9zHH(gC gxp6L rQlp (n_[Z@yK8}t*y"-ry533S}hx?/GNN䁝~.HHC`s2䀠mPhX(n˜ ߁_٘n@@(qjlI$@$@$@Br@So!@9-Mr֧œ Pr/ [Pκ; ΃HHH(g݊ .Yߍ=WrۀHHHPr [Pκ; ΃HHH(g݊ .Yߍ=WDl/[j}UHX:v-s-Wi <(g?\ WʰqҮ"h,E{~?h#o!UEr`XS\f(Fқ   ق^嬗 ӤDstL9[0)gp ԉl7>|RmH?rmY{: (=嬧G}Ds<2UEr`XSjIcP1Wض_A+4 X?*9HLQr8c$    @9[P٥XL) o}Uxq-֔6pD̚ :?~N☘5o_FJlC$@$@$@Frвco Pr_1zf r~$fXeGPd4^oMA0Sxnݧg6B3DG,$e=Sۑǰwz8R>sWhh;#?n4Bcq͝i~bsٲ3O`ёX&Ow㚡Sl#L5ߥ{ߙu9{ԕk[݌.qM0*gvvhkOo|ݙ}-:6 ,&aёM#}G1SQ8}^4iOyU9k0٢pT.gLrvLHm/s,О+_oxܹ~&y& %PrDI?iO`tÇsj_#e_‡`齪vDPL;[3Auz(Hջ#&8Ϥ-3y">k.c`|<鍡dMk l]in]wE⥰73QQƗ.>}vTh),;o7KV}~#"_s/Z]z4\yrfuHdekMz崋iG!,(kOgfOdW,ewMw5g*]V[ۓe@p2,fZXy9ܤOlc?\nQڬ*(6S-N]>mgR `7e\ګ2^7=beطwCv̾ /o cDZ 5^dR`ܷl,*35O,i1F"&uF yfe/{oj'֖o|ß7 .YUr[ Jήڿ܂YYQ4kВj荩1&\ruc+-~&ׯw6)'O˜ +!uNUЫQ ,{rV;7p!gץŦC)Vx ;NboCRz5|`C   m SCx-<#TZTj5Uv\X@0&!'J\RSd͞uJLj"&3@Έ ǘY8h COԺӦ*W h"F&~䳇 -!"^IVCpohX:dWrJa 7͈mUwUj_#*0Rl8^sF$+5^8y1lW8t$7e -e&u1aJ!xzx`RAxd۸z-Gb 8z)RRJeM۷P]/=*ނqM1`{yǬH<,6mU)gƕsZ"Kv3JxxS̐C*a_Zqln-'1c+DLi,nU|IL߷Oɓ9k&I`Dn0Joԧe/?ȸru\rV{oNRz}`W`o?]Pd)L_Aۤ%2.[ 6"Ti|v9EF#>2a9e{XKѹV=Ԏ3/0̳8s"ف[wrZ.|"JV2YC6"   O!@9)c|6Pڹu܄W߇OvŦS{p9Vd+7B˨:JkX2Y[{K :2SMC2nW߁Ƿ U)˲Yd- ê}@ܻxʀ*yƠұ .cz 5W IDAT\WoBIJmt}Ihcg0k<P27'味zTȚ ɼc^_^^OWe˚EROY?6CU6xvn6zTev,jf횲璁O̽B+g%rq*gamRT*_[z:_~=/+d{.Yldx}`W*Q•,dFT n%osgЯiѻas.Y`]P]-]I3k#(pQG x YO*g6aA(~LƳk#0r; pZCSӔ?ifWsv{zGnmCᬱXsbGzfxqzCE U 1 QBe)g]S{XK Q7z"gd]m-о~p0sp' Pκ$N*g%sTÇ|ܞwER味B^tJcL%W0f9kk mySdwTl_h}rL~zwCT𲣗Nەrϼd6rr6,0"̀CDzrިd$+[kɪ}f (4n,\̹l/mҁv nQ+ĚoTe+sVS ,;xZBnN}]+M"~ɑD^idE\h!9+r?\ȑ}%k:פn a-嬵k}ž5z&g[DY{6O/bC Vcl>tokC(%G~=6Z9[X}k{r6TiLZg2P52$4'Drxykl>t?&n˨~M[DP~L\UTzsuϜp9K=llω#\N8ߤXZo]o; ɜy0 g k(g bC   m RκmQ%+\2 vb&͒v)P7&1w]ܿme=_{s㾲Gu;[su3(=GM"=0sesÜGΊ{/b1,Yk233O$$$ <(+p1lL9kk6=@QWV~[~<'7Zց́eY#؆HHH le@r9R{Q"L9[0)gmpTWز8dPЊ_M=rs'&Bm`3 +}F( Cˎ7D=sDs>*UEr`XS*bN</gl`e#((g$@$@$@$P(g /;t!͏}W]قaM9kԠWUmdJFқ:  ق^嬗 ӤDstL9[0)g [{u+~N$@$@$@>MQ9Ӱx   K`,$j-V~hx mNN dž$@$@$@$k(g}-\o$@$@$@$rۀHHHBr-9Hp$@$@$@n%@9VHHHw PnrYŅw0VGA-|ٻlY}g]ٗbKkud`c[   pYdGHrfpΕc:@?Ps{#[uϠu_(ǞrYϹ9   $@9q!@9[DI&ҏ_d^ `-qҒr}u{YY=s]r&$@$@$@ErַZ-[ⶶbքoC9/hM9 Pκ=,,\ Y&@9[/c{-\ߝKk׌w@9ku_ (gǞrrrs?΄HHH(g|@A\3rrhި?ol[aC6L–q6.7@ÈxgH\*Lt*Y?a::6F / <>n4BcqM(gi2Y-3LCk+2΋5g :JHHHl`,wO(,9;{Q&$ԥbؘzm7EÕll:{1;P"0Ёou){: gE❼ojm\"[\3tmA&aёM#}UF?t^KFFH r32DP^;w_+v=F9:H2DM䳇NmGwLyWƋuE.r1i6KVrgِ3̥Xgot5M.^UeZfΊPjG Ş4{:ªqM~$-aq|s5ǷUXVz-x)|j0FngnۜWtE [}5JUPRfmr[|nmgR=G~YT?rHVpjVeٮb(1J^K6[Ջj\)genqM.ʂ ϩqՎha^56P|W-^ {3юv9lFߪUm?ϓ=l1Œq-V.=OwC.-aʜՓz}|<;|Gն/^c#ja=p(G{w0"ՀdY\Fsy*3FXoqV{ 5JWнFOkqܑ}YGh- 뙲G/"N9{eG<۾ ʕ,$gp`6i xͭ*U߬]jѨcW&`ٞd<ֺ#rrs1yRtUA굩gޮc1kZM‘3xoOhU^]_[qYߴcJGFuhkeCK*&2(9k [΀\bGpLi=w5 Ube 1 Y? /TF>-rO|wXz$=ҁ%1:U>Dƕy w[-Cl SY 6{ -Cѣ-VgSΊUX4 ֥m'ZI3xia¡'1ߚ_7NJ0"kS(fX vyٓz}L3Qdr־0z]sjalD>#\-gm `亐8906*g7F>Z {H,c^"Ɩjxo>+oݷyᓟf+?k5eΊ'׬]oQWٟm[̝V?-T?JLL4}BBjp! Y_8כ@aYk5gs]ܤ |(d!;7We>ݮ+JކΠ?YIꗧ7O!benG3)`MP5d8Vbްk߸atBjckM +i6)]48~>ӼN+9k<,rVD͞]^CRf9+RQֶ1 P:0xz_?m_[b/[ [Þ@@iϓW ¸?Y-# %J-QT8U}\rο^^ŋzL欭}Q20Xw]wfa,R/璑yh,pԖ5/LYg!Nc0hy8D;Q?SFU륰c!Y[~PYrȽDdK-`kV;Ox'keK~zmbc   p9Y#eDrV2[*9{uN]8{OAe0g:D C؊vkJ֭~ߑZvTulr֚qY|n9.]gvE#ĆFdžŘNy؎<ljxfxrNշv3՜7^՜53 ل}Eh @s;Ä/ 4>&AIlGWِz^2IkV1|T:{He8.S Oy<t?&n˨~M[O]LʴӘzZQ{rz%lZ1qI+0.ӹzm[G+bLDrvs}ĕ) y V[֟?#80ut6cdsz+y;F~:h̿p+_B=)gMw=){~WbClQ V5LԞ IDATg]?{1+erVt d"L5̸r3-BՃ,kJ%Gѳrzolv%^ڛgyuM^0CUoL%){-`$l2ݕZOJFfJ[VyUT@Nt5x(POmp1.$^U1}'l:j_CF AG9+7eu__"gFP2 X=O^VrFX)uM3G[*o'㣽_}f'?kY}bk/O5H-#ؖHHH\Gru,ٓ(h9HƔҎ:1@o;I9 Z+j=sg嬜5z\# jM޺c5}قqHHH5Ɖ("JzՁ-CZk\GC9GW37u_\!\=(݌0X3m\֢O(gM<HHH\Gru,ٓ :@`Pf:.fwzf Y}/Z#R,|iRYGh- 뙲G/"@9ErvRHXA9lvЛ@mGV|IXZޔb[   p=Y3e^Dr֋S0?Y}-GXZab[   p=Y3e^Dr֋SQzP(<' _Z#;rZlK$@$@$@'@9zы8,ghm* &0q~9GKHHPmsrrn<6$   _#@9kz    $@$@$@$nA=rq`mUGhF[g~T]+aYw$@$@$@$p,wO)|&Ԇ=a7y)g=>D @'@9[&@9 (|!ʎ{1^ܚr֓s8q$@$@$@Elэ-WfHl(>._ˑCY/2SPr!$@$@$@^JrKik8&@q'A`Ƥ-+/Ek%  DΩxY׸ b珴'0}_X}bMvUcX~xtŻ~]T^afOu:+GǴ͟FH@q X9̕;0o"Z ޚUe&Iq+qg3LA-ěaD޳d$.dg {-䬳O^goٌik=:6tiFe)g]M c(gEm_XjHT\^`CdC;"c܋\bҮy6UZ44'b(-Oe3g^'Lk8M䳇 jfo&g}\u-:6 Nǰ&{=^7z-m\YWPd$@$@$@$<Y"@嬿_1i,^%d7G!WDC]Qx)LG;~TٵF3g4'vQd9ϩ4Wj`U"mOY rৃ+У-*CW&} lFߪUq~{5nɬja1~\VFi/oxh۰"B'3 ldzΨdΫoǽ7Cœxk˷xNOćYqxӋvo>9|错I]ʹl}R_q|.Ň`?Fq%+7E.=p(G>ik]$'Lri [{OP^(W[ h">9'Ir5"3-0<}P/E//Z }ƪ*{vi#ll;k~D5*z)bmxW-Cѣ-Ve04:#&8c~i|{~M_>mQ9kXVζ*ˆįWLzu`)6mU~3zrg,-|0'[׈ A냃KKQ%<{(ײm;[QzB8   _&@9ڽVΚ$l5P/&ۊOk\9;l` q4z.5g6A˨:Jj0*go\e1[}?Ua_i&lШ5^{M#UVdP4}-Qu:.m#xw,zM͟Q1Z.cɲ34n9NܫVCc;bI ?ٺF5}*U$Ku_xzCrVo;uҾGhZwε\wlkGϫٔG6Nr[}dY%Ƕ乸Wj%'YOro׻Fnzo UpF{A=2sVo#2[S3]rj<HHH\Gru,ٓF9[2 ܑ]9+mc3 MY"=YjzKѿFwUs -$F%~^RY>%[8 AUD)[C9kkR{0&i\<1 )gP䊩d(ZYfTΎk~ TFȚ*ܴ7cY?c}=O8xӋwtpx9kc]}<53SK{OwٺάD> k97TlK9_Zmg8eןA9zHHH!@9--rQΪ6yƦj$Iē?BVe|j*%!YL% ^?PYy?bT?=|֜a")}EqU5q9U56UJǸfUXy 0zuF/ "K6Ku{cwff*gMnz(ԐzElHLm3FdIr%JãZbC#aD2s6m^ :ɼ]!MY)9yo=}9{kl#%t< kܐmtS{X7VO˦2Y[ק59oFWS^lP{+{k=xٺάMLg4|>:qၶ^룕{D^b7tt@9HHHAr6xF9+%;U>j]d)F/lOW-T;9KӨ+n3RVSGr։[>v<{K`:$g68w"2C=(OC,Y1%""ҭ0m) >[䬭ӚՋ~N){ld\Õm3{Ozם k:פ y-嬭^kYGHi!5_:09ʮ=rֵ< 8JrQbl_x-RApbaBғE\A8;²( _לud_f[_/SX$@$@$@$p#Y &@9_ʋ3s}-F=udW sg @A-H Pz|8A("X| ~٢Kw"qIHHH:Y&@9SL /{0*oH9! Rz|8A   "Nr˳Mr;PB[#c<5'G;F9q,IHH.٢[Y Py}] #u[nC_d-2BHHH嬗v GkFe/$@$@$@$a&muR牉' <|..    fr Pκ<NHHH9px   %@9볡…, ˜uSNNÝ9 O0szW\Yj*dddL2h޼9%Jx4\̝;K,'ƍo߾vqJOO?y=x:99   ɜu)gsHHH|/Ek3r>š5kOI&صk>|x=g}˗chѢRSS!ǻヒ?'G$@$@$P0(g +{%   {(gEr6-- /v7o6l؀Cdɒطo&MgXXz;)))2d뇤$޽uUu`Μ9*ˤgϞ:uRWFSN0e {ƍ1sL9rUVUs,[lؙ޹sg>^wVZɜ駟|333QbE<#Uӕ;׮ZGސ\ 嬛sX   '@9[8*g.]O?/"nDV>ӨY&{9^ZZYjՔ8+(;yd%z6lz ͚5SYsr[N]iڶm[%M[nok׮a̘1y'"/ĠAT֬<+!'rAj& ǎÛo%Ou,[eՓ @-HHHGiY:c >\eZ;$ktĉ*VHׇzHZ"Rov<*޽"q4ԁݱcFaWjJXɰ54!""<~չS4"g%wذahڴ):t䱩$i|5R\"!8  pY7$@$@$@>Or緀opT?~~mٲUx?z`믿5j6R@$djeZRJ;|ʼ9+YgϾa.ES֯)Y4R~R@q}ݪĂ; ³>uIHH`P WJ$@$@$@P#׋4G|t_Ddp5">|_jN0AՖRɜ]*zrJ*RF@2U%˶[nHNNkgxx:oԨQdzѣGEMڵk{署R3Vo˚r~vv+ur7oތ/ׯ/u ő Pκ <%  y>|rVh]x=w^Vu^/\$mUdJUɚTg=3h޼9Vԇ5՜C).\< Ld~R SL={p `K,Q5n۵kyH;???^d8Z9J]P;̟?_ܹsuH\+WTsu:|{r$@$@$zgIHHHY#ئpF@CN:ҥKڲ}Aɒ%+"ISSSUfԘ1+gEŊSuh́ 9oL$@$@$@NuO, }Z2R՛YoN$@$+(g}%\' p>Jl. ?(gHHHH=(gÝzY A$@$@$VnIHH|K(g HHHH.    uw!(g=$ [ Pκ?'  a>|.$@$@$@$ (gHHHH=(gÝzfzH 2OIDAT8    u+~N$@$@$(g}8\㙳 0[K !9:З/ձ]\kK=]Tff}p:-rrr<HHH:٢a&G3g)ḡ(9|M|iZ]?lC)}r`    (HI}{<YGO#5 bbe?v_'؂HHH lAeOrCx|M嬫j?oُݗ(g    $@9[tٷy)9_ 'F9*[#k%Y{-HHHH P$]\!g{Vn*4Ctp.^BR>L_:1Sxnݧvcݎ|iǀtW +a z8R>h;k}\kY[ԕk[݌.qM0*#nc3'Z & I<ˎ&98צ-B~圵adwxަUmzW料~&%{FBAS,Uk܆jaG/>éיAs}܍W]FFrZ~=۠[_'v`?p ,: {\3tm'X^uf   pYױdO^H r% >1;Ϧ"4yxqȽT~0;uT94/ֹŤ] k_OFsxmd]9O' Pnyj.=l=ƒCR+zg-34WjzU"3GQ>8BIhc@p2,fZXy9ܤOlcYOWG[nȜQ+o=pl;''k,*6g/uS;u12f[;oYq4>'`K9+hW#JbOf=g1UǷޛ!I[<_' ,gMYS<.e_)K*:1,wYb%CK6%D]Wy_pCTw}R}#r֞һ-f/9wmj7u7μwZ{i,bX<́~z-G)/XJHv]?A_^Lz +F ulkFF䬼On] ^8f^dNh<,GcNZ_߶VcYjEoXԏf(g3   pYױdO^H ?rVAi1+Q_|#FC_"O!PUr[4,[]}4uT]UF$~bY"qLj"&3@Έ ǘ,^|6~]ktB B $!P"Պb(]Z*(VBTPk)/E@B1"$<IHmÜ37=n}>w;m~&3?ܓEg>F QMlڹ={O/GY}Rup=:KA44IiA/zƬI?=@c.b&܏?߮)Е|&ᴫh#Ĉi 4.}WD%t$ǻРOk#iv46k}t?G=2Y9g{iR;Id,MZ7*+5@iQPĹ#g1/~eꀇ=\vD&$զ:Y7OG oos9޿o[;!˷jL=_e%ߢ_ BK7;|땷ԘَTcaȠy{]{[~ 9{YRG~үϻbheF59A\Wܹ ?4U4!gb  *U)@Uف- &ZuǕ\~M7E& KMa%*mde/it+/\J*|T+MH͟QI&u>N[vVA|H23zfdzğOJNS׿fv叛Vͪ&`#9LQt'ZAZ`Cr oҶ{0v]Gr7#T+TKjW嬛Oƥzpq駟IκהJMTcrSpȑX[hRѾS>oXƥ%xeb;I}|0*N1ᇜWMY̺ gɛ^"o'D߭2"g/1kLoP;VQNSsōiڹ]U]\91{A@A@N-BΞZ|54=:tiRW{T=`"]d%DǹA.t2B=2:jXU d—^W欝DV&}Ԁ#A%C'*5Շlzƨ*nX/+gol%FN8A SrڔKs4y|$vzL[\@:nVy<ab/ueMb .6oBʎn; f |6. v|i'8Ґ/Qe )oؾ`[4&T-?yՄm {Zn[bƃ`2εn.5sa' VS`^=VYR7r?◳]4gCm>2өRz9ׯҮX|z; nCMTff]ó"XuLC5QsOrd_fm֐?f9/Izb]]Tbqj'g9;{=Y9{yr7&xv:~9EES驪fRQY1KJ 8X6pFB9J Z-v ްwrLZ^/wr?7rV eJ\ᗜE{{2ɽ_5 5|'D)d]m:GgG=q}YXm5-rs ]&eg7 5y  TBVr@UYt KPIEeGvnGL wW(acrh7oƑ&͇MAq!\^bMj$KQ93M մoPqy 7|d͋$2F{՜ÆXo~JC *gA.ڽz@Dfа)YGK֗L;9j~TXVLS׿Λpr✘x#r,-Ey_C;6Kgy jNC;= ZD=^CZjlRcQr:wPY?q_LA,<;ub'tYJ\n~da"ke{A*k,8ީ"gaoR3ԾBpi1-۷^!Ͻ8t69cUB=kfkS_uVGMlkS6sw]˺IwB=q0ާu   xCF@ٚ9&#^=zȍ8>}sp'W.]PHYڛ#KcOv%aK iMV9S!gϔ;A@A" lmYB$4Qu]+%߫K}Q| /| **X@PzPB =k8d23$Ye̜ +ʛ Bjl/+&]ۅ4 EjG[/c掳O$@$@$@$@$@$@$@$@$@$`ف~X3G ;fΕHHHHHHHHHHZ⬯3<_U->~Id==̦1O6ڔHHHH `$H3MIHHN!xoHG;;Rn!R .HrݙVSmk= 1ݟij. XA~I8~G{w)Z"`$@$@$@$`{')ΚlJ$@$@ `8+) jAþ;8H@r^AY;g$@$@$@$PMIIHHa ,n^T2n<>! q ;;Nuwg,/q   hXORm뇣 l”A_W׻{{@|z2s Il;gmq$@$@$@MgE) 4ف~t[{&& hv !ebCOk5V{w)ZJ`?$@$@$@$`{')ΚlE$@$@"`8>`xg[|{" 9KO=Fvq^;x#츚;W Iޝiu.1+ U ػ?Iq֪;'  : $J=put:ȑ4Vg<RL:ŧߏi4+ػ3Mq+*,uY   0gK|" U,ΪJD1SsOtjቄǩ~?:b  h {c\ ?".F!%8KV&''#k!6%2٫8>}d}]MQ/Y_W! ui&'(oCr ÒQ]U3GKnZ1s,"v җ;w8ޭ590;!Oo<Woy3vKtywCu[?,)Ξ?|cɒ%HMMENs?>8LxxhK:3{+_L(Kj℥wtޤJw)/8Մcϙ:>o(9. Xmm[QQpu!aVJZARSvSg{y[h.o>nJ?Dێ oL}sYHT-OO>A6m~|H[gƬqS# }Ic% 0@]~3f%ޏcZ᪭"JwrξffDnSKUu=0Le{ XʙKtiiix(Ν;cҥM>wڵk1c E}1fèYʩV~[s%.Etg7 f88lIf|xt1lYK9P䧻6ga~s-e7!  ktUc٫0+*Άyau5 /G7<ƴēZߎ*_‡AÏ0um,O^t 3g#<#F 33SϿ4vM͏>%JXHH\4YE=+YW%Ϊ+BWX:%vC0;]::s٪;Tg"vfwVuQuլ*WD[]a˘J#L"ue'`)gZfKݰaكW^yEp~~>{1|8w"N2ݺuCfLb)I*Er>[eaaߝL³O̔%&M@CXd"

    Pܹ *f  hn2׼2 _~"fUd8荭Ϸg酭g9 Jk 2?)⬼ |-[/kk~M͏%*9 5g%u^h^esNq.JQkRYyP&cl4i-(-)ΪȃH c RB<\qjgfEQ/2#S(Hhڕ tQ>3-g%fDϮ_^iߧO%[eNdCjO; oi[Pzzөfņ-{ xwZ${ 7/?bC1 5Q堵*N ^׾;/ޅ"%zvJ֐OËJd*K"ξ[S۷o_3Gҗ4`]  K秙%JVf܎]+ϊ8C R뜃6q6EuZV%ꊜU9Lrꨋ%th#:+BHan?OI "m ['!lj~$}IC ! $4>! qZ7#蝏6q6:[bLi]fZuTѵYcPWR&x+oܲ*%Cov:̒Ͼ&`)gZF%feeU T"ew܉_~Y&N,X:t]wUj5,TK".#ec?~JԩS4:AU"fmC/ ][IHR7"^KK|Ⱥ>3f^ge|[#>\%K$@$`4p_w%O8{Ơ;VO:mSµsU{Xռv\BE 2u!V%j;̜f[ L?ZX˩Ŗ빙#o䝾]`{"   3k4iv'>idS#ʡ/ٰN$@M>?NqV=U En J.䠕Q]^ل)S톯v :e) 4S|*\67O{wU@Sms "  h2ݟd.UNHHF )Ϊrj79i٫8+ydEdU/⬤2ٺJBn!jJݙ8k ݒ ݟ8kB X@.gCNB=>l=Je΁`US]?3bchPd0{w)ԬH$@$@$@V!`$Y\HH &P8+rvqؒxtU&{JOB۶^X=r2ॱJ]k~iSY_Wg~9+)$O"I~'`4f8" w,g  hXurΊx9kԴrrfSC5֊ifȹgC<\q/x,^uƔĎmǠ[ۙ;BVt5X;g-s   0gM]y#  Sa$JuL x8BvɚWRf ұzZ#1g_R ij:AlYXZu,jݙ8kK Aݟ8k2 X]V=;nݙ8/a   h`ORm Ó 4yg%дػ3Mqi_= @wl_CHHip̬h8LyMy; I '':*ؐHHH 8SM :HHHH@?BHHHHz(Z-{g`h" @8۠98 @#'@q/0Y^!$@$@$@$Y^!$@$@$@$`=gǖ=vH4HHHA PmPHHH8O,   O,   c˞Y;X$H$@$@$Р􉳿 ƌӾ2j$@$@$@6N⬍/ͳ.>,X/{'  YfUE@Kqן3   .mY_ G$@$@$¬>l/   qgm|hu P._N$@$@$`4Ym¬.?g@$@$@$`]&8p/^d7ߏúVwnHHH-h#  &EEE矑^z"((׮e"..=ȣ1hzHIBAq)+uA=Q0Wfplه`ErL]C&bDN )6qx   '@q旈 1]va߾}xU5}]l)7wQ7<$ŧ 'z¿mtkjumH P:هa(uG0Mh;=,#1~4-Y^^G$@$@$`("   FK$qc=~s9,Z~e ESUrQ -GqN*ӯ|2>h[kHGI9 -"> )C~@r#?r"'w"J邇^!-+gmbi 8kËCHHH잀I]w݅>vkƫ>8(H+Y%pqLADoe?+C`DKx,IfZW6*fs_s8Ϝ7,YX;ZA$@$@$`T⬜/ahVeXHHHI0I]v-D}ZcZ^^_{MZ^Ԅ+(i˸xHfh΅NMEF^1Q!g*NKQieZ֬[嘭E=n9GHH@1cƌ'Zaty)A*m!aڇ8k%SO=tD޽ Ԕ6uJ$@$X˱w(ƈ"ڊbȐ!xW?w|i;//3ggg}QQQxG5YOVCˎIHHp/}5sL}ʋYfANy^$qV~:oqr%Ϭz쉤d%zv>z\ZϠ`r3JQbxGͅ[P98')h xm[:2ґ]ꍰp+R8 r.H~pnܚ9[ן%7%WW%5 2Sc+V1U? !D`;}<'l#LGƩS ݻwW"dE?wv-[V9Nm8p@ HJJBDD9Z?;w?DKpo>\tI O?JB\e.](ꑳ+kՠKV7/Vr?WwީƔgU. IDAT;v^RSƨQnڴiѣ""DׯNBExU3rV8;`o8q><8p" X"~Ik ;-t٩iKrr2'PUDp|> /_VWQ%B.9Vm۶˗/ҥKX%}׷^X +*~#GTuewޭ;6غ8+!~mua s% h[p"⋊7vXegGַfqqV>"~J\LL ^yզ@!KU x%ac)DH$l_<~rKÇpBzp2z?y#="g"M<K[Brr-x衇vR$jW^%:t+2b1"R}]kNY/Jym6\"k$IDW՘Y ѳ*DfeeTI佴N($@@]QY=@=eD>}ZɰaÔhPnsY^'cy 7@[ E 馛"jմSDRJD U(Y~[o… U*WK% y!ۭ[7ūDʽ^[_+geN"KtDغX*59 ?YC&·LAX"ԋG}EDICYyZ͢08+[;erCYy(?vEv5$@6H@c/B]!ODY)ʋ6)"Oʋ*/ře8;a„c!/~))~mDFF*) (0e-*QEկ^.ѯ"H=Yث:go^yy*m fAI[I|C'tV_zXW*QO$)"HtDƔ"볉-XY7,@>f! hZU6N~O5և4sŔ)SW!>YMmZ_^ +JDHU~>]* Btգd{1#"yhyPU듇#Oʩ"jA@JJJjD"JHi D믿$7YTDȁ,^9iժUD Kı<ȖQ<ï$u"f!& KK~UV)і*>gɥ.}H4ChQDԕ@]c)8q*"UZY%;9#g#?徦NMqVA*oQ'N B٪&[$TU!.*b|+ϛ7Ogb-FUѷ^"gG_EvH$*bY{1!Y]v;=zTgZ>tEΚ%C_Ҵ}NK$@$`_CKP* V;O8k] Ɗ{쩊6wSH:y#EoDpy%jBj$2I%J w"Eb/DҏU?Ձ& gEuɵ")4JuT$ߝDJNFFa@e˨RFΚqa) @'ϱD%"\CD$^Kek|֭m^M(qVFGG+ܻTEQ塼䓴9"(p.Ί%/8Es"ʽgE߾}"]Neq+;HP(={VyQ1T/=/k2 +9}E;g%.y#~2eWp/+[dM$}%;l1)lrxD8k>Y'% p8z->A_Ոqz(w30De"; /'P*N~@q#%! }݇o_e'/4_*4f0VøThFK)#H@)%%:HdȃR#V9lE[8kJpWdel8C$I= JZuqVeh,#YU$s\r (1r̋IHFhFڈYҌx%Y"YٴĖQ^ ]geQ,kfggez;Nrȉ)[*aw*lQTr(d `Ya.Z"HK[rJy0⬝}h. @zrD2K4&i+i),UELr#y9kϦ.Ϊ\!nhc?$@$@$` pPncFqjyx(SU1T$^B|JoN]tY"T%O<7N'bl^H)5+ \>wDz&J_WW/9+Q=+DRH8k_,N$@$Шغ8{EeW_W| mE8k&muaب."NHHH@'84SY[&mٲEI g 48k) :BϪQmNB߾}CAH3ӱ 2   "~HHHH6*4{g'"i>Cjҋɓ EQXHHH"@q(\أ8+9bW^M6!-- ܹ3||m8   #@qsd   Ol_cP{g$@$@$@$P('mE$@$@$Pmj+ @q '@qW XYev@,M$J e^~@h05tW5 u#sȿdޘm@pξ Ҁ38 yCuȱ{ҋ2a'gùܫf wm ξ,9 P\3>>> \/§5Nnt= C̤(ΚHH8ӌ~Zmd^iHMMrȹ^4<5v|4Hgm2cZ] thSn~?*aPVlLuurb^ ]wcA;uwdD WGg<^ Zc@ 5hjUfsEE򳥋_O'ͧQXVn!{o6F#c 04xiԦV Ě9 ˷ŋ8kƶvO/!'@$`u@"gg[_jkҀcU#864 U`iUn VӼZ'vR+NC+UZ{L5rUGf=vU]tAf^[^ 6OAhw-Q}A$@:OȥA?ͺ>D?M?A^aloge{mg_Z[purvɌ ,?bP$_zQ׷8K˨ae {'@?b+H?ͺ> E?M7A^]log%f]:s2}IDxaý=>XE+c{`P_ώ_#k!8+?Kt_/'cξxv! %h;ĴmX$._EBN|\gkDlqH~\ dZO|GU,"[0F՘kr/[wޭQ_VιnA[{ӫƨ1e6KԬ%rejۋsYKkLs>1go2eew,Ӭ듚Pt8kvMXqǒ=84Q-2Lm+ΦM'*[_iPoaNHÿ؎2<8ޱ[g3ȸ$W32<49$1!).w'b֏ '2ecc Xz) T::S@es -VsLG5տ(RJ(.NX=AcL5 n@eٳelЂ-(є*{]P0׷8KQ(+fftbZ!iAREn쓀l{"Xg,gѯVKŜA7ZWU1D}@>Og'<= ^9;X˨<ľF猓v8xi,:ۺN揹#k>]X3zh]lMAY8!'E8"{(Oo<C07"$';)cJY{1:Bm鋯nnLa0Zm3>[ӔT<+Yj憡:aX.5c_ХekLO_'N?5po=Bqg2s ƽ+_v*>ղ #F /(άά0?rhtѫ톭DF7~kTխyDnA d{b>r탿T]eNU,/,E9 2͠X|n=|BMa/p=Eg'r||jx#[ϭ3^D5ǡsgsssrJ$''wg[y6Á}tŲpp1G7\PvtƊq/qH-pZKZ) Zak8W;^;Y[kN -V:i6?-mV'`8+ѡ^HÕ"M*$tm銓cWb~2g]g-.ΖUT`KJtڻo<,bkЧ[vM|d%WU]EaI|*~][RϷҔ|ڏ+O űG+DOÊ*ە( B$`Nna>]~ՑnXA7eI穣gwNA̍|itNqv+)ƒU)6ZU65@ZD>І-墋lKTՂ~_᧋}y}]_bݕnXwfK->mҾ9sql ~=/;7`s<ʯs\RA׸-_;lK96i68Jlgyk`_)N;GjRИ> 2¿۷O>X`wn1qV}ZVQࣃ LU|_/|y 6^nٙ\ηmzUD"N D-(ѓ^Y[[يl塟F?Mw)igm46s~;)B!Ѩ.@v\"g%]0@JYIpi9a}Z <ԭDH~% S8S\$Ե<|64ObQXV{~SDi)I^v5ƉI!G,$@&г]N̼\/׈w<5p8\<1?^vR8s|}/? >^NUm8I#9SL g;pv(Csxxfϣ)vWjɝᝊ7nZi{/E8[^POn(>"E-ܝsp?)/,:ޑP[]om]>LxfG(ʩa~[s|yL=W 2t~o\ݏmk.6)m<03xW7_*͛gQqV}QXI4dY,k9>9pi^UuuzKH IDATGpodBqV{6^Tvd]*Y[իG -suӪ/짙(f؆uKR8|436`]\e$F$bPΫmѣPBCXqVk3{㓸D%U=̶߬.qVd6$d;*p$;Y\ ?Wޞ߳bL?ٿ D{e׬RHn!k]@%'TTmp׺٥SoB$`!8".ؾ:tѓ݁ء֟8Rϛ.ㆶ qVo~έ61-㥨5.qLJGawZeDrx N(:34BH|'T_Ul֋(K)LD酚mog!(?T朕|q9 pP{Ψi[3Dl;wSߪ}exyAȍZ6ofeلL1tPIu5>==*GG^ [wK$->=W=鷺8[2Je֌ԼYK5{| /g+爎a|zz5vWlCfv{@=)P >oD?fU՝.%3+?}K3{gf3_3w ܏5 o9UuXħx[kRM]v;8Ύxfөm]E?ȬHZH?rY[LgOcM uGW1|rO`F60ʦ쉨<7X(tyc&F%I8߭NFW1'Sm zΫYxe9kodrg JCnޡ.uqV%{=öL-s 0?2&EDڜSR M{J# D%B>h^ i4zYi'vg:@oSv$@B@/}}w&C>۱Q7Y|ʨs}r|?Y'{]i [/ x1c8ХRa!`1Dp4yz'ɡ[aTØnoBwtFZm1:y+NՇ9~wΡpNi#ns{QvEwzݳ*B'V(hE}8Po]aprӝƠ- r~^_X߿kP~ߟJ!.iOoK_|ykL^LU}=A r6+_9pSAЎ2}*uq-l@L~ZգF?M׹1i&˧!ΪzMZތ7f@Ju!>9OL:1Ju">v9Aq2?Z*l6էMŚ~]2md{aȤ%IJk E2V4FO!a"C\3ؚ1쏌p{D`8ۣ~u-DcC0{q˨5nApKoמG3gssetb8z=Jك5X熈RoX L߭--q!n =C[rJܱ5<;Z0EJr%_o덁Uc|nCoa!ј>-=Z ᫳008 PyG]Sӣƣ{\+ 4%ٲ25tQKZ!/jpw\+*)Β1xdlB@W;ɢ^4L zAKfS&Ԉܕg ZVVeQiUI?~旻i&9[֠jwa]=C4NAv.=}<-98 * s1~߉X:2"fWs|.fid͏ż={^;|qܩdoG`~-eVynj8k5HpЄE52E4RĘKՇ%ǔj\saNZS'Κڧ5Q&]M$@Ff$0Y;l6mX  Xw\кEphێ#_`䈎Yi DcHB:.9P|N_IC7xb BGc!K8L=_sMzc_â$ü'TQ 1 ءV2Y m)Z$!it-ۑ *,(j (-5⧉0kO~Ys4{g~ 9   +8keHHHI8ۤ8kHHH8+HHHGزg; @q& 4( 4rgsz PB$@$@$@ PB$@$@$@#@qzlٳ8kDIHHIHH9|9=( !   ( !   8k=PE$@$@$@ Jl$@$@$@F~:O 4->:_M2lIHHl⬎!   ȋic+   0Y3౩8kk XY @d$@$@$@$`<3cFDl#ZLNHHHtgMgǖ$@$@$@$`fcS'@qא3   .HHHHxggF (ΚΎ-IHHH g̀ǦO!g@$@$@F4H^ $i!!#gϪ6%1~3~Nnp? CQMii)?gg&6$}Щ @vÂ×m"ʺ >FЊgϟ?3fԲ}NK\{?[=ct+Ş={+ ArYP-GcXhCG;V˗fLj}Q5z=ؠ@Eͨ(t&k.p@庌h .gym4icƌĉ f.*Ȫwgy7: @%pi;=>j7zÿQRQft?nX1?58pYУGVg$ܜ|twgyO!! zlĄ؈E4HH@.4K#)) xѢE 苜]r%֯_aԩSu1D>~gaܸqXx1Dh]]v=3HIIQСfϞݤNHHҫz?k1u̩Qu6UW^տ8k2G6$悟Fw@|vY DXD3HH4 P5Ѥ XR\o`Wdy7uݻw̙3!"i~0|E,IgSSSOwxꩧW_a0x`vm&MIH "EM,"#7 tx4@ +W!=+b2Tݻwrvԩ:Fq֠Ug%#[o} ĈjM."жps0HHDgMfoFEhYfk׮ذaVh9W^y1116lt}XrJݯ'>'Nk:gǵY -9pqvDH w陸x( F%Z=}$ʋެ,lڴIyiPk +mFaYy$`SuΎi " &Ll^|N0UՖuҥX|y-o":lɒ%JZbSn?F?uEήX?dH\zӦMSYeW6m(@$@$@Г@Daж&": 7IU5Z`YC;/"DHb bjtTV[՟m*ZjkUkOHBIH}?$3L޹3=ӧ9=|s|{C J c?=#AB_l SvZ"@(7H-7CYfE TYV///GDzϟʕ+4MesdQEi bQD"Pa xLMEdD2.mj")?Ǽ%7El]ib6񄏽 ,`~LAHn<0΁ͶݰӔzO %ZY18>1b֬YX,X<9 o]v߱h[E&β|>Zjs˭ZJsk׮b'5 )Sx."@ D@q'x!50%CZGQ8K"۾g +Ұ+X_kٳ*=  D qʏحT(p' EFgY,uP/5 =o߾3gL}׹*,b9gYE&ܹGՋ9`Xjq,СCÜ9s ƞ "@t4[؅$Ty?Vf%.CPzW}GW},G=~86mlL|1}e9kfb/4[9qhᄡ_2Rlbu=téR Ykz4R909n=bSl^XS?-{{~m s%ksŇ(߄gמ\ >^N=1+>@0ju׷Q!D" 8Q@}{Y/whWWq3x ;zhHY"@ UDY$dZm#ʱ8+Գzg{1Og5;ZXbk`|q:uk @  [¹PKy ;](. ; T"@HY#%ӺfI=Q)߳ҧMXOy{g-[`Xp!O@"@7 IDAT0geCd)X?UĚd*ʍYփ5NKè &еD:x p8(}^ ؃G6)nw%)8XǶsCGc n M답mP'W~}Qn[3?=:qlI1((^lm('b Ţs7q#-OYDv8sٸ?+_qASo\.cIiWaQռRK&f99|_h_9թ DFKfu'4v2 (ƣ_hUYY69`֭HMM+OiЮ];$D"@,;ہ{{u{wϱ{#:X#Ҏ:z=mTJ*p,dYOyg[?8y/ S[օwuk0Aj\\~+.{M٫zm?'[ǙkC:rA;00ӏ_wQRa]&)0,jD[-W]R|p=PX%~9g_M}ѧۯ%9|_-6zD"``$(ӟӻ7vFt \,9ߏ:_/>_tL}|ƁU&qVԒ"@E )p>Yy%&̺̟87`M@T3[FT&βA&̲T⬦O9gjX/D]xf>jt\Xp(Ы ;jW] "o_uWvG_Xa]08+5 حkW؏ٺ¤#8̼KKk=~O9E=+c;p\-͕.?geQ qjkɣYx5'{#UD)B_֠FJ<BXsS9.:D"``gӢ`?GwppEHR Ò+qY !}aX[/.a3fNJ}f`dNJq6t40$X& d dɯf9)4Hg $D"@J J67f+k^>,A=G[??kZ?w/:ȋr V![ZqVAQM9fŤ劳>M]0H42 $uw'ڊ!;P/qvs&h$g-뢚f%lh+w+o1=5Tj{,Wc9˺aN B ϕ@)\Y%; s{6cnd0'vh4{*y"9zV.@WBe`Cs]8Y92T{s`\W8`ULQo ?LYcxl"@ @%gzmQ&&&&^M]Y)6B," v5+\YoMӕnk`5T`~a"@%P qHDI0H'aĂhkab"gӢwaٲH|6cƼpƴuŽ==? cƣ_-/@L^L~1;2,8o|Q1ˣZ n, 'gx kkKĮ7 mqK!dT_n=V~TD l`3Gf`pD7;@/0qps)˳?H H DJ.2,_~ATL:_Eeת.Fy"#/ߞͼ+tC(βv;_ 7Ҏ8X"ebam_ȃ ? sU kAFI}4ͱkCpD~!pV &YBi+BƔ:\hgEDkahqV/)b>Z8Y]hQ]"@a B=D2_=LZ%q cg;9gshw .k ƃiG`jD[,\Ò2o*:oƌiW)2u>Ä6N`0tZ0-onj%H@X6 F򟰹(-Ե:y4YJq(̛n.HTc ( \{g "2B DTVX.U H-^1"PBĊK B?XwðlJDD[iqVsV =ge`~polO%06pl #fugk&oäaa{fcjybňyE6Ʋa73V"wl Ž]ص? rFvϭ[VT)g}zR bl: L L h>"Xvd0UPl?+ yqIU`oUk֯jkX~o,v{p/o*1g˛k*xH-.%a|FE@"P q6 GL !pHFLDс`@ 8[2rL>y"gd(^ Ʒ('G3#-F0e-gߘv@ni-6`L 4dygӀ唅xV5ዄ[k\֨q>'ZѬ8[}Jl IT,ZO&5LKu9A]E.؀m~#m- n3flEH 2lۘ0Yar ħ1Ɍuq$.{`O  8?ڲ _$T\֨V\30%|ejo9g1ۆ^RsЅd*Gc,0w&cSAAk†=I:GTA>fz5I}/"@|$gE5M /|Hc\9T, a)ѼV. 0)h 7i9OeS{zċau;8p PgbYZ"!]/]Y}Jgr&< 91j(878;Է++v ̭ϭj6a?@:x[Ou]y;gcԓ}TsǍXMEch6\$g+,U1h6^Rc֮҅!ɵ&5|1=Mjr!| \$%|0|ySoD]8 -kt&9ٶc`P (_BCf&L= )01Cna>ZoM "ŗ! 0Ÿfۤve5Ħח6#)yٹ[A _ ;BqL5L,*K}r#L %Ll|{y+: knVpǵ;Xre;fh ;7|0wO { [0SBtmH~hQh]{~~(F:cTniV,n9AeM5_\؀=4^',rljpk&4_,C8tYv _W(=дh}l{`p,^/u]C\֮=CZg!zWjۿ|a$ؘ:g_R0[gzǓ"!_ʽg]?#atK"IնC aVZϯ. Ϗ5DЇP6Yf`N g"<%aH~̙Z;bEۏ1FD>Ǜ~/ _^j5}09|9g>FD&Χ_'\\aeOGԭ^ DnVb"7_NWhH`Ǝinn`J LBӼ,. I[pW!Φ>-5_8+.\ u?Ǣ8"ִvʶ㋈_p5- !5q τ|4u/ 꿌Jt5ẍ_`nb_)&vrm?Ĵ?#!#  SI&􋔘,mVwHF,)Soq= (cDsa템Yڮk1 tN}|h7 #?tgc^_E`vp PX> SsIbן.kT8-m>kDE/n9o?<©u ]jBȅ)N@ۍ@K ^s/nfٛ'Dm8X@Ej 2,wC_pS#eu,R$ri?,*S8+gߕD w{$v3b6g+=_GI}IxS9/KsS3m Y?$jusC aD cYp$+Dc q؄~&`,qV8i+3 ɢ^W/Cb ^_Y`]Oya^A>4ţ&%Y=rvfpuYT]SKPF8"݃`a ,w >_BmTL(:vʡY6_I}MBTع-Rn{b,+l] V4`_6[b4赗r!El~u'^j+ʻK檼Fc ZRk- O8;ے.UC=*|Gyדogga!n?KnLDQ\&9#+cYnRGOqV8bHׅ!eo)a4]~'vbaƔqR-B[jd)i[rOEg9 D"@*g+7i.:08kgnWG=2vXס{<:E3ΊXWb/yFK3J;}Dű-$; N>neq#}fyHsk [㑔LԵ2pl܃ѵv,-ҊuKTj!^_rjP=;3G̢w΀,qE8ۻz] [S7p$ZautoCxNoEO֘>Ե-y?Y$Bbj9ֶuƗMGEΎX_,챶çxw\b$Y]M,۷:vsv݌ R68N~trkvAgdr\JsVa/nڐ+fb*vyޘSHY)1]t8vX"{=wRr1O?,2[9f! r-=]Ym 䈢DױG]֨qJնvE;bXsV=HIpD}IqVj_^)w[;}~3 D"@* g+'iz08"UYDW %"Yݭkp2~qѫWka[! I0-tel`acl~v}GβWYDo?x7ãX>|4Xn>1o IDAT?1D^+},[`>@ˏnY!#6w&)r*M,{xuO@fB(^piAm3Sugٸ_n>^f'<0ʊ>TXvés$M76/̭50r 2e5dޚce?hd3h(b]8" g5!H]r>v:#/c Ne-(=\,tr2E>E(w!Yb k=4O>*\bcbٗ=/bLmסb,ڎ!]E rT"@ #@ؒ @l6PX,c:]%W&5.FE־J-KT6^y8SD"@ qC&@0YQ5eHUBIY[֨EkXdI-Wg+hD"@@#@l)HUYSUj TeQAiiHkXd˯8[63^5 q D"@ʖe˟z/c$Ζd 6.9gGGU}p qוXOl+͊"@8H8Fj@UM"Ā9jkXXi]^6[$Ζ7x DFwhBƁKT U9$YBUH()OOXGEZugf+ g+iD"@@&@lXDYcuGv D"P>Ǒ!{!!!n~~>DTPE"@ DTt$VtCYp%D"@@$@l "@H. Ey5JVsk̎mEd>Y^Hix*eZMc+n4"@ D"Iv*gOS%R^WS$XVsё8Nq8k̥Zl[D8S qrfC DT<$V<шgFufrK㑕NtU^* UiZC)*8[ 1 0k'8(i85t&CX넪׎٪s1 D"P8[A)/H5'0;$OMW2<ڪ$XV[ "q^Gip$*hING7$B q D"@ʖe˟z/H5g4i}*_U I|Tא8kTn$HHAU, [W ;guoH5w*]g+{irD"@@ @lp hgMMLw6%|.>Ò0%{^&fW$'[èc@o{Lm2^tSU;xz-[גU z`|~qo.ڮ?;o]ʮlNk0d4kٓ]=ؚ[aor֔ܵ =T^R\]}ϗ7z<+)xoPN|ջa>ʅ#1ihPߺkzVsԾ .CF.OqbdD/x@"c!w\f[7= zqz[5KoXaAYY|{w95 Y{ P5dl?#/H[S=CWJ3MmI54QG D((n.\Ruk 8/](zc V 8*mr'G~['^m^ 59K%\Rl11 wH*V)2aG"9[{xhV l:N?kbTd} Mǥf_^J\?B,n4(݈J! P? }XZq-;&`V`"`gܼHdRҲPHLSt Aƥt;s :qqu|1)Wњ?¶j_ %;X|> v]-o!j+gTzqVMjbzxRAg!bH⬡="@ [Sm_/Ua@ܪ{pjbwiSPtpkbc{l"FtmFxϵT"qTq%PJqvY<z73vgWZE01S~if`ɕǛ~/ _^ڻv ML[#<%F9mZaF4,EĚSީ_&a_q_ߘؕp}ڠG >@E'Zך`L sƯڡDzmYueb[^rlW;z]WTg Շk k:<츨:wE?{}6RӲ+Isx]xEm4(d뀉- p:2#5D'#Foq6)5Z."WVN>f6@M'kl'6Vf\vnF.>Dm~s:AG4YÄom>q,X5,FԩS1o^Qj&}8I D0TPK󶞰bi uo↎?D&t. gKWZ2YIma;S/ᇫG(vn 7mcf]fp5lڡhڈ"t+<\,Fuҥ>ޭW8{x ƌ,ꪽ[[͇ikf͝gQZ)K}mX7v\J, rKY,gܵIm#B >X&oLxX] 845]Q)QZcBxɳ5<k[ŭ;YgFRL؇xGMd߿(:+;Sł-q] %*E[`&033FEggzƥn!<*#`~^"tOzpcDHC Z&& 0qvɖ(|59`Ǥa;9RӳR~e*|JH|U`;M5:5qρiX~ 9-c̉mƜ,-5&owָj+~01˵}+5i.Նb{ޫGƃ݇@Vll`T_Ź+8{=+VVVXjj,q9r$֮-zGB⬾ D !Ƨ$aÙ$8Q,{;mgYE8ۭV3 +3 /S+S j7aELi|Uz<|k! ܑ pjzr#ފsn|kC+T\2Yv&|, hmnUeQ\P}Ya뢴2k6Ya_h?oR9g!βYTG7y8Xeѹ-ȓ%β,ZeıKNd?iE~j[+Y&31SXN=B\1efpuY?|CƄi^m5 3]ʧ)_n,je{ac,񋉸W9L=rmW1gl3>v8O0Cd4cuK=z4"?EH@ Z*SK>nx.]ȣO?XxLYm hGt,C1k-ONn>:yAQ;L](> ٜ$ 8NʯyX-_-cY$48ˢco*"m\XPX*{0,lanj%Y}մWԵseo+IrնJ͇w$JQ <^׼۫ܓYjϊR βH,5//O0zhCߥBqvصku_z%??;b֭Kɓ'͛| }n߾ 6 ))G~ᇰG||<8bbbx%KpŸ>kٲ%O>/_ܹ3~mYL DTR",[}3m5,%%d qԊ,-:Y*zllqV8&G[j!_B_ п/!fu,z!6-'l.68ũj 5< {668lZF4ŐjܥR= ]u](RؑA,: dz™X vomABubyt30Z;9R08kgnãSסн棓{wg9e^;8l,{e41q}c"c_,'xYYg,;Q:B{R"r{XrjԥVSp/R|d(“QG]Y;2Wh=gǣY3{"g 7'qV16VYn^mkMjm5 yzݟ8[PP nփ+'VﺆC. E6YU!0v% c^~YW,qDq=X[eÚq(ԸǦ⟓wpq٫)\Igb[YyHM˂32K\A\|xsy(5'Yf<B[lc]yYY.*Yʯ{x=]k7+!Jb!˯.va׽XR vqh#@Ԟ'ᘙ #gSr , _#''G %1!RnQvvvO1{lr Ri lmmGϞ={E|`y{_<&M `wLuXÇ[nw8Yf?[ovt l | X_졸Hl DT\Zrլ &βId"mc44 q*j 3s, 2cypYv,n뇨ԧ}^-$f<i?uWm0@Y@)rZL /mQ)J)2Ƒ9x< J: /oŹ⼤/`\y;yj7`O}uCGoLIVYvk?Zxr۽S(6جLyO}Ԝ<`m[g.ֵ-cY){u^DZiӳS/8E ,l[׆<.d-s n@T-ttk  I1bI,O1{Nm:bkE1nY&XU4P$hbobj,)rή݃j7пbsdi[kRBfO:?['p78s m&NpDd#/5PghX#V)g=50@ԪimoC\k/S"bRqE_C^Ptu_ޘv_ٓˍoc,XDY9+5cxD2g=Ɵ% %-8‚B07en,%-Q҃Ult &j~J9r{/isΞIi_ %򏖴<:#'oJq2Ϣ^Yߓ8k\A*oGG`mO5gؾ#֯'{ D$ՎVm|Y6R{pO2)PNG:tf9?qJmL+{QRUT\EȬ,7t:tM8M8q,֬YUeyqqq`0T(߿N´iEgddd(Vݻ̰o>qhgO(01+^0ah֭L sgYۉOyb_rLS*Ncg١֭jO[g ǰr첫b`z=8z,k s#{o!t8f8v8f  YPguJFXϺǐfht8PX|9iV%_ Z[d3 y)~|aZc\V%4 >64FȾn86=}6b`,rVkp9iQ`n CV(S)jEg O,_'?׳T?Dlb}Q NVq5~f,qgPc IDATܚ\\T"!ccR,';ixݷ ?~׫5ϥ[! ۉ mhqVK#β}LE,{"ݭkp1壹F-lDQv %;[k"3}m:,;kǭc8r 6k]dM!<~>87s/n +5GmkM[TG9Oqjs 6~‘p>\rBY}^MFFvj9SE$goBܽM(βzS-df~G k+s\{1Q O]nذ7 i051m`le9c/ĀWJ#ʽ)**cԸ2rbG4$e׳:w[":h^^zW=\}^J&g[ņ[cѸbc̝GM7o£YcdzS8:YY)βkԜ_po?1~䶛)1Flߔ+XnTMM*/K#vN}KA$51qV=Ox_q#Qccxɫc*8UY|xbyڦMYBeB/Jʵk׸]m, O?0WP?xJ=ys+,8Lf0+[l5ĉOgFԀ"@* ,ΪSj%{;K@%ޞmoc]oݳS/q>MkJ7N}Mő'hWgEùu,>BCl 5߬8&mMBA"14 CB%E"r$\h!t8һhܵ fz"dF%{<}6 }LF>=.h71q)wjmr401Ob]\h.gEK{OGPl 2DZ0Э{k,æ8|}$DNC8[CAMK?g|(HC֨XWM9g ѷPx0=]m4 ANu~};7?O=_v꫈2Z u$ [ ty CªR]7ZGJå7(T~)=rlligY~؈R0/g=#gLRbBA}w^q0xѢENy@.D۪8$9p> g26.UECcTv,:̑Ѝu)&Ji$]`K&o6@{7иs%桦E~ʺy-YbPEF uk,QDc{=q%f#Y=&F!M12$v$qְ<}t$)r:˴\xc rkb&5# yqjc}imC,@RSTph \^)8+GxWZIU] q|5j,`7rӧ9r$V\|o'Oxb)Yv8RRR|W;\ի5kAˢ\1c׷8I=p0`aҥ9[u.a) D@Z"ge)ʶE^qY}m8^4A`bwL¥lۥ6V+S5MUCl;.V,*"glQW핑Q2"gҘ7lW0)@mhZ\4#:?YcJcaupo;,]EԮ$g*@ǫ =I!#3?NracEmҥ0\Z LZ8[ S+Vnx g (Hi 1R ]7PZ#%q:D D@g9%ɡ%YlټD }fwªvGcѩ5ql0^psQ9glNBh& vCo>ʜ`Q}kemHAi90bc0#VQ:ˀw^mQL9aEhg<-8DY1};;]SU"K  q N V4իJeUPIURh H-RVDPZ DTQɏJ7y'62Jgh?N-£UWi^L~E  R9Kg[&,LUW=C1$.\\5ugT227^&Yr:Ҭ1K|c:y&tU~k!}:`p+6 %q5Y宰6cU=\bmꭧ06Y 8 SZ49ob1Of#ykm@VDeY* Ui\S$.iS$j6Il/͎"@( ԭ ja8p}e85Wq4"^T*7nUl츖{uH6=z~,rh\ ޏ9)\mv?A=VטB@kBuH @I","D"@@$Q'ˏJDD쩇+'''xEMY"&D"@ 7Iqsڀj|>inv q* ~yiE6pƀ:Ѫf~ bO,>sE)-A3oKS=8+gFC⬑Y$҂ D"@giD"@@9"PrR 8[KS#D"@J q D"@ʄe:-(lw>,!d'2:a]._ W~;C3%G4. D"PH-[{y%@ly^j]xjqa [lб`?b*݃?c[-W)qv젪b3 D"P 8[D+#e({^&fWn.mlͭ0BjLKQzbvEڡX|e~nU>Lhu^n= Tag'm"@ % 8Kh"PF⬙):SϮŇqʑY!0̾ 65x#LʤFq"2;ɘW|بUXvO{rXR$tDJv_ކ(J1,ُrlj/et@o$g! ~kỨJ}/LU{0Fꖶ8 .oXaє~V\0~KlQ%%9& :7K̩2}ͼ^3X\V~vY8&뿂gx( . #^̿fV4s[$f=]챲d 92._/wvz )6c8+˽Hݿ[b}3hlȂ "Xb}i֮E*h-vj+ժj{T,IH"bM"w׽7{Dw{ʝyg7s?$U%ǟ[$LV3HJn`?D)_yr{u]&`L 0&`gŹ lg oӫN_ɄĔ SB\R4>*nvΘe m\n`Rp.IkP:466j7_ B;zh DC#w(QHKOòBTE8}{\KU ߸`o4~NX^+L Y Do =H[]JUiFbYd<%>z$K猻}Q,%F\[OaD. C7<$F5/4ٿOA=c1 ڍS g [aE( ^O⅘M@fg [cP?G%k֖ WkйL#T/ZAp(hƗX]\}tF~%RqV^*#F_햞+Y-ʭJ=$_RH8X=||IRskqㄐհʗ_X}HSJ%w_4t_˴D>~k!!!y쬸Ӧk Ƶs3&`L$,Κ z([z٬YUˊ?|,]հD|{z&t<Aq;(~ cnf G.8+7iK!qDaouy>UYS=g5ǸG홝Z TϬ1=BhP JF:]!YY[̗抦ȿPYr}pwQ5]qVjL;fs8+Ӹ+YG*)-yvŇ8d@Ne1֯;߆ LT!4/YJeHYzaYKe{L 0&8t zh WZE;P@s ) xl)c5 VHo1)[K#=9#9YsqK YM6yK04M=MC!k;L[aԳ| !b.[dppWHDŽjמH4A狗N9jե/Kn~Z?{^r/)i:m2\1kO ٱ.`vɉD}KX}\lVxv/k:k34'YLH*l#Β mnV _!QRU56Qh[1(h>l N9>Md濕&k<= Sj|";/R냭UAY5fr|Nd^~^Z<3tTg>=lVː8+w_&`L qcMe=CXb0pL'Zv /LI"$g͡es/lg Y WbK"<{wdgg ^fZxv=0Im@zZp$zKsÑȳm_w92C8}}sXeWShU&ӿcxkax9k BRN\\iyQio2KAsm麨UG= cfgIJ㹵b]hP-KC_$7ĭYڃO༞bxȉJސI;hmeM.ȭ%틪.7R4HCm 3+ $+g=\ƈ741J/BcsT~3֯NRԇTrR~GvZribq6Ȳ]&`y]@gts:1HfT{ol :W0.&,Κ Z$Β@4ߌ o7s+Ö_ ?iy雏披WrdB kDT!qs\]3Qʡұ_?Z7&W򠦃(+!qz8bNAzH,`wn2dah}'Or%ݧ%/raf@:ʤ-cK ^*<ڥ_yR_"wt8ױiv*_@~,?L}Zt_x,枘_5>}wܷo_]:ߏÇcocƌӳM\ `L B⾛Mx:)6Nw6Ւ)X5I%UJ[= ]WÍ(QN:uub8Y#O܎eY2m/%Βp{57(LXߏP]^ClڋC(䀊PVsMHNK<H0;@ cŁL$ʊZIߦ`ejT;rRhv"Zj* < /_Gr E܅W+ r~Ӝ$S'RH F*osy(%Β7w{bf?$^ _ IDAT r#vxR>j/ӊ9+cSAIqW:W>jIVYI޿k G] ѳ'‹vu.!ˉt}@ t=94-UJWzӺ$O|}EgGqm?)wM_v /FRKv/^@>}j*L 0& Ȉ wQ4y WPz!foP(ϻJۖg[K[tJECk&gglg3GjrdvaũWƴVQPu1eɛB1RksFQ&|8|}}qFHhLJY3`S_`L@Fb q:?yH[HtvTu/>9'{6Ӵ,Oy&%r8%ްJH}ף Dr[w^4`Lf1,<<9:k"LI!gAEDDx+BP@4_f;}48JZjnݺ"3gұcǰa={pq|Nձemgq֨aL 0&`*,g~F~1Vu UG@BT$sF&BC_W/.e8krLh,,'ګ4BH.;,doxͰ$Ml9pE̛7zBz$sAPPV5k Uv֭u $R g@7Opqy9#OvհWg߽{7?!`L h,K{VÚر"*h8ۦtqĚ]º_ӿS9[`׍S,gYF,C,X!EY$%i?_|F)%cKΝ+bSYJBX;wĹs0rHѣGEx|dC QFv-SM(_:+D(>YNțs6CTVM^/\*T0aL 0IIN<ŜN-$_3Ϯ'7Z6_7L] ~ary*C, N^S Ew}@[:Yvا#6Y0`L 0&ȩ8AN9n7`L 0l u d^-=m; D-7nsM-naZF%\>ٸ;UDU+~=K]|8c.$!6 U=;|w }\*vy&Ć+T-KS*HAQ8_9`{l憽۰S;S8R.y#As"]bqsw>@xWE˗DžW.8N!xUWGwgزx amU9t+fL 0&`X`L (&B/wKUʔt|$vl8Vi _v.WeNq_X+`\{trgSť;JL허G9*#j/+UAbϱui=5^L/ y=LO&!T0MBXHCj~ =ypGq:mya}Q+SmdQ^ A!th*V ǖeI?<_^SF0R {*A`ڦ%kVi񫍹eSrq]L 0&`99o̸L 0&@!,n]Dt^ŷ."02 ƕF8-^)_B@X44+B"˰EW7X)A"'( `@l_ X=q֠Pg5gᥛ%`o1?LO>Ai.Nݫ-9W 0&`99pиL 0&@!,c隣Ī,6vC"q^vS=q]IkpuX=jaKa kT~[jaNrz<žNaoa](*kW)ի {aNC:,W_ظ{T@E؂pLnDקWQ 0}%IƊpr LgWeS)lZ~ϓ 0&`^[Dž@$lVX5!`L 0&rg3  (9hrS@"kK,n*",fh&`q6 7 0&0,Κ50`J 8cyyg`qZ 0&Xeq6an?!X!dYH,U ,2&`f`qY'`L@ gP:u̫49uiWfM-Y&se`L ()@EͮV ^ )Ud[VlsV1 [ۿ.l~(O>L d 0*ƯKT5ll X%g-:l,0 ξٳ'RSSyf/R*qV}MWWW|Jr>&`L@ @¬fu_0s|Z|X)>n 9Sz>Ѷm[DŽ 0&y_+oUA¥f0Ull H0w},OP&Bq^z#F@vĉgyPyv 4P{Ξ8q矑/_>?ǏG}$l,Gu 'Νam1 ,>68 #P%M6?_ ;;;E,6l3P\9_۶mâE3ZNq3O<+VoV<;xw1dT^]~())RVV#giK ŭ[ui5 P'jŋ"G#L2'&`ys1 t5Ԝ֋5PfK%1sZ$<=Q:ux9::* BJa?Ӌ/ЧOZ*bL@/)>T]AabGC$)Z7G5gm1V}[g(c.}dV ,Κ;\>w02l6m@ W$֯__A Sh>|8 ,( 4кu O]uC%AO>QOOOpI,7oچn>UXz5YxRq^}vYƍ&Mk׮asp`L (! !yx@£GhV-RJ YwD|[mcjU," yCxiz|kkkh`Ow;y>Sںux]V ?Hzʉ8@vD_K,N2ɔh}]یҏ?sa˖-K<9Rɱ08[rÑgQ{#?HV&-ƊXn޸qp.9{QpCԪU Rkk]%zFL5a߃ Bj̙\ և^XP9[T8K' t!1DM}1hڲeKn#""(KD[e[nܹs9KuWޝ;w O˗3fXr%;&`y8u X#~< Û[@t )V}\?܈'>˚Y)h qv.s0oB\ ZwR,+ ){vsq:; TX)q>Ӈɓ' GBB#WPPʒ2gHϻ#2vR 1(,Tyq]4PmDcDOo8kb8KU-J!(Jp}|"˂ DIRkk]%A7=ʼn Kk"ϝLg/^(nJˇn.\^1gB1@h=ǀRqAB_zpbJJ8Iuqb8;/`L I@XiC㮡 YUHeY%: l0AaLI$xPx(:^zs޽8~x椔#o>6vXy84, ?_9sFh9;eIIS5Uʮ)k)N:U|,+SYsj (5[lY6yz#oT躉DQ%!RppbgŽ9Rءx:tH~CiӦjql2Ea 9"lY |ʉ C@J|quW`HMng][Q(zS% CGP(8)zΒwʛ_eהBZgq  o}굁Y $ȅ$\S`L 0&$MHEukfW@@\iyQioKxSYU28BBa7$`RxKTq}||) ʀRH-_ȋT5V%[[KrTŜMLLv$''qEP|Ėcooo4o\xѡ$␗ǖvfԷ[o{/R/g{5CziD<~T/g-PH닳}B>f!Mq޽{bsUSaȐ!FuЇ 'VI:B|Co}굁7trp<\=`L 0\L@Yٞ+gcqR+_t"LyR"AB Ibx"ޱcGDRD!l}Iuft X6mk.{J~:\:$M%*K1ewӦMJ* ~{,o9^vJg(y!WTVMgߪvRҚO|Q!dk"tZ%VhYC#ʿ[%sg-1l#y IDAT`q6) 0&BYü`xξ)Sv!t Fᡸ1%ͭ3"` jC6ڒU0cXb}0wm`q֘yygL 0&a@kV UK;[Amu)}+y]cf`MI7y3(T'& >QotXX l8k6>6,NkV6+8+;`L$ !VTlc>|rKFZ) [۱8+3A8F^7(&`C0-l~=ШDUl8k6>6,NkC6kB,ȵly|val帤cɺHlV8goa7M`\IΝ 8G`L J=g3cqG4߮׌j':m:}aQeell X%׆lg5XSoq8NC:@K%qv%X>MSH?Ml'op`L 0",5.`ZX .7TlW8>s{@w O`8p) p&Fd2(|L6)ʉ0hG)>e[bĶ:w{/Fw7o?ðl'0=ά. A[%}z" V mwc}cm;yxOk"JX5dL 0&rgYy[r$gsq@x#30r[) >wqtT<I! "cr(G3xfk`0a͈AQ#ѥB2vL/i"}|{0K:o0* kΈAѡ\AP[}q1cBLwi͋C۱܆]GbhK':G,oԩˍ8`L h`qY$,f f (o8~ WɾXnSnCjԮ|Lg"ȉRa —azwL— ¦S]@0&LC}P|LF9FwimJU0O9ǻ&`hx{,o> bwH +r~ISXe⬥=&`LM&,o1\D\4&`!o8Kgޫcĝ9vcwLe49+'ΪER r 'qkD"|fht{&`Jgm0S,C}wh DN$dqB qVߍ.^tq͏|H N)ɣyy5yiMK}͎Zz bqYL),aL@)ΊPS{`4pîEv"ZL*b7Pywh;FHB}C$sVBl{bZc^M {˶&RX:!Mf@ 0QX7U⬾|7)/CF[֨rǀT:{/OR׵ Ao&Lꃐ5!/5;(k,p} r`L 0-o8 槨⭷N'F'+2X)UVN0{oǵ{m4/U#H(Hr=S@]:%\w7+/Vj5F0 a@V{K/nWW-rB)׆!}5a8[jV(:m_n kn1J%u=Δqr2/,{* 8`L 0& Aqzr|“g5+~Su`N([/W^}qd[ ;ɒĸ+k1)׆!^JKM;Ɗ5w塤eJʝt,B[bdz#!>{Qzo6%?T?,Κ2 `L 0&`9,Z%[MgUjczᕻ -sWK0wk)0?brn^ĩ3:19{f(:i{)1/bhq_\wy=x,nEGt.HYR\N_FgDžs-3Y0# XPs,܁NAvy01dXo =HK#q^pe/vL\ՋVȰq(#󨇷,:aY0%t=%E-fɡ널!q^-p"N&\DpE$<:IR"qĒC_p-9_W&ʐ"Xh,VVp(uĈKq=\3JM笡1\n`Rp.IkD_{gbڍׂXvGg2ZCj(-*R_WWƯE[:(W$f(;o٦n47tYr昃la+;QpIc)}`!~J^ \U6j>mڃ.j7N%\gkkqۄհʗ_O}'"" K^,1w4Y)rAC}X+G?"-=  G?Sr!y@*P\'N\9ܡrA/0O$I(PbSՐ8kh"ʭ Y9J[RԵxcgUclHgs>w 0&r ˱^wFe=C[a~vѦT!I,ΚC^&*$h˻pY!X 7[kZ˓ & pw(~R eT^p)%+}0Oo?OFPߵ oOlchwxV~M O"l͢>\V?q[tYVn.R/JB}BLR܋zuvJR;,نM=,ySɍҤh{s˜Y{eQˬyDX0LA]W_WIk\g)./qp쥘Jދ"BHbX/ru_M4 KTzj#ⷒ=SD=URYRiS"Vg '*C+[E.*;X"LKHI&{oP&Pe uXbd8P"Zia/SsNVdyLeUk[~ߐ8+7ic胀J4eЇ?Z#IDsn@w->X+g`8;4}f!RuQiC}K'u-K˞2K9`L K l$$We1'S+-/w4c*~iL yY5 εLg.`3F_8аeL!WmPʾo!\ ªbIi#Tx[78h>J9~>KWqx]qIc O?QKNx:d88XqЭ'f`)~! !4r'Ж @lѧmΔ(> yٺ!N 0No8+R~N-JXt+{ErT<TlBVsbR9(Vȓ? OHHlڋ(* <ꊘ^ُ.-g {oj8k/QrR@%>W]"[_4a^~z%ڧ~HʯoK]R5@3\8kȆ8+u-m,dqj Ō3z7Q|0p@4mT-D؞={A]ÇqAŞVVVXx1֭۷}|}}LL#Xhϟ/7yoԦ?nnn:t(.]hǾ}*'gbL 0&`a EYvH;}P'g}ȓ#Ao2B͓)B9ISأ8YZE}D| "<<\5Kc1)w^8::sغu8D=g-sݱ&0&@"L 0V]&2&`Lx£I2B[)(KB%ڢ/%eeNƘqK",'&`9]@|y]( tjeczxdޅݱ&e 37op`L 0,"lFЖxhaq6gL 0 2^z@y-naZF%\Yq@XqV_Ayiy^9Tk˫9bW^hyaȎmSKR_ KpXz@5gnpY&`ot zh\JUʔ*E߉oWk:zsFSV (./#{Κ t,f$X敾G>C~\<+PD.z`xyY^3YEXU31&``q<~\:`qYX/-]QŹz^4kA/V<'ހUdqë܍;4 2{S;?7%fyg1cqV&`L GYqNYgs8K{% N%^VttADz3@Y0zT]hYUЄ,-/1K}5~&80q&&`L<,ΚǏKp,β8[)?C8LUqU{63+Փ#Om *RI*"V@31y-L  d8簷GgE|wi>{1ߕ{"$0fu@Ex7^lWjYsgcȉEF19ˮ0'7-_v@ufX/\R負q!z 5?ŏV ^ P?J)rך1@0,38/`L 0&`"3|5ֻ, Oubx.u{O}戳ƴAJ;'!R!1!Ɲ^^5Yͪ,%Κ{PYge8khL 0&%&YYG95\=?BQHV(aH ɸn2G[v*_AUzDEk M0 )~O#5 T>n^4ݫ :҃qv#Hga/5b[.)[MgmNeQ{˻%>>0mNhs)wV2&ǟͧ ?q\St,(ֆ߯A;zv]55+u4~%_CukT~Nf4-gVq79{f(:i{)1/bT7 Bf/·dX֤r;yYkS\SCɼcqV摁YES 0&0l2!>P/!AzEV0kP?nv5E?9[Mgɛ> ^{uPQAnV2&7{z 8pA\<ca/1Rzr#*wG!WYCm'W>~eJrN)Y{6 ڍS dY#v{﮿ۯg(f{k͡=^N%͐;J2!>IFow™@(.S;&$>Gp:.=˖rOҨ^<©`!HN""*S>ܣO骹0Mgò p+6,jYQEƿ-m͝09)uU`g8l {L|Dָu>jICV~ n=G_b9 : zʲ1[qF4ǹc<&Og86<5?SX2K3Tz-t'GF1gu=,lDME2,yqR<򲢗9A1+)n 炅17b7SB! Q8wb9J}wXp$ Ǝ*yH޼/gXX G~k^Kx&~{!\v fq3Ua 8{.\ {κPXI7[L y\U? &" * Rn+̲J4ԾjZZi-Yj .  {=zs ˅D83gsw9*#v RcY#17)`mfF7UK JHlN܍ְQ.glfZqYN,:s9absð|VHܨ KŪթt  qvx3!cVtxT77 F#l tJ@TZ>"5mzs։iu*DžbߊEâљX?Eb| T%(B_JX,A7yb{hnsD-MqE gJūcoćgpV8O,EQ^Gࠤ '*uީ)r"^k9qXr7VC'%K?"C9wq?+ͤW)m= rpVxa4U go@3'4uf(@0„pVNt E|3cNvNɩ 8KiL(j!&Yj"Fxסgم?_*&?m16TFbc!ХlB-NDRdAm3_Mcڣ̉}")""i͋iL:cţC P9m' gmhc#W>H~Eox gi9͢kfYUອb|SPd=YZ\𞢚&H^WC٬/Eeyy h8^LKGVaFxЮ66Nl@z*[ 0:N&o{yC,lkoN­{X4[k1cg3eWct7^铖bRf̍p̹Ps^v≱K//ks1y$?Rm8 3jtE*FOw Y4ش/NGP6^OʀM1)r2N_"EDf]KٗNm,Z{[;<O rkk4^I/S}Ĝr=?9K㏾13r`23ǧ"*6h1M{20߭  0 PdD7;406ڽgaHâU?}9KѱEE,1y:YM} wH$Z5fQPdVp֙EIE@0$lڼO#&-^;Iy?`QtuR>crarΎvlB*&8+_1Hr椾 \l 1;|EKeb~B>D_ 5dᬦ`,W&8UEtri%͆L?\+:d7,MY^`z^k8+hnR]ATwu{_ g(rQ h Գ<\p_dȫSkRnB+#Bhmv ˒tvh(ce5V.kq9l8#%عB6,R$n 2!jR 3FpsvaVKqE$<]n313(vnlg[!c5(g$YQoAX: Hٻ3E+gߗgi9ĥիRٯ/Λ~1J,gO>ZkC=)^)gJ|R0$i'Y?*Vl6D V1mvopx9nUOw Ǝ䣈}}6S(H>%dr[׋3l*,+?Vk?gOa/8 AWGFƭnj1Py^^;P6'F3MؚsGG`U8YGa#vY4N EmƆLg5p6PmCgڣ\bmt!,ŌN@Ԫ؜`Nӗcb܆#Z(PplDˍ ĥ5&4׎Q^9q.6^@.~ '3X/ t"Sq?'E[pVj,iXDz5+{0ާf*Cu(R<umTe[(1S٩Ck/ɚ546 ?70yOH08tr_5b~]PTE~G쵌4@Ot6xcw4r JЇnYw@RC,G9B)IR(E18+,lA :cI>}0Q-䜥zսl k1̫+{N1P[ګ_&qNzR/xwesGݖ*)o4^]YOT0etB7u {W}pyϲWR~iߗ g)m7f]U8KoJM4һ2XJ+[kͭ!v7bO)8+g/pVbW7T_&4:"Уۈ:7\W*R[ey+B9V܁}bS7Sv._ξcwD3'p<~r qVUju&0K@2,.TeuuEgC ?gdd谋 Ҡ2{+"#9=qOP_>6=Fx[/\} ˒+YyyWror9ǻ @m4Kdow*;=DH~q{\0IbEo}s~IYT:I)T9m5⃹F!aC1l~[Gp6?8krpRXnaqoӺ3r 3'tꯨk"}@NI䓏-ч>xTTEd6c|m}wPE%01cML9z퇰w&\̼Ξ'eƇ_[_mc\^pGF{4'n:Ҩ%j${s +Rm=#l@_8[>XYj5]_T>?UYuz81ʼބ͘t^_+Fg+\hkX8H:%V''n!:-Aye@?E Y @K`ؽ.8̉J9|^޺Y]U#%~:K׮M}q-.2`njy7`T,޿O!6ދ񸗛^Mѿe[n_bmcJZ*\`}q 1gXY<;7?FmW oFjb"~Ƕrso& կnCza27W̅sY-TMk`if\1C;(󋃻FAho#x5?_ECh[A~Xx/^ ^NX{h7zDW{߅h FnhʧP+};z~^ǝ«Ɩ;m#p;gEZnt/ ۇt|(f~25"pVMDO8khj"\b7:V^:PR9I(7노I8qQwq}(,ym'bUF֦a373ylfz x ;=n3oAxg/R20#JQ3ZbkPugsB}le :!Y,~Y7!!斺K1WJ%l5zQ1B /tk-Gգ+Yui ;}5zK0v8p6Y(RD! R98r*rJmvRq8[ ߴ.iVƪ'p8+Kjķ WòS7V݁wOuF_ CQ^pml;e00Jdoݿ &J8 gݾ!7o^a)'mc/|RWP>W"ÆH$Z7 gG/O#Wt`0\r8+ݵHO8+k00*tz4a? &5Z ҡ_\9,rV ҁw5 gbR7Ƴ0;f=.y|-B ^7x9`F=skKlam؋Oaӡ"vE*rV؇Ҕb?l޿9^3^)l ͯ.U[g>)r8kEM{yfui{,:0쵣kUˠ-_sexԢp|sj}|}R~, E&=dPS.Q_^!x?aޜ6Y$7E*uAk{գkP*pVU9Zyo5Pml 7+ p\ T.FIll~ص%֚!hMiC1FuHIqM.eRW{C⇘(kMͰ!j+#X)&8K 1% 񰨀/,nff`Bn8z 1M0뿄99Xwxi"cd)?ԥM`jbrlC Rge[ g }Eeߒ{ʸja Vٿodpv]_XyI9;Գ ;TȨ=]Mpb m3տ_rv fO1i(۳d_/,CHQIZ8{A!܌V1'fl-M?8P;o.킻#{3ᷤga !oᙃXZEm?D\atqӹ\W+0VWG8[ZR"5+6q vVlWJh?eUõT@+PR j\Lk Rt*v/l,uBAq8ټC{l4  Jp 7rW֡|}kގxt>CWl:zfcaZzgn^g9v%̷wѪ -@#kIO8kr$"#? mq>^nXWEuZ] ('/1 k,\ M*6_].-ER o N al^@0L~~,L vkԊUj˄jA52\}le`vaZt"g )r;t0.¿N\kOGOFۆw*nBu`cn,,O5)=DrR痢VrCkYWB(cֺj]JPZa][Kխ9׻ pM+yZ ݫ hѕ{w"س)t cUWS#`]xk85h9+/C!##HO8+eKo<n3?谭T V FmT8}4 ц!Tmq8[3v8)ۀe.˺4VkkכYȀ9YNwi;s)7`an1,}7wC>Y@ _9c8|mmT AbtҜ^ol "s8kxMyFF6aj̭k.˺4֚Zn͹V*pﻁ;5e)뺍۷ ;[VկܨftB;v8fé )s~qK= '*P,_]t /.x( ܟ +Ÿ955#SY#055Qe]kMXum-U\og91o%%2:\z6@cyߺ<.q0P hh_Nkn㕣QTrsyW{awαJ3 a&%Gq0H1+S _IR5eyq_CjyuWѤ+85#UpN5 W(UsvܡgsNd?WV:u"a151Ŏ~K)z?Q.ece 8,?p^k9:df=E(exY)[ w:8`Mp#.;UsZI-f'^ƞSrIüJg 2Pb\}PsFf*M[UݯC9~^0nԆ6"DTؗUvJnPPS\\ [b֔6c<{0=;ԃ߯º o+NZPϮj>}}݃q{ ppIf!/} ] [cP8YS][VVG~Yx)jWnoO 7ꀳ^lwMc V 9i)pVj^u{] 3S3YPYΚFzӦM>MbJErnN 5$\UcKo9t. l8e,ȑ=b6j=cfؓr܌Ge\Xᬮ뽲]9U!jjl 7S TeWURM|}isp  }){݇ =o+`PY36/a;֜I 9;YonyEؚ³?n8VQ.ZypqD$,= s ν~VŰpx()1IƧ~Ù{e@owf맰7&2.zvý1ƪh3NHe0 Hhu9+) L.T,_=614EΪE#xڧioyUO>MSl$6jɚ؟oCS;7epUWD>pKY7٭~~+ QO}g|(!B79>*֞Զ:t`MɅRWu|=:t'c"=?Rr{xN5Vui_ sk|_YԵ }.u}ZUo3Svb%01S>d7l~ >e g:o>hZS?]P>2Yoqsѵ:_Vn>b{,vO[Y*﯋b C>rUKMj1Mz"8[3g{zEg| 8kl\W+ TVļ>po9).)31K1p'>H#tn!o[w*y4ӛaoa-0|rR~1#S.g5ƟQ wCov~?$al`'?̊4ϺY1_"5f~ ^]4$[_Sbd8XǢߡ" {~nV7I>p<blԾ!esڌ$Jfv!dI{(V}Vtm= Q9C8+W=Xl:pRpVj.,C"dڡB %N9p&fq\W6+lm]>6 g VQQ;pN(|[08E"g ,)k գ觭1r{tRpV(;h?U4[i:F[^.(7e=ro8;uAϰWpi4>E'5S^DiIe@4se`cf\ɾ/g홏M=f"!oaj o j/EO?YY{MA_qi6s'aEJIE*@)}'OSC+rJ?Y6"rlݠ)浝闐_RȚ6o/*!EMP"p7zuiQռĴ gUN/ɽ`-M2~pi\;rVCۗxtDKkPFX>{Xr,D𰃓?4l%ߦ(T)ibSaڋEdHb+ƧcB`h[:襣s@8mEp7[G=K+{pބ>"_rxsNTGG-ʱG=jo/;8a biw=+ p\ p8hJQ@8K ѻٗ&Yll;m'hD) THV,A?hedm"bm/]EoaS.ǧ0WX頛92ƪx^Ӥ2y?N7\UOVT,XJw/ABNQt=Śwq?+eW)O9/)};M Jg_vgf:wK!gUb-LEUB8+O"Z?{OP5KzP͕+?ESPvpb3(p7j_XO1ݤ|Bl2PƅEm[KB0T2OEZ; =gg*gӏb) ׎:ߠ+@;R2h[ٻ KE8Pxo҃?^(7w}k%Zt?]և6pvl^{eJK{Z u4v6Nʇg_JEr8vS p\WZpZWYrx"(s+JH>|DVWttЅj TL9 }0A=E( u@Qn3ߔkSF2X*鐱NZ-(G8V3(a6h1M{"!b@H IDATu80 {k& E#GYQ{bӰ҇"R9]y,,k hi9w jSo}1i 8q,}ڧ/)}=+]o/ՇpB-壴lkALmɍմ~ZaTXԹnxcRl[[[>{>p &NN)wkú` 4H٬>Ko$=ʿr4t?Kދd +mDiN/gcnh1gpp p\W)l-P>v>ʔ^Y7pUpY}wf38x:/VrS9xry:18<ɓm-"?@vA.{uC"NR~Nz]y8Fx{{L;Ro/㊱RYޤ4ujH8K: y,ZQYG,vqRnޘE&_N]rJ'i#fGn,]KC\Zؘ4AFjꓢ(WwtpUB 8KN)24SdApWG=r-w9Zaq@QrQ&z#PEԪ6pVU];K;f4ӈRwC,prMZpj#p+7GS>dgiUi^qVr>O6(O> e"[(6y( nERT&>'f=W.64rև6pVjISpܬ*RpV=@ED/ފ s10>Cד֖f>3(+t42+Xص%֚!2Dp8+\W+ SYy:jY _?唡\ai>ý(߯P?Ky頏x>*"iݬTXs\.{Qc1HE5EHMc;}9yPZ=^e\8֟faYN^]{O֯R>OU Xy=H˨ggU CS.6yu^쁁*yUtmt(=CHҁ"PTi (Zlad"^H:LeAY]o*T(F$f Ւ|](֖6pVU49IOdbə->j>FRc}:-`8H_:4oEh\Ϲ\{UOӛޘUl][w3;5D\%(QQQ>졕] 9C Ίb{{ܽ_8oG`O_vRpV\J}ջ__;a^]WiZ3j_r8+!W+ pRYC)1JtAHj.#j"gXkU;XK|лj=qM5 딏y!,'jemgYg~=W+ pUY[3285 Scn]2lMAe%g9+鿦_K}jz_eodge:@2W+ pz+YꆳƬ]M}px^AwTWr8lx+ pZ*PZ? $iW^3?05/WR@s$ErKl :S8G=^pPy@0J|٭ޱq0Vs9Zq_U眭)n p\ $~_v(Fd,=iv>Y}u^g~ 95)A]5a9,Yzs8[,S`XdpV;\W+L}sZ/W}H̾s^pgr8[Cª7Uq-..1dL2E9yǏ1{l\r+Wg}&:IIIX|yk-ZgϪ`|嗒J]bhΝKj[_ pƮr 0H8E5^(-5 p\W+ T5ZFξ꫸}_YYY᫯}gРA` CM3g_Nz]#M2`i&Ms\@mS@Wpz&l1*-G/ښ[vEva.6\܁ψlms6>*U*w p\@MUY'XjQQY~0p@@pvҤI>}:O<.)8Kp"wnjA1z,^iii P:|ٻzjlJ8{ ̙3FŅX&8+oVVQ"W+E Hkpn~ٛZg Ҿ ̊.AxM5SX; $:05y0l",f/ MY9~Tx FrgůypH\C*VRMVMU܇Hp PZEinf]8$يFΝ;r>|t={=B8K_|VX9g/\ԩSѶm[P*rhgHLLٻw/E_f""{7n( Ίl7r\ڧ8$a87H!$#rV!WFx()yV;v=1j\ @nf&,,i-Ħ)t&M Z>+ #g a#@i4NiE EYgO0"[1An}7-`[&paz̍p}nGFg[ r(5Z+h 4Wu(*/S4_o,Wp8+>S:Yj0!!~)ۭ[7Ag"GGG(zau҅5HMM;r֭+VmRx!nR^seY~9ʕ\Wv) g/%g0i`s׷L8۶6O~AFAdgqZDg8Mwî_4HFDbJkgS,_Nk1w?ޙعvR.(,O@U/"8e'-F`ݫ*:G+9K6L qFXvqM- 1[^G`fk  uek89sGXg7\=?B^n@ RΊpVUB?EΞ=Aؕ+W2),/r@ RlTTKXv,e DGGoe6%;)Ձo7of Zos8g\WYD42f)κX7[B((QK^Q5YuMV%R"±`W.Bg.Ǥ538jizjnq1wS>=!^pPfF*Or̍ !`<87fFҹˊ@TZ>T-Gآdsmfg_a p8k̳m'8~Pp.rqH(-UIy8Y2~bpյ(۷oC(-e)* fdd`ƌ z{{oasuI ){rR/AY+?D 1h9992e 6l;;;nW+# ]GnbG{^Y>|l #Ng(W̾SPm5Φ^/#t !js X!Rch'-h8&M Wc8s%ƪ*qX?#ctQbIaEԪpĆ,tgl:uwݹ-#p$r0;vx/`>DǖGV.R 8Kk_u]U#ggfO^i H4Ji&0(])))"z *S%F?c*TwϞ=pppO> J@IER=:`.\~~~UTxG\W+P 8L2ବv8L 8(X%#bbJ5\Z/:ؽvZDxE("gY ]ѝ0m';0m_o U8kjb['I/f]!硤gWagǬǙ{:۴+qRjU7  "O<,.@_1?ZkBUgsNs>:k`mbq?%pǐVЦΒ]Hæ2F6KJJoWh˥=e>mq/gqT0>[ߠVsFyuW+ N8\$n]=c*y=J,k9&`$K1u E7NvgE!d,eQ>}k6.!_sV"/ގT [͜fkU]Gz~^Zb&/wG<7Z,,:/} fu7V[p)ϛĕ[XkB߭~iV8/ 3 Rn`xYhJ>O:8z/}7PT[b G gͯ p\@+p 7Y~lVk㕣wM]]c|5]z& +# E!Ro 3KV#-ʌCĆ-LLGl0m v/_D[z)"Wf0z$[, ~fY!qxխpv[E؟zQwq96y-=:(#g5 ʷ`Ynࣳ[q}1`ֵQKVwj,>?^u/A)z"P >4 cDnq>\كg|كf4j*ڮ3cWvEK7>Ucq]4A;!̭E#xڧio8q)ӵ '+{\κU"p#.ޔSӇEᮈEYw,mqyՙ8/^n _Wg}ךws k~Qwx!`(g9F8[\Rm+ïHanVvATEs <|oG'_pW2Cal h`c y#7FJƶ3' gLV ~n9N>+ssL-\=ʹ&8+fcR]l>U~$r ቉Bu_}9[`BAsq)e;x5S”R\yw+l8ոp8Q"~W+ p(p/Am"аC}Ks>P6:קzYj$71#B ػ (l8xؙr ~F0%Q^Ƥ@]᧾ŀћġ;g8x ̬M٘آz X-ML1$|u?,>!3Y-hMbuW13K+Ɯ6lEXy ނWͦ! { [l {ʟ*lLֺgi^i޻Map^ߒۓ`wwtr`>Ⱥ6cŅdoAxާ_{grl`'?̊V" ?5s0'p'DQ8+b/*Yߵ&]´rl1f_pcy Z7FK7A`S;#zhT’JCZgrG.AٌXxk/4wvŎs=)aԪ-B}[`x\7z.*RpVF)z/{;vVjPߖ8x%G^{GIIt/|sd?hWdp8+[*~!W+ pr7~Rrʩz> `Rbs\;rKKo<4Q> pVnYXm֣bj?p4[Q=}u8;l|l1/F}b6F9KQwdы4ż?p2K $^um &sRP4PϮ |28K=\17ofV;#zV2ӪWuOq|}qKAuuW1ro8JQʢ[z\;'7~m,{Ew4(WAϰz<:"ĥүF #ewugɁrlj"jŵΒr|-\{oDg<܅.,1q,2^  ,"3߂%!#pRTkkڟ5soQq'+ `bj{i*j?}\b9g[{VBK8s:^TLU9rN|Lc45EAQfGCZvhTX$wE,ENp<;OkPW+ N4SGuRtk-G"^ҊE/A[;8X WBz#CgC  P $R̛Ytqs*f,;KPXR6UGK;l>[[e(Tl^hR}?`-$&G]+TȓRk@9ZgRMSjnk3 TPTvQm;'8SI)xYj@gڋ uf?  pv8yD9X4)cX<)w_QI*rTF)8KvfǤN=٦ g7D-iɔ ={\HGW Ks[>֞Y}YW+ pp{HVyl cDnCw 8KO#%7ڡG{%U8#ʳ_Pw3e Ύv&*'Y qfQ cb֨Ai ("g YM6YJ φz.'Νz=N$'"%QT)E J)m2]OS *RX1)/`hٛYG"gOHRF*S1*9٢m  !6d",=x?8'Ҫc@DW+ pLg#i8]ț(--#@)P., r6vA젭W&=X>ׯ/d!` 7+~_PRO IDATQ-zU]Q4{O,ފ s18Y38q>:K-)"?@vA.gm(u!笭5K3[p:d䬳=> 6|ACޘNFڄx1l9]lw։YU PᬮkBH:ȏݬbN ʨqMF8KѯĎ=­.ǜÑp'o\cp~^<{9R2Ym:[3?s+7pdsdm4urFl5\Oˡ+Dg):UF DFڃlg] ۩po6^rC|pr£1>9mST.~D ~b geg5JF\W+ p8>p N Ss'7,g$|'u،2/8mt'v\-+b9gɮo/el k1̫+^>)s f ۚrM7uZ%+.YwWw}X<7 p!:KՑ! gE]O 闰"gcZ0Ϙ/Z_X\tU8Z!]$&?^}>}28+ǖǚlpLѤ?055} j-C{p=8bLP'|v_4@oV>tP SsrpmgO =' 0}Wx9:J]z "8/[ÿβC˨J壅KcLwd),E@Ot6xcw4raOt70A Ƭ  ؾO}xo,@| yZwo>W+  SjD Q5N gun R^tT`pO%F x~΃׭58p&%+ puHgdVTY z(pms3ݿ"v3o0Yț p8[~85zm3d--ٶe`z Mp8l pCnW+ pc ]g}rpVJ @0ir(,/0KpjlQ6p{7yȽ\cU pI ce٭eKJ^Ƣ8љ9ᬱ RpRdVVؼjSjntL9h䎕{lٌ@f$ؼ]S+$6]XSؗΔPc XYbFlo>: p8]pg/Ggį Ug񋀒LJF8cW z>`Uvua|sY3yV˭tv4= W @ x:q8kOgӏ׮~89TVƼ:Ug(B@=7`{VPxȹ*1\h\yK8sg4Q/><Ÿh^!pCe tga{r.d&˪c qqdq+OmlY[ p\W+P qY3obc! *{MX<ǿpբr%2D1*q\ _<[]^8 9 {ȈP*s&c''p7 'If~+ i>Xuq#7;;7OJScGQD>R{# =;;U;3>Yl p\WVtCYJepu-\ySjT ͞2ѺYL9ZV2:~A, qh/Ke0rol'yu[8v|[uɠ9q,۪SV&gkp{Vpjq\W+zDSy`*tUz5pjZ.2s  _/;ѥu:{=41mS3fwC 8H9A"6mͬXoI;VvT6f,5̵-l-q# 1 ;bT?2ͫ❘ (}FMJebΉ VS 7~ XnXU( gsW+ p\#PY$U%`)fLMP\Rf)6C@Õfl0'ԷDRo<]u E:PTT5ǛZ۔;r?݉i \PT( P(Csƶlrތa6m4?liؖmlˡaCP( mooK|}>sP֠풭g/F'6Q>N5uLHO8Ϻ 8wFj޿xV5Bf07l+ >>T̷FB#J6'%C٨kjE052sP{iܯNwXO?B[+Lm;Dxm&K-ϺNAƣlpy>N ZvC4H}HU{v2o *:*ܠtle1`8kpIBV`XVb 0r%!-ԪY=\j}\I}c#,~ j> Z}ٖn0!$NS7QX[ȁ-t>JI8u1voX[aß8uel.MD9GSX`dX[;ۡ):HǀS} )8e䢾eMOWxeYve/{073_xvl5k/G* h>nfEtig `Fyoi%Wfӆ* ,kmW1O%®9ۂ`g΂`ܥ,g_r(nW~i>, 㼂JR*dMj.Ml787`젒:$>qwU]mxp5-.ZX pO"){]Ye) D*Kt3I; x| r !mv8>?Ru| D\=B~^ohVnXsq*7s)׿PĤǗ]U>Y>E^upD"ʲ}ȗfVtTߢ.ݥ?:8+â.j7rVV+pO!`XV`Xg-ƺ¾qyOqHq_{xn[jcΥLLvsCKxA|MFz.iOB 7 M}W!}nǥgJƴQAN`hԳīEv D_{wj$QR#8g4)mx{ @3n)8_PMl]-z =7( yH gKLz5g]򜽙ʓvҍ{x}pcX~7Ej}86PF=`/kH9KDcnva+%VzĽ؃SY-S]h"<^'9 G<`\}pjց Î *gkYbb%L>,<[elWT"U:,߱ݹ" Dߊ^kf\ .!a4Nd\ԫT&! *5I 0s#cXV`X(pVNrK!@l6s|=[x>~@ULo=@X|4MiE8?6 9ڶ!vFD19+(w'pfn&mzc?E,c8lOJ\g_Ƶ#Wx<-Gúv@Zn&;n0 ]=SKx7>_wÿ8@1v/Y"oWV{NǸnc]`Epᬮr**<<4V`XV0 gΒw]W:5 :&pkc ڣP&ڶgQ~'Kce@(:{EtRPLD\b&E-jPxΒ+yFLC~Aƈ-x6a~Lq V,а^mlZ ,k9KA+O1{vl,7^j]n&"ѧ-X4bg yH*@鋙Xbqv/ֿr“ <+sVu!s7P<ե" E荓 xx˾HQa!;Lqը> ^49za6pz+pXx!Yw3xƶ><8ԁT_k0D OTzş@jq_CۮčJ;o.lCz͕?cD xP/5}ѱ~+9鸐u {ROs@&"f X,̌kbj!"C]3{?ϋl5`~:#Uw~Cz%J@`: å{qak l+ޖk">hxr=gQlnb* g+ȸW+ + h||> g('YyQ;56`0%`Gej`:6RU~]b QG9ʦun~4>98*dn\ V8u&fM,>K֧Ok{Ic֐ #hq5X5Dz XP))Y|#+ +PZz0pVAeOβVR /7Gc8$,ռHEi@8[чSfJf@8|i ^YİݑOqPi;j.<-@@UtTAi>dGx]ԃm?= /o*6GQvT ], dk4Tn(٧9 Wӟ+ + <}Ζ1ͽ(O߲yLΚq/Ȼ[ul@MJj{8ׅ*l3r? YK5O*h.gK{ qM-KtjJ^ʼYؚ]e,8ewмNcYg 0ScXV`X-`8[pHajaZ 4R ET be+Px+xѮ5GeYV`XV(p,5A'GӀU|x@iLx6]cV17 m$?G٬+PihPud8oFL/x,\MhPՈ+x򛉙%l/GJ#nɎbgH$l]%nDz`r(WQWn33fXV`XC*p!'bXV`X*lb:N%'-)n2E @ R"7 {I G8i >=m;#7o*ŋѪfRTvu{=z4 yyyشiqԫWݻwԮ][z8#+ + T?2~V#fXV`*ٜX J5Y0:~6H0^V Yٯ; a|Fc}D K;7xO/'6=&#e [WocZ8כ/'jdDND'|'!azD%3&~27 1 rH߱px䑆8dcs3#lNF0t~ \Vc]Y{`xؤ7yΪdV te̞=/2ƎU8u) <44GԩSѵkWcٲeh߾+'V`XV``8pW+ + <R?ڜCfVS]X`?'OK`OX$]kEP,@p@dE!$(B IDAT=+ 9YEWkb}:S[5üy[oay19s&QQQ8p :wx{{… HJJBNlFFF ͛7?Dvv61am۶)))xcҤIſmݺǎìYpU8tPHj#G,W  + TQ2bXV`*zt^MIU&DT='T)8hx, [lc= ᗛЀp[x!ߣdTFs64 #C&U8!4k$B&O\XvxE ($#e7"(,Q*(, Wv+U`ii)B#mР,Xs믿Ƙ1cD(YXp ={DXX(hѢ۷O>}ȧ,xɶUEY>WL^+ Sg'ȸ( + G'K;[PިWnɹIhhw%cMwlwcqB<KgHb~(͓ 8Kެ!ɃD$Fh@4ܔyzQ"lUdA+@z8F^SUst(To6B~L(ܴosV W~|*#(O8;j( >nʔ)ޯ> (O˅.y*KYPRm kIʄs+ +TJd1 |@V`XV`@6?[g%.4dC(fU9鈏ބG>@bdκav`4I1p}b-AdHDpP <0:Q@-(KjI[ogSGcu3`#)g (N1 *$ش <07MyflDS5^Ua뤀tĉ4h#;w\gV:zh 6ŜEXy8K @o8y$V^zBL6MxR[YpEXѪieu(kړKY B+ +P& 0-[8陟AWvVb-Щ~+?y鏲 YL+ . o⎙Qp5"aXo O+}pv5d!kM`A>(sGjt8G )l߱lB>muD RMa2< 'C>:VNd=sPH,\1h/RTBTYDsx5[#:%VN({DCdLE,;&e8,c(8|J!vڥ`…8}'K tR gmmm⣏>~gDFFԩSblV޽{%K.aҥhܸk{=x!ɶ JYf+ N 0-[8;PRru.5oAؑ|Q7O1kTQ ˶u÷ ;̀V#8+  ؙ`M},~27!#_9󁳲Zw WPpzuVPW333?!!!SO>l[.lYV`XV@ΖP *ʴ^KnujYfhqRuX8]mٍR?4+ @+`#llw[`V]ᬾYPYV`XVUegfWPԲ95ٺ NIVWf]5GNޢw`_Z,Vo[Vڼ76_=(trRvCq!v8nzԴw}f˻˕(d>ZCU=wYWkgbXV`tQg3E8.Su`8[uG + +pbY:$>Q `jd,:P{iܯ1Npvt,~o\>>:݈Ww ZW*8;3e m09zi)RfW wo]㍃ACɅWdXV`S,[CWl7`XV`줛e); &P%$_Oon QDZ7Kuv7. vݑS]?g+{WEo>(\gm`QI‹u}W.N8{ >>91e? FFF8x .lK)oߊ]GW#W\NAƣlȸ;E{ Ycb_yp}l ַ0Z0JxϺ=Gq?i2R`\T8Y, + JR면 <-8[i㎳+ @T=gLS˻;t񙟰/>`S7r3B$_(q#61q/~cu{;W柳S<ۋy-K׿PĤ#57#8\ʾ >8L.ݥ?%;m>< "?~)iN=ݩ'JCC="`gv|~GBIu^V @Rl.lY(p,T:YV`XV)pbYy/w|)c*k.va+%V g(ł=+ӊ=g_k51O,$xSꃛ45q-~V*=g Ύof[%S!Qwc˵C%u}u  kc8[6/+ @)βQT{V{`XV`XV(9ͦ-(*8t+~k7ͅHD:+bR k@i6R|yΎq_ I_VMU:XDԏ"[H~p uP/)02(]1%\.(D|{d9s{PΚQ&d0݋`XV+pO!@_ gXV`X{*ŧgM!^2/Y=.NKJMOZ=ʼ\9;Xe?::nJnPPTɻE=kZ`QIXw<-h Z׶ZwP\Ӯo''bJR<**T @Wl՟cβ+ +q=` O{u /Ծ;@聛gm'U@~c>(x(b~q7j., oY#@E?aaFxFVD3VyYнa;zzN:ݽ7N /:ow!MK/˻K5a"!PHyQǤ6D-,lφE[Y"-VG*^;XV`X}`8\+pO!`XV` Y%">E8+ߛvVXoú8V`u<+ `8Qҍ Ӈl:[\6SVְJ {*YAାs\]?`XV@3j 0pl:[\V_af=YO}`8BAS-i<-(F.$:Z\`XVHę g2(yV11-+}V luԓlY_#>+ٰ˵T`(Hԓ:)]M:B+ :meff>Vg gVǛousykkXYOS_ΖfHGZ(cg?;C^CuǚHNѢU + h v1PK9 gƬ2(yV1W;kkXYOS_Ζr? Y>K_ժ=8x¦%:5hQS0 [jgbXVEZ5LewмNce5j`O 4*/ŜNcϟ:O:4rVGW߳a{<׬+~6U:hGVpBq~;UYjUy06^هQ-CUMYٓDU7/Nx X4?cYܯb-W-gN#lZ?+U$BOyQ''K;୳ּ/2eዸpl0Aإ=!3uIĬ|SMZGk{ĻGꃛߓ7 IK9o^q\O5]?]@&pVWb8˖UuXV`XVz*pz;_&mTVyNSpn^o,lcpЍ$*a;"/L"x=ۿ5LTEclK}n1+@7v~=sTMq'~ xaXwxEI8ۻ+^v腏bQ J`S>d?(i Ss"3E¢B5|* 4-~8G/XF[X (j,!=D6KjPU(D쁏KzUӀ&E@A$s D:'ia@u6ōy۷qGv"Ue5u~5zkL[w5krѨsI3?>{?BCzX]q}V>tO-[wM|vU:u=>ʮ2gjh9;hl l+ + YݵU@Ĝ%@ i^ Ꚛ!WKvuyMHUw(0%Q}jzT }G^c^KF޳t.7 [DuȿL{um6 ls/`,mS|!b ;y53_DtլcB1;m'M`H>}^@?U\M1yؑyUijST^,; b0+#k V0a,`.(U{b|BUs,g^IW~QAYDU`$GdM/g q-u\(~w$T6g;– &DuO1 >9Ak"=%XyYY5Wg=9rAwN|Ϟ%-ᬲcXV`XC+pЊr}J g 7Ki)HeY3A'LbNt,bjUp^-^m*z5v㕺Q& ap,=\.s8+[a[K< .lr (!j ;yuq*s;_ECy2F}Rbw#yxҘQUNUc_uMȬ稜Xtߩ»ZߵcH8K$vҷq=Dߥ,y8 NԜLs'I)ጣ+M3;BSsU͑*!I@6nŽDU5r?Mύ TT٬UDLY|EHNqYe6PSvᬺLN_uŝz9;ig yp.YMvma粮Ҵ&; <6*gsO66K~qӻ۴{.l&s%2lWVs(᳽\Sl? Gy0m;LP#ڦ"wqBVMeg5H/%^$/U *QUUD:n}lz/=Jڀy8kDpl<}|rz8A7 v!8.-7S-Ú`n!\h E*5ؔD^_Gߎ+oXj=_7G'Nf^*.6pՈaC%PLR"[LSQSRu]53 "RMܟ )p JV@Sxu\@(PNcM[&_յW]?*DDpUoѽ"Y6^V=пˏ,YC`X-UY1RT[َz#_A ps g jŪ:L TG}ӘUum)CL&F8{7I ^,ۊgyPoAϲJ+ΰjGofu\oi1y_Pn&-W/*MaJ3U Ȑ{6 l ձkA!0nС5AUbUVosqeSaf=YO}`8kX8CԮ][iXXtGF𿎯<$],۰>Yל[z 軎 g3zvUGT9@AAvmbYZ*c8QQc.[+vְJ 05,;v,ƌ_|QߩT#_" zʢ)1M:tlz^]rn *:2Ğ]vp6$vƚ-{a+$ @f}`7 ,ΪW`8QSWc.[+b8[VV'Y#F }}}vyVڔAQ]:/ZӺtlÚ*\1Uy^Tn ݳ gcqc}j 'g6aC%za x60U߸q-0#ܼ}1FMΐHLW@-5u;q@DO*Dty _c./bm 4zٲ`9sFi֯_:u;|2-[J 1zh<3xKYjvڅW3I䛛#ޠ5`uyZR }o0}7m۶%x(Ǐݻq-*lmm<6uP*]k߂U ĢEJߥK$iӦ9r$<<v.\ZYϣ"pVW{vCy„ s Qw'ǏGXXJ[f G%N:*5;MBH$( jsb`q4L P`; F)_G2`.:*ԦcH~ ]{tEu7%k>Kwz{^d,?@lܴo۶MIcXbׯ&NZ/RjO~\іNH\C:|daؓe!ݓ阁D3xdÖ4l>w",2 nps3쭞݋8aa|į FiٌNMi11!A:黱h~OQΦHEX@{ŠlH |0ѡ ch.@ %B6߹g5c=$y-ׯGjpʲR&uӕH/%/Rz{Mο{ΪS׮]:n8 81j(<ݻ_~e 8KbΝ={/{bQ ҫ唇<O.$im)Ann.y̛7Oj:Aav>|6mH֥PPߕuvC,WfJ"Y}lXg֭Yfu4jHRp6&&k׮K*icGUjWD jjB0aaDboMzzd,1oѾÆ àACӧOc{io]7n۷Alaq*~GeŴepΝAo-=D}'F=t#->FFFb,޽+yQWU!s gO"f=!tɉFhz}gcXG6DG8$$5uMVB+J[Oغ_ Pstb< wx#-AY2 fDG26&cFLTT*7o _sCg85YKi)_pVZ7}.AYO񜥛m?x<ΝNx /oVܴb^pAɓ'cǎUV?(%73FiY%K]Rh>uH.ݬ|Je;bdg/̻ߪ\vd9a%$:AC5=@PWS6~upVJUڢ.QVew#W_76*<4={ȑ#RHFiߤ}211R@Tߜ9sD}~Lzv S"ۧpଢ}w,1PءϋSG6ne$`LX Ē0%-N~)~XVoz^C:TDoXَ'dd?=}`c,sT5'#bQҼC瞏 z6A1-` lԘHDA\r>lݼ1vs;ѓr#? w(>NFXX,%>!"h5}!>r*WΖպ1/g UE?éZNKx_MWҺl D[8Kq9.Jg?3*Kg <?<OQKր^%%1#+Mt# 3 ۡCg)I5kK7/RRQz2A'!HIl@=MYCذ Ξ;wNxԧDIl\\!_e3ۿ,Ueeo9 eouz KJl޼Yxc7=WW|bCJ i}Iڻ*.R{:8+z< >ӘI D橾i&PY*G_@:Bףn^>^C:Y(;`sJf8鵹@8:#> #1s(EBNLxv'"8'B2A %PCaTtgbKP8FZˉ&'Qkny &ki8-k}]7]J %@GpAUKd7GDXEYPz,6%y8KS|g|YWlyJejZ\|M+~ZpV'MpbxR,LuArdi FUq*=_ʮ ZI!Mւqlo(yM)>Ԓ,etx,x#*b2{RSSݫڿRyWEa ;lQs)T?R g5YٺY]NL1Kc` 2 4, n~띍 ‘li^"D`ħd  wi\8*a٣(o6,"Vo@Tbra[A< ƀpFRcW 닁ǀ=g52F5c'"Ҹ_JGA_vE:Z4Ncϟ5K?dWxJmL:䩎GYƵ!,gxYW̏L&kO([tCC _e3v|UgH)QB\"*Mp㔵mCƢ˘Ik2z| vجrԝXOФ2#_Q3;:A5RYu>>E # ޥ^mP_vGSnh+գfU>Ӽnc|y"h-ˤɘTkYi+"R@%heeÇm/eO{۷fi pz=@+y;TXy8dp/^,N (AP 뫴GY$=,ש.u3,{ ΒP ($:H_V)/y4\ruuѣѤk:4Y DYa{4t(gƍUYU@~z bv;:> #!o/gwQ;|q,t ae>NIY눺jJ Ghdv( Vu4'$"VoB\Lp-wYR)`[sa#d(Ӑa &)G|-UU %##ctl^ǻG,_'OYۆ'ƬQ^sv~0Im{v=P =4i_5Rda]sO+ѕF:1e8PUۅȒ6RM>c\ø\&cResر&m0V"YM\u軎 gM?tEt%<;?z"ů SL䁎%C"hQg< v5hs_菇CJw5`h80B8}N4ٺ ٺ٦]=g5;eU.f3q](̘f0l ,:#s@}Ѱhc_Z,>NVvpYqʾgv-aՃvY!LKu75'TͭM)k_V{gijb汕VUIͻF ]OھIBzJw]lXuA=O=]QIN/ a[Y4[Dmu23b۵xͱ?⋸ߊmM z!Z?WR9C\wՍ4z%m}:]Gسjc((e0mW_ m {tDΆXf]({pu '8[Ǹ1p#7]0z]<]WyNSpn^o,lcpn䊗z`bTCBؔ r%ᬅduplr eTRUN^TUCU(v*a;"/L"x=ۿ5LXFҼ-˻~ IDATpWzY؃iSR%?&=H ^w)1-c1]LGn/W#>+Y*Y9`x=l'^)Vy{Zqurf8[qQ~ӸȸEa/qu}i=Sn0=crlҘUKK)gkwcW9Vܸ6 +{梭>*:'2.QQȣYQv).( foV[TDv_(W|tSc*ZJGXvWy] 6vZxt/zbΪt }3=}.w{%̕q:?8{!$e.S_}XN|KյOtHGJ5d1+4DWԥ/Ln %)U:ӣ{4bl]ȼ&qV+&kGU{3%eIfY=Gra]>Tk>K U=r<ȖWd$f3*Tuoӗ]3}[%JcEJwUq/7gZ,nɽ+kEoQPxWSX-xkJnv-x-8KRIͫ"súU 6|t̜$y)㲒CY,x~Y-'Ln"iU=.]4e]|pC-KF@qF8KiA%̕&RuŒ$~ꢗ}X>W]Jugua-[TLkb(˙Uhi}|!gr{ԕ9K{b{ל/I=QkzVYս`ki WoSdp&n>{\ ˽/=J\A_8~wI41`?)_}2-לbCMћǯȸ8ތ]g9 ^h%^U[!5 9#W8Kt`uIMh_Qq]"se}DZQOr+ч,lRmSy)KqY䑵!BarbJYOG7ylqX,"XtlQG0v.!2g[7ɎW}?ڸ?]gq`*8bA"2vI!/ ٗ%ɉ*{cP scD].ZۮYPηJY}C}$% ?]z/BiJ:>k%vl_bnPWĞ(U_ѐ{>Q\U~YIڒ{\ ˽/,a9iRBHad$84V4`]g >/^` p$m8`q8zפ@~d NtȎJGE)jǖ+!5;_"RXJۖ|^n8xOM8T{ćV:0'" V1R$>}(Vtp,׃7#RF(=NJr;ƨXVQ'Izؖ,yIR+CZ\tW꼓u*JR*GA5(Nʘ"W`SaE^~hB}uhKɨA% T@tŒ8nU\8+wV}OS@'rmI>RC}^+XbyQDbhMoUk' #MTjvJC:%KA(=%2UuR~|Sҧ*sʆ.5De*BsT#Unh W+YA}Aמ8KBWt>ɷٜ}H~⚟>{{Xq-ٍt}1$@Qb?a$[RMx+g 3ORT 8;5!J, %g逥Y렓īvH8K}+ep\}m0!t°xju5W;q7etIK z6k<7tS"ʍ!E,=k34sƣbVHf)rEѣjuoAc B75jjIpZ3ؕBxMQBD;^/c+DbZ(@%i/%x~si;j8qVW,tzRvoȉr.ߪܪA4Y}k>ҴC}^gGcۣrKtle(Ȣ?/uJbS,FYDJM#vXr1sR#ΪAS~Љ_"ߥN]1,ˇtho7ݐ\G5Iwri>~?iƪ> 1j^KLsb+ ö`9⬾YUkۇqټ$YlzGߛ_sRWR8X-x&`L,C=gޅ/Yܑ)?ӹY%ƳdqY㣈G`L 0&!1W5`L 0&@Sťzdcppbv~~~mff&ޒl/xncwN95`L 0&:qL]^`L 0&ZH84|`L 0'<\o>j{G7#;.bC|K񸵜=ѻJk4+W6c*yCg%}Y`L(G䋒7&`~X5f`LH "0n}Gesqy̻q?n7?udq(| 8kd`qc 0c81}`L shsN5Ƙ ǭ^"kY5 w.X-^50/yLX,MqիX~=+O>hҤ ]EoO:͓\ɓ,Yp_&dL 0'Z Q?OHKWjg*%%g[yQL" n^,09gM'ξ?J(ӏFѰaC̙3Xl9vv6 kj3::ZĠAsn tͭtn`L@ qqZ7P=ZWFeT :XG>}Хb?q8,* 7b 8ˑ`q=3%YPϟ/2]]ÇǫԿ1cի>==6662g'N7n6K.{gVd9R~u|whڴ)v%X|h׶m[ 6L=}⍋CڵE;'''[B`L 0}HwN|*j 61VGV V-j%q4<0o RrLgq$eX-!Qü_~­{Xm߻XdUУ_S%Lmw~^[Oü@ϓ.([o,ꍬ:XZXs?JK߇~:u`ӦMwx]nnvL 0&PPνl9pf}H[ L Z!i* @^,ϨXz*FPBXKeC71HzR$-%䧱,'݂قcmL*qsṈOK3g`Uzx6LȉDBZ2 \L1kyQo,m 2 gi/ R9*wЪU+`\tIy"5222欜@zY$6n͚5'|"!qFW3gW4*% _nBJGtf߻! ykMuCNJ9k>c)2N3P#""xb 8P^$^4^ҥ .sM)SqdʎkBL?~<{=׊+`mm⬱L 0&8{%: {OWé eЧXOʎr7rK&3(ެ:T|8N'D (>i6S9qިk KxFXgsZ 2 ـQ_p/!`B6FǮ@ ]kbbr7p߾&^cb7Y-8+eS +[LG*qxFHZO}YE31*p`5~N8^䏹7'ԥ/.`v!,ΚO8X⬌ӌg GfVk3g^^^:ٔ7$R-e.ZHd*go߾-2g'MgI\/s_&Л8;kJ Y[zobƹ5xD,-$gop+Qި_ .|8[tULk6g -+] MA3A~6;eyL?Zuæ3}'p,ofGk~EyHYq3=;]ixv<⬔MRT=Rv)>+cq||)UsJPrr2SKgmHJ:ֶ ) G,ΚO88W$a]t=zk֬_-2\I`2$2VBRDo4P- ^:|||t欷=v온W+5܆ 0&$ٿƟr Xؗ>qmvX\{)Rv87/F4Yو,U@rzdYA*8P>qgsb G5碤=>o4L.tQ&g*i@.x~b6[ZfSZfV[yHCu"/uqV#B{,Κɜ'RZٶ|?RgЯqu#ujsXrq;(@0G9+Bgɢ l߾n|Mq8`v֬Yg}5kM:]tɓ'ŸTSVI, gΜ Pre1BdJm~w[`fA@`֡@U4Z#g%홀g_8}iD>ɵ`\{xGC~%^o^.ywΩAdi t|&^&"FdwVTcE_hesQۑhgٴm RhlgǏ*44pnH8SzUmԌ'{ 8k>RgeW⬙`L 8lyd&PX-L3(Axmلb0v79O2Ӱd;TԒ*: q2ը^쏗܊HsWDMWAl0*pJۖ|^q=.%D|[KgMg$l^*0P^lj8?1Wأ8[P>>"%fdg|?g+& ;;[T3gBQj,E)&`.RPq1ƞF$qz(U 6ghw"111ۨtNBĞ W(ӝuw³2ڮ$DێMwWtM*HmsέYUӭĈY}᩻ Z`p8 #7aZ&0lʆKGVvn<ņ}8pE,xT.z>kϫ8ܫ>:Na[xKQm*0=so@xҳ7Kٷ%\p],WޖgհLԶ5 ެ|KZO2JڣmΜ-Q,৫d%З4r{8KkMUϜߏ~ - %8k>n)2~Y j 0&'k[[@\c=sЭ!eerq6f< kw4};Ԃ4K=spO4U6I1܌<' g#f8== 0rj ̧Q?̗C,C@`q 7 0&3!(q*8,rqaDƌAΘ~n%&VUb61{0 1=k9 z, 3z“yAp9۸#yy IDAT jY3:,BfnxNj7ah8m{*KnT@V>` FPo >=Akz >!yF/(k`Z7,u}L ".B:`rXeq&`Lp T?AaA}8 j벯7)oü$K$?ynjLyS&y;f̏G#C (uY:/ qi̚&S'k4Z J5q5'7 skfKjOfD@̟yV6е+j+W-j=L 0&0N{@%j,~x*???633SVVlҨ> M1QylB?;5`L 0&t0JM:_lN]J{1XUY}ip=zIQ1v{jMskH¹K!Rg''Pg tgot䉠ʤ՜+/Y[p}=d ¼G`Hw#z ٸ88_dy\&`L8[!f<bI"/U:@u)yۢ#zGQM+ɷ:v@CQ%Jۖ9&LjND@T!cϬi-Ωl0[JGdd2=P& `mrPao!Sg -`L g @M<\_dQdPuT;_%ISY[j2%l1nOu􇶋cd_4cqH܃%Bg@5=3}@òfa<ibJYO1&`L.1el= lłO |Wo:`疻V)N\.-1UhI>} 1b ՂkNlX8[0&`E&gCgObQ$yOVh( HJ|f̾Ì}9|J708$ FVx[m}٣)~+z8-&YLj/6k,a+ eL 0&̆FT{zCQj:³#|j1jÀ@b^rS-Xg jaYm^rfK*e bmų>.)d~8 1hT qZ:tAv8$ ttoXp|(%ovkve Lz 8k^c`L 0$mCh_ÉwS'XU,a]j"fkK)8^s6lL>9{6sƿo6_{6zh)Y=`[b&_[5c |q`r> GC0^ @u5c_^bW lq8?C֣kM 7y[ 5!|Q 0) ]jGqnfܾmIfzb+/G`UO6l#0*X[v}cPq_ s)] 3?\UOh=3; 1>!+]wvb3gj$]B̓0&`fLY584$0kei̬g6XYBWT$1mɦKƇox%E >x'ئQ:VC**!r^ DbPߜhHf ~F[cNFt!eFFn oˋV|Fk5%m쑑g_|gg/ ۊPWNJhVrUOGFs~x$>n.$ҭ}(!3$xq~\|P7)O΢k V.Xq֘ 0Բ#!o.ng~ P;4KU,\(3^⬩\, 8knc`L 0$gi_B8ZO9܈y1)cak=EYrK|q4$#?`5tF钶8r֖ӫȴ}&-Vx'ɝKs~=%ЯC5#3+_|hѠK2sVBKzq} VX['G\%bBdbPyg螵УMeTT sמ݄(dF4̽i&,-:=KHL?Oҳ2@]v6 ?:3&s N!0.L_4.k_Ȝu3{6g?~%2vV}UJGXrq;x4z+ KL/l!Xz7h>!#_,'::laZG.|'NŇKEʉ]n0'dًqh`@/|xx=Njm|4ǯöYET8[t|p0>g{GBZ2Z7[qvnUճ/Z;vG<|5^=|/)k5$\ijR4tū) #[Y5%Q8kv.c`L 0&g^w,AU"[C):ۡW*畷- ˶G`Ҁz! :UGr:Y';oԄ#m@[w!n?xG3Kt_9[t#fS2P8"KF- j%?_/[OvP4>CgN|*z ;e`aU?amP~7svKPPxܛds X[ڮu{ ['@bط#_GIpGga@sqȊnaZ1P'~ô3? :pwTGW}T"L8^UZ q6u&ή]cT3s_p/f$9 7SDLi]Q<ܻ3&zVrctn :(kʜHij ]% X|K@P*j7SL 0&Ŵ;,Ϊ1/ٰ!6Yok+FU[ J; uq^ 5Jc[:>X|~0ue wcn;p]8iOЭueS] ;Gc9s?t[Mq֧zi OĀN^p*iѩy\쓴 |3<~u,"oPEmO?Q" E|Z佳,e~yW!piwՒq46T;oCW|^DhfξNsSoJH%C_Y:F5j7F7Hq- GM'{b)HՖKu fFhd SS[s֘PMYD0΂o qE/t6e#;8koe5-' 1NjBHN81jԪAz KꗿkM1N".U]q4^Mk\$y %ٺ gL 0&LHY-0PU@lFfn%n+o8 9 KƤV*ӟW1i煫#jSJ,jVaVSV$n{:Vť~(][zIݲ9ug.qD}XO׉8]GDi2 $(.e H$Ȝ,YuT㳫%mRQȊt,UHe'gViV:f 'E}Og< (ǝX ΢V+ 6 M$M9 S@ JV`͕t3oZurjR,l~6X(bu,b.LfFcYcC]m^.#1@8ӗeK8 m~Kߞn}!AٔuMJl/nD|zmc/c91^E5]q4^Mo\y &YgL 0&LDY- QM{nb*m|9y&<c{)ui8K}8v_k k 2JFJPt XTBklKh8|rM>'6}Y|ؿ:0J=%?캒3Wѫ]UQ@4)k ÷N6Ӿ8-1 ZC|sךWU8=# X gwYHԷ,0NwT.Yt0R^v^UBZOwS9H\]u.ٙ~¬FѠLuޏEJ.k>W~Emȥ&B_AsAy2} vTBn4T}М\"TOwbrL(( ^?m7:t]$B>yLrK'FuqJOll1Ɵw'戳RurБ/r۴M6q~j9Idcӿ:)~uJWl?+\)W?wZc\U!'JLW*Tp)XfGYs`L g@-DqVݚE׆.ҵ8Z#[1b@4g1,Hq~0RMs:Ε=/DP:,=;SFu=^.SC c3g(jdqb1pY%M&lv// 0&PH٢+*ty73g1P48d:kc ?b %4|i8dlM)o /SCB=qU6Lx饗F+FN0&(FרQRW*mзZxbqY/?./o {py~ i<53eqg Qa7ݩV(&[8q׮]Ô)SPD |pvv+?>_.~gܹs;w.[n9CN<wO?۷oG~ЫW/^܀ 0&(t?\[oێŠcqV BS5^ՆI@57ZKSFnz7vԙ673S߉Ò?l$ߵ&lPj9{bIӱys(%X-X-a ,c ΒÇ"Q 0&(H]}lP]C:c{ۙ98kgo)n.*s =2h-&@V@V F.2 <ؗ\ :1N :wC02f鐵N/r|%KxN \(|;V6Z}<a; (Q!moթ/?wO,Eߧ?[rD(k_F I'I¬ i.8cۍG{E^+FkKCeG79[&CY?ׯ_5*8KeHmٲ.KdggcxƍoŊ8{,/^ K%^}U9{-!W\1xg۷o/iӧO%z*Nw}͛7Dzeĸ+L7L 0&^XYkLLm ]3V_yY+gu)3gi@t>*oh}[02QtsHfG`\xݣ#f"kzqluV gI$vXdjU5g]3f@o>!$._ӦMCÆ %h8/۹sg :Ṭ^stҒv=L>M4A۶mQ^=88wHA`L 0&#M}"bpwxʱ8KF/tL-}v] ~p'`,SJְo ?̨/$ƏWDt=$%3 5S.vDo8FtץH3/4cY~3f Hq ئMu<\?sA-… 5k 7x#G}xY&ت9b޽{lVVr$DSY'O=z@>z~y`Ltj Ghv;n4Zi3gu!?YӹGbL 0& g#y0FmѢv܉ 6zxg݋+W>Cݺuszmʔ)c:t#Fڵ_}"q+8KeFmvٯk׮a۶m"xժUl\`L 0%MUk?& +? IDAT{51L>Yy cqقV 0&FY,g%j^$&$$5Y,\\"ҦzTw?.^PF~*XKLb(T aX={x뭷D/^_V8ۮ];I;lmm% ?(lݻw9::бċgL 0&Py2ܮٍ`鷐m)yN&`LX`qX, V%(tݺuB$TZvmakwAٲeEI[5/|@pp0?~+[nh٣, {A;zÿ;9;'1z8uꔰ+Q~ 0&06q* 3~C-[k?؄3guV8wqo&`L !, M@_qŋgL 0&mR#Y5@mB)^n`L 0EXUW,W`L Xy_0EYg_W`L 8[yG٢ 0&PN+{!|jk ZN?y3iLNN?R%+33eʔQY;SC[Yg%fL 0&t08 Wq=.5jsauZ @`qtL 0&I 8ڦNy)nɓ,YDIsn`L82lXw$oyymKbO_+Si2wwQrBg7ahd@E $F_GtbP o 튚R V'ƸוMKSݑ&X!fR&NMe$ >^CRjڳC<;`42=ѴI欘;D2'舑O8wdtvg%gqָ{FP[n )[12â8LjaT/uR,E`œ$4)SFq?pG)1}@nԙ3g0|dddhuxWulvv6 k[ih,[ 4hvvL 0& # !fdfap(aҥlM"Rq6 JU0Wv8?‘{RYj#Ϊgoʫ0ϳ,UեPu<?Gctg꙳N[3:jߊCjY+2ljlܨl\g X/gC4? ,i\ (ss8G#[RXᩧ8K#૯ӧOsѣѶm[EΓg/_.'[UcǎaÆ x!7n,6mnܸ!믿jO2 $2բE L?^[[[DEEaȑ9M@QִiSڵ xEF1I< &p)ۇm۶`{grA5v֭uV 4K.if͚̙3Ky1zN:a8{BbfW/!:R)Μ-0cq6֨pȳx)#cguLj.BY1""/Ѽysb8{:uJ Jp!Ȏ1 4v={¥Ym֬lXL'|"1qFr<3fq[N葑믅`L Q RlR;!=K{BΜÛT Ҵʡ* ?Ա$܉I]pNAMؓ C]&U8X-5+`/8s1,>͍(oqvoIbqVzPqvΝZ-j8K}({Ƶk@'SYHvꗿl.qeU͛E62 t?^)^V_ [Il爳9Vx*?C`@ΞF؃hMGcБ/$E+,dq6`MnJl~ln^ө6x[Q|hOxK._KK upx,E"CߺIE7ay+e.c4u\ǍmJIX 7)[4yV)Y7E961ǭ׹RSk #}b1 b*c/]+_9a[ruW^x 훆,CʶSr "(^z- E YN e /Y}h:؍J7NTƀ.=)3ڟ>}Z RCRqVeUewٲee]Ke =Ç8kaL  qڭXb.iާ\{j;Ժ>& t ǭfq⁧,>gxǷv ")eK8c`WPɡ,_,d,Շ?|(ooH[OJsT>y|Q"Eq򣝦*ABVF![[u0'd“e7V68[ϐ!>9REׂgM)`n=FJxӇ-JYu8T):Vl5Dدi񮏏t[JW1 J5D3wqL~`7087mX!Vل8_~ҥK 666V"tɨ\2V^-Dɮ]bȐ!Xj8Um)0`(#@5j@nr QVmXXXNI K.T@ wQr=JPvS'8K蠴8Q &&&W,gsp{&@!Б9"ⱞ7dqV_bܞ 0FusFJlΨM<}l~7Sb1ѧON ƫLjg[G\I.lBܓ-M`\zWm۩/x^O(U 9erRru0fgۻ u;zͭk1W; t %^Ųft Y5_>[YXbW9z*u򃷓 ƅWHHKm}p]'5>e򒟣?Ι.Jc?YNLÆk1FGxfTl4 ާ&ƒ>3{kV:OHo|j-hQ]R|U^k龣nx_?~YfG#ךhs2gxK]9XӸYMp,:j߿ݻ7o.)Wt֬Y@5e?3;vLk$RVʚe Nk.]]ɓ'$J {(gܴMB_|7nvB&TڀLKL 0H٢ Oq>P/cȀP;^?$)ΖV0)h%<"=nMI<)W^cVp)Y!?#;>} <<>ʙ[ܭDi sB6 AW#`vzsS1UZkM񨭓6Cæ! 2gIq:!AHL{(ؙERgsZ soUOʚͲL˃#lObr~"ۛDVuaK.6)ꏄXkZM»'"3++[|!GRř6[4oFuQM)dzިk KQasԿ8pY!%~b5LY93+19}g>}ŗWuRSguqgi]wm؃T {"{hRV,TunE-6o<ůQcWkU`fO"cާ\jS)g-77} SA*ֶ\?}Y{_jo)zҵtQ8^䏹7LK_]CĞhe'wK"LX{Y`L COD\Ceǹ= =TJ8SG'NsFʝ #ξ -L͋ǵ,_?][6sVTs#j R}L|BRXtqyMI"T}%Ifu2sgW( kSx8S4wM'1b3l(U322;$\wF2U^w;a MA3E֤5v~Asz4NpҬ5(O.JIT6,P$պ|)jƳzl#\"Ȯqq,.TqřuDjwP|MJWŴo&g -+=Y[H}|ȮV՜54sVj?Q\\xUJp;6JjJqҷJiˢ&c޲dgLQߟho7HOGd'U~vWqj,](o_Fۙ~v-~k7 =| w83MqVj#]*<bM}}Y{}FZc[{}V]OږDs}aF.j9~gK%8+%GdL 0&`(k _@\c=Ր55FNqĔ5_4/ʜu+Q:!)Q=6Bpqh!+$ΙZY$WsQ^, $_']RYzV^7*-8K뢬n@" 6|2YjCُg|_. vTaFJY)N4C褄78+MM'SW'4u(I%t~n5Ydn7Po}UJ9ˡ.T봄A >&' R}Y9Pkl+}ҵ*qcœ2ꊧeh==#w.qVD}J}'!KtK&y~Oӕ2e('/~s:Sc8sn`L ? P!(fr*8,sĉr8KHUǹ2zWm-m1fOqmIj >8 W5RWLCNÐ_ VTWrwgQcjj!})۪Y%,}*m'+<dP"RV)>J%Ζ}iD>tp`h, g4-2uWQtѓH!$*.EĂi@DDP@QQ+HwH%RH/w's|$9ݝwP8Jr?*/wjd?%LmFa5ٽ8M,ERNrR_JiA~|5}P޴Jɥ5PSL( }1ݝt+7?igiK#ԟh=d3q?xE3vjh* 8yjqV 7˾$E@I$:G#pJ\- V})ZӶC:hHJ"t_/ aށ8>Nye3qr R4 yh!zù64 W֊$,])XQ澅#g(!'œNq*| N],ҽP6L!{m\1,Q,"iKH &# qS$U: -7|QkqVM%Vv+'?'nYSb^UZl?Y>7$y_ >>L3xF [ŒbQM 79S /0:a9K(Ƃv1ZfrTRZ7NOz32T *nunbS+{hNNe)(3H-@. cuc[d&jB[^)FvXrMxnrT#rRq)V|4 %qVK8+tw\U#p8QHvJ%FIpjq&/­x*Nk9kĂm[ rS^ag-꽧XbU5r4ѿq;.rqXF8G#Ћg")g) ZU7t,Z;x!<]>KX~Y陜f-y;^q\Gczk#go#򎋳\5Q5G#p"Ye #2L) _;p3jr\19*GY9bܒ\5Q5G#p"Ye .Ζ)sr|:hx$mu|g՘9sqks8G#`4\5Q^B\ vUR\5X|sqVO#j;gKXK 2v!ngj!6c,?/C mR&zUnrށvs\zIp~^-99#J2/K=c'.rqHyY5>q!\-Aq6y'(g$^9pZ+yd%ss .+_otףXn7% [EO'0]5g 7Qz+Ζޑs8G#G>L?k5Cظq葟-.+4ߛU4#߳\}jg_O HgNz '>:x93n\'kw/ڼhf@\ʼ>vsmz8t􌛭_B97Sܯ84\쇸8k8҄gKx_9G#\@Hq|"gy1@Dg;@-?ڮR|+b5?8p?TCmF54A?4S8r^5Z+uc3Wϙ)MBv9i48kmy .Ζbs8G#`\Hq$ arH\$5Kp;}#)c\H2eDԺkoƫPnpCF/% Shc+vcv+dbO)nҰ8?0g3uM5gm-#WE[ʇ_"w܀4!ns˹5\_FǸ6xY,g)u}Jſ"6<q5K0jÀ@.:K9bC″ Un@/]GM,@ q*v\?jP̸DZ#(6\oUg(?l uѡ^"7a=@B)(Yoj;w↜5L} +L#2!~ -^8k۹"ܕj*AsYZuU.r~Y{\YTgRmJRRn"#+ w 5c0Z8v.V:5=3*j  ܓѦWj&< ӰaU4D/T/ᷭBz pSn&6>QuT@OF'p 0 ,0O {w S~`Voݓ0b'u}i+5i ͟Ƹ=_Nemv݇͟AźX&a5ѫJ{Lpjcڄ߅'k܃pd`ύud%2:sf6rc±sHJь0DgTx.zSށD8\E|و3dS䕖A:_dk9=~B7+-]igંD9e}]W"Ǖ\U@ՁlvN>H$a Ep{u\C 7gdeaHà+GJhGQb8zqۃ|<, 2bS7ݟg0ih#S$І[VQCa:WX/"r ٿ?9^OcFy`4 NgU?WwQd,9aUx=ZndMԆUv#+~a;9{h^'vzo'R. jߏ#fѬ ui!9#?mgm5 <x}l{io/qV͇hEjmŀsq5e .ߜwڟ9 bz\փu]_sWrqVUԫ<"_[Dž#r:.߆ q-9}Tcݒ]2<=p,!5*aHϚt=o@o;v+`#uS$a5%=Oā71ZJXi"uBbAs gd^o7.a58rsۼ*u,JVM @Q'!hĞmX_Et%L;=YPX?KvSNРhvqhQS/)uEӊ?zEN?EU7nec3阙?=־EחaK_HєDU@lkL_]Yxxr;67_=/F~/Cd7\ǫ1R8i]IY9UjKrUnhV670}w&I}Pqqh|y|5 ƕ*i{jS5"%aU/=Fy.gOWZXU1=r.AE/9c+8ُĥ,JkY h#%=B|лKԯ^<eZo/w&^oe?>펯W@×+Bp\50(3+3~8'{TGlTot/V؁w1G DK_>zAzI(@[u|q, M/n ϖ-uVP5(Z ơO0.ec2!N6xix(-Ea摕Lp>25q6ڿ61LeU &7y Sũԋ,%ASH|tpN],~ k6Tڎoi7׏nH,mhP gY7w~;@P{͞ƢS0LJy$@N/]If]#v7Jz0ebHkdgcRAn\˼%)ΒHl~wnOc w-L }?^=nalBZnP085U5r&Jrf2j<|,|%,=^؆I8EM1j>> WtJH5[kiCՋ_Uuwsn0p4$I|=-g/Voۂ955GycWjnZ*wA1@Hovw`)v 1iQcuf8 -E[j*Y`o|\g׳q'm"ogڐZ|R?}jXոX'8m O7\ȸ%ƶG4o9:w~aΎGH/AhLܖ*Q-υGt1-Y2ri|s&P8kfn;_8(/Nok::8{(h.UбITXFΊ+KpKIh^VmJī&gܼ|,;}NrqSRvE.IqcE(hyW8V{ΔFv" tOZd(/$ Z\?Lz/ڍ[N8Ixz'_^ݏ+;#o_m'Ux]zh9%*O5ACMz=3,0j;꟔8+_\i:o&`Lhf/=r+~>XxwR9qRb u\Ƣs-/{u_[PyaXcZZPE+p"g:/|skg#|IQ,JvD g䧭$Hٛ|_S5cy̮i%$Ig~J(8KSϘ9K"5;S|6߹81^!o?mƚ|?w4w.d$6˲8kxY\ ת ZFFD{Hp6IPĨ۶a)Ɠ0:l$Fmo/ӇGC$#\geopߧŶj\\qRW zWtnOĶRX`]uYv8P=|&q kb@8}1EwhT3$#nIh^7@.8U;=#8 C6Ѳ,!JQ kï/`fnl 2 fi}"-+%8qU1ѓl~k$A=|؁:$tˇ~dyA"gIHܡdw~GыEV*/x5cTCL? i,3\JvY1Cw P+8/ltB]KN٩o/b'і~Olw>VRli{GY^50g-cRl$Lh-gx+WMpSjm}U5r@)_ KBDQg#57_Ndí׏`hmꗫ"i{˴ۮ䋴HZڰ@0e {/JQ~a,"A1QՈ9 o~}yUG u)~+uxщPB}hv}B⬸MPRXJ-1z)чdY)Y3~_=~hy>-GyaH[ʄad*hUAID }<G1uSTOR"[W>U;bF?=^(jUb]Pn+%~q'‹08kڔH\^u9ǔr", WP/ Yr%hrqD^. cr:D6S5e/Qħb#$-mL_u( >qҧ(}T0\pBmݐ3J}J>TzVnS +*XLPBh9m_f~q[tIe9+g{qK?zm{.^urj JRY ૒=T?5(`||GcƍY|Ƚo66wY?ެm8P/eGMQSWJ \]I֥ŨᎯV@Fk&RXJS0ᩆذ2.^D{[XܾSY(j}vb1;/ir% cY1f\ɼ1p˔.3QdeHQ,w\[b69kգ#>dvpJj oy{ʎK gxhyvY#g^o(Rt%Jr"Ah\<K}RX@It ER#tg/6GssCØqrq$fC({M0iH#S䮥8Kcrjng;5Ws[]%ɢgz/+ <&rdP>[tj]JX%5+۳QlTGP90E6vlzfPN׻BRJy#GKv1&O7N53 *HUݙtS A_(h <-%vE 8B9*bW-vUvBd|l]HХ3`?/l?Ekzxꋹ'j<1k"BJ]tORxLr+pP6Eq"ʍJYĽ Y?oe ]<=L^q|VnCgrMUCM Z0_/옠ȇg,&>Ӛ=7-(rWrm}qqQh׵b}}tpr jGrva-.{?86@qVܫ!\MjaHZ`0OOwר7#U#LYkEDJ)@`fٰFFa⬸=g$R#eDRKqb{mH!6K9g)2I6ĦilQL? A,]DUnr Qώ|TPna8KQcT#x3%>]Y:R!DZFIaH9%r8do~$SP}<)M"K6w_mu@ )rϒr<1!N884-Ծ-\d^%0oK2mv #D*Gܜ+Ζ#iKmʫFQD}l!_&h4[/Ѓ }t\ԨR'$n7-]8?Ir~+g3F5gm-#`OqEy!ӦDͻ} A9_}ÒS~K72_I͓劤drFg,EQ'~c[p)8Km#b9iK s=Y:y)wno<{~L'9gXHp_ J6( ()`DvªW^!.VrJ^t@hKK7$YǷ2FO|RSN79b)*O~&-'ldML} z*w$ ;}E?* 6|C%A-Ů}?-Q.w?n>;B ]Lr<X[>rsn JUB)/,Y/{HJ"tQѯ<^;+זا*^nEօ`ah$St? k۵!3~F8KNK gx8‡8.\Ux5RM\\9;I R;PXK >p(%Pe`ffK=ƂI`A1vjV>:,q`  /ev5`˜R$9?m#ٙF#ؚٖ_]0J"bp.2JѮQaLDՔ E<젮釖aʇ,* Ix.cy3I,^^NԂ.h݄^:qSr,EMn2<|3__=Sf[~8RXHÐp{5㉜ J't6BnI c,W8,7 }<7v ǽe  gmC<Y]<rRTk_o=֊4VЇֺ>A,H'S/+@?EA m:w-&8:g /1A"1ӯ3gg̠35?[![t}1-GLl~O"זT9ۋ灖B`lkv h}TV?UҬȍK gLj.*)f^ g'>EymG#pCƯ*#pq#p8lqY9&.f9 p88,0hU/_U+yt##i 1t|Wp>$-I]^Sagg%g*O%gK jX۸m rծ6,_a \5k8c-rN:7~.:{~g'@5+\0k?. _JΑhs_}.rqV?k EkPQpqQ:\u\Im\qq69jWwD sqYS+ǶkG޷dF|oVр6_^n<}Τ]}zGV_/\XVd+f:8ʔ9K`l>:F!`8KbNRvт$\?{Tj{b9fU>l ]ދ?.6o?moFv*:?PeT 'AI\q<ng׶Pbп[2f)Q־ńM ;OFrNܻ2؈xJsG8+noI [K9hg Y[xmqKaXuI>d_'#5v{YKD GS!ӗ*^2yJs9B}ZE᳣xyT gڌ%#}C5 Uo]÷ 1YIp榲FL۷/kd\57"eG =>'1Þ]sl۷4Ӹ8[h7%Β9zxd|xG\˺!]ksFZQ8$YFn4?pb$tR˙EeÕx|~t Phwg~Y7+vc0`TEX/[n jHNBðZ!/-P;Z#U]`Õz0vҴ|-tj{)FzcuשkP<+X6)qQKIX㓜]I(\[IF;[ t}Æ9+5whMi2mջ>=%=“D/%_4_!gwK^S5Ey`JGVhr*W Ə XԿ5% l)n xv\;$Kb}_ s0r}Jb {1v\JF+e1f?DaNЭ&gݾ-bd@ocǎ{:_aӦMxwdO gӘ1c7+vSd={yyyF~ТE (A= XWϵJu1614;?ӻe{.ٳ׋uS]A췅Ot#+nݺf}E?㒰f<h?ɿ :+Ś ;M6v-wxxxbŊӧڵku1m-ڻ~mw#*puWٿ'jT4so/9ke[SL%o70ػ8s2oߩ8by|ݙD%AOl2&I['2gi[3 zTja[>Vl}Do/;Kq>|)bL1Pl}ÏVh {nTgάïТBbQb“ϭg58(Q1}᫶E,"a5YF11Z-]Nl㌒_S,}8iZo6~m+l%dO[>g1H~IZL:v˭bGF}rEJc&FT񯋻eqVsDPG\mF1膪Q_|ub ^܉0 籥ϔg#BX򉮳V3gʗ/ooDR!Z 8 GÇ#|!WgQsȖv,lYh\!ϡ4Q,Sk|QKF|UGFڵmk9Yf%lg- OF CʁIљJ"mgmQ #b)hz+|ܽ;a F/W`[:4 WҌOٺ=1bk"Ok*(qwks< {oڏeQyLyzt6MU~Ҭ|m4Ճ*c2'D5[d+gW% :SߔDIW$ȏ)9+7wB}0I(D![)B'%& `J@~`9콕O&].!1.SXtr u*3-Y5 2g'GvH$ۯfP4&5$i?]+6AضL+J+';fڥip؎BRv٭Xhg&2Gi͞C ,"dn5➖籥ϔg)UOf)("_\,ųmݓ=0~>@M.Κq .uHXFF~i:u ˘7o{nz5 I \1cښ={6ؿITz'0i$ԯ_@nn.[lw}44o#G>r}H?+WիW1tPS/aP4+W_e8Ջ_ĉ3gk?Xx>;n=-Qyԍj]1f\I,5|Y?:r#jaJ xUf_ RsoqL7nd֭5KQKi^̊+?yШQ#X .H#0+DzYqHaM~ U8G^iZ|m͛Vו*U2J'|M~W̥W_}?C1*^Ώ#g/rtw|XU-[ի3-;wưaX42=KhNs#,, >,+Q,`z)*{#C8 Cប א \d=kgX*Ju׾!LTg)کr@[le)XF?,J)(mQ+8g~AvHK/;c Se]$XE*D) ,Pdd  SgsgL;g_ymgi3m%oժjZGe׮Z/"_ڥ,-0G;ZX-P7Z޲/X|96m :ȍ"hiK%));qD 8k,v϶mjR_ϝ;R- 4ݺuc}0Ђ~믿O>?05M).]$κ"`ydvB~E_xNGz2¯]G:LrKg}l DFL? '$ /8k-RGG}Ģg#9*jsҝ=z`"Ӂ+k. IDATXVj9EI^9d8<~54QgijGjb(ђ@ΗřKrlO>CΏYr{(#gĄ SOw^{nG[n=c,U}Z~={&nb&2{-9?_Dvȩݟ\/(KC(:rF2jM8KrgV>"uHL-E-FH6L)ʩ_^mH N:sp{A[B`?Y9qVi]*6axkmnWzW퀌,ui@O?t&Y.TgNI]-dDIJ 2Hi.2qN IU⹜ j JsT,vnNQ 龲dZ? ]*6E MsY945 UNԎ.Yصr?+(ێOKG%{D*rSzzFP_marD8+tT9B#\aF,Nk,;wc9chy&gd5ܷP]+R#o֊>BoRXImР(ۙ`J"m)BoefJ,Ax=zM6;wd"hR=U]7%^;v AܰaCػw?UE8GSy6Yn%H\>܂bpc+qŒ *Lr%$' -`jGXܣ<4w6Wי3gLxn+AF)EB9K\;w.%sΊY Rt>O|1 I줒>l-Z:^ʗVqgx+js7dإK2!"ʩC\qHyU}C0Vvf¾0LBS.@JG@,u1xk7HH^ʸ׏9;oN<*6e) r?u鰨)8K\b:%[X aN9q*:E6d`K7N%,cd՘-TP#Yjڔ+D8KG`{'.6<䓼=LsڍfY(?1E+WmX[>;Ê6x XXc&*d?c Ÿ;d39Xk7)G>{Vn~ )ʵcdCP:ѻ氝LgIq{۩El`dyxeP_`.QMGRkߏ~P90LnرÄ`g'_{w`Z8hs\~mG,EMn2<|3__=”'Җ]ءT(qDeM? *BP{~ol~TnT͘sSk;cP>=:zvxqixH?l8(!%QLn|Ø9?IR(:%n gojQ)%łvDbQ myYk58$a.}B0} ,GQDײ*2Waxy&FT|? :#57a&8jgȉJm`"qV԰RgΝiy#/f9Yr⬜?%G39?b86'l 8ES柳(pKσoWP%䣂UVu|=N[sڻFo)ٶ++ ]FѕxYۆ=w|⑳ֲFLc{/_ƴi\$ xM!%hMpr۷1d|W bT>&.Dۼy3NEtE Jw-X^jR_Y"$LStT͚5YZhSM'4\rL6؁`ywrF"?^gu62﫨fb_MHTr$qm1~✽.Eκ"svpGZ0-9J7:j9*zx6rQ *}s:j$P HX"0w:TfNb)MB MNN-Z0sS?%ڜ*ҳevrnܸ{O2D}! :A" u!$$}a:ӟ#6|vހ{j ¼>ElՊnjߑ|ٺuG!D`g1sߒyXCXgkK͠JymV< ?,uZѽ2QޞV>A#|ui8XX۸m rծ6,gyвtXju'4|jkk)+⬭xS[d)9e4=⬭4§qq֥cJb lǏ1Ws$WG\ϚuE^a>_;剛tZ/2TVaˊ8k- f8ʤYKՠ堑>2F#Yמ+\0 ?. _JΑhs_}.rqV?k PVYknk8Bur];z\u^q֡7p8G#`'hA*w 0C%>>^݅ä0-.+4ߛU4 H9 9 p88.:x8G#p8\-nHw8-T87'xL]E)WgYapq p8,gN2.o`zSǍÞ +J9k'F (TZ={QB+4VÉANtVw9+OH9xuE8'xL]E)WgYapq `W^$c qTsYdaGұb \ sWD Z'`:s>qV'xuG#p8pqV"^,#Y糮.I}(-~J؈=ɧ4YXmKP#s[0fۄ߅3^iW'-Fb}XsaY]b_͞r3^˺\G/ma^y㺶7jCF!p{:\uv ".3Y7V\mNų[g 0AeT '[KGNFZE᳣xyT gO7V\ 'zc|h^,Vo'lZqh[1bT īw| cuČ\ZY1RjsXyš88;٠ܫ_oim]J8k9f9kg#|}p:>Vh5]oUǛĨp!#IS;B%y1jϝ'#9' o]`X/=*=M1vNʇ͟{f.\ _Pn׽umo9B9t;8{/8+%!Β0T{Q'R/b摕q$4m4|z'yYA]/Φ_a⩯7kʔ^9K cZAST6\GW!^e 6\ُc#n91nf]q-ho_Cl@U} 5r63?>ޅEM?,ӪbH}'e'S/aٱ_ۖ6aXƢ})757ٻve,:Q.9'g_nbOݿkkv1qZ( lx<GaR}ZgU;bF?=^(jUŸvc%(R)ZnbE=+aVϼKn%g ZST#YdCbdma ! lg sMYJM%?\1&IY9jGKl&♭jM6=j76NEL@,GՐ|.SZ=sM|RSvK>~ٸqc|Ƚo66wY?ެm>]"]; q" E*{k-+sC/r(ߜpHlrgg, `oq6ܷj*ގ_Ģhq8&^9h{ⷧ[3 [L1Y-_W'`ŝw'纉f q쐨͝PXvvv8aČuI{fv`)+wkN!L c1v<\Lb lFMBs-}:UMħ-3~Bݤ|->"pmF1J U0 m;O K{^W1uw8t,qB%"'a>hq$6$m8J\I8ʿX}6 1h -'ΒfZ- ΔfKNt0B1eb_}69fP,x08KrFj'X̽ 5ZEU‹毜O!}E=W2obL `3-AU^q98x,9gTc WY19I-ÒaύV)eӯ⇳iOϳjAѡl'戒R⹔_ᑳoֈlYYY+wYk `kxCܱuc2GgiY,+F<;8<=#gԜMܻ?wG׿(0hzVU]A S&.avQxN9A~pNIdCRXt>n"i?E UXDQ0[gɎ-+e"P؈:|%傤|Th{~wfY~^~,(R`IuƨWUQk-jCmjs}d,:&qV r ]T /| qx%DMߞ$jtq]h8+!.kه }䰴s"^=Dl8q֚9+沚8Kˑ>e|9+R^Z'M|#"E;?'ggy9ֈlD 7-sgsY/R/̬58wlݐ9 itS8}Gl.:=Mx퉀~UF|tyNe]}=vU]ퟢ}D<<10_39m9W̽绽=|s/3q_dt]3]ʜEgK+,Sj*Vn>Pl9ϐ:e֞:#1[؎lΕMؔ]]hSNٝ*UH޽%>>^/o}sϞ=2~yy :tz%w>Ǭ>uڦ"k\|Pj-/gҒdoYwo] /H-;1%KȊ+W^~U/_e3fHNf>$ȇ9>8{۵/o޼ ۷f͚9S3\;\( ɓ'Ks=o\W ό*gڥ܏h.D ]+<X4ga[YYY*?`dex@ȕZ2aY Gn?33SJ_48zW]n6\~( VS˓+e Zg؈Eb9j>Oe"+/nBV眻⬙!CU>^l͑81g#:*f4l͎jc"AE 2Q_vN;/Cj=(%T,Ҍ#["8gSRzr 4zqnjY3&Vd;WHa;`̽b ~Y5e&j>ֈD -m9gЏQ?lml*Uͫ[ffWX.?NF53-qA׫ö-Y7}W[\ DDY`<9k|uEd lfҥK2k,9{ 6⬞~S z;:$ɓGw.UVU9smEx FDtA?<;?2zC{饗hۺukGs{G~e}AeQ9wY=5ٮ}W\m۶Q$&&Zu uׄra=qV3lW*t7 (<kY7O6gm (6߂HR4_}J]tlls9vA%qk7乛ctZR1Q  ݦӸv#gKPBEbӱQz0>Geә*e맨-W,~\ i[/^N5ni II`&@4b1wkR+ GˤTc<6rxAynb#Ъ?fQwx6=IY**"{˒?b3Ws`h[CpjO*.4QX%wi䟵'G8hx]ul8lc$Κ1nU޲Mw!=Y,3Q3Lˊ8kl{I 7WF61EFwVE]m7_3Q*J̎4ci4W3,53MqMozhd+¦rFi 4F,j>T/V=͹" l;I͛7˴idĉ/… RbEy'dɒ{OrW}xǥN:j ,oF}?GS > A?U-q[q֬Z7m}OJRDz"YoI8\7%*=z4;rv}غuݵl|qqqj([8qB^}UYz|gU >QTyNI_Oʕ*1HDIiQR 5͛ŋH"e͚5uߪMvVmڴɮ]~>}/I&WX1۷T^]u IXjdVq!I3WK:}wg /"xB N9FGln%7BԢɟw9lUUnam"G H(]%Ύ{eԦr.zhgY[gٮ7T9kl5WD6Wr~iiܸSa{3YPv-yEy'dȑJ84,<8D<\3[q/n!~xco6V0g^5E! |=8h(>ߨ\X@~<&a)r{ICevc x7wo]z n)SF~5įJ بHS+_pa+8Ǖrf6a^{9%ԾrJzK/Κ(rLͻ'I"]6 ".OTiRxX#,kk,W P80]g`(ʕ+eٲe2b%O>Q{U"T' VTD3 +<e4h"g.a,8Lp$Zv//aaa%gHZ˫џ%D~A.{w{8`<SD4\f >\}ȵ^z)@n+h\)gf3#qV,k׮-3XY~⡀yJKZrTDu(PZ Y3{ohڇu k^˿՚>ytRx#%%E 3gΔcǎeU#Գ f4iq#q8sJJX,i?^`o1c(b,se玭ZPf⬫lhpͯ௰1|s9^(ʕ+=P5맑8ksG IW8]HFőXW2Ju8C~}?<-o#~T)9'sUGF:2h q1ZnבHYlbʬ\6f}AG$0Ɔijl:K'OIrk9|yE򄙺~BqLAM7o=i :iPbJcf}EcKq9gͼW"mED?&$$HSD;VmTZ5%xa/6@8q<22Rmh"%Y tԨQjU.ׯ]qֶ]ԁ>@Á\#Ypa5^ԅM[쵞 1'*@naD#CŎZbESqe])gf3D]k~c`;?^G,R4XIk`O#qW˔M$"I{4EWDKͱ*]WkGE۴@,2 "'DSWaPV!Pb! ?w`fycό쪟f d77o./ xPS햌ڴD/>&$UD->*?.Q2c;):ZY}PpV j @`kM/I0;퍶;cfI:NR9TFq< S$+w}g콛(κ IHHYpd+7Ve7viW˭:(κϧC>iO# \gO\;({Ӟ"8kǖzHHHH 01qlw%+C֜.9UYe}Ҹdu TYۓ7niaO{qHBW}œA^gP9$@$@$@J,`m_⬯O%FB{=5"zـ0;I$@$@$%g)zɵBZ 1!kz >1~QfNP{$@q֛tY7 8Kq}4G!&,M)Kq6tl͑!@qnA$@$@$(R e)xjhI .{ӞeOo⬷Ȳހ @q6 NGu,:LMvo,y^4c0ymvn*$:]UozlH P8x^= чJH{ZggR esBqN@$ g%gғ p)U-YOe$@$@q9q֛`$@$@$@Ilhڝg $@ q[^͗V ue׈ 5;JƩ#uP˱P[$5#]m'V_GFb"wm%=J#g;Uh%Iճ*iWFFzЬYA ӧdTY bŊڭgU$@AB췭G˝?O,?O#rL-W0N&4/s..˵zūuDAӧdP)ZAznۿܮ8{%y2xd9rV e R _0H(:'j-mJ5I2gRT[zS\-s];)_m46n\IH+n;_U]ڕi"iˤCC64 9g9G Y}r0=.6"ś6y­3<b0>Kq6܎8K   eg=+ΦJC٥8vX~|[v0q]U_`o8N<# P brh$@$@$@ P8۵kWy衇䮻rȞ'' Sٷo\rEcǎҰaC߿_z-ywE={F9?kNqM*DQggwEiٲ?N*K,?\0|um}?F)5jpkˍ9(H_̹GGGK*Uwc] -{ɓx9_GzX?,Y )P5lHHH P56;"juUim6%XJ O>AzTwOy 68옳gϞ2c a_D!5E˙$[YvCgݝ7ݻwEo IDAT-jO 'N ĜrR]uw4+k&t!5$v,Z_6Η.]Yfٳgeذa^gP|L՗Y߶ٚ^ʒt9Y>8k>KqY"@q6 8I10wYW&C}'M4իWg}n+T BK*"T!~BŁH[Dk!ޓwyG}k׮_^ W'OjժSO=% RQ(WlY%nbt$ѥK1bDh˗/gfFc9oٳ%))I4h CeG,YRh" QQQ^|53թ":'M3}y=*! V85~8m48q5⬑89+떑o89ۼysYx)RD]oj֬\̙kњK_ڶ K_R@M2`݇[g83lHHHP56'Dp㏝$^7Tѳx Rᅲ{N {@+O?.^|pSA+ݺu[oUΜ9cx-IL͓KݺuUmbiN2qѿÇHb;-7mh߇V,_~eU8 /<ҦM%mٲE^y?EQca&uU.ZuS 뮸}9o:w|ٲeJǁx5%%Ex AW(Bi fxaz؎YR%޲$5#M'p<@0k~33n3,HIӶm[b28sD?7?x3Ί>(&   /ʹ0;6mq8p׌:̽>BG* x΅a{@DرCGݿ(,ʯ]VM#]?8u Aݞ8 ,`{*QpE+~z\*6͒vYw 9s("=|sF}r"b.!˙Wv⬻WDRCYnR) "kժYU xlM5ffazЎYfs"ckJtx>H6~/κmϟ^|vmu8\PHYq@zptvъұBKy{<9dMwOSVYv @.`lNȮ[g|HWl y27D3vǿ!`jb 4dȐkV0;W_.f˗/NJƀܶYD"Qc5b$Bp5?l'56B9hle$"Ol;w@ɸF%5#YOMEoV͇-[*UgHxj*5 "%֭[gU|HHyFu:#Κo6! ]??gv/YmHqqqkV-O/z3o @h8 6l`a ?u6az| #6~,QnP0gbp x/~aS8# U.ʕ+ܹsUd"&^;E p "K"-΃8{ܹ!!6ٲbePR!&A.^N{Ň0\ĕ78ssB?D%M]d b.aS9Ҁ_b9F84c~@ΨΈll"g}5^_fQ?Gz,@{e;ǎ_[FlY\SZn_:̵K_ڶ糝+"*ݞ{,R;]?9>Yg$@$@$@Buq&u$ ȅcl Wg $m۶M 4@ 1tƌ*_m…}nyVI b'rb{{k;vD /@_J.2- C:u 1C @eԨQJp6?rBt_m}$Y'n1++. WY+}st&\D_|Y8ơc*!ZjJ >O;7n5sAX#nsCfsFS[_ǚ˃ OHHP.83ffV-#0E<+TP:X 4h }Xk1wvUmY Pz6L$@$@$ (g(OWbvv3dg=a.D4b:,'&3Ì#6~SMi6 n>ukpgNYqvϞ=s]3bŊɔ)S\qyꩧSNҤI~ ֗ןgWT1p 94ǥA @@8Kq6:K.^ӧBLq"(\g^ڵǡxR Y3Fbccw +$  g)GO) ؛tCnThʨ)ZsoV/^,.\뮻N/ŋWm&3gqqq*RQFo+ .Q]LٳTV-Gy{FO]_..v.#˵&%KDpڞL-|ž mv&x#P *† d„ PSb_8K5R>AU>k ٠r)Y\2jԨ333U^t%.]TE6L Jl͚5eҰaCiժԨQCU5E9D𚉳\۱hkNu&|̚5K^|E]r!5'  gꡇRoLIGݪRLIpUc*ҾnM+OykPUꮏxBq6\q⬽TH70i$پ}eq }+͓sʫ*UVuZX駟U;:gvXl^O.cǎJ*h]v9x> P8ۡCUQ=\h322T+ț7$$$HYf7z-Ǐ7=7t=QԕpXWeqUuGv[-ocɒ%b yW e?xC91tPuo;rumbcwo[C88vس6lRSN.X?˯*G1^zI[v?3f̰b8o!=޽{v}˳5;Jb%r|;Yqb싊]Ug0=ׄ~[""" Ri[l(;2+֮+^S(Z]ax^P8QD"*MD$DEE)Q9g/) ~^ZFG˴i?J.(">C4C9g@;gϪ} L*UJ%ug|Dl8#GRZ2Tx46p Ckux3zINNG}TqU;}}oPo8p@ՍҤIuLM}D_.@Z4<|Tc5|Ei (W@R[EBxYu/)] VF&W5j}m}4qsI׊#l7wzݻw+NׯWɓ'ͨPBv 6R*6:ҨN#cm@?7o+W˳#g<8OUuaM=!=qɷ񬄥fHFHIm'Y1R`|u+8jg!Z7N?rB&Y[lO>Dp^%TJc%r]!G56EǶ9gaP-~-[L#ׯ_MnjƂLq6G$@$"(^khW7[aəME8!m֛o!qoAw'VWi+JσM`V6m ߬x5ŋ7,.0rxmz9"oBoKUTCz^/i}=W;Zk|[K#)rO 0[tZ5@g<#HPL%ꫯ ԩS<!B0GT ~8q54o(ODRY0H ,8,m$HDrB2$Nj ~W)q֕5mk,#`JXX?cdW1Ft*Du emc\>"`Ch[q֬N#cmܹz<󌲩&*clBڃDj{[GkJ$D,.Q< vr.ul`0CYq;`$@$@$@$[g4I\jazYģ^|CD+mVD["-n,R{*b6*#FP}Qmb5k(Bm_Ou+-ay$Ͽ\\.GWi=Z.]IQfɎ {#3DM< ]ZFF<5$6#[qѥK"/G 6 8A*IKK&()'͗c)gf_T슍=a_g;g%j] rNO`iF8? "kD8V:Q& W/k7괗sVWda3|&>c?I+IR/=L(u+^S9kW JgҬ (^ aUa0zT՛h:0H?`ϦLa TэxjP?MESe{8?ЗED 0 *DA zq};j3iq%8 12NWxylpF@G4m AT.pxjхpEtv@F>b&¶+}90{l*.ZQ:Vh)oo'gғLW9wk+i9E[zql2 ;i֭[RGD#)K0a5,Oځ(^D; }`lexx;HW}rE$3K2JEgSe^Wܿ8Z,8jgڼ Egq pt %8Wm7nAX@#r"Uq~y橨'{/J97C>gjt?t]ohw틺\8 9"'Gjm}AԴm,:58T-~ʑܲeKGgQ_v3C C9 'Y"%|wD쾨P)G2+Yg+9g-`iIlpڕ"  pYψ6{ᇳ7r Wvt͟*3R)RD쉳7#w,6}*"(Dhx-H7)qu#*W, DQl2F /?iW;t>z`1c(OxoGP{Rb<爖mݺ9 hu!T IDATĨ^mۖ@36 >sIqY,R~J2 EH;HJFw:]8T4Z٪US<,|"/ XGlY:lVVPK3_R$TIaf@)^W]q?(zjd=Il@&  0fŕ{#*aOw2b__Vyi嶝/ϧO~` qBq60|^jIHHYL=IGnRn6 s2Ps\_Kqֱ TXwtGwBXqb2OVV"κɅb@g]@2ES!cjꮏxBqe`08 VHHH%@q⬻>[deȚeށ!^/B.a0mS-/8kd~"}M#P$8\$򯐟o,6›87{l=]3mQ=?|iǦM,7MZp`EZ.N2t:(9<Φiqn>=c+ (z*y;Z %2Jqֻwzv=g&= `m6ҧrxGq6plŞzY/@8;Ph%P+Y'& RsV8Kq= Yq8GHm{gl@uP,Cig.Jh>*B[,Y<(tKSd ~o!}*N{gVPTՉVBI Rubp*?mg&K 8뷦arl<ݭczJ8P۱H*J;#ޔ1 2NWoo>Oz6.Pi_}8K".z ]NEskfl\,sn6J\T1x9Ew|G9~|r*2V&&w~ݯK^/j 6ͲwFS[abuna#Nɜ}Mmae7W竽yLmuFl_+VX6Rp-sd۹>ǜnBO+¶._p\?7fPB P[<%v]1FN]ѪwI|ō ʍsr%S2eJ֎y^F]mG/.QiXO:o)/lsYn}9F+m]swMqdCR"aVv)]B~G2%HM2VdaQr&=I^0]'RuY+5g=Q>X[ayvbecFn#f;o鿣~o%b͟Y֧8 W1EOXy#HHH 2&<OAUjJ޲9r_r6-I&lRݫ:޸duUGS$.\NVjt_m*"2n%c|&Oո_*ǔ.US%=TII;o2P?r:UI+нRhEn5߬33dҭm}릜Cy^&yoW* %~-f+2YcRs[pday/d1:>ڳ"XY;ʓkޕNdWhM/NYw6ꖗmUB]qQ䬑ϔ g9; ž_tyA[|^c`VߋFk?WITk۾%!%V&g/i o"O$2 u!"evankY).||p}3hN3MI2V' 1،ƵylMl3yiL ˣĵ~y#~~w͹c£dMCdȺr4P4&WfE!(`VuՃ>_cneY#?ceɷG˝?O,?Oc(Rx~+ #V>,~GD$a841{s 5ʑ?Ol|k|wddfeϗ7Be!~ib/-VYZ^ule8hO,oV׉;J5TDDsFg/^It 0돣S*J>5\wE5kY%VNCɧdh@n⬑/'g^Zx xYeNS~/gQۈ D|y"֯H__5y\Ma*:o>tJ/#$KrLM+wn"nȿF%Ij,o7'ȏۯ 0FGoT$a†%o1[vVHe*EB|tѻJ7 qG;Y#Nz;(R^^pI˼2\_Ž܌Y1ȃ)qQR߮+vm?mWKfђ8kd +뉕S3O_^撽F1Kk Bo%39XfIVad&:#BJ|vpfW08k4ڦfQ6Wm1e(@j:_^RJWgYDAV.Ti@"D_GKBt1cuYwscl cvC<t4]gZQٵξnkH:+9g\lOqՅ P[<%jp#}C2UtZrD]-H5YlMbW7Ðsܶy $ξ\J3>f>.%DǚwHWm>>Јhw鋢M*-"zHN'[ Em*U U'w^$ie vf$H)"^ D1jgYDVnFVTt_uumƁkޑ(cuYwlz]drYhu.Ƙޏجp׮ZVY#_0[O(:{   .Ym8P>|J<čݸT$ B<@thÒTv=b,h%fCǮ[܅h7Tȧ٫j[uX1׋ZBNѮǨ481">^ɕ&{l)oF)s)VY^j9VKk`UCPV?SX^{"cR32Nk⬫v.YPf<}mq=2wr9t餡OEhiqE+SQjd?cIu~9o%8ői>FCXCYXӰUq֑?UQv߷' 7ו6LS~>aԖ- Lq+k.YuBt}+QuZ%3>"g\:̯Ym_;mN⬽kzBq{$@$@$@AOlЛ4#iqbebU^G& K/"{4[Tv?(-jIJ4*LqC+K+$3n*LR#WdbtqY\)V1;ٚeׅ Z>Zғ+a5Xd\Xi=gF_tGb%,2y^r7ۊF>Ѣ8jzs4^gYVŃDc=~ʩmUuϞg1 V<H PHYn徺+:Zǭ9;#T[`f63Q98kGZ%:\c⬽hu.煙_k/іC: EPqW9|ZaY#_0[O(2 Yg>&)qVƕ 9|JfY*+Nl! :ls9vAשq _,"[S7cv,IGLYVviWʝeҡ \w 6ϚgtxXƕYܠ/ls.,<]Dl}ش 26GBKl2͎ʶϱ>Ί89hUvv|k{ãj#{]uΰ׽e*z!=Y,3Q3Ҕ=|ҊR3Vh{,6Yw⬑a+}⬙-}@IHUb4{S,Ti+&zS8hv r>&Mt9Yl693WYXn]lx:Q+[qv.Z yaf⬣:6MIjq[ȟl=8HHHH(z/+w>>韕׃,Z^…٫*Wm^>+u9VKO`$ziKt͆OnOcX멹eP;l6{_W6FgAu ugAHlS7@q$<,l=OEIKʝh+,H%;U8|1Eܧu˙oZd[OL[G{XHHH%@q],(x;)RW\Ǟ{8?&   w Pu 4gـ,;O$@$@$@>5 .?7md_ݺuչRhQx" fq7t    ,=HHHrgl(#+$@$@$@^&^IHHHt&@q6 @8.@$@$@$@>&@q`%@qַ: o P-N$@$@$@g!MlH'  '@q6]HHH|L⬏ }Kou   8[lHHH(Bِ6?nO(1I2xdN2p{RP)yvgyd՛W("Z!efg-%읗 P2`VO~FMFr[b}d#¾1Yzlxd_x^òQNXBِ5=N$@$@$'(! 8l|E :o>oˉԳ% GKJF4.Y]zUi+Qd۹ږ9rrTIA5:/6CoQΓgvz\-s[pday/d9y@&7͒ݥ"g5Kw$J2%+qRLϾ%!"Wd$@!@q3Y J⬫X.(P 3r$:Ɂ'}TZHysLm<['WM⣊+?rdB2gR\UT*WńGȐuSh)%^*l_ Xg&ϑ֠ylMl3yiL #t~w9%b<=!Z,Y+e 4Y?ϓIY3 ;D$@$@$b(Ά9ܜ(#H +VYVk'}~թMgCՔiE/J%&@q`$#=*!yȕ 'Փ[MqdԦYL/ڊ9tZ^K>#-HYsV?SXgZ"} \8y|ye9eGY?}dB6K$!g=Ր (κł#GAH..)3˛>)UE" Oe"+/nTt\27(X-FmD;7BE>|/*Ck?6C.N`;/u,!RDy{<9vA.Ox@ݛt)q֬2IY?2B$@$@$(Ά9hY .q J+GդWնx\&X$83])QzHŘvv|k{ãnys\yނw,[+q6&"ZQjrb#Ȭ IDAT͗Ԍ64kPW GMfQ6٭3Q?C׋8r|g߆ @`8c$@qM,N$@$@$(y   @q6!NXHHH P |r$@$@$@Ml`ۏwY78 @@8cIHH 0":cI   '@q6m 6m?Mg$@$@$@Ml@'  g(κΎ%IHH!G@$@$@$({7 8+κ _h9фZ^pA}i&}[:7##C-jO$   P#@q6, @qA$@$@$@"g$@$@$@$g}Ý ~bvHHH(?'  agCUqHHHH 0A[#  Gg*S0gslHHHs=   &@q6λK⬻YHHH P v s|$@$@$@$@q֗ٶ P    ?'@q 4m>v]g%$@$@$@Nl[#  %϶}NM 9~n vHHH P h8.A'  vg / P%}sg}nvHHH Ps{$@$@$@Ml@w8;eU< >l`%  ,g^쭇 Xg nV<VG$@$@$@!g}Þ 4!m~,}HHHD,݀HHH|BOQ!@q_,~ Yg$@$@$@Klڞ#t   `,}HHH|E⬯ȳ] @q/N #g}mO$@$@$(Ά9(HHH,HKٰCdNEN5zDEW%ߋ_bEۈQ&r|o|y`ڗYpDDWe~<HHHgYpY|J׮]sFgnj#һw\7!  K>/i'EFᅬ/uzFԛ\_YN_`Ygf$@$@$@$ g=Au,W٢EJVc2d;wNΞ=-~xbp\wuҿ)^:B?+SSU;:m`OG֯__͛e׮]RfM?~ r~ٳgKDDq2w\Al5T4q߾}u]Æ 7JqSrm=?6bg]A2$@$@$@$6n#dLUqiӦ˔)S$<<\z%7x^Z8^xi۶}2p@W5w-? ʼJi gGlƍ駟V0~z>}Vw nAƹa0ad7t1}\ҡ8 ~Fm|+! g2vؓ\g{16m<GyDNzMZL6==];wÇVZr}mM4Q"]w%=zPQ!(+WN&O,Æ SG*TH."q} QQlf ܹ3YO:9" ˗eutTBH { ZHo]Q}**X8DiO?T dYlĈh)}'SS6 b.sV#j^&"2V QA'x7ѰaCEq ݅ 3Ϩg-2s8 g8jEu?\ddaXpnb8iD֪W"q'Ѭ? xjtcxz\-gW>l_d6YprU 8/8+IQ_Us̑Fuh͛/ڲ*N!XoڵK\+88"TK@P6jKqVq駟 e:t3gEưNicWX!}w>wE"1+>Tc [Wd˃HHqV4hRHoV/ѦVܞ qv@>LnόQx?rO;cvz(Ζ$HHHYG_⬣IHH 9kfm*2gU@qV-)#   8k?\PNIHH8<8Fy '@q(:x  @\e}DV-o;r;Qz96ZlkLn`~Bxձ.?jjI 88 %rr`mF@&o.~t!\+~3܈ŧ cju:=EqVؒHHHB]hE!@qx$  +f/  &@q֡œ hPe, @8[&9hy!@qx   (Sg?'  p\g\9    @qa@$@$@$@eBl` ΃HHHL P-SHHHq Pu\sdΊ$`)cek_'W}h*,󖾵YElgGݣ0ݸgzzm~~>TcC   p4g\3g)&BԴ+6bj3\Ys g8cNm;:8&mFftKqgߔ#?S]P-y XH⬅"@qY+hVpuje /?[#f`ʖҊ(ΚZt jau̎rId3۱39l{!xjNf[5Su.hYs%J?iP8kY5 ؆Yp Jl):Ns/8wI@ZaU-f:[nj}$=;i-kS4:;F5o⢱1+gUeC! ’ؓzLUbdXyz*g9wmu ܵ8)jhM~cbj ,k3g- x6'   8[rP P-E X*j&ERP/jv г3z,o1q>x(m[*n5+b60#Xzzf5CGVma5;cFwfgsNj֞:oltZs`@xl3bMufY͖$@$@$@$`gA6+ {n\#/eΰqr(W| 0yO^1Fs3ܫuVDNVXuf&\`|Wkzv7"5ȻK[N.e~#kuŠU7q|t gXnj(ZWoŬT<]V7i[ރGW˺50}Fd?gw}EԎ}'qEQ` "'b֪-8޿s30:CU4d|c#fe*U4/kVLF5筤d8kί*+6x]zƉkaTD{x7N4)i;xQ?ՈQѯF^*۷Tui+xk/ҽ⬥ٞHHHlKmyZ#`qVU0STQ_؉ ?O/L*˙T@iD#yLf\i yCfMV~!N;Js&x>((P៳'$M-FXsD^k5b)o8{!*~'g'h:UFt}hT J:.}Q/-QsV筘]K[Ky~ZMB73| 8$K_voEU oi퐖+I^+lכZE dTڷ,NqZlK$@$@$@ά8{ؿ)7n`5<Աn:{5?ފV7!|`mvct8_bUX-O7GvB`I+ILTŸQg`AVTc?kgO] Y{N{q#7CpO({ c{&I;~1yv_<1@] 1FmY*@~n˘K$5:v=l Nf\D *Rp4,=;.g_ k686\gW(f BLcu{g;vnG7v^9OuquzBdNmdl|,:OQq?,vt͉jg֊톿7ܜ]qZ n۩nX%L9XFG~ddgf}WTz1y|yzپ)ը)5k]R_m(v~8~ZW`_{[BT+*j( ؏Y @4Y4xc ̦ Q=qŰ#ZGr:\z'^ ,|O)t'`{1y.2\EB*AXx.wI [E: n|<|O l&5BYSsz#Cɮ}d;7i\?Lܰ_NOõLD=]z[}~95 2r"&hd܎Jq6;U=30V fƎ6jRG'"Cw"!z0ȟ.Tr]bjW8,ETxTk.ΊNβ“;QJO6 6/Q{dLk~7^KB\18^)vxSvYW1T3+ΚW?w{CM/SZ5lAa!^k) .Nxs 4..zPR2c꥘7~OKՖ5뫗'GFgTǯ\+*㓍ȽءBhs8.HIF@o]C6?W$gbVxvZJq֔_y׊lc>u8;7A` nFO;Gx^/(7oruWg4 U/K@5%g-M{Fl?G=~O4J}LJwq[3|bB#Φ߼Y5؆HHHGr Pf;{ Ov+dUrz:>ܰ '''qp/ҳpOβq&t_NxVt3//,s܍N#iL}&.7޺?{Ya[WYRن [tϟJ&TV58ې P[ZJS7 VS@-_l]*z_qȽyosV/_o[ҟ1`;{ q.1_^7 ylZMX|")q6p߭y9h>5+UüEzsgE&YwM#0Lk9^84nEgEF/o2CI=s5_G'˖h^&27cgp#7yhX-X>.A5L*qg=p4h7UءB]} սѼ^Xi 7W biBqVt얉W[-+{F^aM{xҵYUlzV&Y{߅ ߢ:/%tjQ`l8b欰ax?Uܼ|$^ٱ{O5wpsĶe~oY҈-(j)FqV %!   8k|: IDAT?\8scܫ7B(z5>N˓b[f=sOv'ܩ+~Ż(=ƐS YոykY@w8gn8Z/x=GK=n0*z%bo 2S#zъ#Bx؝ŧ6m8+2gϜr]o4X d+5h ת"ǘ٫ce 1x0xzj*KbwtLWOt>_0{Μ=Y!=bp6ʻ qvKW̓𿥉xzla8۵z2㋷b͂:gzv*q4k%e D idqw7ip(W ;6⻨>}=w魲BR{2L11) SQlW~#Gv^c!K|oYp3gVSK|GqV %!   8k?\8{=;oY)EUw|W,gE١-ڢSSJḖys,eja8y#lρҾZqVM_WOȗFub@wU!dv ȳ2n0^U1V{#e9rĴXbCqVS0+{$e\5sg`ǕCښu|j`^'d4JAR ] 5+hNBxsp=7S%gjΪYZsV酟c"9gn@)J%4sԿGl$Ί=L쁢lKbWĔ/oy8/g 8Y5؆HHHGr P V؃7珱m:"JUoGmͺ>r<'ÎzD w"Ë1_ZMv1m|/\5ji*%=wmuފܵUer7fIE,V1QhLHHHYs8ObqIHHHN$ ~$]bzzzm~~>TcC   p4g\    !Nq@$@$@$@Nl# ΅HHH0ss`   &@qֱ8!@$@$@$@Y egˋ'8   2%@qLsp   %@qq}ϕ80    f2HHHHP-+\8[.I 5fΖ8> 8렎粋Pe$ 3g$@$@$@$PV(Ζy[.gl9    #cOOOS=xDDlؐHHHYG8׫G@Q%'    I,HHHGr @q8S$  (Sg?'   P&@qB$@$@$@ Pe P[Z(V'q$@$@$@eJl$@$@$@w8w<(2BHHHH4   cK $NHHHL P-SHHH'@qw0gYF &@qB$@$@$@#@q~liPgIHHHƮ1n ! 8ːphjYœ 1gwr!$@$@$@ ,N(ڞ)- T<g+8c   ;;Ï\(Z HHH(g(wr1$@$@$@ ,N(ڞ)- T<g+8c   ;;Ï\(Z HHH(g(wr1$@$@$@ ,N(ڞ)- @" = OT?ƀ~ŵm}r7x nWd4ڬZqwu8 M P)Nh,g?^zILgggW^9rd-?>>N:|TV CEϞ=q9L<ƍèQlHHʄ}> Y$[7ڷПŖ 5õͷLtl2h>d1uz)ZLHHHH(ږ'U0֊Æ }݇\,^˖-3<]: L85"+$$$`ܹ ԛo}R+$  R'01PP`n#y (̳ܖ#mŃ#﫸Yo1oWO,Yɱ ؖY FXV2e m^O<޽{kVnjvaԩqF 6Tl?vX)Y?ƍQ>r^}U¶ᡛ9K.&[oU< \ha=z[_ F瀵}֛m͗!∋S=DDDl+ Pݏ IHHHPu4szJ*Ίم bŊ6m֨( Z!̶n xɿ\zhB ~gu wFc&wC_OnS1alu8ޓlI$@$@$@v!@q.Xi8[Qp`l]\^5{at8΋m 8hzX9‚5Cqj89kg{jکi#kg{K$R5'Z8 (4LMalF Sq   0E,á P)ΖqH'`ja@~plpa#,ʖR8k>NZt jauL:p$sǙؙؖ,Y#Ҷ=)RmD ْ3 LGqdxtTƮUnfC pN^ ꇂG+JAuG)G GGWNXx&뜷6ԧƄw*Ϻ(ΪƩPCã$i#SemY+Vު(R8*JYfHHH,"@q"\l|8kR-noGzņR} a lH;r;"g#aK {-6%áӂ?f qs24@qbÜ֏`M؛NՌY!,Y"(R}T" ْc NV[mE*neTP<=UvWX~z+H\))FUٱE#s⬻0|tv_Vo`K] jE3_g._MuRǬV d%]pvQQl͛n}6xz)8機7pG0bNS,6Sԡ99=tU[l-zMX^5nC-z9Sc{<_i$Ǿ8^prȶL;/r"hZsf26 X?3/ B=:l,8/_9d50}{9aP{A"n2wu_Aӷz;S4F4/s:O]meu,7kΪ,#   8kZAJ]n`ξv(e=_Gju-f)w8;|1|tloqV $E/Z؉c-;'Zo'KiG3'[cPI3dO J8[E=1Zшmלּ&ZVo\$4^ R! ^h>l~i7TOŜF\5mfabOdagLUҼf͢0&u,eq86؎HHHC}j!`oqqpLi>n'~Z/4 p}hl|juCJN>_גi$k6686\gWefY#3cmuYSs7bn/b|^?.B݃[W-0i~+ʤǖY@@@݁_ C~@GJ@r<}.8B:u:~9qVɶhUz 1p݈oLݕt {$ቮ}p1oFZf&o-}*˩YfQW` ^ V!ge2g{813v4`YcVlV^h_hu!;Dlj|;,|dI앆k26~LU+xg+@;)UPvK*ΚړtGMm1vwLf#Q7ߍV3V|G;5Uג_~3SW'F*e`HN%ʜ{ ֠mSzGoH[ml-`c2irͻ>WsCKZdx[rS]I%~^>,D|VՈeyTs R뷱]kJ$@$@$@Eli8@YG_vOu|)t|-Vَ!? tjemYq?Yt/<Sn,J{Xp|-U-ΊrbVنѵu=*Q1}78i򢤍F}lkqVA xp`|«WWD/KqxW)@7À-3'W j:2Ml{.S&LV IDATjuF3 i裇0Kor n..WcJ~P!?7WgW'{ q69.*}`l=°)q6;U=393v4 ?NVlF>j脕g`t)1-?wCMA54| p-R}cԪv/܃0*z^#[&sm避EY8k혺k2t8k!ΚړtBN<Ց?Bfy|0{ߏ(,ܻf-}LnJND$'"5lS_E=9~k'q  R> bJ1V"qV3c@ж9皊}]kq?ȧ4Q>& Ʈ-O m )q֚kE\18k)qԸ~n+VlgoJo%S-DHHHYr6Z@Ytxo=*]oFMf;bE70nT6WZރO/ޔ)Yla7wWOD欹_!}C03oHDUk&E5OՊdBPCM݁@X"Wa@@W=J)q֔}[ځ0r9tW=|egű3~نСAcf0!;v#{*X⬦i:q_s֋89 ?RϡN{3#͓Хz"+풃{~Àhxōul⬩~aRIغ¬Ts69mzwZ5f%l!se Ace #JR؞d(~nDoq1#Ж10=H\\bG@ }ؐHHHYq4i@YsL qvVw] ajk F.1p 3gȲxLQfG5l#JžxVdTiR$ꊴY1Z}5:z X30ЌԈbv<ٵ\]ng_B8{X*_G8 j(ξf< 4uL)Knz}Cʲ(n\CecnwS+k0vƼYRnY{d(n\W.K~ xo8~Ni˒pq1(iPseP@~(^,6B}p$_(٩ZSY@h;4C-jxzԢ4S kk4L*zXZ/Ϝ84-Yjck0%6JAOqv/IHHH(1(-6 7oyWb5_'4(k Bn|٪jM+-D,>IN"$ptK;W9-6̜e s `գ~pqvdF alxY˺mj*`ov2BzHy)q֔=M !2vG.gcϜD TƧ`rρR*3U b֬Ɛ qV$UWTqWxtF {ЪiY@f7IqT?]!Ш9q1)k3gBqO'~AF> q*M㮰 lN``T{z\+݃#o䔼]<~&yhL^[SB/ b7qVZ9kҾ~~ i0vͦ8k_2HHHK}z9'`oq6ww|%[!UYQ'ۣYOHL^Y*~sdqb qVAITE"%sӽ<bGRELj<3Sd\s7}J ؀zyE%\&_g*eڮxV1.Ίm @'Rm]s9{bn͞|/'Bs@ hygM ,@j"2 S2g8_l6|K׳ЧQs hJ߈ qv'e_KӑpwѷBmLc!Me_YHyBo,)$MkbJ̗F5g9(_[gse 4; ¦Y{zsp=7Se}CVc/3GEҼ~_)*E6N$@$@$@ Τ [KhYx5:~9/29+^%2ě?˗fyc2(^AbpaN=hS="!6-t:*z<_,fبg %j؊J5sk$e߸XRE8ʖ qVe * qV㭶9{<*eaBh{#)#c׃tkCZn%,;᱘]FgXWz2ʪ1 ה\YS~8k|`ەxlP=e S >z*~>ߊX>YE(8v4aHxGaۉh][Vp=('4⬘(oHEBiYbVjk@}(rkvAjN, JS⬰gZZ)P/[?kQo}>aDҼ~~?Y5W!   %@qls2&`q%-!>EQ?se TT hNJ2- (wݵ ӊ>9Eh)|9% Tm9'!R`,3Mtpgp4=9np\r1/.{ 'mzLg81u›̬ȉxiW2E7>PZ6' < @IJ*MHHHH(.Mg#%cuul-6Z N{c~%C:(;#8h0K_X|^Z{ a 86N^M#w\H;3"6-/D/q[B`=26p$pts9و-hƄ_s*kqd^.?;6К4i3"*vUR,KOoAL8KqVE(JgK%8 X@#@q>8[rB /rZw[U$j[mNdJ;sּW*N !/w4crDV~Vٮ( g)Ζ3, hPe,84w?Y15hW5\;sk/*Ƴ-[̝lNԠ-@ICjP`㲤%!'   [8kkWP(ڟ1G(Nl f`%}@q죐3    }gMRq֡aq$@$@$@w,[LOOS6??! 8qWY g$@$@$@$P6(Ζ wZNX*XR99a |mcÑ{gܙG4̷ /,ihn!fZ)lK$@$@$@!@q6i8[Agi; Ō#K;!H h}R;Ge>JQ%&   8[R_ P+h%Ɲ@rx: sId3۱39AQxdvRQ XI⬕ @q𣵫ppk9F?Gw#ACã$i#3VUbdXyzVu^٠gm44A$@$@$@% @qص8[}X8 xIXٻ#K;0#Xzzf5"6İ1#;'Ge>jlQZ"   kP1J"6 ÄP7N.8y W[>u}k`zȖ//Gg'gg|^a>H/'c}fSxvgfۙjalJ7.o9yca~|DYs i^5Z=_C)g ťMº  m!m0% +0 NU+Cu*ȸWck{Ԉ;͹rߦHI\lqWLXLj1qAW_-Io8%?5 XEDw"Nj",+9Swg5k|HMFர+((,xl[t;[^L[E*;5EH-cg   (1%FH@I^ (tl.U- NBnY.fO/f&0&uKX)J7-Y3Gߐ6x@}7qk6jT?T?VoO/GbzV!;OmX\q8kGF!1vb"oi^w ־d .RrĶq0_#EɨU,3qV{t8Hͽ{^({K$@$@$@ي3؆g] ܜ\Mp|,:O~Y5 QoP.+P/7-bTnHIGKpVX&` HQAd̔/4b1n/9"ުa8NOU}٩-RSY9ycs"|tݣ '7`R,{~TñsRyg!{}Y~]~ģ6vnηb>֮[T. +hY{w\ξm1vwLf#Q7ߍVʩtnG7v^9# O"C\ɌR`īc'c(.yxp)lsвJ=xd2m̎Oq%W"Xo\Ru|kckO)sVR"&n.x_>IY[p!Ƕ4sTzT65b5#ZNj0>Ĺ/bԔ8~fj|W+uNGɘWZ5>YQ/La)ꙁQb03v+9qs03 m6k*~<7Z?,J.7.k*>t㭽fƟlݬg-C ObؓrTO5w]o1uuM>V)H^Mۦle c   ([g˖?G/c%gԃ<ѶjC-,afJ{{S"ত n:oFM>^ sЩZ3t~+ۊ{u3MDBofF< +"G>1h<84'&Us|BpɪhԜ6^.Xk6FWgdjn^xvz!x ˴㍾؜ro߇G)G8kT{jrFbF^VYV֬$⬒o_GxaאJJF`EB6nP[qǵ]!2B=_ם_;~5+Uƅf⊹m&@Ĝ8Hbmьm,SR4)JaiNGFQ8+G ”!8U _gw(~4RqTZqVGpR>d/bi*4l:3G%2!(A"Vk|bw!Ίlͧ I2þS2^-)J037L2DE;oW8k50g%q֒8Ԉžx"еSHNӊkx]^u7Ë)i=⬩(w$@$@$@$`?gǖ+kYW/,/R(BD-[ޕߋr|t+-ݛzMY"MfΎ0dv:AD`d`Cm?QC05 IDAT[7Jo֝S(4] ~!m=8BK{gU+ ʚ[#ΚtV)z\ 1FOj4.REqVno'\LEV"qO t n͔?y UB$Ew"W+̗~<LŃRYw%$8~ox9h4D3b%1k|bxI,-qUcF{~;_5ׅ+9ilc3swD qk'>+gΪC]qV"$I| +mS6Ţ WNHHH$@qt+|2r"/[{G`R㡲jv~: OD֒uACJqVdzY-EX­ĴM=*k}{t5>#k i#RQ8vݪO D!k?+tD6V84'g''s]wa|Ԉ#6O_w".z"MLc]:~_D=gum{hM݀U)ކ1)z~! ~|z&lYkpge<`|IS?FH@ɜY#)㢌)X}v? LSjN獨y ~e1LJFmth [%#uy!j]_B[zϓ1; 97u\3Q~ؿTAwZbav%m嬴qOe\S2֐:6﬜utk$@$@$@${(gs-gYooϙT8}IF.x;_8c+qoTд--NgW(ɫÞͫku:򚋴x8K 8Z +0~mhn0rքI% ـ37Gr6s?=2y-,N"NQ:wIu>8_GHY˱8\ajꥒF@%sr:YW>%   >SG$g[Y*%yB(rI+B |hR*3Sbݩ]Q5*^M kO (9k{嬇 IHHHCMrֿpOy ,w3)PAnExpjEWt fs>\̺9VZŬVS;Ehh@ݣ҂HHHH PZN(g!J@s8H?Sϝ@! =hkz3N~=о7Pz1<HHH<#@9?(g<.?~WHry<)p>3reDݣdǒ Pz)g#Y?J$@$@$@ LgxFFBRRج,DGG>IHHH PZĹ(g$@$@$@$P2 HHHH7(g}ÝW5 Y   )YIHHl[Y"   Nm {?   35cT<#'gl {Κ<@\ _q '  (g{?   _%}^(g}.HHH(gM .HHH PuxO PzJ w= / P>s>@$@$@$`r&G$@$@$(g:|\(g=%IHH;aHHH(g}I9Y   09Y#  k~>.Srv4O$@$@$@$_awFHHHPWZ/0,gu~Xr8 br7yU   &@9)g$@$@$@$ri@$@$@$@>!@9켨YPΚ%\ O P?/N$@$@$(g79Y r9@$@$@$@"@9+)PΚ" \ rIHHl۾Nr@$@$@$.gvt@@\=82\q@Hϡ5Ώ#IHHH(gSwlvv6f͚E(\04h^z!:::!ٳ @ɒ%Ѯ];tz /gϞhڴ{o$  !j#1kSfq휘NwMZ.l$7J$@$@$`Vf ו'ܑ_|.]}*O>x'k\"gn>}:~g 0?֬Ywܡƌ3R+׮QF̶rV~ڵ+z![SNÇQR%5\ӑ;DzNƍk.ԪUKU5='~mkS,ʕ+G}Ժ 'OVRڵk;䫷nMHH Oyf4K9>=I$@$@$@^!@9_ *gE$~߿.]ƒ>:uVzrq.];?z)i+VkMJJR">+T*gMٳgc([EJ~vF+g7o{e"Se?~mݺЩS'#GΓgp뭷+"DZ zJͿdY.VZ^_s& ȇt챳g8yU׬w ٵN`{Թb#JoVY)garqK$@$@$@Fr"zrv̙1x`U=xvXi9GzJXiC[EuΜ9o(;|p8p_}]9kGKo?ҝ8quR:vX/9[P!HU#<^飄Tj嬣k4h5jm*ji aY\kLLWs tG"E1zɟ GP2jT(xn' Pz$Kŋ?WRj9,b0z;wѣm6%e刍g}U>→wy+WV")'L`WZzT=hm7|S ^jYeAZ(h嬣kWVM*jd#$$sj  QI;LJE^e$@$@$` Nݘv%g>囎h߰4:Z)gM\ @` ]1}"f-իV*BTd;T+W`֬YbV*BU˗sUΟ?ƍðap-䈹^"E:ǙutmBDKk3f`Æ 2xڵI!C(uOv  0rvsZ*?6D 쁣yŋė3v7#,4ƹ(g͓\ @ sBU9+˹-Zd*=X{=)A+Q^&m[SLHJΝSRY+բ}ÕP$@9C4 嬹1Ol/7`/G9IH X Hy^L<DVՌ $בrdeeA^ɃHHHH>YfF@ s$@$@$3 ;.ںՁz7m^pu8pO{1)L9kG @_PKN   \%\IHHH@,s# Pty    Y Of!@9kHp$@$@$@>%@9S8 @ s(g$@$@$@$ri@$@$@$@>!@9켨YPΚ%\ O P?/N$@$@$(g7ܹJnB精2<&*@}]ZҒx=P,   $@9a㢽EY:o7l$ހW嘮K|c/Scwj/9̛cvαNsk[1!%}n箜-im? RV4@ںտٻ7sxOs~#M[rXbwSr~/ROUKԟxa$CmUK62]AN1ꮶI90(DY!@r2;y xar*#rV FJxxvէ.'rC}0@X!>6ϤpH!&%oKkD57~tsEzrtOsGdfb刉Ѽ0: cRl9W命C_gsɫѡL}_;&ǖk8^yi@!bp*,X?/Pʯr޽aṯTf 9;P,/s4О+N|½y䬆c][y& x r %rBIܷ/zԕxR;zo P2Wja; #]:Qeпfw;wcIڧją`i*2\MWեr -1yzFT&| bgA`tBEOT{zހ^کJQ[~R?[ǶZ%+ k>ݿY/ּMKެ]|$ ol8ysfwHdhOzǪtFTXVߎNǍT,4FnGvV(Z/n/'moqdf_E}uHϊm!ƒ?_oUڪjE*[N^>-Srs `T\;UYlZ -q!2YtKuN^Etu/%#QpISzybw̾cY!brvpt-&Zkm\A`+g슽0o&t c-S8R]z]^ټ33QLYߠNce5&q*gfecjrl9|@Ӡ\EtÙ^7pr gפ$cky}m'0=rxwmsQ~Np 5@^] o$-o#=87٪]#ސðg6Q2&]0j sTPHQ|z)*0' IDATE.٤)X{oYr1:Ԩ[ 9{, N_EݖK7AɘBQ{r3HHHH,(g 'BZ6&JMKnRkx T%Єwn`6.Al^"RF7yVC9 El- Z?^'Uv?,xCYy^CkfJB*gvm /DeU`pCjRqkɛET>S|&ǥk3"gk ׹m'wr(KGR54Zd4YG%t~om!+mc[pG&ReٸD ծQ?ܷp+G(^*X8I{,չIi/W(T²UlUIjcwJՋ<#P*7I䐳zTuRy3B+g%_^>BhpH޺sgU:6 fDPHYHg;frqIDmVtWf/\ #lZ9k4Ymn戈rcJtJu|D )uzٕC>F`vxj'%cڗqVj_ҧUYgVQ(<gr6A@U ~5; #?;/5wO9sdh8}Y<7ޯYX䬳gz]6vR;# wTJ?nKk ZS 5#ސK¬p 3/jv63;[pin"2ܑ2TN"\a!ֹrr1O쁣Tŋė3v7#,4pQzFp Y"uYƔK8 /B9H"jޛmhst m0vRO]ug{t,Cwg{FhrVW0U )=uMfTZ( ^O3wln'y^ZU\kU|KE"@]F^ԧZsV8T9r}հD5kJkǫiWΎj!Y@x8bãsY{=F]nEݘ*ꞔCr*L5T]>ݞ?Zl嬽{Q C^GXYiQ'էR1vl3<_edP08o+r|;zPzCΞxlۄ>A"Xw`/ߣTή?ZuȱN`⪿1n7bu^vs/a%%.kԲ~əut8rlʡ(BbHcow"H&Q:0qN^p6G*=dZQTR%(}wyrgbF.Y[z$.C6LDʹ#w '1sRk^4{Q}\Q Q}]5"?pN嬴SS]>jO Kiy 9;~#mʑWHpX:-GYY}A_v ]{x"y*gzI/)G grVJvR~"g= ge"b+)IMJ܌jޫt9g3/X_6I36̋waoٴ3xp"jټ'ϟ]qegEaƆ5(敪ao30;U(S.ljsgY=y, +W7.gO_8{]rv]~Jw9O7Bg=ۛţM/`lG$B$@$@$@^"@9%? UJz(5=_4?ˋ,!g*ƸB1J> gWзV9S,TU)rQU~O%X..gRˎ\[',03)^FRݨ9 afػE B[Fg/>~X˩6G5-ut{9N*g>+ YYè8HHH@r Q|F 76 {+$V*i_`6 oRs}ݮu63B=g9'r6gWAAm9f׶+>rw${YD˙   $@9q!@9OS"f7Ҏd8v5`n-q&I9@P=,^yKHHH PV[4%no*f-(ʊ 582hYrw)g)g)gsq%$@$@$@$ (gMr6_zvm^s׮r8+] (g}Ǟrrr<WB$@$@$@́'r6;;/̘tRE0=.O=uW-Sr&52k׮amXo7N?!Sw֬r1]^KG.&ԓsr@Pv[흽z[SؙqP{"xxl.a02FOb {pU]}xyT*Au{{O?|tF9H3]9k3t9>_2Q!2o֖cr)}r܍r}Q/ܻh(_ _Hh,rt(Jk6< {3)GL|7b=:kR>| gE❸Bh_z[?>E@P>H>c^Z]Fޒ?9MNੜL,U^y=wrVݍ'̲6e#7NŽ3.gG_,uW(jއldcι~&vq7, df05H$@$@$@Nr6f&k9b.۾ .]BxqKT֥Ŝq>3ʔ piW15q9.,`Izc HKYӐfv_~9yr)*k_lw;_sбF-[A]aSZ*،X%MXk MtU,#^9́\=q/^DӇrֲtDJrնrVڡhXa86cNCiݱVwSk]8w6}jvCxy(_%Ǟ# փqRZEU1tD<{=*EZ=ߵrZJ,;Vh3t ڿy5R\'}َ+Y }vA\xR͖qˏoYxFhWWUAJzԕxR;HE0p*Yelm<\,4|m&^8nЫR;Ue9jOdǪtFTXVߎNWXb8$(XI%oV]|$ ol۲R9'gs9wI1DY.b+gn^/c#Qeg;fspXT}ݎ 3**GK2rcp%,d9{%N/-{O{quܕ<`+8HHHOrL9𥜽p2>ϵ鈒E  C͐~ޙ?O wrXT+T&L;xvѡFm+h=Woqmҕ+{kf={4j1y2%ușx\<ߦTLfVrR΀\lllx4&QqֶQ!rCO(y#'BP>;n\,>AH jeo#=\dksGþE Jc΁ȅ?I{c΁ZVto?p(gELi:.GҎ q^ȍS>W ˩{+T,$}EU .ZU|s^8(U wo!I"$jE1mb$eLͱ+5~DY}]0ʭ<6؈|u~|k.~K[rK患( Lh9Ϭ,k.}WeO)K\瀫{uY7OrՋ}n;b*YWq< xwyr6?#WrKeobuJ2nƦCxܦH=Ǐb%o[a!!shי٩a帘yg`ҭn#T/U/ (pC{:q,>\޼;aМJ;q%]g':`m7HZc͹yp| g ŒCG"bt{ζK@jM!+7xJ'DEmE8Y}^{H~5 q~UUzYᾅCUEfXn?=D9ZEl- Z?^U*l;YeTj/v9 ~?M )hpMUMx-}A')ƒspJSr^2:chVQurb7:n:mfCiDy[:ʋK}!qr'06*gG7yV>Z 9jnވA羵i<7VۆǶvFxokyWKY<\w9GYa$?mێW?mPdx56++ ц@   4q7zf_Y@ g^lULNk9{2,ڈU?<L;z$U@zMp$LƄCvØf9q Y㺕*c=G{;W0gz%~{eXq|o%g͝c@ΊS{\UJ|U\] @H`$ړ/}W]6%?`wFZ\Aw-JA䣸!uˮ_WFU *4ܐu/~SkuみS9kidzGЅ}!OBd)eu~+>BhpHiϓ/\ cď j7C"efqYJZgzs,jYGyZL8/DFKKh(.h^Z&/k[[ʙ䲳rt8Oeb/V;3Y)\PmlLDqIȋ&gWƩ̳}!ݿ㏴me+1h RMkH:  Fij oo[mv𦜍)-MSbM|e 0;P7+׎uxnX.P8^v)N!n2 .2 H:ѕTSy؇[~–C|?Ush"h+gK԰FYwcYbo[:!%| 6G_wж0Oc!eXrdcI^۩vzy=B:U+gQ.=Van$\jK$@$@$@#@9= 䶜C$c]Zwrq@K];M9E9Z+j͹BrWͺVO$Yn_Sf{;{͏y8K$@$@$@PQl> l@]:ծîcwGS.ސd^}~nF1Fo5? ;sHHHH{(gǒ3!Y? %Y Jt~dŬr9\s]\!|u@E Օ,uǒ Pz)g#~,w*=h5:NoFgQ DEʊ@ @ګ+M9 -%   >SG(g(Xf_*#t(g}2J2߱r "JQκBcIHHH(gϔ3Y? ٗJ9kQΚ(Bd F "JQκBcIHHH(gϔ3K%   NO='##CSRRج,DGG>IHHH PZĹ(g$@$@$@$ri@$@$@$@>!@9켨Y*gDp{B+02'OQK_m |E%   (g Mr60 P(s0*5}L@YӇ $  (gy=(g!@".2hY3G?F9q*IHH/[Y8 P}בlBY77FHHH嬟Yp,&@gbu _PϝkR@r6ͽ 5ՋEjrT㘼/w)V^6y!w(0oL>ج"^ ^nMn:4[Oy=[5[Nݠ/T{ Y|@lpP~$^[56F!4(WetBEOTյF+g[cU:#*,oG[Bdϫq2ZZh9\=+E -q)+?_oUJ6XxxzUjƎ6Je}ݎ 3**G8Gu\z?,+K߅zm."JP40vg{ıKյd+m}7Fڅxgxf7TǟŎ_LqQP['.2ȲY VˎmZ3x lIɛѧjąǨj\͸rAUKl;1xi0DzP9IbƜpYGm윣oF>mbдꒋ$k9BaoFOyO3Y#ߟwiFt/%#* miG8z>8;{NLe#lǕ,eybzf@$@$@$(g9;QJغ+݆5'v N=.U-Yj&}*݄*xalEe0h78pYIrHhz] r(7.Ϛ<t\;T[9+?LiLݻX*BU~<0H<;l"Q e "]h}t(Wǜ+ѵܭ}Ra\0rl9Vh8Y]s[G7ǎt/_$rBM|_oOG/l/2vO?w?[$3*F[~tL{v}!hf@$@$@$(g9ܻYmPjGG7)~pxp~n7A\DӞ4DR5ZaTQ$aqW]9+2? JT NxHi=eMS՗BjmX~luȵE!kzN%c|CU,bHzJ?L9 aQht -=gN3sCr{ɥ} Ȱ!~z.[KDZ~Tv0 %G7yVclc֛pH!/4|̖Z&YmDŻTx1/j ׹m'wr!25SeKB{ߟ#~*{+>R_*q~Eҩ=.Y|)[}hYײ}69I9p$@$@$@Nr6 зﯕq+*8T,L6V|B!aNT=/\ 2Yڍ(aK^3N/r}5E|j]HVurmJ&UڮC>?pT!%VquQ44!9;#5+ߦDW~SyHmf6(F"=}/#9fV}~!- l~ x~ȟ0ry%*;9zj_z(ճwoEbl,\)ir:̌rVA'y#K7ZTpSbgm^DGhe '/gx5ܙrj<HHHGr{,9G9{p2Eu- ߨKEvp(QܩVquY"=]zk[ЧZsMѰD5 KN}Mz<>OŪv>['gp|W{[PZ,HUBEom嬣K*Ljp)N9,"W,-3leFFOq`PU9cp4,Q]U[rS{-3Jӝm V:?m$M/ޱ9e5<;1}9I9k<^Rd(gl^Hjk{8G){ Y3$@$@$@$ YWhql#rV}tu:#M\qZ .e]_Vv9*:o.V/k笼DLa"RQpo l^KF`P8yVe-Q\ي1q?;V^%-,^ݑ{ݘJ֖|V8Y:^ 5Q&Ll9GTIҒѪˣ^ .#9bס:y!KܑSrGZs2/O~&bkC76Lrh;S{VUSkh嬣ӞՋy#U_]+i//y fPzξ?I뽞og&gF{R>V H;ΤXxʐ]RH9j4.}!_I*J^zYLݳ=+S/]ѵ\S񇽋нbkSw䬈Saɑ9O>ޫb;U^c1u(TC[T> 5=_4?ri)K(gx8ᳫGC[ ᎜|nZ xk<9TyQ}Ϧma$)_ۗ=>_䬣ӞՋyNJ)/pt\Ozz+ըIcr {YG9ӑ !|v7QYHHHHU|E_l 6KY&@+,cNjs֕˱/SeZ$@$@$@$p#YfE@ Q@&11'5ޔdc5_(gE$@$@$@Ir67rn5}@/ȏ" Xz D ?lvY_uIHHH:YfB@ )&Ԇ7ʜ0)gM"/r!IHH9|`n1YfH  (Gkrgͅ)gM(   ?%@9링㲽CU9띫r   0Ӏ'z]TFF$ËNHHPcm<$   @#@9h~seB Y Of!@9kHp$@$@$@>%@9S8 @ s Y"   Nm {?   5aP#+gn  {Κ:<\ r&  (gC   {^(gM.HHH(gM.HHH Py|PzƏg ?! P=l&@$@$@$`jG$@$@$(g<\g(g=dzIHH?cHHHw(g}ǞW6YK   05YS#  s~@.3zrW=g ;vWL9grIHH_6rVo //)g}A$  tOnHHH@e" oP;j& A$@$@$S>ϋ 0>P2 HHHH   Y_uMAra"HHH|L>/O$@$@$(g6ܸe Yw8eee!::ڝSy ـ37G9iӦaŊHOOGbФI 25l̚5 -Qpa4hzrSZZ^x{HHH\#`rֵu!  $mO>V“O> bΝ裏p-W_55/K.E߾}ѴiSB^?G$@$@$;(gs+g%   g(g5W/SNJpZٳg#11Ddd$كq)];DJJ  ޽{cƍصkjժ*Rv޼y1c2֭&NTk׮C_~h߾=,UݻwG=n:L:FJ/#vw?k"GTJ4o:u(!'rnݺj' Go%XSO},YkIHH wPWJ$@$@$@P:#įkY:e ҥ"q5ݶm TjJXr}YCLLu3gow<:Y4h5jm*yli`^GNHnHH|DrGyY   '@9)\7F_5kfO?^oZjj#*ڗjYV@%SH$@$@$@FP1;r6++ ҿU^ruI-ZTٳ'"##+"ISSSUe1+gE P}h́ 9{lpU+2U ujuҤI\;SUTJJJ_X_T)5\:-[]p^f .^r̝;W [C+@ {>mBrc$@$@$#>˒ <ـO+bSUĮi}ed޾O)HEEE8) G(g=ǓIwH<IDATHHHmnlFFʕ+R*FR};vLL|CCCUonZYoG Pz)g$   #(gP|KLrV K?ӧԩS̀^|Psv  @!@9(>IHHFrlzln#   P2HHHH7(g}ÝW5 Y   )YIHHl[(g$@$@$@$P2 HHHH7(g}ÝW5 Y   )YIHHl[g,sHHH,HHH|Cr7yU`Ie O$@$@$@Lr6ϭ^9+?  ?:ȼp?', 5{Wײ[=9ݻTFFsp:#<HHH;a!W+g)PZCIω]!r/p4y:h%Y9$@$@$@$(gs.6=YӇ <<&A<'F9-:[#h%Y9$@$@$@$(gs.6=YӇ <<&A<'F9-:[#h%Y9$@$@$@$(gs.6=YӇ <<&A<'F9-:[#h%Y9$@$@$@$(gs.6=onZ W.acL=.4?i4_t"6y!w(ᕢJcPxlZ$չ_at9<9|$G0+u9c=֒c|C K>g$eײv[%G6x@ז?悧of"$æ.ryKMn:4[OX6g_}rW#ϚEʢOQ9 BqqLVV\8 gsڍ捷i#k򄑜|po\osW.bm<g2{WU?Dy))_bbiSK{6cSj:5>1N5VfeaLԌ4%!"*> E]s\q]>{־;kҵc.|}<Ѯ;tCNp<[U3VQ( B@!:9:,UO %g]0ܽqkOz5Nǐ3,emgQ3o3(6FCXW{9 b%8^tX9spi1 SٹZd㕵}dMlVLYr*llY'r0݃ZcB!eKŮ[VlU;N6svD´/ A^M@9*ִMN#a_֟܉oO$;*reӤ:R( B@!u 6uSmA2lXLJ~DžЃc1ȳ`Y[;l8 âps}]\Ѹ5wө=;dnVPZ m'bn_4K]ƢR#| ǟmf^-ز^oĶϔyFrg?0@FBQ|_F 0,HdhlcwmV V 2rw}Y,#+3cxmxl+vHu 3zj i>bYz~(:|p8^\ʳŶ3'=6!Ư 9oDejqr1>ڄv2䬦,eH~ ?#ۧ[=]p>)0;O[4꛷}r̦D~Mȯ rV䛼Yie7άfm,:uUx2=긡L;)~EOBl1,~9f냆qRj !c7O{ź"ٞe 9Kk^ąȾpڦ.e.{kӶSGenOaolU3MX%B@!P( E֪T8@e~a1("k@.,oYozX0m = Ǵ66 bVɝ9P\^l^!m1e2i>; ~a܆?ȚO%d16t wƜ=31(v,ΦY&M-Fq!9Z1%-\;f#ػD%41Φ=@zhXƇcĎD-9Ke\T[/1hl@=?ۿ}$PfsFvl9to%9/Ss2F[N_ۿ 9H<ZTrٔ_㹚 #zV'9kfF1΍Z!6 %[z:V(^ FB=1HK39腆vYT-٭h2}q ^&+r֑*CΒOzLq[ e2c` [3GoPF~(rVB@!P( A@Ճ"Pr2({ 4 ?c̓;i$#n(3e bXxKǶ-/!!#"}17syBD_>)ԛHe"3+4FtRdCz&fHNo?mYx: vp'#,3̻IC&g y٬̃FRmǎmp놔 9;[F6e`oW~C'06]DI0#:\)LޭOGYGʜ5)Ys59\蛎Y䬙[-9IYbQ0*Gf|=ۣ+uod/K39r lX%#;wY8##qUYZēۮ0v/gSb;ERyƲϞ!m&G,-iZ#$g{#6„ǀ23gl;C:W۾9kfS~ɏjr`|=HW+/`ݛe)H5ʐΰ @+:jϹ#βFik4+{Nd$gʦi0޽)kj~pߌ÷iG[B;`فc4]!)V|tͳᆺXDvh<븳0BjodI>0V@>DZ'7sauu){j5N,՜]rω$VsNۉpԌHe]YQ,e(OZE; Dp:Z@ӟj9KP n[xӽ}@cX\!97DŽءkbDx '|dCpΐ$_v]^^ʀ/zزOue|̦5/[aIwWE鈞fv`ͯ;6Su7)FR eņ]'ό/*e_(9KqK&r9+̓#qU%(.l48̏ XWGe\c@Z<.3S/fx)rȣS( B@!P}(rV#@*KΒJ=XFҋ,viwH'ZށO??}g? BJ'Pm>:ոTVjRkW #a}Ånq̙7 DPݷ EeŌh' |;椺t 14:e9Kڣ[As$"{܏ 0E ~zd#4öeYKYm5"ٳƷ3&>AR,NtY^y1Վu-Kz>j"g)sFsY_$UY"H+ܩ^X쭸3F6J!g+j5) o}t4YD5g eMԦ^jr65/K蛎)g#]lb Q? a1UZy,NNѼ /Q;3r,~9㗤ixȔ5%{8tJ'~,"gIλ#pOd/BOGek/]"d5u *{"ײjԟ*kltR) B@!p u kWר5ZlLT( bu]VYW}=_WdU#}_ e3ѣ&)Yk}=jzSǜKGMy% ̔jQ@]P( Bw9F@5s]MF8%xMuܰ//e.uUH3$Yڔ9+F~y=َ?9x9l͵r)rZ)%B@!P(E֙UzI!Y)T#䨼i8CT~k']2(_oqI6Z( B@!J SIENDB`icingaweb2-module-toplevelview-1.0.0/doc/screenshots/tiles.png000066400000000000000000005540111473125420300244720ustar00rootroot00000000000000PNG  IHDRgY IDATx^ TUQ&TPsgQJ+JKjnfK+-Ԝʜ!MpDTfdPޏgbk2>y-\Vn(@ P(@ P(P gkԛQ(@ P(@ PPvp #$(@ P(@ P(@-=dohlW =eL}(@ P(@ P(P]|\]Kレ{!:(@ P(@ P(@ TW8bkcO[LuJ Auj=.(@ P(@ PjI<h {kK\JBeHɫX,(@ P(@ P%PmlWwsľTO^[y)PYA(@ P(@ PjK@pVZtpž)z@||8 7ڟ;Q6ֆ:(@ P(@ P] KObSvA32:}y8 P(@ P(Рg&Wr=[)}cՠxr_l< P(@ P(P_gO$f,>gyosWmlOGe2op{R0|K;Kᬹ$9(@ P(@ PzmWď'czÿCqix跣Hɫt=-ؓ}59b9p -ph:H P(@ P(`QGEK8x!C+|ڹ9^ nUD<ḉ)Y((,K(@ P(@ P@9YM;La1 r%m8|]6ƄN>I[NUYmkHs 05f͏52 /@G@L*f^ľ)5H P(@ P 0:< ]@x \H) b5HuApv̙8~~_} \xsQ51M㽾m0dY[֞Oӱuj\ (@ P(@ P(+`t8Ou$>CVF{:ت[v)-KUZH[َ'^džD^GV^$|2!(d>c]_‰똮uscQ(@ P(@cg%蜦0 M{Iµ1RJTFO܊+;G tףO]ѯ:LӋ؋'PlBB^yUe۾}{,_Sb߾}ظq#MO>?vjI+k Rsr ~ R%. Dk\;_~6Om:K )'.~ZwT}sP(@ P(@mYTR=+MW8JuobWtJG4{=ݝ>R:}׹{bb_]~WU;T}58V֮i0eL}ӕ}=ٻ5ԕyվ@M[lo3<ϟW йsg4j(svolE=v?t*/n?[ubc K}~hG׺4ܻfn(@ P(@ P. JuQپrq1-\]']Q8kci!ҚrmCS!Pg8"_Z̡ X%hU`VBMSUtdU޻6 u R쯿Zݾk͛7C"S5+ꉬfpV擀vvݶ(3*I緝`VX],G$ O{[ܾ03re~(@ P(@ PFL gTJoNMJ4%,||'SQ8`3ZHTJx MuUjzjaJp}]9j UWAQE}j kTӏJ<`@M;wTZMKKS=kTkC6s2oـVeg"vYY}VO8 (!nv68|FK P(@ PjTp EXt ;-/ײr+=٠UelTVΖC0Mup֐uh+-fEH7+n}ZVW&ٔ➳RvϞ=x7 Uqqq3f ,,,0|iwAW&?=FRkY~&ՊY KNxsyl6VxZCsg P(@ P(P Fv!'u.I~VLy\J8i`pVzJ>zA>p9d5ʴV ѢE c6 /KKKU5;iҤZmkͤՅY=l'_8X+|S(@ P(@:/W8b[7 Z[cͅ'^yp-8~yV~5W} 7iwL[)l]ٺt~%3JNGf։buR(@ P(PUڭ4K|=?Gf^O@pRzJըQ?Lsn| %mZ lck]pp&UK[&MMƕռٚ7(@ P(@ PEUU9rE<=a@u,TZ ?==>M܎jglqxו _{):vFvM܂B@6}9*tǍGy9 (@ P(@ PU2T6VHP7r #* ge7cHr&}5) M]9+cj?,5+ `%MzJY>Dtw'uf z 0Ջ;Q(@ P(@ T^l5[XK*f'm9U1 RY m5}suc # 󆴇GŒvsձcOVhǺ.z}gkWlsV P(@ P(@=z$ NS4ib<(@ P(@ PF 056 *(@ P(@ P@`8[?Wm&f0(@ P(@ P 054$ j\(@ P(@ P@`8[Wkffp(@ P(@ Pz 0՛;6D (@ P(@ P@`8[?WYM g R(@ P(@ T)pJ"А6s(@ P(@ Pu[lݾ>\]5 0f`O P(@ P(S,7ٛ)@ P(@ P@ XxbbbGFH888Iqr +pV_)G P(@ P(`nlZ ޽<=pZ2'| z5/#q )CA,O[X5 ;e#j8Z>4Qc"BC1gs gkqz P(@ P(p ݻT'մ+V,G&n{f-8/Juz#0{>$ɘD ’@:Yg@pN_^.(@ P(@ 4h3όG޽?}jT\HOKx9X_PX#6: aMyYȼؤ V .@f<"chvzܣNH8}͓]$͹2 U3(@ P(@ P7Q}݇?Vˡ⭷h2.JJ.l''[ '.M,&h D_L ='XJElt:l-,epjW\^4;lV{3x6B^Dۣe˦cܥnhTE0+{2א(@ P(@ P7Q1_A˙]xÇOoς \q7KǦh hD7F+T] d.%j˸M`-\RqR4fSi@38I,1 bZ^17=1rJ2׎(@ P(@ P7Qƍ!!3<[ےӂo?liA&⣮ M/24GpBj|a`ιiH-~HX315 3ĉՇoCC`1z ̝(@ P(@ P$P]|OOO0VfH8kZ_r?$02eѧw^{15o ;;;7`ɸ[1}tU駟=dk.ȉJYGGt 11zo>:ߕqx5 ^pw58JzΦî<,t4k(\-}]asI Hk Ma#*WwQ{dD]J#ic/#ɺ\KpQz[4?=fbzHXЄY 6c7n`8pUBBBp=j 7N}8;;/} -† 0zh|Xy 4YTΝ;:o[l?hk*d=x .]ꫯ`iiƔ*>3ٳ?3 E9s 44˖-NWvZZJU1/V9%>pXpVJU'|[ﮢ9 K|VѸ'hΘpڵkwCh3g΄c`pVNP9ي (@ P(@  PY8+-Dbtذa{UUg׮]UXzyU)g޽1o۔˗/ot"DlO?:V>Xe;v@qxqIծ|(JgjWȷIl}Zj,V~WzD>d޹s`oܸ6MBW͜e YqK>)))CW̤^Y;(@ P(@ y*g5' W޴9993gΨQ?h tС]SY %9%[ TvJzmٳ*-s:ˮE%1c:uꤪa%$lRY+K{?VRObݺuT\ΝUTJ&S&Y{g;VUjc۶m*7yUR7XY?S5N|O[_޽{Pi+Ҟ=|:ޜ$j`o!bpTQVXQ~Ie{琜>`-mҤIW?\ڛb˱|$|Hʇe٭&ߚpVU[$@~g?+i7Dg8{sN)@ P(@ 4dYI(+*M Vy @XK \F?搿Kіrᅬ@Ւॗ^RYT~Zgٵ,_+W,wI5j^U9+aTJ8iqFU:{lnZIx,yDMrb9)DEM)ēB2\Mq]իWz?_5R9ېxn KpV*=٤I)euK `Vͧ%Klo IDAT0U}3%R/>0/IME|#Da]O8+M0A};oowQkorC g/i-KlpVXrV9_Uo= yXzwl(@ P(@ P TJ׵kתjKV[%OЄb!ϼ1$K%4ن[1Hpv^6-_J+ۤ|"|#lW-2}KJ x@Hq4e464ڤ`(iYKnI UIJJBӦMpZnEprr*3(@ P(@ Y *T*=%䔰R-A,5WerLY?]IyI17@QCpVnBcǎ"* z/"z/!d|hx&|kzVT9+-[JYAצpE}dI|hʱeV |l? *:(@ P(P3plJ1#JlA &TzVO6 po߮nC=#J _}~Ȑ!*tOd%9^9N$XV ]бZW*`%QmMbM֋ v feRel8+(IuHQxʺ$[xZ3*Aq;%6҆BŜlq:*`h8+4~ԇ&T͖|PIɼ|$& dʦ]߫&U g4ݖyJVքu|{ZeLrVukBcpo~pV3|9ɷR3٤|k:KeQ(@ P@(z6'9FwuWU2˪CYYz'dJv3mпz<9 P(@ Pe{$Yr?$+ҪpzGƄrJM6cDT(Oۓ_2>n-K4|ʓRL5|"L/~Bh"KɕuĈj? cw﮾Mfc!2f.]TUmՕVY[#J5TJT4l(@ P(@ P0YɄ> ֵs_ł<(@ P(@ P@`8[WX1O>^zWO-|wT/[y<(@ P(@ P@`8[WX1_T#鲛UzW5rh P(@ P(@= @} gGum6$$$۷c=Vܯa^-(@ P(@ PhX g(PYOS(@ P(@ QupY5#pf9 (@ P(@ P@y|W goϓ(@ P(P7ndW xG{c\igKpn xl+38 RΛ6k+|o{Tڃq>Ii]}EXS&yMg999GZZzȹ [[ r=_+p4ẩSt|Ni&1.p_A(@ P@=8<D@M\\wN IGq9~h1[cܓSgIm-J1;ܸ5LT[󚂧kIIIx" Mc-,,77R/;AV~4e@z/p_B(@ P(@+vX (xNũ(;86Ph0X3e#Û@#9_6M̜om9pj^rW3OWMigey&{=LT[KVv8qDoCKKt5R?LD[`09ᬩ<^ J琑WVXxgJO`ަ^p(@ P(P[Ml)Prvp"VuiKl3c \nڐU-eVa&.w]y f>]|LJE%8Z[ab?,8~\le8T4RA|,EW{|{WXYX!w:A~nXߋn^NY6PwD F l&07^N)Ƌx{DeW3|wW۱=יS(@ P@:5GCq%5N0M; jۡ9WthQz>FvJa3ḻ/Bz}&u䅇%ۺ]ww-o\ZjFn.wZ= =O߲>Hj_.+E$ B $$8bŞp4Cncv,Cu;oϽw.`7uB8d,?Yý%Olxaq@RV~h϶N͐{k`ͥU`m?MoEf~6^ڃe{U>yNN)w5:tH ..1n 8Рcw/}5p{FWG.eނNHWG/chZeilk}QIx3WP. g ܹ #}}\!~[{*=s-WbÃ&n=3Y O/ڃ}ikN&vKxt1D'+D,?G{@;NFϥ*rw\wSw<wo |EX4G'cӈp)= C;{H\JÊnCF P(@ PA g3sUmժ %aޮ-xhZ򠭟BwBBz57K8{=#kw^B\R&o(g˚?!h[q gm{/"vLg g=~ {?5ڻ^Ż]WՃjF, /N߉qhn[ƙTiͮO8{c)^LMk7 F͑+NybwXy8:} ºUIKD]z4rƷO '޵%:dߌ?Bg|p3BD]ɔ(1X_^\V ҋL^0:6Ǒf gӱfƢGf g;61T)2=]bxgܵ0.fSup ZKoVϯzqٙXU+᪮M;d ~UûsN\׳0CXZa 8Ny. >8&tTJvxW+-@RkrVZH۫ǥ?N= uaujtm97X{G]WR0pWv8(v_xv`ߣ=_~ SlRIPnc@F P(@ PA T@?-!7?_އ1vw;E͝;׬J1qP)e!PrE^S =g6jKN`չxѪm`' Qᵮpv8Uq"n(@ PwmE6Ҧz~mac5ήv1eƄpVِ0$Y8^;RsY0K(H*wg`eTO,$$\`Gp6sEǔbD#/t`vW֦Uެ+^8 7Y*H&컷ú}^w~ߟیu~3'+ո8'S.axzJq7w i#*$ex,8~ _)~Iq_ ii[-dT{;cݝԜFG0o|p?oa@ػX|5[A;ȢXaIZ qG`@@*^20v+^ 3GϠAMع64a7ӡ>ûǩ|g!nϟUc꿱amjm9B߰'zH|:mW.}K=Kv#7I7Tsrx08ZŚ}>:tQ6|P;qEN~֜Ǐ'cpZxBl 6`$BcSUJY[3r碞En/Xy6Ns(@ P(g`Ľ"eѳMN\0)N5yGowި宍<޳QEzo2E>ں`Zu;~/]C3WŖ ]!iDdᅡc>fɥ+gE"?FqMugª٢D[?L(:{Z`;?zn9RʷׂZAOm3>ՃPY[Z} ge3wE&MmIlg_M;MQH - g`S#h[92**vu܉wA`ʬ1(z֦-0s:x18?EФ0Ohg8;잫)xsydTH7{Ɏzkށ-M2Hzv8+kǤb]ö.eb^e Ωk6{6> V=V]ߧ ֮Ю5w]ιڢ}'vg=hOEPƞ&(@ P(Pw* gA_؉qߣ!`_ު͖<+>FsUzjkp5q o=GG`v@>}6c8^-caeQө1(&xxgM>B7]!iGw61pO%N8}~`+u^ۦ{ϫ{*jՏV.ũԨRczE?~jPv{>.cաC|m $gKOOɀ@u7gЫ m>*a5[ey94Bes)VR>VEFVlXeYN1gݰ>9}< h \N}1j8{ȍƎe#0a\4Sl*BBҰu:x1 X3лCv@QB.b.աTsaq'!q%1e ,v$ [ i<, }5[kKЇ14mH)ʼnf򸭡<р@Տ(@ P(@ Tp6;7o^zu4)]'qYxzxIZCgEo1됌w^u_?x٥]W \z`+g ~voF|=`f3Izj/@׼ξ/|p'N:_Um8m IDATu,G1cAW12\,u>vV:_gukXxv|=^qRI>_jR9ճwܦplNFW{, >; c=1pUUv2޴+g4wQw?S.m8nl8[A|?_´Z!2H܈3b؋@杁Ec1َ [1m4ˍy ;x&yÌY{>bCƎ97o Rg72vޘ,-b6bP0 #: z\ m3F/U:l$ caBs2u'aXja77s8WodFԾNv(@ P(@ ԐpHt$Yn[#jp /Znξ=17C#kն =cnw(iuviH˵ǎv@ZVcY(/&E~uXڴxNTW6 fH#&t~yǯE|m_b㈩G[k\NǪn gK/_~xGzSt]r?|^gnCK̦9PZ={Y:N8ʶ5ۡ9&wmfNp)- *w5gْ'sEP)bNÉE8 > aD,:$,[ԃV%iU>3TیP̝AW5_,3 ]m-0=|L."L]5V(wb8(@ P(@ Ԛ3 lk`9 g19Ҍo8k9eښה0V;32Mʼn- ظ!ނM҄A1=v#Cv!mQ&gt5`p ;?a]X428>:.҆ tm Ext.c̸-@0;7cs1uG-fDc˼a ft܇2*ee 3*ij#8l^̝A"8u gŒ!;9[o0u rئpTAO P(@ PF ,}^4F+ +NC 8afm+DQv0纰Ĝ2Ymk O8,SX;;;tXT8R0. gAF"] '>lUp0 @ukR`{9.C(?읻0g - ;" {x! 1cI.Bbӎpǐ  m.աL1bi&d+YǰH"'jCpf H\WU*po P(@ P5dm@AA,x`0ԭd鏀 hXа3WMcenmK>)_!ξœV2Qmk%+7n(,,-Sf)}ڵkGGG4 ]7r oNcWod8kt<uKlݺ\ (@ P(@N)9>A@cl9F^ˍ}j9p29 pDGE7UˤϵWn5v3W˜2y\M=󃗗Wz8 0t~]-(@ P@H RҀlN>MtDdy&q<G:vHSL;M;7 l[tu. 9;o$ %I6 8˜s$5)X9##C3gVY/sa 8{2sM9ErEW05gq(@ P(@ P~ 0׏7Qᬉ<(@ P(@ PhF p!\E(@ P(@ P gu$pL(@ P(@ P`$p!]M (@ P(@ P_ gj,p̠(@ P(@ P@ozSqdž(p!^U(@ P(@ P gu*I@g8{jR(@ P(@ PH, 7loj'<(@ P(@ PΚߔ##bq(@ P(@ P 0m`cYü7(@ P(@ PΚϒ#Cq(@ P(@ P0m aYx(@ P(@ P gM7Xl=x\:(@ P(@ P@F O=֎Ǥf`Yvڥ8Qơ1yyyUT1՛;6DC .`ڴi(_$r ^~e=z*C=y`YOn;Q(@ P(@'pya0bg7`eNyU˗/W g  Ipǘ1cg dׄΫ?xzzb}(@ P(@ P@8xZxۧbuT0~ЯXPEt&MRc0moN_Ɔe[U0*ժ3f@NeՇV̬lǎo"88 BP̥?7|SɓxU8s]rl]T}i%=z Y7]=geM u׮] 6ljs uRU}vn9(@ P(@ P ["h|l/Gpv`ߑc KٳK.-YG`5$z 7lk_Cvʼvdwg2om*aǏ6¹)@ P(@ P@ Tsʉg>lEX$''3@u 8ϘDO ioNnlZZ^uU /`ŊX~=>c.(@ P(@ Ph gՠ@ޔ'c}B;;|Ik+W"99A߾})@ P(@ P@l|*>sH&.~Z>o2S׾ٚN(@ P(@ )@& %PX+hiƾ*W%M=6@XD,2rm1t@\*=7s'/@xqf {w? 1}`?'3fBgU!spj(gr?2(9:S &ol^:N P(@ P(`l."65Ȅ5}퐁س>p$N?]) g!EuX0/ mĈr)k%gpֈ_)Js%~NW -w,G3u?Llݺ\ (@ P(@ P`R8qbf|O75`ԏpcV\[.#e ޫ1cQbG`5}r.աL}0|8 W! ;wD N¨.j,H\1rtp8ZX%}0vB.^ѹ)%7;,ºB;7x&f|G$Pj sxw@D ` &4_ w ݬ:"h6&]L ?{gӹ_% BDl%UV-E[ߪj/zK kkJ)*'Hb%Ado89sf̙3O?ʼy7y D"@ D"`fe"Oy, Mcums#[Dn…h9e,^i"p˿aDD2"qa,HiY5`,w Dޮ=g C06{f}'_y#pv,3sQoX sacnK 3 q؋X1erw):.ŕʨD 0}7YA ,X/1cZT/PZ `u/P >Yv = D"@ D"@a,I|>0iFDT{Is0IS!,Z!bǰ:pb3L5Sa8p7/ &oCYS%w5sF!?/HpQ>Z{`r35]Gu1QXzDtkiԾ!䃆R?Ǝoc3Y FF±ƿL]Gm5{/BǎǀPƅXS=:ssl[ۃ1E}o~2ٸYX~'n?l$.߂ qE lSSY@Vf N6v|+=C=lbM S"R<08 6$ Hv^ll1|Y Pk2 Gw.Φ] ܿ tF+΢w 4ŀW 8VsoW+ gd'u{q9 = GPVNfld[}x!0'$X1!@7᪦Vj}|>d(гϺtkvsQߚk7Az↨  bӅ}; 1}%ۇ,ɻ{q70ͺD.5gtTR6.ײsrgLn54cܣG ͣƊ`T8ƎocMo峹fL>6f<+${<_?s ?Mbvk:W@$<_w(N~nulhuXbWll63wtk.Ao.As ZǭF"zf5#[UjW[l?Cƪ1BRF(.χrU*D7WWg#|^hT.\\p1:Vن}O%ZbF\b`|q? u[crbgԠ,h;|er2ݠ.f[Zi_` !Z_SZ6vvrƯgbC_XQ;GP >+o-1elJSd[Xl")ח99uÐOTJGR>A⬒W e6Bx 48߸er{jY81SF$Hng#l&b\ϠxnkLa3 /YIzPJor2-n.gM6F)Prƿ뇸YxZB IDATye)\,! M@1b-Nd'wMf">(Ǣrqku{kcmׯ7 B)J$u3n5}LdV~o]bsMRױۆ}JǙ ]3x\_ S |Y9kEl8k 5P;J/OR{$Ccbb,Z#ge8+u=]:ֶD8/%/%9ۖ!=/Z;.N%cL= /ך 2奰'UGHHܢֲ16A:-1w|8l|@sӹYXpbg'5{;.5>78|tiyx;k^u)Sa7 ˻>;W'Q RRٸ'{'1/e Wn-ƅ=idܽ:^5m|FwؚPJmm,O{-E˃vń_:s -M/Bv~ KѨZ|qrJl=5FBԬ+̆tAV^6f7&4ՂRE!6ɽ~Z7c3'HL&un4#Cbcb>j~uguNu-b3\ߝqѻyZi_Z?CxH-4OIE;/ԯw)RDB5t mlHqA;VkTvqVXlkwsEcF:Ƚ90&i#+lNj?vR5&ZYwVjϮMe"2,;dBҍT$ff߳:ĽD qzGGW Jm| LNZ+oargݴw?wkT3VjXw1q-RL\Vl};XIq G+;C5W/,o'.^q>ligc4ln=}Ւ&Q mg׭*f_/9 nή6[~V]5ozcuNl fOd _vRgJ: 6&Ow qu} 5B~0v<(/!UaJ?B+AC9Nwr<g)rWيLJz*n߾;v`̘1$sV,(%Hӎ$ak&r/)@>rU5Af=;\ k8+bbI@,#8mjyw_=a":DC˸AXoˣ4ym"jd_lw_ mxHYCW1ht5슟>s;?FmH7Y԰Ԝܒ[0K#6`/yFfn$규`n'61s;ir>ãN;T/w6v|^չo4<4VZӝ? uZopt>Ӭz=_܀C7QPZĻFF3.8 ?rqA!qvs>N`uV[:{zc~۱x~?^žsES,Vh'HM/&Zǚ6u`U|lw 4$Ώ8`7R'C?鼩፟@ jwLp_m0z6[ )̝K`=kJ95[LI]9BɔBxu$3>7 uTqVl0tۃl]S{f:X%}3Ե"5?:[1V"gYE8gsVjOCop3`kSRgחU] Rpz桹͟ \3$ZЩi" $VqV8F7"R~9yan,i;gpť%Hi[O8A= GygY{s` yͿ8~ =pkޠ+1n8ۼFC} RY* g[Mx0eد'n2kgXWw="#9o fg?3L{rCLSAIޱJ3H&}E!㻎*ΊƈSBmP5P nPew^0E뿺g)H5ii䜁8 l=| -DLi}Jl"b^*|5AfUK3AQiG MK;MGxfwP_;x>9X {L=Ù-`aB9bϿx,KOV9۹cxDapv㑳sኵ!X⢏y7X` $m]Ae؜-!ּAWb."g6)Q 6bmXƺS޼cxPǀ(~][}ˇ"uwLW Y,.TћgN[~صnP$+wDQwhmf@µ@τ'*Z>;n[l<";Ǘ,_̿$ C7RvjZ6fNoaخڼl_f{I8^C7Yb#Wƥlj+g YtJ5t3d;CINL)&V Ǵ/q}Xn ?_((&Nݒ%g:޵ b1qVL  IB$q]XX)\ $΂HXl)}nNg1 F9qVx`w!C~*Zl̵ag4A2$%6qnjܔ580?c-yIcE]99^U`nWyJ"/#r2ukV#"f?.^ ];x}\pa9Y9ir,K J9gmo&`={>Fhtrk{bDXO.۷.nr.p⸉zlYxܞ[X+E׈yfPu&& m|0PZ"1a9LLe7'$9ؚTį+DJ7_^^,nTYd{]bâXo~{KjEl|HO؋X_^k٥Xw~k\ON<2,E!0;,Mj0t#=o_м뉵& Mi[Q"-"]:N멡KlrD9׸M~YCq~I9Ll >|3w&3d1qRL{Z߾d~a8+_ N )w=k>zd8C9N-;/~B+]S=I8_aժ4駟ۻ{Ti޻{Z]l\+TWZ7-k&nfgꊳb{}xX=pMSijڼ7nQil5\t_Zbuݴ܃]W{_N4X~4;6JMj9DQSm*,⬜X %Y!3;S 1M/4!Ej5ΐ#~~r&;(.YKx1~;cuG-䈳}}煠*~")RDrve)wfnjBᙲ3)F0%ił?]X,)RTݵE<)]:ֲAsۛ#К`h%i»X/~oQvrƯ=S鞃%qV+ڲ;jge5uֺA7u|T|dcVgdcǷ uk Lf vjjӞ}PM-5a\xc4s*WUfj+M#=7zobij4~)ϫy?}Y5Zd5$Κ֋i6ݠjb/m`-MX}M`e9k=$Z;H>(="DF>BA0ȓ[唘9XQbtN_**6A@c){IϭSwN4r LfU$n@䃕NGQllJ(:(gI9 gƔLn͡gua'5|FMְXƖVW֩c#v,,EV=풍c KYKvm?FO7 Tq3dcGC#QaXAvډxl\+L mB$Z2uaHC)?dAWZ$"mdtk6s:E;Eodc[Pn$Z7f/HKYttnQhl 3 g\& ll6D7vm>n52ġY Zx:#?\5HP)*@hfV$iS9*`g3ϞBiC*=\`HU񜀈I@1H+3WȮIlTWqYF `{Xz,w'1Vb7òύUk\릕&4nT4NƍjN8QM ($a={luÑ?-{u[aH3&\|C!cF;r^OG`04זek`sd[*/T_M>S~)C;ԓ!8;g/» cEw5$מmWbӘrKܕɘ44+wݦG,']3? ٨\fc0B,.^ 3umc`ͭoL_rʪTk+gg9TwL\^qAh޸}Y0̭o2 *|!3~>[.g)-7כGzkۻ(}P*J#ZbFTibFg84tTY*cv]9*ٿ?S0WFͻVS/Bju䂋yױ6~.Lyꁗb?QX[ŊbֱUH}Ni՞p !}Y7dũP)z#?X}]7 ոNq2'_܀oBSNʧgcal j1`cؕXhLP]kfJsl2~%Q Y na0+P\"`hDۤBf'0eA|2.Fq\rd_%eFNIπXu :"Ib9QF[џE}}Gӆy䳷3J+Tfls+/o}Jj4lvӴt(ū{A }q UO?g" k5C~q1/[%vfv(:0+:OSx#sng#ׯ7 B)J$u3L(RjMbr|,~<өpIoA5G7w!nipg!lY8gzިS#pTgP[<^5&鈰$]3v%G%ڐPn9Js\l244=`|oe~ݮvH\-rJɜ6gKggFC\[O#gKvܟ< SEbHmJ*⷗bDH"#Eaz}Ӏ8!)~#}aCHlnGt @o,Et15Ƚ>obċ-0ˣYcblNÿo,&rNE.-0n-`tU2qVU!Nd#dg"R/wh^ ;.zU7<#@7rVY437g eBqU֐JUmf`畣{-E׺Vuh#gːnu܋ո;x$j~ IDAT,[Džω}v^9Npz6r/7ܿem<װ+Xd{S{76Jto5gQ3vk o>RTI͞ˇ|h7>ᛧxΒ}XrpU8⁖>>Lu-6^5t(κ89㗄178vCA +/ @jAr) Opz\@s-wƍOYюbH^kwY͠^Aai1U/NnE Kٸ'{'1/e W??ӹYXpb*64.)q5"^-|f5&xœHj%Wbkn䬘뮗H4=5Z%R-SӷLI5Yv4^kN3YCl:}Jo]<.ap5^K;NƐ]#/Bz&);ȏxknOߪY}NκHyx;k^\ԯ|],΀Rg99عS{]aO={%gy &)ֶ06߬8{W@BCqVtL8~, (W}?Ff{X> {ZGTSKYaׇل9+SЯs0:FK%pN;v@$kz_ϠQPU.F C "n१q$vQc6غh0qe?'gcD0ea54Y^J⬙\[eG3MP'V,<\)E%z}~`Ѷt%/ B}ѤAu4m#'~h;LX?'ЫC[bw:E9qfnkglέ{|&<׬"u⪤H5iSǘv{jV:218>j5U\<,mg-{4 .›X&>>ɷ3BU]NQe=N<O;q8[K*e709i1ܿ͞&6 42-F(o[##v/Š~.b:\؋A;U0$;̯.npd7{ \Go֫RiˠYE6gt8} I7Rw8C\;/V3Eq⟳Pãl 7墆?omƯY*Dk@Ii t?ᢲyw[\;QP{Vk{VҸ718shвfcL85 5.9*iӰ$-ʩoE 8`kbw-ѵ[(Ip]ٞymbř8x#lqVbMחI}7F>ş&rg)Ry@Sb~X9{esjuE3⬰_VGlMmwj^9Or=7gWsMX˜ȧbCYQ,y8r[~j8[}0T1P,((U"a\ :HgʋWmF][,o-@]~ C`dA:7+!$FtF, !CX4!_hN?Cm00S-}9g̗>mc0EAZW_\&ΆH{agÁ^`94Et C(CK%g?]9F Oc0J'E#Iˢ 1uA.ݭb.R7o|,>( '.߈8zɭɵn ;:=g.b-}[nL4>"}Cn|yrHGAi/c(JO8a,.DFī}*ӽg9w5&ƲOo!5vڕˀLcWi-_ pd<&~c3:AqV\r}Lrj4sc7Ymjy|ugIac:ofx'PýX`*OľA;\;焏Ώ匎dXk'x5ˌoƅWGOŀEwh9/f`P۫ j#|JQdR(5 Bq֚(v 4="1KwM׈̏c&笩b{\_F959g&$M?=oRnoSRgbyT,ZpI&x]kjR~+Ί9ESOW>IκSOt[B8>)vVlV޳zP}[zkH:woAk!a# ΠOk`ٴ}On(ҞpF1vYkHGoXb×o g$Y. Y/b Omp :`N"v7HaqigsKGvr+,M rW}G IWLRY -{o\_x'z؁8",|{1;s1Rplbi 4e;gTu?[{}́/S8T{~CRiC}Y evFA=\xT Xe/h5\Y3Qw.b.M7MIZys0v~%/]{>쇒$] KHui@6x 䟴,+%%\F:?YkHyA|e/cE[(JMEYFEC}0Gȧoj\'uYk| U{g~)) N!'#Pl=tu7I[/=8k5#1>Yu=>)vVdu g:`hߖgw-h| ,Zs o 16.2M2@_],衘oz"gqCQW9BKGBz:i#gFږ9ڷ޼iR^8>+9kĦ^D#֠lׇY?7iHP;}! OmZ}goǢ#< >&Ǧ,ҥlu8&/ /=8xSb>!;崕_9Y?tm"kq_v=_}^ZXT,rvlkC#Jk8+WUj92#8[/FeQpn ƺz#6x7z(SyNv{]|)Iϊw #0RTp2$JG,TKፗ)!eBc}Fѡq2qvnuʢh=x;g:afjs㲔,EH11avۣnt l;-EЯ!~+)qu\ >oD䗸kYW)(v YINZF=;4Dǀ(_Hb=E>}˔T:).0+lERO>eHdO0A O/Ù-ZxҎ]ʯt#gŮ#Hch(íCQ@8\_t Szs'u}_j%b9Vi؋+a8[|#>uѩSk 9{c/n8^A=Skb譣l`kH1LOSձPY3%!ŅԷ F2їc@S/*SYۗ2JѩK{lݸof9cS$(#`,&b/^'B[՝[bMx%gcƒz?Đ'K~:zk8MmʍYKՑdy6w} 8cqDX\,U1bҨF]o?~^l"Xj5+T|`NhMYC78,XDbYv4Fe疥e%k{\D5ׄ&bBFڔފzidQa/d|p;{R ;[N<-K9s,*ILN\>1W\5ҮVqV _lX-g[^)ؒ>os3Dj=[)Jqԗ۝`Y OGѧRV}DO3;{\,"]`<}_Jom_|v5]j.n5VպXqz~>.O7_R^ɂXZ Kg0)q1 M̯ΊbgSξ-uΓ-~st!gYX,Jvܟ< .B+ĐX_L6+@fIs[&$Dbd;2 =ؠ`YZv/לBDt'KTl\7K|>:~^]t,WlL][H6MxvOW V+'β|]8fq^>٪p.9,Jۼ#7OcZqayOYkgM.ް7&ǽX̤i%<7*wuVَB~#/6ꁾygv! Rz7kV򉽕5|ݪQc=^WZiFfԆT ~^(6")ƈ;~<a汕E[e=uh9۰4 &Y3:/غ97'_&@ {TN&OrMIq=<;fŌƔ%ZvVqV)_[⬡I^G8R,ATz(SSQ:sEfecr9g8tn8x)}~#=7U~~|؏3|R'Msu3II8%z=i! OnOp{4ݢ<3[#WRgES-vԝ'{zNߙ~Y!5$pGsY879.r o 7A!HN"g+^nrO?uf@/k*g-5][c&q6lF@%+6Qt0c:: MEm F"*/>V8iyI1u-UV…)lh #[ש뤭ӿ]GcG*N5\H%7괵o4 M?Ff@er׳tIg-M\Vg_IV]?fGCd;H<e"|bku{*U8pQ|*p'$* 9uHkMMZVDUR$Ϊ\8{ N:P\ߩ.aY试M\w갃5F>⎨ vyV`}fI0h>* Z'IM"@k,LTJHh8ks;Vn9LY@UrPn9㡿8kԥ MhXZ͋*-g@… h *D8@R3 qVԈ qL 8JРD8KAL&@訢 paCkZ'+m$Β_X֠L}(EYHR;0e.v4Z'X2TZĐ2 gĐ4 80PjN/g1d-2pd B&*Z'I&@klTT Hd 8kF!8kFC&qn.%HmA [P}:Yymog+ԯ>$Β_}H%gAPJv*!*`$\8h Nڑd9!d$:!i g#D"@ D"@HK q"@ D"@ DH0`jN 8ka"@ D"@ D~8k?Z֤M}"@ D"@ DR qR&mQ"@ D"@ D8k?HuTҼ D"@ D"$Ϊ4U qVU"@ D"@ D 8V9OYR D"@ D"@ H%!芳D"@ D"@ D(LYRsD"@ D"@ D9HC"@ D"@ D"@&@@9"@ D"@ D"@$ʡDe D"@ D"@   qVa D"@ D"@ D@gP2D"@ D"@ D 80Pj"@ D"@ D" ق,ۡ*Y IDATy2"NB1M-OAݷ|u²gޭ&)eP=|q4 D"@ D"@0;XVUg\~ wd[c^}7+:.Ef%Lqb,HT 芳) D"@ D"@ElIDth*FYZO`,qEP,DrכU_X7 o`oiXyXDTe㎕C\05}1dvYA@VOž~1;ɹHcj ~$bO믏S#kxvbhޯT)ڍ{1ե) [1>) aG D"@ D"@TLգ%iOGPL}>Nw|1lg%Fa_1mCq,Vqdal|[1_^!Mug=!#kêX[,Ø~S Gc556Uh%&f Oa?VacPv~ˎFN D"@ D `[q6 3C"A04v]A}(.ĄH/<|Yy щ>:(=˶aQV2 KQWy#=>Wznbw7a$?FCy|̚d4W>oT!\59uziXEğm%7.x{b^}4{%f1/ D"@ D"@쎀MY\IERi "~_Ul2 g1&ʉ3MXb,[sc;g!^,6 f+Kepi:@/ Dcd>Pvxmt vhKؒ!-ЛZ#q2\U"@ D"@ D-ۊeakN>ȹu[G9>(bJ(Qea]h >;ؖP90qvjeisy(2_V-ub/&+Ev24Q tmWsOA]~푇eO!YkrMg׈Uh~>N[0&DkhDK8gGJ "@ D"@ D'`cq`՞Xt6i7:5)m iߝ)Ȅ;7 „:e/;1B֭o{5Bleܐy 5.bRLk BlY,ʼB zu hSª SpCH1`ً<, BH}}Q^@lu]8k). D"@ D"@I8t8*|-"V{:w?nɶl/ʟ*$# "Ξ9sSLюkFn0`eeea„ x0p@Ѳr˙Cw¶ڴiSykɜP]"@ D"@ DM`Q¬VMuMگXsOC"q "*P) g~i 6 Xf ֯_7x6]J#j桯̙3_~YnT"@ D"@ K`#wAH5 TJ2Y3ر6r7|'''?~r#gYY&~L07oyd\t gKJJϣe˖b`9Jzд D"@ D#q6f6eeOⳒs62v(=: LgXd)J`Μ9`Sڔƈ[sŕ+W;b`,FLՀ9˾1l0.<1cuAv$ZU"@ D"@ D@!"OcϙTm'7gEnAzvLYLG8qѦI!D"@ D"@xH@YIN2Y})r#@, D"@ D"@*g+i*&@⬊CC#D"@ D"@} 8r[D67.mQADTR qR&M D"@ DTbSQ#@&{9pw:c֜hIFS @, D"@ D"@ 8kaԼ qN G&D"@ D"@ q~lE#&gI"D"@ D"@@$@l4;M g "D"@ D"@  q<~TQ 8먖y"@ D"@ D@5HU)h " ":EUäX;"[ '-g!3 Hfll&@;N6#x#66'_P1,4ڠYgm$ځ7Dzj_ O7DhhpJoe .٧ TsKUOdcR#!%j Z-cq/X{$[#qrle{&@=[OӦ8Rm Oa]8xy K_6hen tN6n tV8P#՛Fl(–Fa鉊, O;j)uZr{ &5__buEjRi{$@=ZbcMbh[ĺ?q|aV!V8/ s`jdcIgdc`jdcGl4EQa`l( Ɲo6^Y8L3 ~$]&ξKǡ)K8Ngh6=YObFŀcgiƌIKd5ϕ&곉#"+MT}푍g|DmxlZ=ET dK UAPLA`ɧK36P= FڽO+%Φ|뢟N{h8&LsbWYt!|LҲ~'O@˼HO{X3A3;kZ c7EoXyRpv,FM5D毷8-?ۃYg'g}wdƪuQv !S4s& rZk1̨e†հEKШZ]:bu8 y@Jhe26/Uzt+7j<.|ŜǙ[ߜ5,v _>ғAmP5&3\Gj r֏Gz𪉻EX~w3Ut8wNJcB!/,Nݨ֡vSG~0hS5ڰZm,dEw1*>WصڠfCC-6kv͵%mJks\,b ;7b9ArSah]ѵHu>yrlcZl,džR损~;wyh>mnuZao|S8[x+.M*WĖfĸO1=>e) V_KECy;kLoDS0Q>~\qgaޅ1X26;f(FBR5r>fah Y_Z8U<_ޞN0FOU|,1}*nż)?)ԧ*v̛ݗ/U riՑDε-w36EU6԰t,;I9iM19t޶PX*"WڣzĈ-5m6sW2̒MR0*m--n>Zc vؔ;(J6R9><#Үdף n|RD+R֒czo]Ƚ}3~ !g-k֛9iUr}0op6ЂUB]_pis&el"*uT%]O,U5״`{seUW [ӣzj?{?/\3ՒZ5IΞ]3D(?W7Ő7Gnv:!"<P"g.Gژ7 H]o$̜uO-ĬOa r9)kjcL۷#d>R`E$m}̛p+#Wo| N~Kw:C29kmOqrV]Vd8q- Zǂxcyg`4Lm܇'zLR>̍ݚCuƥ[WD=k4s߳<)Z& _DڪVS're^s?${r(wGtANj#gij ry/u~zj꣬vWcLM"*tߏ7a{Zwj;(-=~䬜-dK RXn8I!аrm~n7ur 9 zKOc*Q\k^/ 3jzLއū\|MOxo^d\Q_"q"?y)xe8u{]1 ?܆cC&RɠR"b\95egj3-?KU{?ߣG@7$gZFD_ y t=[ѡ4IkUrrs]k\$g[%_ :~>xo^xr>8蒡4 ;&<ݰưǒKg7 oaɭՠ+}ב6FJvDÆv@ rJuZ ˝#eiEsum#ml5}a_4$NVFVM KgұnflJu#J99_,G{]ؕ8)"gY=I Y5D~9 gjO-CJJ3$g/>Su䬱ʉkP{lX3+9lN&gk%E "B9wXqzv dWDY_(CZlUoI>*2a^u&uE+FŎ CQo ~܎XyT0w\>=0gjAߴ_B mhFƮ؝4޺*:[ãՐIxsg롣I{LkATDVۿːuBF _1rVI#gJD6/ؚcPŽb{ PBea_3>\;UV޻[Ԑ1grV0}8u<QSd/G~ZPoԯO˒h^/?)߫>ܢo d*-i/"ul|&Dț=<:r~E[:^|e,>7-(=6E;/FOR*;&O1#VJ Zp_(Ѵ~d#=XB*Rt:Ԭ.56GKӴҎSBɯ/ G7̀4ߔt 7F: Rlr)-/0. Lc9j˲ڈenF]}kA70(ո1tsR- Xk']LhD"+fx&"ن*Cr%GOz_䜥Șz=S"O=iul-/_E[RC9+Ui7,7~<SW{?&5Mߥ[&zG!w-a58΍Hϔƥ㿋W|\Z+.ڮ8fIīD<2_kCTP/2sݿ%zjRQZ,K]n8UҩfCJ"Uk.;ox ?UξE8'r_vo`rr&=:~>=hJ{DX`p`GPQzȯRAUJcXCR\`~FZC>Q7MG5zPS.طHߔ`txWbEPGEc91Frnx`(atqΧ"ÚVOUhnώn080ZmP)ڽ(SIl9KllI-9K9g??M9g{j-6J'C 9v-՜VcA1_t.JD&e"z8]Rx)xWĸ >D򕰪F샢b(Gv *ۨ%Ujl#gG)rV_eHP <¯yM䬒kQE9?;A|xҮLΪqketl~-ٹX% ҹHζJ1V5 -S9%t$)~N,h<^KZkx,ͻrWi +eeЩGZ$UHQ㗕-nUuJR+\ ˑrsLΪ2{S~ lI cJ'RR*7W&gPG( !""MtoSL .9#gU .TprrED³_9-.ɺ["r(4=}z5d8xې{+OocP./.H@ճF)[t"W_N#u+|颤57JVCBA!\mT6UWkOD 偣K=> iC}1([0A7qZ,]rdKj2y<^\-׈ T"g¶e">o}v/w-Zsc- (a2rW"gGFDD[|ğߏUG'n kj K'qXf4ۓLZjޓH?S7'6?Q ]<R|i t'5E_""NtػNrZXNn9z!pc'te gGHGu#>k(o z>}7/߾uv"OߔưNc@~Ywj;v5䳧8FAn[*4nJ䬩:LY9.-__s=^><1< 7%9Mkx 51*\%rNGa_^uؗ{L/|&g-(~9k6iMmHgijTJ>"b{ΉD VҤҠOc}dUǔ>(Z}qܔ69 kEZ'أj#gu]rODIUXtmu;!6=p`wz;Tg͂˺HH:;'M+( Oiqi'S:t+͆YʔC"=UM*V{tYmؔ6\_c1K5`r֚h:}]<9 "h ("B50K'p-Ht1KBT`; Mvul"/:vzڼl#6i`[pUY,(b4"S Մ"OzZфsAQBwETGm9Sw"YQI%dA:־-!ۈ5 [I:Yc-:L:&#Ozvr lNMa;|;5:N ۈ+ʢ-XP V:֠R,Y \&g]\u'=Ή۹sYeYΩ7sfV,6R:nl o c1K5`r֚h:}]<9 *`;Wa;U:Va; >ۈ@v&DQ%u\4*SՈ"!OzKa[mjgkA ul[|P;X Zж l#֏=c['ڎiumj\ӷآeժU3.ЎvDIO;`Il۹JͬchvrmVjfkEڕmDdl F폹ZdrVrNStdF`F`F`Fp u 5BY[!2#0#0#0#BYS.l?49莋_ S^0hF~tKQt8R'cױRn;۷:=jY{!h&g(0Zm9[Y[#2e{&BM{=Pv6xjS:yu4m+W?*rbc'VLκ.' 5:Qy6,oL ֫45;w(NgX0ꙜuN2oԝ\V7UVTձ5;>ߎ`sS`F:v39:Xf+D''ZTư]#hU. i)GG29NW\JvD?pZ6T ]_J=drtѽgh ؾ}ֱ1W L inG09k?m,N9Ytm}hNo a0ՉRFm6Nj&g uP*+ѪXUbo'q}`u]rO,@Yٲe=x7"=}P 6*`z'wѽc;8{=_،f!Ȼ6*ܱo)IjCYH}Sw/WM9{]L+tk[1sjg< ǙKZ5M9d|kzJe-YiVw}sW2d{fKr$b31bjka͉5t,;I9iB_}brh6h#>9bck=kER];b1M9XbS/Dr:g fG…T}tPkF>ڨ5JH_מ؊2'e ѥfsќ޷iZOݧbޢ˦"g –#D4E.۱]6gy<ٶ#׬UF5;wHɼO l;KQJ쮓ǰ7㤾t)9۾FS<ר?=#I,k!@&U:R&7}y51Phzf%C?`DbHr|?zbOeKT6j6'#wz]߄3]+~(rEdPOT)_Gkqekʕ){=u/SNRI7ajݩTc& m}7t=D$S ܾ[(N|pGnAkwl,L ksϊvgm{X[ֱG=z!z*!٭1^g\uA7i5?NSA=qKغϜy_vFDQui?Ou# -|]ơdaġg('bTb.Pҏ0^=f>WVccOM04 HξʵD׆MxOŌC9h/4 ]jcyP{"gi3I={ݻj煊*%BFnRGeZWq(ր|_ݟB5TҏRew/D6,N ~zb䬜*oQL٢v5{\vBܩ JkEq_aWYB*N {c(VҨVt,%gi_9Gmr0}r^uܦfp6rMobU. i%,/"guSE|qwl;@,?h2h$><#ŭŤ-M>Zz(JM5*t']+uG! -.\YʿF', @GOך-0bC^RG?(%Eª7Qj\#bt|&5arX%gɖ脏2E'^8R_z7|(O6=c>j+cſWvWwY@ǟug,6|g)9K>OH|O#1tL.BYwkFnA )[7+b>a:.?0EI׭R[4ǏPIq(Gҝ'-=d3/4~$94OȍWc0kbbxrOF#Be}R[r)[TÎ_=gs3?$5W֊5<ٯAMj9dְtȑþ;r!rV<'7O8}Z+ 0e #&ǎEcae"$ zӻϋ#E%r!HtRDuk&)L.9m~O=adW RۊEYJE|erV~HR*_zzɒ5P`r&Eѳ;ӹ9 իfG`rVԑͫm:Bn.9Ku#91[w!i0%Dr~í^6ԓEcRuKian*rNKx 2ZNmؐԔ~(zvo*^p+[ɹ9ތiNPD,yH~ E.֤ˮ^ofk]BJx>;/.ez+*i2:^ 29Cb )fB5$\9v'"լ -Lbuay /qQ-|8#gi.`:g*GiRnf)?o1Q@gBe}E%wOY5t~0eÔ;wĶdIZ!{9"U%;Jd+mֲkX4>$hEǺ>8zQ3ɭ79ulX)^aƥk^0 [k)97OuŰadk^7}-WbF!$#uZ wA~MqnZ.jnaτn).l -3&;C2Y Ck؁Djqztn6VG"Z[PX`qFE䬩6v&V&ƣmEy!WDj&gٔ+SmGB0lјm !|.Չ|yS؝O^SOZ/bg@+>H$R#g֥eF9;8#ZVo94+HLz*;3?[WzrVUrgU_,ێǖd-7("o~|P.]kڦJSXz$9K;OZ QB%XOVW IDAT@ 7ʾ`q Tb<F%. NKѩ("=]XlrVi^*&f9?bH -|S㐈Oc9g }4rVI?Jڴ:?8oyuZhx&Biߢ4?E5>)(ҵg"GD䬒*oܹm›Z[G8z!HMsrG߷Nzנ#0tNF  XY6i``3aA@v:V!L0"gFcw+X,W ,u哈Wq=%.YO;EiW2@,MET'E"gޏI~ki^QDkj"omeZLU_R TdADP#y, N?*rZ9K*p r_ţe ['gӏ=z,_99Ky4]-nCZ9Y﫺w~ n|9KQ#&.kJr?ȐJzJ~E*[d 'ogwn~"~.=!겕0U6YZy z'D%O-@MGmO\^R ٤Ķ}R'4,k7dA,jȋNQt^?єl6U~ӭ~Kn ^4Ճ) tO  Mo^ի\۶ҙ:ZdžeG5C. @x!qt67rVi^jiIU3oÒׂ75\:aɻ!Lm> %g4 +5 wDǜD$#:$"]!na :a3%Lln" >zb3cTޗDf/+eOZ؉7.aX05ag<@-`lYR-m_;|Hu#&39\:n uWͷ9{*7$% Vl=zUh%c?8j%X1#P%# ?zE"{C #h?i (6Z_8җOǦ3 )+cE;`lhD#@;zpr!,y^i"/n{y {>z,yO ȭwʔbz q"OPiOHwö9Z,@Q]G3Y566l3=kfrZHzaN^i6k6[rH|BDL޺Ze;~ֱuH ŇYHiVm뵘X;s6#qpWB9MAZ*kbFr i)&nh 9 Fcc Vcz?&O 1bu0r~4z߈C|Y0AI(^B07 eaX֮1ޘ0,?)|09k?mu;!6ɕ8"cX.;IiX6nм C%AKl颗PҢU39k7]!WڨnT9u:/Zk}4Raf-$g )7kbFkPJFRJR%]D\'LWD>Q dtA;>#a, IU! w7 r]B YْR|#]MuC[=GkmZ݇Cw,b,wCna4ik`ij 3 A@v:VamV&N ]Z'[WЛT)G$4Aݑ+#rb7!gEj:$lR}vt,M*@ 01HX2~Kk܎`rjPU UԖ3q 39khB9hMUSƒ}Ys:T=]_LΖnk:Z,Api"nS*2rn> az#H~zI".'r:7z zKY)9K|\} jE>͟.aĝb#f`E-u*7a&gMc%",x\m[[=GkmZ9kr;@qePjP*ee-e ^wyn=,]&T:v}+}~ֿ{}ccl,$gS|ح[c1V#jџ³-^Y2|^jv"ZJw9&gKY6 krQJ:v}39[u޳Ѳv#:8j Y-20%GْcXj`r4h>29k&`\\l RxS:v}39[u޳Ѳv#:8j&gaK:LPn`F`F`F`F`rT2&gA2#0#0#0#X&g&tKc.}ҧsg1۫3kO]iW7,<ll@rF@o]58L:XH[!䬭z/>m.l" v%.5nא5`r5l)ܻgLdLVY`rY4r/A:WGk5grMzn]]ÎەcpVCYBn倀!9w(Ng.oLpnN[09-}4AklvU4eu =jlWZc &g.B@GOΞWj?<H99Yj..TxFL:GV+Kll @rFYk# K Cm#`6M䬦W%g˖)_{Yx^'6#>k?Uy?)c 열{ w}dqպ~~nMH=/7uc7p]pmhUQU 2 oXMkcz'wTե$S֍\z )T9oZF9J:,X ^r6{6ʵV_xYH ؔYۡW$mYlP.RJ7Ѽ}+O7A0_9tӸx~"}Q[EղrZ^%tRe+0]} ]<~;5NRmتg$gO\O\ܹ{~1YK4]bNfcxDnq޽I?|U.JxPD*K^mޞ #O?%}edrr΃@i!guyVj ~>zj Ex2'ygp2'e bѾFS<ר?=#I,kci ⁞Y yO 짞1ؚ RQi}jiZuTT5+I~d,l;)Dh* k!a 9N|H+9 {2I!9s)"9|G[نPxS i z`X.ucPݎ"rVJJsF\\Li+2")CNREyo K' X) OE5vD~Nl>5aT#Yl8v>:S1߮GkٸͮLI]j63 Oo;%\#fzqUwmʽgh/|dJ~lkDn^ št>xf[EҚGiR75[gmccrW;SJ{%iڍZT,~F2_@`E?6NF޹{XA޹r'k7onu]TX ruSRQ O툇j0r6\~{r_EtJ<@;^7HQ OwB(9+'X]]k=ӱ^\}6̻Ցmaˑm#Ju޹w@J@6 0uhY@:y {3N.卓Y \%2E "B9wq|qM&HĐXDiUv]bjr-6t6zݿ/.A,x sAC}Y st}6Y콊*ȶ!--k.}`__mFi5VJu ţu;afp+SVVFӮdZ6hzb`9kh+{^Wv=(#w#F!GRsF|!*i|+TϐCG 89T XQ!%D@`%?Rqg ۲EhD]ه;' IiȽuUC=r~QIؾqv^}5wRg}7{QNmrz_h[؃t6R"jxTŊ0+ q O_(="0 m~Ζ~R/dWJl5Ah]rUx"T>5 Ck&zN3E*٘ݲ]Ǯ(=4 K'Bn/cv;p)]U#Kڝ׶מ-89K=x6!Կy?:5-WEJXAI廛VPcl;~'aFE0lxȷ&~= s=ym@׆MH*Ĥ(AUQ@t]zϻ k/Ͽ9K}߬%6lmӐx(fH&91sOܹ{'nE&Ats2ꅼ+|#[ {$V~N0Aű߱=Y:ds4 {F5|(BoIUkͽ(kmh 4%=Z@ISjCnȦ7TEVx %,/9+9j}I|xG9[w DrW+-Zu:)!ԮȎc_cg`˗uOsYUOսN.%r-8jXÞo d.)g2ED[%m REʵ˛Fk"母O0W/K"P"fr:7l0=XDQ3ˏɹNjStjvx"~HE/|m}gK}iWp(7z+u=c0lL{UH 2Sʺ 7rk :5}g"6 W/r{Nj e\4:GcZ4z94g?:M.)3~J6v}k{ӂCii.|vWqJE^Fg3w!I$r$5YcQYBR5:/S#ZGHݧcx[_A.-(,uk0(_՚|"߼}ׯE'q!/E'PlYd\Ƨ [1{cE$s6$N1R*93(>w OÜl;DzeqQ}lTxjkBy77g\d&&gm3TVF6:9+w`E<<][ʖdQ40|E"g)!KؗAʥ"6K8{deh]MqNѿ)T6hZm.Ԯi<-}?ȝKVH:90 %rVztب[ .VW_.zYvXR[F(h:U@v ) *2">Jm8M /D+:u؆D%\ұC2[rّ^%?On5JA=J~oٯ{܊\UCuzU]kxT%g?x`DLmx1rVi=#O4SJ6v}k{ӂ+cExp.~&$gT SkJk5mM-JJѸ]X7-ڠi@7e7Qx,w9if̒>fAx8?S #p-,ݶsS$ߺ"g޻'+9Kre]ᝋfHήH\,>Nߺ2gdHmgJDRZm1c IDAT? NS qKq҇L<!(YJvvD ZDg4[UUcTiY%S=i!͇4wk0yiȭݔ|}5ƉZr֔E٦g#g)%@nuԩV oMIpwos÷7d#q=9ރRzFRڂU;=`(O:,!k 9Kycdv=-r߾((rv^p䬴WevڭX/EjZ&gm3VFQ09[|uRTFe_/%.AE6sUWzp5]95f[)MO}Yq6訒.foD{tl]Gp9,~vd +gc}~DKesͪi>xU{ȧYGY%[-_]ahѪu)rVԮoٮlgW9g/[m8ZTⴟ?HHJ#G{,sm4fZnm;K!y^3i)A^q?؋oYyWD۠cF"SC䜽z3/3NatLڧX%,EH_ޏ'$@iTvRe4X,,1"ŢoQoާADousmnM r8R7E֭TSkMFgS~QIt(EA{ Y;ͿsSvG?"gh-ٕۖ\~LN}4|QTP}n(WCcCR3roT)/{sdP/AVV/M`J9NМO:^} N#0!"ܔ?(:MnL"t7'6ژ)?ve{2$gšu;Q^d }[[kQ>RJZ=(Xkjd;9Kh@fe-[UѯiK4 "7o߄/!ȷ&mqZ 'nAAr *Vo",z.?؃Q˻*F>V!gdWΈKޅZĥe8ݸQx Mjctx'\'g)֪Gj A5ru_uS\vb&(uQ 50iLΚ 0vEUYȍig#% }P r~jΣ!甔9҄VygE x;w/Kvk?&c]qK#䬥["g)u? @=Xł2߭f`{u2ە+kuv뺺udخ>DΪń) P7haAKl颗:o&gnߡ09Pq!pWZ+e*&:4/4ەU>KDɷ#"hCn@@ d^ c#fIx&gMK0LκrKqx^]g{uB9lWN$ll@rF#gh)rЪcrAs@Ym聥..\m`{-vҪy7ۭsOҳ]iU3,&gJ;LΖv (grv.X۫*bry`6~lWl"΀Π%і09kKtn#UZ/-_qlޥfriln]VەCU"J"˪;&gՠe ^;Jl[=ەzmۭ--u]^;Sϙu&m@Y[u: 撳N1`F`F`F`F@ƾ,v {z<֯Grz n0[(AP%7"$f:zS0{DƒpO_UQ+b?j= LΪl #0#0#0#0Blr!::}:#!aRI΁OɈFY54r +Vb}u‡aHug::{:Nƪ$aرF qZDGt@Ol~ K_19?n׮09kW1F`F`F`F` % gS2j):3"[zD2=e`\D?>f>IK1}c0EF@A:6,]^14Z227 faİ^ظK#*z3 a\/l\G!&PX 35[ZF EOF`F`F`F`@ YcZ=9 dEco:9ˑ+Jѷ[ȸb9gSVb1fXB-9k΅`LZQA=!g7`a0,OГ;- 4cF- KH^WzCr79XrY'DY'T0#0#0#0 `r6W>ULb,5K !d2#(D&`ITDݏ-BR`RI  X3Qݪjj`rV J\`F`F`F`FGX&U;Ab $^ջsP4Čʅ`ذ+!rT+g#i"l|N 6*  & (r"biJ%_sրE>,Y^69 ̴[jrV]`F`F`F`F`@f,Zĭf`l_q9GYW!w`F`F`F`E*䬳>me%#d8fU#0#0#0#0%CT%vu-rF`F`F`FpNuNVBY+0#0#0#0#fC/Lκ6/#0#0#0#8L:XZ+#䬕F`F`F`F`T#j+"+j0#0#0#0s s艥rl?٨E`F`F`F`Fl o}j#0#0#0#0GYc5:L:XTF`F`F`F`\ &g]L`r<4#0#0#0#0`rzXrMNN4`F`F`F`AYQ$w2 7~`F`F`F`F09[r 'FY'V0#0#0#0#䬓+/撳qy.\=PpYL4 ?8۷ooEBB.]U}pAF`F`F`F` }pV4䬮ǏǴi裏bњݒ%KsNL0m۶EZZ/^f͚ YaF`F`F`FLjK,9Yf_D^ѯ#F@xx8N xTT *} *H M4¨TZCX) IX`Td2Mؤf.XbM , hzPZz}.y3{]~߷{v~G۷W\q̘k9~z|hhh@hh(fϞC"u<裸kq=|al۶ ?8~'8m4(խ3f(`:       pig]>> ?[l / 3tEg#PԱ~Ve$@$@$@$@$@$@$@$(κJ;821eyE9:[n[bX}qV w}%%%E[~a]+ν}qXqh52-S*K'jLbIHHHHHHHmPuS `+q"U) W~Iq6((K.Ŏ;yh+E ƫŋ#$$o uҥ+W>Ȟݳg}YWk{1W_)-W06æ,HHHHHHH܅YwigE6lqNdeeL_ ;s6>>x>|ko!֊ \qGQQ̒ ȑ#]v[SN֭TVbbmQY( nb(6>g8A[$@$@$@$@$@$@$@$@E{ً16HHHHHHHH&@qlT PDO$@$@$@$@$@$@$@$(κJ;p8kX        7"@q֍ŦڞY3e$@$@$@$@$@$@$@$@8k'^(za-       pg7"szk>& 9c|js 8,q w|ƚXYN=лr-Ws2f"M{ͦ8뮖cIHHHHHHH @m&' FƚJFᬹ*l!"3hQY55N^]-4 bL^uQuw $@$@$@$@$@$@$@$.6`e^ٮZ5wH*Eو 4%3g'꾭ޘ%HG.| 5!H=qZMr󋱯Q HJGXMV#9#\&jUH_*VB9صz5I¼!Z[4b0#i8_Ɣ7I)53cQi=]XUP1<1Aխ'[O9_z C:gM YB5xZ*Z6|K:'EO}a8ڍH߅)L9HGUa65HMODhm!":%qQEI] $1b}P HbQeD/JC< d B<,3x+SX 4S^sldjb"dW`r\ /F"`jp#4!IȚ_5VZiX*NtU&e};}Agg۟ܳ;lO{͹{icϷ+k+[1mk8[twX6EcN(* E(\pH8Xbd"4 iJm ;љi.B&)1ϔffcFlD$td@l֦V$Te!U_o14JALM>ҳj1Cw\CZh9 a&)ELC8P߸z/W Y3v ˚! cN&pZh{wZŴ;bNJicfe%&ΊL%FOdRËQÍ$}HJFpaU%"{Oŧ +S cJ ;)qV 3& hg!s &e`B}B0t7#=+t닮jh֮AAij %qgrU/[EUxZ̓naAT ǹwX/i{=m]6:=ƮC)lǴ yXNIEdR*"5!pN2bݡ Ίl֬)\IZbD˪Օ[i䌙YmJ B8V لd\C1VE(FGtBFjQ̜U/W Y3v ˚! cN&pZh{wZŴ;bNJicfe% V /u94(@GFsI`x8XuX]P4$~U"sY1’ST , ҧ_8V$6trAJdk^U(A~],,ggzϝuesoom=qL&f!lfm`8B+UQ IDAT -2i̜jDWDaʬ$ċv(ZJ7 V}f(W<|Hwݭ(8{OFKq棂͑@\p5{9νg=x.?:=ƮC)lǴ ,P[uj78Iɉ0vcZH@;۵LJOm+q ӭ=|ۡc_aEEAKcz_kSƐH6U\cƟ/Y |?~xMGZq :~>pW[^>jo!758Zi-GpIiEBlue܏M%׭M0 +G{cN;bWLl/eiW6gMe<{0`$:jvhcJH qmN1Onvs- 5BW_۲k?!7~Oo8Ҿ7gU3M gXgO}gn.CF'p8*6Ӛv8z1g|81O]<ړJ_X5~ֹ~&q~p6wg&,[NLmϟjk1/&‘SǰpV^/ڼRW?]|:cN)JV#|u Eބ38H1ZrgڦXyҰh*ף.żq,ڈvWY|ʀQӬh♑s;||p[8PwG/g^k-sxZr7\'oX X_e 2_{א)' /*9w q٪P抳3m,?Iԝl}A{lcA?g/Z*Йk[wYq#b5]/]en8#mOgGw`(m?2wm#6/f.M`c-LnɡmsB2>.aFɑ=ȹ*E!>K!iȵ-4CC5CmI;E 2l;/%WJ"SțpUKukJpI@ٵr6g."Z?k |e4svsvL4GO;߅.c]HukjT& w n_s9T6\K;4M7_'3*OĚp૥f \Pm"px]_V909Zޙ/OIs)"=y=\ڸx￴Ȧ] v7~c>9k_q&Sk.67ktsYgUSt;3Vk˽I#O Be*͇b|O  iٯaRo>s>u Κ:6Y1919{6cs- uGJVs׫:h=}3M qW&+ckP>KA"e#gc[2GG=7+7b4hT l̈́'iv=uզ&/AsS|[[Q' 8K_OQu6^ӃzGz7_$A2]^ ycooBLʂ)R.臑mj"5fvcROHvX5~>>s+/.EA}ùؙܾYˬx|S#U@S[#'KL9`nqkѷLJ݂}.*狻?ֶ㠛^?5+qV#h!ɐڸSgaWp7Y-DdS?ܨƸx9kSkN2XjQ3V밒8Vڼ!Q"c҇EF}HO:苳[{tSTmqb䏹;wGncxu+Ę螃7/DoZe aI\{.g]ٱQ,=qFJx&2GuX5wwfK^5;ޔ~2cX2|uIq_o}8*OLc(Ϊj}vQA0_J<2ulrbHsbյ\enik|WڷZ^uܢaυ 6J,] 8kX"!b⸾QXkrMvb:nܴHnzŹ<2I|-ztv#^5nxZřRgqGzQeKYsڱءVBS,"P2ؙ/&n7N9w.3ϑqkxfϿƓ%Qlb1rcթ/6L^3'*gd ;鲝G }CL 0"زOc"dv.A;2&&jts%⬨JFW ǰҏdE[)gs@A)ֽr^Eq֐QĜ*t;q$ΊAG4Ľ497Kۢ~LoH5n@lH))}LᝊcZ1JCs }/Oj~LǙ61gm1.+>ٓYc8KqUKeס#O@gۯ;^ vsQ}{y@dȊAk4ꓮlj;GSs5\' YK/c{ɒ8O^X_mNm!tm~Amôl{sbS⬒>4#-0Rq }>^s`[.=l'N9gΊl5q-O2'Gd+:ŵׇP+o#Q%9>7]J/v00V_=^=  -!\9ꞌSφIKp˳ -3?Ͽ@(o5)߲OD(/6An]a瀞:.[fA: jU%lyJ~pY` ǥ)6tKG%{!@d&_@_ \!'"^6YùAe#ΊMvava*Ϝ5jxDQ=`l(_]LO\~;V`ѽ^/1)[(ϖJ"[ŝrK-PBď oIqq5ڸ`V-gOE&&}rvV̍njcf/r_wTnUx9ե2YODo>{ZW⦅ Yv{d,W`rRU[Ok75@hlHùA?sVBMdLcޥ6?fB;_s\g#}q1g'h-6OgOz >KG-?O]1G(q+bݾ"9vJ>Iq5Y!7y i^>G܀N||&vxT1RзGS8+'u[_5w '(aX_>s:2Woۡ㝟8TpqX ajϦ5N?^V񣆹땚8sGY9Vj0Y5{!6Y#w5]|_q}FY0CD )̩\7gqgb([#ո;kl*5rj>jZjORd^yӬqm#v|P瞊c~ڱugܘ8kj6'R\voG5#–O#U KDVOR>)x|s¯E ڧ8_?9Jk5ܞMB/}m^A2?:s~67rff8.Ξ=+&Yq|(1Tm>P'Ք*jpxB!WOœ5F]zNm]/glJjYcVK+)s'<g͝yGp'q֘DkhY51ܹd7ՋsYZJ[l,矉|wn $_(aI;lݙI6/Rt3gK wy0y8w  vhgȨ;X+ߊ2įFN8Ɓpd|U!aʷKABU2cqq-k3&m'bC/QTyY^< V>*6837J}\}3A˰-/sصEUk* L9Ye.O 6ĺan}D[~t?^xˮZ_q'579+ПۯJ skj_1Ɲ!g Hq'XF$@CexYgSeRtS:?}?^%84~jxzuϜ*Y1^S㘶OX#_&>BkTX|ܺIqV;}L %|/*N>AyX)7uڏ je_d8Ua:gM2~,/ w=ҺcjjzC>n ,cQgY[$Au[lx+Zpi ̀5xG+8έ֗;i{ًGz\$g~< _[khsw9qLqEq֞}icok$8뺶a@ I w;~?ǹvvwQʇ/&_Ӯ~'r9r9OC{q{uicװo8k-9(zݢ\pLvk$~u9]m mP.QmfpX#; *3>, Pj;9UƀLbq[JۻlHܦ8]0.o676n3B\SCn8!d7#@q:nr\p-gIw0$k*;lٞ6.s|{ƞocW!WcFq1Y8뢆fq@Z%rK9xml:mFnx;mFkCJ<\S<԰tx8y6uquU8] ٵp;Ϋw{gL;s:6v$meHk },} Pj;\p*cr&K8- L6m$mnS._q7QH! h)m!RC8k7e9.3;{5qv6KlO{͹{icϷ+k+[1m8άE X*κh7,        7$@q &ێY۱dI$@$@$@$@$@$@$@$@8k/^a(zA       p#gXl X*NtI. sJgyoC\N[7&I#i.#@qL$`YV˳gFY5lM9YggF ;y ~~]h_w*Jgz62MӯNˠ8k^Dv'`YfE f9#g&Y:q&Qj^;|]WA#6iܙ8>v8hygm 0ز9R&YwCv'uY pwX:&dP;?i7\Cq֦TY ؗ-eKu׵ [X\˛9{3gEg{Cq=kmڪ!а0M0/[]7ḵ87ks<g= ϲ⬷{ǃ fl')ZI}0閻ϞkPTRG=o^!vmXtC[Хp}h\WΜ=cuG 8k4޾_05Zo!}jpgjއ,&l&%((+Z5Li֭>|{"b#kйB݄:45 8 Idjl*@p\ n|&YH [Iq&SE}2L0 MB`.p|O&y3"g!&gY=ICmԨo^xկeB{T _lQg%5lN>eo\Rem5Q|`bp4eKpkH w_-7km7ޗJ>kJp Uxs7ƧaWPp([".P?"՘oe IDAT92GS(0}x4>5{7W/~n0ƪ͝E ͺ1q?ឯfnގic ]ֶ5kp[.(3/0pUwu@#7]X?x$2 '!z=סD=Niyu ~XY8s]%bIx筸=l57we#̙,yw %)ա G;k'/Eڷjo2YBmUS ?v}y M@z96gz]8TjJ1R{  8t^E6˛ 9PU7}?~ẹOg3ek!`t߭KÙ9krգ$/[cP[!|J e)6 MEep",T`U13шҵx9S2Rki+4ɢ8k|.zIqV+n8;N"GE[ 8T+1 RL rw}~>fHشP52OBӹ;V>נ}%W#دlϓ=?Y WA0jV@^ %WoʯLvcRlncxuX_%7=o^2^? ťç]{ʺ}nzUxs%"bچp̨oGt?:4M"P 4+p1<>u"XPisGDnHz|_>@DP c0e@ *K֊.臑mj"5fLLі>RdHBoWdl7Ξ^}wlS[9N{ê/X9vfw)Lp,PՍثS_ok*7j+n81Argv\)@1?uKNuX"ǽ["~ĝojĶ hj+p1FjRr1xcrlu1=kj낾&b,Ê0Љ"vS'*qRy ,c*gXw'>{[V3)ΚEJ_]F 02JdY1}< OOZ rR  sjkQd"yHe+yiQؕ eЀ$bQeQ=<^Ae=I0\4*髴UJhc4'VFQA1I7{8a0vHól٫"=_tmz̀Wp̿0!xX ܔ!25^uw脵qE[>n}|4ʔ8M z|-~b/OKq# 2g~wZ~R?[~ͪWCoË?vm-޷{s5p$J_c~QR+Ccn6Op}UR,?hτly!rRۣo= rb+2cxs1ɘbyG0y fl@l( qθ,I/Y-6*h(`8l3_ṝȿW/{P+gcDr]eRiuAMRjҿg:Gs7Μ⬚gG 1\#D}8Y1E}u>ܞP-*f!{S"f`FXJ+ـ`3gܘDE#&:Q <'fbٮ)HhQ*kFjzcVbcN.j&g`vX1+09{."sy3#|Qxd"PY$&cV!B,LEidϙNZ_D֏x$sBO(=E}zݸ +,g|/ Ï_3_aJCވe>_D}u-UG9|̪W"+L~X ||'O{HLYqclgǏߘo]5X1sV}457~~Z)n"XОi8{_ج\(9eaL0i yeZ!vAxYj8+31x#^55v[pՐ?ʉ.?_QYc t~bB0-̝EZY~)8"+\< knq"W܁;i`iݑݭ'*FE|]0guQ]1+gcy Y^X{^b1cFY}8Y}|5֣PSXv,YmEҗo6$ 0!,AZ#EA5!h,$ע8;H.@^x85AТZSB ʫNqm81ϝq ߔ-2gBUBLsMʀ8PfUfjg9_ř;b)E]lF.ADKo彵h):= 8/l]ϟ}'h=0!8Z[m_S-/- +ٳ2CK<g{vMVWAdE]} R5]oNJG壭mfs_ݵQnŋ*]f]tœKK,Gf];`sV{߿ygŹވB7n}N֊QɳK1|Nqg8++ziD(<]˚nyX`e%qsqώݰd]QCZ'8{8+ y/οcA}8}8ny&k7⣃GC O۷kg4T➆y+1!5}qVgw%qVmNqxƌ%X~!шb5~}{aaZTE#ڪZT",T_(JEQL&ѨM 7W R XœlGCzViqJiY&- Lgܺi_ܮܣ+.9Ñ 8cj⬸KABU*?ǵW6,g/QT:ފh Lݺmce⬥qRL??[6 EUC's [}\F?OΉdv+ߟ5njDR]y8hd#63Bd. bN2"|Q[\MSDq֔uIqʖQo#'`ImZx0EMqV38ugyڴ2*Y2%F\<7~KgF넫Yi vG9ku DT,)20%ۄ"4D'cQBV/CUh"N#'ǺTh@#0uoҢle*rf"352o kPTY&!8b LE5 #q\bqJB|8ǀVݾ7R/_NBXJ1_6 O(m?rwΎ=fݎpY[:Vbc h&n8k{\" Wf)jU!mY1}< OO5fkjcu sAZݚWr+Yp֦m>' F6EHfl % r3ܬ\:`7,EpwCnKۚ 7B~lm 6"6 ŚN8jbU*k|8sZ`A9}t~}Mt$6Hlٗ/Kw]ܬm2:Xެ8;9k,\'<˞N@s3z~=›~NDÓ>>g  0r lVRYw)s1N$uYCpwfVNxqkgv'O[ Z3z@leX&;[vG \7.j689+t0< 3WwW8K $`5Vٟ7g܃[i=ֳ$ pxdMbg-FH!l93+qAܬQ$:ԁ8;6H\'<Ҭ^)^kzv\8K? $`5Vٟ7g܃[i=ֳ$ pxdMbWHHHHHHHHH@YW8gIHHHHHHH(:?+w6ζ'       %@q{mϞ[q, PI9fcIHHHHHHH#P38k-9G$@$@$@$@$@$@$@$VgJ5nm>6HHHHHHHܚY6VgJ XK⬵xG0Wβ$@$@$@$@$@$@$@$@.EKq4%q`}$@$@$@$@$@$@$@$@Gٜ=#@q@$@$@$@$@$@$@$@$,gE.a6HHHHHHHY4;;#@q@$@$@$@$@$@$@$@$,gE.a6HHHHHHHY4;;#@q@$@$@$@$@$@$@$@$,gE.a6HHHHHHHY4;;#$Nt! ] P+^g?zw#       p3g`lm P-OF$@$@$@$@$@$@$@$`>H]"       7!@qM fڇYpe$@$@$@$@$@$@$@$@ P5͈Wx0l\vHHHHHHH\zTl\5V9H_E,Mk3O.\Qj9r"=dDmpE56f 8u.WEj8n4ߋ8EfWIHHHHHHH\.Ēucf|;E%. AbR"b"[_uXWDYV`U,BbՅXg.m Vi5í+w9Yf5$@$@$@$@$@$@$@$Ei־O_l56f,“|j,ժ/BV&e Q1U<`_ٳ'ת|bJL QؤވFTƣ%s9X]X$$CSʜ3&Yϗ.SuiYUmh:'Fߎnb-ygX{ュYqAǍ'˿8{,,Y~ =Jy+?3٫P>YsQ5sd6}qx_=mgǎ 6`͚5Kp1)~Xr%z)\ve[`<@sa<^:&9sȳkyYq/g1ڡ~]{w^2877"        8{o&i苭oooi8[O`}]0Bd0SikQY0GX0 uBYU U%+^%ٺ:F߭o?mVxs^1 w}+ѝ٣@7/٨4 WD@tvpW-_w:5*h=_-7/0if;']tD9At-ͼ 9بA$~o>껰nZ06#{mVT2\3`$**m3gܛs=ř6s@!A]o#Ƭ-cuq_[͞3lg٘USG Uh,Wmf*Þk964u3t8cd){U]>9--m]: ׇuO3zs9?DG(ę3zIބ'M߬",) d1a6⬍8".lk10{BP@1 [qK7ҤŸ)ZK4%oBVXM]lK1/f20`!M:g+9K_<y VV|)fS|E0tJ^OkD )l[?)9u { k啎gm)&J9tR?Pck8Ĝ.>e(\όMی%Ԝn8P+k93u3o{S`&ږ?Iԝl}A{D)}ŘGϯ'YYSvroc5ז>xQ>̵>Z#ζŖQ֣xGpqW6/x￴pٴ+bϿԨ-hCC[-&!cn8g_'~y7p9n(klHd"wOmCΏﷲ@0R=d*z_įd F6Ug%5lN>eo\"4Z|a(wvա]{?y)Ҿvlo-A)ۘ)}y M@z<_.Tx Ӽ>S>T1d{Xw|50̦Po>)259ʕZy:c=סD=Ni%ޓ_Y2g_}FwuG#oU/\S~t=oaR-E#dl8RM,S[W+#. 5x uϕ! 22gI@18sf˜\ѓw#l1< M±&N^c(zxwƼߡs/'JSu @TV#"pk!= 3_>}c?g!\XuWiM}16gSqQ5>FD׈^C018W%sV?"8[ss(?q>8+q8c:qI37LŖ1[x\5/Rg1_j(ANjVK1" ]8{x9ܱ%GO7[ta5(m|%̮۷j"{rޯ*M&`x!Q_6-Ze G9.O!H 7?b[]48rD` †oU[:=_e,DoZeFjmV.}!}BGOnBdƛO:ʇ\EG9 #ΊGZN!* c;Kb 1*r)Z9ǣ 8{}U7Jf/~yJ{>V͜տO?QDęaE' |Gj|uء Yö#-Kh^,qE۬!?KYn}|qRtݹ;a=./7vˊ7}2&/-bLHUۿ0!i{ĔΜsᝊe @)]C!L{6g }C#˷\?ɢ@ [W̞.>[6}JuE])-͜~6ywuq^4Ym/?{]Ej @7w ;>;Ӈ(}O(*Hҋ"%@ o\[oz̙s~{sfYBy—!V=g͜՛˼x_KdzϮ:nnceY=۽Gݙx^\3i5_@4O;KL\oE4Z~鉁 'H 3PH)/W_tkS9U;Q/:UxI@& 2gq6=)>bG*alVu$fNgK,GM VAv1e<8O-?ELVwǪuSx6C) Wt=V@Y $s׹1i ɆeXge_S=>Vl"H.Rۓ'>YR4E͖zQhF~rU%hTC#9_VQeqVZeݯX4G$dbVzԢet}K5g#vǓ n1ua.,΅gn1-a¦Ц\=5oԷFeH\ozxʴ*z?f"7[\ oQ'L*8k4%Ίm+ϳsΪ-&n]SCJ#g{睆9PhűX9+vVzq޼`6'Ib :`V5SzΩZ^ɪ]2Oae* #Jfm&{ j4FGG"5^Ģ8+Ggl8)}H_Ng=#Xsd $ZW@~{IvE/d˾EK+qVmϫdQ8} _AjBKHuH}}4ZL'J-_qHŇ~EbXޙbAu½ _}Eov-QzYj󂝉")2G+⹦Ȓ8~&׿ '^ qr}̈~,nNhT-wK=V:l8S-<(2}^G{5F!YV{f qGvbYejou"oԷ<_z E2 &6^5?҇8kԯ#pϷb)62zgIJNNOe,8YI^=h++fsnHHm 6s֗-g5'p8+D*UәW:>rkPNJ><7T>$Ot7]ëm|mwL:ϒ Ke%ɌI>#GqV^/Lk+ñ3$g4G<>}_l=Z4Q;>) Hv"}>Mdٺƪ)"=jr#(^(DhnP'!0:𩳧#emkTLC1%{ޤЛ-#1 ɰX'VcUSP!8g̜Ո~;%ẽ![HuTm1![b+nv/G79 AjuGW#Κͻ1]D+k_ٜto+OɁ1]osF?+9{M@ysW<qVsuezs8k~;C$t<i{𧽡gb >*?$ANg=XDh|1çO\1L+SGBRU˲蝵P3{O f#|).nvUk_u {U)B8$נmUȌcpX%G"#!! bc ARR2e-y P>N⬓źِC`QKWԚq/9dW.u&AqXZזoh!调<`';)ܸ[#FT-ښ4a"CFWP|Aq:vlmR.9w64kt3B;#/<8{⬰KB^ХjacR`w@ws"e}s0~I}M'݇⬃UeFSKaQhM#x[8mt;*<F.:4쾟1~bdh+_#)JDAa] lX+ƒ%@q6X>pnlM_{ֱckrfFηY 8mi=@h3rIj;Gi#V^YGŒWaωx$Umnݚ"5C]+"l D|Y]j&8?vDBZNº@;!طrf.؂@ѲuЩWwQʱozndJEæغL߿Ҥ~,Xg[L;u5maTNj Y'Y+ʀ+lӗE6ʥ&vՈ 6GqXu'vw}ΰS8ky t#[vhS;_b}?Ol;pYpyd&Oڄ}FX5c2Ӯmil} uHl&IJi%0a?NM"Xґ֧7Z&eaIԳ*~LPLgzl²I):y͜M\5,.nWF ^7oPqe/l-_㭹 q)κ+u"W=W$!mr+Τ46vBP ;|ηY hc3B;;Hqv ~mZf$6wwJMkI!woN¦ YwY0n 3f"=g pn#x\GowiѴ_o4MS17C,3g(:ބh,WѰml \K0F^CP[1ްmn*eTgfa?3UZ{H˰- l5VGVBo ѿ=OlĬal$5EX5u&N\zbǜ阙YʣadX.3g] (κŒo,Ǜд)?]6vBP ;|ηY hc3B;;Hq6i U>hT:`(T6O`ɘywTpαk =66 %oh!}(-doop׀67agyY2ml48U3guyc.Y"ȺDfج,۝6vm!` Fq(kHv _? 5MYs^pbDuQؒfq6QQ8u4$P^iq\FHjh|! utHˍ¢% Ԗ_,;,v8V<6`Y4.Ƭ)fb<Ѡ~bstIًѵB3 _9ѰZ&_3c{4׵+ZWzThX_3K>CЭbs+gNkq -Kϧ\OVn+*P3ϜB`}` w@;|{XQƃP~>zKaf Ě8Yǧw𐙺rB9CHCJrN -% ]26%kv7fYw-fFW޼Ҋ%Q?Җ1bD }/;KcFZZqh3 ٸɁW;WGeCR _\Y_7T֔qmѳ%ؾLDo;/z N{ɦ!uwˑѽqbm?SzzVϓ oWƼH'/;|LgUeqy3'TnCYʶ+O: ^_)xN7o$*&ͭ\ ϘR0#'vh7]4)%aټ3 eeG zSwu f1/h׀fsY_㺌#ߎ/M:XIz[ %fw"FqLxC=<]U]K09{aP6O|6eOXzpCG>n5=w<;~Za>ǡ?uY嵣qO{VbDQ@1Hn9-Yg%k|!dv<< n Z55ʡ#*vz[nvXcɁ:N7򉴄xt,7p psPX &l^,O-\Rח#fDacy:UΈվX0\?^NF~cվ2Ez<CF8k՛Wfl#JU3twbH߀m§[*J Xxyj2cv3jјh=w$o٠zt:wƧ]e'؞I2_[ӫ޿GjLTfCT&LV-bc)`aלaAjOŰFWv#ydy-"ɜ\R'lឳZ{<}o[.n!/;COZ=Dz8g+4SYlCN)W_tkdoAɤ3zei~#_<1;w.=Z.zEJZeq+}Fb#zj_8$e9+m<}@;z"~L{qܧ^(|Y\-Pj+{ʸ4pCI9n ج+zZ^1QF; cP|vlΖ֏eLY޼Eq6^BY3x~?[mYkh[pͯc^ʜku\/UJ'DP}mr8k4˚ߓ(jC[g.$FqVWJHhbfyRtU֨XyEZBۗk+_Da:8+8x~$Jw6|nG?>ƣ|l+SDJp#j7dPt @l}N; JƵ=F4>ny(QMFDz8a\Œª)xUvx\qVlcd~8+l5-Sg|ꔕq%}JvV'+X%S]dc{tF-LXacyAgU?#vkf}E-r^㤚cNj_B1R!Yq(ӛ /;=A^Vovme%S&{\)&&z=,eHvǔS│Vڪv$bƛ`[N̶3& \kG^mԋ֙:{-ykw[6ގyS'+sq@<.׊Fk_qWlg%\AlĊ*cdo;kuW{J6,p&2cyިܽUvye\2$WfT@Dmg| '34T_8{ޜ; *J&=S*jʉ;QvvFR?Sl%+Nq͜a ɳ ?6$qV^wbʼnS/2{ҳ3նbE\G|0G*d6+S+ʫwq8[`1Lh8]6ye)aL2OW67gO|ʷ2 e>i.H)KUqj1S&j_b$KIv8k4z/G7`x|ض|Һq8s%d~VY7~gk4O+ްT9^ɪ]2Oae*L56Eq6CYziuFcG݂@nR;OŬ̹V‰AFcZ!XMĒ8x8U|q¹*x8+y`<l=W5; > 䫤7BվN{f`X6g_d'iYYx7L3w6݉YowgM=VE'WO;2jeҲKG[ R= Hj7Ea({C,廲=g?R_o_>.MiVYF+pWʴfD˫?d+^T/y[ 1#1Öl¥|fOzvKn|گTD%1O/2V$#?R6  S=ǥɜ"{IKf^Z6$H]@"o}gF).X |XC>$^*@V/oV`|I^F~cվv'/ʛ?CF8+Jƪ`6]qUZk\VڣhNzl!czF2W~Pآ:k6:1eB"cb(lo 3:ϻC5ȇYyH|\51a첱UȶDz~m}:N;Fs݂v z⬯מu5_/.[+j.1)Z%\I 7xɈs C'|y6n ~}Q.ObՇuFs﹦ԇ[ u}E!" ){ɽ+m!b|nexoAnz0W%bxվm[M|tby1/cKl5sVC^yYS 'ɀ##uHF/t!{=;]:dBU@%xSƫk?Gj/|)6=i1B/2gͽ_ʐvU*VNI9vkJe~\AT+G-潍ؙLu?2g v.=Zߌ%v[qlUlA71h CFٜoZ!Lx&M 2W:Jmo+J 1X3]WL)~`4&7<o}Wä7}7gyKϮ.dL,+ll>ԋǮs&vw{nz;Г7^`YToʹNV~8kq-hg] ]AM9qX;NvNezNX՗>}61ވ6>q:D N^޺Su-ْP / 9Y!GuQg3I+DiH9`~#sL s^+ވNq6yh#@q6,a~q-dp,连6~E{ Cn!x~q ;| βQm)κǖlI(#i3IUuԙ$C4 Ŝn0 9q& k9/oD ϗ!{ $PT)6y^LG +bmmlzܘcLpEi¿ Ї forﴱmp^%M{ˢ8k/fgm6o0r#q-dp,连6~E{ Cn!x~q ;| βQm)κǖlI(#i3IUuԙ$C4 Ŝn0 9q& k9/oD 8QܼY8m0ric82`_OGhca ]8܄U>g˨gcK$gKBNAVȑF]qԙ$*:L !Gs҇b~7wm8œŠ7S(n,+F[Y        8\۱! @q6Y @@(lYvKَ('W@QR=%@5h@v-8?8P!&".*>"c46v`ϣ8|A8<^VÊ5Ss)MB["8?cZL X1r*}oc-/X%(:߆lA('uM\cJӆ֦b3uGKP8ꕪjZӘc!~;P@{ʠO˞ZCV[H_JQu ق P / +Na)عƔ M BcjfJki[aY&˅6MkW@K{[6M̜Hpicj VI9<η![Aa%8x]S8;טҴ!)9ChL=q|g,?h]ܹYZRy0ش֦V*\hT穽>٧.MVg9!zWnn+?9~$~ۿoGN@ϖƱX}h+>s6i|_'eLć)=vQ8u2Pr+\rEʊ-qŏO\9huR@ΉQ'c᭖ PH3W.g=Vp ?{6D?Vit^rxn9[SpX @g3)lLukK;l|{Ѯ\ b E྅AYo?5/$.coC4rB%D^8 =^x*~i^Z=7°(l -ЯZ'(GwLƾSfU*dVOLm5.GBtt^Y9vfWP#$[dv&o W_)N[;kvGJ$%HF3yAoҕ蓷_RŸr9{Vjѫ>Ê+'b@+d'TnCYǔ? *LD/?]7~DE2(K,P{Cm(/_2-s`\?jG< J欿|ϓeQ.8#)Ζ)mEaۉr!c[?/ƣTr|DktCEz**+ٮ7nV+ꗪNĊj?*ӰfRZV@׊/kHO{V+03ϕQ[V{i_гM ULIJwzU#-aɌ V%m,go#9S Ua9$#qL{YXvpcqx|o7C$h*BۤO([$iY9Ae D(Ֆ+Anx^_TL(&.JkFOª[pK.H)R Ϧ|ѠT5<+O_s#-W;Oh\ffy?z]`EöM{z˯F',=!ɉXAuR¼aKF[5y Gk[g67a{ J牤8+–! 7W Uͳj ]T8j.{;2z+te&rEJCpՏCQ$!zB/~}q֩cX Gbs1Xn#sеBSc_,xj~M+diΩ%}][V$8{<ܬ_ c2h}Ga+18{iJ܃ #al;^6fY+Ljτb-(o7ZΞ;qmWe뉳ƸF1o6|Ĉ&Db>99Psݭ??C1Lz5fcmleܞu%q\-yo(^7Z{Ht,OLgoo-P\^,g4G1S Ua9$ e L<>Wh2.? 54yZe(SG rHk0g%mz|h\!L8 f?=1VO~WIJ5grS1ѭ/3{cߋk>DB ⺟F hi݉n*xA?zuLƋ|c%еYz>:=sYsGjcW+~쏽΍/g\6|iY;LKgKں)ΆװGvqVS5׹<<ׅڧ4DE?+36_ >%USrUj) {):h*J&lE}(ǟ0{-֨bܩ!omgit[qNbТm<ٻRkLy2lEHNĒ,~&6;|@\7Z=~qGnUw#;Zg\l |O W.,#)Jp{W+}HldLs6F53חg\8+hMg?wnx+nO{>$HSYp|Aqm\_w>1D7zg%;zaա3򛤺YGK(Hr_877kX:1J"0W֞MGa3<9Ǥng|RsٖY+YΑ5~ꡟ8+oy&k#ߞ{/QO>>"=#Y161s@+tc¥EY+}ʶĊx5?sGKD y 6^}ɪK jm%cK81?$u'e TirԓDP8=!dfҔqkjStHi,ON\?4N因YZ_fΊP+"n]֩|c$0:TriV-Ύn>He K&dӉH-Yx勖m}L>&,=SɠL&~ e>fKEJ$]EWC*z*j6@m'O"!ؕ,X =GM^Ao~SæcdWɃ O={S+7m_fZq֩cB$lm4~2qqTo>CQ~g땬U!3f^bzYǬ̣%\E$@@Ɗ@}(fW`l>m_z#sbJ5?wł>)yQW[%3w1(]81v^,@b\⬵f{2Jtkf"=˸=ݿ7uc<ك]o}V@׊_oC3ύUqVQ{˷]LKǖzeǘOq֟Q纎Y.NX#(OdײKǹK 8o$ W{skeuyQJmT-V[܃GURz-2ge/=>q'T^qV&}۾\}\H&l@5*hf)K>%ƙk1Jk7Q{gU~mD]8#;1eƪf$L%U2UGUӗ%e6 Te_(_٫@_h}#gO"!؉-\R9 pW+PHi+rrru\qV^{2;wNm#su WE e9Vc3qH\5-೭.03g,tbAm8T+ҟEdiT-wKw6ݩ? 1>h~_t1f?^;;#nhE.๦ n8zTH(c(z-DD~wj;sĵ۩:} 6t ['2f\!bg<˭{oqV&W=VQYʜo]5ODz~D3V:O:/8k9FA>A#{Ce՗8hkQ5l3ɫZí19ΈdJZIb31t|{d2\3ic,+}ۊ8Zѻ\AmI=slQ3?FFl#D[R#1577xXcKh}Gq6TrH"hg-V=iE& =g&p8F[;#SGl;6;nfk=?.sD>%mcy*b _9OPI*41(D>%mcyDlY",=^mv=ͻRMgQNq(JG.J j[p~Dv DRUM =NO;FD ަf79m~!}*)Gq6d ҰDV)kLiQ̜!Ώ|z^(kH{;ʢOÎFoc-/X%(:߆lA('uM\cJӆ֦b1cjP;m +}mlPҌ(F}X08f,>`FSRsֱckr~0#iow3ObtAG}"Y;B$i{/m&@qf89`g;ΡaPC((: 9TM"m}hcG۝ fՇlزd8#h9Ǩl6;?9t q9?hG{Gl}%maQ|;B'U8b,Yg:֖HHHHHHHH Pfna'@q6y        g1MlL'       [ P?on7nmwy   p4h$@$@$@!&@q6@YPuX[   8|$@$@$@#@q6t,Y PuXe   G8h$@$@$@!&@q6@YPuX[   8|$@$@$@#@q6t,Y PuXe   G8h$@$@$@!&@q6@YPuX[p2Fa_1v׹MZD~?ݦRAgٹ(ϵ+@&x{y~}xpNFʺ 8Y&(#`% w?j$c>5ϭ/ o6]7O$gc+4 (Ά*$I@_tؙy@gA׭B tImGSݍ{]KgF߹Ã%% P /"" pV( 3gwW8jq$UdexiTt,V|p8͊A~ڻoS}f+O: ^_kJ;m߼P67[=Ct$UGjP`6݉1NV,{)ETVd=UlY g8,{$VuJap0Ѫڿ%zn_ٳ7VSgOcϰ"c:CJC ob8}.;8{CՎr;UgK9z@8eau"Kldyn$d1H\^|yܘ'sV+ζM++' >_~jܔ-?ș[<^l;>2WS=/VMγeBbI=`|!dv<)'O5#pIkFOª[pK.H)R Ϧ˦dI$@q6HH@[-W;qd,*Z?ÎxXux+>:ϧ8{  ^:{O}V,,}H0$8V˲]$} Y(<|q ZLlݒUd~x}t,?YΨFK8QJ 32c8McJ#U' *mz|:Ms'w^ٜs5"p0+IQOJle&ξ_5grS1ѭ5Z'3+'rdV)VNt7Zb2D=`VH b(F 5o(FUX'p'BZ(YkoÁSGt?&ٳWUj1?騔90*6Yl_Њȇ@(Q()1WپU:- ~YGi(H (Ά1o@1AJle&_;qϣ/ɤ-1\WfI_**-{~ĊxgcH8`$0 y]nLA)WWN͊17aH?YW$׸q#;,rrPYOjlؓKSsj%v*WuA$@"@q6T$Y 6+UĊ*nc,띵=hb8+S=G4+S+7fo]vQ,8kOt#n*DI{!=\['_&g%cCw}oL*[d'~7gSƳsC>yq6!0>4n75@zjٲKǿ[  {ُv/W4S+ޏNȬ #PuXIzVb+8^Ccjo}҅nxzz|/չ 3ͳp񈳙Y_%!r[w#V٨0+av}I Z@+mÆ;/g(]\9,=/Bvt{ޫ ^j"Wڊޅª)=$$pZv:6{dIBFlP iVb+4vٸZ' E? IDATYNX'Vqj 2fgWފ[wEϴV;9}vPK  3gwW8jq$@$@$@QHlU"  Y@l4Xu   %gcl+ f Puy8   ($@q6 * Fmyh @q6: dmHHHY3B(κڼl @8FaHHHl#@q6q48 V`HHHbX6J$@$@$`F!jg]m^6HHH PBJ$@$@$@8kz8P+$@$@$@Dl,Ym%  0#@q֌w5YW`HHHHHHHH"JlDqfFlY!       !@q6vl͖ @qnA$@$@$@$@$@$@$@$`v}٨0+A$@$@$@$@$@$@$@1IlL8K_        YQAlT        $@q6&F{P/ E]yߨ @q6*J @L8fg=$F$@$@$@$@$@$@$@$@&@q6DY艳j+K$@$@$@$@$@$@$@$Hgi6V:T(Ά$!       Y|W8*s1$@$@$@$@$@$@$@$(ge.V6(Ά(#       JUR<ϕ(κҬl 8YG "rIHHHHHHHP5#]M⬫Ƒ @T8aM@O65'   p<_ߞ<HHH P9ZVYqb&   pyxwL-UL   P !Kp06N$@$@$@$@q6y+  !gcl(+HHHH8k!  Y|W8*s1$@$@$@$6gÆ @L8g)HHHH8k!  Y|W8*s1$@$@$@$6gÆ @N+뭗ը"`z9)݀݀"y9~$>2SlXYy +n޼/ ~; BvC=nZ߽{-[{ũF7==]wmIHD`a:¬i"ζ8?cT`,+ulӶbZYSD<gj|!GJuԨQHNNƀBH$@$@$@n"NqgϞ[?_|oYĕuYƺ " ('T9+)Yw\ur/Gf纞?grΚӳx @RR)-[{|yY`:c |78z(j׮KVJĄ  frTA-V2g%HUiii;PN<ʜg5jԀז-[`Ȑ!ׯ/^۷+T;v,Ϗ~XՍ @YI(V^z%JÇСCQ#JYFm3X6iDYӱaԫWOŕ K?`ҤI(P.rL29[n]I|=sιּys{<87Wb{-v " Լt`4FW0J8uV?AѣG>wy.\Y9M6ƈFŭLm$ζlRņ< ҥK1~x_oVbvکi.~SqVݻCyb]0 g'/[_ܐ釂e=Xgw;36hרn_B&l!e-NWcH .M6Ϙ@w_|1ΝS>}Z gVYO>lY>:tر (Z*L\'F6׻-y^1qDg}eJ ka͚5JC/xgWj[>R*Y\s@8Hl.]t}3gիWWټP\l= Kqqܹjk9K/T=Y^)bDߌ@Y< Oʖ Vb`'|+ٳ %zNxgWT\Ă')ҷc@(Y#k*cVYYYJ5kda%s֓ɚ6mVXSO8gXOfeozm8}'  X%Nq633SwrH'o:y_U7.WX z^(YJ 9+O?ge{/yLquu֩77O,Xl7 h舳'ϜqK˶,dΘUSZx tM[=g=l{յ{O8KGmg%{TH"n3EQ9+ʖ|{!},%%E&AjŊ駟B*Ξ={7x#5j> {zʑ ޽;9}'  X!NqV Q>$g̙^z1|@ɓ')Yއўm | "ZEdi,%ADi^ lׯI|0gEƺ̃HHte۷ 'U8;yԭV5*S>uP8[.8U'8bd,8+ѣw^7ǖ!)SFmI Xɜ]E]xG̶5ՁlG0hР\U>ƠNA+Sh<HHH)JL({0:rH%LzYهV/.R/Fm~3[C%J-,ټ zR[dI){~*W~T\#ƥ-XW  p1qV4Z %9ި>viM 3gUHC{S+z@g]l)$@$@$@$@.$jqօ$  irY_;x0# x YM"   08,HHBElH,ͻ S PuXo  u7aU9{I T6g[癖YSD<(κٺl бdI$@$@$rYt?چ S'={^EfS y9v&m-Yy PuQ$   a"IHHA0@l8gIHHH*VI<   0sZG㍵ӱdj&V Pxy mxpՖBBs6ݩen"^'SF0J5"@k/_w!zWnn\$?s_7}#O6#X[/Moc[%e/F 0|DK~׿CU~ eၐsN[`tC{Zi?}S⹦8 d>O?[meI]VwY} V GYan:PbgCюB(A=86q6oo/p7< "!0u%JJS+@9R=*'#uao9>4n Ew¥91r)|u 781诽^r+WGvLFWT(Z-| ~/#1<|3gړk*šcxy4~Oղe/5#H%3Lqhݾgn ΞUaE&u U;Կm>zVDe)T)sSve^+K溯|P 8uezxmtuޛTuCAS+&x #V+ꗪK^طJyy6 6ƭ5_kUm#uUً~ڻoReꉩyvp*@jP`6݉1Nm?72._ߑ>m'-NiǶ~Ӷ's+v DN#X@E/sVO}ky>!򶁷p#ՓYG -r[檾ay}Վxc ةoOUc{QHYV.ޓ\+nqzh.sHwF8oB[V5ƓZVwʦ/UKz~G=ɳYu01{}|띡0RxcxgG<!!k1fTT.VHV`Ǵ\JsޞL7e<p^鷌CNq֡T%&Y"[H Žuxw÷,u7v,@ϴKЭBsH.\Z?铰R R³-VKTBdZBY ^:{O}V,T2.6|Ĉ&Dbc ?fL顅B* H%AB*it!`zۀӫ .wsGHHv+ɲ$=;3ߝ~@q1E^&NpV;@_|3,ą[ׄXA#d_̝aˇI;>(ѥA0,K٤Hc競Z?{fO`uؗz\R+EޚJb+sW)KX苳Тrnu?*y+g $xӡS^?ipIΛ;hǾ"<uD6Cj0k7”7~9Fu?l#0x`[zGq7H}dP^A:^F snbȼ`07]m1alrLYJ'"B_݃;LݪCY)~kZf/>ߟzE–࢖8+5FMcҾ8}Co˒Cb|Z9O^H% Z)"5;>箩R}Kkcom~F%,QZHkbf#4}aa'0nP/gɝw8+u;o>XsYctN嘵_ +{^AE}v^F )YO:^1jë"툗֍8~U$W稾8km:6/宷EJ]iKLs%9T׎UW}#!:z-$笒뱒pZXaY`q[.Vt.nr%B(mqV.=6!D|A!jսKh3w<xm&π頇) roO\*~kT3ZS$ξ!y?HWT}W8o%)I?v^="dh)"qVՉ@:X8+X!5Q?:^>OBna>L࢖8+5FftZ<vB'Ϊm_,Fdx9@|H"!ҹn.rsW)KX:)g'GV/:͝7LƇOi}֯KkCw>w\<{R}--_ՊFZd=),.+-[5:ZΏ+y*=GYkCbx})w՟w-e3z<!$w%sDq5H{?D;֮i9trp;y%gԁ,:"&?yV8P# IDAT//@zș~"r!=ۇ4Uk/ov t(/c (wIo9l(yg)޷iHc@}KQ@ d S  6a- ?R>;OMkT-kIXvzUO~TY1Ҙ[bvzD6%Z:w*yϑlŽ 9,9 go^RR~TX"Hj#٨ |Ehjӎ+g-?wK8+nGXFEh-vW*Κ;o“LZ*bE0|U Η/j`k:D(Y꺤sqV?*]o]֒6zoRdkO`ɑUHLZ9<*ЍS"5-718xJ_憯V{SD*8ʚCYYMf8p_8hQ;cůjYu UO%Y*iED1]g%)הsYqVɼU:زU}bqV?J"&"v1,:C1B_x,f_8/l-iyF^fдoU HL\4,օ+@Avr=tʶmhj_,ڗwv Z#I,٢ JS0 W6`ypCrAA5;V8S CktoKإrxα8+sj>XR׌`\79r֎n8x>CcYgL>*rg\-_K^짛ؕK&бʹVTT)Dz0uG]`WJ2R^=ձ@ Qzڡ=?6j*s"u =|})kԒ_;Ve?WA숚1XVAv~w­TucRPͶѺJ=%/JC[Q`dAxx<?*'Gij?3Ocn^&ʃ=$L߻DZ0dJ_YUL5|s r [{QC3'ΚEwy@?xYxulޞ;|s#0X7ְfA"יZOU+Lyg$H1]XUK˻gӝ~KC9ܙ!qa–=aڒy[g{2йj+ȯj~RăV _LAE;6g ԯOwe<-ӏIc݋3q:7><GGcHc< U ?hY8+ZlLW"^LlG ޲jW -?(ݣP׳;$;vޅ!CU[srkE-_\\W30?*nfPRU k&׳|f^PR[I'j`8-wXuLCcEW/ pg0 9 [jKm98{Y>73Q'8u.]OO{ed; <1ہ7Rѩf=j Ӯ=вzMlHJD%_?kuCgb<ҳU*ƶjApz*نEF?a|.{$#~3gNe9?ͼ<4maa`wJ2Mѵmқ ݉W?)hdzR(g{B#7Zrr9R Ï1/aH8gvLm:.!ܷlGv:P3ᝃJ xTpsMGrұR<>;DD!}aC?Tjs8Kl5R=%^~u>H\ "g +OoETmQl &n/ov?,w:Ȏ~T9q֜+gW%E%??xy܍TӶs ?П#eL9DǰdFC (^JtB朻E;6"5+ 6KE\Aa3SѽM5 QҎsN_5aNꝅϴu6͝sr⬔ߔ uDž뢟GH`oy1;{ Oug0' .j^m:L5,޳UrRu܌͈v!?=41igU-Y(TkCU $gGW\U>^IݠEh?YSkGJ^2@Y2?t:_zҐawfps}8eOدiVY-5UxS Nj =qȕ [t@ۨZXm=2ss1s[kG!#Rb6ĖG#%Yht/ԪuIt"[oֲ-n7770[z BHqVof=GDk_F "! \HǍ[و=~vJ-CK4i[ ~꓅5`N(>LEf:T\ >c'6YhվQ ή|7p :z ]JQB*owEĔ&BsMKY9){z~+?_VՇ:1E;!>q2ݵ "u HYo:%!3:&8z*qVI ~@k6u^cĆW[`_O3gkT38+{ ]Zqy`L 0&LhFݧJ!~!RTɣs}%Z| mݚNG^~>LY:޾}'sꊟ0AH8w22pǮ6_#^;l:4D,H]CR&hYS*K7p_;Ңrh>n'9Hf m5@t k~psG| !AѳCjD~Pul|]B"86p~Q];jb~R>닳+0:fHjYd,mdrBJ={>ذOnF}AAQIԨl8̜sϟ {CZ/{J UVƗ+F0"61*eHElrfr~Sʗ6zZ=EfܵBm1EnN>3iBӺ#.ܸ!9K6LT4E\?"%Scj@̀P{hnǷ "QDM=B+6\+.XuI`L 0&`se%9}B:vUbLJg?]wC77|#"]=')2w_ΰoo .?XĮZ_>:>R]2(o? Iqޕ8K ߃^c.#IxzLcPipv)YH [m="Hq֜2sn)/gKjP~7D:Y-;MhzanfB) P0FJU{4œdH roD[tk/ܽkaB}+^0o뉚z'ȝ0kK Rgٳ!2&`LuZ̜loB|U5gO HQ#R!ۢs"'00ȾkW5+`xl¾RqO<U8+٘F)G&Ogq9Hc\^bbcnZ>KDU5Guѱo$,FOE<\?|aXͮEֈt9XR9,8K|e^)YD ٩y.lpQ{-']lV?DA.f 2E\9ql]}ܦ6L.YրrrzY@;~ܵUlսfS6:YܙuG@)E9wZnܺG,̸k0ff(D.ٿ[O$*'_>3зc$t(y95sh^^LAKY@U4(BAQPͷ2o(O+DOhRzCb)"wQ!חIfcDڸ6{?qr LÒY2Dy'5 Tg_q?:q

    pGvL|b=酉ޓ%o(꾰w_E:kn,g =7AGⅻOkW mQv}q"n]7Np5ln C"ЧaSEqVwsΔ8ko^)M!~i-N^gzG!TulR"v>};zΤQX$mE+wcA&-уb3H:~,!+STH ֯d8K#w %^Vbm1^OB+*M8x#]U`L 0&lG,Y^c48;g&7rPX˻<'FM}uae"82;$6U\lhC`q"Vo{ .;&Ž qɘ.L.igrz'~kVᯍVF~= 8kO`L 0&e1K;4٢Kw<6bYf:;FĄwl[`qV5Oh0Vن}VE j)2<)g2`K_&dJXu%oX`L 0&`{ ڞ-ΪhIm@#잹0jU N@;e`'e,9U[p-8;T71)[/M@۾jgbϵ;9WpD) IDAT)qs,ʜJB5+g]ɛ<&`L ؞g"=7xz᚜ū@~\RUcVvrYs$ _w/4\۬̓OVa.8ä0K\J9Oo5cqiƇrVvX5nq&TXu*wqgKxd4߀F^(Gij?CH<6$Ycmc]m+5^9;`L8[fK6L Ꞓr,C}TvlFyM@I9g[[-[Qڧ O=%QVv-Y79rVbIY+ 8ځ6j$¾1ku, FǾ?,ΪFp ,:3\+."2LeYWw&aY7Yu#VL ؄7~> ms A44-ń[7R恟:t46\ø:DDCK,lt ilQ=酊^8q WrnNϊ6x=Llx7.<*㹦)mx|vdA$qn`ϩKOT?m6#,Opn!gjZYEMgszqDY;f%0Xκ_OŊrjvCp| ܄p)_.V Q3>$~>.괮Z_AdQ@_|3,ą[ׄ8z ^X62Hk5W⿇G7jyڈz +gi<wx _ ߍ(`LX5Q'IEDag,:"&?yV`q x\ 0h]o4 lRc"̷*VkY(zQ?DǵŨ9[EZRx@=Zod;VJmZfO-/E8Iǧx,5>~)l 0&p<FEDrXu g jh9fYY7YuŽgaL@@T13DiAQ!ynyju {7C/f(Ri)ҕՎ}9Цg]5k346[<՘`&⬭=I."2G8^gqImY7Yu#VL ؔC F?[#ZsCXczZ:Fa-;YqV9^콖e7Lbo`/p<><@\6'ӦNacL 0,4ˁbqց+,Ϊe]ddq1NXhn 0"# RQ+v8~ݪ5GViiQE, 񩈇=#x{q"̧2f'6(]ʃ^6KJ?z, غAx?q)Rs3114)r̼Jg~qY\ 0&jhqY`'⬓:Y'u^]ddq" ,Z2&`s?b@ڣCp#Lh0a>Uu YfLKQkBp$^OI㭶">-Z7N [~x\G䊥O\<>^nbC+6@.y-ҒE9H`aL k,Ζkw."2ccAu/XU*Ⱥ,= 8kO`L 0&3 Nߊ8klYҷM.n8kVN86`L 0&DY;fʣ+YuR8뤎붋,:TXAY+qU&`L ,Ζ';]DdpmöX!22"&e4Y c{`L 0G%⬣z"" zX51 8~Q+Y7YUt.rXu9`L 0&`S,'#""Cyt2NugqzvuY矊<+8k<`L 0r@rdG Ӟ`q֞m6YF\ddq7Xu ?p/`L 0&XuTϸ`\DdpAϘf9fg/jz"&je].R`L 0&lJYdcr\Dd(NfqI⬓:N.n8SG`gU`L 0&P8[(CtQpڳ,ړ bqֆ0Ȕ,Ζf`L 0&엋 .Cbq,",cEM\ddqVӹP+κ`L 0&"׽K Kj`L 0&Xuy8 0&`L@ gP2L 0&Z,Ϊ%].N `L 0&J 3&(X-8s 0&`L@ gP2L 0&Z,Ϊ%].N `L 0&J 3&(X-8s 0&`L@ gP2L 0&Z,Ϊ%].N `L 0&J 3&(X-8s 0&`L@ gP2L 0&Z,Ϊ%]Rq֥̓aL 0&?wނ%si&`L`qܹO@JeJL 0&`L 0&`L 8[ڄپC`q֡ÝcL 0&`L 0&K`q֥˃3GYsw&`L 0&`L 0"lieNAYpw 0&`L 0&`.IYt+J)grL 0&`L 0&`&⬭="S;`L 0&`L 0"Kjqy&`L 0&`L 0[`qV$َSgsp`L 0&`L 0&N, (gǬ}l 0&`L 0&`L|`q|܏r?`L 0&`L 0&ʌev,:L 0&`L 0&(X-~Q&,O&`L 0&`L 0"lYv`L 0&`L 0&%g˥yZ,\`L 0&`L 0&@$)oe#u#˰NM:a]Lȯ@2fxƯbYc,*g%]Zqĉxu$^zaĈeF(11+N>BbȐ!ٳ'Ο?)S`ر9rdfL 0&`L 0& A0غ1С!s a:[ _f?dإe7u8fqW&`8;tPw}òe˰rJ<3;,L4 6", .ѣG1o<FĉWn 0&`L 0&`Wˀ"0<$P\ޖ/C]e|f<+ e5YD\ X+V6mmW_?޽{VGc޴i H3f}׮] DEEFF \r1ˠdЏ˗Ez7teؘ`L 0&`L 0G%`=4ưIj@WwI?͌YkX;_^Yeqr\X+R%Kzj̘1bktt4{9ԨQCAAAHJJ,ߦMKxꩧйsg|BX5T)rv(**BѲeK4mCwߍY<&`L 0&`NK8;%Ϧ>q_mEzv6k!-qJ-,8Rsѫmv2J8 t IˁK2'?aG0'n4j_ÜV+Q; ,: ۂ⬶mmفG_"gt" 0<0!WDYf[KaS,%{$RΣ>K.rβ8kY6`L 0&`L 0 W2qV6bƤ|2kS%j H|#zԴXV$z N&MsT˄8K]1?,κ! `kqP п!Ξ=[FΎ;#G+a p ,_qqqꫯPR%QݴSzmC8{R$_ǠfV VDFFv)YHvwܠc8KVZ%6{{H٘H+?b|7ؽ{7nݺ0 ۱cGYl2l۶ iiipwwGxx8(mB!pBƊtsu,po`L 0&`L 0AHq~ٷC7'oqs }6C-pQ .&\yvr/V8);UW  r Mɉ#D 1sh/lҤ˶"uY dd.AcQ!6BRo@+ܓ:EvPzN_á l $-.Sf*`p|ј5&z S ̯%hF 8k 5uuH)/-YqU`D~fMZ~Wi u;>Vi uq5v.X-u܀#`q֑c߾8k_K@$U 4Fn2KSM^J69 l av.``gq_m:C~:[ 8k 2u~+lT¬vU`h.v+]duV#txcwu9s;sH ev,ξv"ZWgWq˶Z#[Udŭ3l×ItiZ8j![^AOGM/ѳcgJ\Ǜ Fu٦?w Elq8pm}cxaϗ@ mSv&aޅr5h녩>x\?)9&SUDŽQ70q.*;V:>IUU>>Ԡ7O7wfHB$Kʯr:4W4i1d+~I<34]>Se}W[kֻ)-|s}7&kl`:lqkmz!jNIA~Xcm#k-g<r,5cWښ:C}>߷yfL-<j";7fT;}L>ZUf X2e)LU9{ʷK{ѱ)2e =_Yo ;c[w5fSvmu)5^ڵR[ޏw~{g6L49[)gPʕG#;ஈ6j$¾1k5iZnMx^?TkOBRYT"/OKZX- li88ۨb5 (MGT%`E7WadnHMLJqF MsMG'ұR<>;`ս^3}'ꋳr}Eb%ޔ?q4vkGGv]=!H}4#g~c+@S8alTw;P՞e":-&aD`< /p?DtҴu&a9qV6٫4 \O~dx`JݝgSxL\ʸ"=;5mV8{%q6 D ـHl KJ{cj IDATIS=čo[ollGNӷxE 瑭!* oDo:oDی|?Z;1dz]@-xpd[ǐd^m A <>:%%m­ʺ6͉r~&#+]J_iۦʙg&mW1VwϾ)MG^`$ݠ {"F?B׳N@o$H~FF~3vO#Q+Oo-ܴq][X{Mx)WUܦj} k`FCуw3+D4=ǧGWH0fW\ć ?(3gM55|!$[K]>Ҭw­T\nk[әS>Ojn紆5umcsܖ)젹>^?1:<|zN[ϵ&})vj#]9$9Px=Llxͮ+)9jm, BE/8w+97zLϚJ;^䞱_75Kk9`MܽKYxls] W]ahQcK% xf8}kMe,Oق37/Kj#T&j8u9&҃WwV@5|Ixb8:_d{LRf"+ãxZrj#٨nl=W<} ,>R+goԗOgcTnh]!ػ"Yl5hvlۜ+kq"m ,ZH 8P7eEAr2~@s55}lC# lTgG^dʉrB_k崣@@hk` JcqJF:nFØԵ7^;*a {Н@=q.nOL%lp308I 5~%9q`oS"#Gfxl`ڞ{䙍}!' an0Q*D75|L31#[' ;[MϜ8kic2+Ws~PY:OA /6g^O׍6yY];$칖LQ&ԧF? ?ЍS]7#?v|~KcZѠqJekQG{M=Fż??ׄ^{z0*yzVUa`ꞃu9G{)Nr%i:qVηr\$0m& `k[ӝS~O%ٹ)ui k떆;-uO_I=;ȭrKsʙW$s}_$@\[ݏ'v|"ɹ[:~}J^Tg!̕5q6L= q5!R?ziNzYzgy&uԼ(9f|,Ng]ƯbO_;0'<_"ge1wLA.WjaY&Iq68k\Q"-нq𪈂ro`ƹ{hiZf/>؟zE%L7{7yLJ 6笹QߊQzi߈vm*p8qSMZJOv? 2Z#e wtxÖˇU_}DGCN]l XhtTZ[ q])evk/+g H|#z4=ڊ$V/(i\,x2!jk葳$Β@:ls(F 9V- Z- Cso=?ϡ>WGߺU;o\im}alH圽6?YԦGNp6W)?-%MO\ÿvH圥@+ꙺAU u:&,Ɖ %BM۪ мr-[.gGW՚aonKos-Di 7]"ʥP<8=}>3Oy"Eگٸ +{^Ao%s| }E܃xy{1_G5fܛgC%ʡ+[K]ʋ8[|J9ERŚںVKwrs[_١shS1˝T.=I>Qk\ps׽kOn&ҼZ#$s(}-CJ(zs5E3Dߎk^/m3&m9؟*~LE]C5>h]Z}*|1ui Nl8[ZdٮSpEqv^ wDD ܦ(f@(=t'G8<0xՃ⥫{;?{D7R5'J[^YsCvnJ͞ڿeߔ-Ly"@髻7^?HRS-ʧ=̥ڑKYt,=X2~gg箭H9xGľl]i(^޿HrC0ڌub=@y| 8䞁0inMQm<ѷc"g)13wnG}ܨZ$JQaJ/' \l1_c‡Z,ڒ&r:(6.pM9_'4 r?8;dBѪJXbf{ZlpcMk@Tt,:w 5}+Ev kd*dkq ׏Q'w/`fyjGFu_f/%$G \ $m-'ٮgFVa'kaB}+1 aV_Rg! #g}kKyg}g,ΚjoD[sx)Lj֑;zfg?Cܺ.J}/3п7soѱ5BĥI\F%/:GjG92 }Kh.d\:l-RI\=_Jpl 8i(zk"m T5-F[i8yBz~ǝޕڜsk(6Jbs@1 I8Y9۾m %MפQ-pcqvce]Bf-i ANakfc*:}KN'l4ڃMg3)MhoOU]9,EA9łAҊUR=.ҸR L۳ a99'$ϢRR; rޅ)kܦ˶zhG:Q#Sھҹ⬹.0WA?.9kفSn];mE9ssVPbEĥ(1Hqbӳ,EQSx~;>B0DRzSϝkRuyb^-#i>(҈ȭR,MB/ FF?m0~xfק)mYKfapFq9 7z^&~>c|O(ZvƼ?M=o=B1"9>aO\&vn3octFJfWz=`xZlS Q-*!R,mUd~JG:@l5T#zԴ8K(*gpy= 08Ke;-'jM :|Oo(6jYcnÖK#Oe &B楒U+%P![J"gd9`R,Ͷixa8T b擁`|r/3Gl@珕aPT&xD!zJYSO/-jxLI&W#:'}mj篶Hk@_g5kmLĵE3/N|YLMjN"ד].s4tzСϏ.g=?R*{hҭ\ӑy芴 "R 8K5ul+[K]l; xmak[ӗSھҹ,z'5ITzv[?IUMR)r0'R9sW7y07~:m⬒9ek(}YA/|zEu䵈KKng) VGA@.I٤H%MS隢ퟩgl55=#Է8 !k#'Rݡ5}eec|w|N+Zl5_l'%68J\e 88k-tuz!κ"'[o!;0Tcj18CSCɛA٫^ lž`_%lea-!;؛t@ѬYCn'&4_Zuf|^MUm 6aŭ=y@IQlo[vvwɒQrYxO(f9>bx&@ET0 QHs9.s g{zzRwxdwnnUo?>zy#>@JxX݆X +͓X]c *N&0g# ]z=0&О[ U+c9o{U=O# 'o@fztJDd8޸@V4Y) ~5 жEst);Ǧ`beq6~YlBѩT> K$y^*谱W5Em|}lc4>6Ƨ6vEM%a΢.YQwA 82Ȏ(k᱙lx*ª|h+! (\MCK͓A]%GʄP&8k\`DP㳣j2~ : 21y׼ ob ]_D?> - ssI 85Hq6lhYP"c#pՊ2(TH+T)PQ XpKZʽy;oesc{-@h\؞~1Αhl$( 8kYD0GLl[z[a2>X UK[a2>\ ;s 8g Pu/(Κ"gq>ok>v>>t)EOZDq,9spcH:Aq6$YP3l o pBM pL00ǀ h-Bq֢Y!@q62 Y;x6Bl }.o?#F(3b=}l @h9\s|ɞ @q48Pp(Ǝy|_ 8q{Ha.ĭǀ|b"fɱ#*: %PhDPyK$@$@$@$@$@$@$@$@qc *ζ\LbII4Y/Hj|HI9ɛ Dg @qN $@AAY @Ph6C$" PuA=g9>H@7Nb!␉~;l<K8k)w 0  (g9b٘v?;O!ǸiXZt(I񉨚߾: 3.]z{8k?J cijH Pigc< 8o JvDN%cXrt~)PiwΡ@kO8km: 0 &M,GFL8gI1xcW:#k݇;#ƅY+_e_8O,ul,y}%` |$ g#AmXY˺&eˆ_=zO?'~t]yS0e{ZJh[Z|tYxc,JoF5koҹ_o[Y~Z\Z7)n0#U ޯnz>\?Q3~ٳ%sV7[]sq[Udr'$cD>h8;3+Q3~3x(;Ud"itȍO?˿ 75 S ?)Zk53 %R`iZz/Uc`vS;'1Om/qC:xu7asպW9sh#ZQR|vqӆ 6]ie,:GO)b$Ve]zL5K6Bzkj+'XM78`:nG0j,9)8N}<>jgU[իy^q~(:;U*g QqV!J5F<%0* =VvqHn3nTq5wJ}䐟_}1*ބi571 kh76\7AB5G>lӷzw<]"nJ*VqwF^ k5ldNjZ8k'o%ʮǯ7VۮiT:\˗u/f\2OTo$GoЬG5ݳpz>RrY52Wbj.ϲ:`VP\⬴ַZ7=ϟpz네~$szz;g+z#m0hw(Z@b)h37HCB~ZzV}AV/iQ$9`fM&ΝᲘlF^Oqj2fK`8+xDb*_0TWdu}YYAL߷g35qvHVRljl/CRH'뭑zϣ1JBIu%ydkZR%~n"6Uv~#;gH[><^bfP5Cex%?*]MZ ?_qIFcyI>X*W$OHvRnK7égꃊw>j5k{!%{c&g%}ʈ&Ϫ6^,M17lNa%g}W="NkY&@q6Γc1tdG$UuT_!6{Y! ajI"J7LT^L9K~8*>(x؟Y0Vz@$V<\?Ǐ&'6G;{7 $@N 'x}hP2:jgaэ;[`E:xu Poh @Ό%H&@q" Pi$1p+h;l쨚߾: 21y< ~i-%O1F<H? 8`k$CxcCv@W%ܱFs٘r7;K'.fI "(F3*V "o sIIl4m P` jb;{7 $@N 'x} @q66^@` +f?I (Ά/k8w#0D70$  8k' ` 2b٘v?;OqcH xc/$(ƆKb' e'8k<        8k#g8zHHHHHHHH8,8PDz[$@$@$@$@$@$@$@$`gm$>gǖ5 8(ƴy       *QƣMl=IHHHHHHH v P]߳(r Dhg @qn$@$@$@$@$@$@$@$(Ƥi, @ P 5Qg+Z⬭:AcIHHHHHHHlI-FCElH        @ P wr';C$@$@$@$@$@$@$@"@qV&@q6DY Qgy$@q֑neHHHHHHHH(M42\(Ά,%       G?B Pu{9       4v 7&IHHHHHHHP؈i11ͅ'       ?g,L8PW ؑY;z6ِdE$@$@$@$@$@$@$@$@8 0,gOHHHHHHHD⬝E[CNlȑB        (ӜI3^ PhcP ZVL$@$@$@$@$@$@$@"~XX5**9g-s W`ݺ(G3H8'b8tr̉:u{ȟ?)mٲ=lٲphݺ5:wkϞ={SO[nhذ߷zkIHHHHHHH V ̺u-PZVw+JQ863YfPΝ;#>>oRRR"-8 =z 0vXL0O<5kiO8W_}EQ|x m|: d-Q%uQ'8@ݻOm۶xhϟ!C(q|8p z6m%v]vO?'ODJ裏`ضmo .T7߬:t(dG]r,.g;v@޽ѱcGu]Xd ۷e˖UHzV+V`ƍZu+m8p@'^{5ͶwŢdɒ{?1j(%zwI[vVVMN @ cf-!CuQ5'9@}zvͺ;DU*-q~o:tO>Zj)a%)S?7GNFJ*nЀ8ha|Udj Qi B:VcSǏǷ~w܁ŋ*#k%W!xBkɓW__T/]vO?)κ~9{M7A]#Gt,;R ;wϜIII~Ȯ{Gz,~=YEׯիVZ)ՕekVsE'J_(Pf D8~$' -O^|0js)qvֲ(\ KsوxX@3GuvʇD\9۾}{|XveHMMŇ~e믿:ʕ+vH_g]9gY*+ إK ;]}TBSkbŊ*UF:p-@0rcYW h@D{vsz) b8s-Jp,clTE$aV:,X~[圕#Tv~zUŋ/bĉjǬTagLÇ㥗^u]Z9gc?qVm!"KjqaٲejgETIo ֨QCo5ޓ %#ήڳ[@u-.Δ8U`dzٳ;z,s$@$@$@$@$@$@$@Agw={vC 9})͝Ixz>]}"fNZ8kNh       ksVx⬯  3`ك|m޼*e;l虲F       /g9$H g#kmFq6v}Ϟ @,X ,_xs5* g-g8_'&P5Et bg5'|P; \_IΑVeKgPvcyl l{.cۺΰaT?]DIl8fݼ@Ʀ߭kVJmzVI.T)$E W p)Xع/빁#%2Ul0U c⬵Da&>34lY(VH+z%6m8~|?S5cb瀱 J*7#J=5J..2V(Xjx-YϤ8kʙ_3Q m2FLJFgg-Ig#I;626l^RkN ^Y90j_g]sYW] D78,Ak7;6zL(C6e#U M\As $h_uw 9slWtTR~sɅ]upSHM.cű-w=w$lW<]!Oq<_vp@Z?yF|!%!3Dt3c!1LY#}6zNw=xchS6myȵN9C7Lvڨux]+-q^˓1-|mA뢵|w] g_i k^ňy[a?Sȑ}[ހ J׎-IӁ8cEթ0yƕ_I=2(#(5J]r="ߍ(9t:V˗/cƵm9 (]:T lzvypcMi5>S!gSaͱvTl8[! g|/h{XEq60 x}w Q3w]@{ _6Kh4l:<ʿ?d)Uwy;[ 8^.eXsS!)P2.a혵y=z_I-fY׺mBkZKG``bPʼnF[/Ѳ.Iʇ܆-ⳍRu@T Q__c] ʹFcըQV .r{ylk֌òթ^5fωM'wU(zUmhr%Hz\@F'/ TKKU,t,x_7{}s?fpwv(#6܃׎W}i{?~ M܃kT"L+<#9+B _ꝱ9>Z7 %g#4AP87EZ W=rgOCx$;K*w ^1 ThZ9oIUk,{7y r&OVd ;fcFj箍yJ(qwոtsI?۳ ک7.״lF:Foʷݳ08O8߶羃) ȃO3Dn.z[kyOj3nä/5cѪhM_6ҽxժSYn=W~tFx!JBiS1z^gdަu'uhU[u#~_ϟGqgf(32{έj)\J:1Z4۽rCvL^7`+7suJA Mv}g=ۑ"?g#`-ܾYx=]5Ek_:Jծlbҁǎ+2V2ϴn|:G-by󫝵O Z}zɸru(QZp垝~jeVbƵȑŬ-;xllJE6g]} ,dP^g bL3Ћ =x}^{5`SFA=W<.~Aja'MHX-jFesΈĪOHkg͒c9G8 ŋ5#GD*S1yi-FߪQb{Ǔ<%72\;E>xl&p7pr76xsлJ%{2^d}egK6B@hq~Oˏnvzc\v%؅S[ % YH2;NPV9]&wQ,L4ǎ?{wF- j37ޭFm%G6e9oyƟ1cr\M̅W|\q_؅!YSU5_{ x=3zhUS-'^umT=X$ͯ85rf.kdl8c-/;~ oOQMT5U8pTR>+cݕcxkxe;̙K͕'+qVUCC\5462E>g?ɝ掏qՋAbNP^<ӋnXE>_VۆW~ZfMV۪)'jձn=QWO@OqVo |/^Ο#ޜ3C# -}BongCAuؖ@Y8ڗbwY_źUZM'4R띸̳oFd+Gg{!>@{㚽gԊ|n~P+笤$TZu荅`_#ciSջ瓸H,Z9gćFbU {7oZY?S5KA Vd?ˎAyyZ MLABx%|Wkߏ;Nއb,g96<ݾ4՞A!J*V6sHOȒ[׻5|l |{A6#(O:j yJ@v iC} 7c_,:l9nC?r5?dqg btg=Ǥ]LcuJS mVSP.=4Z#W'_,YϏyqhrA'8r_.KbdBRQ.O1wl^ 8NL6$h|$dU>1@I/<={#zw;|n~_UGl1s_n$^fU'ƠgCAuؖYɩ#k;{-j/YO!H4ٵi VUv4ʫ)KSv~֤z|É]]f+ދ>=%bk!OlCV-@S'|w*AN>n8+X}K5Ǎ|M9`Hl?_wrxdOW]?@a+\,_qV(P֝5imR],!%偼ZsvĦ_۞Ejl]_x/͒sVk}xfPx}uG<gŇjݫv翼kGY_[o<]Y?qTb 6. 7be';k~PsB*Ծ,יSκ?G|9"q D0NqvωcX{gEqR9s}vt mzŽh|l! ʍ&e+b/ȝы@^ ge|_qqM>>֦qq3^ k֍vY踨VߜZB+x՘y-nr5gmm <ظ5$8קxxehG.|3jݛ{ύUmB=cPԻH["J@U_x轆Y_S5KA<{=J|\sl;>#^>38+N|1-O]yV!"7T-ᙞ5n)J6T O_<._n U{e+Jly%ʡg۸S " !0 !@ q#jԇaț︓d+b}e*m>ȥsV.v+L򿊐-OUt,Pntt)Byc Ƨ[Υųxuh:8bQ*.;4Ų]0~bEG&Hʞ/ܭ') ?֯Rg9{&.+u Gi |J-fYZ|0c+WI={\@W=Dc?iRoj t\+g:c\FƊߒVCO"GB"*NE몣xy$uǏHNLē ,?zfmY h{m5~ ^V[Uؔ:\31O)3TY.lbo*go-:+g;_^7NRlɵ׽Gy^堝.F!)[fM|n~P+K޶i|{J_O(髎p{jsVѺgX<qV6W:P{ 8k9@YGc'|n0O37_Fjk+rsśTR|f[8kf ל٭D8Y16VdP+夞cV?u^C!g5M0;69iU,l0XlcP`j֫>vڜ fP ڞYۻrr@hP=u qX}|}4THzMq6$-_ ˻(h)Κ@X(Pr#ˠ@+WWDݝ4*Լ88%06>XퟺLt#KFy3c%z`zDq'hdžWY&jc͹`F`豬 P -_ -&@q4:[c+w2)lW*haJ.^lZL iE.]Q(CZe0(ZkLakjc 9#HS( M⬽gEyWb&w93 },y> 9btj.ct=/R me`[6>6'Rh`8 P 'ج{Mq֊^ M\sBj5RGd(whgجb|71Y=1A h,KH8kO9k)Z  (:ș]a|71Y=1A h,Bqc(MAɠv):Ǘ &`        I,FL8gIHHHHHHH (F?6'       %@q6v}ϞTm?9r#K`>QKFsf&"(|ؼ pXE4$mX, P!(ƶ{vmE< 8s|ɞHx؎h= PhuP HVqg# 0f$AͦlIsĖnplSH1MlL֝8kkxsXsp>;ǗIxp+k>ؓY{Vd5'@q6` 03`VO$Alʖ8Gl6mǶH<|8a(ƴmyvA< 8s|ɞHx؎h= PhuP 5x ) 9!U'1cZǿ mA뢵ޯ(\Q@u;d9Rhz5wBYuVz\u38}p\UtTqW|'vE5Wgu m<]:ܾx}-VD7>= Ō4kŎe)k9d(7YJ/ IDATy r&+mVoS:f:ug?n%{HF;Nt3/ƭH fV߮v >]64,|hh$T[vugt܃kp5-a[.~l3XEV qx9C,.s{jwѝҹRݻk=+F |[V\zbŽXZ=w*Ѵ}нlku?`|.;]Jg?eZYos>Kc?ˍe[#otr7\=?X!6YiZxu];nh,VSB'5(|-p#Ғ LmϪ2ַޏ̢O k: # 8~{ۡ&kV,YF_6\Cb2ǶxNk]֋<[Jρo[Ãsԟ ȃO3Cb;{VzyW/PgL}^\E|^B2mV Y9憖xfChޤ ȋO?~K>Ǯѷ(Fr/~gDWQ|e &%]zx`hZ*U , qcK4 j5ƌ}r{71^^._w]88yaTwQz,<lp4:pR>| \]$d ZY6xsлJH- wkb>3~ٳS zu28kf9 D}5=YXp>YF_f2\Pʻպant'.Vy?׺~Qk^Ly^2@h\8KoTE4nsp5n(VTQAq<ٷmBvAdϖImیJypD,= UzAIqOvȟ=7];VE>[Nb<1?WOES"FցUh$+^W U89>;&~ @ZJ9giϛW%xT/T=+w)Ί#/2.5Ri%ΊҶVwX2χ#F_WKɱxcswoOzJI ;&:j yJ`UpDɕsZףQz%}gMzUa=Yӛ'@gf0o̟9N6vM4Uo.,iz}I ZqVvO)^Cf}w)ξR~Ue?{RЛ;Z⬷zsۡEv4j ob ū8kf3|W1mT52V'%q_"Wb2^}?rײh))sD Tr}cϏb3o1VK7w &qϳ~o;d=8GoqVo"4iYY_e1l`9yOk][}yF{K3TڵNӛCn`N1Y_<>pJ,Rд8oL9z5Cf,eZM>2}HW묤pb}mRh1_Ck7kp((nHqz5#;m)κp`jABj|Ck~ ;$f᤼B{G罏b9 `&'6#ߘsRxnj8+9}]ewQXwb'V+/.⪝F^(ΚYYۗ85=GZ8f\.?xN_~rܷ u/䭅sCϵEju4ш'uȆM ShvhP5Q ;gcY*店i|>T#r%$aɑMz fg9_(Z %&IGn=˗_$/Գ)Y1)ʇd|Aųxuh܉) Uy/)%ұ ͖VF  }ٽ-ʕƪT9DP?S}jY)k.PEk(5?݀%m.eZ̈zv}Yس~o;&옍K6TZ[vrTmͱdÏxA>6fL.TW7%nҊẅZ?L2[!iIMS{|12ꔿ1z

    GU7:J7-T8CE2:pDJq6zٲPh)gccp៑`0o%o8%stS.@Z V`rW5YޞQ{lg-`YSX[94$ 0s8Gb1aq5;bgC ًY{C,G0wGٟX&gߍ1BؑǶF@@Flг P  [y˹iϦѱ`G`79crHP FVbWg9Mqci;ͣO,|eFpsHcێ^V @q ^ Q#@q6jp( -G\BH4gX0FpĈc1tv9$(Ά#++v814 Q' p>Dzw#8GP9v$mGf+8k/І85l8Hg#`r.A$`it,#8Gb1Mt:gCؕ@]IIHHHHHHHG|B"Hla)        ,(r@41~vHHHHHHHJlTh8m}       ]gc9$@$@$@$@$@$@$@$@"@q6Zٮ%Ph $1vvE, @Pyk g-A$@$@$@$@$@$@$@1IlLv0, eu")ګHHHHHHHH(i49t(Ά%k"       xl80;$@$@$@$@$@$@$@$`#gm,zgCϔ5 #@q'PgXvHHHHHHHl@ DGlزf        }g9Bb٘v?;O$@$@$@$@$@$@$@Q%@q6x h<m> Pu=}FھN$@$@$@$@$@$@$@$@$RgCٍYy sPu/(Κ"$@$@$@$@$@$@$@$@!!@q6$Y] Ph7 ؟Y= ( @P(N=HIHHHHHHH(w<(Ά"        0E)l,f .`̘1;w.;|A֭,&33'Nq!̙uAݑ?~]كzJ[ot?i ؁Y;x6qnݺذa}]\wuxfk(*1k,<hذ!v O||\sFǎѡCl߾}A=b lܸUVU;Req!##;wȑ#.jժaٳ'ڴi..]k׮Xd ۷e˖U6,X0\m>o"42DT|yv4ie 'ODɒ%qrʪ?FRoNԿCFHHHHHHH P5Y*Θ1}y4j'M+{1TT O>$͛Z]rp*b?#F(VZxGQ~}+W~/\ERhڼys%6mT o._AeO> zRf]qwzJ=5j(OAv8pJ#<1s̐CHHHHHHHBS<~"8+ZGݬ5:l0VH׻["z7{QN~xJWR#Hصkb~EM+;l]6 (6qo}~wxN#ׯիVZ)ؕվkVB$@$@$@$@$@$@$@$`Ag-9>q> ^yTXQ#DDrZT R⩫޽{[;geرcų}kׯ)l]%qVRHٍ+p- @R,ڗT O㏣A\֕sV>@&T RV2ega"JWI_`ӦMJp͞={h<}tE曈SتՎ8?\](Q;L%c> ]rAcǎ)QVEQkӬY3@ ܹsVaYY VvJ% &       '8/ gM7`m۶UPaj|,>>>M$vai PhrXI=y$rʩUv2DqAq3囘vC8jϱ>       8OXIH>رcѣ*̀\v>({HHHHHHH (Ά.<FIHHHHHHHBFlP";8kGf       p#{aYXHHHHHHHH hgF L⬝GIHHHHHHH(>Hg$@$@$@$@$@$@$@$@ P5@> = Phu*ζ\Zf5$}}]q}_DhҏN.sG$Z#A>mpBa%} ⬽EkCLl:[EV aCkي)X5!3>JGT7~.40*ǜHq1dG8k8/Ndp8KS>xps>v]=c׮R=(r82^c >v!C {.Qc}m"@qQdg$~z:ǁC- 59}|o(7@ ppC@PDV<<`UDP~,x. Ȯxz }_r#@-3LtOf{fg]]}~jƃZ{,jͩUR| ]b<>D9{cNU Ss,Vۊw7}gFWh~,nbW,UǶٮvBqf`L< ϭwi~!J}QР%g"Di[â_H{EZ=D_<ǍY9 wտʳ 50߲FTMLQ&o`^8|6yQ/*Ư9:]!5/`lՕ;T3f㕵cEVؚqŢVRil]ꁜ\ug];-L>6/]66{28n7T(UO ?=qZ{sU£nDVr5|o)OFqcrV3s9c˕Ny;Up8zsVk<`,8FM|6Q&'>}5ʥFA#W>Rc3rwVFMW?Q4k=<'56룵vǕ(ϻS?Ȫq8Wo8~^6!6U|'J_jľvr-(+֏8s<;6 d<*ݝϭE):>GzNմ?wî=ﱕXћeJ_] _RKֹc4;>8毢Y7;h\}j8'[rU<otţ?΃rm#_s{GkW\ϧ9l,/ٜ55쪔3+`CnġyJJbq:},|{!x:5u5;S_>N0fXs|;w%2+ٕӐZQ 9̯.H+S|16M_⫽?]:$J`r!xhxcbq\rUzG0x8s Ufh{[wpU"dOe_I&O&\D/t^ m#i,}ggՃ*M%_-B$^9P9;UYO}X= 9tZ%,CQ`k/ϩ8Лb4T#߁ܦIeWl/{F Nim|Pd,}̕dU]Zy\zb%\`U8 TϹchΆ2Y6 ٜ^zhVUZe×MV$ƕ§FOJbE5(~HYəټz]QVZѲ#[pN/O:7eԿ]GY#нjKOk`Oߩ/[2X5gǷ}X׶ S/•b4kѡujUOT՘mR/}iξ>Z-\d<>,n3i=4#N/I}Cvvh,;7U+c͜Ic^Q9+zM?W*J~L82{}E,nY'!y!?]ל_QPfn'ʽ.+FlܦdŜSў-Vkv_[͍Y_FMۦMk'};ќ BfaɥIcgj '_ٽ$f'9DwfP9qV@cݏHu-v/ǘcڝ +'|ԗu5gM2=?COf1::1gtmvY;e}m57Zk|'`U<yߎ~ft_>ؓ՛*N/C>jk_ٽfv8{?P`Vpā9뫿~zjx(X* S;=A?-^o71>oJ| *$oX\|ajoԂ >W+.?l\nf |ŘޑNty߇0A oʷAfZyF@OQc7X:Obs{lHs=£YAݯN7A+XժcS)Y5*~嫧aŚ LN}'%Oe/w6Wq{KݏkgB&<9F,>8&zzqw_|s+AJbB|/IR;txË+CX,[ٯ9+fY- p|tbVݎqmSJLymʾD6ۻD9{EfKe3$Pb/9kWV>w@ Z2`h~0ֶ5ۧ] sV'q2pwu%r;7miI& iGdMU:uv3]P]'Nk5sKAAڊEQFJG7{fLJrn'rjq¸ vkŜyߎ~ft_lBOyս#,mHoB>볟}%bvϙFlH`VpāYwoe̵Ԡ[=H)d8+0ge~l!o^B,hΚV\Y;y]_ٸT\g~_1fs/|f)c١K'B >9cb8uL8j&sL$ZG/1UJW72sV>6˭ɃP0&]`=9\+}'oȪIj,"ywj|a60MY~?@av#NăʘKL@5Oia(/М ,z܃+|B~FĊc|Ƶ%<Gkerb& o653ր} t-)Z v9'Z&`̓rmG^\;9k6ؐl.^Ǖ"u%Oeƕj}Qe z}S 5f;P/;7nV 8dr_[iFzc髤HI,hv Fy}~-\THM".:U+^iώp4g#\J6J%vrh[iqs:nь̎t}m54jPcqhxpKԟVm_ԆXzdʊ?"IcfuӜ-9pecY88QSN vhE#W;5VIEq:5v"@s6dcl`oX8RaME&5ѯ2ЊcٟGvVkNukh4gQElT$N&(=qҜ=au-_xClיGZ uhliМe82vmg^Ш~ͩqkl;"X瑫՚Sc"8jmYx|T9Ur16 ӷ ,JgD&͢QSN vhE#W;5VIEq:5v"@s6dcl`oX8Raiƞӌi/h5gl h:wYIHHHHHHH v М]rvٞ>In$!M zCq 0K3'V 0gD85R9d섂3eҜu;4g]"DVa j3B6e Őah*) 5vX0\ .A] BV6ђ- v =㡸C%b+3_ojK slV2vBAՙ2i:ÝWu ."B0B Q!C2bH04_;,@.O.!B؉P|Tlhɖ@lx;CP\Iѯ75~96tE+;L4gΫ@$%KWW?!!:08zmƜC֠g62%2a_hgڿ _]S>;`a(#qxҷqZ0aXrdmS}L:[@snň]}GQ514s6&Cquvg4k?(.pm8 2ܕu:7gbcnY=Pl*\* PzpƎ04_w{l8^uٜm[!Կ)'( 3*T.][Nū>Q+VL~.o/Gp6?|GvQ'j$^o.)fN~.: ĝ̠F5#7w+8zU1~LM E]70_/ [nٍk9R'eZVqe楞Fy,/{s[0Vr+s7{BB9L$Ml?'._4#e߫olY-[tō:;w:E)Pw޳L:eYt,$6E=Ct!K|'G{j2iZ<q=oj[+)jM_b.THHSQXsH(oCzLdcԀ6`o6g1 Y2VgC7"M+ňwEm/$8bc`wa mGeXFFbM+mYL2g+ar!*ii11O%UglG6&"!4Xz $gx&Vfqd5;UD/v:&u>NrUk̪9=9G~/v/Bj1p0kQ:Xn'=y`{{+ Xzd#ވ'!ɱ_;uqY3t}F..UUZg[ܭƂf=~EEVr+si8IDATR7<jx~vzkqO[|6>K'cܨZ#Ey@ {|Aowj'es9v h5;,oU޻U ޱmY`9k:jSŎ1|$67~Zh1Y=(DVr&F6^=lͮ+kz29)lΫ^ Ʒ}X]ۉ$inHI}Z˲RuѡuXph2geǛF5M^T*/u$טP|u*_M¤A^Q++=g]9 M~Xc/2 9ˍuMvm~_# ߗ(izmW<~sz+ůR$B+y]ԋUF?To0 R~&kCʞRͽf >_UḱJbE=!JnjʓIwcѽjKJJY^-=ӵ?6m9@}|L~2Oxfjbe (uH[Tgkv^RB"ƶ~nH #1^kwy'bп+u?;]YJ] #{Jgkvv[йq %Oe|A^e'dYI cʶ^r*U<6(_]MSjў+bgQaJ;W#옳fit猦ڕܻf5gﻨX>4+6,=?0ƜbCz tԜ_r|ԭ?Zǜ5;+gǵ_I"o.V׶ ۡܨ^ڝs,zx21ʛfy{H_ne㐤>/Fyӓ|ZlvCbZ&z3E1sׂ"欬zm3k|_Z*JR{MlzaX6oNƒ[cl>j{lycH7~f6nLKT$ДyMVsV:_ٻ9 .h ?; V+ bÊ51x[be`#IToġ$&usĠ%p\6eʫ֬4g.2iR׳voƦ{Ԡ_fƐ^y9*yOڲqKԾQbJiѼ|fʦ($~3S}N}!s֌sRTxzqZ945Y1{>9kzCxǐ/ t,j)x J} e|K0{bDϪ8Er쇝_c9NwUnؗ9qn2}OhUW5UXX]F3g+7x̜ڗ[S"GQgi~CjEc!5y0/'֛`]ޜ>tD=QĜTܧk"olŝWHʶw|B9A/dM#?RIDZcc=&5Wd٣GV$fIQf3J@WRdlޥ:gdIbPO,} eOJ(W9w \1=IgT_7$Jw@J>fCMگN7ves,o4 T'uxBJ{/F3,N: >6`rVxjqc; _}?a-Ep:1옳8 {/ꍤ2CoPT[woSbj?ق@ٓ7OŔ3);9,!'{JR׀ss i&uƎ/MƵi?LOXa2rS}\Ʈz_}<3u:Oz&愬IYT~^+?89v}km8bj+p޺^^Ss fxlfY}9Ehyz|.^ӶSlu'WW1o|NY |߿^N}۾G:]VFVַq}͎=n#%{g63 ޗρlb%GH6g#o*롍+Նe@^jS=,#]n0Gh+! {CglmuSjv_?j\|PuJ8]%b vrNq |т5qAMqXs|Zv4d*+3 2/!gE9,^> " jiV_7+gɪnysmjC,=QmM?NIs6zdK @s6hsRlsFM_ci!u CJN(:S&Yg.!@s%BDh5Fp!6!D`cXP 2KPcq "Dh;*jӜ-ْМ O`g``<0K1T\<9)b9#ѯ:džΡh%c'T)3yU9!" #TU"1T,c(CSOa%8 ]p " GiFlIhx3d0 0%*.AϜ[1zSXZHcCP ΔIsK5g]RmVHHHHHHHH Мل М $       (dz#]sOFxY}        9%XGМu;/J$@$@$@$@$@$@$@$, Мix       pYGN9> .=[,ÀHHHHHHHH)4g"뺂YWJ ܪX{|=w@HyM?^U1gߡ.ȃHHHH М2A{hţIHH]sVOC=lm lt[G$@$@$`Y{xt9e9$@$@$@"gsx9톳yC,?Ű|osmPjd$"Ĺ"eFj`p1p8u KF}ЮJC9Vj/O&    МuZ^Q4gϋ fΞ:yӷOhQ>/`ɜM+S˜cޕHgWN Ȝ쀧WLA|j[`M.# =4gQFl ޜ}C~HYəټ?{ޒ9۳ZtLo&ƕ]GY#P+)瞳f+gUaMogbّ-8Wvd   p nQpYG$@$@$@.%7grna~[- 0JmJ9zښQ|u?o|. %VHHH"A$@s6:ueHHH#,s[VL"FkP:jz+:*`@={jO(aMok("   9!X gМu;J$@$@$N2g+JmiX ӛ|ឳNC8wR},leeJ\ٳMU,6f4gH e4g-Hl46 J X\MjkF8uĖ{ Y9ދW{,$o[v/"9,h|3V!~y6 +Мu Sh:E%       9i4gcZ~6HHHHHHH%@sQh:O$@$@$@$@$@$@$@Kljϖ90        pY @s2$@$@$@$@$@$@$@$hƤlF,cHHHHHHHH)4g"뺂YWJ @L9        Мu< 4g]!+A$@$@$@$@$@$@$@1IlLFk욳$G$@$@$@$@$@$@$@$@"@s6X$YND9$@$@$@$@$@$@$@$hFlDhJ MlDʓ @D9%@sy> @hJEQ!#A$@$@$@$@$@$@$@IlDJ`d9$@$@$@$@$@$@$@$@v МKGQ%'C$@$@$@$@$@$@$@ElDUs6ey$@$@$@$@$@$@$@$@$@s1٘Ɠ kmCQIENDB`icingaweb2-module-toplevelview-1.0.0/doc/screenshots/tlv-dark.png000066400000000000000000001226371473125420300251030ustar00rootroot00000000000000PNG  IHDR{@(PLTEDw(.9+\\\DUfD)''-8&,7fw)6<(3;(0:7],BB*9>>k?m:a1^NCt.OGCv3eQ7yZ>i=g9^;c@ApAp0\L4jSkkk5pV6vX9`(/9=hBr6sW2cP0XK-HDCu@n2`O7|[/TJ4nU.LF,@A*;?"@O\`ipIIcAA]{|Sf@EOz0WKeee" A5%6CnnWߴ\p```ذ<&&FMR[fvff{9VVn>if}48CљttRcy8=H$*4x٠Ҙ( FJS~U"V\m]13!%_| {%:iL"f,`yV}~'8YzgdU|#|׬뭴N.Ƭ-1>h OmnUYIrRX{!k)C39KyZ`oO!W6)B=̑:-=e"kq|'*xL==;j%cͅ@ؑ,[t-˶O?m=!퉳#E.= &KMegCo3s|LkM=;2F._g&Wfei|p`oO-rK$&,"*3NRgi|qḧw =>_)Kyov_ ,!)^pc%=Q -ʅOW!=Tya:Vmݗ*RKqC?MVǓB:EEe僘~P/g5?/GɋrFDJǃrp@@AC.OvvuUd%hn[LV_h'׳ww7|Q~Sū׳;7хIeF%diVn/Τu~d>6g(R{C|w6/) TUz{^nb{n)=oWNSZIz7{9c <4BZKqQhĺ=<>DL?D}?X bg!VB k `b,Na3{W:dWnϳ6_ht)ow([FxOgɥ BIMN3l1$LVՏ5 cvViE39=vrOAH>d2PiD7HjUUJ{Q{ϴۛsm-WNJE$CWћH`  F鐔n6L(NX琫h$AӌNGٲaz)]ޞd}?Ӟq>fO{Ƹ`d@15f$a v8υ.m=ʏܫwG6ܶ'„ mhʪ:`kf䬵ǛONwo''b`81g@`>aM%#ٺ=9:rǧz(ذ=c %:a= Dh }OnOYUUUڕ;_hJ{=mW77cgF4euL=t& MkSυBi=Һe<>d|yCh ~!8ǹbŎm{zRc|頻]ޞmv^r{88E5=7==kSӌ(d{f2>| lÈqRdx{z󴌣bLsn=eժCvy{smonO}i{^@z/kyW{22`==?$X BUUݱjPpugX0PhZP}^= [zܞ-ߞXp6`=@|=75 mtmO9qkcWS>Zzs+Åf LsL=XU mC "Lg"9fzn/$bXU Y{t @8aoOO öA߀Vgu phfMhBEJMqNw;"ޞjBb^h.dwR]W37" zJ#}楘LdwfV w!"sl]W4A\3z$ ~}\1{q{ = q@{<0=y`p{?;Ϣ6qoCrO ܐ 1$ɡ"rfsH \2;XjXK|5?d0?cn1yc7j{Nuq^UH*~ 1؏cV&;v0kϰ*O1K{z֔<O[!`NƦI'^0mߞ%en0wiO!Ux^|:}9p>^ qgnG!jn$ 1K{Jk?nϣvL^b;.II¤'BWoKH 3>PJrѰ^s,j} >V4ZTE7=۵˵;G0;GN'$Iy63#RR\KC<\"2&.=QrH>DhdkayoLߒgqAZw`1'3}/R<٤fINsD5k.B ʹG!:"U'H; (o=]2QMeb_yPԼı e,ǦYH4[= :Ma!cd{JT?y2bMoG&OۣbF)'-5%.pgQ4DIik=d#ٳ(ם=PLJѻ))ܹ|0ݞqpOz-=ɶ͓pvW i{tpib A5;:hY{4:I2-ikY{V#@!W\B!JP1؍\8[Gt}#léQGC<2Y{ "# EqӾ!e)Hfn ow#M"(=cl5[3ֳrNJfZPUY{F(av.V$|\{ٞq"Hn9F%1cQ[=XQ 0*z3d!ke'[&9Q#lϱp}_Rrat@GFŕMLyc/%:hbBy==v3t aޮlB) 5nU[#5sF7osr1Pya=ݲ1'v&$8<v]z((҃DFAE#%ubuf[*A=Y ]CRqeQP37 &șye}\=˭C{ڃx.p= oOrf*h25l$KFB&#sƃR>b/b9`R.BԤ0cUiC2~4$ў&G{?6?~>l3&B6tfZ-ҚĈ/dދ8Q[YK7^3D0#GDs!Q)("l1KT+% +kk'G{)l%c(aFe$UD3x?dYDbEXDQE$rigҞɖI1UuޞᖯL{34מ/}}_Yy^]YYI;cǯ8`,M9An!7ܬY՞t6R5MEi>=qj,YdEk{&eʴusӞhQܞ[t*J{/=O7V'Sե۔g\47=m~k@榷B8ڞ =B%ooϻ^Ғo{Ǟru{71Tkǘ=_ vԼ3_, 9gql{ C{m<}G%k{W7ӧ;֞tQJW*~778gu<ԞR&ϵgGƷgn}Tl:cmϽshO\pͱ=uܬDc{@on06 qcҝ>[ѝғ՞/ӳnOP, 쟯^:?=ؖ=Y3ړ9k3=?.3IOV{%IG^cy7=ݓxbdG{ޡ=ؖ=+?gX6R3s#ޱ7=k{qf~ϯNXon7r|^ZoMnb=kƤ="56bxƿ`@444-R\Ƙ~ؑ.~1Zv|RTDvgLuK-iO1c̳ј yV{p(#00+i_%6 ի|FEdjHdhͶjP G%}jF)rC*/k/өo Ufw]/;]~OҞ=*S H 0:;% % jD4=3,=5=)Z4Rq{Dx'^PcaܞL#j=-=c*~B\!l_љOVy+"{*dָ[Wlq3iOd*m*JܞxC{ ۜT-F]oXzG&iMHϹE㳸=d7~k6C{r9`=03=+}im"80M>rًo`/! $]CBrCn>@U| j[A|h2۩zӎ$/3lVs`e@{w`C{w@ɓ"[{WnSbow,ł}s}vP1L(g!EkkpFh^{D5]GRw]w+?SNČOR?9/\65ٜ!vb0/Њ>'ң:?'YՃYOƦQoɽZF04H얆rԐ܇4ΗE&gJڌ9nvz9=el˙j^TQ)0ڳ_hCnhQz4Z!Ul:0D='LM k|\L^մdp땶=t@Ӟ#V2\N7Kl*r2B%[ihO4U/m\99d.9i7=7֗w\.-m']{?kC?DS'ۓ>^ybv{ sZ*>m)3V=U0ǏNlϣBH4푞ti]ii#=-( W,a&J0vC)ݣOgXgc0G=ᘶ=[֛ ڞkAAs&i= xƓqI83s[{Nq{;s'Ksry/n7=,X§'g 3c֟߹I^(Qӣ=~RmO4=;70={Ġ=؞z\*moϔ=,*SڣGm{hۓ5H6y4==k=L8[K6Pػ8DgXz=LlBi`Dr*E>AA|.MM9d=2|$f~yU믹|vg=WWn۟g4>9gLw޾k=DD'--Z.R=DDlOșV!"D43[=DDC8CY=DD;8YLJ!":=Ut_FrQ%D)l6;1c!"l{O"m{&@b9T ڳzZ=DDmϽDDڃ'mk6|ú=M`_ZwPNgڳx=DD՗iOEnHکJ{oDjZǽWnDz]slϸ 2[zi%pBm-@0Nhk`6jσ!"L{u{&p|-=N" c>"L@/g~T(uȴGY"aoOxړb|c?ǠukeST+r~'~[trA*"o=?6{\o[IQ#a{N`nJS)=\8")5ņ?:Vۃeصg01;#,ςa{znJS)=n&r9,Q9Y+N1o=G=7k)X{=?;F0a3IsmKI4mz(hI >AOOʊ0ja]1l"I'$'hf?~sLα&礱gI$YެSgQ&:ɌyAI3>tgO[ dw lf@Lvέ#֛wث_pD.՛wث߸zJ7^}y9u99I׎iDe@,a=ۺ `VX(/xY(o}yXo>{<9؍:^곧ϓXϴ~!wZw?i/:msRkJUU=GszN؉yQ bDl";@JFBNmU8y3="Uy-T!70{deO2_;*6t"!f 0 5fd>{Q=[=G7>Yٓ`TSgA<;71Dl}(ƞC —۩ԗ |n' |seZ^>w)AiAx'==2ٜa=%jǞlkO|ڦ}s/Daonlܓ O?s  {}3ӟsJJS(2bcRfR5ϔ|9Rʞ}pR |T\K(y:{Uh3eZ2ml9;ъÜgQ=XXǙ[:_yjYV&``\ bg,rgfb6@xKv9<4Q>0JGkjh8j  sȠ<-cs8!*һ`%Fl$Qt|̞$=6o?3GeKo|/RW~ž9]t=R?ȜU6`g,ny FhQ[ch=30 SX캞@1}$vUU9M w-n!6a7= Ϩ!Y`{._cA]vpe0tcq9BVK ɭa6Ŝoںl hfkݸ+hlROحj?_c(^c7,¨aB3Erp'A“f=bp*IVrJ)rR>Egѥsn-A!{jG?l.`Ogsnrk\^~j˫6#:Z6b׍資`@B\bSAHdTtR;cυ;a3wTn0'0ƕavFp,aU `Hm#y |1}? H!ˆ6Mr#n|V97*1LhLkؘsC=Fun]Y,i"90b$b ;xU=={;_{$~F r~b{&'snJga`l`"_b^zt;ŋŮ#g=i6r}! RKi:{p5Z>xbG^xy3aTl"Xk8aL$ f]ZVQVg_x+`f_K65M~ˌ!?[ʲ`` E@m~Fʞ ~8%k2Vʨ5;!C6'X=Ny@UEef?w=8){=cC&nrsF}F?0艗-[w /n$PD= v`dYhfO=|WnR?R@{=/{0d,x6أ(žQ\=3CAMtN؃.=qf߸p*Ξ MԲj(Kk{<ؔ=>3jž2ZXس 28){PEC\Ǟl-`v'FE9k׮ z:d.cB6Ǟ ^7BAy01h=b$yΑs{s= ey,HYcŸ|9K5GWyϤ[{XS*Ξ!ZVWWx3;Փz#5Sg0A=kllL͛cjġ'N~Zc‚<qVm= ZR(aٓ.JW d!w րN}FaPo,F-kצ=TpS?{$~FLIC[HTղ$b9Z }D"L=?#{`aCrd6(nI7id}[h7%;Zdxqk1HCaN2/ULYZ쳇 ֖~^c؄7Yg4xfvьY^Yr pS3wxa.浂m::wd;k]^kk8`L.rPs {x(d=b,GdBB5Fg$l|l"wP~c-Lz{;id}o'0b]T| #_2/9Zko9I_{rs?7{gp %h}@|$zIc7/@؞`%؛w*=5c=|S{zayb̔o~]a=WjDy牙3Snx<3f|>+W=aI4 3f,'0[=müL)=G4at=n+{g?)Ǟ~7=ܳkJ%6Gatϗ=;Fq8>|5B \ Q1q>vgi~!x!Z=+*;'{XӘ3gwЊQ{jcHCcCc]0 gjLﰛޡ,՞ٞC j}ZyX- i4]MRbgjLﰛޡ,UQ1C!d=ОaTYW7 8W]PӨ=Bё~_{.^ aƎQLӧ-(r# -~ &0AˍqDwÉݬE hϪ|lm 8eBʬe^M &0Aˍqlb>0ݺģ=28wT7@ Mz?`p2L윻 @DcR(H*Eyuݍ3wi0{1$$DI!q{eYp8|hCt$ސAt?NMbH^N1N=="-BNͭ"('9cFivӤ$QsseݘsذK"e&$asseݘsؐ@G=]mll I(ÌMr&oƆ=^%fAeJ}鷱cOgo',@h\f-> ǘq&PxuA^6I/sm)`i`A0mФK֑UdaN|)}YS#ΙW*@k@z*$!;"D_{ i 4 {|>~j|0=_y =&ц=^%fAegp&P|=wx|x3{*Ya,jq0kXJ0%nlhzp.{z1w3HҴpAi* Y2~`6#"Ú=Љ']zqYᘒ6{><nSt = =qmUkT~Mi=_}Vgn;/ŶÞ2 QjA$`OGns@.z1o( zeOK1Qhu'WMstȞ-TP"Zшt=5˞ĪQa 7\/Vze~=N \wzŷwøq @r\ؠc|q^?{v`OX]ķ٣ nNcPJ؍:F 31ΞVr6j%S-qƞ=ڔI<(5c߾gJZb+h^6p=cϫ}qW&06#ڬ`Ae~0Ď{gJ@{4|הJGQEɎ ⛤˧?˞INS8tEjv߳n˞}1gҟ@ן<}as:#!T+@_{X (KoJ2a[@^p`{9 9~2b:{kWٓ#B\Ǟ*-Qd%<YIuh.( >'&gw'MY'I$ M21ݣ䓺'Uu IB$y@8PnȄ8?bc@*Idb(2alj3SZ$JdQ0WlIGօATFH@'pLlf|1 <mvLIN E&rǘh=;$$ 7ɉ=[q&C'eMrb(2uTd\Ճq&C'eMrb(2uOz+5 < Zc_{twU=&C'eMrb(2uOp_^=rj>kYO47{=LNdʄPdzeDkh\2{~9Œ{zt! ?g{D"ȋ{ FxvOA=bуSs֛{f1U`"ԜT֟{K#H$<螂ٶ?I{6M=a +XcX~[SG"H=J{pHs+]B4Y['x7Ŵ:ԠWs=" ^Hþ;cUa( :=| %C!{6@p )oZ$\-(-4s~'Pq5-}OXˆvt>/4u"j$9k'dj.^aHUkGƖrGJ*fiߣ#2!޹=o%d!߃A ,I1ڰx:ƕ~S'N4GywC~G\=Q.4wgu كT$*{zoP '=IApaP1{I2{(IApaPk2J)aV e9lb8x(FOģGckP>.Gos"HbmM;tWhIFRA: qVċfH+/cMՊĩN4IzeZtiTxUw3I{26SsպpTԧ6W8=iV|aE%y@TP +WuVFdk,E3%܅Nr@[}sdDew"y@P^[=9;tOf[&/UYS҉ y=ӻc +2)w`{8Y6ɨP( ^b|sѣ{3m*ݳzn6s"Ys CB5ӌDm}@@S;HF`@c[{VdJ:Hs.e_Z5- Nc +2Gx*}sćCO3wr_}K=M)/dds&%rs.z.މF"]gh >b{n){커Y">YSjORfVtR">[lfSǔsP.$IF3@aoasO};h$#swNrGL{3g략?(fdeYNJSRhٝkX9{粛6ͦj<p1bKlQ8PnJY%]GekL r6iX{L C *+ ߷y붵5UYEQ* ]$&#.'j 3i/MP9 Ɇy ΁=ya#Ȁ"h#\:JC  @ٍ-xz{;:G=XA[Za ͗_OG=TE5o[ӑ;A۰;pB{0fvsʺFsrvm<]Dfn,DNS/z]%ɠQt1hʂjIrR7%i؞xt +)ԞԶs.%󢸶t1%ukO Ɇ h> ly ^j~OyAO$$ºjt]ڢ?J>rh;ZCXsYЛ̳{~'/xJ']o!ȅu>!1YTqBLrlP{B߱4䂄eG yn' Ԟ=TB.HXvTl/Ԟ7#1_3!ŐTB$\0R=yaU( })F`مEԆ Ldf&([^Ch JI:|#|pX%Aa#gI`P؈YRa6{@X~6ŭɪ͛w.$}wʒӹn+=l[v UӹwN[E1Ba6&s|;2<^^CQ8>oNZ'ݏ1@Xyޔi}5+7s߿|}sǨBQߔ۰bX >4E`,|b y! 8o{\~5Ҙi$=vn42i6?=ٞXtvoڞNʸ ݓݶ,j=}q=Vz g渑iOdNJ u3e~8ѵ= /3Av2APmO;ըXܶt,/2,|$珢,__r=^0 @Uda؂ 5 07-w ZʻZ Xs=VG{}7&XeFK\~ۀ7x&Hg^ (nv hakT :!߻Wې>jQae>0 c"Vh+1 U. Y@z==j]$N}Ùg4'&hϊqkinbPvbh)OUb\(\Ȯޞ_~Dgx=ɚe^Ubnէ'%HC{㯑-gԃ 30.uZaJKۑjTRV>PUcDXl1u*?sՕvGf:C !3~Z_:8xǑLp8:ݞ۾Vg;ٕH]UGg gnZxGHk%)R9=CMg .kż=naZV,zX#fm|t=5CS5]/97h?ִ6=[J{`99%,+Yd{ޟoMv=^3GbUWoh~k*q,`dǕ LfQX.'dcn][ JQ=3B+{ܟH0f =EQwsOkiEV|@p6Gp+]i i_4R6zm+4\s@Z=EQܞ{ߝڢ؃$C:mXnxnp{0)DzŤ0},lx bIPEQ3{JZ^ S{afF78t`+K=f;Pv>%rqf.arsqpnO]->TjX3ٓ#q'~;NG=%=2ov@F= n+NI X8gH8C%P=ԞlԻO{roa5dsgOp[=tNZ™=w`= Y`9DiOjjd=)t4)9^쉺)F=wH,ٓkvt}+[e Wa41Ӭydi"|F=wH,#nG8r[f R0<20;B]RԽIVy =ǝTW{~ػF8! mf2{b7$jV Z }YQAGy*В< }>؂ߙ11v]qΗ%3n;9933lg KcN͞Of\cnOq=̞HОANZn-վiݥ{aEߖ՞ `ۓSОj9h|zTgivw.q!]6ƺg> rKC{:Wݡi~ӵ޴IiMZ|=.pŐeJ^r0Y7GONK?~L@—ࢬI%c|ӶÆ݇[''k2sفE-BlWTاBLX^13Ji\LϘGR@Qzk}|B[jw׎l%yَq|YpR/-s* th>c>gN;,I=q\^0/FE># JE\7m٩X fOU1}3_YMeqhj|=ק=W۳Xqym4nWc׷98=oH #{HˆXsО]qfO d L&*TTxIr*`dq1?}I>1K챗mocm>nxhF.{H1ĞcN0cc|bОWEo?QԞIo#\o%-7u caD{fj%Ŕ{z5OhObaAU &1OL)d9 A1ڔ քbrc1! xf+"[{7S6"ب4{e2}N+rF錍]\ Cm: 9}=p֒J@*j2̑C {T|a`H^.Q'h?%] ~niCF{qyUSGMV:F'bASQ{BYVmnW ][h)P'=~&̊8JP,=qhO ~AjGDV{ (^(/8˜[5ls|#&[C0%\2 [4P'fęB9Ucς/i:,{N;A{pq~!9=x["Y47I= ¬0hjwDᏆ Ld'Ǹ lC}~WA{0aEbOH ̞9v{b(j8ޞD $SKl67$ZɞcD{] ӫ̼y@'Kލ l 0\OU_?!xvҁ58 =*#e}J8`Oa0nسı7y2}dxQD`KNq~U9m=UwFj< tџ?זC^o@6ت1s ۾W2S>! FCo _[3x,U  hfh OJ4bȇRv{&h7?s 85sU)c*=D5b%jͻ̥<h͡6t*1Q`9bf<wYXqherv.[g9=n:73s\Aז.4A'P3 #tE{p\#Gz}hFMN1&fo_bDf(pl"#%Rnj\{p -0fNW*8+ԫ4?M=݃7/Hpmy\^:3]cq@5gܴĞ~ \2K=EfO>4ųt wDAohw}B,ngDz@!*dft)3sWB͞נO=Q} >G!{IഢVSMԹKN:B%xjGu !AijX3ȫĞ@&70})nv1Џf'$Ϲ"N64kVU x{12u@4{=Vp!1jQW疪 sK>5ۓÐ`CО[=K'}Ofϐիic)N|OWlkJ_:+BxfBH#PB͞:+Bx/}*,PgD54{Kߦ 4%; b 8yLs23 $lf`SBfyĵM T{J,4Vܳ隁 rO ׊{6]30RAB)!<@ZqϦkF*H=%dgH\+tH Lk= !Yi qg5#$23 $lf`{7{RK]T.JiO#yU@Ys3@Җ b%~?=YrvX洇d, J斴PhtL(8 Jk#S_jrTa}q dکT֞:ifԾC{^|aYSP3M`/S*M ']"6ջ-K ']kO,*d쬖w2Βv^:X(8 UN1kۓXT'4 ڣ #`g.cPG!eu j` % L2KU -IfT2jBHeUGݞKt֞P,GX{<ޞ Wb t{w3-֞*Be>D 6` 䜂mW5h8y:N]ŽO{S;% NCuܼޞ"={7aE`pQ{HZ+$Si s%lOlZprYM$3Rڽ7hO*`x{3X{shOY@`֞Ӟcsj{]')yq-L)g[NzHgx{/$D9L(,5IiϘcH]~=|\ @mjCPvg{*^kV)΂[b&N{p< l{ʜnN{"0Jb=9 | ^Nhv{Zh!? 8TZj%n'SXhh4zr1z"-GjiX{h8Rky:sSܡ݃8{oAΠD:Aͬ|Os$7ޞp'G: bH9lOsy}q ؠc{pmz_oݱ A@ />5Seٞ23Mٞ23Bٞ23MccT}lO89: 婝$G`myjg{*h[ٞJ2pږv 婝$G`myjg{*h[ٞJ2pږv 婝$G`myjg{*h[ٞJ2pږvl؞ÛGm0^{QE$ʅM 8 ؕː"ܺ r.xwA&Bw H38=8=8&FC{hC{hԆwC(.̉"@e5'ؗ']lpiI5tDZҞ+pij@iI5x?§$\fr뵌u(r$kO{T#iyKqn=\@u$Jqa`)\mOTwdNgT`3TJ}6ljҦ'ci>d4t={Oá?@F36x-/s#2ԡXƾkC7 RTJM7c|Ն5ҏE=ҹ{vP%5G/vcn8jA{em[מJ>@n|Ruo,1~_;YyS diyrr@U8/RSdfc{-h. ۉo<7,@>=g w8E3>[ @h\=/DVTi4ԁX:nTjŁnyD2CBH Œ4YBIpAG.#O"e~=F>n*ғ9qBH{M[@mJ5MCFX5v%ﷱ? q@'/{nÑT*u6Yeoчӏ{nW{G>F]G.yR+?Þ}{d^rZi zS]}@&ݷi6Ȇh[xl ô`&K`_@deמɔj)Vg\-貺٦={*G{sy#-ӗT|ibAä*,1id% 1>1Yyk<Ԗ϶,]w:R_zC= l$MEI>9I:,jeOPs6 Htj)䓙/SS\iM}k;  KE: yܵ9[k밇'{K_}dc"'F8j.\<6밇 d PM@VTҹw%nD|8Tc/G{wy80yWK4xh`7 Av0H۩]ۉ><}-hҼ_Q:X=7IKQ_6T ^[ R`}+:=,pa H1h=CgϵƵ*z<-x`a"IE+d莇l屑]=k(@}QQJW;aO.O R|Gj8;$ @_>7U6TŸ{dU}z׳gX{$s빿u?i!Wsеc %g,ފytjBP{_8(ă}ϐ}{޼`ϳgOr~0ܦ' Zll!p^0K3{BS~ǏH=[$=dgI*1-L޳.>=7&^= ՞_Q1KYqHLR4H!̚k@@ ackPU1{MH={ޜ\aϟ=gU`<cޭ=gk /A%b-gGhϵ-n{t'SIwњf=+met ï(zI[{XJNMiR.Zoʝ}>1X~dRmrE 8~ҳGg6GynEpte53[=EhJb'S==IQ::!n4g ͳg6\Ϸ澰goo>W"'waޓ+C8QZ_}ƭ=,EV T`}WԤHP ֠igLۉ;GO~R4ZZ kN͗\{ofyvctVZa o-`,-1(Ɲ"Y߶yG{8;I-ȼjh 2qg1 H9Z4-rLMUQXy ϖ8FkTdg6 32Ll4Z`K13.}I0&C7^,:}~HK7`OР3{.CjFOeQgqNjW}]]>xT|zgKdŎ[Qj,Wd+o=2L{i&FjgERE~ǞgKҲR=tZMd6btUD>${rbԔ iU: !mOB)_$8[7!u&vPDi. nug6m:6\Zq7>/m͓hHoa IJ04dEDFRr%ւV"~_3O.<~}^gus2s=~'ƺ-l=ӽ;]Xq/ryY_[~7Y`mh2Şgt,y u]X3Ʈ48K2KW50fW%dv( Ӫ[9K;ʝ= hTأqiA=]_1MjwCΥvأI'#O{dOpk3xJɘƲ(.1bOLOƔ33 d,!=dL=,.1bOLOƔ33 d,!=dL=_@ ꔐR*Gqo !Lꞓo !Lꞓo !Lꞓo !Lꞓo !Lꞓo !Lꞓo !Lꞓo !Lꞓo=?7@mLYe":bnpXmL|N='V T"%$ژzND:=KI`1e9X1Pt{jcs9bT,'Ɣsb@%ҩYN)ϩĊJSݳVS6SωHg;8jV׏88MbXy?6@@P+$4H + e(vrЙ2q!g^|wOnlG/&94z"+,"ȞO߮O?$(diHi4EVX%FSdϾO>zt>&(efܥ롯iJ[SdϞO;j{|E8ܷ͌u=u=MAIwjVS}Ѻ-/}E8ܷ͌u=u=MAIwjVɍf1p*eP/z(X MB\l 3Csqg:ݏ< u8kFwrYYzZ$@%]?}ަ?bϲAIU*G〓=U{gO|>_ȞԽi PNȞcOa Ş7^K?y]H (_\p{&~=0{zaOjvy==='?>o^fs~ `N d Tv'Cb*UyvV.ʀ2E)L /13gMiGv_89;{ٴ}v,i4K P~mJdJ석*{ wk\}WjC6o~{b*Tij _T_h/}'?r 5iGnSBhA qڜnha5.&m~Ȟdձd͍ {$4Ddfc?AY 5-Kg}v^mMAq =:i˞ P;9t,inq  NZru?eK ~?{vnvIo'P$w-f{O.D7:)"TYbÏ%Y97OE #ǟ zzrݝ1oNȞ{f2ȨsN-8+`N*!q`(a0K%B"tMyi&˞,ءg(D>]A#Y"#zJn315\9$Jj =F_J*Z1䏛{^=bN Ke+{8zbO/iJH=eHRnvXx"{rmVYgf?"{hg߼ªUaܺ,"s-=ϟ,{S^}*zw_, $~nE@RMݞyCkuXHb>n< L#30D=K1N= I۳< L#30D=K1N= I۳< L#30D=K1N= I۳< L#30D=K1N= I۳< L#30D=K1N= I۳< L#30D=K1N= I1nOUUMku{#C^UUرJpq>J!u@:u 8(Pq:wr*8hL_/Ѓpz@C{s8"`4iG`8cE{C{0VAZDD{.ڳ:۳s}Xz_F-N`{F.lmW{nҝ~)LQ#NYl{>7 e^\K2w.'NAW{f6Ssy19܎ 1<[<=٫Vff^vXa(8g:&^)ꭵVRߨ=101+>$&ni|I{6% hF>w\= 6ihrU9*WG'@Df%$`S{ne{_;c{>v=o{~o aOYÞ=n'aϞP7{ؓyVgOz=<+{س'=d=ٓf{2Iu=ge{Þ̳={CaOYÞ=n'aϞP7{ؓyVgOz=<+{س'=d=ٓf{2Iu=ge{Þ̳ν$qlؕr)WfP@&q 7>o㾐I7l$$ӜvLzͿͿdCs{מp;'UžÉ^۳誾s {|pb>=3u6& {|pb>=>*}ׄ=JسA uNV 8ܟco55tF-@ߵ^cE-R Ǟ=`X>{MV_rn3SNoi۞eڲ=4$܊|y,|eYRwh=S-vOy+-!{z칫A!F)nY̞#,r[n{BR8SQRc(xd3D^io\x ܒ }1t\SN̞:Z6uFn:Ϲ9zdIfmODv= "ǀpSns9O'@ݞ +{0ZD֞e.]H8${tŘKVsAUڸe̞e֯=ṱyؓ|7F.$nԅ=lO aʞ^D"R*ǹE9+No4{= jctej!c} cOAk 7=tPI E%v;.p*^Jqryznc̩cGk{Z$;$o")E^rsjdGM'{P;8@Ly! c$sFiGSO]<η=S}_+Ǟ_x,vd,ްg4Zƞ7E s_릀<)c'sP /sgS{ ߿'ߏKPmA#,⑳lG>ptǞZ0=o4~B>sA/LlaԱ~iM\+{K-{*Y8=|NGAK,gO*I#쉎drWS-s0XXnth_\5ɱPHxّ9pnKҳ~ =.{=˩1m4q_e vx;yўt=_']喝9| {gحW~ľ<6oet͹=s|pb>erۛsdm &$/\1 0 AOBHb>i*hϞӃhϞӃhϞӃhϞӃ|4j$Z/&hx@A{ P=R:[7æ>Y3dæ7큣h#hE{A{طcG(|WG iRebPlE)+۩ʃ-!NwWZsE#XEYP{D,="Va{Q{D4DGnn2 jUA>xMۓ&%!_{@d7njq}CG{z <8P{jn2NIfOYLzѐGnjaў(de  a sEI~yvLĩAvSk=@)!bxd8L%]{*ƻ]A֞e=QB"jb듌kxKtoO}]{^xUjt-xz HX|'{ t'ˢ qV|{O{ g_gS2ޞ7Yt0Jo#12ryCn b\(pÉ~IIuq=2SmO+ ڃM`¢U{jC%hԁNBK2̡F6ɈL=) b3$ӬZXJYa{Dl,̰="6(@˯!pڸc^6s{iDkN==E{8A{ p@( Qh'T{>s~ԋxļ_whϦJ+j;NW|P|z{_Q){褑z+ͦ^5BȘChMc}L} OG[ ԂHarxV=B֐{h5*i/x[Iv!z82'&$OpѡJ̿Q8P֦3 Mܚڵǽm@lvX%~Ksa5i37{Laōϱ.)Vm0[%{.e@e왴H !Кd(@B3 -q{zTHl @:س0pIxStD x !/F:ǃ=,Ws'߼ϨSR<wsK٣K֕ya;;>_s65;HnZ)yPP8B ]6ϒi73Қx ycO%| UPLWVeApn_~J3z6)S!=' ,|P«BV۱g,yX,s5;>_x3$I !eUs mfo9{=/O'ӇG>)T[gP{gJ:Nb \CgD׭;'I/vn7Q `RE\C4 A&j›>AߦO[nqAd<9'?I+sb(&bvw̙=޽o⊰/ ,/k,_{?h`B%,,A(~j;{xAG:({&D2S{x3nؓm=3[=30"'fM 9eP FAVy߳!#9}+j nS=⊰/>0QLǒa7a o;_dO}O=\3t9fmÛ9ǓC=;.9n*Ӟ;#GtI\vk\Hד:&|쁿!1Pf\;i@kϥ"1G٣UD^=Pm=AێWكU_;lωT=gX#:𚈲g90Ps7sjC{2ggN{I@=fN'%)֞mRPr1V(̞sك mC'QUbEs){^Z֞n=3hBSVf9#ka#i;TڛW *Kv99E6T8ЖъrdϨ)=[bofmdO&R2LO{'oؓm=3[F/ǞTSGN'O4PP9DZ{{Z$r'Op{*+e쁽 /L|Vŭ=Ubd+=vƕ*9jV>uIx~E3' h^@Wh|Y xͭCj|~flvzQ6c҄ӣD]7TB*{> V/Ղ>_2AX9 9#d^G* 5 ,9]Qk_}nҞϯy8FPAkj 1EQ+qΣ6/5(5_7|k{'Zyg~GiWڭ"Uڃomo` ) ,?Ϟ+'h{=[b{fgس?Ϟ+'h{=[b{fgس?Ϟ+'h{=[b{fgس?Ϟ+'h{=[b{fgس?Ϟ+'h{=[:8 [ BkD{gYSמhϢ/=ўEgiOiO_^{&ڣ=ҞҞLG{==-yh,:K{J{Z3Ytg=ڳ,)ikD{gYSמhϢ/=86UO88yylhx@{ عcݴ0 o,%7gaHLHM$b  lHL^N(u"bGpHc%hB{q p=|!.(E{h(G{=Jڃ*=96g@Vwv۽<=&_r=Ab@֞۳c{eg7H@#mYtzej@Ԟm 3߇Qm(md΢XN9I3h p[Cy OGQ  ߞx+=.Q2iKOl1w~oD nD/U8g%mlnjk%~{Bmi-We3h_՞͏T9{RO~udg&sټhO[-V{wԞIWl@/ѶD{{̼z5hV{z6)oϓ=/뮴5 sXm =_=٨{oO1c-6=p[S{y֞U[m(=CMS3=5_w_a.mJ{:ړ6MH[{PQWM(^O~+]FGz8m&u<_ yn%jmIwhdMN߯loBs &Nӓi7"}1#9֞\ YGڃ=yA{s0ǩCqTf#5n\7ϙ7fs~q犸q|μ1ӞHE2F b0f?'Pԛt5۞"apEB}mO0l{F">궧}a=#\PFuS>0۞HO)qfmW$ԧQ3̶g+Өn{`܇f3 iT=E0 ኄ4۞"apEB}mO0l{F">궧}a=#\PFuS>0۞HO)qfmW$ԧQ3̶g+Өn{`܇f3 iT=E0 ኄ4۞"apEB}moyq=m}%=oq_?e"חm؇zl_?uWΙ&DQ<00DaF~H^IﲻSJ|?R?kޭwrŞq*9<, @wndJhӜ=gnQΞhbo)xÞ/q 鲞籇Y^P_"Lm`Zi?Їڬmܮ=(;qjt؀a.at |`/\SYboʽ z1RX춓#eRMӂ,=q^%VKJ|&|`3B,bh*1afU7Kd.U'J\W TOꕢjO'*3YTXxۢ4](3z8ح滋a.V7I ֜a E 'c6pո k35dϥr=3N4C{1R,v0"MV)'O+FaO0٪앲q+aESmuMDUWglוhL['] s4SwnG'|OL%kD#ꔓy'虦Y) *!Zߝ%r칫m*Sz+}x {~緔fVC*GL?OgII=?׍&gO,쁜=hd05-~RXٓٓ珔#M״IRc=gț쉙=m&o0מȨQpܧs!4\{N">DqfkωWdԇ^{@8 s9k}a='^QzO3̵+2CT= ixEF}>0מȨQpܧs!4\{N">DqfkωWdԇ^{@8 s9k}a='^QzO3̵+2CT= ixEF}Dg{zS{"jOԞh8߃b7H,jODDԞ<˔9IENDB`icingaweb2-module-toplevelview-1.0.0/doc/screenshots/tlv-light.png000066400000000000000000001232621473125420300252640ustar00rootroot00000000000000PNG  IHDR{CRmZSPLTEDwڪDUfDfwSSS~yΞҧRװL}~ϡVq˙jɓٺϠܻbōծ^Ċu̜سnʖnqqѤ޴[[[ڹExaabgȑݽZÇNݪÉӪٶ^_`͌լdǏjllFyXXXJ{Ӂɕy{|gghI{uwx∋cddŧ ͋Hz⒕rst(죥LetGyUVViWﷹ뭯ZЗأ؊͇v6ިy,wX<@wVΙRcf*۪hNvo,Sdȅ5C.}7;@H15X#,,kHxFPYۃyQ bmsg>Enے^aڮWD[5qH)YFHڟ\ŝNy`0n}j/ vIDATxPiZ]4mŅ0PfaRR"Qha $-VS0>Y&v"$Nb-YKV?9\n.s7^o4@u=@{͢=@hi4hi sj~_?X{s˺Z sjOjqm?z_<ێe":ΰ=77SX,v%{:7j8_o&׏~z=5c_YMV slwzmSО>O+rd3u:*g5E=7Ƈɳj^=?l?W֞fVҎ| |3E W}J,PCĚJ;۳~*ꇢHd-.l5z'L((nἘ+㑷DO ۓ'(r/@Mi&V<ĹC)o|@McWm[tW=JZC{ʵg8TC{ʴǎ40H{ht^8Io*-=ye3ns$19:BJm[WRus3}p,=yRRjfgJ)WC{.UGHĚ1:|{z^ϴηA$NXgjP=މpl)g9}C{=snȉ)C'}w΢8ȉ]T-y֤=p|zTCzhxM2ӃTa#'#A ߋكHOIUkcNJ 9IMua|p=\a g/CעQszz== aܳ?ݶcgڭT}ʼu4izL wP}MҞ)+v<;, 'L{t(20g1԰=q +Zd.X%fI/W=+,ǬlmO'=]m/~2(3T x +JW_h3n{,<\CCDN,¦=b L"Tخ2h{|ߩd=gJ<5d^!UhEɠմgHTm{R{6(WWI'bLU !{M{>Oߧ=TX3Mn/kOµB$ D oxe̓ @Ds'')shLXυERrHEZH9Ҟ|-.-(zU l{0ڗnUfwӞ{o|oY_֞NޞeoRrK0:s8`@]=gWx(;A{`+T9ձxQ;' @!` dĺ޿=SbqpL{-@ +ׂ+0 3yсXoz{ӶH{2PYԫ!|`۳{nܾܒ,쥞{B)M{R"xJ)x F۞(S%*3y18Ҟ(PUs'=BzU~A%=~@{!|}bw.j4p8 _I_)|Ǘ2H8UZZ=8\L]=gRR-Gy܈`OPGhO:ȫp_sn؞zUBεb,O[w,˓uQiE l%=ҁ*ĊB,mcp=3۞ӟ=՞aggdwYyÇa!53;ݞeۓsr=8ƾo= }w^=քrnyOδgř~f%x`'xn u?Bȵaoa//xBȵz{{&,`1hߏݘ~Bȵz{{YޛLc}xhЧcu<=nc nc}zcuٞ}>U( Ha1xft`$uQOFxݛZj15TgM1z^"C4F#t$R-7 W ۳*P-EPmueV֣'UuT'&N6:y*I5 1Ʈ=7D íp![-GKX*DXVdd&D9x Mm@={ҩd7 i q q!É1U{ ExYݹIV<:զ+ h=K!r"~jOkL]Φ di^:~3v;df6cLD^Kxs}z(QEG(BӞhyFjbSlnh=oϒ%ݦ}JfDžq0vpLy605T|ׂ{91Ѓ/`1Q;C5Alh[+6T:y{a+"W9GSWlstB]iI,b=垷#qD;/4%7Ш[GmL;1v605Gcdcs6ڭm(Ư1Xe{ zW%nRD&wB=NFڴn64D+ hT؀h{ ޒB\(ӕHKR~A5BKq`Nc=v-SG=5ԣ4EhO{6I: %k}BX:E{ yS{Z3F7l=b1Xe{.y?#{?_ ԕ`81Ң=垷ǥ~ =0'!=iM\x۞O5M#mrI=m`HJv ệ1 i28|z=<ֶǓBԡS  %22e]Z3Di`C3( T""vq$A$D]:X<3?~kU=li]0hs3F{4jMqv'pZӮSZa"hOOsz*4h|Z@]-֥{ԑ/hK4ұNM<ў s=8rc+iڃH1 3v;jB#ΞЅx7s#"FnvA-onG# ""{lb{""c{9CDD6""SKM}Ecޖۊ兙)Lya3)so62Ie(Q&C*JjꥊjXl3 ӟV*Ig@D`ўbsE}ac1/|"wY{5Ȫ@1iKjuLS̨QƇ:mf<3O`Ⱥ_`l1ЯlDDUI@> 0 >r !P/٨J4:Bs<4'U- ݒ#`x.sܡJ\>^=Dp՞I۳Uo,|go1!hOs׻=?ߖ?sHQ}hjOWޞl؞i4sC}oѡKsqٽ`3{E[. X=]:._inOziR۳g5kإɎ6b j3FWz{nl\=gbA{%7q{(_nϨ#MyU3cn6ۙdcMmjϡq?{}eYuuA{xzٲo7N=:ݞh&*1Us\۹h6oa58)nxpcGԞ.TN=w{(edj{Mdk4:_*cmYOD{e^h}Gt8{O]ڳ"iXI2t~s۾Nφ&Vz}ي=P~PGsx}hԸQeTE:!eX @TgړT%RQ_c.ڃgY~"2?Cj[RR%QCU3;=3OdFi)V']RG4JCgTg( _X. =]\<{F*~2Ҕs$\o|kO1LHžb){E`-JxRD-#SvzNg}%)oOP-,E{d{ h= )Uf`"CVZ>/G _2=5sZO=h@C{'A{@ N{|Puh ڃD"M"koψ7r8_ׯkn=^:kmv٭f?Sy?4t)Mp<)>z>^:>_h},2@{*L)T5SFX{(U)cEo9T:jϵV]ej=:p]Оϖu=e=jشJghYg*oOO֞{5KrU'Xs>g=$eĄ$ݞfv{_/AK`q9-ڤKyv PLb ](4 eZd8N=/ p{Nhm9A{h@)n_̺H}rJFz|NJNXҸԉ*"+JS>{ d-z=u*:ͬߴG|JY!÷G/sq4;NG<ؙjc7p{JTwi֗D{Sg}=؜bhOTEƪe)]՛sXړmnړ(Dh h_ΐ7a cdj!c%`- fSPsu̠\tTT6OYezw$@T1X1tO=|}][tIw+9|MAt7A9b#ގC{NX1timf7J\GnrT13+W{F30w #el"Ȑxe]ϐOk. .6C\ G<(a3rug:aw]BX `ǯz4y~x>W"W~<ٌt{~σr_1c+W{f]=3.% wм/h>@dQ%"ĨCzMD]nVƬ;}+UU!/R?Y'=yl\m R0/ھl|X, d,8TrO`ϭ(`r2>+䫲]/>iy4;{w|LЙ3O]-f=v8hgigsō,2P+)èY2*=Gqq=@fOW3Fga$HST 7쑗r2h =8 rߵg<`0 e`{<~*cX{Nam 36gwe5fIz5$Bv00ި|*dv>P$ kB>|zWj&!@: nC"ѳbO& | S8yjs2et{8k=//wfωس|أQZB{Aʥأ̃H c ae5rtAHmnBу!Ƈ"N2lO@*_cV1ةZ7I\R3FaA=7',[8Լl`{*&4tsĈ=KЫbTnO;K?ޱ=Gfg*Ka)r&=F=WD#xRѫz=$={(\4${rpKyQ{D :䕛سsӌ}6oϲF &!3 =8p5pYQ1*<5*?X\Jl{f=4PcVn x`!b֞Ue<0Z̖`4MhTP+JH d&_P1bO)GV{&h@f?z+[\[-d=ȥg{-eZF!w$DgŞ Tl=\.WnAz!'=~|wmpt[0O{VQ _Ȫ52UYC*_0}h]ᲛŶOǂƬ~&Fhpgg{ql% M${r.JL^X=|,7E:A9Waϩ3;5]<&3C\"{F+sVI=W׬a QH_ʂ=w!=utbI{N{OI=~|/YlS$g+0tBVCNg,` =ۇ`Sl{~$42+؞UW1V5{eZf{ )6qMjA՞//B*zrƚO޷I5ݞ-ˣ HmBAo(<ۓÁ,AOP.=b1 =f(ҐYكxA4mA rARU֭Z&ši!s czʹwE?ε9B%A gx5EFaϷ?d~ݟkgO`4A{n,Α="m+q2wW/b1S"){T="d ^40"[ }&8uԕ+أ*ZG>\H{*سi.^Y:KղS!/| =Sߣ=z?6ni: {5ԎOܽ]Yk6S{`̝`kDZ},X<4K{fxlQXZ+khwgaL6dgɞGP4э>7?x(rQ>ό(Sg#Ue$? `)+1vι:<]ztzY{j %f NCuy@'cw5q5if2@* HK`]ȩ<CDDE۞sC-wz4 )Dm6[8lE^ls a*~D | \Q!dr"׌$d$̬v ; hm8eʆi|Z1 < \;螱'I95I6\BcC$< ( 7db:{϶|Br댓(DR]8" yH5:*Oqջv $< ( 7db=H?D7)g3٫0%"=,Lt$ܐAd{ vO>$Ix@:Pn 2uvOsˆTeR$< ( 7db NLIbp21L{ŻuM3ߜ$: `AYMNLń;{YMMݠ]<5&I'N/( щeN=u,Դ8ľ)I_PnÄ<{"Y_oPƟn[ZRhGǀ HfL6FۢaohZ [4A:y/lbOϏe^PK8MbLImJ+_}'Bs_U:C ԍ%uLҟdDo 䊣+ +WB\/}2N 9_E6f wV?z1񿘘{k-k7Ivv^ol=܌8_‹qw?UμeKsz7sͷ2Þw'ه{brI 7T’& 8t a\hpz@<ƒ*%/P br9I_gOr/ll|Ffxvl+dW[%FS7;/1H\&ӵK]b::="#uIR@_Mñ]R4:)?2,kZ= ӋHq!?0o9nÔo{p({ wvnymD-xv= j,sPCE4{oj yO .^VrPLd4N:-Db{J =φ+FH> y@Ni9Qbl%ZeKa18̫LMIq`9ND_9ہ~\$+fplPMA`OI JfgUL/3L˸6`NgM\9{zƔgO_z&m Czc֬AP+/ٹ=lUA=s'M "`9(]hG*{sk3 `53o, sV866ÞiV%Uj2tN:jJ&ǾtscCp7"FKh$PwHbJ4g`N{ui ʬgvv=Ԛ{@iQN\kŠZʷKq0bdعGH){$:c$9kd^P*6{hfjw޹E(fS${t4LY&i)%ρ\䛛 oAWHWQ!ba쉒DP@6+֘M=uDΨT*<|{(SK@XtT(`5EvlY:~87N۽]4RhU<ßp 4~Q`o;Э뗺d#W3!T"˼LrqBPL {n\}8ʉ̀=}^kȦ>)̐PR :]@&.\OOSf;5 ! 4o`dWQt,D9(97n2Q1{^j%z'2hyI=ر+矅߭'gG+X,ޛF~L.Tdy} HCf=:"4\R an̞m̚P݋U,l\g$:3 ;dC/ÚP݋U|rגD:iw~ONaܝ[uԝЊ˹==zvI_;ɨoLи+&vxt{~O%I~fߌU#(T&ߓ|D`cMHb!)JmI_X6Na7`,ܛyB8\ހt$ܐAdvϝ8LĐ$< ( 7dc,=!4!Ix@:Pn 2ѻ=9{hCt$ܐAd=Đ$< ( 7dcsX{hCt$ܐAdZuOR@<;ܫ{BhCt$ܐAdZuQΦJ^9lӺ4[uOB%l "Ӫ{c^zߺ#)vy"r{s=QB%l "Ӫ{Fc tMI4m'kNȶjƍs&GɖfJKV=zܣ٫`TW.؉ Vb QAۭB Uf3Lfg N,A4 y noar8K{eQ}F'MrnΩ)"H7hb6^=\GٔBHɪ1?/9%u¹=b6jO$1$ŝ|z}b{!AnT|՞ad1}vEۓM@+"]Q]58=4QEsHN%j{n߳e8559-//j^8'QspGPU4ɮ=]שzMїA!!lBȵ= Hx#={ ۠&D{{nY]YCX2XšYoAXڞ;X p{nl ]mPEc'A|_~OSP]PU֞[m#}נ)(.(*K7?9C_6Iw.iQG,펱 Ȧ@BHhVREٰ@)R*uUYYەL7m`OcYXL' &Xį?cQGlj2 k5cgq ~` ? [,lsK쀩g518?0-q{^N[g'$N` wL-l@y8:YAQax=0{(Gϫ0檆* V8=|~hwѱ +x^dct=Q Ǻgci6}8C؁cE.sp{|{ JeuoN2x:/Ə{j>i}{zr=jHT:bsKߧ}@0]s sQHXQek,b:ͧ@6J2sg`wDQ!(0&2m#e1 g#zZkJ$6VI9kX{LܳCE+J@FKQ{yX!p3.HEU{Jo瞎P :uܑ)913r&PADNju(gTu!KKd+\:rJΛ)Yk{R"+Α#LyJb@M8] ?6%]Ɩ{٬XòݳF>6p G@vUwώ_=t% LTG`dN0H@~ pfA h^'q.DQk$Xh@V`D7ݳ8T"@uȑ)>*kJoXٸg7{W|aY& qAz-PZZV6^JȲ1agԩ7o|;ϻwhR/kKgyOۗg) %ITߞsҳ>$-7ۓ⧭81I)VPg#o}$X?N.ocanMf Y $׼`kt!J|J(mbihoy V`bޞ ?9r-}۫{w^z=; Cp%an3 ?7:ژ{<Ɉ;e_jRlN{[C k{v~*V孱Do2S!kA«!j@0"Z[Ȧ$ ߒ8=G{ qkp*n{m WX`8'V㺪~A &t&J@%7uh~/̏&`gAB`b6j8kP{N>: ԞrA¢WPB.HXtTԞtD&s&0!a"P{ "$TjO A䂄p@$\0R=q F*'N rAHE8 D.Hjϥ+B 8 A*Bo݇zzs!Cs\`U0 _,RŘ̥B:!)N#""ˀ6&4\@ aa)#r`0 uSܦYin{be 10cpgV&DzNMQK} 10tڳ1Nt\<(.Kڅ+(k0k$WglzjOvN2[;XMt}F۞,8HgVůS{J֤F`k0B C=홇:FS{ѝ|9g:u=AΣEbUɹ=@^hsOeIjSդHYRsn@{oGC+<@=6A{_՞l\{r i78Gh=,~ϻoi/{w̚FpWsܗq8ADL7B11"(RBuKu.03H^`k {swp7OoV$a2x/;:FgY=0Ko=D)  A4_6:F,. Yzl5f2LmNy'c;L:F&bDsG={%9p9n;R* ?Ƒ_ˉR{"]ؿ=?^|kϙ7{k{{buB#A$K>{?Xl'=gi2xF{h߱=;ῥ?;ԁ(P 1+ML d!2¦] z.NnL;>Dw}vu_P-7E:\xLΏ!!5)..rֳW=AOuOmhrAdܣ2"_ Ķo=Aħ،`T]|ǒ es=Ag ̶Ձ|ja*4SD=ƽo@w V:-Sb8:c: "m.ψÚ{жL}5+ a%МWUhXa#a(B=']=d50GF: ȸ'6؞>?rZEŴptZ3q@u(=Ge%1Ӷ2<<, $A¬{nF N|{*Wa+xA{Gs4=ӊSn I(9DZH?{Fc`&鮻Q{lS{=9كiE)R7$AŒ{i`\uaPI^f{lk"{ZBr''{0=Eꦀ$HqÄ^i-~c7@m8TԾf{Ԏn||ύCL+rO)`$ fܣVrIiE)R7$A‚QasȀӊSn IIsȀӊSn IIsȀӊSn I8Szj>=)OV!=ot[)n%ZBry~Zx~O^J[x̮svs]Jq}s&ܴVnߧ R=VX =}YiV<1O>;|o9+ݜ 6ƛ|=ٻ8?+S䚝9qB^+IHB^FLT2)ZRźM&mI=NSNvi'$$(BہK@Lҍ5q7U$Sy_z.%PG+Gϯz|GkMO|~O=}ص>TXoG!%ϻ7kDGY wRR U{*GgY-!kѯ㥊Н{n,Tѱ+}?{V|t2IbKXqnK|6"AoX&TB՞j c( fNz|.P=zÝ]|q7Oo}n%^ ,Ş=o泩G'4'4V3u/7T8 +L"= N Tr!N ¹}\kerL&L,~h4iz"'=!nHT23ffa۳Co[4E^<" {R@7j4[)B˧S'CëL`k^N{W(@6SKe.ƞ.˹GCx.n} 3̌V11q2upXpV JK*{ύ vOE Rk3l`,`r38b =Gǻ'"{gǯG^>ܼj`zڃ;H*9qqF6Pe̎^jڭx`I?XOxA&,/ f[dc٘/TB["{2?me"m= .iHMBbdsO/%FT9 U\K{?M'fS3l>կ=K/j$'o`OtfbOs^ML CF(JjO 0h eo52h 0i 0L uSwb*jJ'0bTX/{|^'˷ڄ~i͋kγ!َ3BCg\6{s {\N#lTBi7ϭ|u"ݓ''qܚ[9VsZ?!BPNf͏ǞI`冡YĞ¥=B D:mlÞSwzI/X=[cH22 fЍP aG*%d@/{^ sͣaܳ߇=͡2;2كYvH'I7kp~=|3l|6 W9{<ޓq75H d!T<gxl?e~in)oOͭ.ɮq;{s=5 vw%P`^=b$u0n<}XFw0_siD1Cu݉ʰfK} NN=Q} ސF #= SZ~&ӝfSIy'E$`D 5Pc&ǚXUʁd2=(FuENըZQQߣ?eF DQ>##{ R}D&{#`CP[ܨ=x_?~O՞W(TG\z+;kJ_̟옱Ao/4);;fyq޹ሡ sfyqr5 sfyqr5 sfyqr5 sfyqr5 sfyqr5 sfyqr5 sfyqr5 sfyqr5 sfyqr5 sfyqr5 sfyqr5  rODD<{޺_cնg݋֠`Vܓ{ZF}]7h>P۾O=?{gDF;f:  )$NX)rKWg `bK{.o#S9c{@ۜڱ=R xlmC)<66vlphP;GJ\ApiBGUxg@j:ps`ax\Wv. oPxp#70<+R;Uօaư8^x G1ǥ9\v3ỷ1{8jgG0).qw{Q@q ۮb{~FSQ\|۞=5y$8rؖa s!؞Cf5ZM!8r\ 4dD8=zkGk||ƪ՞Xn?JfQGE@62WS+`3QX܈͜a #mV{D@KSib0qJ7o>~^G_sv{f77`SzVR7δ'+r>ߞlϬ=JC\0Y옹JG P6 kniYz3őö3*GC$6J4=<ݧמvӇ4CrHc{ޞt5δ'_xڣJZ)Qy< A X˹Eö8!c#b82";۾n!=e@;*=oOˌ&(=5ʑ/l]{l_DQJuq #D@_1܎BHa1=W0w<Ϧ9CaOSCtܞY_sz{41&lߞQ.]e{ړ)_PjL$*qZB1-9˹qB y0uZ-%NX9c\{KY{Fƶ(gdp3iOl֞nB9ӞC=`7A:@ˎ(I{rzekqsn_iv8wb{z+ڬ=9][==1Ԇr{=\Qs>oRNZdS|>yV9I*Ji{GGk0;f֪ɴbg#Yuro5 jOY9\O.\{n5B3[j}]jMTZW j)ݵVZDSy̴{tn <پڝnF:ilۃn8ҲTu,{-(ʹm9)%BX:V{W\{Sq{&觊zrYl7vFծ t.=F:x=6_kpm/ƿkEp3؞C oRa{I#n߀? <3 sld~pDxg@j:<66vlphP;GJ y#%܀G<Ԏn#`msjH 79c{@ۜڱ=R xlmC)<66vlphP;GJ y#%{up!QpdY$ҟ~N}lܷ k,@{ 0= G{ОAiOA{h&ڣ=1؏NfEm( 8F]כ"U E> A0ݴS^BoK)VH[h)Df[ds8_/S@DDa{=9cc4(ԬU53 ;m@DDiSYD$&X{5Ap42ֶ"umT[JdK)=.BM=Pm>}uk g;s F'X^[Ӷ'wHĩ>IڳвvGv""@.fE*DЃ[D: X uI5qH37,1CDԝ=sH"""zGzra{>~cMDD=DD-%"8ApN|؈HfI8,?05KU=-|#""=GD$;GDDޡ{tHvtCpO8ď/X.>@A83S0=].x'1!gf &o@$8LDt\ v).KݓĎ33r7{qf`{\.tObC;LtO%ހI pbǙr='2ۊ2dơ*#=K˰ݓ/9< +n"qPZya7' <{tωh/)Gun?ݓt<V2;~L8TSwoia75P9  BHBD%jd7-TiIӻN&Θu-mWY\DϞ~:kxX~F!6`E"%$8>㑐3^13 f5(wfj=Z{"!@"HV0,HL󍂓G+<{==j螅vg~=a#/Wu|^=aIQF\x|=/ {9 t{Ξqxw`=Jrl a#C`wvah2M/pUEwʨr,LoYU(T8R?{j0kJZL_N9:q|+F+|%{;z ^Id9|6UM!nLYY!GN{*D* dfXɊ]Þ$M{Hc43!˞퍺gga>i1dGّPbLZ9R)XCԣ&5 ;ye1iC'˞JFG6?w>р(:0 ;eOJfiFWUHzžBZ[tX%ݲ{HcG5̦'7_` ÞgɲޓG{n9a^ /Y뙔4w0 H&ӞzT@X>ujL{r/ꙿ?D)9C1b:@NU5o#&i t19TET/'BE+U֕8ȨF6p *@Kx1IړS&"[۟hCg=A Z'(eFFg -{z4{[EDUZS%gP&L{HJ3'Nkp,{H챇4* b$>=|v߻goWVYW\cϢzW M{Za~ @@W}o$` lU@0Zȋ==Ϟ 01{i޲;ڱQE1bS ˞Qzpw>϶3I3F3;W=+{H3J=9;1vG$}+ݸ Q =i*Dϑ"i!ځiφaW~t֞T=d$31=Si҂U`VQ b $=%Ϟ؞Jd:C)^YJ")(D=ݝ] ,' z}O$53)W*΄q{rjJ&@"[Bg=A`Hr=oVUٟ~ec{Þ_|ƺVw)T=dY]D]2yC{P> h@.{%[I2,)?S}egg",Y~XAF)=bORJvO|pCٜ,+@L͠%|J.PP-DߞCE憇"У*ݳ!U\ajzhs$S[ UbiŪ_A˒&$*U?dۇn|npl}/n)O4r:T=dgi0fW=Z/d򜱇 ۓ 3 \\@{~&356 !+I%%aү0솁kP(&(eFv*X! 8zPRMa\cF@ 1G²TѨ7SVliDb1!} GPh*+VB:cƿ?4n=_Yy{[Ƶ=g5e{HnC:[|ga0xʨ s2xBoOZ Lfڣ8N$M{%q:"T%zp]Nf:IgaĤǮL:.|K%9Er暃[cY{9^Ts#w(,nv{qå9%kq޻<{ܼ޻f䄛3F{fa6lNr;ðǝڊ݋q<{q3Μ_6/va a_uJw)#8xu0`qMgRxu0`qMgRxu0`qMgRxu0`qMgRxu0`qMgRxu0`qMgRxu0`qMgRxu0`qMgRxu0`qMgRxu0`qMgRxu0`qMgRx히=jc/щHos{Gjcs9bT,'Ɣsb@%ҩYN)ϩĊJSݳVS6SωHg{u0axB.џnҪhF$R"H!=X)^IV6lPN1g/3iu3aa@o_)#3)τIHS=~ \<$!Mh %`22sLX4s*S#iP8i.g€ʤkS;m76\nkiS &T N ArNߥ|LX5oOTmLVm8~u3aa@Ī)ߞ^ɯS/d[?Y& ٠͓,BH5e!r~fis.w+:7( 7VWhZh,!@ h8RXpKP[R(w~ɹ'كG,N{"gm, TN'ĞcZZ|͞_K}{¶[B$̧weO7ޥ{/̞Q#X,w<{~,({饻'滻2ќS>Fb©Sr{c )3=ga#Y {z*STS;,sR̭̼q7`ꐆMbg=|5-,7K,bJzR`GGQ1{#d'poUGatOV {=8")m7/΋ψ_ZH>{dW),G=>{dR^gOi쑙EHjeOj{V!KP3)zψ艐=bDpߓ+ZJ͎=wqA֨3Qj㲇:7OX֖t=&0MG0 tG'6yXD։ܟ 0/LܭbH=U@'~C/g/; |@{({BJ#d+GHj}@cO;/^jG1}-rL~ž3\=cމ3b0h^=Ty=)y) 2XEaZ{hN+y}C$, nnNJCKe{eKH+3Uya NqMWXlF"?+|Cٲ5ty{Jql*FHj=&jVf>+~W͘xߖJv61 h-*'HôfE-ݙ3MHv 8p ADzIn)9&xԞP%A G03_E{:<qG sJac6Z}NB.E0eom{h6ܔ~8X\Qʵ!{K8SKhY6Q=VF ڵX}d6;)=6Idy5gN3l5C3i{g'{pҧ`qnաyZ?iA?=瞖F~CT!} XU{ݤ=izk {"p+\{hJ'{8R./dRT S'{Z{~kq=u$f6ʮe% $r8G>%x 0c4RT s9֣D9N7t.#9BdDsKtSU?뼧o0[y>zD{J{Zro)[>|D{KK{N|fpr2e.), LH/S'F 1"A2II'F 1"A2II'F 1"a`w]+( }O)p#sXH"MR&0-F630D=M`ZlΩgba 4{JٜS@i7i19$Ҵ)nbdsN= IiS z&HӾ L9L, $}O)p#sXH"M?دc 7]5%&#Bd`  !ar{M|}Rhk{qB{ =`h@z Zh$OF; ==G{@=Cz=PмR~J큚֕<,Z{. 9}<)b;n)4,.s3\ٻcU0<8xǛq89 Jp,1Z2g.&/?KѮK5'oLMqvl- b&=&>l D,r=K~="jʶgE9q?>g~Zs$q~e{Է=ӸK>"z 9H \kϗQ 8ehsek|ݞޥ=Ch&, v>-l؁H ܹ0g>2Dag՞l`L&)6!r73[Ei,XqĠwzJI>?lhͥ n'IvneXY1s|1~5esO#Ӟ,Cukϖ1"s'Nz@{<:Y (^cf"֨[{]X0}=|f! 8 DJf{k{\,Xv9DÉ̱?rZv{AMӞY4iϏ}ʶG6TZMΖFJS{DJIJɿDElHۨ=Rm;N6jT)!GIG{ut0 DA0_s 4[;HbN=ҺأSc.#=:8ڞ sg}4 Þ̳=sv=ge{Lf{2̙d=3==<+{3gzh7{ؓyVgn'aϜaOYÞ9CÞ̳=sv=ge{Lf{2̙d=3==<+{gnz0&wY>C@1`$ƙ$΍ WR]6B?tB:3fiao; UPuDͰ=d{:dكfX=TQoA3d7^{F3{= ٳ>4[ثcC7\#dBzcgz̙kOY-1j豷!{<gu: lHD9-Ca26}k>Ğ#]NCMQa] kp6 \lʞoJDȞQ1}ȬxU N{*'XlaEȞl9[i6׽ wl=3fG--OSQ*-u=G"{!T/Omg˲G @#w!EQI%p$G)z,dZwT&-r +7z{ݱHO\?==.ds{ sdٌ3}jmGLo̬gsNAۓRTk03XbO,dD,s Mt2b_JQڵ^rsw ?jJNs(VˁՋD(9ORRڲ.D=T3O ߀h09.x˜9gnOk{Ms0Ɍ8=JLT΋=gP;xKhOJIWhYXSp{G)1/)–0{.崧<+=X܄=2~_zQa}g$]5#=أ3̐oCsz>noxd,6Lq̯ͫ=$mOM9R0>%_h~Ms{^[:]sd{RK8[N{93Ќ4*\;i".D's{ f9x9.FFcx<aƣO6ǞNWڶ=jમŠ`ZܞtC'{>ٞ {2&wrV/^G_[ <^gt}2gh2ηoۛcOBgO|;.ܤc.7uš=dn=*m%֞fՍ$]BEocC|6&giUОB =݅=b9ύ="@|+{1M46gmQZd{:ޗt9Gqƶ+ -\Tcc3x=sbϰ/=W݊mO@u# JpnnqdٳޞD eC^ZT'DNmx>>;Im[_ ǯP{{Ş޳>tM&Yf>9NxR˞@ȀmO~$YoR0s[)ƾ$1г!{,{%堜8-.#,POGZC-Ee!QwJ`" Vj2vWa=ö-ci{ ߉iiU\s),=rUmCStC]j"d,Q+*, xdڄUsq=Lސ=C)+Y79֘ !{ևfSU7= !{ևf {u Ct!{CFkM|LFCx*dla7^{cJ=z=da%{PuDͰ=d{:dكfX=TQoA3d7CVqUGԛ!{ +C#M=h!{C&{4J=z=da%{PuDͰ=d{:dكfX=TQoA3d/ [ŽW Ҟڣ=c홙ڭ=ړ9Vўڣ=c홙ڭ=ړ9Vўڣ=c홙ڭ=ړ9Vўڣ=c՞@{ Ώo=hڣ=yh@p==\hlv6iρ>ܱPaVERŁTSI)L,2 A$d@PH yy_d^L^f}-xz2njUy jUy jUy jUy jUy jU~ٞ% 2Z_{pI|]$yCI}m$nn2 jUD,;A ( IVBlΚ ~vMl8 0.Ri# l$۷g9L{ X3@a(Qh#hDF==E{SY?W^|lOG[ݨtzijg鿼h==KgG{',)Y/=;ڣ=AgiOiy :K{J{kώhOYSڳ_^{vG{1 A&(`m{M Şa<{ÞY\ϳ= Şa<{ÞY\ϳ= Şa<{ÞY\ϳ= Şa<{ÞY\ϳ= Şa<{ÞYY Utɽ {ٓb{bϰ=), {ٓb{bϰ=), {ٓbϲcBQR D Ʀ8 6Фl]7p?oҤo8A'&LbSώKr9_'dϔ:p%¡\@[͡fy2xFW+k+sr &("'W5rg0{$m8ZEχ)d~).wn?X0*j_~\'!71Jᐲ& d Y.U4Y{"vz0p;ǕjfǞ/4(3d7*Dpp /#n$um_KabQ5`% CsQ6*ufİ)߳GcτC/5MY(y09XOV#1g{׆I#ݒX_*ž=35LE_Gϧ[ :>G6zraOy}ca{2Ե1#]{M0~`c!/F@,@VD%.Jt77l"5U-FϜ/ѭ"{r=ѣt6tmg=%P"{"]LYhC*! 'W+P Až4#;$W=rPmhh.ؚ/]sKLXc͘<%匚kn>6"k>@PVt-vP{W5,fJ$3!knrOM+[g{~a{@.g¯P,8D[@;8w۸ڐ3x'jE(~&Q=pudO 0<$Z2*쑋ŋ/#Jp={:w9=wq5CZU`' ##]2UٓH"7= (e K'"{䞚_ gkbȞXI'5MQյ~)cJ=5rPNi8 {3,5{=Ub\,1H2w&NB.4"{ǜqA=4GFzPTe֣hV\GsjϭnW{tϹ=5loy=ShG~ϱ=\h=i{+J=ch p=-P\ Sv4T|^RcWQd{''5#aʞ20+Y̩=|ս=}q0WdSٞڣQE=̚?N4~؞O7X?QQD$h+yVns[fG=b.i{J2+㺐c{rD\8%hv8﩯`aV1L%訰g8iVUvsY`, DُQb\>,͆u#Դsg{^bϪ'Si{*~ډq W!ZWY|oFJd~h=W=3~*{FM1hgY mN0l _~3\?I~b=ž=d2?mϗw .3~jrga"{~-Yأ9ʿ'n^vHi+>0=M+!{w q>- {b[lgaOu|8rH+- Ӑ=wnQȞwͤQdʇ`QK\/F=kYӜPj'bʣ P,=*35ߎ8'*)aDžÞxYyڗOA-aOGrT{mV UaT JSqGv'M"!13'f>,EueLzP%á !Lzp˦7p:m!?FKܛ)r)yB;PFW)*v+Y7T`س:bn[WEK=ȡf4c}U+D5S {Jb{l<]~ ihf[j[O`ƚifm}8LS]b,j_*Kee SCvUKm'b}S\ߞ%rSug+d+-VճAq8dPpc`gXpk?pg遥ȏ9=OE{zv{$bgDY}'On'niAovRt9ecp,FgփVt䶟jL \ߞ%r'SL<[!{\aO A gyY@AT!RasSz {TaR&JECy`)0=*P9^u&o$R87CHBG1S?A3HQO/Q/R 0T`j}a='^QzO3̵+2CT= ixEF}>0מȨQpܧs!4\{N">DqfkωWdԇ^{@8 s9k}a='^QzO3̵+2CT= ixEF}>0מȨQpܧs!4\{N">DqfkωWdԇ^{@8 s9k}a='^QzO3̵+2CT= ixEF}>0מȨQ]֞lO1sjODG {CI{""E퉈7Ԟ o{IENDB`icingaweb2-module-toplevelview-1.0.0/doc/screenshots/tree-hostgroup.png000066400000000000000000005134001473125420300263360ustar00rootroot00000000000000PNG  IHDRgY IDATx^xETH$$ HJMAE *.\ſ vł  (H  HO?/|$7y}s9̼s[Ї\$! B@! B@! Rn"V)oL! B@! B@!8Mb"14HK r! B@! B@! BizY]2гwGB@! B@! B@8s_` K-1YB@!pMp3;K:Τ+e ! p &W|G/7mݛ}[=gJ!PK dH&,Ɣf ! 5E#,8-B5X,k~M!%xc[|Y [Odi]Ef n_KwI|ZI&!`W ɄŲ~\B@! j2W8uIWB@!,giSvk ="ÿiGR&ndЬ<л,sm. 'V  !M&& ! G2q&])[! kIeZƻ{hKdcX CĴ(K| uk+ pɐLXw77\w(B8W8_e#cg_RB@Y-f0 F!blzh2sq(-.sh]L0qJm]X)jW ]1dt3Gael;'\z͸ ! pʹ)udcӍ# ! @"`8fы9؟v KX$ W$شQo[ -ߊ!jhLN^{5k{}޼y\7#øIH;hP~j!PbT&mQʡ]ݹnnx{u|9OͶVt1̟?(**Bƍ1flǏÇ~l-D:2ֱޑ넀B 8kd8k kׅ, ~'ܒ[ t:3Oyڒ=qkTioJ6~O(yE%\Y\]}ۚ%q}}Mʬ`j{C+#5vXd#Ix~Q44Lk,V>#4k IIIx7crmO?4~9a#}a/{SX\ ?/,gIiuD^x̨FFWRB@&[7:q [UH2 LɹjѐlI֎G){}aԩh߾}Y2;0QFgϞ۷cɒ%xGynڴ ,@VVw&4,B1Ec}2KZdSu,{$B@T%glg)t;E\җhBk+H/*'j(26eY#ט]?6;_`u*o",g#`==|./D@u>2uj٫Uy N9`k'CJӧ1e<2d3(va…HNNɓF9j2(p"yĐ S&\T?}Lilق˗_Ta}]qe 2ֹJJ:5O! K6J0=˃(BVLz1ޱZb}<:L툥T5!XpkGS6-;7UQՖr^zQu2-m#}S65\@z$6Ko[*1'?M>]naj `ME贗-!NCqXjnݪ&1L999xk׮5gy >8R[;ↈނԚ(3Ke2{cxLY8ax{iGR&n[ yť"$! 52\3KN=f5{lP4[7V^mrA!V?f᎟^z sQL0Q&ʣ铹cRey:uB:ul/cdc-$ ! @px.qޭvG@28[!D)VYz&?>H]@/^&YalPCoV L~847Y !y djpekG PTg#KI]_[Vݼ8)_yN d! f c3j1hg83///scl,,W"*=\q\'|\3͍w8ʕ+UY >>ZXdSu,s$B@Tggެ14,ǑB7,>vRV0?o" @ZzRDSSڀ\ \-^7ݒ;6 @YC)1Ř0VahikIv$~E'?R!"ja-2,eӗ[T-8vITe >-<R/uG< giN<[ɐNsӉ… j"QQQsY.gLXXAY=c_G;6! {;k B+BR, .(XWcV;Sr? K.WZ GbccxbM6]wݥS͍5|}}믫, åK O&++K.~e\a ecӭ* ! 0I% _61h%Ǔ?%ۤ!\s돘,exNI^[cs Iɐ#뷷,gUUp߿}"#xVU! :pzŜrv ,YgudKB@pxRqV*@kҙ|,؊"Sd ZzJ*Ξп 0m}ɹW8-Ӈ00 u͡D-RB'CEnd! G2q&])[! kTb6Ķ [,Rd'8P,C篶TM~6pɐLXlvH! @"g”3JB@! \@⬩O5>Vgǖ{z9˞l9S/ 5m@$pɐLXVB@!\}<3JB@! \@)ّ?amE[iL }UWmClduz*3~݋_8FpOҁqz%rY$!h> )O! @p3XǙtl! ARqXY7Ҙ 0&˹R\vgt Py}<;l7]7MLj5v;^K S63LŤpɐLX,e#Bfp3XǙtl! ARq͠-'2r'bИ8˂adcxd!Ff7KmKJESG,S/R; YyS bk1g5-&Di n_R#˄Enc! O@Y}(c׿B@! %`8ko%7%+(aSgocUhgY7c*ѓ1 \҄"l3QK W ɄiB@!Pxę"cgҕB@jg)f{tf_ :uF֢U˄Y^JHYN暊kN#0!ňw-)y҆=VY±A󞕸> qbB@\}<>3JB@! \@`y]=?xG.BN%:4OC?o+*ы9&C8b)LH'C2a2! 5GR:Τ+e ! p .!κJR<> Kͻ"! p&u%yB@N"~V E'C2aY! p3{@:Τ+e ! p niii]TR8@z_(B@!\x2ޒA!  8+w5M@& tKㅀB@'qɀx! B 8]( ГkB@!`r! B<g 8{Mw4^! p2g XB@! \.߅{8k=V!  8+wB@! qVktKㅀB@'qɀx! B 8]( ГkB@!`r! B<g 8{Mw4^! p2g XB@! \.߅{8k=V!  8+wB@! qVktKㅀB@'qɀx! B ,`Ν7o.ΟODpwcsy0ҀkF?K+B@! lpZB@!`8~YYY޽6 ŋiCff&xAZD(' I-(Be7{ AyݢȔwJX͗f욏ʼn}0vXS;2ޏ!^&-q;OB@! j5gkuJ㄀B@Iݼy3oߎGyefЛvѢW>^y%p>> m@qB7@iM-!%jt]s1}"IzsR3yIVݽbB@!DuB@I}䑇Ïw &Bx/ ~Р Og;)Bܐ""EH8 &MРN ΟF2$MȂWh{Ý$d#q{"Yd4A󺙥4BxpEB/7KA@a9E}(V! _UB@! $}xgн{ is;O B@Fxqwa֙6ٳxq]wa̘1N{ǎX`RRRЦM<vAm6w>k׮ŨQp=8m*TYgr)aȑ5?vHYYHmy-]πMlnn./{Bxx#}rG hn8Ȧʉ6(ޞW=gukӈϦ\C1VY| Y@f"SA[vHqW=z`B@!%ξ[hذ:Pq[7zJ?UsܜK.W_UG1*<_999"LZ.B@8_ϵ)-^X}\=ƾq>qI%LP7l؀͛7qfЭ[7?gɓ7+Ж$<7 CxI8\hYi!>n(LDRkU IDATEԃ[)̮MQdEDPE'(HéYe9OxU>ٙx*^_XWbF'/wHXi qv'OOO5~}||,fY,E`7n8 >b]%ޱcGL:U#v ! @e?_~eޣ 4P.Y+WTEDDm'DRRӪU+L6mW% ɓ1b:tHmܹ~S^^^[hѢ2YSveΝ󈊊3<M7n̙3P6}Xj8KHH?{jkӧw޵1=e:}b[Yw핷˗ܮ];5{ΚbmxӘ/?y/}駟ԭ[Wm777K dB |W;]r&|jc߸|HL=k.bOqπhǦ5 'm'ȿd~a\VfqT-}wz[+-AAF2ҲWXpG_ԭ!pĔ,^̟1 3&b`#aL(qV_<)84U8ˉ'"Z;O!p0'2aÆ)nҤIҥK9e%fR,ؼ<%L9Ы;QLihKbbQL O(b~Jmܸ-F1?Daa_IKl{\\bQ`n޼%8n:%c=V&Κc/\]pAv|e2x˖-J9lMlL_Sp~hS:%=D~ޗM4(Xtr ,"Y{m9 )&&F-Lؒ4☘m6^Z-&\X6[yҞG}T'I"_gn nNOOW߀|5R >o)߱5%QL {{ɰ|2_O35ga[x iWM.3tF/ۍ qY.,Fz^4~ <ݭ[v8K(~՗_/RmN y8Zs2N0" !fg8;qDp tnK'jG=Z׫ * W 1U&ZRC=,5yĀ9^wM7Su 8qD9j99tj@n7xhsO/"̣'A<9ifzѢE 竁 CprdI VW<~! *{Cu}7_{YֱN ]w(R0ڵkWaYC; mYO( k")[yxxx(ޥ4Zl+SNxהw9sv1qv>S*/ª9k6@؇\XSc~X7$b.>~׶y7>d8{9^R"=DŽM KN9C,mk)^E4xgEOG$Cǯ|F&L`w.\;kpASۿ/k 1 19˅?{Yf.>\|{R;w*%wlRuԱMRX߰\.*1>}T5{QsxΧQC˨)r.Td0&Βũ<1?&?NgibуaӦXpQm7ip8089Q㇛'?RpgYKʠ7 s@OPiJxZq`jh8gT݆8-@"`Ne^E!,SXX~cbSXB8W;vlabb'Yzhݺ I]}giNC[(0ij798Ya8.\ Xᄕ=s5YdWYs/Nz~(JCTπ^^J&9ReY* 8r]YC< ξmm?vLw(̞=ڢL)"2 eyܦJ>B=ir!"=5'k廍sw}W]vhA{faH7sFR&N'tHbVM㻝"} YSԮ ⷃ0UD4;3[K\졣 TKc!\$ w8Z579\t3)I{Ӗ".۝G\@|h}|pNR3^. ۖc0-U"pBk;,D]ĵ~qTG<قO q mkn'gG5eq@A5W9Hq"V9 ٜ8t֔ _p҃`޽ea ,c :'ܞ2Yb~8e[8LjPG%%va,,W)`3Yb3=)[!PS gGOz["O~~~9A1zR2@}ᇕJoz=5{-zY''X4g5R~z­ȴ;U ﭣY0Q(؁k~dy2.cRD[X7ckY6s3( yg 礞x$NMo4>#$z}j\FVqѣjbCC㿦MKcY,99ɧC-^cgm'561/E&6S|kN֖BߋSo'9M1Lg;[q\sCWJ.Pd:ᴅh YX1JCYcdk֬QSdtP;b 7̣0xo \oVO&7lloL%z׾d9o7؇عpHm>RpvQ䘁NT|r ڴ^ܵbC1mup{r2&G<ٟO`c*lnQ1noOwmfg%kGځ`f́3|sgN5em<|a 8k/[?0ii8~Do kRaXkLJ(^绂 #k={cl[wz5]v}go_Bw΂j\da-*>T'@.>7.^с*.w8&`nz@[wH(rQ",F2Y8U |8 ~c(v=,ˢHH>>Uyoo(Rggi'ߕldw0Ov9Wv)K楈ɺ9G?Nb/c-m#]?:Tqa޹{{N~U>k]=leqMJSIF1'cM\$[K8Q՟m(Zj#? k[X>'ڜ(2.?ZU&#-v7.}sB@ h(p;lj%=*JKNh(8P'2|QD '[9COW BW7C Qyx^IY<ܔn mFN#1|8١0K;(*j46 YJ1Zަ8KR$J9Y%O2xijw^qbYN%'SzCE.Vpl!'IO(hk[)f*K8zS$v2α#MLBdgӖCX lQc(|e"%Ь BG8vt%K-|rSs.S,朏g8.w?85WKNP6ŀ\3 ?;8м'9&෕[)qvڵe0+uLdorhㆉcӜ BnKr7}JZzsaYwSTvXj/1f ۨo Yn޳?*GGn3`Jehwwƒ7F#|+kk5g'r2ExZ[˵DF&l01SI2._\y4&jh4ڢ.>[Ysv_'p &ۉ laM5^qPg'bX .;29B嘇 8qlbmv l+0Q7Kk˥W:[Y4rbko \HqH Ak[5V\Ї {n=whEifG=ȵ G0] sɸg>K??l]O⬩xgNge\bϦY.^qɜ8(--w"Pؤ0#;, 6dwj`rg(:[E&\⡨\ؤ8929}OQ[nϘ}6l-|wqf{!* ɞg8d*o1oODƟ&8k -[8Sնi`j EY~dm(s,?p'(k[qW9ˁ-wpQ/rG6|b)k6h,egxCZ#ZbGAB@# :HOfzӃ%)KgY.E n9eA[u@k8KW8.W㤙"%=+IA^5{5@e`Ty ;Gʆ'8ѭΎX6cY>gF&&gɉ9~)n(_bY~l)gB6Zbz^|S0qx;*O:8šPnU糤݆Ts$wKME!jDunq߫o5C0>#jw8K;8gN5䤞D{J+Dϯa~mI$K- YU28ySNͅڰgYEz|RМl 3AG>ːaDQj'[FOg!F!"ve :0Pθ$L X*7Б^CwýiQԢ8 y@2 .8&爦)20Ln1ljǿ[FöFB4c3$sKeT7 (>sAh_N_mAz؝-@C+"Ļ@l2g 5?DHx;|k T&Rg"-\@+~0Tf#\+f8b'CCi^ \ԋ\EGFRM1{ʋɒv(ֈQe7T$Bp8[ H%(V4 SXUg(R$ 2#՘}ouO v){W|"|zt7º3$ƶ*,6}cp8k.\"6lWՋάOB@! jgkV5B@8yhbmJ @oÐ=˸71swή7 ⮟!*OᎵc#)k bEdDun8\RB@N@ٚCb裏ڔ+Wl_mWWg].F@Y4Z+ ! D=$ !`/ngڔx&IM k`+7#PπeDun8\RB@N@ٚCbعs:ޢjЭnݺ{1=,Z T3 #9k!gkaJB@C@bB@!PC 8[C;F̪"V gE! 6 8{mZ! SIB@8\`ln_!@0cktY @ik,+78HҏWep+ ,h= 5]VJ~ڄip,]"NɲY'+zep233cOuZ???aÆ6Z||;^l봧ΡФ9MT6aB@kPgKS+qV ! KjVшԭB "PGNv (ς@̳@*f^}O<%EdyowO<~4npdEUd*4esjj*N<˗/SkÉxza8N{ pLJbuaV#! B# 5D;B!P l` Ib'0f (!t{@eufVL<h|rSwQvxxcVIhנRgɊ^{eCo>h߾=)HEob=lkZ#fLNS+mN.*deU=06k6//Ϟ,:tPy/؆cǵb3 ÎzZuuMg?rKFXED2 ! B<g厸 X+vyw->zOqP Owm'#ʡcсN mGo _ -}Mȿfݝ(~ 'yCĄ! NJX9+]*2N.BfBh-uw&OT7OGe6m tF|#V @ˆYViUʪ^{;wtjHNƞ֭t!(! 4{pAVaq*\Y!  8{ v4*k请y9R(z7c0u[eY,gy Ɲ9{Vm,80}-Vf'=hoa'nZ{/7]-,-d((N Rxڢu=?a&3bO1>Vɴd 8NeW |qK{4 j#"Uǧ\ݱ8:>Ԫ-nhӾ\L[#7jzncc1ͽwi]U޸#bٱ  eRO7~Ӂ#K#-ƬwEtop]MӐWߝgKT&^fH-'{3Ҋ\qMYWng𿣍_x&Eq%Ձ -PS&!g ӫ n0Wou?y:,?[ʢ]Psx|AN˩ R/l81فzq6!+=يowB@呻EMyN<߽&tl&! +FuL5$S\rj D˦`85w.P0pE Vi,gCd~sξؚ.\N=0 ZU`/3tjD Oëe}%^.*Aƻ[ӻ)4Ft\ZtwG_]..AG <[\ cސ:xgwؚ|킛.Y8yVⷳ;* 0Ne'@)^ Z:x%~5gL϶"+٬,,Yѣu^jL">=ƒhD'NÞ{'.ΡuhcL^;tۢo`=sQnHy|Z})ET)B@j"UF^qޡ?H٬|lK0*S1g{฾bY,?nLf6u8[|2fyZy.+<9-hkÏb~p䥸j*ٯǏ/UbD|' < n>:n@\ru/=Gyt<o/.-?ߠ'ѵo;EvXq6z>b{!mI>o6LłИ6yvE:g7l؀={bܹYz6*ݑw?OEa!VKkө&[t4MnU9 mDqT?עLxg5,5 ! uW痽Щ J!ceLr5W9ː;{p;uΤL< 0{w7M`]]'fKV5LΦcoqh|_D{;OKd>^-@^q SIƫ[W>$! zk.e~ CnGh@гv~I^r8ᢃ&`'T|Ǖm8kH/ )@ULd8/ӭ=Cvɭ"Wy?!{LW) c̉%x'> {.$3_y[Pt"ZhȔ$p %Y`;u˿+YzÓFɭ 5?a>Ig0qLM5[C`W£0qV3j̙g%X(/cC=0Vżג낼=nlFn&>JeijJZ^!>{Fp'g=,U ! lZDnyC# +J~bDxulh>x@!`8kx sn)="Q\FǛek+gT70/m^ n툁M@8;yp<`YG(ڔ8pR,g)ް[ŀVޓ_oۈ!ת-VSF jn,o~-gol32 }aؒ\ܥ~<^^ ? _O4i9MN|y!6oSNls~9 n6}LQXd^_]cY?sk/t_]egxuw}H?_l=78Oo mA(~73=-ui퉙ju}J(\b1֎Njђ?S! Q݅Yg#Aʑc^1ȕ*[+?xFYТX̜4h 1 31eycv?*lfLXs EUڑ:kRkێGtF^=Bd `V&MưQ]U[uPq]0~~omgü,K؟zI$R,?!۳L( m mѯI0 K|}ם@_t7ǼűWuEcA،,snÏ`]`2RœU'`uPbgk`#ؗZzp "olJB@(&Br)9-C6$WlJ@RZQq}R~l:xZ,g[njo֞۱35M.?`a|/jt5 #擁W, Xz:ƨ=xB|w+7B^MPt";z'(I)Voz[6Ō= 3(_]aaZ>'y~'˵o8#Hʽώ&!xxJ;VWҰq2~~Vvxg),Posb1s*DOb֎ U_"1]U0e̘SZξ2έŷQkB@X@,(,V5@ rX)ZPbY,g+-Ȋ ViQ"Ld'gm-ә׉8LRB@!p-QU+Xx5@C +3DƐ X~?r%<C k;q `Y\R2sk}ޞ<A C VbB!£Ghp >ùƽ6aa0w"=zǽ 0Qa>!/NŨ3vĸeXrȁ`5qv&@M! C{BYtxa"VTUGlݺ<gΜEHH7C??;ZHB@! 16)ΪzD"cHxV>AUl⩘0M31eE{|:4 BaLL^EA,5qu$@M#r #˹Vv}S$txY0s u>Z#fLNC0,\?;UQ'+z큩y߾}˳8ANlñqYT@gj[R /^VcgA۶m+Bw}w7kIiʔ)6mLǂ ޽{!<RSS222裏!(LK.ٴiSڵֈ?S>}(uРAx'ʵO?of{WѣѪU+e{?jDNJB@*"`8뤰9)8y-KA) IC +-ª2uOġ8 BR;,{XqÑj&icu~Mߌ0* 8lfƋSˌ 1ef8 CnL,LUtO[UVB@\Vm'8-#!qbùuDM(c[@:V1:xX=Nt@X'޲:NVV]So'fOq][~}DE)W_K]tg{K{jq?F *3S?~<͛j׭[M6ᩧBݺuʥ7W_} BpwVZ߮]мys; r]t?blYfMŸ 2}7Vz&|P n_CRRϟoVu佤|~^JNNtR/8&n$H!lg+{똽#Wa8^ω`U 1tX &cϜg z3b 1 ,ȅ/ Ÿ j&:$bź#Đ ``1oq,3w?4b Y3v zqطp歋Wëp?`Qj"֞v !XW졂 պZj[uUjb_κ۪nQAEPe}Ϲ!$$$ӧx99WobR.У`_>%P*Ұ緁#tI<2 a1P-;HLN#cn6L-j=&QXes[njFFFBxP O"RoL]bjlC$r7-[6m`"^^^r%erHIv}lll.;;; !6rHu&M@ِYVl1|p1W9)SIDv4744T14G~}1~b}6)REgܹspww\^J2""Kv05\&K\>|.]Zd[#11Q^*@ógD.=KPPL#2FuM2~59Lzz;xΙ3'+kާ:x`lR5ZHHN< YUL IDAT .\cИ#Fq%6oތ7no͑9K?/_jg;_w~gL yEa<&;3L nB[x]s~<ܕ?c:*v3hW[a݀|t[Wtn#v~IwW)'_֪kPes~D՜c,s΄א:ŝת%7}tؽ{7\"dlS'g) J$PF"-[@[$C AǎŞ`FXT~|BRR˗ .9S,*@KVZdyi2$)v̱?/^\fM{#~)O1KY$IȒl$JB$._u yN2m5@T&䷃FG wNNUREh!IJ#A믿ԩSYSw:p@L:UdܒFYfܑ ~ULӳ}h(S{"#ZT}t?~<6m$All^Z*tRE?6y2&t!rVz 5-0&PPA @FlsoXm@R4c[3[p XWS9f !xBeZTH̖:֝XW: Z޼ (׮mSEe,}IָdΔGI ].W$jT]tKL?uq4)E!u_TgVm]Ƭt`}Yׯ~Tr⧟~T9K5L}||eY$ѾR+$!IҊ~Mٚ$Eg̘!%)EuQ}PR$ T5gM ӅSlkѢX_@KِB^Ȍ%Q(L)J3kPf,=Ow^Iq&1 KR<Q֯@h Z*_@kpBQ*B?tH~$M"~=`!gIܪ:gt5LB===aaat>TY,}.#OR9{iM;-?w!o)(,g 3RT -;bL 0&}+V8HZ~-e.s% ŤKH%L([nǧZj'NĄ D欍d5kd1I>*% m$ m&~0h 'HrQ $OiLʪ$)KcQ)ʮYًHy6Ś\D'G5,n:{Ċ~`1cƠo߾BٳG9#){v4mT5Cr|Y:s+:s-?η;0& Y4K`L 0EEARP>/sl쥯5mbJeZH̑𥚳΃$'"F۶mPrQk۶<ՂUHRŌn=KY˔Je I٨( ?W&guz_+U,t% KeڵkgYiz)9oooQ@TpD3x$ve3gѥq46WeL ,gK.U`9ˇ 0&`G(YiU9K%I/Ny$,@5)1aÆaժU~)~Q$-}t\[9KGeǎJ.%<|۾};̚5[XpDTjRYJQQ4g%KmLڵTրD0'Kعs\I_$9v. @Ϟ=f^QF0!GUVsFҗE#aWT)QʀÒ,rTD+ˢd+!GR5bIVxbV Ef͚%Jfh"gi֭Q-djR9KR\949K$x7\~]_ʚHR TD.5Y9K_9HDӾ{yyz$5wQs`L@W,gu% Y><`L 0&P UeHXȂlѢ_`P7ɒ|%+ q !%x&`L g 0&0x,g ~ y`9 =`L 0X aL 0&z,gh,gK`L 0|&r6={6j 4mڔ 1&ЙYrC&r֐w`L u,g`L 0&rw/T,g ?`L s,g`L 0 !0dٲˎryE@2!QEpv;yj ܘ`Lp -\<:`L 0&P -{3G,g.ֈ@FFcOXF} Aµ}L 0&oXZ`L ,gF2Fl޸q/41n^t$7x F\whGL(\,g ?`L },g |ˡ"P ۺybāOҪ/?q=ԧ\l`L dL 0& Y. 7Q VX^]}ϓSt }eW,͘ `L 0 cL 0& Y2> 'M+`V'i1W*q`ej<`L -@<`L 0&`XE嬾Hr}bp  \cuaLqcL 0!r@0 L 0&`9kSםYr!0Ƴ*Xaک;3@ J\]BWfL <ϜGdL 0& Yگb?[7oac/̮Y\כ^R"Ȱ0Wls 0U-DL A\J΂yL 0B$rL 0&A`9kT2&iWnqs-8ݮ<^4*Jc淜ÆB':%-k8#zsJcl8#kA(L̯6zqopq;7 W!-Ces=a:-s֫,qޤ89$jYy/5mѾQ>jԕn.=1&@ ;;`L ,gK>*-=}I]Aﱜ;ټ$915_Eg6]"aMPW(rXc{7/O+^ BptlM0Ƚ|ۡӎj9i@5È:Ka;uL?}GOF\0GMg`L XwcL 0&J %fBmf.InفVVhr㺕1quYRK>t/߈ eܱ')&4pƽIq:/"#Zj;`V,ހX|zѣ=iRy;/Ƴרnk'㽝L8r AE|0E-Tędun.bKSPugmhq)|ܑ8X]t~VV5yj47YQ+9j2涨Gވ3MgwP1C}J> `L hG /rvk'K~hL 0&z,g}>xlqrYQstu aoRٱp/_JH ٸ]U8= < I6A/D|;Opv`S $ضj9!(ᾍ1]u+>0l8V_{(D`Jh,X̀8ӚԀsK #l1cۢ+"sb~}ۺz 9[D%YnkcgU {\|7*:q켈/C]rV]?]v [+~."䷦su;Ц6<R@} D">kZe14^a*9jGȗ<16`e젦^ #JK,4yaL 0- Xxl`L (,gKvŖ35sm$!%Gz}Hn6_~Y\<0k $[Ԯ(h/ л!:)"+叚aȾk/]0`UpWBZ;D^Qi T-cJfYhN2ǴEBW{|P313Qyq.k-GvR9kͨAZM6EvJk2{j&ϑ.)|eǥzkءߞ+Uk+*O}4Yj)IV#W]U<8efoE}S02B7rC7UrY%[{8wUYR;ݏ_F\ā6Y&ЀY GX 0&@'98vh$m l!L ƒp=ˡª N*)r fFwp{o,0K6 LnR\)#A@DL  }|3X%g)p^u o/H&7D`mZYAdxTD얮YِS@)3J-xPSCӢfCF}Ző}H*g);綮|),O ~1P@VMlr_eb_ q7mԭPZe:eL٢R I.RO_߉]]C Y[kU,V[/k?=y ]~}& cl"jت`,1SKװS= $?ȍO\s`#rV, *ق"0&QΦ lB,$¦ ʵL'UUC7w:tR{{7V_۔ò63gM!| Y{S`<@ٱ@̚  U}XaY=$2}w\>)V)gVW>5Ѿh׊樕+2[dPJ 05xUWSK9F2m_"d e>.;E3sI<*+g[T8og|ͷU2|\+TctMzǟ|'~xK ;!x}6uzUģX7FBy^ZBΪo1UQ NI k榸6>yPU/(4҉KYu]ל*c`jlC[٦xEiP⺠uܐL 0&Z*"-"`L 0C@'9xm f. "pDs66LYfWh3s)ς!g)N,͟`N\oP3EJ7 dMDzpx⭝v{fU{in FX<`~CH/<"PR[`Ho])6%Wk$mPէFkJ%BL=9@D`VĬη>vPNnKVXr'KoЩSG,JQȮUJ[KHȵj(sIj&^?I,e{$2o}*ڢˮ92#IQ9AcQsC7G4|Vf՜=AaJ8FVg4}H_D!0Vƀ2eee Lum/>I iv[$񭨗JGIΪcZn(>{GwQ䬺~ofo| ΅kaJjp gr;/lMσYJdژߗ@8ˑY%I޺J٬7h?W4b#qܘ`L@XeAEb9[Py&`:YD.IPm`kX3q)2ЅZ r%wDԝ9?bd ;=އ 6ܬyh a^p"9;?zah[G$ǂÎ80\djca'4r!lGw܉-`Krva0\-v'xh@,Y "bꔎ}a.5ЪA9l T"0< ܷRv+-u&,W)g)pZBZR[_۳a{j2 )cp3_૓wO8K.Fh$g)[GM{k]ix$9˔4QT.-OHV*gIn }?o'%bk5:EM8XW|yE?O8 >,̖3)g B b'bO`L ?YQN>mڴAN.\(~Mk?MHKKÇ~vaܸqr]V\ b_Dm8z!ekd.ϐ سg:X[[^z8p SEɮ]݌4}NU}WHNNƒ%K4yaL J̙3Xhx}˵6 gaĥ8/͐OXQn ez9+[sVa$g1_<7 "{a(h;a7u&zJйųޚ)[a;yn{tY龹KUoLtLR0t$FιOW9sRE<ލ݇q=20xX[յuّl $)e/r)) XO(0@e9r6ٓŬ>ifb1?\9*`L@JE9K򏲅;̚5KH:hHÆ ڵkU浟&&9\raf&ʡ'O'O`Æ jzU](>m6=zGϟ IDAT{0˘t>;WWWM3L 0.]yg臕#F+1l|܆̱vUH03Al;v,̙ZjѼsS `nn.uԨQM3fL?fϞ-ս{wg>r,3sgej!,p^.@n_ԙQ)cl%Xp ) Vlfnnf ܀UnvcM/7Y,,> ,gu=nK\{.H[5@< )6r՜%Q^zn .HݱeP]>m$ۇS Gښ5k IHP}_~ܹ3/>OR/7*-! )d+U I.Z9/_\Hai#9Keh JIf͚$0~xw>3fC^_ˮ] (`bZllڵkcΝz3r{/vލ+WRjU{Mco+WҥKy -]; UgEKn{HgdȐ!رctQ~xT&CeLds39շo_E'9 $ TuuBV=1ebgq!ª,R8p Fx`SFJf@ܐ6n8D8r8 r@lg4g.a窍8 I/ -X,XϾ 0&@QMR^KfJmgI#KBz 4 Ï%<F&@JmcӀ@@_i>n^O29KTg#IًT5ʲݻBR-]baa!Q%()!e>X{Lh3gIHΘ1CdMŋ$h]a*mR9Kϒ| G&9,eՒ̝9sFr֭[JYC UU;|bJ2I?$SIr>QFlXX~'!{UͅDΝ[tn779Kcмmx(!$f)D:7&.g5~بϦ qh$[[7sX&1z_cJՏҦ]vTY&g,fNmGÕ2&T(rw@X@%+P&g<ږRŰL 2ҳ:\{'J^#ap<001|W@@@:$r6qu9,e$I)>VXˋ,Lʀ,ѦM}Ve? :h qI}T^ײ$gIfJMn*."aImĉeJTRF0plPʈUʊ)${I*zIHRp542VTn@YR63IU۵k(#駟f=BY$ihiٯͅQ^Z$elkULi*guhQF9.ܗ 0I~`H0ҟ -Z}@MrVX%`#H?xOi\z@Ŭ * b6rT&:EZ:.-+QjW*$i.1juʻI6sz`gf⍱)c;0qj 8 <8)gsWSLR<%IK$#?CP$eSRYu$ez{{}]eRf'es@$9f9KIR#9JlYUrƍVVVh׮R9K .ʪNl4͜e'JUfׯ&4e2wlV3e;D4\Mȑ# KT;+7=캉 h2$i|:T`L ?Nԭ[MEe9ם~' 9abٕGIҘ,gY=Tb6rT&@ny-8>}S~.i@Yu1j$Oۺdjm m#w`ǚ=}Q*9cqS5/$!,Z$!Hu(S?IR*]^աC 6 V`d ejGIdTv2k&,IZ(g=P6/ d=x$git1JdPŵb*|JWRRR %QJc)ۘ)qLa*@)f~j.ty~e]TGnݲNfTS<+$VIVe{8oY8t^(XZ@,l.]dtL HCB'_X'ӕћڱfCa,.+CJ=W$~*㰜3bXT,f+GeL hB0YiTi)Skd*eRJ.tX}<)Y&1*OHO&Fƥ,[6$ٲI>>8|\MF3,=OY$'IIeQ+HsTcEA$HJR,Fϝ;W65jo.IT#l:uPT+RR>}Wtl欺tNI`&$,X .Ih5RV+c^9s戋׮ + Nx޽BbS&lR!2+U$#Y.KQiŊYusQұh;*!vʐUvVs$:9Kk׮7vYqVHrcL jر$g]xrV49`9kp[Vl'b6lpL 0M XR#F.If(Vv?HRd3+3/d} $?,GM HUi,Y*9ps ~@},`b\]+u#_[̬@ņs{?`m@#$Q\:Kr|Ee$ɬwӤ;#mۊ-g#""~9Rď1~xٳgXS|9`L 0E,gL0-?`L ,giM{O P53s[R,IS%Enԉ5!uI2ífb!L*5d> Rޟdؗ5\%g䂱?b9K"eG%cڵ+Y9N5 sD&`X`Z`9,~ 0&(6 Y$KeJW{>d/_@k̥;nobBDl@| >0<fV 7228!j6u oc)@S1m, Xp!>s#-- ML]YʌT&&&xELtIYN9/P5iYh!`L 0w-yXΖ=3&`!Y@%2+6-k,s$ǒ ֌tip!){(pq;3Z]kKI_+_p+ɶAK.&kF@jRրƚ1cLMMŰTvƍ`===5 Hʾ~...޽;ELurV\Bh1`L 0<`9Gpܭd`9[2W`L0d9k({''g+\љ`L >$raPL 0H =<|/7ZX_F*">yLzT ]KRSJjc <.ly7I`fv8B f>ڠ;׸Sբԍ6=ŸbH\IЊVDo'tas3,gM.,gƏ3&(&Xe ÙGaL [w#gw.NaLۈ5G=q 83?o>]rl;}n)tAh]^GLUT6;OɁ:qQyo=s\:#49k0[eL 0bBl1H^F`9[0y&@%EޗgW|yI=Š^lM=~g"#,S˚Mkjjƾ։ΞvqqY`52&@1!rl$/`[o?Ckƍ[ʕ+qA_&lwņ TT\ݻŋ~S6m1%0c3&B`ּ3G"4^!GٟyyHQ09@5}͏8VeGEY &Y*(`L ,gF2 rvxэWQ\903'O, )Zrv:t(4h wlmm֘aÆaڵq< `LPbiwV5,_&'b}+kjUWMz!4"֖ ة&5~ 84:<:lnr!x>%󃚪ץɩxR֝küx&,[:IjSKzva5ʚƗQ\u<+oASIy1nnF{mYepogEš?uSc#wpe%ԓwpYVE7ØY'%`L za<-8ר]%^ $%9pBE1:uʕ/Ie˖hҤZHHN<Ǐge:t;v@BB\\\0aۋo޽VVV۷|rܿ˖-C6m}v!%))s[ vxȋ'.-;jAi2 ?SX4O?#޾}5m###;k1CԩSqQL4IĢf͚$Z@ٺg“޷Ƙ1c)([,,YgϞ2>}:z ___!p\"}ʘ@w۶mhذ!Emcr1en޼eL %e ߸RYrV:t~7B0}j(gekl;rg, l? Gƙ[,P# )Vr^4-A%A &t>Ki%gTǵރ5b٭p?a51fL ^]pe4=(Y3L? j=,g 4`L@B@Or6 'S֩*@}M-Piy "8hg@{ 6ZN0Dr=6fWSو;yP 'sCGX"6%5=î3W4s. `l&D6 h-ٙDl¡>/ qa^mD\FN:$W9Ks}6~ 2DKmTnٲtȈ Yn:Tj~BܹѢ\P,]4K~XBr eJNOOW35ꫯĚ)[ln}&=-,e>?bZ031Bމs0SMؔ6WW 9k -[Xr6%,'#PgQ@E*rY qqMV&P#с1滈x.7LԨ{J|ͅ`'s]a)DsU9'G\˫4SDkjشq5T*e)gqw#4pRx&g:/ 0&`AΦ!8"n-ƒӀubOsgy94 +*IRG0>ys~Y#%jlK wb e|'bGhg|}#SVsV u49ej{͚aq5iD:S;:*u1ǜuwA5No(tBG^NJ5g)K.2R9{A%9Kd7n܈Q.;w.;*UJԜ}yr6 @eLKR1^fhr6lVZ2eʈ5pcL 2r'Xr,@n>Woiq|zף0s6 ! øFU;X^@k;N+E>:;)J=WzBJviu5g#}[!kZ}Ii-a\JU.fErң?jTœ8vo<R\/jW)Iv{ΊxcܺʍKtm BCV+ޭ o2HHƔ80^ڴޭ"m*UWf䬲o"9slO 0&J l 6Vϑ9w]OYbc.Ag5$7O* {4縃?--S5rW}μm.`(mpc>n';T!aB0ipZ[(,k&q_*K|e2gmt;:bځtL:nхb5%BS邔Q˕TΒ\`u,e~駢ÇE.]Xh\'[ր#)Tf'DEE ZjU17LB0Cu̙ڵk~L 0'$sV9h(g6&Ƥ5LSڔ5f ʞe9+՟lo^-`L >53eE+ɜ+=34sF$ZyC̬ZdVIi] 芟n`N9o4Vie $z, upuf&f*SNCe,3Z]@VG)f<Ŭ|,0/f אlA⁘`L@5{$?lUJE * 55ׯ_c\ ѷ,)k׮-@[AN2dʖ-ӧgق 0"p%̛'SN1b^b9W`9[w`L -g@Q>{ ~NNR6ɓѵkWt;wٵx4s6((7oF\\jԨѣGJ*rUIƯ ={Dfpy4L^g},[ mڴ(+ SL~WDEE)?.\ _ǻq+++1b|r]dҳFk,QNYsM4 GGGdyxx>|x=L:Ud$,~ML=z$NVK&gխSVs$W?c!q/`dd$8\,Yi(:W^aIb3f.ǜ2&"pΝ:o}f@(f9'd`9[2W`L (rB@kzUYc3?Җ䗜Dz a۶msnHVVMo05l+p0``8+ 8Eҡ85=ぎ?'nk5}UIQ'+Wn@?ف7@р;Ppc;82 h/3oAZ=IG)ߧQ}"]SNhXxWztcU EԩS,U.1ڠ2fCCi ~_r,AlGi t&\˄‚")ڙ^i[ܾn:FBMy,+ Etnծ]FQdc]}y}+Y&XV(pv= ->p\7yl+*sS& 8͆Wwbm| )mj@R$pks-`P}/U SUz|"M >|P#%GHI弪T\.ZjLq@FƊEUģ rOm299ÇҥKE幥HW҃wTuJkPQ HTl%g+E ΒWUYm7*,G ,_j(Gi' rXV`tV9O} 6L4fc8kL5VWlb^ + )p/ V078kUVH%`i^2X5P,~ݭ m+5 ;FYKQjHѲO|Om[V(Y*EyP ۣq2dʕ+'#G[[[_~شipHU0`Tlr2R_`(S]z^9ȧm68KYxx8f͚%4oRRTћRqD䬲6=z:Q_jוrRրD~A'FzR&ˑN.,uV3 Nk@sRD5? Hr[ܾ_5(#@96PNQkDz+O<رcAto>!zpV/sIWlIx@Sls^1+Is%_Y 刽 b^_ISvH^)kFԧ`SvAf T` n6hv 5 ;'ǿbBsնtHI=Q{KʍKu W+ 2WI !Kyͬ+ y`8W+ g@ƋLu "^:VǀmVPj6m.px +`<Lq❹Y[8EF/? 8UׁaRt&8K}|Z?J9g)۠-ATHB݉n+GrsRAW'{Aw cQ/ g׈{+P`8[v[  #AH7VM0ߺu5=hZ[P)HMs"!p,C1fLqYCc$ + \ξ\y63W,x׍t̷gdwL.B^fTlԮ)l-R\b3y +YS;hps Y7`XV|`8k{Ǟg*3gD@@^}n;;;P*dPre ږȘT!* s+ hvWUî)lʭM}.C40Κ̪Zb]]mS]-龘1DSfcΚ羱׬+ Y;(l8[@K[SI>wrr2V\8L6pVy]TmRXnW`s,k?^錓j H}a~  ; ;6VXxeN> NU".= W)l8kg>p_* wY&GJuyf},`8k}.J`_XV`J gK.@QŽS?6m`"qPn](G*5i[l&M/[n}xU44whh(~7y޽{a$&&&L'#MqFlݺU޽{wڵ ?~!ܑՏ?(Vu~x=7q76- g-Khx Ra][-*{+|q~%b?82HYSYO_sACtNÇ9rY3KΦGLyzވ17ETm]V$wq BǪ ͅh\[` gKeaU25l`XVȣY(X=(*p+VЫHX~p622ӧOGѵkW9_MGѮCE˖-EzSLAR@`prrQV}$f[o٧OwZ ph"P1c@G}/*U@^Sѣ?gy IDATfZb\5G)H=v-`Y`8 y u-q}ǧn'=g'a$=Ilh5PgVll,&O>Xf 5:蜠Glر#t:?զ|(XZ8;<30γ!8-N ëf# /Ld#g ?spw}fXV0gΚ/]gK.-BӦMZ\Bk?aaa7ob*G`OEZ7E- @RfL7Μ9#6Y.bY(p+w@F.ö7R1(5, ߂mr8{%'7 GRb 5ՠA4nǏnj3:SRRD>_lܺYtiIW5IU g͑u!rYоJ=|10  gKƥaU25l`XVШY0X=(l8k(%9;{ljPg)Z-k"55UDQ8qHC啣8oEBB?Ԭ,رc""7##9pVGJi@Pn]~ .d8]Vag 1 MHτMêH}$prJY 8 Fxẃo{>#əeK*~6F\A"gMufm޼Y4PotPW_}%KeY/^jS⇶S} gө%t) M&p$"<0f@aق@(Yv#Ƀ k=r֭['o)Çq|ݻN:?ᬙnM91?*2'g&ICƭxeՅU-gm5h{ ֥0У-f>0U?CN?cC),:(uԩy4VDoϺ@QJMUtSh""L9guᬱO'wUqC5}r +yg SsU#u}f"P<8H\w#6{FiYzoYaXV`J gKnZ @aY}7Neg)… iii9px !8cZJ ωU@ b;0ȥG~) "i$''cXt)ʕ+'R8p+~ WVlYe 9Kok{PH|M^9r6$̿r\*,8k3R(rH{CiM *T˦Q>S詀{O ʻM yV.M+;J`fH SaTE {8 #5da8$v<n[~`zܽyfNƭ[ē䟦pW&cXV*Pp6 לNye4v"f Kj~e!2*w6aMxez)pV/3+Ph |9ahiACU5^A¦"5e g QǰS!ޙ3ZX.A@6Ovl=)5Y>[Iw<媊 "i)́VF*hUJ4'X:]ЫPGUoߗ =`nj R۷PJ5fZUQʑ4ˍ7c]vR:-;tPPo4 8Kb1b TgٳgATր^~ 9KTۀTuΒMZr-+g;YV`U…QWbU}h)#aNd3NOi@wO,K:kOuT:+VŢh3wFGH%k.U)R^;lUC5<>e+cߚ0Djng47hE52pe|r1WM,W$1Nk#<;2)kn"O}a'k# $An|3CΚᦱ%R8sՄzimJ5Ԯ)l-J\z ݙ!Vx 1;sH`)=2`ۛRT68th4`Yh; 8TM`.mpu=,cs[P-V*i|) )AG@Rj&p0p}KC %֐>F2RJQU4ER z" KU%I)o-!hժ( Ι3Æ &8_~EDkn)w-Ejk΀|(jWFYJХK3TЖFi m(`|r~"+ +Ppa~..:f=AO0]O?y[ðݻ9݄Op*&3qY,wo smapuhiy$D9PAՏ(_#ީKg0$sC"&FQW\ mR!8 77#ca"C5oEp9{1 zuaX}MxÀG8Ԯ_f?Y.v`Y#&Xb92@iM \]'Z"g  P, lp;XLO)ٟPh~@]% =It=oM]h[Q,86[*LJz!3e&g ݻ~(E-22RhUoӧOZQbʔ)Q*H)(YzM%JVPPcTR $JŋѣGt ԗrpQ.E+ Q[Դib;+ C…Ϡu JϜBOAOTAD_78f#1)ZKg.CjA)P]y5G`qT "ӳK  ΆAή|=.oMC|~1F;gSϊV/H6 wz#QxEN]Z_7 v֧ͪ,= ж:AMjTW,*ݽaXV4 05l07Κ X|(V.g `XV( *ŃhorZWXYlζ0g [9=nVoC? [jI 5pX)yD4ϱ0D4oo+Ak&8`/Ay2U9vDnu0|:o=]J$zbo'$Dت[Gdx Mi[ w0Y"H6"O&\ EHk8[b`o5%496)X/`e<^gcF*9`R~A[cZ roQO gXV@^|u)p\9[rW +P4(d8K M,tjUMRA .bDD5=C X5LcjLjM؞b~>= 9ۖUރ8,őO:9_Z^\->rڦ`/R2kz{by*p9+3^y}p:rƶ|8#V\DdfP)` 8[ +  }HJ1FƘm+ %Y‡%Y}^)p춌fXV`X#*/c8kD_)}%Ӱ+ VvkyaPTp?b&+ + KNk`,%\Z=dXV(^ 0-^ɫ1 gM,0gXV`X""-&qIde+  g`PbqWV`XV(6 0-6[B+w`XV`YƊ gXV`XV@ gKup5`XVh(ph{a& 05b7YV`XV 05E"=+ @1Tl1T^`8k:m2+ nG@ݍWr5܀^d` 6}Mr'.`a26+>Dg5,TfıXw"eױ:hf.RP)(ms%Dv g ǰ+ +` 05םc E";O +`#} ):)2mHQ@*6"Cs ftzUa dxzv TQP)HMs"K>p41L5L7 + Ya%S%syլ+ 냁^ Yu寀ۤvՁ3Tlo̬yqͤ*W?7bvMaSn2DfcΚƱ۬+ Ys9P0g8^{Mn3gD@@7n O?ÀPV-asbXV8+ڂn UG&YhcJ3{>6:}bvMaSns" YCT31 gtmV`XsUᬹ]( }wC`ٲe(SVM_~A ^~s;;;#66ĦM0c j+ Y%8{q :y}j()5+OG`k~u!] 쳴 ""`W}۸_Eg쀦SJ$ t pY]5bhC*ퟄ  HpeZVM7aHwKŞְ(#fɺ,x%WXe8TMͱyu|rf+:25Vq7p0`XV)pmS( 8{|(;#.]+\~pѦM_^qơnݺ*Q~M4-[PreL4 }oݺVGn/_Ɨ_~'rv޽ذa &̟8܁`X@6Г}q)u'!_U ltl 3>y[a;U:z5{rՁV3oɛ*[fo`y+uR_dd!e5XY&*ϑg7Pr^fRT*ㄳ\|̥6oVA?p%S+  0嫁C€^hh(͛oK*c KFFFb߿?v튭[",,,8~ӦMСCѲeK̝;W)S|xb899%7wLL (2Ɲ;wrR'<}TN.Zvvv3f _}+ N/&*"+ Wc`PLl :YAѱXmL,.ǐi(Sٹ `.x, ERgV]_.ocZP 0ī><+ڸahpCjf:~ߌWr?W۴ b8kZ}:+ +Y$X=(,8K.R)TXXXxٺuk9Ki~W=?͛71|ZRO?VE- @[flrr2 +V rym:>~;"qGV`:72Vٲ=jVT 8q 7:{t;:F*نgT. UΦ?Bƍ8uVC[;|T:W"Q\UrpCȃPuCA֋,a[? p%S+ RJ/^tAAO1tիW 4()0-l$)Pptz*.\z ͛7Kz]"ggϞ-@-5,Ab֮]+1Dmĉ"WrshUV 8+Wرc"*R:Y}K( @qQ@G8KQ X~l?>V9{nuCYk*g]O7rWp/E{.v]@M#ւe%{uI5UƌGyjMgW % ן#g/KZ/ UINN3zhL<9OJEU_OҥQJQ S l)2L{1נZ+ 8~8.Ա",?Ո9ЭXx]<ɼsNeQQQ D_>>?vg(l8[(p"f߿/$(;r֭['"p)ÇE1E,ق\ <`Jۏb ϊi)rXYJ#}UobL_XY_b]%O>6ϱ 82*_uL$t 736~aeaKwPk2C}(ki *XSaءyu?>p6- x^p IDAT(*+1ƀPKoDPr)/Sٗg gMymV0DsaΜ9b(ꡚ=ƨYYY >> @d,Hc8[xlSO"@_8)_pv׮];\g?~,"k)?-Y %B+@ d}.MiXu(fgmGkcQqߌo2JQgk'kb}luG)zRߎeTl8~Ȉypq7m6+ჀY >U7bp-uۡ>O+b8se"VgT7RTRLF<}KJJBFDkkk>}GRY< g7n(j%P1ݻ>G*"gi>B߾}AYW_ErGaj[ܺଡFrk6/մowyMVZaU:uP5/)+ (@7w?:|7@ZpR|עH}Ï .6lIA EdCYmgǶ.أ)C]O?+K)b  $agJJ |meV"x \ wݹ}͙*6p'o_gX@F}/?g)==hN|^3f ~?Zh!R|5kրrR_e˖AUXR%ݻSZY@A=&8pڱcΞ= ڊʭZj2S~=1m G4WEj2Zհ4hۻwQ+eMƽ+ ]&tjt6ٮo#'MG3(lA%Js%jx+ 9ᬐ 6DYJK$y+!bU ̓r$e*;$u )]) ds\[/sü󃳺i 'AX&] 2XǜTȎ9RD*8y򤀶ʍ =9EЖZJJ ~mQR5 _g)R_)J"9KF(gz\@QoAg墵rն.ɊʠV$G/gO֠m^}S9K$v%MQjۇ"i:HgL.k\CO1zYH;A7jNUV11AHW^=+WG͉U9K_k 8KQϟ &ڊ*^9!. j[y)rVӾO?L R43E{ߵ@RnHS^vpttIJeCg)Ӕ\tCR3ڊS: h !QXz9.o,n: S\0ZQ9]ZLߓg6No{FrbbV`Tav4<}@8؋ɷtI==*@#YۢOg*TmSn/2q<29 E;cG4u%= k rjiK?f gV_OI=@U^kC(S@Ŀ2` 3-ok}e\I  +ހ7Ymc<:UfKs FH|TS9ct"HCg)ҒM#R' ˗]v#n $*R(Ig)Z`_~)k)b,*rV[ZMimڴ]5D^zH j[Ae|}9giϩxEI ]<`Jtc' & G ٳANſf=eٳ3trcQۼg܊SfcE%>'`v Kpv5 Y:51r7OfY*+ + MzJԡ-KE%,ޫj)YK[ɒMjp~THvk)rcjm@rfzl%G}h`ƍ=N*eS%E͎7NT&J㒓Qn]DtEpKJyc±W 6mKi( S4mhKkh-}[ܺଡFmk !d[Ӿݿ?R-AFBjiorcC+P"Kcǎoh:WTR=7Q8KaI%>[70i|{%ĒKr-pFS0I VMMyȥf+^mp*X`X&۳g"v"{RRl˘rZv8b!\z4q;5M1nSUtڃU}/!٥1F͜e֯fg\&~} g;+ @1T}ӏ@F -iwj{Ia/^TkP*Dj|*PEu8k[B^fJs W)Omv-'7rR;H/ERظu9ƻM,l+ +`6 P-@,(I8~gLT'u},<1|̌ b-y4_ClVh@\0>~ G}aҼ6s&ִ:w`g|٘INc(t6C0{&XIpdiGglc%m>25bOYV`XVx 5%]rRXx k.)@P4 +_ @V:u i`Vv@)@­u pnpVn :$XL@Y,y}pV`XV@$Z5D(lnk7 ٛMD>(o @Kkpi ƭr9Ac/-1)|>3 C1|Oa}a*7̜hUS0/}^S89&]ꃥOiOufq9^ b"V5̀\pPV`XV0[Κ8BdXV( Q8Ks%#I<{n`J~l$"*g"jt!C gƩٸ1Ug5'8Ea n3gsy֪XDpvPdKf8ҤXV`XV)pm]a8kj>+ +@"Ut 9-R>v0= SŔy98|(VѴ朕#nl̹NR'g%_3)ml=̓HA` YupVb7 g.)dXV`X3Pl\d8k,%+ +Eɸj~Nh9 Ʒ[RA03 >LvtlRyc@3n58KEDA= 5x\sk^vњׯ%Q>jq_V`XV(. 0-.;: waXV`@р[[bL@Qi@FY I%`+Pp\>|{\=b*V(2 8\@F-EfLYk3+ J 0ˁCg#c9ܕ`eF2  8 dd2XV XZmsa8kRŋqEk?V`Xbbż@c*Ph` 3͘d[+` ([Uħ@F9.}fXR΀cYڈBl!S+ dΖ@Qǿ(r[R?P`[TWń׶OsY5=c27eu4mFM?Req"gEQ @@-ZI7bgk@13-um˻JSߎٗ&5O +  g:`PٝoIXw- ?:z3:\ }U=.H DnP- [a٫=9?Mxo(>]ӵ.b㛱l7eq5E[jz'Td|dGX6 BR@ꀟ'p",Вf^)=P-p좊uo1wBNLVzUm2ʶp,XY/p3J@:1g)H@KƈpvΝ8~80c uk{`?(}hh(n߾޽{( +`6 05bGE g 9MWv&}e7P!xp(\}Gr[PvH'I=pbA}K€FK4Em WwX4h90p}]4Je=z4 #aʢ?\1n@Ah],Q>U'd/0|P{-Tlt<>-oVh!e.ŗl`@T gM)gpð]z  ȶ xQX`x "::ÛoӜYYY3gN8KqNW\ի{bŊ S0eL&ԡYD.+ M%<UkG5܁[@971zg_ ]&nN߾+S4P#}lh]K),?+S-Ồo>Fڹ=VZ7x 1gh͝~ MaGe~BGZQ h5-jd3aiXte%W*7c2ob+i&<O5ȣOAbC@e7 P{wcL);'nEgd`ƶu֥mh\v[uɆb3fl[Hhc⇐]ߦ|]j*/~tD p7֝=kKK۶K$r+:܈}ϫo݆o)sD Oy=[m=۲@YJn3Ul=- rMyuԙk_уĄf9k!}I? ("gnj2Zq7H*Ke<BM !"ҵg]'@9={w4'JsQ1a9N@)i-?JQj+PlY92ꫯr xcݼy3._LxyyaB j4]?)J6]r ߿^:J.9u V`Xٗ7f 8m Dl"dG6NW[X55_\',zOgk {_3v&EьT Y~߼x=oua[FF/dKWOkHi <𔥲 w=[!`&X^vu:7u[Ꮠ '7Rv_Gڡ܈:Va׵V]-zAٷ*$ (늫 w1J<|)Ѩ/< |hO)'@]ŧ@ĿvF~Ƹ8n:888aÆS5U,Xj6m cLƍ9iU?gSSSdpvvӘh-Z}Õ+WF {B}}yFk,GD5G^l`XV 05l*Pଢ;}|߳Trdf*,(g fPx%A-KqVu)X1'To#=yH(Ezuר#+{7%PHyyOst##984 {yRT8LHOE7]򘡵̣_]lfb*_~˱(zg۳7a N9/Y2agiɱwcj`o#8Z2Xٹ`Ma8 }Thdia=޻6ݺlzF>߾v ;1vhQD/PZ )Xq<~re``Zsvoƃx+75ωw,K#}xUtpq,߸-_}(]\PV_M;ЍpdBh[[l ; ven([&7:{ake6GrZz8yrAq q)hXi-Oil:|ءO@6KG;[ w ݲX[k|4!?)%WO &?eଳM9T-*пTѭZSW{A:G5ΖCC +)AԨTUD$lU-  IDATQ}V)"W[@@-\4CqWU *Zk>4'dqdA^4[]v-z)"Hvjr8K) N>=K0~ZHp6228)bg׬Yg RWUnb}]'g ׮][YEg|wИ"QZJ#x[bXVx 0}j\f@q?(Ɠ'hTY `BO)Zo쭚g=(R(*\u'@8Up6xOCvIoјV#_ׁ6Mmv@*vrQ>q5Pq98D*uMhR[t[^3$YWDyz&sz FR3s]*_ZYNEhm[[cPJ3P(GxA ܋gcjxν`kU~ԩRYʡ~oV6vBZXvt?{@@ZˢC{%ڽN}%Lĉi(Nûm;JiJeԾ+#"4S8K<:e?ꜭpvɑNvTAD"k;33+9|=\cr3&1ˎ`ZB6"g9w`wU\`t={ =_-1rVSK,8~~Wp!ZV GXuSp,m%$݉uɎ'& 8%創.d?I@[+m#TET$,!Sto_Ed+5J|}ޕF_%߿~zN/~ٳuVܿ_D:*TƍŜYʋeL0}guV3FV8P͚5ˉE/p"u!p6y[l²d6AhP /oua&<ۋk1v,b8 P^Y а'¢#qVpYEDg߾]+cɺI|бMLIA2rA5b+/_9.w 7wX.bb{rA-IpIyA̍i!6I@YZ< %"PG5>(E>QoJzFwb4?-k0p~|"R9PrAB(Y9*1ڷR2R4Bpl!R>X#Nw_]l{S۪ &MXΕ:TM>PfI.bBsuS4pl.p XJ4Gʀ'EfKͭ%0Dż/U|xب̐WYL%XJTQ} 6 NNN =_w ;x~mٲ%Zj "rK\ 8MMp6==]^ѣGm۶QHy@k&0MpU@Nm()-AjWWWguY!cXV` _RO<1TL{T|y,3%JO]Y ]<: wKJSD׫rEVLg_WN~ >Ҹ]^8iRQjg{g^句yԴ!Rh XE,y,Jp ,,Di[VJsdboEX.~ur($8խIö5f O8{E ByyN8gRҟWIV9:CV,>};wgԧP`WIJw)[xz@ `y+#/5:Z,X|9:thRUof1q R$,=?b)EΫg٤ r~%c$&&`T"٠kjr䷾#G=iooo>}DzCtu۹+ @)p癋% *~ ߔ1ɼټ iC"`i;L(1,EU=P,MA*=FDMvk&Um1]J˦ (dL/=Y..JS }]#GZJPi ( oJB[8G0x%7ZE]}lƽD޾yٚe+cG̿6gL*Q o88s<177')T5.1YmjcO?P.Wg;{Arzq /iF XT^ I%x+$JheOI_ZiI%+ŠR;iVXifXIJ-,4C L460 0<= 3znb%{SS77f}G>|]y=#}2z&e׬0}j?=ڟbJ0?j~dq>29{Y]v,ސkj֣L6WԼehX)Z-5?A:K!%m k0ߊp~>޲1MZo{~E Ѻy>޼JJ6F3}'0KUP 9F݇ZS{6ăkV5z%[턝%k2][D@D@j?? uU*Xgc@㐖Ǘnd^ErYʍ71`4pUTl- w\h(sg֍mwpp}4j,.hX΀+h,Ã{o8s%Y 1ۺ/,mpp|wilŪZ*՘_>;wl6x}[9,7چs_WCwHA1?qg]gĔ֥Wn2͍R\r6QcLϬ[UW (aσL={˶uXݷ(9rlͿXuǽ"X_tZ"eLJuIY֖uS5ʷ=Vnr2_cXM59_&?zQr֏&C@>ֺKrQ\VO9p%d[(UuJ*=돍M[XXJwՃŽZE5gr֭~P^2A&{*ʜL՜L_7N<|((gׇ|mKlٽ {wij#˼sX(.1Xqq;9[!g ?~2g.(" "P HKrMexi2/e "X`|u}{Ptׁ=wVt=[$oxM&ai9zZX>S2Șk"z7Й*,6_lY^r g/N#ۍʲ-NjnY?۶ldvj֝.u;ٟ}lC^V=!ezu?`Jw\pU N.z@r}])S>zg |w p lewkF該\7h" " "Pe$g :oenҊ]Z.+Ỳm+oOkKST?J|nƾ6.*?W,6_lag% a,`5Qcwm,mOWz>;f'Kw{n4S? w{pz -zz֧C Z@v8_Te'WU?" " "PG HщװK *t*C@IG*VGB.¾Cv~/֖evqt3: *C˾_`Rd|cnvLԁzah+|՗79 ;oo(޺@97ܡO:w>RZ.@GNX\_EvK|wu=6=qKKن}v9{Xr6&X%gE@D@Dr$g+KG2.g YٕZ!GSS%к{5P+2HK!6[75T!Ųx{pf'W@) ng͚Y' ˾U߁0  1J¤(FYT7" " "Y8ZJ ,eK&;N%"6μٹnE@Dt= l'$gdk" " @@rfA1 g ﷭/{j .,"P_iwe/~Hu9 ܤ4Ss2f%gb}o8p䬛tX$P[lJD@D@D_HLTCY$gu7iuz5x7 Tu3&&" " " lmEc5!g-q:QD@D@D@j-e+To[oVC5E@D@D@DJ x-g W_!bBhDb3$Lǚ"È'ZP" ~XFlY)̘ 5A] k30{y>J0@AV E@lʜSTl%`PlJ/u5'rM{a|Xtw[%0) sv.ImW "elwf%bQD$F"e*ALCHL$d#lDK1Qˏ5(v_4f%by$$cÜD BԘd^$l蛂Jס~@@r&A!=Y"(" " "ZlUB]kE9 q{0xXMA-Hޜ)bK;57VbKsUo52YlG?ry睇[nM4z >lѣXh>c޽͚5C^p 7 4nXTT[o>|HJJ?2HII97qTw}ya۶m8|0ڵkaÆ!::2ݔ;>v1Zy<(" ^xoiӦiӦ^vT,edغ&"yx)=iLqP+{BiPSQ2a8%YcٞP1e 2 }F2siCF:Qrkہ%g_xhŒ_?387tS^Ú5k0ft{5w܉'xׯX*+g;ѣGcܹU;~5jziꫯnHdӿaĬcD@Dwux׍2e N>dׁмysO.;C9q h^0_n_*GQl[ 6gLE>-llXvN"sJ9:@vZ"mBt\*F[j*trM9;rHpUW&]SD@D@D}>y~g6o.։^# YfL֨m$?RR]tEL{iii[l)9"6JWe2v„ eu\K3u Cr@X% ravf6BwǠ0'9]rYsҐ0&9LɋZbLjUo֛{F 9ˇ"6~}зo_\~/[ VԩS΅2-W˙-^㛗CEkj)R1uqefi^Q,W$QQ?h8k$ IDATQpMf(Œ~?|pfuɓiӦ8x2d8~7řڲk0{sz~]u,sk׮mߘٺdL8ȹ'|\s)AL:;d|,:mؾ};%gݹ5*+gy<3WaŸ4,9[PP`D>h3fK.ӧ[JgLˬ-no&=\DEE SN9 ?]wem`q7s <ٳVyݹlJo^u." ^Ž_YK.1_wǎdl<YOCy"=@ߎX?p9p|C0`Sĥ%L2,Arتg Xr6a0<#cuhP>&t ZwExa"|7.(9[?(*n݊^z|2}{^|ŲRSWa c}?8.\h[\NuY0i+[#d)94n؜j)ksl/0٠|63Nz+g);YAXv?#Cm9J[Ⲛ@vQ씿o/BOzNdKk׮-);;,'ቜug^=wԙ" "PX _Y]w u=C9g˲!;!## a<$L_"+0>m,ߓ)9UI ,yx"hPLJd~SZ)lKf͚e-9[>,sv93=0t8) YZ㡨ppq\< n{ĨՏ!9{3XaC97o6;͞='r֝8)Z7|3:ud^n9k՜3X^mҍCW>ݻ<5ϱ|ϩ793gYz饗%gݹm4e YfJS[+()Qm3g)mw5j{4o3g4ٯڲrNL&,=~+3>l#g|k.vfz"g+˹kD" L //ϼo:k\#hY_\Z}@T9\VC=a>̲FWlly~S|u|ʙ}𴽖䬳e[rc>?,1ָb&13V|C=묳\~'''YMU.5+@"ਬ%]ABL\w%u n]cų(9{W1+<Κ}YZfӽ7T$]X*m\zVSrf&%YY*>11Y֊3[NNCKaHVJϔ|ήN׳?Y\gČC9q%gyPYfZV,9YG[q9cE̬Yf6133KIkR>۰ayfc&:x*g;5ޏ@"w:jL 䬷u~@D9P@,ʶk')w|255Cm,j~>9l)3/&MdB;;&-MXWzC(30(yٸile*/" "PlxV<-<\zrMUW=_ENr!IAe|Np'LFκlYHa\ҙR,Pr+E)H[/e&yǎ9=eJI(g||\0sNK&ήN׳6E,Wh8?Cّrv&Ӗ4\w$gY">>HnnkP4,id%)[aX(Zk=0ȍϺg+X8_L^g`㴗cd]fZxZ[D@!d/zq|UҀ}Kz3S:7 Fr?X׊ٷ|r|t{"go7r9ZŇ>>ZܸK(^l`fXr@1u?-#O?-95]l,du'7J7t7/)c깷`ܚ{Ҋ҉ ${/wY٣7r֝8T̴m|a7/60$$lVgװ ;w.wi7䤘j4ָL47nv$gg]>2B8N['w3ɗœfs))b9NdK›D~W5}O~B kSL1ٵرc[o{Xk׻F#"P0t {e"ߧܘ9&9+' VZČJZl>TZ>,9c,w,3le`Drck9`QـE@Dl&'nCvو:-9qe8pГ-{<|&`i#.gF#r$=}1sjYQQ&W`q<7o↮%g/omJ#p?e/mռ'e@2,$_I=`rygc-b^67GrEV EaQ){\Y&^ 21Sr͛o*9S,97Y~,D3Kg[e&l5%D@D@&`#μy}ԫ'>>7}ה;Nr1Ô_ܻ*UQxjLe,g.]{j" "PWp%fm K@Y_e&)f)&mS,ϵ]M؜՜kemo[ր6ҪInvioᆛ;e|\'mV~$g+KLNj@>ֺrB!8 9kaGD@D@D@DuSUlehX&p3=l oiG ./=s؇;Wy 38lh 9Ӥ @e?,XLlG0XnXUԯ@X:<59#зo(95Bu " " "  Hƨ$gk" " ";wo›?|z?/zꂆ^rm:PD@D@D@*E@rRtpm# 9[fT UAU} 9NӯI@rMP:LD@D@DX X*3~}~d>NlΜNI[ 'DZM[Sk'_f^+9>$g}@urvݺuXx1gNN222?qѣƎ`?;v *VXGW^;аa*::GT۴對}hWh$g§/l3P" " " ".a{dq* _a}!#b'N;b߾}Fv]vQ_sŤIMMMEqN|q 22}w}v,]0c۵kz-u]U~m]@D@D@ƱR/26YA1zBD@D@D@*G laa!|I|w ŭފ;V"((_|8 #?4i^{ͼ?9\rinJy-^?0n8SN97nh_[n{exgq5 **rѮ֭[d#O?t\{8餓L~->#if^k޼+V$g{=&c+đ#GSOd]HHnj\wŦMqgy&,c7^@%F֬Ŧ^׳%.>SAJ|UWw޼yF:Q?J֙=xaH ʘ)Ewm$,_{1|p3fò_s*WFvv6 ÓR2m&9::|)!l[II ϟ޽{D@D@D!QX n }ڭc$91:XHֆYD@D@D@Y|}GMIJTJF,9@)K/!<<EEE?q7CM1JAj.rvm'LIqqd.#3l| 6dee \Q5"gE]Te (̙Sn,A@J>f *yyyF7Js dvuיX/ٳļD@D@D!Y"P=$g"" " "P7 ,>|,f|xǰaS̐exd'e :bĈr;q{M7`] T}W尣)C=dNYlVג˗/7nvl2g',Z\\%Ν;Mp\\v؁O)gy_ 4~(|A{ݲe6eofh°eiY*PD@j5=s7YE'" " "MξhРX[v{n2,]vڙ\6OIK (t25Ng̘a>ˉXDX+^|.g)۶m[3yY% >(p)MWZesc,f_7^Fv,l],66ְecJY W[fފ?SL1>vO,yGddČ%&" "  =f`j$gk" " " ULlg[811g}#J_ °4i:%ǡ'4K aLjj,+S}`|pqL$82b.ߕ5_4dw>[\df#-!Q) ,k15'–`Qx$ĄֺIր!" " " UG@rتgAK9[T"6~ UX81=;##|!`ήA- 3g:GR6&dOJg!eZ6"-JG(L&_9k'gQ.®`LHl䬻tTl EK9 \7 >aA%ؕEN?VmX{,p2gʼ=8Qc@DNdNGf^0b&ymE@HhĎ>mGr%0+EÑʛ[$g|k" " " K@rzyj" " " Gk9!D梕ۅ E *f0D,޹$vFw+7Q{H@rCp:MD@D@D@ 9$"" " "P D*s0='b`HLztTD@r"Bz]D@D@DrOH.# 9[ulճ@G}!!!> @r'I ԙS" " " @@r6fuG?Owygg͚e˖7@ x_~ypVԩS~@jj*} 9$&&"%%\N}͛m۶h׮ hmz±h X~Νf͚-̃O!3:A6tڴihڴO-9$P H)n@ 9T͊'|AA=SN0EfeeaŊxˁnv5 ={4ꫯn ٭=֩S'$g=t;(dWnSL'l:p7oNWN Nt>_D@D@D H%ȑ#qE7}OrʲYM~-**BDDƏVZK#qwލΝ;{)[gaطozqơQFNϡ{,}뭷ФIšGZhIJJ6nC`c̘1&cepnnp{C@_D@D@D =xL@Z6~w#FqGq4tP\|e>|8^~e#UiӦoĐ!CmauF}gg 8.O뮻UF62㈱2 B+((0`\̘1ӧOl߾ݔ0h #6׭[gJNXf ,YbBLk,IXw}Ur: ;%dஜt9ܲҥKaۇwosETT'0+q8ݻYWcVκ< UK5G/š.}wǎ\ iӹO@r6Pc(g\n@-uVKga䬭1<_42^w?9?aV쏯( b޽F>Z|kf'3J6lh,j)sL?X6fzxWMF6W`ROy'x!w8[#d)94nfF!8((o&#Us֕&M2s2ٮOdvMk`o/BÞ^g(͕t(u6& V6;c{^@`p_~IȺ6Yo & 9ӧE@D@D@YJ$J5<}.dκR r|.e 9x};5@PZr\B,SEcV,,e 13;;,֚WXo3U8v)( ܟ 3)i33 m3))Q1%Yw}S~QdSN3Ui2s9KͬYf6`]u3NU혼ɜuu?8+kj*s/[B|⿹|?uoEE$gv@79k-@t'rɺ%E󼑳0[k]uUFƲ)E&cLYJH.ŷeˌ%[nź,Տe/W)9Yo%MvifJLPUWru[J1DǎaΝxGYʌb,,X`j֭ qwy'{17%-K9KG6Y<ٲ 05gqf@ŸFiQ9ak.;+~iaeZ5gVrp6۲κ39jѽo QD p˴GW% طlL 3WTD@D@D aW5_nѵFWd2j,!ljT 86̍!">~D1{y/E/X%o|$g}IS}ـ2," " "@Qβ38$kW_}Hz2ٜy駛㼕eÆ 3 ,qƙ52٧k׮`Z`"6)0&E)"K\e`YgzlM (gB$g$k H# 9[ulճ@ 9[;Q䬇tA@r H:DD@D@DNӯK# 9[ulճ@ 9[;Q䬇tA@r H:DD@D@DNӯK# 9[ulճ@ 9[;Q䬇tA@r H:DD@D@DNӯK# 9[ulճ@ 9[;Q䬇tA Puxb$&&1 hܸ1z聱c"88uƱcꫯbŊ8z(z; 6O:=LrBX n& W$g=Fk09[:dDĉѱcG۷HΝ;.ׯܹs1i$#dSSSѿxܧMܯ_?s-O_\xڵkYd>e3f=uYS$g'" " "P-,,ēO>[qyʜC/gag&Mk#GK.1Sinz[n)`ܸqHKK)r;:ƍZl_5ufdm?gyLN>\sUv؁{qqqe9rO=&p hժrss7ߘc(1aÎYƛ6m2g>CnvkיgC֭[dsO?^{-N:餪@>E@D@DR$g+K6mF5"or“mۆYf'(C AJJ ~t<j#Eds= RJۄ#gΜ={Rs…ҥ~)q𩧞 WJ䫮\3BxU6,/6yd>m+\QRRb$wm~gO_rranX"̝5?|0?xk`H޽{j" " "P$gkzt% 9[uqZN,k>裦%*bFY.e{饗"矸(mqm0dիM={Oy`<æ,#k5]H}gqEUIY^әD_*-Z6mQMsʝWY9_~%ȚٳgJ9sr0N " " UM@r & 9ӣD@D@D@Y<|0X6`͚5ͦS6l0 9K)jekR1sٲ̾1bDywhs*] T}W尣)9:-[ʌ_ukX|)eUќY |\upl▜駟  G۱YWFܹd|hѢekT+)" " ! 9[Z:uSo&4h֖ݿ?^Dٞ,kdSRHr. ˧~\[FUvS+XDN;4I .R糦*K߶m7Kmpi[oe69S*,c$֭[͑%'Of=3CuYY˿[L/VfFDD ;;ի,>E@D@j/ٝK2m!X}<݃@,AZll<\Zæ!BXD(Xa cl@\`Lp5l@9-" " "MݻPf͚ (S eβ믿n p>LkɲC&c<ƶQ~G(((0Pq-fx6oeZGkCHHQXjz2YsÔcm߾ݔko<@(Y"ªoK)M,1)`###`,gfsLk5i>IO u C͈waGIƧu!g-9[%;9g!/څI4 _sZu8?n'93E@D@D@Yfe%%d)" " "!lZJz_7EPl)BPqk]F#&.J9{\Z\}8-Q073ۊQ1{։E$'mi柧 rLb#H$$" rȞ=+;M@Rrr65c0OCdMŢ(Ď>FڴDMJ@d!e*o2x2Ӑk 4%-b`TLҐ䤁hYI1 m,zf#mJtaș3 0 c#8۲;]u%g`@% 9[kV/lR`_Ecj1re8Gw E l&d#:%QH>0y9HKBTJ"6"1'i͔9i:Ml !u IŠHȱn6Rs]HJ-0\C~K0*e$"ltį솔:!+7u}tCԵn$gڌk" " " I@r:iZ" " " H;9LΩKvN ؞:&{t!,+c6mfg$\k_T$gH#g^2)OLQ軙>Mka&aL$XJ϶ҵd'r2cQn> (N# 9pvq@ fY? " " "Pk HکD@D@D@|D 9[0}'4DQ 薳cm[:Ée6kj SB'df#-!Qj~28KnjΖl-FV,gbk Rre 9ĥ-0j`to4$dYgRG7D]Fr͸+" " "P$g%" " "1/a:V96K$tC $r`D'$"~BʴlD#6[ Qt.l"18scQ$CrR0E>VNG>Hֺy͔d蓒N9)ZK,@Va4&%Ţq}d i_1K$(ZK@rN&" " "#䕈>a'T,BaMܠQ8\#ggcUaS ሉRmK3{f`[!FO[^ٙ9QaԘ+\07{JB;ap,F3YV9(aضiF@RDVtd#!(yg.w @9i Rdžau ݰq_r19䬏nH:2D@D@D@D5/,Pvf/؈=%%b騤fFLB$gkj`" " " >"Q FjlׅE@D@D@:0W$g§lϠgYb1PuX$gk@`H\x +ZptH% 9[{V#y5?@D@D@D H(*& 9[ŀս@& 9[_ptH% 9[{V#y5?@D@D@D H(*& 9[ŀս@& 9[_ptH% 9[{V#y5?@D@D@D H(*& 9[ŀս@& 9[_ZG 33}qd|>NlΜ0Kx1ݻnݺoDXXXHIIqobqј;w(󑞞oFN<M YہDYgaر8묳";;K.p^r֣[R'AB_E֭1;e|8|08͛ѓC$g§lϠg<;VTTqƙ̄t֬Yc>r;t`D J{}[oe2*УG󫯾2^tEی7oܹ3瞲\Rh"4d[l1ײ[f/?dsL?~޽{a…mg}w((%zr+&llaa!z!#g"›&9 =$g~ 5?&rK)(~;ƌSFK/Ç/ldɓiӦf)lauF)Y;02rپ=zwy- akfL>f̘a5w,lX '''.X<2馛0p@ݻ5l3Nٳg;k1xw̜gN?ttڵ,%t IDATWu5UE*|Bj\r n;aÆgo7tn )D@D@D@?Y.çc-LfCnݺG~b֟P1<_42^w?9Αȴ?8ie em꒳+W4._lo}ɈOX2[28氢k뎜=L]f#7^-ڶ_W>)yb;mVwEE@De"W$8k\|$g}AQ},ـ:." " "MR],v8.0f7Z͛YwuX*\Ϻ\V]rY&(5fLm+E2e(黒V̊љ9(c677m,E-(dcINeǍXe XGpժU.,NL)2l,wE%ݑŶ\8vf.[sPk#gɉvj[cZuW;ud2W)(XuҤISN90ڹs{1ahSҲYOɹq2p&3;n Bgy)mq3m<ů%Yk^Yo~Xsk^ea+D)aq"ŋf]2enG>'tR99j>(™,i:kX\mSቀ ~oş櫒[rO&]a ᮫ٚ &g)t*O`?ڸm۶po;qPJqY7%mc&'eucǎFYLf͚{FBZL(P_{57kӦK9K˹e,7ܰf*^)P)>ɂ704jW_}3acY _o6'cfiL1;)y3:ɔf )S(E]Tn /%0kR\a4fy`LRw,/l=Xpc- o*s [!q,3we"sZ1T46mjD<},xnk" 5WH>ϳ@a欯䬯H$ 9ӦE@D@D@Yb{G =~ʍFaD#싙VFκE3=YjTe6"wN9ϷEwjjjX@`+1/El:t0+I 87e XD@D@D e 9fdrѮ];ٯ_?C֑d+3"O7y+g+K f>ZYe6mڵKMr.Ͷ*" C`СebDr֗4W )S" " " DlS" " " uld 9Y" " " "Pu$gz$gk<֪QA<CIN8pU8ָ>$g=«D@D@D@D-naA" " " ul|z?YQ`O;1vv$g}YC1D@D@D@D5Y!~E{4WqO3lŌt@& 9[F |בmQ`O3lŌt@& 9[Fi\ǚ4O?$9SLD@D@D@*& 9[1#!" " "P T-X%AuW5ŀ۬5z7펉̓E@i" " " "S>ũD@D@D@j!قy\>#c=@NlXsB7֬i#b'% ea^rl߃"$,QGadtKpĒEKSj@r6 \'9[SD@D@D@D)@֭ŋX% hܸ1z聱c"8;00z9|s9r=[.c^߳gRRR+DKkVHD@D@<$࡜B]X5;N6FQP' $> Nb h46 a,OGB14 CxX5m:kc1ywbF@Edah$VȪ27k?Rfؿb0A*w_ZNڀ:Fo2؟c35B)gP( h]񓐜#5R?9 aٓ nE@rVw&g)<)0k,9rGO#)n?n-$n]+" " P~QbK6P៣?_sg">rgUڏEnŔ۶m۱{1QZjzMڎ1^q?D%Qpl.eUǶYr^mȴֈ&63qQi7ǒ>q'E#>:#1z60,}.!YP" " " "PMβs=gJ Plٲ,KPʲ1cN:0_~RRڷoC< 3LGa{I)o,YgyƌvZ#%)#mb"”mڴKY'NYz!ës&3վRξ;f4he˖zbef͚M/2~aQ;w\1Q5vCQ\4@PEXǪjfZ)U; @Q5ǠC50bp[FBj|4ɈNёQY8i~8 úa?9[=%q`js|& YLJb5}wHA10ߪ*BŭD@D@D@DMr`}mfJ0sRԖJUf˲jsZbxEkqyfI9?._lk֬12:e(ۺu,?l'|dښ,93kdk<@gϞfsf=MHNNȞ? -" " ,G}<ϬTWruRY`F2p1[r2V+}ul=E,K"p.G$>s nVY 8n5 /ছnB.]rc*#7e|X󖲘Xsٳ/6'gɊvfܞ?u՘KJl̔:u_;<'3nSSSM|<ŗ58#๜܆^Ajj;Ԯ2ǎLX7ݎu#"<֝AXϞW[۟4ݚ@EpZ"AxT z@75)TD#A7{8%sE`TZNAJшpqhYk;9 Bep"uf5ƨ1PUr6`E+g=\rCp&" " " ^49í(S)c)y%@0gv-Zd ,YҔ7ԩ!?#۶mk5W*f8^zeZ Mہ`=X.I;|lذHO>ϬYe!Ve |Z@.qS/" eK;Դ]s#1% a.Pqtuo5*|O>s-8{mǔ)j &" " " D@D@D@D'g .8~9(VFƄǀҥ%g}BT9>+])" " "$gsz% /2wQV6™^wB9"(s#$" " " nu .bAZ: 9@D@D@D@G@rl5@ 9[} <<@m:b`ߍ'OF |O0j)n+.'g_{5TRŧ 8p /ʔ)cqFDݾ}?n#FAТE 3͛`[х" "% _~ժUâE'.3b9s^zWHzON@r;E@D@D@l {ٲ9ٵkׂo\322РA=_~?… ooȑ#q|3gf2bYC5ٜ[gה,Y2ga}Vضn݊O?ׯɜu+V 99dHs=ϫj2g̘cٲe(_$z+Wn]#}Ylܸ[_>(Wkժ+98miMĕ#+#?nbGr壾Dwy'VZeD@D>\O؋tL0YIzCO}-O@r[0@gϞ5oF[nl+ CzFʵm6}?~ s8{̰b7|3bcch}l?i$%R'O4~SO=^z!""ˆo\늍 ˚k}/s!** ?:wl,(W_ ά˾8BtRp  3+W61sg#G8bbbLv%2&9\DO ?`vKiS_j" " " L 3bXn #()nѣGsD6'ǡX߲e {{Ȑ!9#:I IDATQeff37jט$gBpIOk<]ç%?slAbE@rXm#" " "`MRQQQ9j]L6ٳ}"g݉1۴iLF [:*k7|œ&1-b`,3Vn/3Q&E:lm"ʜ/j("Ko.7:j:u[TK)x'hr␏S&:ky'3'yMy#g݉0[lp%R$ 9(ȓuXY˗z|cƌ1Xt.M*R̺W<̋Y,аaCsHk뮜.\05g9d]fuP*3V+UdJKD~r2e8 *gɜY|,Yb2{Y6oYw2gz?Ԍ \,3L9R;n837kԒlVx" N i^JplY݈AM@r6_3@HlFc+=mE_5r.Fκyk;eɓMFo&M0x`#28)͛go޼9z\PY]ۍDe,}Yg8+k@(2uRlrZ+;zjL2 TذL6ZA,1k~`#FW\ᑜxx,a@''kɲ%<;Q~̠-[,z .hxM6q+AR`欯䬯HjK)h49Kl=7VN1U[Fκ Rhk矸t~Yfffĉ=BD@D@DXJΦ3 D ǰHnYL_3@*8 ]zDx SGS`^Rd!skYXzM3"օb9AVh#tu`f+,#YmAj\lo4 qëc}$550Z=X-R\D@D@D6FĎ; 6ofj&Mpmys?Ǒ#G>o[.2v2w\\r%6lErgO?mƠ޽{7zd)))8ziP  >a2Æàf-(RFRddW@F3hZTz` `A4," " "`&g){x@@rh"" " " n49˰ɲܷo9j۶m43g)lY|̖ees|ŊF.PR͛M(尣|}„ 9+3~ms\``#Fpswܻ,YW٪Yɐ r5|)ů*f[I&Q_h(vC _Y]%" "{g-D@rBPE@D@D@,G ,/Uɼ<}4}Q8==]ٚ5k|pn*"e.%bYs)3h)Ϝ9[oa֯e)[F 馛r `e˖R7e|UF`WR%G2+zРA˰xbSW8?9K=dYOuݗ58% 9# Hk" " " ~&hrԩSFQVTEj;Y,k.ZȔ,oЩS'C*o۶9dطd^'N0MK/u؟S˒ {1sQΟ?6l0^x&k}|(gyW UuJyʲ ySO=f{9qYv2g)VɣB FT3޽{\e~XjU΁`7j" " "P$g X5 LD@D@D49k6Ye$g=nŃlGBD@D@D 0 Hz/qS/"Y+bY@" " " "pY" " " "& 9ۯŋ䬟kxjkCD@D@D@D5Y!AM@r6_3Y?" " " ' 9k-! 9 =$gukClPo/" " "g~E@D@D@,O@r[xC@rz+" " "  HJ|IM7K׺E@D@D@D$gXX7P{G@r;~-" " " x$gTD@D@D@lmz1Y" " " "?ٙK4" " " "PD$g BD@D@Dx-UXj$ )dV)P"" 9[D5m` }P" " " œlWJD@D@Dw$g}R#Y7M!XeJ"il`샢($gjU" " " # 9;ɂ$g-i YD@D@D2$g-U TD@D@D IIIXz5^x#K$gg+1bZ@--I{ł pdggf͚ӧño>L:ӧO7sEEE!66O>$Ξ=xf?H~s_,gc\p+WڵkqqTXM6E~Pzueuơ~" "P ;Xx;8ydTP'˔ F bUV9-" " "`Vإc1b -Z7oތМ(0y9æOɒ%1p@4j(ݼ"q1.]?dѸqcdff+<3(U2w{"" "` UE1;qD\ve3gK/jA^Sg*~@& 9Ȼ^l|ٿDGGLQ[B2ereFFFСCiӦ]QoJ*([>|1cZj{{Gk:u!Ck)C&MXi޹~i3^9Y9ry3ްaC6nh޸_jY_l2/_FB{ k o6m`СF`;[+ϱpBoM|s?rH{1fd޽{ ~OnݺϺw*(&>\Oz؋tL0YIzCO}-O@r[0@|RroF[nر!믿bذa9T)( m6}h?~(Ν;`Ŋ` 7܀0A[re3}YJL I ʼ?C=dj1˔?`"i)'Yc?A%d}WA!~?8$&&l&jnX\l4̙3ଝ8qˆbK}Y SOW^@rr2[L4 )));v/nԮ]Z9LW^1<(mV2kqߏΝ;DvovM "  ~Xl]vm~ƿe~4ٳ8g'fFMP?7q BID@D@D@@ Y>zwܳgo|U^=#g5˖Wg?Α{}~qn˗ԩSFi-L9X(lق?Oͺ_O>de7lqL9ط~4.e$E_|a$K 0z|L sׯ_UVn:%,?&>Qr2N~2{}sN#d_rʙml6l_~i}U{VYlCղE@x'.OA5n{HΞƞX+Rh޽n8m?}9܂j.r190ge>*wstl0*" " "PMRQQ .8đݵksgu'^QSL}–~!JȚ{\Y Hfڷ-[H9K6dYƌѣGc۶m1m̙f?ݑpۍ5kB̠~39aJ0N6{r|fj{gkOxsc,?DpD@D4sd F߀9o~Sa[}nቜ-5kCD@D@D@DM2so1Z޲ XxxxN7o2g݉T).;>&’dV}c= hРArFZRNLZܑLf6L&wr$xُ9u]`,aK,1Jȃ#8]G}Ԝgv;kdmY6p+B#@8wϿK؞6z)HH܎Lh*ڣd\Ҩ\5""Z)ZJljr qh^]UpxûHNW֭+cg*p[P8e%RRLMpK.hḇ3yO8W& ;?|fW`m]F%5ۭTOHzBM}D@D@D@D=&gmyg-dP>e~Yw<̖;dMS N>^Xru00V-j˜41*4k-92:52Wln}/:8cn6}XcY,_CØˬTWr W5`Sҁfe.83xXr.2k'kX17YДGrֽqJD,5_4ؾg yuR.+ڋH\ {ߍ!me"鋁ui]W`&x``KA˾wy_2O7A۰lV 7U>) ]0[}v3eAsmMr6q'.o6+) [ ;hy:\vze= ND@D@DMR41m5Վ͋8dP>>~5jȹ9N :g"⮰,f6%%5ۧpe&1?a`6&&Q8q9²k׮&־mڴɌ˚dRn޼dvRSLv޹))4i3e~q9 LJ*ZV/kgW\RR~&[2j5z)7on}u7k憆wfOxȘ2g- XዀxLpG~h߷l'#99{āGqp^t9Iʨְlm9ݻIn741FvC}Z_1Vn^YZ޳~f\i[ax00־ٿٻ L)Hz2gFQ]Ple;aT>8-n#g_W;q D@r@t@Ysϙ5UjLNf߈}7,ڑ#G,Ӳe˚QvךU5 uv_K9Mg_T "Fw3'v>svK"fmjknJ-1_!ۖa5Wֆ&sײ7/lxJeJ>,$g &(g(" " "`!^HNZyr~K5HԜ]N ޔDV]sY5"uGae ]s&׫%*l?=JxOa;e^hY\O՜U欅nuǡJZ~ & 9D@D@D@@Yd5Xa'~,zХMsݲg2 U*aוvz,[mdRS5l[ub-^V?ZGq\ 4o.[Y@q{䬷_D@D@D@!" " "  x)gӆDQs0OЩooU)mNOGO5Qi8)W.Ph ^)Rޞ)b%ड़-`]vRVb_yB4A[quh ŨXl(N$gnj-" " "  P?hN@r'" " "P$gY+bY" " " "Y" " " "& 9ۯŋ䬟kxjkV~-}DEEeKҐ~ ʕC1|pTX.\z | OxxQti,o&žV@@ P0M@rk>`"`9=?;v,6l~H&Mnxøq㌐CNСCt>G}Gy!!!^A+ 8UVɓVn\qB׊@@ P0M@rk>`"hr6==/݋P 2-[-s[nQLlڴ 3|xkzh׮ʤ$uL֛o<@#GD||<*W|;}v3֭[ѴiS#13m Yf_̑=z@ll,x ԯ_>R6qĉ1c(H)m###9s&Zh;E1|r\s5Fpj _~S2.Zj!I|wwxw(G]Mr_7C=%J`ƍ'4%3%tBB>w{})Mq{q#h233͵dn^v?G͕eojj*tbb&`{zjT^7p՘&]'" " lPo/" " "g&gY3%(QQl\r%(e̙:u ##~"F1JAjnv :";v0sQ2Ö;Oyd#($)A)?mb"ulڦM5xw  `ٲe&YŔfm֬\/~dΝ;7O扜e+3b쨹78ocfR^{Fښ1]?- /" "PHR N@rCD@D@D@%hrqggge(ۇ۶m3 =I) Y6Ef2[ٳ9ֿb #n;Ԋb6ol2M)|m͚5&VQqmqݺuq%7[f={4 sfMHNNvꉜ%`殣6i$m_h[YYޏ5 d2g]Ɂh,M@rxVY"" " " "?&g.]jjӧOG5SʹʒǏ7ٔ<١<$\q뮻.*E,K"p.<>s nV=Kp5j^e#XYBs_ /Pr]l̔:uKL/efܲK!,#G2$f/?u8Aj?(Y;ʬA.ŋM]a{9믿qkFrzj+lr4@& 9[W= " " " EF S T9@v YE%K4 :udq>H˶mQk3HYĉ@,f8^zeZJKہ`=X.yI;|lذM`,Fr*gYd`^l[r5ez\x\ίF~m*UL^JoO?P2w5lGrmٲH^s4`;1]oz]D@D@l$gu/5ek" " " ~&hr6Y15@` }QTD@r@k$ 9ٶKzMD@D@DJ:uW" ?|1p@@rV& 9;$ Hk" " " ~& 9g^D@D@D$g-Z7$g" " " "pM@rVwHP E@D@D@L@rπ5 HZ~ oHzCO}E@D@D@D5Y!" " " "& 9ۯŋ䬟kxjkCD@D@D@D5Y!AM@r6_3Y?" " " ' 9k-! 9 =<*" " " AD@r66[K %jd("E^E!" " "P< H}ժD@D@D@|G@rw,5 HZpeHZf@-"60H>( I@rxV%" " ";c,H@rւE@D@D@,C@r2[@E@D@D@l״A@r60AQOs_*KdA4," " "`**" " "$^/BBB%3Řl1\-MD@D@D Hxq:g„ hڴ)뚘|w͛7*Ur+6GcEt=P+f͚5k`(USxޞNKƠ~" "`e;QfML<*Tr$g}QXUwNqXvu6YkJ*]| <ڈ#㏣QFk8p ॗ^B2eLwX`A@Yg ^k}8OD@FB_~Ajհh"#f'N. 8s .R%9>u:Yd;ŖġC`ӦMC/8ݸqy~j0c ԭ[׈sgСCؚ4i2`iZ2cۺu+>S_>'svڵ 4hG_n_bM=c8x𠉿}Xlʗ/QFy榟1mA|2f3,^̦OP5o7$g-Z@D9{Y,\yC7Zݺuug_1lذ%K4‘m۶9?۷/ϟocǎv_~ѣ>8l!w=g裏bܹ~򓅔Κ=qO>$jv,?`J$ܹ3N>3vA9+KpOƎ?= 9!!7|?ltszŊæILߴ}FIzCO}-O@r[0@<mwyLϞ=3gyU^=#g'ea_XG?u̢_|9N:e$}Naټ\2fΜ֭_|a$&E(e,E7,[oeJ łsO&g~m#JNҥK׼'՜eV-entt4>C|7&NTp<\fNj/~>^g5gm]\}͐2d_'WBB'5x≋|8gu lAhbG@rm$" " "@M۷24J9G͑ݵkɪ={O;qb4dKm-l9;rF\15`#y8쟀M2s0>--dJ(Qo&X~1u]g,3};fvލW^y%Gβ53im3٘9jw}ה4wPD@?`S/_4Y_P% 9k٭S" " "  hrO>1Y̔t5uk6os̈́ fκcf=R lV@eI NJgK>o/7lA9[{9K+W4ucY҂&g}tRSe XspÆ Frmۆ?f%l,s6}YW3F(n_) QD@ o.8j:u۠$g%& 9kS" " " N ,՗_~iWz2S+٤7r֝88ey՝wid,k2 \r#gYv&Uq>sYnjcj6lK,1٧ji1fV-;ܑ.\05g%g5kF1f]SĘ J*R,;]j1˔)r~rv޽Nݻ9 kfR >'" JOM7ǖ-ԭdF@r6vD'&gΒ\5o;qP1{G}$ KZV+0oެ3e'Ξ=k+V55>QA1۲eKAhY/~J_6Y_X# 9k-S" " " "rr|ܛRf͚ڵ;Hz2„ pW뼕CHchGijЖ-[dEڷkdabefT\ڍ\"51>Iae,G@rr[E@D@D@,D 嬅)T 9%:' 9CD@D@D@G@rl5@ 9[ꪫp=UVl{۞={(կJt=g |93\JݻwW^f>Wtc5@ P EA@EA]s @m|5k^|9ۣGW~}#vj(T<%e3@AJiKYՙ3gEرc-\|9#Z[j/HuԟqQ תU wygq,X`#eѣ}~kQn޼ 2c|{6SR,Yi(׭[琅ue #FiN͸șlW_Y Vl}Xke|;wnuQ>9?uK:E@D  Hk9$gu3JɌˍ7b߾}@m۶̞*E1Uf2`Xˆ%D M T[c&*P;O'L`0딱2:ǵIQP1bO7lX&2ĉF ?{Ys U8`܎D}\ѣGMQJÖ lrcq ,Oɹ9;i$#پkmbj0" 9Pۡ` la|" " " D ҥKAR-{i( I@rxV%" " ";c,H@rւE@D@D@,C@r2[@E@D@D@l״A@r60AQOs_*KdA4," " "`**" " "PD$g BD@D@Dx-UXj$ )dV)PXx15jn_*95B `eV=." " "$g}{/f͚_!C୷BsF駟"::,** Ng^C*U܎B[ԩS kh@D@ ~\pUVEDD֭?)))صk;g̘1?UT^Sg*~@& 9Ȼ^lJLF/UYs,\nF9e˖W_} hҤ y 9C~ӦMO? cZ~sƍ8cĈUlm۶ᅬ.̼{pvW[ICoG%Q$*9䐔SڡHKeKv)JI}}52\s559?Zk>c<܏\r[:Լ͛7;V?L'zUΆi8˗֞1c͞=N;4뮻Lkrv…rQ|yر(Q1^d2 $g׬Yl_xu׹_͍ǻY /P@v>&r$~@@*Ç;()w!͚55kfϞ=ֹsg9 ]׫W/;nݺBVΊ^޽C ƍ[ҥē0#FX*U'x}=e?ܵ#9k$L%WCpڹsO=]x6}to\YwM7d3JIp~'7Evb ըQ#m+bPٟwY-+vq`|:*1W B Y۶m͌{B?@  6 />B7$CUή_ ه~تUُ?>s'+Րz͛7S!g-Zbyg}%%U|MWի5O<yoتUBΓ՞+WEf -UԮ];$1d$eٲe6ylU}~W"go3Aƌc5r-ȕ+[F?2r6)& @HP.g4% -HY <&UR%WEm*PI?:u긶ZU 3gt- 2X+Ƃ lʕNF" >m۶c=%9b r{sy 5OR_~N{L3 -p(AJ:~ۻT挕zWbZ1V_fbL`޽֭[7 kʖ-~P_sipgy݌F~&s D'rVQ;fV\T'g%(%&U9NnܸP^.R+RI^{uK,qrS7$U/KǍNώpR%VlIIٳ꟫{JΪej (*gCq b1\Ԃou5(g{ϵP[KI_F'  2M?kF[ 3}vPͭ?]A$+\IZ6@@Hv9;|UX *mڴiTaw=W_}CK%?J}QWI!IZKYUpbJSVi=㮟ǒTkذaZԊ+L~'Ysty:6zh'lUդ~}ם D82ۗbTXcwaŋOG!@@@&on @! GV)OG _5k?=ząUlʔ)}v+PU^ڴic ~'N'ŋVV-k۶͛75a[oe-ZH$R,  @ (,FJ@Φt< @q&9O Gu"{VBۿ+Wo1[76aٳ/իWϮ暨 5_~_}\D СC%Ga:uR߳g :4ug}o}Tƒi\@ M9!x@ƛ0C Mݻ׆ b7nbŊYVf͚Uz6o<˗/\ʖ-gm3yvUWN>UݪnݺC^=pkΆnŋ?q6ڵ^W/ J-[+&g_~ekܸ]z1$gvqlذ>#'?|Ow͚5ʔ)uVW{7g}f۶msyk]wwy?`wyg)9q 6  r#@f !@@h&g%<%͛mر6x49{w[nV\9߿5jIQU>sNBFit^3fըQîtP$)?R_~ׯ:_WqI {&*|-[wҤI6sL=;q %g9J*f ;v8AtR[ltMn˗/wy̖5j.?î٫W/Wq\vm3gk5: &LCpʕ+$lX$ @6u XPd @ @Y|0`k) *?trV-$e5ƍgK}9iجYt  4֭[Dnݺu^ݵkWSNu՞ .t2So]qAŊsrz@t6pH%\⤵x 6̵JPEm5%%sX*`5b ׿7X[뮻.?r )l.) g2l  !hrVXoS M6٠Aou T9+) Y IBUZVUcƌNfvĮ7KW1*9l>׫ ,p\zsѢEM^U9/ٳxoY= 6L+"CjOa U?_} Kfr6\[lBփ ɛ[vl DI {gy1=xuٽprV}Kղ@KJ.UyJ*JUVM'bAR_UI; Ç 7t^W+{9؋/huI{}_K|N6͵սU0z8U_1(_kaVޡdQ&ᄨ f89(/bhb38}]s8r6\,A g?&l62 !hrvNJ.\%rV=Ny^@ӫAzZzJT^y1]8T]:|۹s;,KZlҊ)t*yէV;K.}7mɒ%NB-UjNGTX5iırV嬪UíNjON;IlմilUpCչ^mXbփ @;DMld: @C _=z%d @ J(1-9 g# $./1  GY?fcF93,@N"塀 @ gyBRr6!@3l< @'} @v gC @ <,O @O9)~6@@ g !@=SC9z̅ @ gyB @@xY&My@L9g,@ g}B6c. @O9@@4lJC g8fy@|O9@fs!@@xYB T"Mlד gy( @@D#g.47@Y l綉A9y @r69ʮ @lX g}4B @7IB C9&lb( @HN+ @ vcJ>[G/ IDAT$a @&U @@@xn @ 9 g3  @Ǝ%+rևI#d@|C9T( @Y ZŊ.¬"gL9; @N9Z|O=9rĆr-[쥗^W_}6mdCu7".ٙlcǎ=4޽{[…CG6p{=ql…c+T]|֬Y3+YdhG!{=3vW[ M_`-Yxt[&v@"y6lheʔGG}d/bsq? "g~'{ D&Md-Fes綖-[j`#P fq'gGmgyIAڟڄ n޳O>yT:t}_X~,O<1SyC4^x8zmӾ89_Ǐg=;nݺ6_wc g}B6@@@&pr[odem֦MOng϶ -bs=rvƍN֭[][xqk۶UR%]/W\qnI>~mۿժUڵkg^uȑ#6m}Vzu֌3ܽO;4뮻LkHdEVvնnzWg5}ri۷ܧOPB ,_I)W{eHq۬Y\nNL2ZyWj&a&r$~@@*Ç;a(&yTT)z͚5RgܹSߝwdeG_|Uvj/jUjm۶ 37}/c[ɸ~T%p?c1bD:9+zm{&Q;dkܸ.]NIO1ķ!}84 'UߞY{U~Jއ|<~.Q%rP$bk0uTwțQAơ{5H ҅*nd={Cڒ*g5Gm9\)>UdKJΪ6>%@jػwuke_E۳ 9m,gY?g!@Ht.g% cFa($*CUxrVQQB/NJynJn~ U ڽWUYi͛7?r68^z)R$JNHZ%H8} U S)gR*:[`Ū*C%UaJY$YQTEb8> :PJ+޳!*AiQ~!_s[?OĦ*[5Xt-YYPQbO@͍ޖ/6LJ~~]?=~ј]A}YG>JB ;.g*QIRaH?$"@,ȉSŧU^I]tE5yrUd~/y(T;q+v?JW) \L׻UvzΆꋫp.\ ݻwLJꐘ_݉dUr:J{ *鬶 bδO оU٪*_}NJ DHzVXIxING UJ4UI*ٕ 0@XAF9\Y!gu/ /G/>l[]tJm{3Yo|xC D -M:٤K) @ $+)%̙V!sVBPKS+ч$!٥VoВw5͘1I@jdU駟^'9)+!,YU!dl BF*VzuUkN*vUD7,/j笮U>}8.+WNԉ'K:Lks9ZCT,A"CrV]U*)!_0/_>89sӦM3vY#X.TY,y/i(0&:8LDW^<DI|@Gٜ%waN @ $UtQ_P uѣ]N@99T깙*}-ʉ^m#XrQ'mzflIqO@U)9r'@&KA RAJIQ9wyv[jhd`֬Yn*^崜:KU[Jk׮]d~ @=ğ-lc2 @K , @lv1O! @ g89@@B@&D" gs< @  gS! @fs}O9@r6Ch $lB rr6s_@Rr6!@lv1O! @ g89@@B@&D" gs< @  gS! @fs}O9@r6Ch $lB rr6s_@R_5k?=z%-V)Sۭ@VzukӦ*T(8q&Nh/Ǐ[Zm۶7oި׌vClРA֧Oh8i_֌نOBW-[Xƍ֧h;@R@&EDђc @Ȝ_l;G:۽{wP߿Iʕ+ۍ7|M0zK/dճk&5Mܳg :reŊ/'_|1x?r䈝}vYg[ &g:` )dr ď@ٽ{ڐ!ClƍN4jj֬i^쭷jsqʕVlY'? ,h'Ov͛7ʁ>}U%kݺuJWzk׮ >܊/~`׮]!&!کSt~|W/!/Ҙ&Truvms̱%JM7uֹ?g5jjҤ;v _UsѢE{ufw}gs5q 쮻J> g}f۶msW_)S}a9Ÿq… ۊ+_uhϞ}Yg~Nu8U/:Vbwg856l`}~zN;4+]ɓ'r6\e*Θ>,@  g(l%Yg @ )DGz6vXΝ1PkUEDE]7}jMYK@W f:tȴΝ;?[wl8%gV־}{ǧ{$F(bj[Uj({sV&gaYiK9y  gc% @@&gmj )i&wշ~ZHJza\U*t;|mѢEg@b7/tUKV޽{u,XbUů7U%ƢEܫ?}+7:K\6m> qk{' 9UFYS'hz5nzXt^ ֊%\|6Y @@&K>Qac @@وNAHdDŝr6 @)L9Jŋdތ3gu6#rĉڄ bFJ49pB[x/zmPܣR\ @ A g41uj gO g@@j@?$;c֭s?9҆6u`UmF/]wWX֭-wi*gvj[nuufSL2en=P>~mۿժUڵkg?sk 4iرÉN:YѢE-\ڃՙYU /_:vh%Jpe(Ƒp=t=nguϮ]Ǝkk׮ҾO[o*=zWڇ~hgq=#v%}Nlp۬YdɒnP޼yիWU^3 rO"֘@) B 4 g>MTR֬Y3Yf={XΝm{Nwyխ[7PQC6yd#bGYݝ2d5njԨܔ,駟Lڷh®z' ;wtUվш#J*Nzר*Xyz'gE{`"8v{vrQºPBֶm[  %g#Mt֤I̙3`{ . {ƶwm7t͛7$_y啘Y駟-[:vz$srk9)̀ Yd8B9, @Tz_2XbQʼ@9{Q߿TcJ2`˗/b;zrʱ/0/^{Nl됳A@ g˓r6n @H,.g%f ;kސЛ3gNZl`YIBɾ.]8Ó^wmtĪ7tѢEnӦMmЭTG + @Rr65ήrG ď@*ce@Rr6C@p@ @Ə-+C ɑGv%l@" @ )~6 @#[V @ 9 g#"J(1  D@9$. @ gS:l93@G9? @@r@&GEQc @r6H\@@J@ΦtsNBJ9$H%mv1ckӑ5k}VJ'Z/r+Q_>|I\%1|ī$-ܒnI&9Y!YܱcǘgT޳E«Ue{N'j  4֭[|TҥK]]Η:uϭpB'U 7xÉd W_}ծ⊸5P,*VlÆ 䴪jdd "8;w?ܶns׻\  @@Ξ"q g77D@ gCv@@| g˗r6Dx r#x@N)-r6qsCd r9d ėr6|Y= g @@Ξ"q g77D@ gCv@@| g˗r6Dx r#x@N)-r6qsCd r9d ėr6|Y= gɓ9kڴ]qe{饗"wVkC6{lmǎVpaU{VXoG0B-r6qrA$ $spB[x/fzmb'N|&Lxb-gK3ڵk4h=z4!lO4V\i?UPvm/.v g T#Mt< @ ~c{V>tiD=묳mwe:uc:9(*ʕ+-ZUq9 iӦY}Vzu_|<g˗;Z%k׮uVO>io 5j}3UnrΝ039*V-gomwڵ~:-.]88|pw~qbSړz#TO=qVdtr6Pqϟ?d^6o.Sֿ${n{1'K./U>֨Q#ӌ Ru} DC9 5$ lҤ@ RA>|ɹ˗DfRYfVfʹٳ:wlǏwu<;nݺ !I$J5i}0sL'*%VJ2eN*OcÆ ݫk֬qmtM48`:t޽{;'ZP!k۶<;(/}u!CXƍFJO].֝;w>.#FpիKz_G[`&Uή[줬EA8V߰yQ-Z_I.OmNfSNuwmϐ`/l @@ RHIq]R@&eZ @ B $kŝTRLUT]vDի:L=.Wv<&YֲeKWAb ''5$[je'N۷;ɦ?Jt^sd'|b=\H9~z'dU[Z5+PI W9.Vϝ 8$`rJR_?ϰ=gYk3ˋ|k=*ϛ7ϵ4P2۲e졇r{:Ljмys UPvmip޽qӁ\:(kܸq˭ޚ:3U*UM+&4Wl`u(Ƶkצll 9[<l @H^.g%f f:^{CrΜ9i=g%$/U)(9姡 Q NU>zCTBTRZUF3Oե/;rN׵6՟Ub|ڴiNJDzjVUd̅BŪ%ՏVzuWCʼXE\ObCtxXzAZFVd*Tܑ%AUjzf .lwIf|nB1/ Ti2 r$l@f !@@X.g޽{[ѢEYfN[Fm;vtP#PkB9U 01 @K9gf1 @# rȑ#*>lwVZ4>5k C `@ wv<  @ ~RAƏ+C er ďr6~lY M<( g4@ l &My, @lز2 @A9ydQ@F i @  q  @)M9gY@ ?ee@r69.$ @@@@]M;z訋3V"XPd @6u@ g}$B @ (ǎo~#`V򂒖;OlDf N9 ? @L/rv͚5Z=sժU6e۾}(PWnmڴB E}?;a„to{^3W^m[lƍ6X3f ۑŬ9 RKeklc gA @ EƓѣG޽UPo'Nʕ+ۍ7[֨Q#袋bŋMȑ#vgnguV /Çֿk^z'/+kf)X. '6l#"%ʖVlD(Y g5  D hrv޽6d۸q+VZje5k4r[oyY|lʕVlYٳ,X&O>ӟ7onW]uC<}tWu{ [=C7o4víx'%k׺{iH@^|֩S_|-[:v޽ƍg?.\VXau]^6l>I?߉O?}&|viVti˓'Oĕ۶mYfY);k B@j| ZJW"g1bc@FBk @@tMJxJ&m6olcǎ;hݺurY]5s=$d>}lȑ5}Iۮ]:!;fQ3pH2~VJ'Z/r+Q_>|I\%1|/$dªܹ,Y2Du!{Wo+ P%{Nsۺuu׻*YǧsLUŭ"=gUuh IDATfw͸ba@H:٤K)JTD qA MΊmj|r۴i 4Ⱦ[ך@ՐxT媪eU%z}Kˌ3mѢEtIV~嗮pwn XUq50vWG槟~rվO=gWF~-r6k@m "l~1B W&g{=TeqO@ I\@@L gcEJ97 @~ C $I; gs<@@@&qr @1! F+_3G @4r"F@ +Xd_@2m @OD#g.twsox'&L@ 9l䬸2 g0l  !MT @ J9!SC9{j8s@Rr65ή!@r6rV\IT@@@&L* %M֩!=5  @I9yg DN99+LB$L*[ @ a g&@@@&hb@Ξ $Mͼk@"'W&!l&-A 0 l#XΝraѣ 80[ڲeKꫯfk`yꫭA>^`-YĞ iӦM6tд"s#G#IL/ƅ wٸ#L9!6@N9 G"O8a>M0![]p-^.^z9i[~Ll9~n?ۨQ,wֲeKXbl#)ӅN)C͍r6BL $ lrdғ #G:9m4۷ի[׮]m֭nïm۶&Md;vp:uE͛eʔoӧOٳgn;wLܵ^hג/YfYɒ%=FQ^=kժU:t~aWzYgv;֮]4P:+#Iy뭷3ϴ=i]=;yH']@H#r6JpL @H9{a{m&WT)k֬լY3О={\[ǻ:UkyVnH%\,T5nذk֬q*ly?~x RM2}O~2vߢE _5߷o_'L%\%v3Z駟vW\qk|I˕+kfgqF:xK&MϜ9I{7d̡le(~?~}Q{-O<.61ɗ/c<!@ r! gS:l 8H9+ZxqXbRUڵ.Guբ^sZ|\X8q{; (*>`ŊJROFUonݻwwt?}Nj|NbG"g{(HN+G"g%|A{رc߬WbEWgħo9%eUIúԞ`РAw$dWΪ@ab@s(9"EVF$IX=LK. )g#C l@fSO9@@YY/iS"rΜ9i=gw$ěĥFrQz_zЪuǎVL._IrVĖ̟?;kƌi vѢEoӦM]#FdrVT?\UJ {CnJj^%ör)?o6jt8V\/a7<#F@B9*fA gy0 @@$޽{[ѢEYfN [FVZ ZUz-ޟ{X Y?dF97, @,RoYa;jժ=>5k*G(  @G9z9g< @ ~RAƏ+C er ďr6~lY M<( g4@ l &My, @lز2 @A9ydQ@F i @  q  @)M9gY@ ?ee@r69.$ @@@@Rr6摳< @ ~c $lr]DI9%8A EήY>CѣG%V)Sۭ@VzukӦ*T( ;a„to{^3ډAY>}-ѯ_?{g]6a_H  kY_K9]̇ @ E3Gu"{VBۿM8*Wl7xcn/ZF좋.ٚBoխ[*UEٳdž.>ڷop1 @ ʚ!M H49w^2dmܸъ+fZ5kW9{뭷ڼy,_|rJ+[ ,h'Ov͛7edĉN`>C7o޴l8pڵkgÇŋ`׮]zj⋭SN!+m [lu1.OI89uֹf߿ժUT9|gڿ46l>?nv;:fͲ2eʸoݺխq7֯_owt)R$%g[׮]OرcNܪY9/Z{VD wm}gm6,]}n %Mܲ g#% @ J&g%<%۶mk7ocwanݺYrLrQըj?=#G-[8i+'!;fQ]{I6~VJ'Z/r'$͗U\{N"mA!)Ν;[ɒ%TiT z -Zd&Mؑ#G{IPUbsǎNj,]n1%5oذaNܹsiB"ũ*ڵkۜ9s\ ;pdݳ$!/.?j(\r%, @I9yeW@F @@MΪ\KITɸ󧓳j9 )1n8+]۷Ok֬Y: 3gδI&^ u'R;81 ))24hPi/P  e(2)܈KʭH+E2|L}{}kzk-||wYUZh;vxSLc.0|r}Gڵk&v(KZ`+W./.5X=vT7SNgnذ͛]EqݏmiӦ\l5\y啺%[3gN?f}m.P8k-+.B.s m s @" &v  pVzY|\~{շ~ZX嬅 P BӪeje˖f̘{'$V;-[--ty޽%ssߴUkW6ll8k7K =g[lѬYa=;VuX8kղӂzǦW9oњ5k gYJh[턳Q{kٸ^lzB| d^ ٩S*N-o> M Ζ*Uʵ,[HkaޠA\Q ,^Æ scWV-Uk-^֓*h-7n85~ke`uY}կ_M\駟J̆eXnTP0VJV g-P*d*jłZ@#ڣ  "CxWpֻ{@@ b-ݹs C--X5kC UZ?I&Vj 5j6*7O\r{ɘX~s/uEVJ^Sk-|/22Z5bW-6/U'<={t͵RF޲+Nsۋ*`֋Ƶ#X8kY^ e-\`z:5󭕁 >~r6b gK1jQe`@@}5ƅq'~=zx~-,@B $lBo?G@( fp6sn\ gk9bd @@Y @@ ,OHB &x@l@gs_Y DNp6rAYnSF@zf( dl6s }`  񹯬 @"'@89KF7)# gg=UL@Ip6ml>0 @OWV  %#yPpփƔ@@3*& $@8M66gcc ħѣ;S-pª]^ϟ_7oV߾}5jԨ_p,XPUT߮J*;M6iРAzW=7z.L\sM͛O>D=\a"5=zN7|zv|[UV zksNwqdl6s =`  [_6rH/^-hzT\9s= gm=Ŋsktƌzꩧ\PT `=n۫W/^uUQ g?mjܸq!yzv'  )#zHpCT@@s۲&,`pB=3.뮻NӦMU>^?פIdCձcG.]Zt>܅vU>QƟ0a٣:u1} :ԝf7ȑ#1b-[>kذڵk9s+zl~VJT 5g`mܸͫlٲ_]eͥ[n}J3pܱc:wѣGLY_֭skoРf͚_~*c|~wW^yE~?P DnO?~mcj#p6WΫWfΜ%KYn΍5}?lVp6a,  =Dg8D ,h+UZh;vڥ.]hرGvUFvm.L#X嬅\p[O>9s諯rՠ q{zw7߸0׮õ^B+VԮ@ЪYtذa.h|alڠO<ڗ_~Y͚5SZR2vI'NW9XeW_\rf,SnVwλP F裏[1,{:k9` p!yVml>vȶ_ gC8{Znw{vl>=rkE?J *@8Ñ ,@,ᬅVؼys)RD+WtVyE9ap699UQ(oM7o^8jJyq!oR_tU.^؅vXm/_a 8]g_~V#TиzjZ%U˗u gۧ6mڸ/:g q}n&Y_ X6ZYZ O?s=e˖z/ C״X~>cWb=\Ν;e`=gϋ'NpfFt#))əYU6 EY/sl(@8A .%-Z@}/YYwy繊N/iLS*}tYg%}!O. C=\T^$UWyV=½V.w g-٪|׀ IDATp6Yǎs,̵p{5# pծY "6Xjx7ܪ- NΚ4H{>Z𚞵PMp,Yhoǔ)Sd`!<2Xbz|ĤlLn :Y'K  @" {8k!ڵkO-ز* ZXho^9VhVv ٬zWYZUUxZ嬅ܾ|^[*L-lcɒ%.(g{`լY3U,ٟٵ5g뫜o3pB~{fNwImk_9{!Wl `վYۧS*Tkkg ggV9۽{J,lzO#@&N΀<  @=;wTU{nuA'ON gY/+RW]uU#8r;n_%ڵ ˭TTU=Z5 uΝ;uKx 6n&XQ i-0p*:JZivϛn)E$P%VϺƇ % ϵj#zjY{_ʆ9mVcƌqatp֮*b v֪}癡*W*m-ص` MoSp'!gzY< DY Y f rkӂ*{)Bֿ笅bYiV?Z` X;_P{)3 > ֨QÅ*{~{ɘjϞ=zW]_k `UVZ k`A6g@4#ksłUT V%lG gK.ٳuꩧv`c},~ [xn/#9ZkYom)|ǵ=e o-<|PBy9k'?Tԭ[7sC[X!@$g#X ܖ1a@@f… pUViȑZv{ -L>=:=L5҆16= Bp#gzY< DY Y{1Jw߭ի g탙3gkѾ΁@Vgǵ @ f?wfln q-l\o C@ FIJl,sC@ z}? D[p6Œ1=L@<.@8 d  u٨sX an  uY G@h F[cZp6! g=L@.@8ubn; @.@8d  mh 3~L 09@7# {v?٭&o*T/#קw<gz{Y dl6oG@ =_{T_(JV,r<ׇKO8ťl\n+B@J8b ͞=[=zܒ%Kok֭ʗ/jԨ:@wܸqoڴڴi13{/O>' o{.х1 @@oYЖ\**ׇ-Jq^\ 嶲(@JNNvAOL}p>YKo ']Zlߴ=(WY>ulF87gnKY Đ@w/u֩H"Tvm*goF}ʓ' +WNO?ϯ'׭Zҥ^yWu{q5h@{rΝ {\"ʀ Qj7WRSV g3Źq'@8w[ʂ@@ b-_7nѣ5pp[nQս{w/_^}uըZ gyB>\6mrmn\ ;j(ժUKW\qE]9sO?S%z[k`tz饗\lm ~ZUn.]TdɈᄉ,xWt׫rʮ-Cgu>];b瓑\KYX+))I9rBp -mry]w܂m۶֎%#\@ش|gl8-W\Sz}8C8-΍;ٸR 1$k|ׯk)`!jݺu7oTᬵP-Sh"ᆱǧ5\vڝ ZUWvǎvʔ)z8wi˗w5j;o~p^W_}L?"vSBM6MuqUZ /Ѕ MJ ZTkYЫW/ZEA\KW6vjRvXk`ViԸq[ke`uY}կ__]w k_6 ~zTvzZXlUN<ٵH/5+s[ѣG]PUZjvX]ݯ*h8k/~6O6/܍DA@N@V_3Hٌhqn ݖ @!X gVZkAcf\{!X&MhҤI@Μ9]{F9iz9s\x%9UtΝ;W^Pe[VB^o֧M mA`IV /!#`d˪mBe?kU6ѳgO7w;-sa Wrzk$|96 EaVl[\"X '_ @/4ׇbp8/.gr[Y Ĉ@1’4|aq==@@ uރO`d:z}B8ťl\n+B@ Ff΍@$`- GyOɫBR݄p6=!>kٸ^ ,@8@@ gc~`4g  ~@HOp6=!>kٸ^ ,@8@@ gc~`4g  ~@HOp6=!>kٸ^ ,@8@@ gc~`4g  ~@HOp6=!>kٸ^ ,@8@@ gc~`4g  ~@HOp6=!>kٸ^ ,p6@@*@8{RY ڎ0@'̄{" _'ւ 8Y Mg  e(3< x^p["@8=E@B   gyBZp6# @g   yYo! ȊlV@-@8  Ihل~ Q 20# g=, +YZ@@ ,O  Zp'$gzY< DYp6'icǎi֬Y裏m6,XPu]wݥ"E5x`aѣ;ۻwoUZ58W S]vT͛7O|ڴiu(:th  ͈Ɲlm) B@ T&N?\۷WJsNM裺ugk)k֬I5#G\@l27NÆ ծ]TnzMN6M׃>5j^ի3gdɒܹ,ݸq5jЭ[7UR%e}waUq;vpc=Z[nM[oUw}嗚>}/ y?P D w~6-7taw޼y;t>_gٲe믿o߾Zp&L={ x e۴: "@Vp6n#@8  Hp.ȲR J*-Zv)hvR.]4vX3;*0o65h s'O?T "SL͛uM7Κ{ァ'xB,j֬jժ2tzZݵ^-XB=\p{']Z@c)G.}ThѠDZ m~3fpavX s9:ucp؂ wnH X(W\Y9ɓͣG{tW̚SO=aÆwIz  q,,p8@Ȝ@"+VL͛7wWW\*+.rplrrNW?}zgNxΝŋTή^VZzu˗15QFoݰak`A`jO?qƹ0Z3>T +-,_|Ї믿vi;jժUZ:f7_駟jl ?cg>6OW_}Z4t5%m8kasaY<򈫀XbmS s-̝; }UZ(kVImNlUp6G  o>3lkc`;vtV9k`m uօ5<%X rgO:97D@p־߻ؽ{{ɓSY`Ͼb~Wꪫ̓`+rڻw݋,6U~j!}?m8kUVZ9jTY;b-5ݻww!kpzZV'l=f >X8k/Z!kmlp*g3m8j+ /0U8k/b{ə$7pk`̃D@ эaZ'Gp8s@HLxg-2d,貯3gNJY ?etz̞=ۅ _˽~{{q/ZXլUjku #Z+XZJaU&K|G`SNI9ϪY-m۶ճ>ZX[pY Pنi/K#l{d嬝c-Vu[F wsyxf @ 0"@8{R  $@V%iae-\0j*93p~oY-*R[]/" +#[g" @$B8k/޲Vmx}ٺUz]N3gtX% jկ˖-SZ\) d^p6v\q,@bV ٘gb  YOlld@gy @@&U٬ r=  \+l4099O<*U={護R*UԤIztDlLh׮]l0udO! Rp$gzY< DY ݻw_ֺu\x}vUx\_\rz駕?~M8}fnժ.R;︪ǏA{;wٽ{СCUX]rJw/;kZvҥZh~洞?յkWܹSsQ%tu׹{=)A7|5knsYUܯV~w.h5+;H7J8ۻwoGcǎ*U̙3UlYg?N:]=GVkϕ]뭷SOMk׺,?st7\o:"TٓbMp6v  @< Z8kc6nܨѣGk)-ܢ{*_Q-< ,h>|6mBnݺ@vԨQUThu绠^z.\zu-ĵyY0\tiK.Di *K.*Yd_8kk^{M={t&:;cĈ2os;wE]rY gŀӷ}g.ܶLV]]%g}͛#G覛nJ@sw]w`۶m.#3.tD8'ŚlA@xpzWޭuU޼ySrBY;x )SF:-Zڞw}WǏOkFڵ;a-*Rҵ0*lwz oLO;ϟBeM{,_\}lƑ6=z|c\2ڜJPkNp 64ؑ6dp? ccǦԾ qƾ3& .> IDAT =y)gcpS č@kՍ6?˪[ך*9-UyZfV-k-[L73fpmz/`^;-[!X8z ps*VisߴUZ 6l&m8o*b_s=*|ꫯ\EoB*g3{>,t "ٟ~IR s6T嬅6k6a5Xۗ@A i۲ef͚p/}e%*Ϡ 'MpQsX ]aN  /N:UVieZXiapzZ˂^z*Z $  … ժUKB b-̴{Y_R ->p7nzZ2q:,˾ׯHJJrmN?<6pGu/ as*۴iEjɮoz#Gtvfj؞!~/X8kٞ>XU[`;,Ys#mj}noӮ!u8{lUPS]~.XΌKT6A@NIF(@8œ@@ ^b-~Y[`A5k̅mҤ&M ̙ӵ7hԨ&%k/ɲK.q/s ѪNQVںuk*T(Vk!Y_gc_׭[kƍ:rJ*͛nݺZ~W_}-G߿Ѕ?:xq}Qy)-XTo]*UJw>iך>曀7Nvؾ5{~zss@ =`(@8@^p6>cǎjӦjժl21WHE?~\m۶]3gNnZ+WPzّ#GXbھ}>͘1CO= juᣏ>5h͟q@'@8=[F6)" gg=u)Jٖ-[gQժUS~~aɓ'Uln?s^y,Y2oŋ+o޼ CM6iWfΜܹ,D5jϝtRWŻm6y V{[j?\Y4iVZ{Nk֬qsU޿Z\,hڎ ]v.xt gm]ve_սޛRlݻ>c2O_;CYfSN-"kr=<@;+f(2$  @"Є k+-ZPڵS]vK.;v׫W/vmjРA?/VY:uT]tEYS;?CBZؙ8v옒4`ʕyXh͛OjZ 9-ed9\jAvUz]}޾ g-ԩ&N 6~{z'\_~Y͚5K.NᬭZs=]@kl+On޽{Du֭Cf3J&đlm&Kɸl͸@W Y Y-+Wjz\i8}.UW].eoipլfBPW_} k׮n-֩SDžT>Ӯك>εPX $/^Za!᭷r ۷ϵmBp*gW^۫zʗ/_= Zks?l 6sΕxvXuYΟ??gܹc @&N΀<  @=Y;-Zb{1/}5h wyҫ^eUE + *B.@YX;L^f#ַ~Z=F% 3ZܳgOWm/? '9z>֯_ߵ5ȟ?m >.ȷ# mo[  [Ð!C g}ݠh>ᬗvF\p6  {8kڵkSB1­Ѫ>**A}xR,ʱw^YlrRMپBo-*Tn8k=,D6vX+ | gl*=j#+m bv,ش9Y@kǒ%K\i=hmXˇ`{p֞3#np֞CfP뱗<@x ]d  4"  {8k_']޽۽j)};t_?+=z,lQ[g}Z 8UX۶m[3F Jy9ge/ >^xaXᬽ#rʮru….T vo}Is֞Ϗ?XӧO׳>kǎ‹/誂-v g~ުU+V[R%tM\d$ 6Z\.=B3x5W PMnN@l(ȋ^5 ^pւYa=:-03gNJٝ;w0тJ ļpX}u^<3gN}ٺ;\hڊO 9gj>}t˪nWi|n\ Cé wٲeɲe˺Vk-\>UTI/ o޼ń͂UaZ?CCows6lXٳDž:YX*gC[ӦMss!Bp[Yۯ}[] &sDAp6v5dZp6t\ + .> VZ#GժUsF= ,g'dP*i/圎 pgO28-f %}zW8JnU^=e3ӆ̙35V _jKp6/ 9̹qUF @IDgcI! gg=UL4PeL@@OY@@ ,OHB &x@l@ըQC:tP2}?qR]ߴiSi&c |Ms='/^`s1 6L;w{\Zh;υ~ư{p.YXs  $Ňl|#@@pvz嗵n:)RDwj׮-_7ި>UW~*W~iϟ_'Ntٯ[jK/ԡ;jР^Ν;eCݫx@CUbNب@ׯ\ˎZUVu!fJۥKjѢEz# X Sݺu 8UGn͵jra]v*s9G7|N=TY޽رJ*r6رc۷?!}SoFk֬mݖ2ffw}WVѣGUbEq7  p ,_p@@xZ`xkƍ=zr-߿w˫o߾BQk!3ϸO>>|6mB[ .-5j (T3gu绠^z*QV^z qm^ .]Z/ mANҥJ, :tH r .ǻ9]wBi mZ;߯#F }-2uTw/}񯜍F8Ç5aկ_#  $xRp֓Ƥ@@#kRBԺu*o޼Yk9`oʔ)?CD@kԮ]vH*>Uر#N2E61|*[ncrk׮Qy*5+u֌3ReU? g-*WN:e65pk6 d6_pٞ@"%@8)I'I# Gb-5#G|Z~^|E}5Y.ZUZ%h˖-S[0imz/`^;-[!X8z psssߴU 6l"TlpB9nٲEf 8笆Bqk3`-*|=g{9WmlW_}媣gղ[Vݞ= g1(  ,gy@@ Z8k_ϕ+ܷok`U g,ի iվoUC qa}^pecWV-Uk-^e˖u8p@7x*V6Yg%{ٗ};a\O?=**5L f@@0g@@Hhل~O83 DOp6z !@8*2)@8I8.C@ S@@ gzY<,  =22 ćl|#Ȥl& @Cp6 $NA@ Mg<  @gg  񱏬"2@@ ̄a )  @VfFk@@2^;nY  g=YL57eD@@'@8˳  Ihل~ Q 20# g=, +YZ@@ ,O  Zp'$gzY< DYp6   fEk@@ҶmT`AթSGwu)r}6mڤAW_5x`'>[ʟ?ʴ?c}zgzgvY\ 1AL/et@HlYᅤs-={TRnQgǏ/B۷WJsNM'=~ Ǎ%2 @ 0'@8{ $VZt՜O>dp?פId{^|yuQKÇe]iӦ QFpvءzH/ʔ)U>裺tUWwqյ6NӦM 6]v֭TryM gm?W^Qɒ%P@T< -@8@@ 8p@&Lw-ZPڵStwڥ.]hرgv^^tmAQޅ oᬭvlUfT:w\{ PU͛7[[^+VK51 ~:kM2e+=}Yq.駟NgC'Fv?pαۂo@ }eUa Ά i  @&!Xb.+Wѣ袋.rjlrr*I4pv͚5zK/iҥ)=g?C-^؅vX`mɂRj}Us̩ 6hn>p- |}V?;w-Z/Wl2x9j> H'!'Gp8s эaZ  ~wzsСZh8_N=ԬY3O8k-l鮂} G> X }oAoO{X嬍_\9mݺU:ur[NC 9! 5`m{ud-͛꧞zJTz D$@8%>.w# @, {8kՖk׮M }{aUj9rT֯__? 'r gBCk1`/޽>c-\kкukn߾=U,;))ɵ;PB k׮uA-_ܵ6cɒ%.L[9j>rJ@츿ӵ~+7pO8?(tsIDATȂlCV +}OU1j{nuA'ON g۷oͯJW^y'ZZ҆3[gy geZeʔq!~5RN^Z}q %@8_j2(@8A0NG@2 Q[ XZU>ZxYZ5aÆ sՠVʁ +@8{%  Hp֪HU8p@g}nU^=6m8k̜9]cUy&02 ĴlLol@Y D_֎ Y ͺ!#xXpÛ@@ gc~  dl6o^  񽿬@.@8uCFᬇ7# @ 1A@fln@@ EXE"<˟8 xAp &@85ZF@g*T(Cݗx:24'# ^ .1Ǩ F@@߿_ Ȑī x~*24'# 8;#GpV`H /و02Wgs@ p!˗/CSϏ<28 dEڿ{>p\yr@ʑ#GVnC8%=.緐  @ 9rDs W!Oq2r޽{sN-[6#}wضm,Ι3N=TuYʕ+Wc=qǎ_Rx*YdL m2#etHp6o->+ZlSZC;ZKV8+Tw-q~O>~4zȄa qJ ޲2@@63kKrQ{E{un[K.ʱE֮;ze@o I֚ }5DlRs.АT0k#{5!(wJw*֓-T՞=ղfj_]P5j@)*`o*O#߬!`|"k4p-ٞW{3 :wJ o?Zj]mjVAӖ%4`6<E/ԪԮtyK_ϒ~$YY2ai,i< g H֓*[,Rpt4TT )Ai ֜_jX*Z6Em-qTn[҇3Ttn )N7eWL=ƞҒ,T8[teRҞYҺ$)F*ZFyX)P>YgT5]եK:sGZMҗPl RGoG]sGxoϵzYj|j{fYH~U/w*[AgܫVxvZCuSY.EjW\Oǥ?}PA]nq=tiAi֗R=HyaKJ?Js~h [(.Տd8GOi_Oi_/+Tҧ9KW+-,5 gx\*򣔧Ci)]T`8iׁ%Bo<yLѾϟpVʯUT2g(k*VQ=l3sV[M*BwoYp68Yw_ꥯfiEβjU;cЦ0RJD."(mC;CS$fH:,qhB | NQh E}JKIȥM{EAһw;}wO}XpVh/ HRT`o)pvHSP*C "N!x32&'5X?}&RoI9'ɑ:hfŲT:8gq9Nq|80G0g%3 uܣ]ojp6lr[y}DC.,cƾ锄{k˷((qH 6^O˶.j9[1Lj/f8| gQ#Q4Zt8}k*[cjde${lÅ`3 %/]-sً< *6nj*./x0V~0\\{*|3CpV& ]ЃNpU]o`p5+3G`YVMヰ>Z Gp}R 5uCM(ޅBA K8fh96\=奫[pVnj|׹e9 re~OvkIENDB`icingaweb2-module-toplevelview-1.0.0/doc/screenshots/tree-service.png000066400000000000000000006077341473125420300257620ustar00rootroot00000000000000PNG  IHDRgY IDATx^ Xǿ"  *nXZi34JV?~٢VZZifn御 (sqef`QyrÜ{÷ `L 0&`L 0&`L *#gk7`L 0&`L 0&&vrŻb=Ixd8#gL 0&`L 0&`L 0&^fvW_ł<`L 0&`L 0&`L +r#ݵ1|%`L 0&`L 0&`gMq߲'2^eL "Wt?wGt)`L 00t_K_E 0&25xl +ScDg`d7dWbL@ }#`L 0&;kk}0&@C&8{b?:9}JffoCb2[;s~Bl`L 0&ZX\tA`L 0L@mq6jfq׽tJfm"&+!3:'` -0&`,Ϊ_`L 0-pD?FH-9>>Y>2]Q?"#vBZtxXzA1FiբƕzXUbL 0&@MU9˷aqV&hg6[ݛkqx7/i9u*6ĕ)uNOzܙN ;:3&`L@ tA`L 0LF,k''􄹱B~W1`sk-]m:{"1iՆ`ldtz_pgL 0&n " C'PcqV@@:8#!vlЮ 2p#57Rs3;y :+^6ڶ/ϟ hB?+^k6(*}qX|A5.`L 0&GkMCthoϳg25geBy;-a9^& "]Hw^7C gˢŋqƦVP _|#145ƨMD~׏7kux0&x q_J΍012ZKɮ5FH5~9%ҩ=NCcc :  6 22hڴ)ƍu|Wou_u_jZ-̌"72:3Ժ޵~~cjF%u>+Yן 5oUo0@j,Ϊ\JP&Y|i[`n}An\MV^jG~q)H|.F[5=ק}NȬ2҉˘;w.ڴiS{PFҥ_gpXTGsZOj `9IӰg`L@1a>+İF`(0Ӻ R0rWBkGUGpZR2b퉚4WFg"cM:]v.\UV?::ҥv>Xp6NioN!)d0곢φ@#C#<,Ђ>'@UE<ah'!%1sӝ8FcN⪬PAS_x'-L+W]{ Mq&!O, %y)E"G*Ȅ#\^P\I Tr3.;YLR{\~+5udxY|S +zYĞx@NO{= Ũ.x'&*U~⋯/Fhmgt<8 `ʔ)_9ѭoRq0:F">,* ? OkZ;Z7DՃ#4%[Ⲵ85hGOt@P\:N3]SϊTU糡%ϙprwaEdFV^t*:>N0r'L /,٪*z#LKB+MʅNF8;$Pˣjy`VOq.Uj'輪 $ڒ/NJ-8 չ2%E8\ bdKQ37ŝ㠼Zcp$& yŕ#:%T٘oę3gO%77ӧO׏=i+qN?v"g+:qOYn?uc^eD#7Qe*zˁB<&YZH%%* :|%?$fLn`L<"fe  wp>lL@/8֜@6 ƖfByhׯ/u!~ Rv3{Xf@5sL|g(g>,"j_G /'4ufNu' o)*|V82<<haovCuA>i}%N&Nn>"HBZw7:8ݡφϖE%.V0_\[_>L C@V,EC|Jfa fUIQlY L5P47WI MW_YspT4XIhfm0KB (PQ&$)ڥãQPf:uO@]qvNf`~i莙}]C)66V ?F}BROI#-&&Z%Tե&ѮShFOMivvOwAπo)\, S. [&Βޮ fեLϊ`}6T}(ń<-; ?"fo!/j: g_83&_JJ;%qt+]HE⬫xIEY hXoe2qV&Pʁ+#a)|(K@QbHan/O iVY:xꔀ")cSEJ]mҥ8K>T?.:y*kꚦ KqƖwdlIu/̒=/z`a/o r1 #E^Ky4]3`G@Aۙ砭mVɤ|cؙ3̖䖗WCJQ-Zt|۷/,,,X@Q۶mCAA aÆUg)r廝dG(uLo v)i]@2GsXX<}98KϴjRM֮.}wM{Ygec(lls!FB 4t^}~#*J@t/X7{|pV<E -H"*g\DM"LgJ E*g5C/LXگϵw/Oנ*o8gi9? +ȉf*bbQ&}yڴi aN5MWW,O#Ǜ "b#fel>R.zةK/M9s}&hYYOQ>t^^E? \,,Rk9؂_ZwQ.]ʂ@N*o?8+KkqrR,KH *O-?uY %OK4ĵ=v !IY"rQ< !PR7]Mc眕Ըpv(}R#PuMyٗS6~^_"f6zyN13(gwS=Fd .`L 'q%1+;⟨qOQZ:B۳?h UB)ҫv;jm۷ij>+SG)g>eee%KRqO/ׯ_!꫰loL;|Te>"ѐ~r I"EJ/k%IŬC7D5HgKSRƙPvƆW}Ee >%Yo+FLZ:Xaǝ$%g+]!\ko)g,.^:y/M'"=L*[E5[g/5y`З-5W_lMl6׋~RNm/ѽudL 0g+3J˭4PW{\Nʪ5aV}kHCtP:!hN}~͙q &PW/U+JS&]gW\FCgf/?L6?Dd2i T߈} ; cL 0&` ~tA02 ƴvw;4̙L 0%P8+*ovy6>Ckk U<$JTT![]G_י@;5Zvn`L Ct5]P>`L!VUp{#fH\6A{59KjsV:T;ϵsS&sTC0vVfL 0&3Ct5]P>`L!VU9;IӚ"qߜW=u(OyU^NwRѧ8;iUQ FKSYJ(yJ-LEJӫСiT_ 5C``g_w`L 蒀Z`.(rL 0&А T+*9Kb.TsVY:k}0&@C&`!7l5jxL 0&#4G5`L 0&`X5% hCm`L 0&|0&`L@5giXmϓgL 0&LY=`L 0'/!O@,jC2&`L@5gaL 0&j,Ҡ 8۠'`L z3&`OY_B6XՆeL 0&j,`L 0X;A`qA/?O 0&3g gL 0& <m8 =n`L 0X; 0&` 8wH&l^~<`L 0&g,0w`L <g ~ y`qVzܖ 0&` 8w`L 0&T8[XX .`uS#L0ښ3 A,`L (g tl&`LH-((mې=IW"$$2۫5T$$#`lj Ʈh`czТR~"" ,'kf\ڀ}0~da72'cR Y`L 0G`L 08{i;w3f̀mMef4jaÆUo^i"O45 pjGZ}SYu(:aٚ [9#dkBR67oRzl`L 0&`X5d`L 08;ctL>U Ǻu?O> F̣9\M뗖"lOFA[B-A^Zk3cL 0&tCF}@"an^cZZZ ;vl,,Cb=5KA,cdD |d䠯¤(D6.gqښY-EV9[0&sϟQFac{ogŸqbqF$''m۶xWޡb׮]HMME0{l899~}u⬾rL 0&BFl^^~w 7ܑrJOJ+)Dn1-9^LhjxA1L33lM +ѵ8-90Wfr¬=2)A[~H8;k,ogϞ^l2`L 2}~)4i"GD-٠@!1wOƍ"Uc}߆TX5b[`L 0 P#q %'ĉ8}4(Ϭ5wx=۷ơJ47wæ+ZL@\R!l=Ąrf-P,k{5Qjfۡ#L b;x5we!U W΂CicbX{P1c/’e}<1!a~3bӦMҩS',ZH\&!֦NaÆ)l?SSSګW/3m}gՙV ˍ`L^N￱gdffG6nXeǎ8pk׮^{5$$$:ZҥK?P4h"+}GΛ7#F ҥGDᩧ–-[#g٩Ȗ .87߄lN2CO<+V`ɒ%bN?<~ 111xwsܹs>E~066}R;iټy3n݊onnnpa[Jy8քc۶m())&L?(쵳###Mg5ŕ`L 0H2VU_Сx駫-EaFR_T059A Np63̢0t[ KD+Z6GTE)#Z9 D\lI:EڠEs'ȍ8~EHx9%m7UN97̶4w6iu!aS1wv+1J,3MY҃R/:cL 0Z!JW1:tP!͙3]vbixx8,X ؀ZJ$|*qo߾oOkwaĉׯH+@cvZT@QDNj1??3ر8Kb0}ј$n$ܒHfnp-!眕S.&Q+ig ER+~Z &qvпg_|LLLKSLݻ믿;wŋEt5k*-ΥK@)軛H6X'XOe+,?WgKhE0|`Ds9w>Lm_x!Ҹg5U=Az!-YF5Ȧ(lE^F`%F]E׵M<>`L 4zg _nnR8u$6opL @}g)mE=ԑK2el6mă])i+ҡ/FAIx-=*g)F?N-uӰL 0L@8K h >|$Rquu-^6l C{HtùgǏ_~K/$^*8K$dw&$+G Uf-K.Wse$R,$RыN:XT-[-[ A)]|!f$բE ᫯'jM(*W"JQΓ"5)8K6>c^zNkt̜9:p':; #ЄK&|JlQ4_!E&RT T"8~`L Л8ˀ!FU6? * sUAFHE&ΒOoVC,]$Rd,LvɶM&Hz(u׏>HtKQ4 票?+-l1{mdL 0<i9j(L<z!sNqUiGAAA8>H̤P%JYZYӅ*=$K@9K6EJ#gQ$*S^E`t q46n]SqV: _dr!q"#Ȋ5Q9KB j+eQGhz e, ː饁{;L/Cg=**J[#8KKK 0".@9ݣdE*1`˙~P`婖[o( Mša(kv2&@ lXWqVv  #G, `т9SEP|x!Ge"mᑊ/:С'ɣP=: E謨?uma`L@CYPz H"'}XYY K:$w43I(Oe#FΒD/ I"DE"\"H%_G޽Et"Nhw2;IBxFk)EBEjTH$l#`L =g~ ؂:$8[]Y&'@N*t5=tN@rVA/Yr)ˆ =|Qă"Q%JSז:xh&ЀLoB*mw?-ID6:Vh[>E R$ R!ȑ#b? B;?(ҕ^gH%"zn"; ' H$QX$a^F8P$HBKboKQ}Qt+$̒5gi5{aN3 `$fSUr U%ҨȋCHh"=)g}"gi$itUԵ呻xBL 0&wzK3fHU٪x+} d:$GQՉ䜥0@PJ-vhYY^_FtʕL*fz &:vK&.L 0&4!&#GYʅE\i B(өI:,mSDdE2Q9u •%>J[Ǝ+r R|yQBrrڕ 2q:['`z'vIC>IH(Z(ژ"meʣ.ΒGI~$[3b[[PJA&ES|-KmZڽEQ@(JT8K4'3K%88XsV];X;aL <:X}t֒gRڈ#gDMrNSrǍ8y#\ L \˔1A+jEv)rgzygG벺9{~EϮn‘iu"g4q%TmS-E3jWW(rv4PY&ESNh*˂~ Hl25 N⭮Jvv6>*M<[0?.sΜ9#u{ҤI`L 0GbT4'8K-;F)ͻvn Ku݅QťBw]IƔ}y7.%faځ0o*ydZbٹHHBJ~YbB;w VU8Bb>>2`on*^RDHm8 0C`> #K8V׳He ..st +VӴT1ƌSA=1jcLfNu{lÇh"deeᣏ>w}'h;oRO>)r@FΎ=7oƽ{aÆM6.gL 0&/=MYΔGJG'avhꈝXֿ5^Y^Eq Q6$6& kޫ9oS0BSNn8yߨ= VV驎012*"hvy9a '~i=++//(%g#S:Ц}ukwA9NIed|p2??-9=w;jH-JF&'b`H%jvT?KBGwO܈U\;JcSax'tuuCnU sAe/ʪ?hSi{ p ҁ[;[kK;_Qh=Ga|;y'+;ܫs(lslRRhw{aolՃd#bY,/F7`ڦ1lFb36Jr``Z+ & w*Ѹ ^l=6Hğwa߽T㥶cl:'fmj.WRѧ)r c7q6d6IIHH_|!D)ez( ]ռ9Àո-vPfOFGg[$˱Xu9F\SNf &?Q)xM/Vy9,nK"z_Up XM>>SkN68o Q? ///dffr?sfK" *쩧Rͩ8{U믘;w.~QQsMceu5xב+w(eq(bNI%AyժUB7m$Mj7b„ hڴ>}*ٳg+Fׯn\?ʿ?ED1 IDATR$ڵk1fܿ4?o&gIȑ#'͚5KK}0&`q@ ]2a#otk&:qfZ.n g%fUYIۯ;qԊԖ1i nLFUN=W9?lLDӽx-\G)x8U^:=Cc'^=Z`f'|#1?eDtf>~Z `u@@8WXnpnݢbRA T1$$%kSٹEy< )y\.ʓ))}z{JP5\]D4j.j Kq"?[/BLRKw%]sp?6 Xoo< m>vۂw/L icgs_GttRd|yotlY=`l]inJJ]0lFi4=uOL5wl%]s_yݦcŵNPzZz`oo섋#Mp'L̤VDZmK):g)rǎGϞ=u&6ɽO?2=eDg<f Xr&Bbb#̮d+mw9/ooMq46MFH5~>g  yZVп"p/g3 !@IYws\?þ)sxg1]:gK<":u3`bL 7z9nƋH^W88캓m#YE%8g@lv>y^ {">";I>]fa ZtBDQe.L >%lV~.B""Rߧzo\E;WwdD=u9\㎛ܺRqv=f๧[RX4g- 7)UHꈳ-'+jun/Df`E0k_ u{e;KuldYF(*lu s+ aqJCDiZlTK[xϻq16z{Vz ǜJ%]ÔːVX!@J wnޏRm8YL=qzڥK#r/ۑ#+''chRs3VV<?á*Dx{s6"qvܙ.HEzCgOIsrrD#EqJMJY?˅PG*$4R.X꛶ k%"i,qb !tK⯢/eEUZu,qhai!1ȑ#" رcx)/tSuUgggvB&RJ3 l޺u%_q*ꐉMM"> $Sl``HG@QO1͕jPM,(]&hXmγ~H@[qv➫JS-Eʸ6W9K) (AE 5zao_ҐJޑ(IȆ턊 YXy cʿOS#riڏkgV" C71;h(ovPTRc{a+z@7?8[:LE".Yd%r(pK0r +C=;`^Vs07šgc+ۦ IکS5'(BrrBY'ĉ~%ܗ\ 0&(8ЃO[vx2ٺpCag6È|(!2MYih=]HF%>Չr0* +4 ׹8K0Sq`lwtp,GFQ~ft1A⏪k$.:_m;ң' &z?nP,F!|i!a]j,^W~IYǹLkg^ls;K, }7{lxvȊZ@uQ8xEi (b"AZSq"XK&RXX'dt@ +XqrRt")U딚hWl)1lgI%). $raL 0K%!R!KCmb1,YS?Z5]9cŜ5{؏=|8b }*3hbcѪ\L]:U63lƢ5QZT10!5T ۪ob{Ξ('`V'^MwL7+ 7޸iĿI$^{^'KJyn9E%KTH>]!77-eu>?W6XX;pDaI)v'kqn)B 6"[v."U4R?1(9Kh+[ 9&@5, q eCxum%xoE5rV!XCq XP{6,0S8KCwڍo*Okq% x.l胣)I o$=M-+gbQZ9rp$Js#g)/mғ;LT}W8[6?cuN8&lCt(rTk~N- },O(FSnaWş M%)l&XdG,8y G ]ӓXrd) ۑ?RgO벨&gğh+ScvFegsE&`L EMlX@Y+\ah|X&bcUt2!D 0(ʈظ;~b|Zϕ ަkRNO‘W\ِF圥k[bmj"%TԮgöjZfaUH,6E\O)rqx\*iH|^#]AKG+H#gɦwQJvx-Z[g]t:\_l ?N1&-,;p7+_(q??rV+KkǢp/uj :w,fO yt2ꈳmW"xFFS 9g+z!ؙ㋰a )I~[U;[zDlǷ+6^mH7{k4n+;x۹۽~j]%a˿zFT]kb|-prKlnfҏeΟ?_=(_Ai 軯Cc~#|/ۈ:sDowdGL;*"aeEU;Wk "_n:)R*+_l+|ye܀ 0&`* PU9qVkܾX 3sl El&`@Q YݡȄ=<`>pl ġ7a>`rW@D"c @x_JP~{0"X~1mH$Va.~np,e.胔`r}81‚k7ZWGKw8(ДS!-y` `L@P";BhR9϶<ڌs* xqDmUVTCq8H. Ը#ζr镑 OT|u6GƝ&_M{2vݎc3_=DRCi {â#ґ5ؿ&NVb#P[)e㶱rW镍rTlr}XX̙n^ 0_EQ*,8 {QZA1y7-=cfcjr-Dz~Xh(IH]r²CnC)a`9cZ# ny+Cf$/= 13h10o6Kk1jh q臧D@8{)&vx[gKKJU۹ ?-~۾pX[?Ew,>W^ʮ#RܮawH[Ud#q@<g[CLdYX|;t{ JT@$&,/B_P cGKX=.]l#KSXS,17?w*ÑK~suT_1Aڪ`fyũ% -8|ѥ8K'2吜8qZ7E=D=T?+VH+(– bWʨ.X?`6YCJ?[P֎vH|ZbNfp@tf>U)rڲ8ֲr%&`L M.sV5(:4; (w suy]31h, ˓1nK𥟑X,N3*IwÖcAH,"mn0V; T Ƌ3gqp) 9eü-֘SynվvEgPKU4LkP}jPUj+Vۑg5Ru5Z)MZJil>rL 0&@C$PCq6#$0k+ QZ34cxr? n 9P"5#HD7o$gAf>JC#,n~#0yZ }x8uab,Ʋ1X,!?0Yr9n)-C~@zbq. @}!NWYyg,Vq &`L hBMgŁ`h3`0|R=g0-݂HtO#q6f",s ,SgW`1?9[I͍U+p\, ¢Ue48"O`e=Nocl?bYMZl`A0dY0ahi ..ct f:SE3N-GlnNǐ;ǵ1& VWjSjshh(N- ,+RZ'UN[R iii: FcW7._gL 0&8ɸyz Ne:cpH[`?.}K.~f gd[84n`j2C^t<|b=c|ݫ* ; `E ͟8f6s`q> @"p0_Zz*ƈXN=c} ^@{caUu^Ǩ1iWR#""Mwjurr%aVL&XTG8\ 0&`Nl.-y}, ’5!?Qy \LCƌG d\†q:mcx/^amfbx3^"R+3'EEZXc[ȵs`4 7``Df3u2S"Yv 8 n^"ECp&l7̣f>ڊ|9T`aT]у XU" *.K4L4L*Kr),+RK3L3-wET\@Aqgf.su~cZ3{gX;-T`Q|c S'ڢIb   ()g 85x) @%}}hs5k0P}-}k!>^󏭱ˠc|Su۞c`]~|}wڠ朔3gXh///T^]ݕحR N:oF֭VIHH-[υ Y$@$@$@$`?IεF b IDAT۷O ?xѭ[7%7%tJ7N ^;#/BI]=p-g90̝;W+g?5{Y fټũ[6IHH l` la΋HHH((Lr6;;#G'|3g`Z)oևzݻwW<^ W'O(Yݲڵk瞃ɤ裏0qDHɄ:u9W) Y2 u= @9kSi>*BR;~M9˗ 8Y/(gm HHHH@@a Qbtj˖-H[ +e ]۶m76oެdnn9#4]zEA^YYYJɡ^}N9}DJ{驲vWXk׮a„ IHHmj{gʈ$@$@$@$!PK2\7nv!%aE6mT}Ѷm[fJرcU֪d&I+Jԭ[W \]*/駟T-[s䬱>2Qbr}ꩧPlYހǎâE[fMFS[$Wdu3f'oSMFxzasݻwo/lڴ zl r)))M&xArX$@$PPzP    (r~-Ep$Zvܩj ͑wQ-X 6($;[dskZASĬAd|h!l$@$@#@9k?,Zr)=gxӻ4THHHP:.ȹCf͚i/J;vZ) RMeJ]:uܹsJCafrn-[TܫW]v*[Y2#$sȝ!,s?堠 jJ;y򤚓' G믿bʕ*;yРA* ZS\|ZjRBΙ3G\a{Wiiiqơjժ&ĜQ#fe?~T9x lٱg @9`7`aXSdda;o6  ((g 77RM64ɠ\|U6`hҤ ,Y&2ԩSѳgO%5E6&e HwҤI|̙3UΝ;*4rRB`ӧ޽{1m4%7:)aj=8qSbEDDD(*밄Cɒ%,qo)Y,U<*Y̲Ɨ_~\r:|0d]zR-f6lɓ'l$@$@#@9k?(g&)鄟»[cǹ?!0[95=`" @q&@9[4v_]ll+v /"֭[N*M2ARSWDLo=ocܹѣG?DjjVʡkQ+tqv"@9k'\Ĩzrat[xЏI& Y{}pqEɁi){6_:LjWIY)q PLNam~u)5`hM!"rVƒyI^u嬩q6lrr6Wd5ݹ޾}[!-Y%%D"˜> .֭[\"sEΚJ$GJQH,iőI'\]V^mA+ҍ3B<a&Jol$@$@$PPl>"%k^zzqzKVo}uR#͛TQq=)۴iqLR9kjիWC꼊`&qYS q=g*%J3<.1&gel)5!YRQs9k ?ӛŬe^M$@ @9k (g ֵ`{p5B:a&%:;rZ$@$@řc'%8|U\rZ>>>*Sġ/0$%6"x%UW@^t *3Wo|:ڶDZVΦcȑ­[T\q;P ,Z2_W\C9'%%a5ݲrVw"_%gd!K9Vbֱ_= uܽm@rm o DcE50[ا06  (D(g fs*111T% QڵkcРAp0i;wT%DP\/Blٲin)+5XE2j :8GjJƍҜY Uzԣ#I)=+=cXv->|qȽ-,Y.h)ٻ9+ɚE.kf@ƍU2 HH VcW'@9[8喵Q׭,B9Z8'Xg%ftmTg) gYݻVe&뗬!C`6FG˔)Z:Dh6)h1&Y9bR7w}\Ge%YRVHH POj0;cq.kew;5Pro#y. 5˗S]~;W LI'ܯz<_F4g{O. Sp2?dTOÊd;nsfr@-o "  |( rVѣG/#!!Ae?I9SO!,,L>PYR{SJHvիWU=ү rHH[q*B믿V?G%իU}P19+uX%3f(!lYIjTŤ,W{.\ ts/޿Y4v=/݁×ҵ$#s1kO"b_UhT S;5@2.X>ƕY9\b.DBn#Wp)#/tA{C;-R=09[\) ,3Dmv&_5^nza<]=xuW1&4{ ̢n o\kHHHn ={,ONRJY"e}RCI{Nom{VR6ɖRʕ+xוik(sV3T(kIrJ~;%OR"o}-϶GQݵz-Mg0E- kR~˗ƿusSo+;UuacXp^&Ӎc|xMl__=AgRL{ű+ӫ/DD껗żGbʽJ`[jCΓfUce SFlΈ}Xգ 32Z0JE$@$@$`AʺDz8p@ =~8>C߿_&YGZT4tP=4Ç7,##GFfR k֬QҤl6mp9UT#gZHΚ5K l$@$@$@Ar1X̲9?UQ#2=+,(7P)>:Ro{aგ=drdx5ވF]f`HMZi}5R*UZUyyznz^gOz;~ ˻闺k&ԮPC7WԼ{j"Qu)Nǽ=}z}9{:c }nܺmkaJѥ:ΛcҖcV69ax+Ur֜}ߛr 3)qP>HHlI0e˖S襶lzzz_$:0%gk֬2]N$ᅬp>}Z U)? u̙*v-֮]m۶Մ͛7gU $cWH$ T9ڵ$sW^Q<<9_[KZJ'=0kr9MJ2Ϯڋ[s??\2hGR嬔5G2?kT:Tj*TI'a,2\9{9^#iHH @a"@E-WdnYC>(~GDEEIOD?Tfl.]!cr[uJկ/O5/neQf>.Yo߁`j5>"z{bϑ骜$Y$ԠڼoOT_OY ]͋ 9k;B8v|||Td슈mذf|   H*9>ܪD,C1MH_x5{8) =#)3{`rHwdE/‚$noHtl:5MAeզ^Kc {cp09(eGDGggC܂ؘ@Y8w>V =3j<, Cߓ:i0 t/d 2S\LG!ub[PD U&c-{nJF9b2ޔs?owW߲TueQ-rFHYZKCD4wi;TtKYI]c6  (hZ){nu`Y^;hHHHQX!gs$MM*61 üc~Ll j#+1k~Mّ a1\V#tF |G!Qń)9*A0c'Æ[76% a6k8 uA|df%Dhpg A iX懀ш!0 !Q>8'jdcH-*(H>99*@ld6RW.NYˁr@7<89+lrV>ZWo:neq5ydݒY,pF6F_&JIZDڍ<} #TP#z\aHhPӻ6{)gx AQl ֋r2Hm#f5 h2FNyL*',D;i[q5떊=KC oZ22ю߶:MD[GylK6o[cKu.rbwc l~ɱ @q!`ݍ9AC[/ Ƈc_6>lsakEd<\oF "&D/,Ӗ`Jx*x գ 11OĔ1U"DFH7,)jYCйdmzѓGdɆ/. =6;_/ r&t%m=ރg'WsX׸ƥ5# Y{e\   B 9sgb&Cen\^่Ցn\XE@dHZxId4C$<&NA@v ͟CߓœWbӹӧu/ a91#C1+k†!r\dbwbVbeT $fӯnnQ[)e3hn@g`V^? >0Ck0kPJ2gG1ҖrΛgQʒKtz6Az:y3 S̚ϊW ؏22 @ `MpEe rA%gϜFĄhMɜfj3gBS^@2gCb#<:j IDAT>rMC|\{Y0!;,rYH^1HH# p:p`ʢ,tMƚqpaЕRband4.ʜϰ@̜s}!!Or6bOYwbrfA$@$`_ @"`d!eFYdddͺAp/Td 3)(y>SUi ƭTEUjEŬ؃HH(gϘ# 86YeVE??䣔6'ks{  قQHHH]ћyv6 %/\nyTFڻoΔ6j@{ قc͑HHHc[u(*^*>;KòFl#{ ,قHHHglC6iE(YQZΌ=HH l3$@$@$@Erֱ1YG8YˡQZΌ=HH Ý 8Y+,vC @%@9[d #  Yd$@9Y 8Y'ΒHHH}p9r! @9[6S   ((gra$@$@$@6"@9k# (gs8k    @9Y .[S ۩Ovķ``xu)9Da#@9[v)P 3ٕprh[WK֝;1/U̾}7}M~S36ByEޔkz?bX`W` ;-ہٰ'^ݧ39 YirѬ&oR?Uv;MĂgq2:J9kҩt \Cd/6YN8z<{ų\}XYMx1T`pݗ[Vﳚ{| NZlwо1?J`Uqsrp;NШ+ [߷ѱ;ۮVw+Ya vlΎHHH W/B:7& cQ3Vo#:kEש7߇ң<=бak3 rD՟'Fuɰ_&bҖc*܇N%pb:nܺVUcυk_+SY;ތX|( iJR9qAܕ \#Zm9{WnfZkƕݷyq*͖krF&F¢-ЬJs>Y\K݇CwnBuRX֯̕_ofZ}gVؒWo[YLTk1\F22hu}Y4߶%I?tnSu 8! ³ @#_9牋z2v8t)]YizŐk;xG~)}'ṇo{7C2.qʺCx»rl^mU mRwQ1~=vGrzl?>\߮.yW vĺ7KdH*^MQBu/G㽭qF m[,zխSYg'cNKI|գ1ʑtA4V CÊXw/G]UN쵛ִ^12Yc77A<GHp}`Yg'in쯱TS4jռ7\̆|Шi}+H<31m ˢԗr(&b1Y M rV-h5=cCHxGomqJuYap*\=*s|Х6ȝE蜇~ڎ#:#tX ovΓ 'Vdb *mChVMk7YMsz5U+^h4 <432#4il{DoVycoQi`C׳m.ocrD ~+΍}3z_(suׁE/lQMb#c   05rVYӎ'ٟ"A =llNJ2׹JɬZq"lbeBo6*/;qrt7%cC+)V>-T I*j-xلSҍL%(Fv܁Ϸ[q?N^4:u%sUg$mUxNfiJkߎ_PR_JGe;pJZ^aSYd58~^湽 Χ}`RGoxیUֱFbX}6N[*3Ez$+{اL16 !oS3Q%WmF[.X˽r{bl^k="7+ʘt_s_!ձ5r>͘&C‹]!uڭy_$ssYs4uڵ#u\mNrHHHH5fujjƜWmX? *1l}wv``g}'ٲ%6=zZZUrC%{6Ʃl{uI >o#tqQklܚ%k8;D(u]IdG.cv&z1'}{,Wig;O]]*{w=* C0iQuPnXSkG]y4R@F~WlO"MZll)g_[j?*vW{{-_;>j| F=#ejoM[zEfɚLŖgۣTEIsYs8zH`s/J;;u]a_;]eK^&#wbs*]9+ߔ;pGrrGYc;ټ{5|H&o59S7%ޣ?D1s)Mƍ1ԔXMSְuU,_/j>־SΚyEi7 PZHHH3RR@jJԘGu [Ч949xK_^qyyAJtIbsjζtWb_l͕rb۰V2Τ/ʒO%+Ը<.eDcɴ<_`$Y"%MqvwEU%%b~=_τ1 ZԚIw_㶃~ߋmgZ(99kjmRhjYJU+Vh5۪Lk{'^c#Ү͈{ *q֖˾WU7\t[U~-^_r0;꫺MNr{AjwU"f`ħ^7؝M}7מ7OaGj?u 6Wkf6$^&⡚1S=g^7:1y!TݭA} \o:En9+}?.[Y%gM7y[yf欱{Xޗw^Ͼ}Maj^wkWO.g*i`7y2DJH盛ڨ)}Z}2u`gQK9[vkM䬅XyݵV%URJt%LkC ˢkLk^ROviV:^RwYXhH: s嬼<5hJ292^K]8Ked,uiFմ[fHJ9Mu7S M07%g՞xڵ;al^yg?ڰow&4TO(jkuvR0m|cz^k6ׁ;?,b٢\(gF IHH3Zm,Tq. V]vyw+VeK*a.R'wM]GX9JBT|$'BN-\7'Җ:8 a],潧FWȁ}/|yA鈬[qR:J( lŗl{\ W2\(C5g- !x   p8@:#N"RW?c YojVė5{,ݢXH˼~կZAK(V.ZJs&]Qݚ [K&}zUo<+!b\=HHHH f@%$@$@$@$`9Y˙G"@9[6K!  Yed   bMrXo?O9{HH )۷g=,d@+_n-dA&v'H^ ,ng/7-l=NlD\i{бj䊛yV'\@ĮD:otgCA,~^[r3hvw/5!   < P扈eEyw6  &pnuK ҏq)g]/ؘa[Cѵz GᅵwAfD9otH$@$@$@P((gs$@$@kWGE`1d$Z h:I/Fжz֪ *Wd;;ik;RZϐHHHHYŚ[ngc=#Gjlذa|M?~}K8qsSN>_mrCCCo>,Xʕ3 AXXY"  OZd`;X1;G5&qGNw]ykC3d   0@rE&`o9ꫯܹsF.]C2eLÇbŊxwPfMu ` 9o̘1?~<|||,_ܹd\6  Fp<m߂G|K_a͔'xMCtI|/H*y~zcŤz֙ i֥kxe!lO֯MK9kѝNjIHHH@ LΦ_54냾= t!CrvΝ*5;;F޽{9uÆ CPP6oތ~[+sK.Xj"X7oɜL־}VcǎE˖-#ݺu+~G\|Wkժ|WS7oɓ'U/B}ߜ~F$@$P ٷn#rvBEr6ObԣyMJ#(LnʄkeIWJ!ao4vȓ͖jTun؇'=0Vg"Zm)"   AFr6cA% jrE_w?Φ(4 AO{{%2:HAT4vńzsM)~<"f.AwL{Y!g|GԂ.QkĐ> fȈADHMMBش8 ^9 E2n ֐02SIr†Qo(^GDfN,+gcDD|}}Qrer6p:t*w 9˗x״kO?TeK9st%,ËIH&!~p­|)|MjwGiw,,[{1QfAKD]9ktNu1+XY]e RZ63sYP4iyU7g/Tٰ'OV٬iHSǥKׯǖ-[2220b{غr֒~ְb_  "B쉳Wq-uG™~q;OpUrNjyL9Rvp!>l7-+?&sv_: o@0*[[SO*nSϮڋ6n$FoI    JGan̽`2RW˙ujYwJ({L O\1&aMٌpLэtjLƐڏ!+51L jQYx! Cg"9@Ī& 8GV11f1^rG%jaBR1'ddѲYNQ嬬~BLL WnPJ)eУGUsvÆ JΔ4sŋV6lKBJ-L6Rsvȑ;wgN @#`Dp-wCPt 1x>V{ԃO%LY@J 7ogCW[6?>\Ձ_/߭.0I $Ę}*l{ApA$@$@$@Er6Hv_ljHVlPH @K؏989"40tLYRxL EyN&ğtS#G^aY!=eur-KP(8G"tfi|u2gMG>IF@P,a%np3g#Y_;n8%Hsg;vLՐm׮:bŊxWиqc [nŋUZ9L$6$zCCCqa{&=u I Y3fYi.CZnSc?   ?|D5R wxvDpXDdA!}e?s66!'s6"GB|fΆvGx"og Ьl[}5Ypb D,h%#g%sd"d"6†B/\F"tq{GM'  |U*~>PZHHHHn)gwcVlf̫; '6b҄/8a 65g6#A+ga~?L5֜Up1Jjz!8LI{wjޭi)ы07Aݡ2PxdggRX<䬊7;H؜T]s蜲TY1Y` :"?(#5 vMn`٢\ e-rźExTҏq} #ѺuxeLz֪ +—)~ޔk۪jylڎY;9ȗ/_?oY?[F    !P8, "cG@0t(N.bxz݃+9; Eqj )1072 gX zzk JiX2!=sYc}HATD"@/5_]d*ͰÃz~Y˂, IdّHH@VVܳ FwZK@z16ۋ{[Cѭz ˏ?;0a|v!# H,^ᙶ1r8 ܼ-1!u !)B$`>YYJ  (Po'{/Y6t*@+_nMI[=@Z S^F/ xpop}?e'7HeMzСj8(7Nw'b׹{5enצz@)y])gf+HHHH )g1Pڊ$?fY7$@$@$@őlquHHH8-(`lkHHH VcW   0NrwG&@9['  0嬹x XDr"\-j; ؅]2( P(5TXO$@$@$0 h/_ƿE#b   pl(g$@$@$@ŋloHHH(g페fFZNafʹ A,kP7K"  ( (g .pCρIHH#J$@$@$@(gh8U=SF$  ((grI$@$@$@la}`90 #u\IHHmj{gʈ$@$@$@ElT.HHH0- 9<0 =&  CmY`a%P2[ (N6peH?aYr^{+Yo[z ؈fuuc&p b9;vX/ڷod60 8Y.N(gmMHHH8v XͺIx{Ǹϳ.nJmblLދ}Cѵz|v,`9;rH\vMoΨV:t耀)SF}Ԗ333"::gΜAVV*V-ZU{%bZt(1̙!  Hr(*d6YQB  (~^ \bZ<*Տq} #Ѻ^@Iz1Dճ۠BM|q\&9mbĉ"g!##. tqq[4+U- @"@9[6K@qn3<~9s௿O?%KZx뭷p DDDrz$@$@v'v1#cmĜ֋iM[k5s>٠ <#j Xj-['''|w*{6wfA1ի{ѢEйsg%@5͛;v@rg$,X@ 7|S]; /W",, 7oƍqm CUs3ԾKu5x`\;Gkd.[s1 o{Aξ8wѽ~@9;bȚ?SHv4KQ5k%DS{  bMMxo#>MѥiLfٓIWX>^nxupMٞ5 Q.8\0Я؞rX/~QR@28/_~^ )?WΜ9SUVre\t :uoaPΎ3F]ӬY38p@L_TwȐ!xIـqƩ2>*`8 VsZ*.\7~Y3F^?{.HH, @9k,^Z8ݹs'ÑmpF޽{9"a 4 ́{f}h2g/ -- ^d^=<7n_nnn{[l?25ڵk~Y*U>'NW_}nݺVY~iժglB&k2U.\*Uyc/f۸85w{T~iT\1%KE~!35ock͋Q HH ٷn#rvBEr6Ob#'3fDV*UamGapV&<]+H2 {{D\1^ݻw|--?rV~Ƒ #MƫdJ6R 5VLPM$Uw„ M{޽igV|XhJ6#N%Fhh(ۧW@3G+s > D5 bZ5cy/   PΚU gԏ>rɣiQH~xT}kADrvQ2"r&Qꊗ_~Ye^ȣiۤI,YD}M~ sҤIY_rcϩS;`ӧV\ //abl[nիZDxJ&Ѻuk= "%dQAɲ16_!kXDW:~m+'F>I?Td06$F"gl~u|އ}.ˣ܈GիBjg #DJF#rV[|V%g5?h窡Cgܸqs܉3x`!mڑO&z9+bZ#M2)$@$@$@!@9klI 8/$/Fzԓ勋FJd<Y"=%sX?ÈmY)&u{7΂My=@7~MGxUfl?G%%%[yO>H𫑳r|&$wR/ѫyY8b u|g?S}^;ׯ"k%G9v5rVR]]E"]YNRHI?VAR,lٲ"ł-}k (g-g.D]ŋխPh$H|i+rX=K%DxjrJN5J*V!*ɇ~&_$:eˌcɒ%8tzA"V6B?9$Vn!7n>\ 9+yEH>ij<䳈Y7PrV>;vL;cj5[y@1cƨ/]+rKD +"vDJUiCX̔ ꘒYjlQQQ*DdXYI@-.Cr̥)jl^\>>>6ljG|fn<1иAo*N|I@fL9kv{&m]n6O>>DFF*~=ɻ*5DNH%[oU+"gm%)$ԁTa$?2k Osw^uw|6"fsY|i&YLX 2!f2[y Nrvl ueIHH~(gc/hM6-eRKJ̓=UnD?Uݑ X@rX,z,` _R`6\o)8#  :Y/knmcۛ@YmzEMn]aqVׯrVchȑ*UN]rzZHH!@9k 5q. G`w>ּJE{l{m \CՇ-n#ѯY뻲q.X___:lxu[ Brz(g~ 9   ރᣖm t Z] Ԭ[yfp9pretjx=w<ކVcg}ZbX~ݤ#&   ,gK2—{リ<؉qӰh3ćxeq7Y{e{$@$@$@.IK'E$@$@$tlec|{`DL)DhU̘/>G`H?DFF J{ݼHD'ލiNu(gZ$@$@$@nFr%  Zlef#=8'm!kZu7  ;NF @?(is?1F!j`?HrWs&  XHHH!`-Cvjf(5 EXkw]z#$10?[,LJ- Ybdtdi7D@L6Ŝ+|C1HKN.@bd fƯFKQ<_4Q#SK 5Hﴦ IDATH3N$@$@$1yes U9g;a%V_Nk LBʏ*NE6F#gd$NG$*4L@D~=-0DJCBjF!P4 z iY̙"1x$#JrvmSo8b 0x3= 0=i-    `ݨHROmqb(0%HDDV9;ቈ Q)>.峐?~p϶RIk#g/IoZrV"gEs1+- {1pT"!9R赡-gk@Yv f!x%%t?D' fuڥI܈-6(gwm82   &r֩qNNr'p n̜uHHHrv+fNdž7!/S9qVT^OO 碌ąM9‹˩ DX{xĮRpn:'ZC&YæqHeY'&`h"--)c-Ŝ!fa   ''`uYs$p_/mX#*N>urIH,[<+JבYڰVg3v6 l=uR:Ȇ0HHH\-)'d wFƒ>D,K$bMGމ6;mkQ6a5flAz.>IIIvgI̲ۦXSM5w gh::uCZqwb̘1ׯ_/bLx~Wm N!嬥YHHH#@9k'rQ(ge)"FrǽT;C^0a:s纼Os!77WSk5z[^xQI9siU7cBˣ.^<É2ڵm1:\{H![䬭믿G!%%Ek.Wʦ!==]ޕ˖-5UO4p楗^СCѧO)9k̵_~XhwLL u놸8۷O >-Xf S>q%׊SU19ۺ?4ǚCEx=^3ա-}&`έ"ixg8gJj V5M#gMK:]'w~w:yH9{5W} YwZmεw+Ud^޽-9;o<%A{=1C9g%rLdnBBhuW_U(++c=/BEȊF׮]QNUƔПv˗/WQ69m(v=CrVX"o Sɵ-jMY*UxH_yyyJKtߕCH䬩d/pU M0P:'Ѹqc̘1C<4&g%iy9k\kS׼;vN.LsjWv?w}[F>}뮻`$@$@$@FrгcG rZI!륑 &hWVQ5j_E"Ji.]*^݊!G޽[dIk Ѥ\phr˾Nr}4UO_35`HΚ#o@r5זp\dQdPU}9y1؇)!@ on]gO찺szͳ5rVHJ`u]YSa ]'% !`\硣ӧOXhܳgOv~W,\PM39 /R>QΚCeHHH9 P:qv"nrI/gvŋC_WhX"Q Yf^פlUO.)r[<],V"xE~hW$oNNJmg)9k%r|50UG[ƚpyC;rVĵ1eST#cBiFxH4g/r)gqͳ-**RwH[wVy%_L𵯓0t.VyrV"*<,, C QV-irAo+wgP}R5IwMnf~Mȏ4C?((H#?1n8YL 3|΄HH܇5gj;YKSIMEy䜕(YMU]b"Iҗ_~%8p"R D(U&&2Cn n׮z0O?S'r"g_4i*k9VM@``cLΚcJΞgHJ;LJV!Msţ>u9MYӹsgՇ r|N1v`رsF*+V5o0ruNi΄HH*pk$gAR%Jfʕa ) $E"nj+rCD펑*򷚪aW55crTSrV S9)_dr1x`FcScC掴䬹3UNs*#V@j۷WE YH9A]oIy?p 8q:լ*QD͛6mRENڇzo`"~V C|PQY~`>(gɂ$@$@$r(g]nI9!KPZBe]ljC*g3B6l=u:j19+wȝ%-ZP&ZIA $rv*'avYr׍)QPU'**rp,K$@$@.JrE2yXH>oog_:u Y''`hmݦ%}5%gM՛8q"F%$w6%g%RVİu z+Xْ6oV-N9|  p n̜1$@$`6,ܷ;K-ѧ%M:£F-*Y'&`hUNYI yճ /HZSrT-[`(,,T9c%_SDž 矕\ȍ+<쳕K19/_y\[oĻC'  0Dr­ Pκs$@NBrItmsֵasv$@$@$@Dr֝VsDrHG(g`9E   @9[٧u@HH(Ynp +uU&@9k6*$ j#@9[m1 KrHHH+: YgY)H PκsCra!  p-UV<18 DU?v,%uK۰h,L$@$@$@Hr'`}MԈ-bPڣ : ?PκHHHl%@9k+Awj.%g- \]Lkpuy7   !@96K͉"@9}A$@$@$@f5 (g-g.DrօS!  r(g[L$@$@$(gz9yY   0XHHH,'@9k93p!. T' ;G-I@`u@:u]֪4Ϛf3ZrvlHHH AaSf!;3/+Di'|)|lfSb<"-XĆ3o>щ#`,MNXt2(g-Ţ$@$@$@ 7rmn ~,܂?Y+]Gf]_QrvlHHH+g7!5co;B#66F؛#gYMdYsp̿(gHHHB`rmM5]uӑwmx->3c $@$@$@$` l9-04>[z=z4dm}]xz^P&LPZP4 6 8#r Hۼ^ȫ]lhkG0zTY-) T-H+Q D%Ag+g-y X9 ӑr 1(W/MĔHȱ3c71ҐZQT!+%9aOG|_ֳɸU\YY͛7?Ξ=F #lRP~aѢE*:7&&ݺuS}fddoAii;~x4i{i筷† X:gEŽ5 7x#z_~AfffE䬱EbBҖlk֬itfe!  'PEZmA:u"ga}=˞a!#g{q$@$@$@Kr %%cGZd,+_Zgז##5Y& !l,e!$)R䬎TLER".ovx3s'9+mۆ$>}"%7lˆLKK{W΂ cሏ#<Q+UJ-[`^u+'|RݎD>sJwǑ#GWI>C8q"VZ^/mG_"}O:ekbҥ {=(n^o߾Ѷ̆˂$@$@Ml@&q(]SG)g{q$@$@$@nJF9[HAdl4".'-GTP ~8*.$.YӰ4`< 9. aIq+@Ҕ,"2KOEL|IY=9M99^Y:Mܹ}hG !!R˗#++ >_|JwyyyxwWjCUi_i#Q֭ëꕕSxxxT%"g͛dy_ĮYr9;߮]Brauhe`& p^WYv&ǻ[&1ryGN$@$@$l@Af }RxE=Qል@&7>O PiDf^1N"*z < iy^~s1'-{J6枀!9rlH f]k-+,HIIԌD߿Æ Ûo y"Y%%n $RUHj.]*v;JiH7$g%V Q"r~%gkԨaoiL$2zݻJk ) ^vmmœuIHUM6G¦8{p>ymjN8L   $`jeyHKDN^!J=!𲳬`f-@y$|9-{Nrֲu?~8~i@j/{/ڴicT_ .T $5kz 9-uu}MZ9+rV8,^CYiX4ې@shgV[fi  "`D>r)?/әw@:u O:\1Ro#moyUۤu Ygesve{Sd4#A5+i)g-gW_Anۗ(Ԡ 7V__UgEe˖)*rV6_}IڃvD krJ*r_֙HcMNNVi4rvŊF^dqv5/~zXHHHMPκBs Prg ؅| cmME贱eu$5bu3d $@$@$@$`,[uIHH~.\6f@`յ@͚:u]S(** /^zehn+ٷ|=sϩ(c6IHHJT٦u@IHHUcƌ?3c4m{Fdd$֭k"DsePzTgߔWbE& Kr Pκs$@$@$@p9==z`ĉd9sŧ2('WblHH\+.V%* $gcbbp-8y$a…Y&>3=裏ĉHHH__xb TQݺuXUt7n_^'>#r… zj:t 6Āp}Uь7ď?Qcn߾=>h׮ݦ;..۶mCff&n #GO) vءxI2CVSRRc2|Ά'ƖnQZ J6lDIK~~~3gBCC/L$  $@9IKr\R,G$@$@$@J~-jժ/BI'xGEpp0vܩ$D+-[5K/AoL8|NyC 1(gE,?~ >\?6MCظqcEuL>2>C#gk.5ܹs*Aĭ1zh 9y  %@9k˙Ar H,B$@$@$@$g3<ֈK|WT^Zcǎř3g eE={ZBrrNf͚T " ֭[Ѽys%LXV_F.]TtoΘ1k׮k)G2]wA;sLDҊ?4slԨ'OW"ja Q/p/;J jڷ[ [%S_"^%HX͑_q{DJ:ٳ**Qw9f͚29{ij'U;WD!RDEv]&i$ǫDJTig„ ӧz{jlV"L8iTdHhCXJZ k"goܹ*W?<+9k  W&@9ʫ˹UIr@I`2*y 8xFQ I_JXMN]>&֚YS2iSR=H={U] !@9{EQg!@9 @ gY2^]y tysC > M"#N0[_c’u<qѬQD wà]K5m /?|z|"v)it29+3[t?$Ip׫D =z1ݼ"`UrV"t%"W"Si[%RQdՔyb5c ;vP9+EP]Vg~"yU߾}+CT)kn"ׯ_o?5% 8(Y]p{9+ հ9}މkVÊFHdR597DyI*{J0[}׉vUMzh;~.l$'kO`uUR n{"^+itB9+ŋ~z@"^ЭG}TEJdQNDDDQ6C_2J]ɫkKUVGk+۲eby뭷eWHH.٫˛9/[Maq*C3n55iǎCѣeіJO«T_m|`0\e d3߱i./Gc10wK;n7 ioƵh[3@z&.;iJJ- 5 weh\!zzᕮ#X&o|#ӄLv{NsIۈ\uoC[݄Mst{  c*U?gUܨ C@O_fue p۰q3/meq]g6'_ͽaԸvC|vK| ,ܛiwt}( _ ^:6jF9+hY.^gZj". rVӉ;X<Օ+֧V;P%oKYΚcwx0<9r$87xC =z4lcN$@$@Ir1ׅJ(g-4_oBVޟ>a#{5k*Z Y݄SgqCX{'ot ۼ YhߤիvXIh,סٵ.аn]߽7:Z[t[AVK"NpN7v=n;7Aֽ7^zHׇ?֠NJRK5ؼol z^1vi`=-:1"VKNr`XD͚hQv ؀`H 0782tT%gE$mj XUlVE׺Ξ/G l=om-TDmנUf8tY;`] Đj76ݥEJ+ejŰeo𨒟)pjDjX_쨶ùpwQ+ k~u|TZ?K~D ˜vFXNxs\Yv5W?ef k`ψjw]KCzᮀ>x#sܳߧ*ؤs>G݊rC}\`۷+:]&_]cgNѠA8t(&n%'uNiSb=J9kCpUn… `wXiFk XGr:n",`(Q/zJ4҆f5xgb,="fG-xcIJN~ҫԮ偶Ma((=fPJځ u>`D=VnX:xXgv oe}N5j֬({j)ة-{wJHsّE}hߢ=}l=^O?g=L yl?PYr܊$9+R!f]Nmԩ7Fb(Xߺ1M+˯PΟAB#Xqp,Rb7.(@H&oL0㔳65e/:t o'bЦOQĻv}HJksVY{Rh;:΁o>͹aL:u <7~ΝV?@۽"#XU [ժ9mT 0/ Mr㧟~‘#Gノ;⡇͖!   Pr75Y#g/bϼqa`Oa!Я}J{K?rVF[6wʵjO~@`fZt%٘@VgMWЧTĨ;WRS*rVd ݤxS|"vg?Kju,RIz0 x Zx51KΎnw;^0S%ʣL2GJ9{9'2Xw TAr[ĭ PZ.gsc?zmK<3LE~g\xQEv{AZ[_صt[rl7R.U[;)}x1^p#_aƚڠHxz+n>ZX!guNlڿBow=/Hځwԏ2cHT]{B_Mp9zT*5}}QJٔ@E|Mk$t{X=:U*9{wŴ p Gv^J̃VȣZAۆ͕ҏt]/m+Q'csrVq_6 _ǂu ˃޺A3TӗYS㧜T[-{٫V8·Dj܂z`_tm!ax=ҏw"a_U5TsnzÁ]*Q{ qSmezp)y0Vjg!9f6l!-*Eή8oV Y[Jzy W9y ؐ}Upff|tlJGIZ56~K䬈b9vOvܒz{V9k^ݝ[YRjHJz[@nI2eX~pzXb QzM[l=G=tnGX@0rx _@rV>j#32_#gݣn?/3; uЮ<YH{?-E1oeߣV+p҃=Ī=pT6Yi}W Vڢd<L C\٣ grZUr/[6[h\ {uwS&g~]i.^5?[WkQ:Ty|S{DK搨Ly \pÞrU]yqVMrjF,A$@$@$@-X)bϩC퇘Q講RlBK Dx-ƺXnrZ#a88rwr?[z_[7vfwZMC#tF#,wQ^<vbUaUտ;P.W @Ji?MٟLkPMݒ :;2dcV'E0C0>y 9NK 3[|^Il:ol&W!g-uQXؾٗ5/wW`{eV"f۵:ms=>zkodo7W'Q<~_UqZܿ[Ƨ]٢7wʽ\Mi]nIHH\rlf&| eZRx| 1~9(0>z8UrVnDL Cb|P=w 3mQ\JžOwB IDATE/$F^D{~fc@|g? Q!5g2 cCZi.,F^ Q6"==%-Q˰45|?7y,Nߊj3~ŚY5گ>XW߶,c ˖G@m@zuMka2`럮)f=jhϬ+ּ}rK{anۚճ<,t rY1['y7a½l[!O(+OY96D$@$@$@l"R_m!*^E !D?3 Ac*G(ZĄ]PlG 2 )HF\B$2<%!1-A֬i lr6ZD`TROB2%! $M^*7/-H HҤlFF#*)HEbBJ2RƢ{IR&g"(6ː={ " c;SvZ5/U(g/cce-Vg%= o^;:U#0㽸Eq/_e`GFTڟ+$@$@$@$pE(g{.'bDǶAffbtF$lYd!96 *.,)qIGHn2Ñ۶vяM)1謂`R2c0?abH~2ⲵBr|6“cZ" פkȟrD%BtQNH 9i|&"Zc@Ү8CG&UR7T? )uYqlnHqhY)b:ܣo^v RS6?)gyu= MJ$e(4BǣS₲ 5&gU IF"G"eS9bfl&&o{T%gH@%gZ> I#ߐ0 QS"۵q* edt)4זȞ%sQTz Ja;&RA20+1Ikfd9(ʖnGE!BeR #yP7Y#2AHLM;!we9{yNK9k_4Q# [%hr$@$@$@$PMrvƌ8s Ə_l _g XۧLJi/N+~;Й+zjL<݋d|:?<@:^{-RRRt^߽{7{JmX[ 1%m{x饗pJT_sbϞ=8wd_>VvܱjF* xԯ__N:Jj O?̙3!7VZ&&'%%2?[C3;cƌo/[e6Ŭ(./7? Q16-rNl#  pVՐPF 8Qr>hwlqgdd(o4k)i;`sN| |}}9*ۺrVкu0r*fKKIOOG-н{w[ĉ'[qM74FM傂,^kѣk׮Ųetӧ T|Odp\O<*nܸQՓ||r.ŋ1g,YDةS'VR>a:tHoSrV*iҩH<5jJ$MrnYcGA$@$@$A˺)`Ȑ!+++Cpp0WD>L voEnݐýދm۪rssrJh޼9naڴiJ" ۲ejC5kPZZnA'ZwΝX|9?-[ץHR~"WӼ'QQ?yU6|GdFGG+YִiS5/ً-lDȏ :tP{{{9+ц}["b}ъYiO!h"ԭ[111j!?t,WڗaY9߾U4{&MlZGKYڏџ/!//ƍN eNNNoBXXZjU?\]+&tرHt% 5Gyyyh__qϞ=SO67l`ydsG%rXD7x#q%*ΛCyk.uinl9KGIī\']bҤI:ɿkFRիO͛7C5va߾}u]? 5H~S<4ҌE1/ҖUu2Y]: r… xO(>@I-%%%ꋴD a$@$&HiCHYf!<<\} *SmI=*CĂ| v{ĖHHo_| W4}/#FPDkr#G )DII'OkРk"^=kttA#ݲ?ysϩ;bjEX#goՆ&'lw4s@~T 8qDg2^Ȳ_͑yW q),X@'bK.}:gy[…"ƅ&BWqD ^۲e|ro߾]%\~-k)qJhID%G9~?i*?s=غuk߮AƦ~_[nU\mZ-Mdvy,"X~ Q,EEExWU$as#93uHҥK9"bRRA7gMGSyʏr.4vHڇyJ)OGhTWEEkY:`>֌Ei"f%5r>5qr֕WslXHHHP3\>LJ|CDDL߱c%UФ ":"/Di䧈+0+_L勭%KRVoo/҆Ze]$|ԧN#y0Rr sΟ?_ k"/2!D%>&OCHy̱0z76(GAG!Lz(jyS:%e%%4o;S][c($W\Q:#zkڀ‹BRj]#ڹc/>Z0jHgF 2zx* gu܅T7{A>KCYG)YPtQ!mHkrn77VGJF%*g9>^Cc)x3맜yx.?E -;12`J^GABC9I1˛k p ڗ:'7!1'z]=1 h e4-(g5}SjRt r(M)a]5ݤ|bTs8Ze4!1`юe>1:hҖdbm|ecčv(`h:F ?́LӤ9*El\#Oͣv.750T2j+|:5TxLdZ4YA^ N7#4z)U)5e#8F:%6))ySQ2ړ9KGƵ sujciR-9[,Y1*gS hLy)dhhUS:PVkR0S$]c0F2yr&e0'ŷP2jV#53mxC4׼ouTq7+X=(KSF1v,E-cg<2%eynk*\;. [[nn)Zw*g5mkN+PVr^9o:g^y·akT,rLt:RB@" $ͯܐ;N)UǦu}xٲ痜hA9/e1G)K5yb[l(d&1iF jS9/ )I9ˆ>bB)Aļlo/I[RyӃP;(B5<~:gUTMF%jrRbԢ>9˼c=qC!NyIHc픳VyƋ&-PZ1M90g+%Pzgx=97_gZcw]cgXErr9a`%?8~SLy,[m:MJf1sj NQE?%%?Nd(7ouħ ʻʓF`7V>efS.>MxZBްc*JUk~hXsrT\c%s|C#gխzßy=>5k.3#5T#!H5yI)ɱP2QHf)F(|nJWJʹd>W#)5S xk*NEh1~M+oL&#}cEڅae 7#_ g'v:/獟,kT 1~}C#}Ǖ'g/]$-` d7MшS?XѣոxE_?PFB}9 f>D Osx1 ]vY9x!s]wqzQ1&q=k)X5}4hzZ;O&G{dE;tj@̯(_GLF|IKUB@N@={!gs۹)e!ףx7ul[Gxq]h:t},el(5O=&)DYJYhhwa];씕1;Wn[|TBw)rbw5Smn2b?… %I67kJ?J6Oˤǘyy7}kY^F3ҬYTb~Kl)! @!`@Z'1ul6@jLI|"$t:ud]0B@:O@lb`y%rVÀQ2gS070p7l`AQɈ(9}tNJf0=_.e#e+>9Xe̯7)s&$f\e?K,.&$[()s1VBM9o$I#0"rCƠcB&@Φeb麓x^pk\,rֳAsm>yzٚpoB@! 9k+omr]H?#y݀-sUK>}0}wTN++Vin6`eo\\S)4dffB;rRjqLiP E{H4رc!r\ӗK*!N,ܱ;YrW)B@!PG#g&g]g1ގpiX9۫t sʭSlYc2 ! &|x IDATBN9['Ue(ku7zdenWJRFjNFĔDjL&8]9g/pKm9hoVERR2ҕѾ6m-Җ|SwF fjM?Y?lyc`"g+\! @-$Gf\ߓCppx` l\;vC"g+.G! B.n rָi/Ii9y]ͷ,#[%JM¾`ذa~F2*%-7HR8p@E?'(s s4Ҙq)ut"Q'gǖ—gRFF15n]B@:A@] VŤS}{6@>5wG\Y:dB@! @% rN 0"g 9Yxɕvٹs'U[P^em޽1uGVs0ռ\ZRdzǏ/de]jlk׮tet(4iʕ<履~R^z ߒt rָu%G ! 63hY:H䬱x! B@XY˱j 5pRKB@! j#:g-++ FU_l4wJ8p>ť+%aqA{-͛7cĉ%열%9+ e˥zfq Q/e"m-B@TwJU@JqYԨ >痜ȿ{DVP PrW>Eںuk"g׮]$17.oL&E! /W3<ҼB@B k7p -ZP/sW_4{8p߿/_6։'T6{H<ӥ~g3 e˖!''G2e 7o^N!`FCuoNeDB@! @Q!pqpq]h)QXAQ!v?OmFBᑹ\btA߼m돮%r :IrGŒ%K3f |}}KE^piu릎k!!!HIIux뭷ހ<9[^eASzzz*ʲb :uJIR=e-E3 Ү]; 0@oC̙3~ /Ǎ###>l\2(! )DΚBMΩ3D֙! UI@lUҕk1m9Kʈ9sHSMYFر)Yz)|X~=/L>],hyr:Kٷo,O<zYJ29*)Fܾ\c潔ڿZFoذaaax֥B@9k^R[-# rMtW! "gZ hYvQhڴieEn˗_~dt)˱cGU(g˫mk7nhXJS[`*[[Rr+J`ں|g ,ڿ۷oWi X/B@XY – #`s:DfdvRn4k](r&ᕓB@k# rf\k r6==]EȎ7N66m6oެ"Os→T{eюe+E*Kllթ?(JjccǢր37kpuf/-X \fo۶ ?eZ[D0! Y3HgŰM4Ko5QضDΚT"B@u"g L$PVβ~IԖ-[*!{Œ]tQQL!pI9sO"gq?R 4nXIZ-N]CaT(JuYF~*IJOU]fӔqϟ?>@EB@"ge(N֛Oy !r֬T2! BN@zlSN%Ѳ{QQm۶UTCWx3, sŮ[=z4!n 37? #vO8b{M_Z̚`!2m(§r6"`y32M@b0ov,|PS2+4 rYׂ909,Bcpa3@M;3ˀ+' < /Y8!&4mmHM7R[ PuU;~m  vuj$|ACD*B@! j^D)S< Y٠5 I8HLLxO[&Ď`;'aQi 08'n\ߔ1 @DbpTE#l^6D=Oü1PHƒ(`R8z}9ȌD\r b+ݿ˹ز<7O'8b:S@~ 3ִq3pηY6@*kҢҘW2xh}r,oWxs]:e:'8L?iLjy\yッKL:ߒ' {9kIҖB@!`MLYkc>oOX9ዀ0nHv[Ao~2gE md3/ qv_%0%d(ܐؕX6p Au_7shy/ CƂ89:0k aQȟ9k nsY6 +ȽZ;Nqt6t-?Bܒ= ͛ǐпG0a9/am%KKn\͕_O,͕Tu̵L+Jٔ^eⷘ38zu@}G{FhߪTVзk3qƿQ0xN7~-Ա98^?+ 3-m:cS9¯Iq<+~M)iקqD?=7<>O-һL\oQ@ޅz״ST1 3 wG=%c6E쾓(cO ]ܮ5ҨB@!P (g &gbyJ<|뙏H+pBo %Q)GB/BnRHsӑ/O흿rM:돉T .KXn2FCLX*r64n0"Q69+rF l1HWŢ̨b]3cci:QRWY;[(-Ϗ$UY8ɴe)<6 -ҌGS}S<9;Go> ȩJ铳7χ0O(+ʃDz$=NˑaNJʬB%ym 7ݜ 6 qG R}|[H8urkT{TV^d; nN/*T?ύe:[ ~x2+RbCuZΌbm_}R߼o /'~+Wv:od[9[fD#B@5܃X0cn)H\<<ߑuIu)4%i B%wDigd#9v "?4L+_\4g ~9tɫgaApC:bj)|!15;ޓ11੃&rƮ 嬉=9[8bc=[ iSq2 l0>P,ʖi1D= {2غ&=TQUI{Ru:x7Sm.QnȐvg$㵛<:N0nhhExpo愁+93W.M0zHuLZFS!}(ٕ},<`gZhGXT^ƍݲ&uͷ $;-Q=tmrK!rVWI)e_qE o g{5\nhs-jεžhwŜ+\ iHV^7(Ǚv(otwn{RIyq&7v6}*N]>)p, fQtUu:܍ ;"p n`b{1v^׉J68u|ձ>8s3Ze]k9Ƌ.#++H9۲~kfa1 9GsRJ"guG;rV׸(+ꧦ*A@xg"7q$o&B@Ht9f#iKB0g3.@:̋܄`12 g.Bg L] KW"!%NpqF1<_ 2g,f@fDtblJ@='s*FAt3㞌E c 0C@"gkj9kTc\%#tsz/_#)Kˎfg::>GuGض*e4k\,]{W2RڝN Ⱥz,$FΕt5YQ;;It\JSAK՚ʬIVnY,:iΞ.չ K:A}{|St|D.KɑT8 o~7ZGwS7 (h;}[bӭx׿oggxhvwwn\uVQ:ӏXz5V~Eod?*ȟ*]p6/_YyZ}kv4~n]U,[s&Tl9|p`)4dnk9x{JR[GFu@xJ3Ar@U.lWWO%;|_Ir0ף1!_ R*|vTrv:CYبs\v*gErV>O՚am' ! VKrrn @U\"`w޼^pCN͝0:) QG5)svP|e<[6PcoFDl#‒ es޸9 %`}eJ>!^9N ɇݩ'߼+;ZN.mT\.)q{`S&?e8sԕsힿz3o B|IHDxu]E|W&E9g٧WA{iѼ q sE) DΖ^"gB@+$Pur6}/V9 71.]jDIX98 zN`D=rh!P?jY;w\}:9k`IYcY%ba?pL+**wGNMH*[Μ#x)_9%&(r{F1:buL ^ӭJʩcɗ71Ӯ`c>8r2[ݔ*{<M,_5+6'\b9"%\,P4\f^)k B+]nRW5Ioi61箳ٱ}{ ;,GƧ5`Ĉw ϼAE6tGAaseOe3'}AuVQ"gohYFpv>&1n#+s ү}Ouv|ОRrݩ)œKxe)9W;9b5^u<=P%|Yu|x9_DQ]=6ҧxi_9k_5I|iL#Z5wX- 1WKw tť+xNOsZgvٶ Kvtp:9k+rN.nb򵿾ѻywOYY>)+"@y㏣qxкuk5zm9["g+COB@"gkѦn gǴzAW+xT\/\/'7))\pcwӎq0傼9KQyY ۻPx75&  Y01U +u~rV$x֔zKRqh2=#rrN%@y:ac˖-1cقDFFbϞځ駟Ɖ'tFV$g׮]e˖!''^^^2e 7o޶m/^K.o߾xpI|g7o:&11w}}u#ߺ;22!  ?YMbuXYKvj+G}K,Qbv̘1+goߎիWc ;w.h9{e x뭷3}Y#$$ѭ[7>9o~~~uzB@ZA@l&dU9[99[Ubvy HhĹƝV]GQV]+_FZZ#$Ʀ[؀'ʔ-~Y#km9(?sݻu=r&MB^XO9r2rwÆ  .ڑ|]w}}eS"B@:"gkݔII@,ó+'̉U,O]Դ8-yV@_dMZrЖש>CBv@J+>c;=Lw?i/5|Ky/nRXUhYvѴiS1BWB*3geJi ۳gO%gWXdY]ʓߪޕ5iج׌xv| kBvăm6135h)r֐ c@Y9K?-[E2ܹsj1SNѣrv͚5رcj>PM:*ڶmoF aÆᅬƍ+I0W_|A_BDZQc 955ch(|seMTΪ:姷˄U]R/v{{ eY&k]rի2ee#g)M?SVEW֠, n>ֱcG̞=NB׮]p_T) .\+WwJr0n:bшV뛤5 +Q(@m& r6ϞDj!#4 bJB@'Hvn-{IYDMz4 > W. ZNu\&hm@p*"gMb*' ! B""g+"$i"gB@s9k.RB@! J9+ ª ! 9k()9N! F9k.99[fT#B@T UU*B@! YYVM@UO ^! 0YCIqB@! 0Ypuٿge7"B@X..k ށYZ 2Z! BbDZ 4T - iqw(W i> ! $P߮v*rւ3 M ! D@5Ͷ"gyxnGV/+D! m䀩hܬYYB@! "gTZ[?𓊜Rtsm=д~#nѠ=_to#=oWcsb__NG~ӪY}Ʋ[}3zWQtˡ/r֐W$g<Z;G$Z"gveB@! hif9kh]~TyQ;_ e#+o\,_cؕ~Wsʕ;/AWWO;.bQxaǥVsj⥤o+0H@x8syѧ oOc[f+!) cnhT*&!}Hjާ 9[3?SWB@F@l]QB@!Pi3"(ْ/i es*% 'g&b˹*B/!>$vg$"|t.CZDZLcߥGWZa}^s#h~h쇃wEC{'*ˢkV#g 黦$9kя iL!`DZB@ 9kD% rx9ϭ+v =W)>>MګT666JĜ?k9YgXx4Ky;3o}}8a&ءWS/ j]<ŽOP:4l<[י^e* [b}j@#X+[Nt .60Ƚ\k~!i^9kHE BZ ֙q ! " rRI@rryX5QG_E m"z5鈃Y'p&7GO+yTZО ◓Ԗ[7{ v ';G\S[6/u,#dGzܮ"}7S~ukNusĢ3Ftbyh BK&X򲔠e$=o&<9{{x6|RUyWH! j"5qVOB@! @]"Pr6 cHwI: ze#im4CrFw/VϪxwDmOσw"m-&g'TX KZ`fU!rx9<a`l>Am F*r!VQGF!g ! @] r.̢A! .gS̥'P`1v7\GҒvCv*bbi'&d?!: z\is_?b2LAβ&kbuXxB@B@, ! B@T-3TStB\^7!"tB7510:'r_ ` h-p4\lL ~{kظ=zX6E,wp0x_!dB42TWSW#|v,'#ka^7BI9;+'a`w䬝Y 7Ă9Z 4"cK2VFEam?B\9˶b>a:&07fnBS1= fc&"b(pϼ2i LK)GF@,0ugfURjW|bwz6řԩ!~Ӭ3>_jrB@vļ~)ό1 NVV{˨`! B@nf{"6>+7@>51f՛ {SB1fnn,慬P ΉFXD:DL3052gM9vBbT7o$B7C!r6" "#KB~l$r,!Gκ<ڽjrb=(#|Lk/MBXӤs太! Ϟ<kRvaC>AˈYn6ܣ?')"B4yǔnO9kD9K! 0M sv#ۣ/{!>.KW~_abWLeJ=M]Ɂ7hMC`A4"soXYuGگǜ@DݬO{î"gOEXbe<>(Gβm"븪N^N ;>AlUṲz]<`9wӎձ/8үfcErYAB@!>5h)rVB@! YFfcxBTdjBWYH8& ﬐Y#7,K`]Kf-j~7.~C4F§+ckd䬡co*䖟ފ/g*F9O! c^$rͰ G! )*-go2JFYuEvsn:bd+ƆwZ̚VF"/@2ԐYτEpN@tBlM_X`hdlDtFBL[锼q>u(\bҥX7*7!1 |,ќ3*$_k9uoeDB@! @:6B-YY=B@! {pwJC|J>cbV3\$]%⑜85/F +10:'r8|9l]4cR]y+&MɊ[|.9 FҖm+{/[|vc=3oLBdwl$g W LRѸJ^*ߠ朕 B@ XXaؽ{7.^GGGtCEӦM+nM9૯ɓkJw5]Kwr~!vﯷw/V4ͣ{. y7?@! @m&P 93<(21[ ӑ'O/r%s0gƒ >KUF@"g T,B@%7n޽{W^U'$$駟mK<{lJ+GPp8^k[c7vǝmѮڴg^~.:69[-89[!PKTBI1/r r}'a֊A"fAcSSf]1fՊK'LN73 N!  Ig)++'rss1w\M6zۋǺup%jJ\777a֭mۦ"myXoqx۶msvv.wشiիz;vDdd$Ν; /`ͪ={>lԄ[EEvs=pGS92 ə,.v;;Ʀ7CQ/\‡wy?g)|w \oOD8S9[{ ,;zoo?̫ '{[yܙ+ѻyC|tWWti J`㽧 S7 0[+|0DZ/O͘8sZ{{Y}:x#"$8{nϦX̸ׄru%BTJZ,o# rͩH! 0?K#G`ժUx饗$;;| }Qxxx(񙔔R?L'0|p%A-Z qFIS 9~)ƎvaJҲ>_~SO#"";w޸qK,w܁Ν;Fxgg;w-KѪ#/۱i?mm{v8"!+w-ŪQK}<02s-=큧\;~څe#{SgLnown^s¦,n{GguSy}= i>wc֮8sߏQm e^zqJf Mm6.ͥ4$N"g]꒜]3lvX/]ܲ&w=Xe[L8 5طoj믿|T]{3fU:صk*壏>RΠΞ=CjkׇG IDAT %x3bd?X"5rXt)xUP])v\?]Q$%@5SHC <'3{[*9[{4?ߒ.ДbJڲ\/Wqz \ԤAJƆHtHWu,p1踽s ~}f0^=?ƙɃ؎p V("gk!B8"g%G1"g؄pHjC/ W#Y_< 'N`ٲe ;-[…  ,9f̙xHWFj"o7l؀ׯ{U~=z4 :-}yU.9˓)wݻL _L_(5)ʴ.{SRr+HȺRR‘+rh[~ W ohz%Pd`x'uA1"oCTÿā}Fj~{MHυ0YӸYu:22j' ڧ@:P dWtiXPRxΙ3׿sxe#g)g)9-2'g5R2) ,SRj' +0*TWQ)>!-ځTEpvl]{*?SDmK93znˏ/Zռp*vV4kۨH<ɗ$] Yj,?W<-cy H0(R"gkIkT5nJC CrZ2&_:tPѰWF?^etlrrzԜrť$笧 JX[[R2Ϟ=7PsɸٙٚMؓp:ߍAK#19 _O֍K.3KRh~f!pQǏ oC*Ѭ✳/}O{ g\#{)x{4kiꌉ=Z,y7t]'Ձ)AjY9g~I<_F.%cY ;д-:WrB9[SgFe"g-Y"E~~> 9)Fa@np7\]4B@ %ys[2,';vPRII!CYfj~)I5d)h)rl֭?CE*w,_//r}o|e]lENT\IkP/"@]:7V9Zmmh\1[+tj\j=p^_tsv1}8g{;ԧ=Un+ z 0mSD.T:W}`F{'YTܰc8}*5mwy÷yr,qؑF>JB@e"g*$`MrׯP{lJۏY~T_5wQ3c+5Eʚ4OeXʮys}[ZZ0RudS䬬Jc d[[+9/r֪ ^Nס9^k J! DLNKI>#j&N(,b]BԔ6۔Jc5YiVY{v9ּ9>EZ2 ! UH@l•k>kǎSl0g7`1c^XXqCPPPI?qFL66O<fh5U }}3~M;R~.Waz{i/핑]< k׮Dhh(f͚eҬ ڙ7osq|jWTIE*D|/v><<\mF,\ 4Po4+3su]tO>x'UKc:[\"gj^! B `V9[F[???zكHYW?hܸ1^{5%YDc}Cwth莭A 8~T]Yn,COqe频P_|E&6Ie_^tumS[j̺0g/.]ց… Ѿ}{/z~,EʊB@! @9[5\ZB嬽=,X`&a?~<УGYχ}*37 > ï wwwpnFڴ!s&W$iGЩS'xzzئqwwǧ~'OV³g)~:tH Nv!>wArV3,S6PQ2gR29[Ӭ 8GZV:|uB6%{%-ge2P%YD7Ԩo'N@<}6mڔuw޼gaРAY((6Ŵt|)z.N>K.gcY Pt.z|I;Y ,`L 0&CXfT5O@_嬑x֭ՆJjh޼96m*2hE?DRv)GӧB;VHx9Qd%~y1b 4fQlRRf̘oFHbfff6Ҽ B{6<p g9K{HփF^Ts.\(b۾}8 ܹs=$cbb*(ףGzs˜U֧2lBKYK3)8Vwleq?p?t 9['gtT9{=zT7Ie˖a[n޳!;E?'+zBCCşbSYL$g^z4h ~KG"9'?ԍҺ^Q̗t-q`L 0Nի9e}>&rrͮ72T=(=5!qmܿ_ٶm[JOW^͛7_+r۶mË/Df#ӧ A(WΒ y/\IfJoe={VdjRS&TvP.XJUr1)-gI&QQfǏtR7"2I)ŰX._,b([ZRjTY\hSYNX/krm#Dƻz9[ԸW$gP:4i4iSť@'N֭[yܥYe e KDAOc2e(Z.Y_rV"`L SGe 222fRћ)jT>`ŊYe1-'\ʼnR7/FŘ̟֬9>䭙JR'gK#YR\`L 0]"rVvq$gѣG< (FtXtRĢ,@a(Yr#Tڀ!a@ۥ_ΩݸqC7jR=C*@Tŋ8|#aLݷm 93M$&bVo___Qn B 9>i, YU֧V6Oi,˚͙{zei&zߒדĥOFЛoԤ3gŦ#yeSɘ̟+7@z<5S9]j)xg9KQseL 0&tY]- 蓜<!K'M:X>>N$5gpX"9Db5!gi<:TJ",YD%IK2)ǎr,ݿuVqAr&xw®A N9qaڵ"c"KNSN}>x8rp(oi)VOelBKYSƤ( >.*g)~6R*-CbpvvF~RS{*EC) )Me1]sApٳŧcYAE(ysDk\O 4&g? Х:T+ C 󣏢+ʜ *,P* 93gTJ)ݡ_i0u5M9KcS oVtx";joR0rVYV6OiUPK3qqqԖk?B3hK`Q7(jW]Te>|X駟w+{5H5ܹ&b^?Yjxc;&`L "rCA OCgMхti"9==]tGo(P:XEKWY5*8ܧ]_Wh@Qc^S?YjrW/&`L &rA şl+:5Nv\V,EzQsssԩSǺ<}qP-O3*+9rveL 0&Y}=_?Y=_~fNF'jܬ0N'c#wqYE;bGhƼγղh=_`sU*`L-=<`9S(XΖmEI^M`|nX+wS8T\Y{T\Ҩ6rڵѹsgԬYS {1}0b׮]裏 ߧ ׂR gE7HWNT"^frD* ݋MqEz': c6JQ:ehUmMy#1_S_ 0&PX7a_ T:Y!ZMLLpE$$$y8wxm[.V^1ᅬcǎpq#t钨G{ CfЧOq_@@N8/^LיzSkܸаķ&LLꈊ匰S&cT~>֯oü~|c4n螾NU)ZUbYD%b[u,T@~_<6`eٲǼB%Xrx0`I܋n׭Y*믿⫯BRRVZ#FVZ8<?~,JݻWA.\\\yflRյk׊R Z˗#!~SRR?cDFFC#{%-[ĵÇgFff&~7 6L̙3Bu$]&Mv܉:qM9BJzvXӳbR_~o&VӲN5$[m=k۠xYR::츎=\ OCV}t5341 m]^жF%x=OҰw#ĥˮ829j[26 6E-9S6VHb:Zom}%y=gq8=SN50lx&4 G Z5 űw#&%ȩ]5lcb} vr;:%߱@b\?݌L5`D.UXj)wXR9<mZ g?bܹG;~ý{Ž>MCx>3 BG{G ~8( {{2P hp vJ(̹U9̫F)kӽ0x)3ėYhx"%?:l‰{jYe07J(k%cMyyWo#Cs 6C>"}{̿(R~ere-)AĚ8Sk$^nF)Ϛ 0m'!9C[q8 Yb#k啯? [EWrMIQ< \i%Ia9CSeL 0&J٣G"&&F7޽+&9kjj˗ IٶT2W&zQr1eRZe$0eRIۗE".Ez~FUҔ\@R&U*滇J qr_`d^"errg@JN7sz}r_;yskފL㾸=xߠܺTV欲T6eS-}Rٽk#dr'X3BMW0nU׮FVG9#C|ƩX샸 |3`L@~uJX+& ЙK #gufq92%g[MU3&`OЁ_$c/\Njÿ,e9RԜ,֐-Pte>}T}urrR*gI.^}έ8kUɜl_IY{{{1$@2{FլYlGp@{{ *+i@ҳ[9X<. k&Fh m*deA.|6+e-}TܚY<D;F'[8nsԬh* ˭9K7_C[NGP|rVY.h[bg_wxYb w., _:x\ }4FZY.xLTɜ%.[pL 0W4#gCbN?Hc IDATnq;Fjx8|aưvl^0u[a٩/z[#kbXXE_;1lͣp!x%b$d_xnhm[q1#F;N}Z&'FbWrv?vg.';〞h?1#,#_W"͓lP^`L 0&P<JPW&ycCޮcͽeV6cŁqTX,͏=2&@Y!9@!!Bā`5aH`Rrw'w!lxtd}IB=ayݟ\09l3cOLs+ݤ_ë>qtϚb$s3]#Mzx&wŴ+-Nn2rVkұuձ 2&`ClpQ@ϢWl&,bzxrL 0m&Pd9{'֟ ALQ3jXe"6$!Y} .F6b[d'GrSB I6;c;ˌSC{`*Y%I;DFW802{G7Yg9[: Σ2&`:F嬎mO 0&Eq-.D)Z!Y;Æ:Qn(gͽbSͼΜV5m̑?|E欑2bt6n!q<7嬮ĸy-ȋ`L 0&Pr2>@ 9X;zVa`9YyA3oe!;MU7SN/d9[(l|`L 0& "PD9C5+;e1Vw|'&1Fe=(bj7ଢ@ș8tpom/#R9[&(ebyL 0&JE@JHaf4iWWqbhkQ-:: 0&`Qf"Nt9AaCԦ6!3a0Z6:G;b@eJ`*<`9^M21\]]տYwoGa/?c˲0|z2dڷo_P^Wg.ju3&v9E3k&_?N-rz..r٢3`L 0& @618,SXڻkpҦ9\3f ""B!~SSS[+:(gU76l+gO 33~~~B.Y5j}2`zK@MM棏i<cP'4s r̸<>k4ͬ2k; d9Q gL 0&t@:@uEzyy HQ^8q"~mG"gIhժ Π t&LÇzji5MwMlٲ"}PB,ػwӧ;&7sVQ~)vΝ{tӧOA%ƌ=z ,, $K; ٳ7䬲>i~4MVΒľw.]*vzzz%LqqqݻtYZ×_~W^B,߹s .T7_`B@Q}&5,$tFrp欮ϓ 0&G,gqyyIҢI8@LKK!AǎՊi9W_$cm&D,eR>}]qF1&#GqU̟{IJJȶݼy3BCC1w\w{ eKe?oSN)W&g% hUKuh۶m+D\N>- J-55UHdZ#IdI[`5P?—57&(c 1)u:#rBJJP@B޼*f r?O*r/ 0&(SXΖŨK@, +L$n$z%q׮]BRf͚?PUإFr$7DIٶf$%%aѢE믿˔J–25*@= 466V)sVv>$Yo>;s̼KGe˖!999r jԏ`L@ (!8y=ޮ ˊ&mR C`nf$* O 0&{,g>>٢xat,5jȜ}@ߘ<~J P#Kr T<9+-UϞ=K.6mY:slQ#gL r66! [?GrF/F9k[f7| AFz-;_`L 0"rZAP9K([{s2EғtI^J%*+gIYƍڵkaaa!J PSt \bbbDf0uvve ?x@M,Yc`L $rؕ8rY%- /S9;©}+~4}ɈI3&`zB嬞l4/S>GFa,աC│X$cQX*m L4 NNNrKرAkbbw}e>5:P~8̫0r!,K;;;(T8L gUG"뙀foPޞ={jC 0&$er[yQ`9*_G$g)Õ`L 02KܭCʕl&j6mлw{߿/JG5'O\u|(N@g 4(POnɎ_F t"Cqߜ ޽+wty%Q&`9S(=,g}qg#0&PE@J+he_]G٢&~kBwfWSEa, - թRSU9ŋCܘ@IcI&&&"55aaap႘-VqͻoN*O>-W\~`eٲB`9[ht|#`L 0& M &hmјԝ T;ζB;Htk\n,a9h" 8wVӧ^:/Dի!QQQ8qℨuO%{=T") @\۸qc'&}ѡqBWi@!(kM$gO:={_~!V*9ken*-Z`ԩ ;V"g%%*U$s5jHiߙ٢dڷo'*|^d嬲y5I.AcQCy斯sҗxu2&{Xޞ5HarWL 0&@N?$G `0PXfNF'zfU`l`|]]r>7յkWqtl||x!KC5:s-H&%%aƌV Je3::~)ϟ*rJ!4Ia,C!t`zM-=zsIe˖ah֬e#g]Ә1cУG!`zn~mq0=Ωי`EliqY`L 0&JI)uڴi"URs֭[B=ZKOO=IPFDR߽{]d!Ӟ?]vo߾[.ʕ+BM~ JHVi9+{_(AΞ=+pP&PI`^~]T&[sӦM022eWK꒐{4iSSSKVWҜ7o,DXmܸQdfdd`ȑb /Ω=י`EliqY`L 0&JIOOOqg <9K$#t… 1}t/_>O^x'O|.´d}AO|HNNPDJr?MQ.S Je7 YuLG%$> *d͇2mIQTր7yM]9KFr~ÒFs\t+:sҢ0&0a&L@_ {z0$HS` !DkuyL 0&@q(E9K% ֭[ݻ$Hzѩ1hj2g)2geJ!P-5ɍ Jb+V@ FT>/ ՜w% @;HR$Qݸq[l5h)sˢt͜?YE}KG˜kڴ(m YeTa͚gd3g{3g՝{1&Jْ&iZ<&`L@[ %$$HtHMG5g#ߔ18aaDʾڕ"S.}W\\z-Ak֬rV[cPKEqְaCP:MW^r6&&FH9JOJyCHƊC̙#ׯ_/n˖-ߨ9KAxR7=4g`` 2o)#SE*[%|ǹsEsRgZ&@I`9[y,#rV분'`L h#RTsd,SI,V:ȈO"AKH;UI‡N}'NlmmEY:,o>ITגD6Ɵi޽"f(i, Xzɓ'puuqLQi3gbÆ 8}40dFשԂaaayr2XIhGq)JЁbBYT Zղ'gbŊAIYuL 0$r$iXZGm O 0&F%(gq<'&eR;Ð4D%̍ 0&X.`9+&38Rp0#`Vrz8-}P'fH¾q+& ϙ,Z,k39t@%rVk'emGy=L DlA2M퍽o~ⴜ)Pg`JD9N|pz,뽽HC@d]%P՚^Y]N7`L 0&XjY:8 fqPƽDdWïӪ/8U _T DLm<45S@zRF6P&#Ew3&`L@zM,M;]+jO^"ASWٴ㴤wxӧ9˭pr@v.ouUZO#D'PeLJtOI_ԭz3|hْ1&`zE^m7/VY ]#@ <{@+0[U:*W}@܀bJbK?YJt1nq.q$*EA? aѻV+(O2u?e9-`L 0&$er[yQ{9K n}O6)%.D99WV;_ ;@Fu]A weA(J:ק1Y/1E>X3G_6xkQKlxh8E>꺶RK}w e 4`L 3v轜9EHNA|Kelo }]4U /!)߬wBV5O^[N9e/p4.M=vR|7&m'YKB|>n&H%xҩևc"Pb㤥ggAjz&l*_{4tΓAS,L |-Bb@sGs[XZl2wc4qO-&Ie7[x ~3kg  787u-39D-HʀWL Vۋ,:r$̽9ORA$Z%rsᚳ%›aL 0&Ys^,|[Y#Cde52ѦћHމkϑRK%"4U~U~.X>>~ %$/K߇qz1wGƊWG1X.(g$gxPo|uffvʝ`eawքY9$` xI[X:`L 0&Y=x^v.٥["4*Eαԅ[PF߷ >)UL1XT|,΅pV8BS[NoMlAbs{ {o4/g[6x]N!5-w^N> aɦզ&:6úpAUՖ;;,JtkQ O7:LL Lm,AX-0nU}V3svU뙨cQMdu.]T?砊%BSc!!P5Y9KBsQƟxupW+{zo/ZLAqu%yMF`_!)kp8*ƻ =&aKO+6#R@R$er8v+]">p9i/@swXj,m6ތ E'(z_x9؋KM=k`d*:rVrYVfL 0&Y"`q`97lT#ۙ-ZAICFfnpQXNnЄ|5gezF6wrlZ'kcaq ͘BRF<9{1ǜq+&P1y(ΕmfѸWMAT-_I$'덏\Z?$GܸIښÆ +FEr6 >D.y *Ir6N7ÕF9`L 0ElO^XΪ/gĵP!bTƈyBu\YOF}7^fh+]3w]X痳2bC"+##3  a.j[Cמa`71KRbr"kb|r$5yy3{r%=zf #Of SCEιER b4<n$>Fc9i/J*dt ]fV8kϙ`qHPlAJYzSdÿx|eqVǯY+s{pDM !=ub@ Dݓ{?^ eņ$G/i,q* OrXYc9Or&`L@ճ 'rV}9KpծyYD!N\k?ў|b{UHܸZ'g+1s+S_1wm "Q"%/Q\b:Gu@{.:ɪן,giNLmn[9Ƅ+]76AHDr>1'MϢmETl lawvvsrм(mbhqK1fY`@8T .# "K5wZW@à]qoh!R̚63P܎J;1&`LpXUF}8e 3^:jvǩ:$ڒ",f{zklx&13O6c1&`L@Y&rVj!{p ^| (g)[{S8-P'f&<߁Gm1u3_+r6##?-[=Ɖmٲ@vkyNL 0&Y\q`9[܄&`LL(a9;n8$%%Cgll [[[n.ʗ/_dgϞի9s&:uT~hL:|OxL 0&`9X`L 0U hΝ^gر...o@аS͛YSZ`L@.zM^o?/ 0&P@)iӦk׮b{n!P7n(gA󈈈w#11 ,2ٳgB# ɜp>,D{9Ih"?~ׯ_>j*f͂ƢA4sΉ#G̻.''Gɓ'kkkj xp [7n@rХKqɡC5(h-sǏuOi bjuL 0&tY])g`9[,XS&`L9KeH۷FFF" m$"*=eƢ~qrl||<6mF HYܹscI:277+VV\)RH!Mرcѷo|c6lP^&-m&86믿En\I K7$%5g333 \<9?/(AY{x=L 0&Xr 5EF8UVL8`L 0&_YB3g rJ&/䬢ܹ3f̘L4Iy JY~u͚5011M)+J*/EZAͅɓ'#==4Ƙ1c@XBHڵk}+S};;;!BI➚5k]eҒn$8)"J%ǬT/х ",,LOE^bB}O`P&/ImꋲrU&='bMlH$ #F):LZ;ܽ{WaYESɫeL 0} rVvר\4go{{`L 9F&]t5 -H_ԇ%ɹxb;dQ@"LI(RIo/^^~ԨM8T[Q%9JxBN8o4zƫWc׮]x䉐ÒVV-,_\|)J 8P|O? ^2 2ҐT&}XFY+ |:PVEU>=˗oLOЦMω'vZQVR@[nFUn7_vMd S-eJD>\YU+/ 0&Yv^Y`"s[pr@v.ouU'p(2CT/bL 0& ݪ7獆vrVJ5dIDRF&$@`,IYtEM:TOy/HRV*INKKK^8LwYu{r Ԩ,պmrO_Y*pҥYuZd嬪i"&`D6ϥ &^RK HbvKo swwVQ$U _`E&Pˬ ֵ4-JuPIq2g݉y#źsq6CNgFRŽFDj,\o,_X ζ!la9?`L@ժ0&`e2$ U_ήj=u,,w:ASK!U?ѹ5Ҥ$%rkV~uG#OPv,A �o} qu%V}w#8)HdR\z C!Wpermʎ]'>rjtU]QѸȔ%qo>QFtz/2%# 0&ebyL 0&`9śS+~,g՗bc4T"*Ѣp9WJ٦LΎt*mIq+恐V&XHdYIF{ S,GJϾQ7p!e\N՚]MOm=>-N0V)TvUHx"m|F2ty&(!,gK4`L -zp"rV}9kl`ZL˒$}(7NvMv+f<%$X)kEF2>o< {\@tZ<~h>//Cz45Y*dk+VBMy+,j>!g^ébuzo/ZTcOe9?>`L@o՛2&`Dl)aY 0m *!6=$U2p!.TsX%dwYQYS;2m>ZGHLWL ΄ych.@0#cQP~EyCYz,@FK|4\qAB?ٱjw'şǢf`W2BDjl;m49ۚ@N IDATjQVҨ$Ÿ> ӎg`eٲ&&`L@զ๔8YMrrVp>~M Fv=?qr َ ӝݣ > O 0&Y`L 0&P-K(<E' EU#=%< krRk$Q!9! DZ[&&`!r0&`L N2H,0)]K0܌ۅXjaゥ~ u?`L@]_[MϽmͫ U8k5_`L 0&rVg_D,g,UnK]zس83h)cj[f</m 0&4AZ }0&`L@zM,WW!b:\|}K{wh*p>!Y̪D/bL 0M05,mfYM>`L 0&rc Il.}O/bMa&`L 3O6ipY &`L  Μ-ܩ`9z#IBLzl!ϓ 0&kS 8bgrVC&`L 'r#B 3&``9*) 0&`j`9.`9[v`L  ł;eL 0&Y&P^$/ 0&(V^s2Ta/fL 0&n`9dz/"YdH/)D7q|;`L 0& rV X|)`L 0&T'rVuV|e$Pl5epxIL 0&V(=ܹs1`5J?󀎪N$z ЛR H MEQDEAzC BBBҾu.N$SL&dfߵ\}s|={ij>kƎ3g믿}f͚7nIv>~gرf͚)E7[m r`  ((U6#@qf(iHHH 88vZ,X:ZjVzΝ2e {bԖ2m4ڵ FƍqiL:kVBgtj>hgmA6HHYgXe(    @?VBll,kDЉ"^x.\@hhʦcҥvVÇg:T;w0p@4mo_*v޼yضmIvZGW_E3޽;za?s"VWX}aȑqFkxG\t7nPիWСC3e!?~~L2*#Wfn=,d67_~N$@$@F⬣(cbg   g%`'lXX{=t ;wo (!Q'Ζ,YRӧ^@-T~X"4i'dgNDqY,\...xW_~٬O֭[\mڴ f[oi܀嫏cuO<^z)Cz!yذahԨ (qZrsas  ptg}9?(2@HHHH@;g=MKKSKU u"{F5ԫ-Ԏ[.֯_DF/!!AS 6`ܹjL777|*Cnɜ8+ulor~w|s3YFD~.)qVʼnjpc-!مHHYZNNRg-%$@$@$@ 0 ye;{cSS3~ ی3VBʭѼT08+}%W*H}+u5_B̮QΝÔ)STVՕML]t?뫍ѶkN R@KMZ[֜5|@$@$(:y8)Zr#"7j6zhL0rxDjjAP:uX=B~jy @0Ԛѳ}(SJ廋1,|Y|96oތ[nWŊ38ǬwƍVoU=z(]<؇HHYg\u9 7"Z… F"EFqVNȒYM'ʍZ%l6|~f!  #`Bx.GáeLA+T #BCUt_;o0jHL$@$@$@G =C"߿_ef+[}gMva+6se d kƔMH(Z-O$@ND Yɜ .C{aЎHN3\!J$@$@$PP-pKFmIٜTݲeʜ1bD׬YcǎwUm߾]BqqB⬵cAN#Ǔ Cqo%xK(__4>['!1Ag<8=   Ml^>:Sg-'EG߾}1|Uf@5kΝ;;f;wʂR5g8{ZYˉ8ksVHHH q|]LD&P ibE= kvlǿGeUo@rKNcUnAqqJ$@$@$@K =g-E":u ƍS5hATT0`TZU xbU{V6{DZn:|$@$@$@B cƍ:t(ZlipJ/_Ƨ~ye<,, 'O̙3mҥK駟w^|Q7l؀sfg…Í7$ /dҤI1¬]c6["  Nl_@3gsƏG 8 <g?puu q/D۶m1axg:wq%~Ǚ>w^{5 <!!!Xt)n߾wy>3ab㭷ނY-ƴ ss$@$@$(:s8     P>|8"""SÆ ',Y(ԪU oF%sVN:aٲeRgz5sv߾}m\xfR"U&sgTƪdVR%;v,>@>.. ŋU6<<2.$;gY3pAvڵ%J(AV2 -ƴrp$@$@$("\,kE–iIhй 1X͉7E  8 q>۶mS6LoA~Y+V!_}fl .`J5Ԗ/_jgΊ,sqge˖tLMMUkشiS+-$; 8@ɩXN,4YG"(\*Wna//nqPakv7P޳caQ` d|ges-ɜ:Y+gԀVZ̘8+%߿^zɠݻw ױcǪcccU\9+>Ӓ+*TH ]6eCѩbS|}f N\gI,xh>@8'qVj[R ** 0`U0jXJ $;OZjǾ hРAsYZpa,Z7oD:uX̝Ja%a(]YƔros$@$@$ (:*sF 88+ neܽdl=|Jy!zqFZ^|skݨR7к(.)e埱Ezxs8w*v8+ 7ObSa"Z ~x{8.X3Ʊ\a8YWG @$@q`gAӌywq/1y+y5p4UҬظh!<޲"mZ^?}66 ˨5}Yztfz dz5kkO7\CpDklV.12@ԻLt{xaox{xz/H|rx &⅊6ceX{E2o[ĠSsmC2ٯFG]VXe xyF0j|?%-n.0r|01bTnQ6^J!)>:'^}l;b߭36Yѵ{pe1Yc gPb%@qrq6~*>P n.HM{nP~@4yn%+1["Y8ʓ50㗓| VsFcb /E܄\&s(Ί]Q(Q)ipqS>&O9 'O@Dϛ7vB|J8O,:7ozJe^{(b1Y`Umu65)Ow-%| ch`pU8{N"o%O!z 1wQP Ȯ]2Vnxu%4~Y,HO,nq/A2* {ʨSH#ꝸ$>#gbS5(ΚvWl2 ]ه J:i)i*`I~X{e/*zœn:q6į -V*+W'+P*W1*ꏩR3mnVçƆ>GJzAzU{TGQ1WR_6ߺp g#:Av=Am׏b?= RP,]/8o1^[bm$CkYǯ7W4*Y¶ &. oG͕F%jpd:V5JUe.~۔9q֐=Ʉ5tnmC|#ʜO:Ӱ10f Z Gbep=1}Nɔ5 IDAT5)111j*6    (227 W aC[01%PS5|Q\qO}F%q_Ɲ([ϚExl>7U&>T4Dڽ61kit~| MjWN!!1S<:Vt_qu F"n(:6V`h\U&@zYJy;JmӰ oj!.!39GD=-\nn.0Err"гCR]Ki&u')Κ9 f4*e9J8j$JQbS+lDT,֡cz|Eg'`\>w8{6嗶!.9=u>&e*hhR2`pfWUHHM}ip̔T%KREqj%w/d{o6XR 5Q.9Q1lnpy:Z^KƇ{cKIo` XcC{c㵃JKOx Ki>{Ũ ᝽sUvp| yw~LHI2@$kY/"t0>?:{CvM˶"X0Zlh||IHHY'XdN8gξþ+x)S8WԿ ݚsT m>f9[ηϡVQqVO^cnCٴtnApwsêxد୞uSXޞ]3%ξr=%&U]z!DѕhR ɩpL,﹂?FdáѶaY]~U+z#/U/w#Yg5\DV Lڔ&U٧VbY'ΊSx9bW5;aPz C6$+k585ԧG(ϮQKvcw9Hƫ1 yϯSE՘8[^)+wb֩1'HĠ9FA9-kat/bT2N)WsNRE Ew޹O MQ˷ܻif+;YU'Be7:qVjI fj{Q,&$铆]T C8Ii%@qrq}U j WbUjzz:} BWg֖DrJנ_T >^,7+ϪRɜz:aطq?%OEWǪ)?B8vw<ܑz"*+ꡲWu$J-䡍*tc>و"rVqv͎ ` q6~U%$K~KIMSˑRz<[8cqiZx."S/CH*t0sj%vDS”!QI2guv>7N_s*R-ѡoա#T§d%4ɖ Ru+oeX>k ^6`⬼^Xs1 +;sTD']Yf\pfK9aYCNbT/ꁤJs=) k)UA6&e:횁{Js?^G'J>p-6c^YC֨D Yx։;NuzϪtԙ]zaY HqV$v!   8x<8k8+ጟOfdGhC BPe?!bkvޓ73Rv+֭&$1jU UY#zv\2.?'[ nHX9O>\>n$YR6]Brj^yf*rg/?1}!z< Ï/bhZfz ^D,Zu6Юq9\r.R#})l`S/9g]fdԤ|B>g03gAx c),VV "l( bٿz}QԽ>w4MI4' ¿:JZzߜ]j- #d|T7VnHQLJaȄh-Q9ziz]>k8HN3gs" G~P%7< olfh-ԅqVJ?Wo2ۣsc6g%{ݐS|7:q0T-VN,GAߜ \V盜Bnmlys̝ قJHHH 8[WYYɎ0DFSYDkS7UmW] x 6JNIŇ6:mQ"퀧j5pBWjUԖZ7JFa勡zEY~ѱhZ>ۖݱvHw?pr,Zq)Y=C׹:&.>\Ӡ8;kΕ$V<|0Re7UWAl},<.EƩG&\ӈ8{l4q6kel*3oO6ò.p.(VFe.S1Q-jjJdJVqV>Dy?c! _Fp,z[DH#"Ifb Mt,:]ݟdBRڔ U".5`OVl27GVU6(ή=%jPyħ$`tA7\;Ε NTCT1AEJӵ/o+ FCZМЗDNbTl=S )wOMgp-E"vF=h_c#KUVC!6gCZjy`APqoa}n iHHH8[WYY}Uo5鏾OP?(`!uh+n~g a6\Y}eM`#Jhd+Gnn[ '\{Q_Ax\lamyLN3g1Fvm lZ[϶A[ذc欭H &@q(L8vͷ3S[ .@)VoP &%T MnHf P$ ؚ R 7[^܈g񃨣8k/g   pTgue9/M(89;~c@o .~c}W <*o왅w3ݐilAڦx4p?Of] E2o&;5)em˽|*ᩀ(Y4v8v`Ds"qqq̙3Qh ׾^={ij>kѢ+/'xBU ݸq#fϞawذarEEdg   Gl[2:lKg'#M[b-xRKFhj>IXk:HHH T, .q?w}I_ŏ?5j࣏>;\]]sre`%  gf)H~pvqVJtg,ґvLfỰ|]6eCѩbS|}f NRu HHp Vu )2gSBT{1qv֭?ԪUgAhh=rH\p!yjn:>|8SC*{J"txCDSN!>>%J#<]*#6ׯ޽ &7oFZZ:t_|1C`}Kyŵ]v~Ф$@$@$P(:rr2pvqVxu{2zxs8w*v8i&bYf[߷y3N,ǣaEfXaFaS;oC-9#Czb͓NAـq |~' :L|`7kZj)qSƁ*W +Wλ(QFPҥKoec^N|ᇪVQQQJ o}AΝ5#⬖A!::39d% K{ql?իW '@q(Z'xaox{xz/H|rx &y`Wږ UAx[+7Lj<ocؔlTq&5Q#ź)3HHHF[;v,>3%pN:˗&޻wO IIIhӦ z6/YreLZ <7~~~oooo|'v5kwyG1V2w=s &N8 6   %@q6oys4;#@qrqVvo((4%JKNOUr|]gp z`qQm2$>=HHIBL\ '`ߚ1,KCm׏b?93E焾8۸DM1,+2ER0~o}u^,FV%!hYl.4O$@$# 7TuaEܱcVZ6 ¤!zK("oҥ͊"˜U7ʕ+JHNNqV7ٷ~͛7W~IzgϪYkEQ۷Q`    Pp g-gk*stT]U7Fda\MVSCM!AO=LV(QϬFYWw%6+U ܋U }*2_SejZwIþ8}`Gq%6닳=GQ|}vs.ͫF):еS! G%`⬈wV m5TV8{L @\iWKeT"Jԕh"xyye[~G ʕڵkUf%~^m$fH9+'pA9sPdIG g΋HHY\:W(Z.fܤ*T66`= 2m;+QNuzψNj.AjMҮ\(UJZk܎Ses ]PϿ*Z>1t T,9U}R T)V3NHH {g(RIՉRsVI֭!ɿts2eYKJ^{MeJqV[R׶SNB!XjˊWY:ݻw#22;w*`9unZYɚ===UVԜWhԁ*7 @8w98k8۴d-<uS/CH*ɘsj%vDͤX+5aqZɫ$y.sv?YW0pt+J 4.Aٿp-F}^e޾uïp1 qQXqy~_/ ;l (j.<W5k /-UnO?5}+bxnji~o ߝY;< UIDPTNYFefmRg>PuUM6 ۶m6c 7"qVܟ~ ˖-6^ժUUAe33&YN=xH⊿Z:7-Æ Cttt6˖-)Sl$@$@$@yGlޱHvHd_Y*vw`!F3>:GՉRuv7!5f_=E!e '(߶Cr Ն`UiY'W V*D[)KpL<#R |e+^ b.ʽ8uytTٸD, ۬Bߔ8+>;cن"Z#  K @A'@q DԦC|vd,9=5GkBX G`9 /˟ 8>Ɯ gs&2 h܁V^RzaB- 'Ic 8ΰʜQg7;x79y#Ye]hT>?U    J7iPLĨzl$@$@$@$@ Ped85ot7&,Iɸɉ}[yVaunA Ȧbjt_{1pL1Y۱b3,8 gb#HHZ_ IDATgm80 38 9%@q]3Z6=S|*ᩀ(Y4>}7`E  @n(͇WvIHHHYS8` NԱɓ G`XpPupv/&g5ab'   YKC8PX@ %=;N8a@o%tKݢcv(#|`{A8,С[{Z SuXIHHQ턀3(RM`sL84GnWE*S7G69nK Z+2"‰+VSuP$IHH|a타3z?'x>Ӌ|%0dt\{5G>T.Y_ϑ kYs֊A#p"-g"8I`9ldfHHYG_a$ggwXhy^|,9ul8xfCko9AkYƠ5c!`sI^5HKKøqмyst)ɓ'q!\ꫯ0p@\z?3|Muȟm۶ؿ31c >}c?0k NnX|<ܸtTĨx"`kKmf/O8u}ϰ35l'hLccl4D$@vF⬝-[( f'ԩ^xe˖`0L<3gδ(@nW\G 7V7lsyL:1-rn ÈPxD'W'9TsE%$aZ[kY[;f0`Jp ;!=VmҍƠ&u-bP7A777+WݺuC=mjܹsXd .^/_=z@&MLڙ5G &X4/KǴȸ ;ϼVaY}g(V$KdbVqVL8Y^)S..h.1,@t:%Ԅz LC,mgjClm- pGD6bkqVv\a[eʂK(=}ybc<H dfpVqVhZ+/ظq#  ܻwOo>?".cVa0`Wh㏸r{q1aL^-]nEUrY'^F˩0f(& cƳ^åKbΝbڵk.ԾtwqàΈKI;BU yqum4i9 B7A]F={C,ݜYD}bѢEZy}V`X]t#G@+-8+ˆ p]`㩧RB10Rƍ>^>,!~ fBUʿu7 ڵݢЁ:w&bLLtET)^2^2e݌ߟV2>KJMCaׄć;Rl"DچT #_쿄. C+a+ٲX\>}Zl[ 5{*Yo?l7aNEǫߏnNEf(yщX$fXt*& ̈́d4(yj#1Ķ1ǁBS!pPgta9-mYuww7|c&a$*VίiӦΜ9"p!4߿ bvM/0-cpȑڵzu:J8iIUkDO?h_ /bر- ]KNNV–Ys;#K.z-y`9br ΕV+XGa|gܹ3f7we\pA2UrH\f-k CE\\\F%޽{7)_re4j_~x*sa/9d>mڴQ߅vء&wtaGgOxQF ˃G9{PXaE]|'ad*|eL{\JC( D4_v A~".&N!8U0n<*Ct=y/VwmDNtl)wl.,}9"5­dQf+k0 v> Qg;K?OzqO ZC`NU}*ٷ=dt S~O$ +Pq*JѬY3s޽Xp!̙c7o}BRFM/_1cƠO>J߉W [lQX+]w"ΚQb[nUKiM|xckӢAgsqFGqx6%Mܼ0 ]Jx*~$V}E5}t#$$$CxTUǎCO2Ʊ4E,"Ίطf5J>e!zAXYt,H⬭bPĉ*Zogl8A%Yw S>zKX߬ -UѰaCԯ__ŒYL]Z7!塠C _gSצ_FM+yuVS'qVMbLpIVK/)T) wKYu)%jrz=Ƙ8k/nN}=ĭЍ(iǮ`M-ҹ:NJ%z֠8k̆+G)AUTTj .h4Y(^u~|?/gzIlL6WD\Q&4O$@6!@q&ipFqZAX^SSu]vi foU7|zTnJ5۷o.i G-$CX۶mSY_r&M%SXYS>kk׮UY,y[Nel87Z̫sɜ0&Xe~h/ 1i)]oq6'l.sV"K?g%n귬]}HXM>?ms(<("Ί!W .Wais1XPY[ĠĊ< lѢk9є8)Y+`AK'q*مo%]D3]f/|1v,B]-pc_oZYn͏\l^\ռI gz)y晌e`]B[-g;ؒu&7ǎSݐ7)L0/Vu9Eڵk~hy! g>$ ɩh>:NF㣝M-q;)q'_~P\Fu?KIsaN`l:ʺYc6S1h݌7oawY>`jz:>~[ ɸ6c q֔_iFC (2 9$PA^cMjIk""˼ D%J{7ԫ-dKSGi򪯼()75AWntY|Tbt}c ifo%xK(__4>['!1ASi<g\^Ej'+T ]ldwy!M~?SAID3c(B4bW%"R@Čl f ZnZG5c"Į4$N%[j|bŋ\?ƮϜ8|*ʛ.h=эe\k%Y8]`*%$dʛ99͜ձ6mRL$ÇgM%0%!XgHis8?aL))UUrP{qQ Wm+XV)]PdLt (n*{uucC>v/E''Yc= LXrNozYR |`kO 9gMY?KKl!u1B UdJ}@,0ZY76Ԟ,.IIq֔E*G2q$SFdyQ6q87Z̫Θ0Uo@rKN֛_-ٔ8+q%iKvU%1˜_5*35~,2E<3RYJp0yD5+#Kilb_|L1bt/1(F٘.cPz_Gj,$%UYT_cEԕYyPߤ$Jek:-m͉9k|gA -,牱ks>2Ăd/^\RVFjKY9_dlf-ed62TsVlז)SWVblbT{N+{Rg\Ô_Y3e3b-&Nq68ƻ?ŝBP￷H:ߟnRE X~3ݿ~=s] \5gUaLbZތCOlᚳ+qIh.9`➋yGe`+{c2e9{5^lVbq0bTDiB|g$p)6A=!%2%6[M$@ClpvBY[!M2"Ȧ/r,7M"bI+t!grkKqVvK66"+d\QV2їrZp̷f͚*Lftut/Y2ʔsYZ}ȩ0f(7sL"b8+k'M&ŸaI&jjɜ55NzRDn޳Ƣ,@\y ɹ!"iVqVnLv9Wfm^6{AcWNc[ Ks5L]79@bDWGVgy+©*@?7C ݆wĩE2M]͉RV7uɃCٰI6Z74t9f=L]pE˺ں-s>"Ɗ`)4vYZx+MJ\ˆjJْz"5QJ9*HAXN]yH&a/SdJl'%Ny̲>lko(vŋ<]SUvi:"1ɘp x d͊foe FuNcPɯ84'ΚZGcq \dTK =,BPc} & $D$޽-Ssв!xSS*ǍgCuAȜz~q^_^0]-{q~ 1v8t- P}> k:߽#{WX~bjOHbzR5{A8,h\\ŵZYZa֑H 9#m,X+H\HHlKmyZ#@q-ݵ-׏#KsdoLѺZ SJ*s?yW_%A;[g-8?Qbk5YŞ$@$@$@$`)c"@q֡@Jz*vE/p }ЭJk4+ welRCu8Pa吓\嵚C'E$@$@$`'(BЍ!@q6sT8XC{X`X Lg k8k#4CV(f%8fSC1G%@qQW"  ggy8|89: Pc ơ=}{g~ @$@q`6I3$`%bVa6%8)NsTgue9/   |&@q6/˟E1ƀ=`*'@q Lg kp$qFHhHHHB":111(^Eǰ3 ٳ'q7={`ӦM1bDLeј0aΟ?Sb̙jcƍ޽;6lؐ{k265|2>S̛7/ɓ'h6w*ukՄn-[Z5ζ_9{YG^],f ,qw{g˫Ny)Φ+axѢEKhj { Ymssmzh){s8YKٿ:L互Q|ma |ZiTXF@^zaȐ!غu+ƌcPݹs'~H&y``   *dD,:v숕+Wȑ#O`ʆ"85>}`ʔ)}vF%b￯2}O`oZG}?>===ꫯ*25vRzիq?qqqF}z͚55jD(y>hРAy;EluqڵJqƍJ|e wgZe̿+הm5zY2`Ś裏-Ìmgl=K - YSSp28ˈpjgzjZjvC]lq Z噧g 5*8YJ⏜Yr ArFEѿ%$HPO * AJ s˒wnqz{zzzfzfnݩ{zoz_UDs^WXW/*lرJԊ&?^EڵK>#զY&gw%C4+Ffp 1|wDC|t3fb@FpႴo^3СCe4>vڶ"ή[` 8kdjFxF6c2eȹp$#@q(ƴcjZbܮ,е89 H)Ά={v-8Ab vR$[lԩSUzl9 m!,j[{\ڀ8;}tٿHl/Hu}˗/o*Κʕ+I2ej6o1a+a!֬YS5@:xz[l 8A6 Ѽrzkm+E } @4Qn8k4?l_E‡b@$8V#@q1l(@12쌉YmZ|Ȉ F_[o>z޺vR\7!Ң>9p $'~c"K,D%;G6'Zʽ۾^ЎB k1'|юXEɮ8+v /XgCmu)v] ZT&'*Q !JUqx;;v(?8 D+* i ({ҥK+1"R2a4."Y=DRm۶j7oVB%ftyUmjAc0We͚5*"4j-VgVo8>~}`ʏٳg73qhmwY1%ΚO^5o#;G8..N6mvlxɠ9R'gl8ǒ87O?4h J]V ]lwYVwk3cwM!&/C+;[ŊB '֮3#gCmzG$@$@$#(ƈ9MbIm֬vZQݸqWx!CKm].c JGͫިb 7ypVߎhzGUVM;(~ؖmzϰj̙[1 m~ Vh]3N!/C/D d*B(_|Ҽys^:L5AuNO“l7б[9a'Qn]ݤ/8d޼yj0֣^Z=](v6؆q}8~ Ny!   (#b@,0x 0؎ճgOA& 4ts/l߁Ȃ-M[,3JrOI٬Ex},?pNJ:1r/4_q8uET!J{e~zuYpYv1cT:okזYfH*Wjv^ OP?95   8V<bYM2|7 GΞ8qBQG} uD5lF<NN%-rv˖-4Yxk4tgϖ}[Df5jHd0g?xj2e~pv+6EIq\|0mLIlťe['z+ng Da 9l0g(:o,NC)83D6iD~a%nذA|H+W.8 A ~ѸW^` P~d43ql ? (Иg":m4Au*U"6[l ^37n~ 'D.^=hD ^֗8H g#g"U8i؛}#Ѭf9}~k.%csUԶB#/4oJ1V;( B2#q#hI{҃yF[>/E'Yu֭[qzfڵkj!@C8%_8զ$rP ʎv3^|EeoliE7vq{[Y|o!DC $;K~Cgm IHHHY:HLEq٩Snݺ%VaLٮ\~ uhu93! 5@T1>}JiYF)ϟO2?[F,"h<үb+yaPznq6ы#/,،f#GxEa7 (`K3"!C BAaÆyg!kѻ'OVEJ={i&S?2?8 eO.%7r S|юj_ 7`'DGkyGjժJ >\L#gc鞁u8 Q:uR`E"gkݠ/}\yqoK~Cv3r6fIHHGlز k⬓†^ӥK&,oD#ak!V/4s?YҥKl cC:7#% B!-ZHEP6֋yг71t\AIW&kt6ɥLzp8ED #箷rzKk4lNQ9kE;xe?ҏCf 0h$ΆgEH)R$[*Eb|F BvPң~9sƒ8k ٱ@g ]̙3u589ґ GIYDb]#rB.YD#B}}8r$@$@$@IlDv@,{gUE/ΞHAME{?Jm";r.[L~w9i?DTH_+)~皁8O툳E;l/ž8 Lے%KT"*3eʤ;Rh9J/"¢D._VEҤILBm'v3n޼X^;+B)^.XBnH6is%ΚB5,xG,ĚiӪO'M6UtoE$cǤPB*g-"O_b\2T;y{O6 8ku|fg䬑}o88i "qD2D{K꟞vSN-7VJAGZΪyCfb+رohW3Vo5Ұ`(P@}xFp㞆!aÆe\R ͊8k ]vJn!Iq\x,u{ _<<؁. bU!a7Ɋz1.]گ5 u'(ZyHHH8kgĐ.7:P.߹~p8YH?4[Nq68+ [u/] sF#q$@$@$@%@qֵBAl((v]W lC()|Z뿃6DQ..P?'|~hOnYw@‰Kq]>ѐ DeOOg~Xttai^+(H?4-؉⬻k⬻|!  .g˞( &puYqlLٻHo2qi:R3gI,*R aD7`1i'}~hFnYw-w~ڥ8.hHHH'g'~c%@Q,bMUF9iȱUFʜ!C͎HHHbز7gA,]"VPhK{CwG?:*rlXy,_\V^-gΜ4iHѢElٲ4QFIǎm;慮#puiѢERH!y敦M=x_{5dΝ2tPOnoԩSGz$U͛'-mo_c3ܓ[o%e˖۴u-hƍ/.ǎ 2Hj駟8. N̍m 8C3J8&@od A&i fC,?. K.o.?$OM/vJ׸&~嗒={vvl޼Y>c4h˗[ڵo5v*Ο?_}$mׯo٠^9Ӷ8qzԡC)Q:uJ{9||GgIBGlX'8BpHA!@%(X٨~ cu*u .Ȑ!CP?~C",X *ZBn9ȑ#2uTX,\PRN-O</^\>s9zjG{nU'!!A iM4,Y7n(0RJIFdI߲e,[LQn]+(cȝ;>}Z F=pҽ{wկʴi;TdʔIp AF)_4hЀBOאhاOy'?3)T{OEw*tK/I̙W_{Kƍ"gwءOg٣>Q̘1CɣڃX ߮Wo> 3DBDʕK}vIu:9y4nXj֬_ʯk43|ߓO?$ΝbŊ)ϙ3嬈X NM.4kL_|jhqOXfhgwމ1blڴx׿<ۭ[7R/hڞ={c=& 0>rJ!tvE$ dSG ȣ D 9 2ɬYuͶm_U"Q9{@4ygػvR zADhQD*Sj߿\xQ D`J6mZ%}6[V VR%z1瞓3ʏ?&\geF5g!4c.0ck׮Ubޕ+W*z~]q~feEBG4$*J~^~e%ʕ)SFJ 2iҤ$i }믿.mڴQ"DSq7Yd] mz!BxE>}#Wz1kbm.]T=Xj2Ƥ3^0ƺ{ &cO^:udh_o߾;塀b~1^5bhٳgk!|^~Efʕ+'e p2yd/sx=gߛy% @8 P '}vgnHHH R]~B8*z}%TAXhܚ b^ľa:BڇH S_ׯZJ:CD&Ύ9RQtfxd9 qv̘1JB;W^U NÆ *Ug.T#u]Jx7~xA>ZNJ+_~  / 9mG}7U*:#G&vU ׬/XcF Q~kh_) @A-5[pssd/ĨK~M]2`q֌Y̫B *5^(7/ޮ_~m~sU/VY+E lH vP[s^D8;q(5lE  Cۢ Ȩ@ЁE F![µŪWm q*~[!R-YDѺDD"zVgc0/4g!,#O+g;w"z!P#R R,N^ B) < Ɣ)Sg-m߇ẌEADB>\ B\< Q/&L9{2@Xv! [gܾ~"Cm<|p%Κ.F5rJ-| R*@|R{>ZgqBHig&"و2WJ̚>wF V IDAT?ڼO.,ĥ!z+CNXM򌜵"z54Z>2W^E4d\כ8k6'NȔ)Su(h QME""#YVp qb&WDg1JkNDB툳h Sŋ/ fsyҥQxg/Y $Ԁ8k6V +U҈hQVǫE2Cprli]BHig&"و2WJ̚>wF ?ڼO.,C\ؒ:HEd\˖-UYlFI|E[!`8sn*O=7o: Qa8 9p!}݉#jqy hhȂ]ж&bK9VZU1r섨"- "!PuZWP?-Y!1 q+tȧ g@b1RO1Q] :0/qvΜ9J8!E^8C~Un !3+ XjJ Ԉ@.Qԯ_?H1ƋqXX;q p?lx= `O$@N8I(FbnPbMʨlf ޤB," H?!j;? Z䓄3gqرcU!"s!":=#3D!]GD]6Hq4rbY<`6^|~ 0:B,R# -f ׈J6޶m^+rg͚9sf -z{7t^ϞHAl0͈!@q6bLhE7 8R @ɗ/ߞyj1Y-A mZ*UJEZ-H(xxvTA D 5D_H+B$@g1MlLݼ.ˏm){ʎs|*+(M בZ9H)-_gTJCڀ] ;!5U:#􏰙,_m~|l٢C-"W3ePu %>GՂC]XL)VѺ<\n;C$<gǖ-GXgXrh'C\xd|qqQܛ 툳wm7ߠcmqa>B3;6H YLʆHHHH t&K,#NXeFˊ+^jϔO>wm7ߠcmqa>B3;6H YLʆBY:47 g\hYq*$(Ƥ9i@,͚5SFzg2~ZD8P*Ю)8ZDfoÁիWլfYi[Īu<8Kno'rI{`l/léȃ\Y8aƍ^@f~G@,1 JQ4"e[l)e&z&NA N7=w:{3gNA-kժhܩS'ugWVbcǔ3g,x0Ƙԩ#?ۥKslmۉs"kO#2>[H%8Ym`vyQexbYpab䬑}`[b; z7x=D {sy̘1Cɣ|/TՓۛƀ&OE ϟ?j~OUD$CE:늅Q䬑۷k5o+V._tL0AZjCM}83g>g﫯NvGIx܈ó-񐔎+$?]jqw6qI%ujt1{ _~ˏr>kc $&G_d#E3%G7J J͒AA.8?IHHH 8(+[,ΦLR 3z/ĉe׮]~pu %b+6  [U,Wddɓyr,#E ֵ8k'@H5Zx;ވGT//+W.Q=p3R( UwΗ8k/ =\a{F9Q{˲׋v-<^ ]ʇ~q[3c)[W}=!B8R3]4,x0Fd{ァQ06j~,)J^X6T޸nBjop"  Q^F "D@Zl{lo6kd8ΈpնOe{h/?о<3 ^EYPAbW4/ZWl"ěw.8sJ$@$@$@ @qf E @YD>|XEA BDQ3F9g!"H"I\i  R i ,Y"9{e'3rS=÷7qt\AIW&kt6ɥWv8aoMEN3guU&΂}P L7 }9,oW/UqV)DO"G>i (#RLԏU߁E*b~ $HID9jvI?&wK"^iof931ϗ8aM_^[}/|on K7e# 75݇2e,6mRQPpo@>P}JfoAk D;naϔ@,zgU)@$:uˈÑo rA=z8!>  ,G.ⳃ*QѲW9gqPؾʼnxǃ4G-!,Lf+^ ˬ+ :@lGuޚ8SñQːAg͛gh_U9Ej%y="gl8/;[g| [l[<}h9q )0&wܷdH qԩSʎ^ *$_zSzh{-e l_nsfbDvɹVDҤ1K fnu{͉) 41b/^\NZ{o9g}v>̞݇ 29S⬙E B {BG;~FmS ǫg{3;[g| CP0ї8Mw0w@+<#gChvĽ BxZ*ԁ !ƍ F931m޵a&X>+nX?/76lvF ҆{/{VFW1_}wx裏|ȯ/F9gQH- IHHHY:HL8r`YzEm+-)',;Q H-H,0e/g$'   (3b7B+C!Ȕ_>Qv WFuT~~H"#[|]zٍ7aGt,MܹJdqPuҪlHHH#@q(ƴ}N~ >UxBK )0 7,}'& yg#& knauvN$@$@$(Fq95(f5ݼ.+m){-(WH#5sRXΨ"ـ~AwBjufGa3YX;N= eⴿPIHHH/gFlY4:Cq6:YwBA9rD2ouBs?}d͚կkXHHHbX6ztH @%1wiKD8(F8L   H#@q6,:J⬣8XP@ hF`gc3 @P dv^gk?P v w쒋agfIq1lHHH(b@41mHNHHH r} *g6N$@$@${(ƞ9ct   MlΝĉҫW/Q X#8\/; 41m~N>9AIq8ҨmÎAE$$$ȬYdʕr1vȑCԩ# 4'N5ba M-6 m۶K󷈉HHH6h @q69`ҍ+aO1:YX=}rQ)Tے!C$NΘ1CƏD Q  Qgc-g $`NB =*URG;>a]?PVZ%SVZIUe/=(-[ɓzE)7SLR~}iҤIb7oʯ*Sue˦R%4k,1ZSR*?^#ժU\3g3Fr)|JJΜ9#ݺuK.믿.+WvlG}$EQdrw/k׮$sP1`۷o… pXOc DQfPN?gڡ!puY~lLٳPv;W JuV2*yJVBMހ]4;kCt@;ZӾ!!gWX!V6(hR<?(? ޓ5k4Hǎ1 Fbk~\\ 2D2guVF-ri ^*/FҎ98%BT_Z(ȎY)eʔN?f'_$@$@$m(FE9Ē8\eiӦ+#䃍 -jgkc@TԆӸ@)8(MDk9۳gOUvܹ*?m%TS1b]Ç\&L0A6!!AE(P5VF^]-… ?~+X7q @9~}E"b &CW^Q?~g+WDqNXx fW#K,r!Z g( .+ˮCQ))|VVn@qq _+3w@mЎN[=NF(Y88 yy'[*u֕ Zp8E*,HQ(!CΠ#[LDQ"+}kh~y]wcu8ۿ@eh㯾JENJkQVǑ @hP gR$jmֶ@ENx3?߹szO-]f4&?R;Ɓs:F '"y<7A$^Ϯ]ʉ'Xsv IDAT#ҷN:Ү];og-r٪YK$@$@@l4XsM Y D`[Ґ-%TcrBxڞA1-L32YBѣJr!:uꤶpzZPp< x+1ہ́-< Q.]7KjTD}?ƊkbΜ9*lfh9yI8f'bJ- B]_%,_\&M$OVfx5]b/$K,Ik,dw!$v_0x]42Hoڴi2e%TTI#h:=lA46?Pmم`CjGFȚbC7Ny>Rѳu|Ӌ/"0!J A}q=l s%   p/ G*jr-XǏ-n8Qȷ1c(LEmۦY7PItf,avڥ!A믿/zAs B "y!l[g Dp X7Njq֮ % ,+V(ŋJ?AU](ȁhX2 1'L9sFEU@@\}ыF~Y5@;%̐SyRnQ_<_ mBuT>JX=lݭ]Vēű9M}{v_X!8D=s^ 1>aKֽ/^"&oo&#Z!vVu""*`[C4{+r6TgcOfNHHH (.v?Xg@,#b9k$"rJ]8 qxZ5 Qgzvq%U^ɗ. Y,$_#BMf& yѰHMz[/ZHE26FV73qV9c-'!:.r+x'~l37r@נD@dGl"Eؑ9F}=@="ڊm߁YvfL-~W Ԇ =RoPugp<$@$@$@BlXE-l( oP/Wh)ur \Lq6`Ao PD>;Ԇv9b+Nوu!HHH(κ@^p P ._neű-2e"~v_+$Mԑ9Hd)[e# zvtX hsVNوu!HHH(κ@^p P ._(F C5JH1|#o ~MӒ5kVae   %gcڜm()HzU]vt}::aIHH-gfY X% Pi5y_\[vti?0G@$@$@$(FY9)(Z%zJBMZyWg+hG7Z%c8Cp$@$@$@FlYYpr PF9eMp.vtA4nB$@$@$E(F19 8"-    $"n5 k Pui8P8 HHH jPSr"$@$@$@ @qv(Doq6Ld$@$@$@$N>-Yfġs$@$@$@$gCYZ"  vُ?X7o. aԨQұcG["CO>r%O\n7o̙3er1I>-[Vyɓ'vXHH=(κIP tvI$@$@$3!B8pk1Ù /.ɓ'6mHɒ%6)S!/*UJ.\~^z"E͆IHClp!@q6B a D$@ԩSԩSbŊpBO</^\_.ӦM۷+6˗ ȗ_~)GUѣ޽[] &MH,Yȑ#mڍ7D_5j$RR͝;WΜ9"{5kYbq${?oZ6g)?O{tR0aKjդsβgUOݱcG5ΝS  %J ZϞA;׬Yں{矗p<׮]z i  {(ƫ(1$A$@$@$JiӦѣG}'5jԐe˖Ν;}yfYr} vڒ?~AZŋeذaҮ];ɖ-s?}Y%@nZn?.\Xʕ+'~˗eРAj|NnC"ʟ|,"bkժ|@̇ 鋙9s|`Η8|lB &MծYFD%9 cϞ]@ ! D-'YlG! Uψu!;UZDj,`ӦMJE*bŊ%Fm/YD?.O>dͻ^={̙3G91c7M/UVU,YKӧ ӾI[gH}mTYxp=o5kY$kB$@$`Y{xU8%4HHH\I 6i;۫5qycՈHkׯ_SE4$0-BV"r駟v%o*Ǹ[n2rma]CU)/g r9@_! }w}V:u${V9 ǣl1J*Iٲe-G ! #@q7^%(F!9    W8(VOQ7ŁJ^T֭[UXIz58TԩSIpQ;b w믿*qyo T.VZ?\8h) ;Hz1>C C"EHĴ@c6H իJ;糖ƌgfiC`06Ag  {(ƫ(1$A$@$@$Jg-;uT 8)O}z H\\4mT]<͛7e֬Y*Ro.ϛ7nԖ8 !/ 0c !jK.<6̮=IHgV"5M$@$@$슳19HHH @ql"r P\q$@$@$@'@q6IHHKlx08f{   &@q6ɑ 8@D8IHHOm ga&@q6`$@$@$@QMlT#  pY %@q6rmǑ Yۈ#$  /Ll IHH٨6/'G$@$@$@dKlڎ#'  p?GH$@$@$^g˟0ݓ D5Qm^NHHHg&"ȵGN$@$@$~go#HHH (Ά?{3a6'  jgڼ (:MD.k;HHH(κF! @x P /fglvO$@$@$(Fy99   Pu"\g#v9 Pu8B   8^=(ΆHHH Pjrr$* n6)W++[O&ȤmeJt\5~H v P]s"Bqn@$@$@$@#`Wy,_\V^-gΜ4iHѢElٲoAlȑ#K/^t wݻڵk/_>i޼T^P#|~]sN:tՉׯ_-Z$J"͛W6m*s]ymĕ2J?c\v]:*rdMznܔ_xMɤDҫZirG;l9 Mfmyi={{V0kM1?eެh~Wn]ڵkF%S^Q, ܏Jvp/OUIl88vp$@$@$@QL8-?,XP.]~޾}<s_\\63~w 4/ٳ+zJl4hY*Bn]{QzW/ܭ+7nʒٛ,9젴M)bJmӦd͚U "R݊{)GU/P]]P٠#fn&@qHHH"q… ]v?~C},X *:Bn9"ԩSL2tRi۬Y3>}>|Xh 4\O.\( J`jҤdɒ%+ >O:<Rxq5Eɲe.Yr%#g#ݩuزeK߿-[6W& D &(?VtY!;vLJ."s)Cg}& Rs=9qAPU?,KN|I_|رCEyl49=Y>}6F2/f_[ܕ/L T@=Y탺WU K낭rg Eۤj睕H3 [ZJf%1|tU.CF_ZҥL.[S$iS)1[eΞ&w䖏+)oߧH,*s婙CѪ=%mJQ-U]k4sBb7*Dz8;G󂭲eM#G~l:yVKרQC~zYx7kϗ~IΝ;'ŊݻKΜ9-;#C1dڴiwӜ9s#ͮ;s9c5c ɓ'AzWo^5c5QtT(Ά3;q+n E$@$@$ 숳۶m_U^yCgϞ#F3<# P"]cǎJVև~Xʗ/0n,Y2%ZmJ=D[ 6LM&xF-wzx=~9Rfr!wLk SL*UHJ8qℼү_?%>\4_VQ}~Pzq3o>yפu* %ٳo߾*z/;5jD(\[o#u¡CYq-rv˖-GY[#s>XGFunYM'!&u׭'ZS IDATg!>.=xFZ(KZTW9lOY-]Bږ'H͉+db R-wff,p@9)5"/Ũ eKg_s\yS+#u%\{qSZgO^*eY*:U.תUK>%^xQ^|E"ySNםeȐ_ϟ?o//~mɕ+jÚ4l?3kk_WQ u^w%GxqMF!#Nw6g˗Y#  hvYD;!BQYv.Ϫ*/__=hBꫯLD (Zz)J=Dˆ T3kljsGEv\P<Μh(r֛8;qD%%"O{9ZQD_;"d-_zN~&݅hokhurƚ{7=_]tQ /Z[WF<.Q >cbg]lHHH gNPhThƍ'Vyw$"-Eʕ+C^ExxR7mڤD4<c;&Ύ7.qk{I*’lĻphк~% Rl< "fwU(!~SYJku@X _fk{/qV?_b՚.8ҡB~si%P>T$쏿$KN(V cd[[k ]WNܙN/k(v~$} [OZ6oi{ːFE~},^/S>SR2Ja{!?Ϝ2yQA}5 !oFyۑ@z@4:"b QHkY?w]/{:"oܸa/RId-Xɓ'wC}w .aYxv8etHHH\E8h' "W7nܘ9kEt*B`eÃ(Et/q?ۢ )κE RD)r`)`4 #.YsDݻm#AXyT OqVk"r "{!#g!Ԣ&/rКC?_Y1S?s'9 rW8yFQl~Ivs6K٤G3gbFEkoؖ<}1w}JB>d-cɒ%UDlm֋blTLE CJ D "2D*1#/8 %" r$CEgaU$B=>+le-jHt9zfU\l^MrO#]lg/&Ξ|M~Xv_F\SH2?o8PFc1sYy}ɿ>=\.q,Y?Fsy}sK-kȚD΢F W!/wR, R+CY޽{tGą{,Q5we~RϨnݺ%YHՃCBuxug[ŋ7teDg 1MlL'  2lIDn HH <(Ά;{u .1A$@$@$(FY9(!%4HH P8qN8$ME$@$@$@I PG 9&@q6ɓ  f$@$@$@Olě@Z   0'@qB$@$@$@(Cb٘6?'O$@$@$dg ͓ D<oBN gkIHHHYz 8Kigc< @ P 2`6O$@$@$(F 9@P %   sg!$@$@$@$`N,=$ Pis$@$@$@A&@q6Ȁ< @8&!@q6zHHH P 9&@q6ɓ  f$@$@$@Olě@Z   0'@qB$@$@$@(Cb٘6?'O$@$@$dg ͓ D<oBN gkIHHH@رcM6F$@$@$H,! Pis$@$@$@A&`Gy̝;W֯_/ 5kVSTR%hG)/_ݻ'ƍ2`$2d %KL*kÇ%# 9+UTP%HIY@A3JNsΒ3CXrikzzg<0]u{o;o:W>#I0~66n([ngΜYʔ)#2ec.^(+Vʏ?(I&uI|7nH:ud8qbGV\)k֬N:ɉ'O>2xp?A}օǏK5\߹sgy嗽n]vңG$@$(gqVا#@9c @F۷O֭['ժU9s{''NFIʔ)bXX~'N)W熜mٲHB?v̝;W2f(~~|rٻw|'%Kyi&_$JHO.L0Aڴi㐳/:(L9z 9;|pI6m ߶mWH@4n~SaQAYzҿA rvٲe2sLA=9s(k!ChѢ2o<]͛7ǏKҥ5b2͛RHiذFcNuꔴo^&(QB_G[[k"ѣGsǎ5U\HǑ'O5kٳGAH PV-N>mU^]#-Z#Gw/FݻlٲES8V\"g@… ٌ.ԅE~hwm ] @6Ȏ(g8k3 ]x#gZ3rZbS.#,@b.׬!jP ~W&D.]Ɔ`CL)H.H5kjMsA~O<=V#+W.GEJP(p'g+!i ֮]+WEUDFH(Α1!rbEe^s=# .T4 (+@΂63I{c>IHH7rQu(| WlJ*dE䫑ss(9YX9tɐAXFbECMwj*(i -[`GnY#ѩ蓳TEsѲeʔќnT Fټyj/D*=rtU#o%K\^r֪MlHQF ҝ7 Ƶ1 K ^@)$@$@$@$!o,",Xecoū؈NrJ{N8H%NbxeC aw{RJBzznK yDb,DBH5$44TGN" gϞWLtF O,umMD#>7rbS0Ȑ!K9ۧOJUBƢ@6#1pݺu!'r4Mʕ5q!G}$K,x6gOI HPDs Pre x#g}dRF wY%Kѣү_?Gڵ=zxVD9rD&L ǏGILZjoFt߯_^&O,Ν[!hǙƝ?~RQqfGw 0 iu[dDv _}Eɑ5ƘJ*%7K.Xx,ksdjoĉ˩S{2bĈcW*wmn'O`d˙d0)1dN(\ߞȐe̾sr]I0#s*V.ə2z[*)--c}ZWv~]|$S/Dͺ*h/0&ԙ:uj۷$H@xPvEVr܏̹xذa:jղt\wDYN\Ǎ#ܖ{Hh-I͚&LrB&8/J73eщ+rڝ{]kr[rskD7XPJ(!} X炈~0aBeh 7Ɲ" 7 IDATg[/yD:m͚5}Ge׮]fgΜ9Ss)͚5{MDVc-Ezo9!ǗA HZ_K)_ I G꽇R.{:^~G,{?SϖVkD6^~@(}d ɐ2tȳ9&6 x_*2W%w2Ei쀜I ~Jݺ/=JԨ|?vs[٨㹶'@9k)HHH@tٻwJ5 R2O?}ɦMurF:u PH?*Eِ-[6xBPlܸQE ,C+Vg]}vFZ l"F+/_V1ɣb }) ĉ u3O(r"еkWyU3g>孜E!!/#HU!]q/g ?CԸ 8m?])?06sk!2%H`.mtSj.أm^<Kr;2hQԈ*y3ӧ"甜oߖ<ڎs%g=lT\r$@$@$@~L ,$ R ݻW GT, g5"6\Y*D|:5s1sAtD gz4DR' *%0`! 2]A% 0rF-.`'[+Q5-ln # ϪM͢#r6"M"!2) 2"OiYH`DK#W5;wJSu 6d2$<^_O=D_.^Xat*dA$>'gv=⋬WG!z!gehQyD#*C(@_.H!㩜d AD8㥗^: ޮ1/׈JZ赻rc&uBx~ @^N\Q֜&u쓃o!w s۷eڡr迷eXi< gܦ|t\mQelċG.?{M*ߥW%HuˊEFG|ѹ?r6*x P~ 9   ?&r#z bz5P@Bt5r.rr͈5εh ѯ"s.lsU,"#~)d, RM6*\D"9 2꩜r@] وQY>&I򿨿萳D޺uK9 >E1Ź 9wDc:G*X!ڕE,R :BB!!ͯىs rrx#R"p<6B?RdónKd"I_1Y0~=һ`mr\Nݐx`9kx]3DBJz9 o\F?jRY)Oy^>_~GO;S{e7oKvFNYYb%JQ>z4yw#֨rZQ۹䓜R^Ū k.٦hݬVz Iqb (_rF$WUqAT* hQy`qB w}^GOKqwڧ"?v|k F[liYsqcD05 cXk:7D z:իz@cGܿnj/TclLw61 K,!<^HqY xU}``Y6 YO"? 1yg 9hE47@ ,D@5QR%PV.,x 29:9tQxx"g"Rzu SE* Dr>afɓȅu.:;q䓅wHY=2eJRL٠n½@!i qAT`D l5&WgkA[5D"b@Շ<-=|J_9t,SrJN'HGiIRrڿG2č9گ="gnݓq^qY4%ᨦj`Js56ACp阜$&{vr6*x P~ 9   ?&k$@6'`޴C],rȃ"Y^yRoTS#:dK'erɗ&|]%μO;O;K˺IHHl@PYBސ XjA=< P0'  =YO!QsIHHH,W X jA=< P0'  =YO!QsIHHH,W X jA=< P0'  =YO!QsIHHH,W X jA=< P0'  =YO!QsIHHH,WH qԩSGƏ/'v uʕfԩS c# &ؓ=獽&  Y{{Y,  (g"lPO?O$@$@$c>c'r2dɚ5\xQ֭;2c mԨX-[&3gԝ3gNi֬O>VIH|Krַ|Y bHHHlMrG@9{)i׮ԪUKʖ-+gϞ:Hʕ\r2|ٽ{tMnݺ%M4Ν;KƌeС4iRiРHH Prh    o PzKفrm۶6^xbZ7n\9v[ ܐk}$  PzώgDHHHo P԰c@kזcjQ.]*6m;eȑ5~޽1ߟ.\ SL͛Gt( ǏK5TRҸqpZ[tyx܎ĉҧO}Tz)#͓B9 >oԩSK߾}%A lR.^0!] 9ۧW^鏫~k۶m :T23rUC={v5k:tHXFA+VL/I8~+W.=]U}W\qDBލ;VDɒ%m10X-Ze׮]f]7F,̙3ƍ3gNi֬O9uuXN"FwBfA"N#0 ><|pݵ: ϟk?E9"W3HCD.2dоĵ׽{wٰa#4G*)3g,6\8wޑ3fh5j$ڴ:":7X~WҩS'yC`w7y@d?>ҠA)P@~=zJ{3gȿ/t.#jjFUudĉrM)R4lP DdpI?Ԉ`u^CId}Q &e1H$/>l0q׀^pΛ7O2f̨6OK:uhS YƏGETQIqfqə2K9s?'_*,ZTN޸'_J)M@k,:qY'y7ċGf&]6j$wn,{ I8 *]@Jl_ yJŏ' CCdԞ9 ila9r8"h㿑JJ}sgܿ߱[no*Alؠ6L;B$@$@$]vΝ;˨Qdlz-[6YbJZbxlٲ$$ݻw5B\_VZ* P')+}ƍ*PU:'d/} @:!@۶meʕ*P yW1X{M45  R,.]$-ZШ[ȾS >HXpu ,Y2r֭[nۅ,Dŵ/j וyr.d޽ZA:-\@~_4k,k5ps_[e%"w\ ĉ !! [/|z7 dȜJ:ϩ'm0 IDAT^2˩d|WdK2riqa,+_&$S6OB%wRo~yTARvVifPf]r,e;{GJM" >]H2;V㰒u9ҍ ŋ!A";ovuuwO5#h>r6:{|$@$@$@"U9?!15HU#,!k ר!t>$$Cd+9}v9x# EYԉ?ԑ3vҤI*WGԤFc+B^{kY Wlȏ*,@AYFA?7q>d;N/E97oެ,H΢007rj8YOc7PNZZgDBL6M7(@AA*Y#;čꛒ+UmSy疧ѳa7\;y5ޖaeRi8mfAkȵ;]!u쏔?CnCWc~ ?^Fp0wY꞊4*Q(gc:~3 @94eʔ7D#":ѧU`HKVȈ5곒V#U}BG<2@@,gA>L9WCB$zDAam"9r6mXrlș!hQ !?yGݵ ɋQCqXY[(g.pp'    DE x1u*d!W!!!*C<"jQm8# " l'fD2C,X@B ,kwW_9g!mg3Şr;#d! 9(o>%l myY+FYx*0Gآο bܼ9פy0r" A,ˎ;>GO QV#r'OrBp|wuk|M$]=2du霙@~mg6=OHu55c2rc:~y7Kj @M~shƔ2H8|Qf|Q'oܕ.o8qD8(TɛAޜIeiKՇ%gʤyr,gs]Tz]2'O$ ,[%tYUdHH-? ǯ}NZou1Wk k0pE>`^ވu駟(gc;2 @ .9 yMm- <ZШB Z1"( ;wDB@JdɒŁ-5JH#8@Į;9ݵ\Ɔ`8Rm`c!{0YÇT?~]؈ ѵ|CF~E+$rbC7oPڂE,"D"1eʔRJͷ ܵ GJ43oDY9 ܞ x(O,;p« \ɓ'W \P?Q;ܛ[t}wcD.BCCU^A<ҥcWkǹ['3 dx`.6ms?P. oDHƴE_<-H%9^;?vHL'A{tJ8qL42LI Jvk{Y2̭{n,uy1$O~x# qRz[٢qK$ ͛m'dWEZo'b<4'cC%k^z* E loPT#$@$@$@H98$ !`2$[#NXCφ?@$@$@$(guf9.N1-rģy(7k\0ŽeUߐ Gx, 3Y&@9 嬏z   rQ!@9z<HHH Pr 5Y&@9 嬏z   rQ!@9z<HHH Pr 5Y&@9 嬏z   rQ!@9z<HHH Pr 5Y&@9 嬏z   rQ!@9z<HHH Pr2ǏK5\sΒ,Y2ӧ <81kNz`HH'@9U(gz9x   1`V 9;|pI6s}9q_٧OJڵe̘1ʋ &@9˕(gz9x   1`V"+gn*&L0ɟ?4o\RH!C Eʼy$cƌǥtRNkDu;2c I84jHBCCUVrI=~)SȀÇk=2UlHlM(9ţIHHH 2(g#Cڍ@dKEҲeK)PL:US}7H%47u'N=fذaC::t +Wreҭ[7~2yp2YzڏTRm_ k~==윯 P0'  f=ʕ+YȲcǪ`+Ydmۦݾ}[2e$+WTRx.]:(\te_;{l)P[N#Ϲs^?XΞ=+s̑ ^>g˖-\M4իWQ *C!V&L(ǏwDPUĉ͛RHiذgg9k|H?\2fNbΜ9Snܸ!9sf͚I4wm! kx)C k{zmQ'Ov b! ÑؔM'&  oe?#$^/U-ZT6n(֨ZY^zu+VUh֪UKe$ɝ;CΟ?_7(DB"j;YR1:@IJػw .H5Vn%g<5$~4,)hED?r'I!gg!!ݐi ̯nfuoD E4.qyC0AP@{OkYwms32b}(t)gws$@'@9{l Pk$@$@$@'_/PXYD";D9B`QFG>Wj!F5hJZț뉜El5RֈENR#rWcD"Y|C6m*F2)^ׯ +Qz9ӧOGa#rU[v.FYŪ~Y߬!J$@ @9u(gz9x   F΢Kt #Gx%իAhDךe-!!!*c!Rk֬цi 2dȠm!Ze:e( y95j$ɒ%sB }j :ЅٳnZ*g79}EYED&sNƄ6丅XFA$6T"_x/XcH-"nF"#g-Zi1b1Wm!s!YZՏn[ZĦtuL$@Gr6#H$@$@$@$I٧Opne9.bs0 /aņL(i .T4,aFA4*dlXeر[R% k原qDF΢o VժU,Yh׌v)\H q!-DrFprYficea/o, @Ɵ Prp$@$@$@L[9B$@$@$x(goN9H,J$@$@$@$@9I`.:C@$@$@Lr֟g}9Y#f$@$@$@ALr6'C'  GxP ԙHHH?@$@$@$(gyv79b6@$@$@$(gx9t   Pz*@YHHHP,$@$@$@Lr֟g}9Y#f$@$@$@ALr6'C'  GxP ԙHHH?@$@$@$(gyv79b6@$@$@$(gx9t   Pz*@YHHHP,$@$@$@Lr֟g}9Y#f$@$@$@ALr6'C'  GxP ԙHHH?@$@$@$(gyv79b6@$@$@$(gx9t   Pz*@YHHHP,$@$@$@Lr֟g}9Y#f$@$@$@ALr6'C'   IDATGxP ԙHHHrӧaٺu\vM%J$9r䐲eJ4i$,,Lƍ'Za^pAL"͛7|Yȑ#^zr96mZٗuIlcQxK/$UT%JXvĉҧO;יΝ;/쳶Y1 ;Y!ϧ(g} 9oUdǎ駟JHHܻwO?t|wr堔={H.;/q6mZy۷Ok^$SLnrWvm3f gV~IvHbl,gAr?恽   L;wH߾}U4eΜ%DN0A+&$NX*V(r!q,YQYfUJҤI={Ȳe˗Oϻr#riر7o^)Ydջ~z~/xDϟ_-\xQf͚%͚5ӺΜ9}СQ Yh#rRprMބN. *x&L(}1@wu(P@֭[9w\9kG=W;?.ŋoUY DgH"\s9C wyGf̘QF:"?yb4hWB cmۦ"<ƍl$I?~6l>|X<و1 Ark! Ps$@$@$@>&=x,X@~+JRqFFLxUz-[6Yb~ϯ_bVZ8sL=&w9 9bU/Gvk͚5پdϞݭPFTfN¥5@;rYdիW˱c4X5J}]e|QSN`]\9)T ? qQ+X}bzW޽{Xbd̘Q[ocǎ:|0?~ΫV1-x`DUGQ![n])\sFA9- a"!"9kV.,"Gatn H \ AMr6'  1o5j/ ̿]V.](CDmsBD&:z: 4R7rWJF4eƍ5:ҼyԬ,e rJy|u,Bw >>^n1^}D#9HTWrHݻDA$YZŋk5R ꐿM4Ѻ!q!#e="VLk˗ Y? v% P"}T#!h!{<${ァyE$ŊhS/J $SL "AFBJ!9eGE4W+rz8r͖/_^K0پ ( 9(\D'B΢;V_gOdժU>c\F>XZԩSG<>Wu{*gjÏ""ሣQ5kVpwr+9v9tU7oT4ŃDZ5q, "ʗ/_.)S4ȯV5rs G/RXc" ,BP IHH|L[9nz 1a ov?'@9 ؚ嬭bA<: @qlПPl/$@$@$@Fr6f!  nMي嬭%  YMK$@$@$(gc9'4 @ xHHHlte}"@9kbgIHHlFrf 8G?B$@$@$h(gmF9   &@9DYPjY   ل$@$@$@1Nr6ƑA"@9O @QHHH PF7Qg+.vHHHf(gm6a. @qlПPl/$@$@$@Fr6f!  nMي嬭%  YMK$@$@$(gc9'4 @ xHHHlte}"@9kbgIHHlFrf 8G?B$@$@$h(gmF9   &@9DYPjY   V>}T6l [nk׮ID$GRlYI&ɸqUVB… 2ei޼<98yȑR^h+KjG.iӦڵ=zx|ǏFGIڵm޼YVZ%mڴ.H$@${(gc=[~0  @VB,رC>S {N._rbgϞ\V굜ź`3f gkժ%R:HL\Y@  ~1 Dl-lHHH x#gܹ#}UQ9sf9;a)V_8qbXʕK]dFf͚U ͒&MٳG-[&h'_|zޕ+W^cǎyJɒ%;Gn۶M۾}Jʕ+$:t\xQҥK.fϞ-ZO„ >sU?w?! >,˗/ r1riȐ!2`<?zHJ%\O< 4H?.'O\C_sj͚5QFfi߾,gM5BtDG"bm,A9"zv)h?HP%D BBNb#/+ xYH;s_|EPnxYtЅBӐ8fѢE)Qr =>Æb˗|T نc]%1꧑CByufl Ccǎ ^(EXRn~M}xE,`C]jTt.]t.QFG6ŕźn֬m#ZB"߭Y"qhhJes^[M KޝGTqJ*DDdRF&4JH̙L %UMMDd(4e5+~:tνg{{?y^ϾnHJ٤6&/xI2  _XY,# (V/ZU*Vǁ -@8Sp0@Bp6ǬYK5jd׏ y"@8'4Qge' l**kB@x SNp6鶌 # @ &f1U@`&Md̙֭3>. 6mӧx^~3+Rgr岼NޥJ2_~*gWXa}_Vti~(Q9oիg-qm?곩R!5\pV':hժU]8jYWGbP [nVSu9c g>upvn-[_~v=w}Z;x.j^Y+VUqG;վ^UmU-}#]VS8;dW gj{B̉)@t M' O8G@@b g0>ܮz;#/pVձ,GxsU ?_PhGBCš׫(V*B gؽ{빪ft_*JP+ u0U;g=\RJ1B &Z[p6' 3jٜ)H$$lp JMWM|~sLZx\˖-S(IwU/GR#x9lڴivw^xE:O֬YY,]^"! gvUQ=gUѫ`o؎;g} [ABZ b5bUe8ֶ3IDAT^dP?_zWpV/*W/[CVhcDF;pV~pV03tEuwU!r r:'̜lJo/Np6;!~ .k8{!/zW]H۴iS"*g5[}|Μ9ڒ%KW\a'|[Z@I Q~ guB'@Ka g5hz>mօY/p[Wc);ܘ}<ꨣ .0l?uշ~۵"P5s9ǽtnƖqZZ(VP^9 WQPլHHlNpVhذ[s…]덊+f gs:z"X  sٜqE Φf@H8Xل[H.O gi+.K/Ú ?Y2R &1e@Hضp667 Vp6X_FG M߽gfF8c '@8-## @jΦ>gc2@@$NA@ Mg<  @p22 lj#Qp6F8.C@|@@Hkٴ~O83 '@8-## @jΦ>gc2@@$NA@ Mg<  @p22 lj#Qp6F8.C@|@@Hkٴ~O83 '@8-## @jΦ>gc2@@$NA@ Mg<  @p22 lj#Qp6F8.C@|@@Hkٴ~O83 '@8-## @jΦ>gc2@@$NA@ Mg<  @p22 lj#Qp6F8.C@|@@Hkٴ~O83 '@8-## @jΦ>gc2@@$NA@ Mg<  @p22 lj#Qp6F8.C@|@@Hkٴ~O83 '@8m:h馛w~=>]vqΟ?fϞ~ֲeK^z9o-^؎;8G|UuYdɒ!N:${Mcrݿy蜪T#4\ކ T}GѢE ts  3+Wgs  @ n8M;]ڳgOZӧguZ]I)|ݏ*`xhvU ۫W/+Y۷/sSŧ*[u<35Cwu߿5jd t8`#Fp!erlذanoJ. 3f)~>s{UHu~̽?xѣzׯm޼ԩcݺu?ӭQofn 68' geVرcMcYƞx @@ QgugW 37A@42]t ߢvW9}t駟\eʔz}pVZ%Pgns/l[ ϟS03anB^UN2Ŏ<ȌիU 8UV @LVX1{Z\}n[9|.8/Z…+O2Uv~7;γʕ+[j2I_A IIL18l@8p63 h?l'|=CXYuꅌjJN~~*w O?>> a_~.]/UJ^oFUUj5jՃ*rUv\؏7v׮]nݺsquVh-ZT+wƌٵk׺VQ@W > $l \a&  A^u>+ CEtX4ΪrS-tV uꅌ $k׮3M^*\?UXꕻl28p^|[b易p6tm]jW?ή\ҵaZ9 .̴ƍMשGW_}=n8v@D M]aN&@8k@P pVUG0u֦?R2Ys 2)ݲe+VvM4qbUuU*HT*N/p"=Gs纠7G iy%j;wz0Vs>C/6 9@HDDkF͍@@ gUŪH)DUdzRUϾ;o>Y:sLwB>UnذUn۶hӧ^U5z*HmٲOpZ{QO"=zi{g}mڴ-^5hU*T(e={뵪9WTڶm^*c7ݻw-2Vcj-C*U5YU˂iKFH+OIENDB`icingaweb2-module-toplevelview-1.0.0/library/000077500000000000000000000000001473125420300211755ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/000077500000000000000000000000001473125420300236625ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Model/000077500000000000000000000000001473125420300247225ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Model/View.php000066400000000000000000000141761473125420300263560ustar00rootroot00000000000000name = $name; $this->format = $format; } public function __clone() { $this->name = null; $this->raw = null; $this->tree = null; $this->hasBeenLoaded = false; $this->hasBeenLoadedFromSession = false; } /** * getTree loads the Tree for this configuration * * @return TLVTree */ public function getTree(): TLVTree { if ($this->tree === null) { $this->ensureParsed(); $this->tree = $tree = TLVTree::fromArray($this->raw); $tree->setViewName($this->getName()); $tree->setViewChecksum($this->getTextChecksum()); } return $this->tree; } /** * ensureParsed parses the Views YAML text. * * @throws InvalidPropertyException if the YAML config cannot be parsed * @throws NotImplementedError if the format is unknown */ protected function ensureParsed() { if ($this->raw === null) { Benchmark::measure('Begin parsing YAML document'); $text = $this->getText(); if ($text === null) { // new View $this->raw = array(); } elseif ($this->format == self::FORMAT_YAML) { // TODO: use stdClass instead of Array? $this->raw = yaml_parse($text); if (! is_array($this->raw)) { throw new InvalidPropertyException('Could not parse YAML config!'); } } else { throw new NotImplementedError("Unknown format '%s'", $this->format); } Benchmark::measure('Finished parsing YAML document'); } } /** * getMeta returns a value from the View's metadata. * Metadata are root elemts in the YAML file that are not 'children' * @throws ProgrammingError if you try to edit children here */ public function getMeta($key) { $this->ensureParsed(); if ($key !== 'children' && array_key_exists($key, $this->raw)) { return $this->raw[$key]; } else { return null; } } /** * setMeta sets a given key's value * * @throws ProgrammingError if you try to edit children here */ public function setMeta($key, $value) { if ($key === 'children') { throw new ProgrammingError('You can not edit children here!'); } $this->raw[$key] = $value; return $this; } /** * getMetaData returns all YAML root elements that are not 'childen', * thus the View's metadata. */ public function getMetaData() { $this->ensureParsed(); $data = array(); foreach ($this->raw as $key => $value) { if ($key !== 'children') { $data[$key] = $value; } } return $data; } /** * @return bool */ public function hasBeenLoadedFromSession() { return $this->hasBeenLoadedFromSession; } /** * @return bool */ public function hasBeenLoaded() { return $this->hasBeenLoaded; } /** * getText returns the Views text, which contains the full YAML data * @return string */ public function getText(): ?string { return $this->text; } /** * getTextChecksum returns the textChecksum of this View * @return string */ public function getTextChecksum(): string { if ($this->textChecksum === null) { $this->textChecksum = sha1($this->text); } return $this->textChecksum; } /** * getFormat returns the View's format */ public function getFormat(): string { return $this->format; } /** * setText sets the text (YAML) for this View. * Hint: This will reset textChecksum, raw, and tree * @param $text * @return $this */ public function setText($text) { $this->text = $text; $this->textChecksum = null; $this->raw = null; $this->tree = null; return $this; } /** * validateName validates the name of the view. * This can be used to ensure the YAML files have proper/expected names * @return bool */ public function validateName(): bool { if (empty($this->name)) { return false; } if (preg_match('/[!@#\$%^&*\/\\\()]/', $this->name)) { return false; } return true; } /** * getName returns the name of this View * @return ?string */ public function getName(): ?string { return $this->name; } /** * setName sets the name for this View * @param string $name * @return $this */ public function setName($name) { $this->name = $name; return $this; } } icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Tree/000077500000000000000000000000001473125420300245615ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Tree/TLVHostGroupNode.php000066400000000000000000000115711473125420300304250ustar00rootroot00000000000000 */ namespace Icinga\Module\Toplevelview\Tree; use Icinga\Application\Benchmark; use Icinga\Exception\NotFoundError; use Icinga\Module\Icingadb\Model\Hostgroupsummary; use ipl\Stdlib\Filter; use stdClass; /** * TLVHostGroupNode represents a Hostgroup in the tree */ class TLVHostGroupNode extends TLVIcingaNode { protected $type = 'hostgroup'; protected $key = 'hostgroup'; protected static $titleKey = 'hostgroup'; public function getTitle(): string { $key = $this->getKey(); $obj = $this->root->getFetched($this->type, $key); $n = $this->get($this->key); if (isset($obj->display_name)) { $n = $obj->display_name; } return sprintf('%s', $n); } public static function fetch(TLVTree $root): void { Benchmark::measure('Begin fetching hostgroups'); if (! array_key_exists('hostgroup', $root->registeredObjects) or empty($root->registeredObjects['hostgroup'])) { throw new NotFoundError('No hostgroups registered to fetch!'); } $hgFilter = Filter::any(); foreach (array_keys($root->registeredObjects['hostgroup']) as $name) { $hgFilter->add(Filter::equal('hostgroup_name', $name)); } $hostgroups = Hostgroupsummary::on($root->getDb()); $hostgroups->filter($hgFilter); foreach ($hostgroups as $hostgroup) { // TODO We cannot store the ORM Models with json_encore // Thus I'm converting things to objects that can be stored // Maybe there's a better way? iterator_to_array does not work. $hg = new stdClass; $hg->display_name = $hostgroup->display_name; $hg->hosts_total = $hostgroup->hosts_total; $hg->hosts_up = $hostgroup->hosts_up; $hg->hosts_total = $hostgroup->hosts_total; $hg->services_total = $hostgroup->services_total; $hg->hosts_up = $hostgroup->hosts_up; $hg->services_ok = $hostgroup->services_ok; $hg->hosts_down_handled = $hostgroup->hosts_down_handled; $hg->hosts_down_unhandled = $hostgroup->hosts_down_unhandled; $hg->services_warning_handled = $hostgroup->services_warning_handled; $hg->services_warning_unhandled = $hostgroup->services_warning_unhandled; $hg->services_critical_handled = $hostgroup->services_critical_handled; $hg->services_critical_unhandled = $hostgroup->services_critical_unhandled; $hg->services_unknown_handled = $hostgroup->services_unknown_handled; $hg->services_unknown_unhandled = $hostgroup->services_unknown_unhandled; $root->registeredObjects['hostgroup'][$hostgroup->name] = $hg; } Benchmark::measure('Finished fetching hostgroups'); } /** * getStatus returns the current status for the Hostgroup * * @return TLVStatus */ public function getStatus(): TLVStatus { if ($this->status !== null) { return $this->status; } $this->status = $status = new TLVStatus(); $key = $this->getKey(); $hostgroup = $this->root->getFetched($this->type, $key); if ($hostgroup === null) { $this->status->add('missing', 1); return $this->status; } $status->set('total', $hostgroup->hosts_total + $hostgroup->services_total); $status->set('ok', $hostgroup->hosts_up + $hostgroup->services_ok); $status->set('critical_handled', $hostgroup->services_critical_handled); $status->set('critical_unhandled', $hostgroup->services_critical_unhandled); // Override the host status to handled if the option is set if ($this->getRoot()->get('override_host_problem_to_handled') === true) { $status->add( 'critical_handled', $hostgroup->hosts_down_handled + $hostgroup->hosts_down_unhandled ); } else { $status->add( 'critical_handled', $hostgroup->hosts_down_handled ); $status->add( 'critical_unhandled', $hostgroup->hosts_down_unhandled ); } $status->set('warning_handled', $hostgroup->services_warning_handled); $status->set('warning_unhandled', $hostgroup->services_warning_unhandled); $status->set('unknown_handled', $hostgroup->services_unknown_handled); $status->set('unknown_unhandled', $hostgroup->services_unknown_unhandled); // extra metadata for view $status->setMeta('hosts_total', $hostgroup->hosts_total); $status->setMeta( 'hosts_unhandled', $hostgroup->hosts_down_unhandled ); $status->set('missing', 0); return $this->status; } } icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Tree/TLVHostNode.php000066400000000000000000000077641473125420300274210ustar00rootroot00000000000000 */ namespace Icinga\Module\Toplevelview\Tree; use Icinga\Application\Benchmark; use Icinga\Exception\NotFoundError; use Icinga\Module\Icingadb\Model\Host; use ipl\Stdlib\Filter; use stdClass; /** * TLVHostNode represents a Host in the tree */ class TLVHostNode extends TLVIcingaNode { protected $type = 'host'; protected $key = 'host'; protected static $titleKey = 'host'; public function getTitle(): string { $key = $this->getKey(); $obj = $this->root->getFetched($this->type, $key); $n = $this->get($this->key); if (isset($obj->display_name)) { $n = $obj->display_name; } return sprintf('%s', $n); } public static function fetch(TLVTree $root): void { Benchmark::measure('Begin fetching hosts'); if (! array_key_exists('host', $root->registeredObjects) or empty($root->registeredObjects['host'])) { throw new NotFoundError('No hosts registered to fetch!'); } $hostnameFilter = Filter::any(); foreach (array_keys($root->registeredObjects['host']) as $name) { $hostnameFilter->add(Filter::equal('name', $name)); } $hosts = Host::on($root->getDb())->with([ 'state' ]); $hosts->filter($hostnameFilter); foreach ($hosts as $host) { // TODO We cannot store the ORM Models with json_encore // Thus I'm converting things to objects that can be stored // Maybe there's a better way? iterator_to_array does not work. $h = new stdClass; $h->state = new stdClass; $h->display_name = $host->display_name; $h->notifications_enabled = $host->notifications_enabled; $h->state->hard_state = $host->state->hard_state; $h->state->is_flapping = $host->state->is_flapping; $h->state->is_handled = $host->state->is_handled; $h->state->in_downtime = $host->state->in_downtime; $root->registeredObjects['host'][$host->name] = $h; } Benchmark::measure('Finished fetching hosts'); } /** * getStatus returns the current status for the Host * * @return TLVStatus */ public function getStatus(): TLVStatus { if ($this->status !== null) { return $this->status; } $this->status = $status = new TLVStatus(); $key = $this->getKey(); $host = $this->root->getFetched($this->type, $key); if ($host === null) { $this->status->add('missing', 1); return $this->status; } $status->zero(); $status->add('total'); // We only care about the hard state in TLV $state = $host->state->hard_state; // Check if the downtime is enabled if set_downtime_if_notification_disabled is true $downtime_if_no_notifications = $host->notifications_enabled === false && $this->getRoot()->get('set_downtime_if_notification_disabled'); if ($host->state->in_downtime || $downtime_if_no_notifications) { // Set downtime if notifications are disabled for the host $status->add('downtime_active'); $state = 10; $handled = ''; } elseif ($host->state->is_handled || $this->getRoot()->get('override_host_problem_to_handled')) { // Set the state to handled if it actually is handled, and the option is set to override the state $handled = '_handled'; } else { $handled = '_unhandled'; } if ($state === 0) { $status->add('ok'); } elseif ($state === 1 || $state === 2) { $status->add('critical' . $handled); } elseif ($state === 10) { $status->add('downtime_handled'); } else { $status->add('unknown_handled'); } return $this->status; } } icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Tree/TLVIcingaNode.php000066400000000000000000000013771473125420300276700ustar00rootroot00000000000000 */ namespace Icinga\Module\Toplevelview\Tree; use Icinga\Exception\NotImplementedError; /** * Leaf nodes that fetch data from the database are TLVIcingaNodes. * @codeCoverageIgnore */ class TLVIcingaNode extends TLVTreeNode { protected static $canHaveChildren = false; /** * Interface to fetch data for the implementation * * Needs to be extended / replaced by class * * @param $root * * @throws NotImplementedError */ public static function fetch(/** @noinspection PhpUnusedParameterInspection */ TLVTree $root): void { throw new NotImplementedError('fetch() has not been implemented for %s', get_class(new static)); } } icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Tree/TLVServiceGroupNode.php000066400000000000000000000076311473125420300311120ustar00rootroot00000000000000 */ namespace Icinga\Module\Toplevelview\Tree; use Icinga\Application\Benchmark; use Icinga\Exception\NotFoundError; use Icinga\Module\Icingadb\Model\ServicegroupSummary; use ipl\Stdlib\Filter; use stdClass; /** * TLVServiceGroupNode represents a Servicegroup in the tree */ class TLVServiceGroupNode extends TLVIcingaNode { protected $type = 'servicegroup'; protected $key = 'servicegroup'; protected static $titleKey = 'servicegroup'; public function getTitle(): string { $key = $this->getKey(); $obj = $this->root->getFetched($this->type, $key); $n = $this->get($this->key); if (isset($obj->display_name)) { $n = $obj->display_name; } return sprintf('%s', $n); } public static function fetch(TLVTree $root): void { Benchmark::measure('Begin fetching servicegroups'); if (! array_key_exists('servicegroup', $root->registeredObjects) or empty($root->registeredObjects['servicegroup'])) { throw new NotFoundError('No servicegroups registered to fetch!'); } $hgFilter = Filter::any(); foreach (array_keys($root->registeredObjects['servicegroup']) as $name) { $hgFilter->add(Filter::equal('servicegroup_name', $name)); } $servicegroups = ServicegroupSummary::on($root->getDb()); $servicegroups->filter($hgFilter); foreach ($servicegroups as $servicegroup) { // TODO We cannot store the ORM Models with json_encore // Thus I'm converting things to objects that can be stored // Maybe there's a better way? iterator_to_array does not work. $sg = new stdClass; $sg->display_name = $servicegroup->display_name; $sg->services_total = $servicegroup->services_total; $sg->services_ok = $servicegroup->services_ok; $sg->services_warning_handled = $servicegroup->services_warning_handled; $sg->services_warning_unhandled = $servicegroup->services_warning_unhandled; $sg->services_critical_handled = $servicegroup->services_critical_handled; $sg->services_critical_unhandled = $servicegroup->services_critical_unhandled; $sg->services_unknown_handled = $servicegroup->services_unknown_handled; $sg->services_unknown_unhandled = $servicegroup->services_unknown_unhandled; $root->registeredObjects['servicegroup'][$servicegroup->name] = $sg; } Benchmark::measure('Finished fetching servicegroups'); } /** * getStatus returns the current status for the Servicegroup * * @return TLVStatus */ public function getStatus(): TLVStatus { if ($this->status !== null) { return $this->status; } $this->status = $status = new TLVStatus(); $key = $this->getKey(); $servicegroup = $this->root->getFetched($this->type, $key); if ($servicegroup === null) { $this->status->add('missing', 1); return $this->status; } $status->set('total', $servicegroup->services_total); $status->set('ok', $servicegroup->services_ok); $status->set('critical_handled', $servicegroup->services_critical_handled); $status->set('critical_unhandled', $servicegroup->services_critical_unhandled); $status->set('warning_handled', $servicegroup->services_warning_handled); $status->set('warning_unhandled', $servicegroup->services_warning_unhandled); $status->set('unknown_handled', $servicegroup->services_unknown_handled); $status->set('unknown_unhandled', $servicegroup->services_unknown_unhandled); // extra metadata for view $status->setMeta('services_total', $servicegroup->services_total); $status->set('missing', 0); return $this->status; } } icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Tree/TLVServiceNode.php000066400000000000000000000120561473125420300300720ustar00rootroot00000000000000 */ namespace Icinga\Module\Toplevelview\Tree; use Icinga\Application\Benchmark; use Icinga\Exception\NotFoundError; use Icinga\Module\Icingadb\Model\Service; use ipl\Stdlib\Filter; use stdClass; /** * TLVServiceNode represents a Service in the tree */ class TLVServiceNode extends TLVIcingaNode { protected $type = 'service'; protected $key = '{host}!{service}'; public function getTitle(): string { $key = $this->getKey(); $obj = $this->root->getFetched($this->type, $key); $name = $this->get($this->type); $hostname = $this->get('host'); if (isset($obj->display_name)) { $name = $obj->display_name; } if (isset($obj->display_name)) { $hostname = $obj->host->display_name; } return sprintf('%s: %s', $hostname, $name); } public function register() { // also register host, because that's what we fetch data with $hostDummy = new TLVHostNode(); $this->root->registerObject($hostDummy->getType(), $this->get('host'), get_class($hostDummy)); // register myself return parent::register(); } public function getKey(): string { return sprintf('%s!%s', $this->properties['host'], $this->properties['service']); } public static function fetch(TLVTree $root): void { Benchmark::measure('Begin fetching services'); if (! array_key_exists('service', $root->registeredObjects) or empty($root->registeredObjects['service'])) { throw new NotFoundError('No services registered to fetch!'); } $hostnameFilter = Filter::any(); foreach (array_keys($root->registeredObjects['host']) as $name) { $hostnameFilter->add(Filter::equal('host.name', $name)); } $services = Service::on($root->getDb())->with([ 'host', 'state' ]); $services->filter($hostnameFilter); foreach ($services as $service) { // TODO We cannot store the ORM Models with json_encore // Thus I'm converting things to objects that can be stored // Maybe there's a better way? iterator_to_array does not work. $s = new stdClass; $s->state = new stdClass; $s->host = new stdClass; $s->name = $service->name; $s->display_name = $service->display_name; $s->notifications_enabled = $service->notifications_enabled; $s->host->display_name = $service->host->display_name; $s->state->hard_state = $service->state->hard_state; $s->state->is_flapping = $service->state->is_flapping; $s->state->is_handled = $service->state->is_handled; $s->state->in_downtime = $service->state->in_downtime; $key = sprintf('%s!%s', $service->host->name, $service->name); if (array_key_exists($key, $root->registeredObjects['service'])) { $root->registeredObjects['service'][$key] = $s; } } Benchmark::measure('Finished fetching services'); } /** * getStatus returns the current status for the Service * * @return TLVStatus */ public function getStatus(): TLVStatus { if ($this->status !== null) { return $this->status; } $this->status = $status = new TLVStatus(); $key = $this->getKey(); $service = $this->root->getFetched($this->type, $key); if ($service === null) { $status->add('missing', 1); return $this->status; } $status->zero(); $status->add('total'); // We only care about the hard state in TLV $state = $service->state->hard_state; // Get the service's current handled state $isHandled = $service->state->is_handled; // In TLV flapping means the state is handled $isHandled = $isHandled || $service->state->is_flapping; // Check if the downtime is enabled if set_downtime_if_notification_disabled is true $downtime_if_no_notifications = $service->notifications_enabled === false && $this->getRoot()->get('set_downtime_if_notification_disabled'); if ($service->state->in_downtime || $downtime_if_no_notifications) { $status->add('downtime_active'); if ($state !== 0) { $state = 10; } } if ($isHandled) { $handled = '_handled'; } else { $handled = '_unhandled'; } if ($state === 0 || $state === 99) { $status->add('ok', 1); } elseif ($state === 1) { $status->add('warning' . $handled, 1); } elseif ($state === 2) { $status->add('critical' . $handled, 1); } elseif ($state === 10) { $status->add('downtime_handled'); } else { $status->add('unknown' . $handled, 1); } return $this->status; } } icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Tree/TLVStatus.php000066400000000000000000000100551473125420300271440ustar00rootroot00000000000000 */ namespace Icinga\Module\Toplevelview\Tree; /** * TLVStatus represents the status for a TLVTreeNode that is shown in the view */ class TLVStatus { /** * Properties track each tree nodes Icinga states */ protected $properties = [ 'critical_unhandled' => null, 'critical_handled' => null, 'warning_unhandled' => null, 'warning_handled' => null, 'unknown_unhandled' => null, 'unknown_handled' => null, 'downtime_handled' => null, 'downtime_active' => null, 'ok' => null, 'missing' => null, 'total' => null, ]; /** * statusPriority decribes the priority from worst to best */ protected static $statusPriority = [ 'critical_unhandled', 'warning_unhandled', 'unknown_unhandled', 'critical_handled', 'warning_handled', 'unknown_handled', 'ok', 'downtime_handled', 'missing', ]; /** * meta tracks get overall count of hosts and services if this status object */ protected $meta = []; /** * merge merges another TLVStatus object's properties into this object */ public function merge(TLVStatus $status) { $properties = $status->getProperties(); foreach (array_keys($this->properties) as $key) { if ($this->properties[$key] === null) { $this->properties[$key] = $properties[$key]; } else { $this->properties[$key] += $properties[$key]; } } return $this; } /** * get returns the given key's value from the properties * * @param string $key key of the property */ public function get($key) { return $this->properties[$key]; } /** * set sets the given key/value in the properties * * @param string $key key of the property * @param int $value value to set to property to */ public function set($key, $value) { $this->properties[$key] = (int) $value; return $this; } /** * getProperties returns all properties */ public function getProperties() { return $this->properties; } /** * add adds the given value (integer) to the given property * * @param string $key key of the property * @param int $value value to add to the property */ public function add($key, $value = 1) { if ($this->properties[$key] === null) { $this->properties[$key] = 0; } $this->properties[$key] += (int) $value; return $this; } /** * zero sets all properties to zero (0) */ public function zero() { foreach (array_keys($this->properties) as $key) { $this->properties[$key] = 0; } return $this; } /** * getOverall returns the worst state of this TLVStatus, * given the statusPriority. * * @return string */ public function getOverall(): string { foreach (static::$statusPriority as $key) { if ($this->properties[$key] !== null && $this->properties[$key] > 0) { return $this->cssFriendly($key); } } return 'missing'; } /** * cssFriendly transforms the given key to be CSS friendly, * meaning using spaces between the state and the handled indicator */ protected function cssFriendly($key): string { return str_replace('_', ' ', $key); } /** * getMeta returns the given key's value from the metadata */ public function getMeta($key) { if (array_key_exists($key, $this->meta)) { return $this->meta[$key]; } else { return null; } } /** * setMeta sets the given key/value in the metadata */ public function setMeta($key, $value) { $this->meta[$key] = $value; } } icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Tree/TLVTree.php000066400000000000000000000151541473125420300265650ustar00rootroot00000000000000 */ namespace Icinga\Module\Toplevelview\Tree; use Icinga\Module\Toplevelview\Model\View; use Icinga\Application\Logger; use Icinga\Exception\IcingaException; use Icinga\Exception\NotFoundError; use Icinga\Exception\ProgrammingError; use Icinga\Module\Icingadb\Common\Database; use Icinga\Util\Json; use Icinga\Web\FileCache; use stdClass; /** * TLVTree represents the root of the TLV tree */ class TLVTree extends TLVTreeNode { /** * @var Database */ use Database; protected static $titleKey = 'name'; public $registeredTypes = array(); public $registeredObjects = array(); protected $fetchedData = array(); protected $fetched = false; protected $fetchTime; protected $cacheLifetime = 60; protected $viewName; protected $viewChecksum; /** * Return a child by its ID * * @throws NotFoundError if the id cannot be found */ public function getById($id) { $ids = explode('-', $id); $currentNode = $this; foreach ($ids as $i) { $children = $currentNode->getChildren(); if (! empty($children) && array_key_exists($i, $children)) { $currentNode = $children[$i]; } else { throw new NotFoundError( 'Could not find ID %s after %s for path %s', $i, $currentNode->getFullId(), $id ); } } return $currentNode; } public function getViewName(): ?string { return $this->viewName; } public function setViewName(string $name) { $this->viewName = $name; return $this; } public function getViewChecksum(): ?string { return $this->viewChecksum; } public function setViewChecksum(string $checksum) { $this->viewChecksum = $checksum; return $this; } /** * registerObject adds a new object via its type, name and class * * @throws ProgrammingError if the same type by multiple classes is registered */ public function registerObject($type, $name, $class) { if (array_key_exists($type, $this->registeredTypes) && $this->registeredTypes[$type] !== $class) { throw new ProgrammingError( 'Tried to register the same type by multiple classes: %s - %s - %s', $type, $this->registeredTypes[$type], $class ); } $this->registeredTypes[$type] = $class; $this->registeredObjects[$type][$name] = null; } protected function getCacheName() { $n = $this->getViewName(); $c = $this->getViewChecksum(); return sprintf('%s-%s.json', $n, $c); } protected function loadCache() { if (($lifetime = $this->getCacheLifetime()) <= 0) { return; } $cacheName = $this->getCacheName(); try { $cache = FileCache::instance('toplevelview'); $currentTime = time(); $newerThan = $currentTime - $lifetime; if ($cache->has($cacheName)) { $cachedData = Json::decode($cache->get($cacheName)); if (property_exists($cachedData, 'data') && $cachedData->data !== null && property_exists($cachedData, 'ts') && $cachedData->ts <= $currentTime // too new maybe && $cachedData->ts > $newerThan // too old ) { foreach ($cachedData->data as $type => $objects) { $this->registeredObjects[$type] = (array) $objects; $this->fetchedData[$type] = true; } $this->fetchTime = $cachedData->ts; $this->fetched = true; } } } catch (IcingaException $e) { Logger::error('Could not load from toplevelview cache %s: %s', $cacheName, $e->getMessage()); } } protected function storeCache() { if (($lifetime = $this->getCacheLifetime()) <= 0) { return; } $cacheName = $this->getCacheName(); try { $cache = FileCache::instance('toplevelview'); $cachedData = new stdClass; $cachedData->ts = $this->fetchTime; $cachedData->data = $this->registeredObjects; $cache->store($cacheName, Json::encode($cachedData)); } catch (IcingaException $e) { Logger::error('Could not store to toplevelview cache %s: %s', $cacheName, $e->getMessage()); } } /** * fetchType returns a given type from the registered types * * @throws ProgrammingError if the type has not been registered */ protected function fetchType($type) { if (! array_key_exists($type, $this->registeredTypes)) { throw new ProgrammingError('Type %s has not been registered', $type); } if (! array_key_exists($type, $this->fetchedData)) { /** @var TLVIcingaNode $class */ $class = $this->registeredTypes[$type]; $class::fetch($this); $this->fetchedData[$type] = true; } return $this; } protected function ensureFetched() { if ($this->fetched !== true) { $this->loadCache(); if ($this->fetched !== true) { foreach (array_keys($this->registeredTypes) as $type) { $this->fetchType($type); } $this->fetchTime = time(); $this->fetched = true; $this->storeCache(); } } return $this; } public function getFetched($type, $key) { $this->ensureFetched(); if (array_key_exists($key, $this->registeredObjects[$type]) && $this->registeredObjects[$type][$key] !== null ) { return $this->registeredObjects[$type][$key]; } else { return null; } } /** * @return int time */ public function getFetchTime() { $this->ensureFetched(); return $this->fetchTime; } /** * @return int seconds */ public function getCacheLifetime() { return $this->cacheLifetime; } /** * @param int $cacheLifetime In seconds * * @return $this */ public function setCacheLifetime($cacheLifetime) { $this->cacheLifetime = $cacheLifetime; return $this; } } icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Tree/TLVTreeNode.php000066400000000000000000000214201473125420300273640ustar00rootroot00000000000000 */ namespace Icinga\Module\Toplevelview\Tree; use Icinga\Module\Toplevelview\Util\Str; use Icinga\Application\Benchmark; use Icinga\Data\Tree\TreeNode; use Icinga\Exception\ConfigurationError; use Icinga\Exception\NotImplementedError; use Icinga\Exception\ProgrammingError; /** * TLVTreeNode represents a node in the TLV tree */ class TLVTreeNode extends TreeNode { /** * @var string */ protected $type = 'node'; /** * @var string */ protected $key = null; /** * @var TLVTree */ protected $root; /** * @var TLVTreeNode */ protected $parent; /** * @var string */ protected $fullId; /** * @var TLVStatus */ protected $status; /** * @var array */ protected $properties = array(); /** * Determine if this node is a leaf * * @var bool */ protected static $canHaveChildren = true; /** * The key which represents the display title * * @var string */ protected static $titleKey = 'name'; /** * Mapping types to its implementation class * * @var array */ protected static $typeMap = [ 'host' => 'Icinga\\Module\\Toplevelview\\Tree\\TLVHostNode', 'service' => 'Icinga\\Module\\Toplevelview\\Tree\\TLVServiceNode', 'hostgroup' => 'Icinga\\Module\\Toplevelview\\Tree\\TLVHostGroupNode', 'servicegroup' => 'Icinga\\Module\\Toplevelview\\Tree\\TLVServiceGroupNode', ]; /** * Mapping keys to a type * * Warning: order is important when keys overlap! * * @var array */ protected static $typeKeyMap = [ 'service' => ['host', 'service'], 'host' => 'host', 'hostgroup' => 'hostgroup', 'servicegroup' => 'servicegroup', ]; /** * @param $array * @param TLVTreeNode|null $parent * @param TLVTree $root * * @return static * * @throws NotImplementedError * @throws ProgrammingError */ public static function fromArray($array, TLVTreeNode $parent = null, TLVTree $root = null) { if ($root === null) { Benchmark::measure('Begin loading TLVTree from array'); } // Check if gots an array if (! is_array($array)) { throw new NotImplementedError("YAML not valid. %s needs to be an array", var_export($array, true)); } // try to detect type if (! array_key_exists('type', $array)) { foreach (self::$typeKeyMap as $type => $keys) { if (! is_array($keys)) { $keys = [$keys]; } $matched = false; foreach ($keys as $k) { if (array_key_exists($k, $array)) { $matched = true; } else { continue 2; } } // if all keys are present if ($matched === true) { $array['type'] = $type; break; } } } if (array_key_exists('type', $array)) { $type = $array['type']; if (array_key_exists($type, self::$typeMap)) { $node = new self::$typeMap[$type]; $node->type = $type; } else { throw new NotImplementedError('Could not find type "%s" for %s', $type, var_export($array, true)); } } elseif ($root === null) { $node = new static; } else { $node = new self; } if ($root === null) { $node->root = true; // is root $node->parent = null; $root = $parent = $node; } elseif ($parent === null) { throw new ProgrammingError('You must specify the direct parent!'); } else { $node->root = $root; $node->parent = $parent; } foreach ($array as $key => $value) { if ($key !== 'children') { $node->properties[$key] = $value; } elseif (is_array($value)) { // only array values for children foreach ($value as $i => $child) { $childNode = self::fromArray($child, $node, $root); $childNode->id = $i; $node->appendChild($childNode); } } } $node->register(); if ($root === $node) { Benchmark::measure('Finished loading TLVTree from array'); } return $node; } /** * Retrieve all objects as breadcrumb * * @param array $list for recursion * * @return TLVTreeNode[] */ public function getBreadCrumb(&$list = array()) { array_unshift($list, $this); if ($this->parent !== $this->root) { $this->parent->getBreadCrumb($list); } return $list; } /** * * @return mixed|string */ public function getFullId() { if ($this->fullId === null) { $id = (string) $this->id; if ($this->parent !== $this->root) { $this->fullId = $this->parent->getFullId() . '-' . $id; } else { $this->fullId = $id; } } return $this->fullId; } /** * @return mixed */ public function getType() { return $this->type; } public function getProperties() { return $this->properties; } public function setProperties($array) { $this->properties = $array; return $this; } public function get($key) { if (array_key_exists($key, $this->properties)) { return $this->properties[$key]; } else { return null; } } public function set($key, $value) { $this->properties[$key] = $value; return $this; } public function getTitle() { if (array_key_exists(static::$titleKey, $this->properties)) { return Str::limit($this->properties[static::$titleKey], 45); } else { return null; } } /** * getKey returns the object's key * * @throws ProgrammingError if the key does not exist */ public function getKey() { if ($this->key === null) { throw new ProgrammingError('Can not get key for %s', get_class($this)); } if (array_key_exists($this->key, $this->properties)) { return $this->properties[$this->key]; } else { throw new ProgrammingError( 'Can not retrieve key for %s in %s', $this->key, get_class($this) ); } } /** * @return TLVTree */ public function getRoot() { return $this->root; } /** * @return TLVTreeNode */ public function getParent() { return $this->parent; } /** * @return TLVTreeNode[] */ public function getChildren() { return parent::getChildren(); } /** * Append a child node as the last child of this node * * @param TreeNode $child The child to append * * @return $this * * @throws ConfigurationError When node does not allow children */ public function appendChild(TreeNode $child) { if (static::$canHaveChildren === true) { $this->children[] = $child; } else { throw new ConfigurationError('Can not add children below type %s', $this->type); } return $this; } protected function register() { if ($this->type !== 'node') { $this->root->registerObject($this->type, $this->getKey(), get_class($this)); } return $this; } /** * getStatus returns the object's status * * @return TLVStatus * @throws ProgrammingError */ public function getStatus() { if (static::$canHaveChildren === true) { if ($this->status === null) { $this->status = new TLVStatus; $missed = true; foreach ($this->getChildren() as $child) { $this->status->merge($child->getStatus()); $missed = false; } // Note: old TLV does not count an empty branch as missing... if ($missed) { $this->status->add('missing', 1); } } return $this->status; } else { throw new ProgrammingError('getStatus() needs to be implemented for %s', get_class($this)); } } } icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Util/000077500000000000000000000000001473125420300245775ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Util/Auth.php000066400000000000000000000053571473125420300262230ustar00rootroot00000000000000getAuth()->getUser(); // If the user is unrestricted no restrictions apply if ($user->isUnrestricted()) { return true; } if ($restrictions->isEmpty()) { return true; } if (Filter::match($restrictions, ['name' => $name])) { return true; } throw new SecurityException('No permission for %s', $name); } /** * assertAccessToView asserts that the current user has permission * for the given view. Returns false if not */ public function hasAccessToView($restrictions, $name): bool { $user = $this->getAuth()->getUser(); // If the user is unrestricted no restrictions apply if ($user->isUnrestricted()) { return true; } if ($restrictions->isEmpty()) { return true; } return Filter::match($restrictions, ['name' => $name]); } /** * getRestrictions returns the current user's restrictions. */ public function getRestrictions($name = 'toplevelview/filter/views') { $user = $this->getAuth()->getUser(); // The final filter that is applied to the query. // Any means any filter has to match $f = Filter::any(); // For each of the user's roles add the given restrictions foreach ($user->getRoles() as $role) { // All means ALL filters have to match $roleFilter = Filter::any(); // Load the restrictions for the user's role and parse them into a filter $restriction = $role->getRestrictions($name); if ($restriction) { // Parse the given restriction and return a Filter\Rule $res = Str::trimSplit($restriction); foreach ($res as $r) { // Add the new Rule to the role filter $roleFilter->add(Filter::equal('name', $r)); } } // Add the filter to the overall filter if (! $roleFilter->isEmpty()) { $f->add($roleFilter); } } return $f; } } icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Util/Str.php000066400000000000000000000023631473125420300260640ustar00rootroot00000000000000 */ namespace Icinga\Module\Toplevelview; use Icinga\Module\Toplevelview\Model\View; use Icinga\Module\Toplevelview\Util\Auth; use Icinga\Exception\NotWritableError; use Icinga\Exception\NotReadableError; use Icinga\Util\DirectoryIterator; use Icinga\Web\Session; /** * Manages the View's configurations, loads and stores Views. */ class ViewConfig { use Auth; const FORMAT_YAML = 'yml'; const SESSION_PREFIX = 'toplevelview_view_'; /** * The module's configuration directory * @var string */ protected $config_dir; /** * @param $config_dir_module string Path to the module's configuration */ public function __construct($config_dir_module) { // Ensure the Views configuration directory exists $config_dir = $config_dir_module . DIRECTORY_SEPARATOR . 'views'; $this->ensureDirExists($config_dir_module); $this->ensureDirExists($config_dir); // Set the configuration directory $this->config_dir = $config_dir; } /** * getConfigDir returns the configuration directory * * @return string * @throws ProgrammingError When dir is not yet set */ public function getConfigDir(): string { if ($this->config_dir === null) { throw new ProgrammingError('Configuration directory does not exit'); } return $this->config_dir; } /** * ensureDirExists checks if a given path exists and creates the path if it doesn't * * @param string $path Path to create the directory at * @param string $mode Mode to create the directory with * @throws NotWritableError if the directory is not writable */ protected function ensureDirExists($path, $mode = '2770'): void { if (file_exists($path)) { return; } if (mkdir($path) !== true) { throw new NotWritableError( 'Configuration directory does not exit, and it could not be created: %s', $path ); } $octalMode = intval($mode, 8); if ($mode !== null && false === @chmod($path, $octalMode)) { throw new NotWritableError('Failed to set file mode "%s" on file "%s"', $mode, $path); } } /** * loadFromSession loads a View stored in the user's session * * @param string $name name of the View * @param string $format format of the View * @return ?View */ protected function loadFromSession($name, $format): ?View { // Try to load data from the session $sessionConfig = Session::getSession()->get(self::SESSION_PREFIX . $name); // If there is none, we return if ($sessionConfig === null) { return null; } // If there is data, create the View with the data $view = (new View($name, $format))->setText($sessionConfig); $view->hasBeenLoadedFromSession = true; $view->hasBeenLoaded = true; return $view; } /** * loadFromFile loads a View stored in a configuration file * * @param string $name name of the View * @param string $format format of the View * @throws NotReadableError if the file cannot be read * @return ?View */ protected function loadFromFile($name, $format): ?View { // Try to load the data from the file $file_path = $this->getConfigDir() . DIRECTORY_SEPARATOR . $name . '.' . $format; if (!is_readable($file_path)) { throw new NotReadableError('Could not read file %s', $file_path); } $text = file_get_contents($file_path); if ($text === false) { throw new NotReadableError('Could not read file %s', $file_path); } // If there is data, create the View with the data $view = (new View($name, $format))->setText($text); $view->hasBeenLoadedFromSession = false; $view->hasBeenLoaded = true; return $view; } /** * writeFile writes the given content to a given path. * Used to store the View's YAML content. * * @param $path Path to the file * @param $content Content of the file * @param $mode Mode of the new file * @throws NotWritableError if the file is not writable */ protected function writeFile($path, $content, $mode = '0660'): void { $existing = file_exists($path); if (file_put_contents($path, $content) === false) { throw new NotWritableError('Could not save to %s', $path); } if ($existing === false) { $octalMode = intval($mode, 8); if ($mode !== null && false === @chmod($path, $octalMode)) { throw new NotWritableError('Failed to set file mode "%s" on file "%s"', $mode, $path); } } } /** * Load a View by its name * * @param string $name Name of the view to load * @param string $format The format of the view * @param ipl\Stdlib\Filter $restrictions Filter that represents the restriction * * @return ?View */ public function loadByName($name, $format = self::FORMAT_YAML, $restrictions = null): ?View { // If restrictions are set, check if the user has access to view the View if (isset($restrictions)) { if (!$this->hasAccessToView($restrictions, $name)) { return null; } } // Try to load from session $view = $this->loadFromSession($name, $format); if (isset($view)) { return $view; } // Try to load the view from the file $view = $this->loadFromFile($name, $format); return $view; } /** * loadAll loads and returns all available Views. * * @param string|null $config_dir * @param string $format * * @return View[] */ public function loadAll($format = self::FORMAT_YAML): array { $suffix = '.' . $format; $restrictions = $this->getRestrictions('toplevelview/filter/views'); $views = array(); // Load the YAML files for the Views from the config directory $directory = new DirectoryIterator($this->config_dir, $suffix); foreach ($directory as $name => $path) { if (is_dir($path)) { // Do not descend and ignore directories continue; } $name = basename($name, $suffix); $view = $this->loadByName($name, $format, $restrictions); if (isset($view)) { $views[$name] = $view; } } // Try to load View from the session $len = strlen(self::SESSION_PREFIX); foreach (Session::getSession()->getAll() as $k => $v) { if (substr($k, 0, $len) === self::SESSION_PREFIX) { $name = substr($k, $len); if (! array_key_exists($name, $views)) { $view = $this->loadByName($name, $format, $restrictions); if (isset($view)) { $views[$name] = $view; } } } } // Sort and return the views ksort($views); return $views; } /** * storeToSession stores a View's text to the user's session * * @throws NotWritableError if the data cannot be stored * @throws SecurityException if the user has no access to edit * * @param $view */ public function storeToSession($view): void { // Assert the name is valid, to avoid tricky filenames such as '../../view' if (!$view->validateName()) { throw new NotWritableError('Invalid filename: %s', $view->getName()); } // Assert the user has rights to edit this view $restrictions = $this->getRestrictions('toplevelview/filter/edit'); $this->assertAccessToView($restrictions, $view->getName()); Session::getSession()->set(self::SESSION_PREFIX . $view->getName(), $view->getText()); } /** * clearSession removes a view from the user's session * * @param $view */ public function clearSession($view): void { Session::getSession()->delete(self::SESSION_PREFIX . $view->getName()); } /** * storeToFile stores a View to its configuration file * * @throws NotWritableError if the data cannot be stored * @throws SecurityException if the user has no access to edit * * @param $view */ public function storeToFile($view): void { // Assert the name is valid, to avoid tricky filenames such as '../../view' if (!$view->validateName()) { throw new NotWritableError('Invalid filename: %s', $view->getName()); } // Assert the user has rights to edit this file $restrictions = $this->getRestrictions('toplevelview/filter/edit'); $this->assertAccessToView($restrictions, $view->getName()); $file_path = $this->getConfigDir() . DIRECTORY_SEPARATOR . $view->getName() . '.' . $view->getFormat(); // Store a backup of the existing config if (file_exists($file_path)) { $this->storeBackup($view); } // Write the content to the file and clear the session $this->writeFile($file_path, $view->getText()); $this->clearSession($view); } /** * delete removes a Views configuration file * * @param $view */ public function delete($view): void { // Assert the user has rights to edit this view $restrictions = $this->getRestrictions('toplevelview/filter/edit'); $this->assertAccessToView($restrictions, $view->getName()); $file_path = $this->getConfigDir() . DIRECTORY_SEPARATOR . $view->getName() . '.' . $view->getFormat(); $this->clearSession($view); if (file_exists($file_path)) { $this->storeBackup($view, true); unlink($file_path); } } /** * storeBackup stores a timestamped backup file of a View's file, * if the content has changed * * @param $view The view to store * @param $force Stores a backup even if the content hasn't changed * @throws NotReadableError if the file cannot be read */ protected function storeBackup($view, $force = false): void { $backup_dir = $this->getConfigDir() . DIRECTORY_SEPARATOR . $view->getName(); $this->ensureDirExists($backup_dir); $ts = (string) time(); $backup = $backup_dir . DIRECTORY_SEPARATOR . $ts . '.' . $view->getFormat(); $existing_file = $this->getConfigDir() . DIRECTORY_SEPARATOR . $view->getName() . '.' . $view->getFormat(); $oldText = file_get_contents($existing_file); if ($oldText === false) { throw new NotReadableError('Could not read file %s', $existing_file); } // Only store a backup if the text changed or forced is set to true if ($force || $oldText !== $view->getText()) { $this->writeFile($backup, $oldText); } } } icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Web/000077500000000000000000000000001473125420300243775ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/library/Toplevelview/Web/Controller.php000066400000000000000000000017141473125420300272360ustar00rootroot00000000000000 */ namespace Icinga\Module\Toplevelview\Web; use Icinga\Exception\ConfigurationError; use ipl\Web\Compat\CompatController; /** * Controller wraps around the Icinga\Web\Controller to * check for the PHP YAML extension * * @codeCoverageIgnore * @throws ConfigurationError if the PHP yaml extension is not loaded */ class Controller extends CompatController { public function init() { parent::init(); if (! extension_loaded('yaml')) { throw new ConfigurationError('You need the PHP extension "yaml" in order to use TopLevelView'); } } protected function setViewScript($name, $controller = null): void { if ($controller !== null) { $name = sprintf('%s/%s', $controller, $name); } $this->_helper->viewRenderer->setNoController(true); $this->_helper->viewRenderer->setScriptAction($name); } } icingaweb2-module-toplevelview-1.0.0/module.info000066400000000000000000000006011473125420300216700ustar00rootroot00000000000000Module: toplevelview Version: 1.0.0 Requires: Libraries: icinga-php-library (>=0.13.0) Modules: icingadb (>=1.0.0) Description: Top Level View Top Level View is a hierarchy based status view for Icinga Web 2. You can define a hierarchical structure containing hosts, services and hostgroups. And the view presents you an overview of the overall status of the sub-hierarchies. icingaweb2-module-toplevelview-1.0.0/phpcs.xml000066400000000000000000000023321473125420300213700ustar00rootroot00000000000000 Sniff our code a while configuration.php application/ library/ vendor/* */application/views/helpers/* */application/views/helpers/* icingaweb2-module-toplevelview-1.0.0/phpunit.xml000066400000000000000000000013701473125420300217430ustar00rootroot00000000000000 test/php library icingaweb2-module-toplevelview-1.0.0/public/000077500000000000000000000000001473125420300210075ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/css/000077500000000000000000000000001473125420300215775ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/css/module.less000066400000000000000000000216521473125420300237620ustar00rootroot00000000000000/* Copyright (C) 2017 Icinga Development Team */ // See Icinga Web 2: public/css/icinga/base.less // All handled are color black to ensure readability, expect for warning @tlv-color-critical-bg: @color-critical; @tlv-color-critical-fg: white; @tlv-color-critical-handled-bg: @color-critical-handled; @tlv-color-critical-handled-fg: black; @tlv-color-warning-bg: @color-warning; @tlv-color-warning-fg: black; @tlv-color-warning-handled-bg: @color-warning-handled; @tlv-color-warning-handled-fg: black; @tlv-color-unknown-bg: @color-unknown; @tlv-color-unknown-fg: white; @tlv-color-unknown-handled-bg: @color-unknown-handled; @tlv-color-unknown-handled-fg: black; @tlv-color-ok-bg: @color-ok; @tlv-color-ok-fg: @text-color-inverted; @tlv-color-downtime-bg: fade(@color-ok, 75%); @tlv-color-downtime-fg: black; @tlv-color-downtime-handled-bg: @color-ok; @tlv-color-downtime-handled-fg: @color-warning-handled; @tlv-color-pending-bg: @color-pending; @tlv-color-pending-fg: white; @tlv-color-missing-bg: @gray-light; @tlv-color-missing-fg: @text-color; .tlv-overview-tiles .tlv-overview-tile { display: block; float: left; padding: 1em; margin: 0.5em; position: relative; width: 20em; height: 10em; border: 1px solid @gray-light; text-decoration: none; &:hover { background-color: @tr-hover-color; } .tlv-title { font-weight: bold; font-size: 1.25em; .text-ellipsis(); } .tlv-name { color: @gray; .text-ellipsis(); } } .tlv-status-tile { .badges { .badge { border: 0.1em solid @white; margin-left: 0.2em; } } &.critical, &.down { background-color: @tlv-color-critical-bg; color: @tlv-color-critical-fg; } &.critical.handled, &.down.handled { background-color: @tlv-color-critical-handled-bg; color: @tlv-color-critical-handled-fg; } &.unknown, &.unreachable { background-color: @tlv-color-unknown-bg; color: @tlv-color-unknown-fg; } &.unknown.handled, &.unreachable.handled { background-color: @tlv-color-unknown-handled-bg; color: @tlv-color-unknown-handled-fg; } &.warning { background-color: @tlv-color-warning-bg; color: @tlv-color-warning-fg; } &.warning.handled { background-color: @tlv-color-warning-handled-bg; color: @tlv-color-warning-handled-fg; } &.ok, &.up { background-color: @tlv-color-ok-bg; color: @tlv-color-ok-fg; } &.downtime.active { background-color: @tlv-color-downtime-bg; color: @tlv-color-downtime-fg; } &.downtime.handled { background-color: @tlv-color-downtime-handled-bg; color: @tlv-color-downtime-handled-fg; } &.pending { background-color: @tlv-color-pending-bg; color: @tlv-color-pending-fg; } &.missing { background-color: @tlv-color-missing-bg; color: @tlv-color-missing-fg; } &.total { background-color: @icinga-blue; color: @text-color-on-icinga-blue; } } .tlv-status-section { &.critical, &.down { border-color: @tlv-color-critical-bg; } &.critical.handled, &.down.handled { border-color: @tlv-color-critical-handled-bg; } &.unknown, &.unreachable { border-color: @tlv-color-unknown-bg; } &.unknown.handled, &.unreachable.handled { border-color: @tlv-color-unknown-handled-bg; } &.warning { border-color: @tlv-color-warning-bg; } &.warning.handled { border-color: @tlv-color-warning-handled-bg; } &.ok, &.up { border-color: @tlv-color-ok-bg; } &.pending { border-color: @tlv-color-pending-bg; } &.missing { border-color: @tlv-color-missing-bg; } } .tlv-content { position: relative; width: 100%; height: 100%; padding-right: 0 !important; padding-left: 0 !important; .tlv-header { margin: 0.5em; } } /** BEGIN of header **/ .tlv-header { display: inline-block; h1 { display: inline-block; border: none; margin: 0 0.5em 0 0; } .last-refresh { display: inline-block; } .action-links { display: inline-block; margin: 0 0.5em; } .badges { .badge { margin-left: 0.2em; } } } /** END of header **/ /** BEGIN of tiles **/ .tlv-view-tiles { display: flex; flex-wrap: wrap; height: 100%; .tlv-tiles { display: flex; flex-wrap: wrap; align-content: stretch; flex-grow: 1; width: 100%; height: 100%; margin-top: -2.3em; // - padding title - margin tile padding-top: 2.3em; // + padding title + margin tile } .tlv-tile { margin: 0.1em; flex-grow: 1; overflow: hidden; .badges { display: inline-block; font-weight: normal; margin-left: 0.2em; .badge { font-size: 0.7em; border: 0.1em solid @white; margin-left: 0.2em; } } } .tlv-tile-title { display: inline-block; width: 100%; padding: 0.1em; } > .tlv-tile { // first level min-width: 40%; border-style: solid; border-width: 1px 1px 1px 4px; padding: 0.1em; margin: 0.2em 0.5em; > .tlv-tile-title { font-weight: bold; > .badges { float: right; } } > .tlv-tiles > .tlv-tile { // second level min-width: 10%; > .tlv-tile-title { height: 100%; text-align: center; &:before { content: ""; display: inline-block; height: 100%; vertical-align: middle; } } } } } /** END of tiles **/ #layout.wide-layout .tlv-view-tiles .tlv-tile-title { font-size: 1.3em; } #layout.wide-layout.twocols .tlv-view-tiles .tlv-tile-title { font-size: 1.1em; } /** BEGIN of tree **/ .tlv-view-tree { .tlv-tree-node { display: flex; flex-wrap: wrap; flex-grow: 1; width: 100%; &.tlv-collapsed { width: auto; } background: none; border-style: solid; border-width: 2px 0 0 5px; padding: 0.2em 0 0 1em; &.tlv-collapsed { > .tlv-tree-node, > .tlv-node-icinga { display: none; } } .badges { display: inline-block; font-size: 0.9em; .badge { border: 0.1em solid @white; margin-left: 0.2em; } } } > .tlv-tree-node { border-right-width: 2px; &:last-of-type { border-bottom-width: 2px; } } .tlv-tree-title { display: block; width: 100%; white-space: nowrap; margin: -0.2em 0 0 -1em; padding: 0.3em 0.3em 0.3em 0.3em; .badges { float: right; } } .tlv-node-icinga { flex-grow: 1; margin: 0.2em; padding: 0.2em 1em; white-space: nowrap; border-radius: 0.5em; font-size: 0.9em; } } /** END of tree **/ .tlv-collapsible { .icon.tlv-collapse-handle::before { font-size: 1.3em; content: '\e81d'; } } .tlv-collapsed { .icon.tlv-collapse-handle::before { content: '\e820'; } } /** BEGIN of breadcrumb **/ .breadcrumb { list-style: none; overflow: hidden; padding: 0; // breadcrumb badges .badges { display: inline-block; padding: 0 0 0 0.5em; .badge { line-height: 1.25em; font-size: 0.8em; border: 1px solid @white; margin: -0.25em 1px 0 0; } } } .breadcrumb:after { content: ''; display: block; clear: both; } .breadcrumb li { float: left; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; } .breadcrumb li a { color: @text-color; margin: 0; font-size: 1.2em; text-decoration: none; padding-left: 2em; line-height: 2em; background: @gray-light; position: relative; display: block; float: left; &:focus { outline: none; } } .breadcrumb li a:before, .breadcrumb li a:after { content: " "; display: block; width: 0; height: 0; border-top: 1.3em solid transparent; border-bottom: 1.2em solid transparent; position: absolute; margin-top: -1.2em; top: 50%; left: 100%; } .breadcrumb li a:before { border-left: 1.2em solid @gray-lightest; margin-left: 1px; z-index: 1; } .breadcrumb li a:after { border-left: 1.2em solid @gray-light; z-index: 2; } .breadcrumb li:first-child a { padding-left: 1em; padding-right: 0.5em; } .breadcrumb li:not(:last-child) a:hover { background-color: @gray-lighter; } .breadcrumb li:not(:last-child) a:hover:after { border-left-color: @gray-lighter; } .breadcrumb li a:focus { text-decoration: underline; } #layout.twocols, #layout.layout-minimal, div.compact { .breadcrumb { font-size: 0.833em; } } /** END of breadcrumb **/ .action-links { .action-link { margin-right: 1em; } } .warning-note { padding: 0.5em; border-radius: 0.5em; background: fade(@tlv-color-warning-bg, 40%); color: @text-color; } .CodeMirror { min-height: 60em; width: 100%; margin-bottom: 1em; border: 1px solid @gray-light; font-family: inherit; pre { font-family: @font-family-fixed; font-size: 1.2em; } } div[href].action.active { border-left-color: @icinga-blue; } div[href].action:hover { cursor: pointer; a[href]:first-of-type { text-decoration: underline; } } icingaweb2-module-toplevelview-1.0.0/public/css/vendor/000077500000000000000000000000001473125420300230745ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/css/vendor/codemirror/000077500000000000000000000000001473125420300252415ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/css/vendor/codemirror/addon/000077500000000000000000000000001473125420300263265ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/css/vendor/codemirror/addon/dialog/000077500000000000000000000000001473125420300275655ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/css/vendor/codemirror/addon/dialog/dialog.css000066400000000000000000000007731473125420300315450ustar00rootroot00000000000000.CodeMirror-dialog { position: absolute; left: 0; right: 0; background: inherit; z-index: 15; padding: .1em .8em; overflow: hidden; color: inherit; } .CodeMirror-dialog-top { border-bottom: 1px solid #eee; top: 0; } .CodeMirror-dialog-bottom { border-top: 1px solid #eee; bottom: 0; } .CodeMirror-dialog input { border: none; outline: none; background: transparent; width: 20em; color: inherit; font-family: monospace; } .CodeMirror-dialog button { font-size: 70%; } icingaweb2-module-toplevelview-1.0.0/public/css/vendor/codemirror/addon/fold/000077500000000000000000000000001473125420300272525ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/css/vendor/codemirror/addon/fold/foldgutter.css000066400000000000000000000006631473125420300321500ustar00rootroot00000000000000.CodeMirror-foldmarker { color: blue; text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px; font-family: arial; line-height: .3; cursor: pointer; } .CodeMirror-foldgutter { width: .7em; } .CodeMirror-foldgutter-open, .CodeMirror-foldgutter-folded { cursor: pointer; } .CodeMirror-foldgutter-open:after { content: "\25BE"; } .CodeMirror-foldgutter-folded:after { content: "\25B8"; } icingaweb2-module-toplevelview-1.0.0/public/css/vendor/codemirror/addon/search/000077500000000000000000000000001473125420300275735ustar00rootroot00000000000000matchesonscrollbar.css000066400000000000000000000002741473125420300341160ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/css/vendor/codemirror/addon/search.CodeMirror-search-match { background: gold; border-top: 1px solid orange; border-bottom: 1px solid orange; -moz-box-sizing: border-box; box-sizing: border-box; opacity: .5; } icingaweb2-module-toplevelview-1.0.0/public/css/vendor/codemirror/codemirror.css000066400000000000000000000201171473125420300301210ustar00rootroot00000000000000/* BASICS */ .CodeMirror { /* Set height, width, borders, and global font properties here */ font-family: monospace; height: 300px; color: black; direction: ltr; } /* PADDING */ .CodeMirror-lines { padding: 4px 0; /* Vertical padding around content */ } .CodeMirror pre { padding: 0 4px; /* Horizontal padding of content */ } .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { background-color: white; /* The little square between H and V scrollbars */ } /* GUTTER */ .CodeMirror-gutters { border-right: 1px solid #ddd; background-color: #f7f7f7; white-space: nowrap; } .CodeMirror-linenumbers {} .CodeMirror-linenumber { padding: 0 3px 0 5px; min-width: 20px; text-align: right; color: #999; white-space: nowrap; } .CodeMirror-guttermarker { color: black; } .CodeMirror-guttermarker-subtle { color: #999; } /* CURSOR */ .CodeMirror-cursor { border-left: 1px solid black; border-right: none; width: 0; } /* Shown when moving in bi-directional text */ .CodeMirror div.CodeMirror-secondarycursor { border-left: 1px solid silver; } .cm-fat-cursor .CodeMirror-cursor { width: auto; border: 0 !important; background: #7e7; } .cm-fat-cursor div.CodeMirror-cursors { z-index: 1; } .cm-animate-fat-cursor { width: auto; border: 0; -webkit-animation: blink 1.06s steps(1) infinite; -moz-animation: blink 1.06s steps(1) infinite; animation: blink 1.06s steps(1) infinite; background-color: #7e7; } @-moz-keyframes blink { 0% {} 50% { background-color: transparent; } 100% {} } @-webkit-keyframes blink { 0% {} 50% { background-color: transparent; } 100% {} } @keyframes blink { 0% {} 50% { background-color: transparent; } 100% {} } /* Can style cursor different in overwrite (non-insert) mode */ .CodeMirror-overwrite .CodeMirror-cursor {} .cm-tab { display: inline-block; text-decoration: inherit; } .CodeMirror-rulers { position: absolute; left: 0; right: 0; top: -50px; bottom: -20px; overflow: hidden; } .CodeMirror-ruler { border-left: 1px solid #ccc; top: 0; bottom: 0; position: absolute; } /* DEFAULT THEME */ .cm-s-default .cm-header {color: blue;} .cm-s-default .cm-quote {color: #090;} .cm-negative {color: #d44;} .cm-positive {color: #292;} .cm-header, .cm-strong {font-weight: bold;} .cm-em {font-style: italic;} .cm-link {text-decoration: underline;} .cm-strikethrough {text-decoration: line-through;} .cm-s-default .cm-keyword {color: #708;} .cm-s-default .cm-atom {color: #219;} .cm-s-default .cm-number {color: #164;} .cm-s-default .cm-def {color: #00f;} .cm-s-default .cm-variable, .cm-s-default .cm-punctuation, .cm-s-default .cm-property, .cm-s-default .cm-operator {} .cm-s-default .cm-variable-2 {color: #05a;} .cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;} .cm-s-default .cm-comment {color: #a50;} .cm-s-default .cm-string {color: #a11;} .cm-s-default .cm-string-2 {color: #f50;} .cm-s-default .cm-meta {color: #555;} .cm-s-default .cm-qualifier {color: #555;} .cm-s-default .cm-builtin {color: #30a;} .cm-s-default .cm-bracket {color: #997;} .cm-s-default .cm-tag {color: #170;} .cm-s-default .cm-attribute {color: #00c;} .cm-s-default .cm-hr {color: #999;} .cm-s-default .cm-link {color: #00c;} .cm-s-default .cm-error {color: #f00;} .cm-invalidchar {color: #f00;} .CodeMirror-composing { border-bottom: 2px solid; } /* Default styles for common addons */ div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } .CodeMirror-activeline-background {background: #e8f2ff;} /* STOP */ /* The rest of this file contains styles related to the mechanics of the editor. You probably shouldn't touch them. */ .CodeMirror { position: relative; overflow: hidden; background: white; } .CodeMirror-scroll { overflow: scroll !important; /* Things will break if this is overridden */ /* 30px is the magic margin used to hide the element's real scrollbars */ /* See overflow: hidden in .CodeMirror */ margin-bottom: -30px; margin-right: -30px; padding-bottom: 30px; height: 100%; outline: none; /* Prevent dragging from highlighting the element */ position: relative; } .CodeMirror-sizer { position: relative; border-right: 30px solid transparent; } /* The fake, visible scrollbars. Used to force redraw during scrolling before actual scrolling happens, thus preventing shaking and flickering artifacts. */ .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { position: absolute; z-index: 6; display: none; } .CodeMirror-vscrollbar { right: 0; top: 0; overflow-x: hidden; overflow-y: scroll; } .CodeMirror-hscrollbar { bottom: 0; left: 0; overflow-y: hidden; overflow-x: scroll; } .CodeMirror-scrollbar-filler { right: 0; bottom: 0; } .CodeMirror-gutter-filler { left: 0; bottom: 0; } .CodeMirror-gutters { position: absolute; left: 0; top: 0; min-height: 100%; z-index: 3; } .CodeMirror-gutter { white-space: normal; height: 100%; display: inline-block; vertical-align: top; margin-bottom: -30px; } .CodeMirror-gutter-wrapper { position: absolute; z-index: 4; background: none !important; border: none !important; } .CodeMirror-gutter-background { position: absolute; top: 0; bottom: 0; z-index: 4; } .CodeMirror-gutter-elt { position: absolute; cursor: default; z-index: 4; } .CodeMirror-gutter-wrapper ::selection { background-color: transparent } .CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent } .CodeMirror-lines { cursor: text; min-height: 1px; /* prevents collapsing before first draw */ } .CodeMirror pre { /* Reset some styles that the rest of the page might have set */ -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; border-width: 0; background: transparent; font-family: inherit; font-size: inherit; margin: 0; white-space: pre; word-wrap: normal; line-height: inherit; color: inherit; z-index: 2; position: relative; overflow: visible; -webkit-tap-highlight-color: transparent; -webkit-font-variant-ligatures: contextual; font-variant-ligatures: contextual; } .CodeMirror-wrap pre { word-wrap: break-word; white-space: pre-wrap; word-break: normal; } .CodeMirror-linebackground { position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 0; } .CodeMirror-linewidget { position: relative; z-index: 2; overflow: auto; } .CodeMirror-widget {} .CodeMirror-rtl pre { direction: rtl; } .CodeMirror-code { outline: none; } /* Force content-box sizing for the elements where we expect it */ .CodeMirror-scroll, .CodeMirror-sizer, .CodeMirror-gutter, .CodeMirror-gutters, .CodeMirror-linenumber { -moz-box-sizing: content-box; box-sizing: content-box; } .CodeMirror-measure { position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden; } .CodeMirror-cursor { position: absolute; pointer-events: none; } .CodeMirror-measure pre { position: static; } div.CodeMirror-cursors { visibility: hidden; position: relative; z-index: 3; } div.CodeMirror-dragcursors { visibility: visible; } .CodeMirror-focused div.CodeMirror-cursors { visibility: visible; } .CodeMirror-selected { background: #d9d9d9; } .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } .CodeMirror-crosshair { cursor: crosshair; } .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } .cm-searching { background-color: #ffa; background-color: rgba(255, 255, 0, .4); } /* Used to force a border model for a node */ .cm-force-border { padding-right: .1px; } @media print { /* Hide the cursor when printing */ .CodeMirror div.CodeMirror-cursors { visibility: hidden; } } /* See issue #2901 */ .cm-tab-wrap-hack:after { content: ''; } /* Help users use markselection to safely style text background */ span.CodeMirror-selectedtext { background: none; } icingaweb2-module-toplevelview-1.0.0/public/js/000077500000000000000000000000001473125420300214235ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/js/module.js000066400000000000000000000062711473125420300232540ustar00rootroot00000000000000;(function (Icinga) { 'use strict'; var Toplevelview = function (module) { this.module = module; this.initialize(); }; Toplevelview.prototype = { initialize: function () { this.module.on('click', '.tlv-view-tree .tlv-tree-node', this.processTreeNodeClick); this.module.on('click', 'div[href].action', this.buttonClick, this); this.module.on('click', '.btn-remove', this.onRemoveClick, this); this.module.on('rendered', this.rendered); }, /** * rendered adds the CodeMirror editor to the designated div */ rendered: function (ev) { this.collapseOnLoad(ev); var $container = $(ev.currentTarget); $container.find('.codemirror').each(function (i, el) { var mode = el.getAttribute('data-codemirror-mode'); var editor = CodeMirror.fromTextArea(el, { lineNumbers: true, mode: mode, foldGutter: true, gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"] }); // avoid entering tab chars editor.setOption('extraKeys', { Tab: function(cm) { var spaces = new Array(cm.getOption('indentUnit') + 1).join(' '); cm.replaceSelection(spaces); }, 'Ctrl-F': 'findPersistent' }); }); }, /** * processTreeNodeClick toggles the collapsed status of the tree nodes */ processTreeNodeClick: function (event) { event.stopPropagation(); var $el = $(event.currentTarget); var $parent = $el.parents('.tlv-tree-node'); var $all = $el.find('.tlv-tree-node'); if (($parent.length === 0 && $all.hasClass('tlv-collapsed')) || $el.hasClass('tlv-collapsed')) { $el.removeClass('tlv-collapsed'); $all.removeClass('tlv-collapsed'); } else { $el.addClass('tlv-collapsed'); $all.addClass('tlv-collapsed'); } }, /** * collapseOnLoad sets all OK nodes to collapsed, * because these are not as interesting. */ collapseOnLoad: function (event) { var $el = $(event.currentTarget); $el.find('.tlv-view-tree .tlv-tree-node.tlv-collapsible.ok').addClass('tlv-collapsed'); }, /** * onRemoveClick shows a Browser confirmation windows. */ onRemoveClick: function (event) { event.stopPropagation(); let target = event.currentTarget; const confirmMsg = target.getAttribute('data-confirmation'); return confirm(confirmMsg); }, buttonClick: function (event) { event.stopPropagation(); var $el = $(event.currentTarget); var $links = $el.find('a[href]'); if ($links.length > 0) { $links[0].click(); } } }; Icinga.availableModules.toplevelview = Toplevelview; }(Icinga)); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/000077500000000000000000000000001473125420300227205ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/000077500000000000000000000000001473125420300250655ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/LICENSE000066400000000000000000000021231473125420300260700ustar00rootroot00000000000000MIT License Copyright (C) 2017 by Marijn Haverbeke and others Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/SOURCE000066400000000000000000000000511473125420300260040ustar00rootroot00000000000000https://github.com/codemirror/codemirror icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/VERSION000066400000000000000000000000101473125420300261240ustar00rootroot000000000000005.65.16 icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/000077500000000000000000000000001473125420300261525ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/dialog/000077500000000000000000000000001473125420300274115ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/dialog/dialog.js000066400000000000000000000122041473125420300312050ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE // Open simple dialogs on top of an editor. Relies on dialog.css. (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { function dialogDiv(cm, template, bottom) { var wrap = cm.getWrapperElement(); var dialog; dialog = wrap.appendChild(document.createElement("div")); if (bottom) dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom"; else dialog.className = "CodeMirror-dialog CodeMirror-dialog-top"; if (typeof template == "string") { dialog.innerHTML = template; } else { // Assuming it's a detached DOM element. dialog.appendChild(template); } CodeMirror.addClass(wrap, 'dialog-opened'); return dialog; } function closeNotification(cm, newVal) { if (cm.state.currentNotificationClose) cm.state.currentNotificationClose(); cm.state.currentNotificationClose = newVal; } CodeMirror.defineExtension("openDialog", function(template, callback, options) { if (!options) options = {}; closeNotification(this, null); var dialog = dialogDiv(this, template, options.bottom); var closed = false, me = this; function close(newVal) { if (typeof newVal == 'string') { inp.value = newVal; } else { if (closed) return; closed = true; CodeMirror.rmClass(dialog.parentNode, 'dialog-opened'); dialog.parentNode.removeChild(dialog); me.focus(); if (options.onClose) options.onClose(dialog); } } var inp = dialog.getElementsByTagName("input")[0], button; if (inp) { inp.focus(); if (options.value) { inp.value = options.value; if (options.selectValueOnOpen !== false) { inp.select(); } } if (options.onInput) CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); if (options.onKeyUp) CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); CodeMirror.on(inp, "keydown", function(e) { if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { inp.blur(); CodeMirror.e_stop(e); close(); } if (e.keyCode == 13) callback(inp.value, e); }); if (options.closeOnBlur !== false) CodeMirror.on(dialog, "focusout", function (evt) { if (evt.relatedTarget !== null) close(); }); } else if (button = dialog.getElementsByTagName("button")[0]) { CodeMirror.on(button, "click", function() { close(); me.focus(); }); if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); button.focus(); } return close; }); CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) { closeNotification(this, null); var dialog = dialogDiv(this, template, options && options.bottom); var buttons = dialog.getElementsByTagName("button"); var closed = false, me = this, blurring = 1; function close() { if (closed) return; closed = true; CodeMirror.rmClass(dialog.parentNode, 'dialog-opened'); dialog.parentNode.removeChild(dialog); me.focus(); } buttons[0].focus(); for (var i = 0; i < buttons.length; ++i) { var b = buttons[i]; (function(callback) { CodeMirror.on(b, "click", function(e) { CodeMirror.e_preventDefault(e); close(); if (callback) callback(me); }); })(callbacks[i]); CodeMirror.on(b, "blur", function() { --blurring; setTimeout(function() { if (blurring <= 0) close(); }, 200); }); CodeMirror.on(b, "focus", function() { ++blurring; }); } }); /* * openNotification * Opens a notification, that can be closed with an optional timer * (default 5000ms timer) and always closes on click. * * If a notification is opened while another is opened, it will close the * currently opened one and open the new one immediately. */ CodeMirror.defineExtension("openNotification", function(template, options) { closeNotification(this, close); var dialog = dialogDiv(this, template, options && options.bottom); var closed = false, doneTimer; var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; function close() { if (closed) return; closed = true; clearTimeout(doneTimer); CodeMirror.rmClass(dialog.parentNode, 'dialog-opened'); dialog.parentNode.removeChild(dialog); } CodeMirror.on(dialog, 'click', function(e) { CodeMirror.e_preventDefault(e); close(); }); if (duration) doneTimer = setTimeout(close, duration); return close; }); }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/fold/000077500000000000000000000000001473125420300270765ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/fold/brace-fold.js000066400000000000000000000105731473125420300314400ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; function bracketFolding(pairs) { return function(cm, start) { var line = start.line, lineText = cm.getLine(line); function findOpening(pair) { var tokenType; for (var at = start.ch, pass = 0;;) { var found = at <= 0 ? -1 : lineText.lastIndexOf(pair[0], at - 1); if (found == -1) { if (pass == 1) break; pass = 1; at = lineText.length; continue; } if (pass == 1 && found < start.ch) break; tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1)); if (!/^(comment|string)/.test(tokenType)) return {ch: found + 1, tokenType: tokenType, pair: pair}; at = found - 1; } } function findRange(found) { var count = 1, lastLine = cm.lastLine(), end, startCh = found.ch, endCh outer: for (var i = line; i <= lastLine; ++i) { var text = cm.getLine(i), pos = i == line ? startCh : 0; for (;;) { var nextOpen = text.indexOf(found.pair[0], pos), nextClose = text.indexOf(found.pair[1], pos); if (nextOpen < 0) nextOpen = text.length; if (nextClose < 0) nextClose = text.length; pos = Math.min(nextOpen, nextClose); if (pos == text.length) break; if (cm.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == found.tokenType) { if (pos == nextOpen) ++count; else if (!--count) { end = i; endCh = pos; break outer; } } ++pos; } } if (end == null || line == end) return null return {from: CodeMirror.Pos(line, startCh), to: CodeMirror.Pos(end, endCh)}; } var found = [] for (var i = 0; i < pairs.length; i++) { var open = findOpening(pairs[i]) if (open) found.push(open) } found.sort(function(a, b) { return a.ch - b.ch }) for (var i = 0; i < found.length; i++) { var range = findRange(found[i]) if (range) return range } return null } } CodeMirror.registerHelper("fold", "brace", bracketFolding([["{", "}"], ["[", "]"]])); CodeMirror.registerHelper("fold", "brace-paren", bracketFolding([["{", "}"], ["[", "]"], ["(", ")"]])); CodeMirror.registerHelper("fold", "import", function(cm, start) { function hasImport(line) { if (line < cm.firstLine() || line > cm.lastLine()) return null; var start = cm.getTokenAt(CodeMirror.Pos(line, 1)); if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1)); if (start.type != "keyword" || start.string != "import") return null; // Now find closing semicolon, return its position for (var i = line, e = Math.min(cm.lastLine(), line + 10); i <= e; ++i) { var text = cm.getLine(i), semi = text.indexOf(";"); if (semi != -1) return {startCh: start.end, end: CodeMirror.Pos(i, semi)}; } } var startLine = start.line, has = hasImport(startLine), prev; if (!has || hasImport(startLine - 1) || ((prev = hasImport(startLine - 2)) && prev.end.line == startLine - 1)) return null; for (var end = has.end;;) { var next = hasImport(end.line + 1); if (next == null) break; end = next.end; } return {from: cm.clipPos(CodeMirror.Pos(startLine, has.startCh + 1)), to: end}; }); CodeMirror.registerHelper("fold", "include", function(cm, start) { function hasInclude(line) { if (line < cm.firstLine() || line > cm.lastLine()) return null; var start = cm.getTokenAt(CodeMirror.Pos(line, 1)); if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1)); if (start.type == "meta" && start.string.slice(0, 8) == "#include") return start.start + 8; } var startLine = start.line, has = hasInclude(startLine); if (has == null || hasInclude(startLine - 1) != null) return null; for (var end = startLine;;) { var next = hasInclude(end + 1); if (next == null) break; ++end; } return {from: CodeMirror.Pos(startLine, has + 1), to: cm.clipPos(CodeMirror.Pos(end))}; }); }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/fold/comment-fold.js000066400000000000000000000041641473125420300320250ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; CodeMirror.registerGlobalHelper("fold", "comment", function(mode) { return mode.blockCommentStart && mode.blockCommentEnd; }, function(cm, start) { var mode = cm.getModeAt(start), startToken = mode.blockCommentStart, endToken = mode.blockCommentEnd; if (!startToken || !endToken) return; var line = start.line, lineText = cm.getLine(line); var startCh; for (var at = start.ch, pass = 0;;) { var found = at <= 0 ? -1 : lineText.lastIndexOf(startToken, at - 1); if (found == -1) { if (pass == 1) return; pass = 1; at = lineText.length; continue; } if (pass == 1 && found < start.ch) return; if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1))) && (found == 0 || lineText.slice(found - endToken.length, found) == endToken || !/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found))))) { startCh = found + startToken.length; break; } at = found - 1; } var depth = 1, lastLine = cm.lastLine(), end, endCh; outer: for (var i = line; i <= lastLine; ++i) { var text = cm.getLine(i), pos = i == line ? startCh : 0; for (;;) { var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos); if (nextOpen < 0) nextOpen = text.length; if (nextClose < 0) nextClose = text.length; pos = Math.min(nextOpen, nextClose); if (pos == text.length) break; if (pos == nextOpen) ++depth; else if (!--depth) { end = i; endCh = pos; break outer; } ++pos; } } if (end == null || line == end && endCh == startCh) return; return {from: CodeMirror.Pos(line, startCh), to: CodeMirror.Pos(end, endCh)}; }); }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/fold/foldcode.js000066400000000000000000000115711473125420300312200ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; function doFold(cm, pos, options, force) { if (options && options.call) { var finder = options; options = null; } else { var finder = getOption(cm, options, "rangeFinder"); } if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0); var minSize = getOption(cm, options, "minFoldSize"); function getRange(allowFolded) { var range = finder(cm, pos); if (!range || range.to.line - range.from.line < minSize) return null; if (force === "fold") return range; var marks = cm.findMarksAt(range.from); for (var i = 0; i < marks.length; ++i) { if (marks[i].__isFold) { if (!allowFolded) return null; range.cleared = true; marks[i].clear(); } } return range; } var range = getRange(true); if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) { pos = CodeMirror.Pos(pos.line - 1, 0); range = getRange(false); } if (!range || range.cleared || force === "unfold") return; var myWidget = makeWidget(cm, options, range); CodeMirror.on(myWidget, "mousedown", function(e) { myRange.clear(); CodeMirror.e_preventDefault(e); }); var myRange = cm.markText(range.from, range.to, { replacedWith: myWidget, clearOnEnter: getOption(cm, options, "clearOnEnter"), __isFold: true }); myRange.on("clear", function(from, to) { CodeMirror.signal(cm, "unfold", cm, from, to); }); CodeMirror.signal(cm, "fold", cm, range.from, range.to); } function makeWidget(cm, options, range) { var widget = getOption(cm, options, "widget"); if (typeof widget == "function") { widget = widget(range.from, range.to); } if (typeof widget == "string") { var text = document.createTextNode(widget); widget = document.createElement("span"); widget.appendChild(text); widget.className = "CodeMirror-foldmarker"; } else if (widget) { widget = widget.cloneNode(true) } return widget; } // Clumsy backwards-compatible interface CodeMirror.newFoldFunction = function(rangeFinder, widget) { return function(cm, pos) { doFold(cm, pos, {rangeFinder: rangeFinder, widget: widget}); }; }; // New-style interface CodeMirror.defineExtension("foldCode", function(pos, options, force) { doFold(this, pos, options, force); }); CodeMirror.defineExtension("isFolded", function(pos) { var marks = this.findMarksAt(pos); for (var i = 0; i < marks.length; ++i) if (marks[i].__isFold) return true; }); CodeMirror.commands.toggleFold = function(cm) { cm.foldCode(cm.getCursor()); }; CodeMirror.commands.fold = function(cm) { cm.foldCode(cm.getCursor(), null, "fold"); }; CodeMirror.commands.unfold = function(cm) { cm.foldCode(cm.getCursor(), { scanUp: false }, "unfold"); }; CodeMirror.commands.foldAll = function(cm) { cm.operation(function() { for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++) cm.foldCode(CodeMirror.Pos(i, 0), { scanUp: false }, "fold"); }); }; CodeMirror.commands.unfoldAll = function(cm) { cm.operation(function() { for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++) cm.foldCode(CodeMirror.Pos(i, 0), { scanUp: false }, "unfold"); }); }; CodeMirror.registerHelper("fold", "combine", function() { var funcs = Array.prototype.slice.call(arguments, 0); return function(cm, start) { for (var i = 0; i < funcs.length; ++i) { var found = funcs[i](cm, start); if (found) return found; } }; }); CodeMirror.registerHelper("fold", "auto", function(cm, start) { var helpers = cm.getHelpers(start, "fold"); for (var i = 0; i < helpers.length; i++) { var cur = helpers[i](cm, start); if (cur) return cur; } }); var defaultOptions = { rangeFinder: CodeMirror.fold.auto, widget: "\u2194", minFoldSize: 0, scanUp: false, clearOnEnter: true }; CodeMirror.defineOption("foldOptions", null); function getOption(cm, options, name) { if (options && options[name] !== undefined) return options[name]; var editorOptions = cm.options.foldOptions; if (editorOptions && editorOptions[name] !== undefined) return editorOptions[name]; return defaultOptions[name]; } CodeMirror.defineExtension("foldOption", function(options, name) { return getOption(this, options, name); }); }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/fold/foldgutter.js000066400000000000000000000126431473125420300316210ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror"), require("./foldcode")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror", "./foldcode"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; CodeMirror.defineOption("foldGutter", false, function(cm, val, old) { if (old && old != CodeMirror.Init) { cm.clearGutter(cm.state.foldGutter.options.gutter); cm.state.foldGutter = null; cm.off("gutterClick", onGutterClick); cm.off("changes", onChange); cm.off("viewportChange", onViewportChange); cm.off("fold", onFold); cm.off("unfold", onFold); cm.off("swapDoc", onChange); cm.off("optionChange", optionChange); } if (val) { cm.state.foldGutter = new State(parseOptions(val)); updateInViewport(cm); cm.on("gutterClick", onGutterClick); cm.on("changes", onChange); cm.on("viewportChange", onViewportChange); cm.on("fold", onFold); cm.on("unfold", onFold); cm.on("swapDoc", onChange); cm.on("optionChange", optionChange); } }); var Pos = CodeMirror.Pos; function State(options) { this.options = options; this.from = this.to = 0; } function parseOptions(opts) { if (opts === true) opts = {}; if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter"; if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open"; if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded"; return opts; } function isFolded(cm, line) { var marks = cm.findMarks(Pos(line, 0), Pos(line + 1, 0)); for (var i = 0; i < marks.length; ++i) { if (marks[i].__isFold) { var fromPos = marks[i].find(-1); if (fromPos && fromPos.line === line) return marks[i]; } } } function marker(spec) { if (typeof spec == "string") { var elt = document.createElement("div"); elt.className = spec + " CodeMirror-guttermarker-subtle"; return elt; } else { return spec.cloneNode(true); } } function updateFoldInfo(cm, from, to) { var opts = cm.state.foldGutter.options, cur = from - 1; var minSize = cm.foldOption(opts, "minFoldSize"); var func = cm.foldOption(opts, "rangeFinder"); // we can reuse the built-in indicator element if its className matches the new state var clsFolded = typeof opts.indicatorFolded == "string" && classTest(opts.indicatorFolded); var clsOpen = typeof opts.indicatorOpen == "string" && classTest(opts.indicatorOpen); cm.eachLine(from, to, function(line) { ++cur; var mark = null; var old = line.gutterMarkers; if (old) old = old[opts.gutter]; if (isFolded(cm, cur)) { if (clsFolded && old && clsFolded.test(old.className)) return; mark = marker(opts.indicatorFolded); } else { var pos = Pos(cur, 0); var range = func && func(cm, pos); if (range && range.to.line - range.from.line >= minSize) { if (clsOpen && old && clsOpen.test(old.className)) return; mark = marker(opts.indicatorOpen); } } if (!mark && !old) return; cm.setGutterMarker(line, opts.gutter, mark); }); } // copied from CodeMirror/src/util/dom.js function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") } function updateInViewport(cm) { var vp = cm.getViewport(), state = cm.state.foldGutter; if (!state) return; cm.operation(function() { updateFoldInfo(cm, vp.from, vp.to); }); state.from = vp.from; state.to = vp.to; } function onGutterClick(cm, line, gutter) { var state = cm.state.foldGutter; if (!state) return; var opts = state.options; if (gutter != opts.gutter) return; var folded = isFolded(cm, line); if (folded) folded.clear(); else cm.foldCode(Pos(line, 0), opts); } function optionChange(cm, option) { if (option == "mode") onChange(cm) } function onChange(cm) { var state = cm.state.foldGutter; if (!state) return; var opts = state.options; state.from = state.to = 0; clearTimeout(state.changeUpdate); state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600); } function onViewportChange(cm) { var state = cm.state.foldGutter; if (!state) return; var opts = state.options; clearTimeout(state.changeUpdate); state.changeUpdate = setTimeout(function() { var vp = cm.getViewport(); if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) { updateInViewport(cm); } else { cm.operation(function() { if (vp.from < state.from) { updateFoldInfo(cm, vp.from, state.from); state.from = vp.from; } if (vp.to > state.to) { updateFoldInfo(cm, state.to, vp.to); state.to = vp.to; } }); } }, opts.updateViewportTimeSpan || 400); } function onFold(cm, from) { var state = cm.state.foldGutter; if (!state) return; var line = from.line; if (line >= state.from && line < state.to) updateFoldInfo(cm, line, line + 1); } }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/fold/indent-fold.js000066400000000000000000000032141473125420300316370ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; function lineIndent(cm, lineNo) { var text = cm.getLine(lineNo) var spaceTo = text.search(/\S/) if (spaceTo == -1 || /\bcomment\b/.test(cm.getTokenTypeAt(CodeMirror.Pos(lineNo, spaceTo + 1)))) return -1 return CodeMirror.countColumn(text, null, cm.getOption("tabSize")) } CodeMirror.registerHelper("fold", "indent", function(cm, start) { var myIndent = lineIndent(cm, start.line) if (myIndent < 0) return var lastLineInFold = null // Go through lines until we find a line that definitely doesn't belong in // the block we're folding, or to the end. for (var i = start.line + 1, end = cm.lastLine(); i <= end; ++i) { var indent = lineIndent(cm, i) if (indent == -1) { } else if (indent > myIndent) { // Lines with a greater indent are considered part of the block. lastLineInFold = i; } else { // If this line has non-space, non-comment content, and is // indented less or equal to the start line, it is the start of // another block. break; } } if (lastLineInFold) return { from: CodeMirror.Pos(start.line, cm.getLine(start.line).length), to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length) }; }); }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/fold/markdown-fold.js000066400000000000000000000031101473125420300321730ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; CodeMirror.registerHelper("fold", "markdown", function(cm, start) { var maxDepth = 100; function isHeader(lineNo) { var tokentype = cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0)); return tokentype && /\bheader\b/.test(tokentype); } function headerLevel(lineNo, line, nextLine) { var match = line && line.match(/^#+/); if (match && isHeader(lineNo)) return match[0].length; match = nextLine && nextLine.match(/^[=\-]+\s*$/); if (match && isHeader(lineNo + 1)) return nextLine[0] == "=" ? 1 : 2; return maxDepth; } var firstLine = cm.getLine(start.line), nextLine = cm.getLine(start.line + 1); var level = headerLevel(start.line, firstLine, nextLine); if (level === maxDepth) return undefined; var lastLineNo = cm.lastLine(); var end = start.line, nextNextLine = cm.getLine(end + 2); while (end < lastLineNo) { if (headerLevel(end + 1, nextLine, nextNextLine) <= level) break; ++end; nextLine = nextNextLine; nextNextLine = cm.getLine(end + 2); } return { from: CodeMirror.Pos(start.line, firstLine.length), to: CodeMirror.Pos(end, cm.getLine(end).length) }; }); }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/fold/xml-fold.js000066400000000000000000000150561473125420300311650ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; var Pos = CodeMirror.Pos; function cmp(a, b) { return a.line - b.line || a.ch - b.ch; } var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD"; var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; var xmlTagStart = new RegExp("<(/?)([" + nameStartChar + "][" + nameChar + "]*)", "g"); function Iter(cm, line, ch, range) { this.line = line; this.ch = ch; this.cm = cm; this.text = cm.getLine(line); this.min = range ? Math.max(range.from, cm.firstLine()) : cm.firstLine(); this.max = range ? Math.min(range.to - 1, cm.lastLine()) : cm.lastLine(); } function tagAt(iter, ch) { var type = iter.cm.getTokenTypeAt(Pos(iter.line, ch)); return type && /\btag\b/.test(type); } function nextLine(iter) { if (iter.line >= iter.max) return; iter.ch = 0; iter.text = iter.cm.getLine(++iter.line); return true; } function prevLine(iter) { if (iter.line <= iter.min) return; iter.text = iter.cm.getLine(--iter.line); iter.ch = iter.text.length; return true; } function toTagEnd(iter) { for (;;) { var gt = iter.text.indexOf(">", iter.ch); if (gt == -1) { if (nextLine(iter)) continue; else return; } if (!tagAt(iter, gt + 1)) { iter.ch = gt + 1; continue; } var lastSlash = iter.text.lastIndexOf("/", gt); var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt)); iter.ch = gt + 1; return selfClose ? "selfClose" : "regular"; } } function toTagStart(iter) { for (;;) { var lt = iter.ch ? iter.text.lastIndexOf("<", iter.ch - 1) : -1; if (lt == -1) { if (prevLine(iter)) continue; else return; } if (!tagAt(iter, lt + 1)) { iter.ch = lt; continue; } xmlTagStart.lastIndex = lt; iter.ch = lt; var match = xmlTagStart.exec(iter.text); if (match && match.index == lt) return match; } } function toNextTag(iter) { for (;;) { xmlTagStart.lastIndex = iter.ch; var found = xmlTagStart.exec(iter.text); if (!found) { if (nextLine(iter)) continue; else return; } if (!tagAt(iter, found.index + 1)) { iter.ch = found.index + 1; continue; } iter.ch = found.index + found[0].length; return found; } } function toPrevTag(iter) { for (;;) { var gt = iter.ch ? iter.text.lastIndexOf(">", iter.ch - 1) : -1; if (gt == -1) { if (prevLine(iter)) continue; else return; } if (!tagAt(iter, gt + 1)) { iter.ch = gt; continue; } var lastSlash = iter.text.lastIndexOf("/", gt); var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt)); iter.ch = gt + 1; return selfClose ? "selfClose" : "regular"; } } function findMatchingClose(iter, tag) { var stack = []; for (;;) { var next = toNextTag(iter), end, startLine = iter.line, startCh = iter.ch - (next ? next[0].length : 0); if (!next || !(end = toTagEnd(iter))) return; if (end == "selfClose") continue; if (next[1]) { // closing tag for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == next[2]) { stack.length = i; break; } if (i < 0 && (!tag || tag == next[2])) return { tag: next[2], from: Pos(startLine, startCh), to: Pos(iter.line, iter.ch) }; } else { // opening tag stack.push(next[2]); } } } function findMatchingOpen(iter, tag) { var stack = []; for (;;) { var prev = toPrevTag(iter); if (!prev) return; if (prev == "selfClose") { toTagStart(iter); continue; } var endLine = iter.line, endCh = iter.ch; var start = toTagStart(iter); if (!start) return; if (start[1]) { // closing tag stack.push(start[2]); } else { // opening tag for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == start[2]) { stack.length = i; break; } if (i < 0 && (!tag || tag == start[2])) return { tag: start[2], from: Pos(iter.line, iter.ch), to: Pos(endLine, endCh) }; } } } CodeMirror.registerHelper("fold", "xml", function(cm, start) { var iter = new Iter(cm, start.line, 0); for (;;) { var openTag = toNextTag(iter) if (!openTag || iter.line != start.line) return var end = toTagEnd(iter) if (!end) return if (!openTag[1] && end != "selfClose") { var startPos = Pos(iter.line, iter.ch); var endPos = findMatchingClose(iter, openTag[2]); return endPos && cmp(endPos.from, startPos) > 0 ? {from: startPos, to: endPos.from} : null } } }); CodeMirror.findMatchingTag = function(cm, pos, range) { var iter = new Iter(cm, pos.line, pos.ch, range); if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return; var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch); var start = end && toTagStart(iter); if (!end || !start || cmp(iter, pos) > 0) return; var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]}; if (end == "selfClose") return {open: here, close: null, at: "open"}; if (start[1]) { // closing tag return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"}; } else { // opening tag iter = new Iter(cm, to.line, to.ch, range); return {open: here, close: findMatchingClose(iter, start[2]), at: "open"}; } }; CodeMirror.findEnclosingTag = function(cm, pos, range, tag) { var iter = new Iter(cm, pos.line, pos.ch, range); for (;;) { var open = findMatchingOpen(iter, tag); if (!open) break; var forward = new Iter(cm, pos.line, pos.ch, range); var close = findMatchingClose(forward, open.tag); if (close) return {open: open, close: close}; } }; // Used by addon/edit/closetag.js CodeMirror.scanForClosingTag = function(cm, pos, name, end) { var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null); return findMatchingClose(iter, name); }; }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/search/000077500000000000000000000000001473125420300274175ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/search/jump-to-line.js000066400000000000000000000041371473125420300323020ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE // Defines jumpToLine command. Uses dialog.js if present. (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror"), require("../dialog/dialog")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror", "../dialog/dialog"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; // default search panel location CodeMirror.defineOption("search", {bottom: false}); function dialog(cm, text, shortText, deflt, f) { if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true, bottom: cm.options.search.bottom}); else f(prompt(shortText, deflt)); } function getJumpDialog(cm) { return cm.phrase("Jump to line:") + ' ' + cm.phrase("(Use line:column or scroll% syntax)") + ''; } function interpretLine(cm, string) { var num = Number(string) if (/^[-+]/.test(string)) return cm.getCursor().line + num else return num - 1 } CodeMirror.commands.jumpToLine = function(cm) { var cur = cm.getCursor(); dialog(cm, getJumpDialog(cm), cm.phrase("Jump to line:"), (cur.line + 1) + ":" + cur.ch, function(posStr) { if (!posStr) return; var match; if (match = /^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(posStr)) { cm.setCursor(interpretLine(cm, match[1]), Number(match[2])) } else if (match = /^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(posStr)) { var line = Math.round(cm.lineCount() * Number(match[1]) / 100); if (/^[-+]/.test(match[1])) line = cur.line + line + 1; cm.setCursor(line - 1, cur.ch); } else if (match = /^\s*\:?\s*([\+\-]?\d+)\s*/.exec(posStr)) { cm.setCursor(interpretLine(cm, match[1]), cur.ch); } }); }; CodeMirror.keyMap["default"]["Alt-G"] = "jumpToLine"; }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/search/match-highlighter.js000066400000000000000000000141101473125420300333420ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE // Highlighting text that matches the selection // // Defines an option highlightSelectionMatches, which, when enabled, // will style strings that match the selection throughout the // document. // // The option can be set to true to simply enable it, or to a // {minChars, style, wordsOnly, showToken, delay} object to explicitly // configure it. minChars is the minimum amount of characters that should be // selected for the behavior to occur, and style is the token style to // apply to the matches. This will be prefixed by "cm-" to create an // actual CSS class name. If wordsOnly is enabled, the matches will be // highlighted only if the selected text is a word. showToken, when enabled, // will cause the current token to be highlighted when nothing is selected. // delay is used to specify how much time to wait, in milliseconds, before // highlighting the matches. If annotateScrollbar is enabled, the occurrences // will be highlighted on the scrollbar via the matchesonscrollbar addon. (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror"), require("./matchesonscrollbar")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror", "./matchesonscrollbar"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; var defaults = { style: "matchhighlight", minChars: 2, delay: 100, wordsOnly: false, annotateScrollbar: false, showToken: false, trim: true } function State(options) { this.options = {} for (var name in defaults) this.options[name] = (options && options.hasOwnProperty(name) ? options : defaults)[name] this.overlay = this.timeout = null; this.matchesonscroll = null; this.active = false; } CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) { if (old && old != CodeMirror.Init) { removeOverlay(cm); clearTimeout(cm.state.matchHighlighter.timeout); cm.state.matchHighlighter = null; cm.off("cursorActivity", cursorActivity); cm.off("focus", onFocus) } if (val) { var state = cm.state.matchHighlighter = new State(val); if (cm.hasFocus()) { state.active = true highlightMatches(cm) } else { cm.on("focus", onFocus) } cm.on("cursorActivity", cursorActivity); } }); function cursorActivity(cm) { var state = cm.state.matchHighlighter; if (state.active || cm.hasFocus()) scheduleHighlight(cm, state) } function onFocus(cm) { var state = cm.state.matchHighlighter if (!state.active) { state.active = true scheduleHighlight(cm, state) } } function scheduleHighlight(cm, state) { clearTimeout(state.timeout); state.timeout = setTimeout(function() {highlightMatches(cm);}, state.options.delay); } function addOverlay(cm, query, hasBoundary, style) { var state = cm.state.matchHighlighter; cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style)); if (state.options.annotateScrollbar && cm.showMatchesOnScrollbar) { var searchFor = hasBoundary ? new RegExp((/\w/.test(query.charAt(0)) ? "\\b" : "") + query.replace(/[\\\[.+*?(){|^$]/g, "\\$&") + (/\w/.test(query.charAt(query.length - 1)) ? "\\b" : "")) : query; state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, false, {className: "CodeMirror-selection-highlight-scrollbar"}); } } function removeOverlay(cm) { var state = cm.state.matchHighlighter; if (state.overlay) { cm.removeOverlay(state.overlay); state.overlay = null; if (state.matchesonscroll) { state.matchesonscroll.clear(); state.matchesonscroll = null; } } } function highlightMatches(cm) { cm.operation(function() { var state = cm.state.matchHighlighter; removeOverlay(cm); if (!cm.somethingSelected() && state.options.showToken) { var re = state.options.showToken === true ? /[\w$]/ : state.options.showToken; var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start; while (start && re.test(line.charAt(start - 1))) --start; while (end < line.length && re.test(line.charAt(end))) ++end; if (start < end) addOverlay(cm, line.slice(start, end), re, state.options.style); return; } var from = cm.getCursor("from"), to = cm.getCursor("to"); if (from.line != to.line) return; if (state.options.wordsOnly && !isWord(cm, from, to)) return; var selection = cm.getRange(from, to) if (state.options.trim) selection = selection.replace(/^\s+|\s+$/g, "") if (selection.length >= state.options.minChars) addOverlay(cm, selection, false, state.options.style); }); } function isWord(cm, from, to) { var str = cm.getRange(from, to); if (str.match(/^\w+$/) !== null) { if (from.ch > 0) { var pos = {line: from.line, ch: from.ch - 1}; var chr = cm.getRange(pos, from); if (chr.match(/\W/) === null) return false; } if (to.ch < cm.getLine(from.line).length) { var pos = {line: to.line, ch: to.ch + 1}; var chr = cm.getRange(to, pos); if (chr.match(/\W/) === null) return false; } return true; } else return false; } function boundariesAround(stream, re) { return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) && (stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos))); } function makeOverlay(query, hasBoundary, style) { return {token: function(stream) { if (stream.match(query) && (!hasBoundary || boundariesAround(stream, hasBoundary))) return style; stream.next(); stream.skipTo(query.charAt(0)) || stream.skipToEnd(); }}; } }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/search/matchesonscrollbar.js000066400000000000000000000074221473125420300336470ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror"), require("./searchcursor"), require("../scroll/annotatescrollbar")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror", "./searchcursor", "../scroll/annotatescrollbar"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, options) { if (typeof options == "string") options = {className: options}; if (!options) options = {}; return new SearchAnnotation(this, query, caseFold, options); }); function SearchAnnotation(cm, query, caseFold, options) { this.cm = cm; this.options = options; var annotateOptions = {listenForChanges: false}; for (var prop in options) annotateOptions[prop] = options[prop]; if (!annotateOptions.className) annotateOptions.className = "CodeMirror-search-match"; this.annotation = cm.annotateScrollbar(annotateOptions); this.query = query; this.caseFold = caseFold; this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1}; this.matches = []; this.update = null; this.findMatches(); this.annotation.update(this.matches); var self = this; cm.on("change", this.changeHandler = function(_cm, change) { self.onChange(change); }); } var MAX_MATCHES = 1000; SearchAnnotation.prototype.findMatches = function() { if (!this.gap) return; for (var i = 0; i < this.matches.length; i++) { var match = this.matches[i]; if (match.from.line >= this.gap.to) break; if (match.to.line >= this.gap.from) this.matches.splice(i--, 1); } var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), {caseFold: this.caseFold, multiline: this.options.multiline}); var maxMatches = this.options && this.options.maxMatches || MAX_MATCHES; while (cursor.findNext()) { var match = {from: cursor.from(), to: cursor.to()}; if (match.from.line >= this.gap.to) break; this.matches.splice(i++, 0, match); if (this.matches.length > maxMatches) break; } this.gap = null; }; function offsetLine(line, changeStart, sizeChange) { if (line <= changeStart) return line; return Math.max(changeStart, line + sizeChange); } SearchAnnotation.prototype.onChange = function(change) { var startLine = change.from.line; var endLine = CodeMirror.changeEnd(change).line; var sizeChange = endLine - change.to.line; if (this.gap) { this.gap.from = Math.min(offsetLine(this.gap.from, startLine, sizeChange), change.from.line); this.gap.to = Math.max(offsetLine(this.gap.to, startLine, sizeChange), change.from.line); } else { this.gap = {from: change.from.line, to: endLine + 1}; } if (sizeChange) for (var i = 0; i < this.matches.length; i++) { var match = this.matches[i]; var newFrom = offsetLine(match.from.line, startLine, sizeChange); if (newFrom != match.from.line) match.from = CodeMirror.Pos(newFrom, match.from.ch); var newTo = offsetLine(match.to.line, startLine, sizeChange); if (newTo != match.to.line) match.to = CodeMirror.Pos(newTo, match.to.ch); } clearTimeout(this.update); var self = this; this.update = setTimeout(function() { self.updateAfterChange(); }, 250); }; SearchAnnotation.prototype.updateAfterChange = function() { this.findMatches(); this.annotation.update(this.matches); }; SearchAnnotation.prototype.clear = function() { this.cm.off("change", this.changeHandler); this.annotation.clear(); }; }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/search/search.js000066400000000000000000000271271473125420300312330ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE // Define search commands. Depends on dialog.js or another // implementation of the openDialog method. // Replace works a little oddly -- it will do the replace on the next // Ctrl-G (or whatever is bound to findNext) press. You prevent a // replace by making sure the match is no longer selected when hitting // Ctrl-G. (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; // default search panel location CodeMirror.defineOption("search", {bottom: false}); function searchOverlay(query, caseInsensitive) { if (typeof query == "string") query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g"); else if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "gi" : "g"); return {token: function(stream) { query.lastIndex = stream.pos; var match = query.exec(stream.string); if (match && match.index == stream.pos) { stream.pos += match[0].length || 1; return "searching"; } else if (match) { stream.pos = match.index; } else { stream.skipToEnd(); } }}; } function SearchState() { this.posFrom = this.posTo = this.lastQuery = this.query = null; this.overlay = null; } function getSearchState(cm) { return cm.state.search || (cm.state.search = new SearchState()); } function queryCaseInsensitive(query) { return typeof query == "string" && query == query.toLowerCase(); } function getSearchCursor(cm, query, pos) { // Heuristic: if the query string is all lowercase, do a case insensitive search. return cm.getSearchCursor(query, pos, {caseFold: queryCaseInsensitive(query), multiline: true}); } function persistentDialog(cm, text, deflt, onEnter, onKeyDown) { cm.openDialog(text, onEnter, { value: deflt, selectValueOnOpen: true, closeOnEnter: false, onClose: function() { clearSearch(cm); }, onKeyDown: onKeyDown, bottom: cm.options.search.bottom }); } function dialog(cm, text, shortText, deflt, f) { if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true, bottom: cm.options.search.bottom}); else f(prompt(shortText, deflt)); } function confirmDialog(cm, text, shortText, fs) { if (cm.openConfirm) cm.openConfirm(text, fs); else if (confirm(shortText)) fs[0](); } function parseString(string) { return string.replace(/\\([nrt\\])/g, function(match, ch) { if (ch == "n") return "\n" if (ch == "r") return "\r" if (ch == "t") return "\t" if (ch == "\\") return "\\" return match }) } function parseQuery(query) { var isRE = query.match(/^\/(.*)\/([a-z]*)$/); if (isRE) { try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); } catch(e) {} // Not a regular expression after all, do a string search } else { query = parseString(query) } if (typeof query == "string" ? query == "" : query.test("")) query = /x^/; return query; } function startSearch(cm, state, query) { state.queryText = query; state.query = parseQuery(query); cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query)); state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query)); cm.addOverlay(state.overlay); if (cm.showMatchesOnScrollbar) { if (state.annotate) { state.annotate.clear(); state.annotate = null; } state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query)); } } function doSearch(cm, rev, persistent, immediate) { var state = getSearchState(cm); if (state.query) return findNext(cm, rev); var q = cm.getSelection() || state.lastQuery; if (q instanceof RegExp && q.source == "x^") q = null if (persistent && cm.openDialog) { var hiding = null var searchNext = function(query, event) { CodeMirror.e_stop(event); if (!query) return; if (query != state.queryText) { startSearch(cm, state, query); state.posFrom = state.posTo = cm.getCursor(); } if (hiding) hiding.style.opacity = 1 findNext(cm, event.shiftKey, function(_, to) { var dialog if (to.line < 3 && document.querySelector && (dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) && dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top) (hiding = dialog).style.opacity = .4 }) }; persistentDialog(cm, getQueryDialog(cm), q, searchNext, function(event, query) { var keyName = CodeMirror.keyName(event) var extra = cm.getOption('extraKeys'), cmd = (extra && extra[keyName]) || CodeMirror.keyMap[cm.getOption("keyMap")][keyName] if (cmd == "findNext" || cmd == "findPrev" || cmd == "findPersistentNext" || cmd == "findPersistentPrev") { CodeMirror.e_stop(event); startSearch(cm, getSearchState(cm), query); cm.execCommand(cmd); } else if (cmd == "find" || cmd == "findPersistent") { CodeMirror.e_stop(event); searchNext(query, event); } }); if (immediate && q) { startSearch(cm, state, q); findNext(cm, rev); } } else { dialog(cm, getQueryDialog(cm), "Search for:", q, function(query) { if (query && !state.query) cm.operation(function() { startSearch(cm, state, query); state.posFrom = state.posTo = cm.getCursor(); findNext(cm, rev); }); }); } } function findNext(cm, rev, callback) {cm.operation(function() { var state = getSearchState(cm); var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo); if (!cursor.find(rev)) { cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0)); if (!cursor.find(rev)) return; } cm.setSelection(cursor.from(), cursor.to()); cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20); state.posFrom = cursor.from(); state.posTo = cursor.to(); if (callback) callback(cursor.from(), cursor.to()) });} function clearSearch(cm) {cm.operation(function() { var state = getSearchState(cm); state.lastQuery = state.query; if (!state.query) return; state.query = state.queryText = null; cm.removeOverlay(state.overlay); if (state.annotate) { state.annotate.clear(); state.annotate = null; } });} function el(tag, attrs) { var element = tag ? document.createElement(tag) : document.createDocumentFragment(); for (var key in attrs) { element[key] = attrs[key]; } for (var i = 2; i < arguments.length; i++) { var child = arguments[i] element.appendChild(typeof child == "string" ? document.createTextNode(child) : child); } return element; } function getQueryDialog(cm) { var label = el("label", {className: "CodeMirror-search-label"}, cm.phrase("Search:"), el("input", {type: "text", "style": "width: 10em", className: "CodeMirror-search-field", id: "CodeMirror-search-field"})); label.setAttribute("for","CodeMirror-search-field"); return el("", null, label, " ", el("span", {style: "color: #666", className: "CodeMirror-search-hint"}, cm.phrase("(Use /re/ syntax for regexp search)"))); } function getReplaceQueryDialog(cm) { return el("", null, " ", el("input", {type: "text", "style": "width: 10em", className: "CodeMirror-search-field"}), " ", el("span", {style: "color: #666", className: "CodeMirror-search-hint"}, cm.phrase("(Use /re/ syntax for regexp search)"))); } function getReplacementQueryDialog(cm) { return el("", null, el("span", {className: "CodeMirror-search-label"}, cm.phrase("With:")), " ", el("input", {type: "text", "style": "width: 10em", className: "CodeMirror-search-field"})); } function getDoReplaceConfirm(cm) { return el("", null, el("span", {className: "CodeMirror-search-label"}, cm.phrase("Replace?")), " ", el("button", {}, cm.phrase("Yes")), " ", el("button", {}, cm.phrase("No")), " ", el("button", {}, cm.phrase("All")), " ", el("button", {}, cm.phrase("Stop"))); } function replaceAll(cm, query, text) { cm.operation(function() { for (var cursor = getSearchCursor(cm, query); cursor.findNext();) { if (typeof query != "string") { var match = cm.getRange(cursor.from(), cursor.to()).match(query); cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];})); } else cursor.replace(text); } }); } function replace(cm, all) { if (cm.getOption("readOnly")) return; var query = cm.getSelection() || getSearchState(cm).lastQuery; var dialogText = all ? cm.phrase("Replace all:") : cm.phrase("Replace:") var fragment = el("", null, el("span", {className: "CodeMirror-search-label"}, dialogText), getReplaceQueryDialog(cm)) dialog(cm, fragment, dialogText, query, function(query) { if (!query) return; query = parseQuery(query); dialog(cm, getReplacementQueryDialog(cm), cm.phrase("Replace with:"), "", function(text) { text = parseString(text) if (all) { replaceAll(cm, query, text) } else { clearSearch(cm); var cursor = getSearchCursor(cm, query, cm.getCursor("from")); var advance = function() { var start = cursor.from(), match; if (!(match = cursor.findNext())) { cursor = getSearchCursor(cm, query); if (!(match = cursor.findNext()) || (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return; } cm.setSelection(cursor.from(), cursor.to()); cm.scrollIntoView({from: cursor.from(), to: cursor.to()}); confirmDialog(cm, getDoReplaceConfirm(cm), cm.phrase("Replace?"), [function() {doReplace(match);}, advance, function() {replaceAll(cm, query, text)}]); }; var doReplace = function(match) { cursor.replace(typeof query == "string" ? text : text.replace(/\$(\d)/g, function(_, i) {return match[i];})); advance(); }; advance(); } }); }); } CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);}; CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);}; CodeMirror.commands.findPersistentNext = function(cm) {doSearch(cm, false, true, true);}; CodeMirror.commands.findPersistentPrev = function(cm) {doSearch(cm, true, true, true);}; CodeMirror.commands.findNext = doSearch; CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);}; CodeMirror.commands.clearSearch = clearSearch; CodeMirror.commands.replace = replace; CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);}; }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/addon/search/searchcursor.js000066400000000000000000000277121473125420300324710ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror")) else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror"], mod) else // Plain browser env mod(CodeMirror) })(function(CodeMirror) { "use strict" var Pos = CodeMirror.Pos function regexpFlags(regexp) { var flags = regexp.flags return flags != null ? flags : (regexp.ignoreCase ? "i" : "") + (regexp.global ? "g" : "") + (regexp.multiline ? "m" : "") } function ensureFlags(regexp, flags) { var current = regexpFlags(regexp), target = current for (var i = 0; i < flags.length; i++) if (target.indexOf(flags.charAt(i)) == -1) target += flags.charAt(i) return current == target ? regexp : new RegExp(regexp.source, target) } function maybeMultiline(regexp) { return /\\s|\\n|\n|\\W|\\D|\[\^/.test(regexp.source) } function searchRegexpForward(doc, regexp, start) { regexp = ensureFlags(regexp, "g") for (var line = start.line, ch = start.ch, last = doc.lastLine(); line <= last; line++, ch = 0) { regexp.lastIndex = ch var string = doc.getLine(line), match = regexp.exec(string) if (match) return {from: Pos(line, match.index), to: Pos(line, match.index + match[0].length), match: match} } } function searchRegexpForwardMultiline(doc, regexp, start) { if (!maybeMultiline(regexp)) return searchRegexpForward(doc, regexp, start) regexp = ensureFlags(regexp, "gm") var string, chunk = 1 for (var line = start.line, last = doc.lastLine(); line <= last;) { // This grows the search buffer in exponentially-sized chunks // between matches, so that nearby matches are fast and don't // require concatenating the whole document (in case we're // searching for something that has tons of matches), but at the // same time, the amount of retries is limited. for (var i = 0; i < chunk; i++) { if (line > last) break var curLine = doc.getLine(line++) string = string == null ? curLine : string + "\n" + curLine } chunk = chunk * 2 regexp.lastIndex = start.ch var match = regexp.exec(string) if (match) { var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n") var startLine = start.line + before.length - 1, startCh = before[before.length - 1].length return {from: Pos(startLine, startCh), to: Pos(startLine + inside.length - 1, inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length), match: match} } } } function lastMatchIn(string, regexp, endMargin) { var match, from = 0 while (from <= string.length) { regexp.lastIndex = from var newMatch = regexp.exec(string) if (!newMatch) break var end = newMatch.index + newMatch[0].length if (end > string.length - endMargin) break if (!match || end > match.index + match[0].length) match = newMatch from = newMatch.index + 1 } return match } function searchRegexpBackward(doc, regexp, start) { regexp = ensureFlags(regexp, "g") for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) { var string = doc.getLine(line) var match = lastMatchIn(string, regexp, ch < 0 ? 0 : string.length - ch) if (match) return {from: Pos(line, match.index), to: Pos(line, match.index + match[0].length), match: match} } } function searchRegexpBackwardMultiline(doc, regexp, start) { if (!maybeMultiline(regexp)) return searchRegexpBackward(doc, regexp, start) regexp = ensureFlags(regexp, "gm") var string, chunkSize = 1, endMargin = doc.getLine(start.line).length - start.ch for (var line = start.line, first = doc.firstLine(); line >= first;) { for (var i = 0; i < chunkSize && line >= first; i++) { var curLine = doc.getLine(line--) string = string == null ? curLine : curLine + "\n" + string } chunkSize *= 2 var match = lastMatchIn(string, regexp, endMargin) if (match) { var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n") var startLine = line + before.length, startCh = before[before.length - 1].length return {from: Pos(startLine, startCh), to: Pos(startLine + inside.length - 1, inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length), match: match} } } } var doFold, noFold if (String.prototype.normalize) { doFold = function(str) { return str.normalize("NFD").toLowerCase() } noFold = function(str) { return str.normalize("NFD") } } else { doFold = function(str) { return str.toLowerCase() } noFold = function(str) { return str } } // Maps a position in a case-folded line back to a position in the original line // (compensating for codepoints increasing in number during folding) function adjustPos(orig, folded, pos, foldFunc) { if (orig.length == folded.length) return pos for (var min = 0, max = pos + Math.max(0, orig.length - folded.length);;) { if (min == max) return min var mid = (min + max) >> 1 var len = foldFunc(orig.slice(0, mid)).length if (len == pos) return mid else if (len > pos) max = mid else min = mid + 1 } } function searchStringForward(doc, query, start, caseFold) { // Empty string would match anything and never progress, so we // define it to match nothing instead. if (!query.length) return null var fold = caseFold ? doFold : noFold var lines = fold(query).split(/\r|\n\r?/) search: for (var line = start.line, ch = start.ch, last = doc.lastLine() + 1 - lines.length; line <= last; line++, ch = 0) { var orig = doc.getLine(line).slice(ch), string = fold(orig) if (lines.length == 1) { var found = string.indexOf(lines[0]) if (found == -1) continue search var start = adjustPos(orig, string, found, fold) + ch return {from: Pos(line, adjustPos(orig, string, found, fold) + ch), to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold) + ch)} } else { var cutFrom = string.length - lines[0].length if (string.slice(cutFrom) != lines[0]) continue search for (var i = 1; i < lines.length - 1; i++) if (fold(doc.getLine(line + i)) != lines[i]) continue search var end = doc.getLine(line + lines.length - 1), endString = fold(end), lastLine = lines[lines.length - 1] if (endString.slice(0, lastLine.length) != lastLine) continue search return {from: Pos(line, adjustPos(orig, string, cutFrom, fold) + ch), to: Pos(line + lines.length - 1, adjustPos(end, endString, lastLine.length, fold))} } } } function searchStringBackward(doc, query, start, caseFold) { if (!query.length) return null var fold = caseFold ? doFold : noFold var lines = fold(query).split(/\r|\n\r?/) search: for (var line = start.line, ch = start.ch, first = doc.firstLine() - 1 + lines.length; line >= first; line--, ch = -1) { var orig = doc.getLine(line) if (ch > -1) orig = orig.slice(0, ch) var string = fold(orig) if (lines.length == 1) { var found = string.lastIndexOf(lines[0]) if (found == -1) continue search return {from: Pos(line, adjustPos(orig, string, found, fold)), to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold))} } else { var lastLine = lines[lines.length - 1] if (string.slice(0, lastLine.length) != lastLine) continue search for (var i = 1, start = line - lines.length + 1; i < lines.length - 1; i++) if (fold(doc.getLine(start + i)) != lines[i]) continue search var top = doc.getLine(line + 1 - lines.length), topString = fold(top) if (topString.slice(topString.length - lines[0].length) != lines[0]) continue search return {from: Pos(line + 1 - lines.length, adjustPos(top, topString, top.length - lines[0].length, fold)), to: Pos(line, adjustPos(orig, string, lastLine.length, fold))} } } } function SearchCursor(doc, query, pos, options) { this.atOccurrence = false this.afterEmptyMatch = false this.doc = doc pos = pos ? doc.clipPos(pos) : Pos(0, 0) this.pos = {from: pos, to: pos} var caseFold if (typeof options == "object") { caseFold = options.caseFold } else { // Backwards compat for when caseFold was the 4th argument caseFold = options options = null } if (typeof query == "string") { if (caseFold == null) caseFold = false this.matches = function(reverse, pos) { return (reverse ? searchStringBackward : searchStringForward)(doc, query, pos, caseFold) } } else { query = ensureFlags(query, "gm") if (!options || options.multiline !== false) this.matches = function(reverse, pos) { return (reverse ? searchRegexpBackwardMultiline : searchRegexpForwardMultiline)(doc, query, pos) } else this.matches = function(reverse, pos) { return (reverse ? searchRegexpBackward : searchRegexpForward)(doc, query, pos) } } } SearchCursor.prototype = { findNext: function() {return this.find(false)}, findPrevious: function() {return this.find(true)}, find: function(reverse) { var head = this.doc.clipPos(reverse ? this.pos.from : this.pos.to); if (this.afterEmptyMatch && this.atOccurrence) { // do not return the same 0 width match twice head = Pos(head.line, head.ch) if (reverse) { head.ch--; if (head.ch < 0) { head.line--; head.ch = (this.doc.getLine(head.line) || "").length; } } else { head.ch++; if (head.ch > (this.doc.getLine(head.line) || "").length) { head.ch = 0; head.line++; } } if (CodeMirror.cmpPos(head, this.doc.clipPos(head)) != 0) { return this.atOccurrence = false } } var result = this.matches(reverse, head) this.afterEmptyMatch = result && CodeMirror.cmpPos(result.from, result.to) == 0 if (result) { this.pos = result this.atOccurrence = true return this.pos.match || true } else { var end = Pos(reverse ? this.doc.firstLine() : this.doc.lastLine() + 1, 0) this.pos = {from: end, to: end} return this.atOccurrence = false } }, from: function() {if (this.atOccurrence) return this.pos.from}, to: function() {if (this.atOccurrence) return this.pos.to}, replace: function(newText, origin) { if (!this.atOccurrence) return var lines = CodeMirror.splitLines(newText) this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin) this.pos.to = Pos(this.pos.from.line + lines.length - 1, lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0)) } } CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) { return new SearchCursor(this.doc, query, pos, caseFold) }) CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) { return new SearchCursor(this, query, pos, caseFold) }) CodeMirror.defineExtension("selectMatches", function(query, caseFold) { var ranges = [] var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold) while (cur.findNext()) { if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break ranges.push({anchor: cur.from(), head: cur.to()}) } if (ranges.length) this.setSelections(ranges, 0) }) }); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/codemirror.js000066400000000000000000014211341473125420300275760ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE // This is CodeMirror (https://codemirror.net/5), a code editor // implemented in JavaScript on top of the browser's DOM. // // You can find some technical background for some of the code below // at http://marijnhaverbeke.nl/blog/#cm-internals . (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.CodeMirror = factory()); }(this, (function () { 'use strict'; // Kludges for bugs and behavior differences that can't be feature // detected are enabled based on userAgent etc sniffing. var userAgent = navigator.userAgent; var platform = navigator.platform; var gecko = /gecko\/\d/i.test(userAgent); var ie_upto10 = /MSIE \d/.test(userAgent); var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent); var edge = /Edge\/(\d+)/.exec(userAgent); var ie = ie_upto10 || ie_11up || edge; var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]); var webkit = !edge && /WebKit\//.test(userAgent); var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent); var chrome = !edge && /Chrome\/(\d+)/.exec(userAgent); var chrome_version = chrome && +chrome[1]; var presto = /Opera\//.test(userAgent); var safari = /Apple Computer/.test(navigator.vendor); var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent); var phantom = /PhantomJS/.test(userAgent); var ios = safari && (/Mobile\/\w+/.test(userAgent) || navigator.maxTouchPoints > 2); var android = /Android/.test(userAgent); // This is woefully incomplete. Suggestions for alternative methods welcome. var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent); var mac = ios || /Mac/.test(platform); var chromeOS = /\bCrOS\b/.test(userAgent); var windows = /win/i.test(platform); var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/); if (presto_version) { presto_version = Number(presto_version[1]); } if (presto_version && presto_version >= 15) { presto = false; webkit = true; } // Some browsers use the wrong event properties to signal cmd/ctrl on OS X var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)); var captureRightClick = gecko || (ie && ie_version >= 9); function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") } var rmClass = function(node, cls) { var current = node.className; var match = classTest(cls).exec(current); if (match) { var after = current.slice(match.index + match[0].length); node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); } }; function removeChildren(e) { for (var count = e.childNodes.length; count > 0; --count) { e.removeChild(e.firstChild); } return e } function removeChildrenAndAdd(parent, e) { return removeChildren(parent).appendChild(e) } function elt(tag, content, className, style) { var e = document.createElement(tag); if (className) { e.className = className; } if (style) { e.style.cssText = style; } if (typeof content == "string") { e.appendChild(document.createTextNode(content)); } else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]); } } return e } // wrapper for elt, which removes the elt from the accessibility tree function eltP(tag, content, className, style) { var e = elt(tag, content, className, style); e.setAttribute("role", "presentation"); return e } var range; if (document.createRange) { range = function(node, start, end, endNode) { var r = document.createRange(); r.setEnd(endNode || node, end); r.setStart(node, start); return r }; } else { range = function(node, start, end) { var r = document.body.createTextRange(); try { r.moveToElementText(node.parentNode); } catch(e) { return r } r.collapse(true); r.moveEnd("character", end); r.moveStart("character", start); return r }; } function contains(parent, child) { if (child.nodeType == 3) // Android browser always returns false when child is a textnode { child = child.parentNode; } if (parent.contains) { return parent.contains(child) } do { if (child.nodeType == 11) { child = child.host; } if (child == parent) { return true } } while (child = child.parentNode) } function activeElt(rootNode) { // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement. // IE < 10 will throw when accessed while the page is loading or in an iframe. // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable. var doc = rootNode.ownerDocument || rootNode; var activeElement; try { activeElement = rootNode.activeElement; } catch(e) { activeElement = doc.body || null; } while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement) { activeElement = activeElement.shadowRoot.activeElement; } return activeElement } function addClass(node, cls) { var current = node.className; if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls; } } function joinClasses(a, b) { var as = a.split(" "); for (var i = 0; i < as.length; i++) { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i]; } } return b } var selectInput = function(node) { node.select(); }; if (ios) // Mobile Safari apparently has a bug where select() is broken. { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; } else if (ie) // Suppress mysterious IE10 errors { selectInput = function(node) { try { node.select(); } catch(_e) {} }; } function doc(cm) { return cm.display.wrapper.ownerDocument } function root(cm) { return rootNode(cm.display.wrapper) } function rootNode(element) { // Detect modern browsers (2017+). return element.getRootNode ? element.getRootNode() : element.ownerDocument } function win(cm) { return doc(cm).defaultView } function bind(f) { var args = Array.prototype.slice.call(arguments, 1); return function(){return f.apply(null, args)} } function copyObj(obj, target, overwrite) { if (!target) { target = {}; } for (var prop in obj) { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) { target[prop] = obj[prop]; } } return target } // Counts the column offset in a string, taking tabs into account. // Used mostly to find indentation. function countColumn(string, end, tabSize, startIndex, startValue) { if (end == null) { end = string.search(/[^\s\u00a0]/); if (end == -1) { end = string.length; } } for (var i = startIndex || 0, n = startValue || 0;;) { var nextTab = string.indexOf("\t", i); if (nextTab < 0 || nextTab >= end) { return n + (end - i) } n += nextTab - i; n += tabSize - (n % tabSize); i = nextTab + 1; } } var Delayed = function() { this.id = null; this.f = null; this.time = 0; this.handler = bind(this.onTimeout, this); }; Delayed.prototype.onTimeout = function (self) { self.id = 0; if (self.time <= +new Date) { self.f(); } else { setTimeout(self.handler, self.time - +new Date); } }; Delayed.prototype.set = function (ms, f) { this.f = f; var time = +new Date + ms; if (!this.id || time < this.time) { clearTimeout(this.id); this.id = setTimeout(this.handler, ms); this.time = time; } }; function indexOf(array, elt) { for (var i = 0; i < array.length; ++i) { if (array[i] == elt) { return i } } return -1 } // Number of pixels added to scroller and sizer to hide scrollbar var scrollerGap = 50; // Returned or thrown by various protocols to signal 'I'm not // handling this'. var Pass = {toString: function(){return "CodeMirror.Pass"}}; // Reused option objects for setSelection & friends var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"}; // The inverse of countColumn -- find the offset that corresponds to // a particular column. function findColumn(string, goal, tabSize) { for (var pos = 0, col = 0;;) { var nextTab = string.indexOf("\t", pos); if (nextTab == -1) { nextTab = string.length; } var skipped = nextTab - pos; if (nextTab == string.length || col + skipped >= goal) { return pos + Math.min(skipped, goal - col) } col += nextTab - pos; col += tabSize - (col % tabSize); pos = nextTab + 1; if (col >= goal) { return pos } } } var spaceStrs = [""]; function spaceStr(n) { while (spaceStrs.length <= n) { spaceStrs.push(lst(spaceStrs) + " "); } return spaceStrs[n] } function lst(arr) { return arr[arr.length-1] } function map(array, f) { var out = []; for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i); } return out } function insertSorted(array, value, score) { var pos = 0, priority = score(value); while (pos < array.length && score(array[pos]) <= priority) { pos++; } array.splice(pos, 0, value); } function nothing() {} function createObj(base, props) { var inst; if (Object.create) { inst = Object.create(base); } else { nothing.prototype = base; inst = new nothing(); } if (props) { copyObj(props, inst); } return inst } var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; function isWordCharBasic(ch) { return /\w/.test(ch) || ch > "\x80" && (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)) } function isWordChar(ch, helper) { if (!helper) { return isWordCharBasic(ch) } if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true } return helper.test(ch) } function isEmpty(obj) { for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } } return true } // Extending unicode characters. A series of a non-extending char + // any number of extending chars is treated as a single unit as far // as editing and measuring is concerned. This is not fully correct, // since some scripts/fonts/browsers also treat other configurations // of code points as a group. var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) } // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range. function skipExtendingChars(str, pos, dir) { while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir; } return pos } // Returns the value from the range [`from`; `to`] that satisfies // `pred` and is closest to `from`. Assumes that at least `to` // satisfies `pred`. Supports `from` being greater than `to`. function findFirst(pred, from, to) { // At any point we are certain `to` satisfies `pred`, don't know // whether `from` does. var dir = from > to ? -1 : 1; for (;;) { if (from == to) { return from } var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF); if (mid == from) { return pred(mid) ? from : to } if (pred(mid)) { to = mid; } else { from = mid + dir; } } } // BIDI HELPERS function iterateBidiSections(order, from, to, f) { if (!order) { return f(from, to, "ltr", 0) } var found = false; for (var i = 0; i < order.length; ++i) { var part = order[i]; if (part.from < to && part.to > from || from == to && part.to == from) { f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i); found = true; } } if (!found) { f(from, to, "ltr"); } } var bidiOther = null; function getBidiPartAt(order, ch, sticky) { var found; bidiOther = null; for (var i = 0; i < order.length; ++i) { var cur = order[i]; if (cur.from < ch && cur.to > ch) { return i } if (cur.to == ch) { if (cur.from != cur.to && sticky == "before") { found = i; } else { bidiOther = i; } } if (cur.from == ch) { if (cur.from != cur.to && sticky != "before") { found = i; } else { bidiOther = i; } } } return found != null ? found : bidiOther } // Bidirectional ordering algorithm // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm // that this (partially) implements. // One-char codes used for character types: // L (L): Left-to-Right // R (R): Right-to-Left // r (AL): Right-to-Left Arabic // 1 (EN): European Number // + (ES): European Number Separator // % (ET): European Number Terminator // n (AN): Arabic Number // , (CS): Common Number Separator // m (NSM): Non-Spacing Mark // b (BN): Boundary Neutral // s (B): Paragraph Separator // t (S): Segment Separator // w (WS): Whitespace // N (ON): Other Neutrals // Returns null if characters are ordered as they appear // (left-to-right), or an array of sections ({from, to, level} // objects) in the order in which they occur visually. var bidiOrdering = (function() { // Character types for codepoints 0 to 0xff var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"; // Character types for codepoints 0x600 to 0x6f9 var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111"; function charType(code) { if (code <= 0xf7) { return lowTypes.charAt(code) } else if (0x590 <= code && code <= 0x5f4) { return "R" } else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) } else if (0x6ee <= code && code <= 0x8ac) { return "r" } else if (0x2000 <= code && code <= 0x200b) { return "w" } else if (code == 0x200c) { return "b" } else { return "L" } } var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; function BidiSpan(level, from, to) { this.level = level; this.from = from; this.to = to; } return function(str, direction) { var outerType = direction == "ltr" ? "L" : "R"; if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { return false } var len = str.length, types = []; for (var i = 0; i < len; ++i) { types.push(charType(str.charCodeAt(i))); } // W1. Examine each non-spacing mark (NSM) in the level run, and // change the type of the NSM to the type of the previous // character. If the NSM is at the start of the level run, it will // get the type of sor. for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) { var type = types[i$1]; if (type == "m") { types[i$1] = prev; } else { prev = type; } } // W2. Search backwards from each instance of a European number // until the first strong type (R, L, AL, or sor) is found. If an // AL is found, change the type of the European number to Arabic // number. // W3. Change all ALs to R. for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) { var type$1 = types[i$2]; if (type$1 == "1" && cur == "r") { types[i$2] = "n"; } else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R"; } } } // W4. A single European separator between two European numbers // changes to a European number. A single common separator between // two numbers of the same type changes to that type. for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) { var type$2 = types[i$3]; if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1"; } else if (type$2 == "," && prev$1 == types[i$3+1] && (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1; } prev$1 = type$2; } // W5. A sequence of European terminators adjacent to European // numbers changes to all European numbers. // W6. Otherwise, separators and terminators change to Other // Neutral. for (var i$4 = 0; i$4 < len; ++i$4) { var type$3 = types[i$4]; if (type$3 == ",") { types[i$4] = "N"; } else if (type$3 == "%") { var end = (void 0); for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {} var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; for (var j = i$4; j < end; ++j) { types[j] = replace; } i$4 = end - 1; } } // W7. Search backwards from each instance of a European number // until the first strong type (R, L, or sor) is found. If an L is // found, then change the type of the European number to L. for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) { var type$4 = types[i$5]; if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L"; } else if (isStrong.test(type$4)) { cur$1 = type$4; } } // N1. A sequence of neutrals takes the direction of the // surrounding strong text if the text on both sides has the same // direction. European and Arabic numbers act as if they were R in // terms of their influence on neutrals. Start-of-level-run (sor) // and end-of-level-run (eor) are used at level run boundaries. // N2. Any remaining neutrals take the embedding direction. for (var i$6 = 0; i$6 < len; ++i$6) { if (isNeutral.test(types[i$6])) { var end$1 = (void 0); for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {} var before = (i$6 ? types[i$6-1] : outerType) == "L"; var after = (end$1 < len ? types[end$1] : outerType) == "L"; var replace$1 = before == after ? (before ? "L" : "R") : outerType; for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1; } i$6 = end$1 - 1; } } // Here we depart from the documented algorithm, in order to avoid // building up an actual levels array. Since there are only three // levels (0, 1, 2) in an implementation that doesn't take // explicit embedding into account, we can build up the order on // the fly, without following the level-based algorithm. var order = [], m; for (var i$7 = 0; i$7 < len;) { if (countsAsLeft.test(types[i$7])) { var start = i$7; for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {} order.push(new BidiSpan(0, start, i$7)); } else { var pos = i$7, at = order.length, isRTL = direction == "rtl" ? 1 : 0; for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {} for (var j$2 = pos; j$2 < i$7;) { if (countsAsNum.test(types[j$2])) { if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); at += isRTL; } var nstart = j$2; for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {} order.splice(at, 0, new BidiSpan(2, nstart, j$2)); at += isRTL; pos = j$2; } else { ++j$2; } } if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)); } } } if (direction == "ltr") { if (order[0].level == 1 && (m = str.match(/^\s+/))) { order[0].from = m[0].length; order.unshift(new BidiSpan(0, 0, m[0].length)); } if (lst(order).level == 1 && (m = str.match(/\s+$/))) { lst(order).to -= m[0].length; order.push(new BidiSpan(0, len - m[0].length, len)); } } return direction == "rtl" ? order.reverse() : order } })(); // Get the bidi ordering for the given line (and cache it). Returns // false for lines that are fully left-to-right, and an array of // BidiSpan objects otherwise. function getOrder(line, direction) { var order = line.order; if (order == null) { order = line.order = bidiOrdering(line.text, direction); } return order } // EVENT HANDLING // Lightweight event framework. on/off also work on DOM nodes, // registering native DOM handlers. var noHandlers = []; var on = function(emitter, type, f) { if (emitter.addEventListener) { emitter.addEventListener(type, f, false); } else if (emitter.attachEvent) { emitter.attachEvent("on" + type, f); } else { var map = emitter._handlers || (emitter._handlers = {}); map[type] = (map[type] || noHandlers).concat(f); } }; function getHandlers(emitter, type) { return emitter._handlers && emitter._handlers[type] || noHandlers } function off(emitter, type, f) { if (emitter.removeEventListener) { emitter.removeEventListener(type, f, false); } else if (emitter.detachEvent) { emitter.detachEvent("on" + type, f); } else { var map = emitter._handlers, arr = map && map[type]; if (arr) { var index = indexOf(arr, f); if (index > -1) { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)); } } } } function signal(emitter, type /*, values...*/) { var handlers = getHandlers(emitter, type); if (!handlers.length) { return } var args = Array.prototype.slice.call(arguments, 2); for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args); } } // The DOM events that CodeMirror handles can be overridden by // registering a (non-DOM) handler on the editor for the event name, // and preventDefault-ing the event in that handler. function signalDOMEvent(cm, e, override) { if (typeof e == "string") { e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; } signal(cm, override || e.type, cm, e); return e_defaultPrevented(e) || e.codemirrorIgnore } function signalCursorActivity(cm) { var arr = cm._handlers && cm._handlers.cursorActivity; if (!arr) { return } var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1) { set.push(arr[i]); } } } function hasHandler(emitter, type) { return getHandlers(emitter, type).length > 0 } // Add on and off methods to a constructor's prototype, to make // registering events on such objects more convenient. function eventMixin(ctor) { ctor.prototype.on = function(type, f) {on(this, type, f);}; ctor.prototype.off = function(type, f) {off(this, type, f);}; } // Due to the fact that we still support jurassic IE versions, some // compatibility wrappers are needed. function e_preventDefault(e) { if (e.preventDefault) { e.preventDefault(); } else { e.returnValue = false; } } function e_stopPropagation(e) { if (e.stopPropagation) { e.stopPropagation(); } else { e.cancelBubble = true; } } function e_defaultPrevented(e) { return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false } function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);} function e_target(e) {return e.target || e.srcElement} function e_button(e) { var b = e.which; if (b == null) { if (e.button & 1) { b = 1; } else if (e.button & 2) { b = 3; } else if (e.button & 4) { b = 2; } } if (mac && e.ctrlKey && b == 1) { b = 3; } return b } // Detect drag-and-drop var dragAndDrop = function() { // There is *some* kind of drag-and-drop support in IE6-8, but I // couldn't get it to work yet. if (ie && ie_version < 9) { return false } var div = elt('div'); return "draggable" in div || "dragDrop" in div }(); var zwspSupported; function zeroWidthElement(measure) { if (zwspSupported == null) { var test = elt("span", "\u200b"); removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); if (measure.firstChild.offsetHeight != 0) { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); } } var node = zwspSupported ? elt("span", "\u200b") : elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); node.setAttribute("cm-text", ""); return node } // Feature-detect IE's crummy client rect reporting for bidi text var badBidiRects; function hasBadBidiRects(measure) { if (badBidiRects != null) { return badBidiRects } var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")); var r0 = range(txt, 0, 1).getBoundingClientRect(); var r1 = range(txt, 1, 2).getBoundingClientRect(); removeChildren(measure); if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780) return badBidiRects = (r1.right - r0.right < 3) } // See if "".split is the broken IE version, if so, provide an // alternative way to split lines. var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) { var pos = 0, result = [], l = string.length; while (pos <= l) { var nl = string.indexOf("\n", pos); if (nl == -1) { nl = string.length; } var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); var rt = line.indexOf("\r"); if (rt != -1) { result.push(line.slice(0, rt)); pos += rt + 1; } else { result.push(line); pos = nl + 1; } } return result } : function (string) { return string.split(/\r\n?|\n/); }; var hasSelection = window.getSelection ? function (te) { try { return te.selectionStart != te.selectionEnd } catch(e) { return false } } : function (te) { var range; try {range = te.ownerDocument.selection.createRange();} catch(e) {} if (!range || range.parentElement() != te) { return false } return range.compareEndPoints("StartToEnd", range) != 0 }; var hasCopyEvent = (function () { var e = elt("div"); if ("oncopy" in e) { return true } e.setAttribute("oncopy", "return;"); return typeof e.oncopy == "function" })(); var badZoomedRects = null; function hasBadZoomedRects(measure) { if (badZoomedRects != null) { return badZoomedRects } var node = removeChildrenAndAdd(measure, elt("span", "x")); var normal = node.getBoundingClientRect(); var fromRange = range(node, 0, 1).getBoundingClientRect(); return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1 } // Known modes, by name and by MIME var modes = {}, mimeModes = {}; // Extra arguments are stored as the mode's dependencies, which is // used by (legacy) mechanisms like loadmode.js to automatically // load a mode. (Preferred mechanism is the require/define calls.) function defineMode(name, mode) { if (arguments.length > 2) { mode.dependencies = Array.prototype.slice.call(arguments, 2); } modes[name] = mode; } function defineMIME(mime, spec) { mimeModes[mime] = spec; } // Given a MIME type, a {name, ...options} config object, or a name // string, return a mode config object. function resolveMode(spec) { if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { spec = mimeModes[spec]; } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { var found = mimeModes[spec.name]; if (typeof found == "string") { found = {name: found}; } spec = createObj(found, spec); spec.name = found.name; } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { return resolveMode("application/xml") } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) { return resolveMode("application/json") } if (typeof spec == "string") { return {name: spec} } else { return spec || {name: "null"} } } // Given a mode spec (anything that resolveMode accepts), find and // initialize an actual mode object. function getMode(options, spec) { spec = resolveMode(spec); var mfactory = modes[spec.name]; if (!mfactory) { return getMode(options, "text/plain") } var modeObj = mfactory(options, spec); if (modeExtensions.hasOwnProperty(spec.name)) { var exts = modeExtensions[spec.name]; for (var prop in exts) { if (!exts.hasOwnProperty(prop)) { continue } if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; } modeObj[prop] = exts[prop]; } } modeObj.name = spec.name; if (spec.helperType) { modeObj.helperType = spec.helperType; } if (spec.modeProps) { for (var prop$1 in spec.modeProps) { modeObj[prop$1] = spec.modeProps[prop$1]; } } return modeObj } // This can be used to attach properties to mode objects from // outside the actual mode definition. var modeExtensions = {}; function extendMode(mode, properties) { var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); copyObj(properties, exts); } function copyState(mode, state) { if (state === true) { return state } if (mode.copyState) { return mode.copyState(state) } var nstate = {}; for (var n in state) { var val = state[n]; if (val instanceof Array) { val = val.concat([]); } nstate[n] = val; } return nstate } // Given a mode and a state (for that mode), find the inner mode and // state at the position that the state refers to. function innerMode(mode, state) { var info; while (mode.innerMode) { info = mode.innerMode(state); if (!info || info.mode == mode) { break } state = info.state; mode = info.mode; } return info || {mode: mode, state: state} } function startState(mode, a1, a2) { return mode.startState ? mode.startState(a1, a2) : true } // STRING STREAM // Fed to the mode parsers, provides helper functions to make // parsers more succinct. var StringStream = function(string, tabSize, lineOracle) { this.pos = this.start = 0; this.string = string; this.tabSize = tabSize || 8; this.lastColumnPos = this.lastColumnValue = 0; this.lineStart = 0; this.lineOracle = lineOracle; }; StringStream.prototype.eol = function () {return this.pos >= this.string.length}; StringStream.prototype.sol = function () {return this.pos == this.lineStart}; StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined}; StringStream.prototype.next = function () { if (this.pos < this.string.length) { return this.string.charAt(this.pos++) } }; StringStream.prototype.eat = function (match) { var ch = this.string.charAt(this.pos); var ok; if (typeof match == "string") { ok = ch == match; } else { ok = ch && (match.test ? match.test(ch) : match(ch)); } if (ok) {++this.pos; return ch} }; StringStream.prototype.eatWhile = function (match) { var start = this.pos; while (this.eat(match)){} return this.pos > start }; StringStream.prototype.eatSpace = function () { var start = this.pos; while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; } return this.pos > start }; StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;}; StringStream.prototype.skipTo = function (ch) { var found = this.string.indexOf(ch, this.pos); if (found > -1) {this.pos = found; return true} }; StringStream.prototype.backUp = function (n) {this.pos -= n;}; StringStream.prototype.column = function () { if (this.lastColumnPos < this.start) { this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); this.lastColumnPos = this.start; } return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) }; StringStream.prototype.indentation = function () { return countColumn(this.string, null, this.tabSize) - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) }; StringStream.prototype.match = function (pattern, consume, caseInsensitive) { if (typeof pattern == "string") { var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; }; var substr = this.string.substr(this.pos, pattern.length); if (cased(substr) == cased(pattern)) { if (consume !== false) { this.pos += pattern.length; } return true } } else { var match = this.string.slice(this.pos).match(pattern); if (match && match.index > 0) { return null } if (match && consume !== false) { this.pos += match[0].length; } return match } }; StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)}; StringStream.prototype.hideFirstChars = function (n, inner) { this.lineStart += n; try { return inner() } finally { this.lineStart -= n; } }; StringStream.prototype.lookAhead = function (n) { var oracle = this.lineOracle; return oracle && oracle.lookAhead(n) }; StringStream.prototype.baseToken = function () { var oracle = this.lineOracle; return oracle && oracle.baseToken(this.pos) }; // Find the line object corresponding to the given line number. function getLine(doc, n) { n -= doc.first; if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") } var chunk = doc; while (!chunk.lines) { for (var i = 0;; ++i) { var child = chunk.children[i], sz = child.chunkSize(); if (n < sz) { chunk = child; break } n -= sz; } } return chunk.lines[n] } // Get the part of a document between two positions, as an array of // strings. function getBetween(doc, start, end) { var out = [], n = start.line; doc.iter(start.line, end.line + 1, function (line) { var text = line.text; if (n == end.line) { text = text.slice(0, end.ch); } if (n == start.line) { text = text.slice(start.ch); } out.push(text); ++n; }); return out } // Get the lines between from and to, as array of strings. function getLines(doc, from, to) { var out = []; doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value return out } // Update the height of a line, propagating the height change // upwards to parent nodes. function updateLineHeight(line, height) { var diff = height - line.height; if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } } } // Given a line object, find its line number by walking up through // its parent links. function lineNo(line) { if (line.parent == null) { return null } var cur = line.parent, no = indexOf(cur.lines, line); for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { for (var i = 0;; ++i) { if (chunk.children[i] == cur) { break } no += chunk.children[i].chunkSize(); } } return no + cur.first } // Find the line at the given vertical position, using the height // information in the document tree. function lineAtHeight(chunk, h) { var n = chunk.first; outer: do { for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) { var child = chunk.children[i$1], ch = child.height; if (h < ch) { chunk = child; continue outer } h -= ch; n += child.chunkSize(); } return n } while (!chunk.lines) var i = 0; for (; i < chunk.lines.length; ++i) { var line = chunk.lines[i], lh = line.height; if (h < lh) { break } h -= lh; } return n + i } function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size} function lineNumberFor(options, i) { return String(options.lineNumberFormatter(i + options.firstLineNumber)) } // A Pos instance represents a position within the text. function Pos(line, ch, sticky) { if ( sticky === void 0 ) sticky = null; if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) } this.line = line; this.ch = ch; this.sticky = sticky; } // Compare two positions, return 0 if they are the same, a negative // number when a is less, and a positive number otherwise. function cmp(a, b) { return a.line - b.line || a.ch - b.ch } function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 } function copyPos(x) {return Pos(x.line, x.ch)} function maxPos(a, b) { return cmp(a, b) < 0 ? b : a } function minPos(a, b) { return cmp(a, b) < 0 ? a : b } // Most of the external API clips given positions to make sure they // actually exist within the document. function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))} function clipPos(doc, pos) { if (pos.line < doc.first) { return Pos(doc.first, 0) } var last = doc.first + doc.size - 1; if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) } return clipToLen(pos, getLine(doc, pos.line).text.length) } function clipToLen(pos, linelen) { var ch = pos.ch; if (ch == null || ch > linelen) { return Pos(pos.line, linelen) } else if (ch < 0) { return Pos(pos.line, 0) } else { return pos } } function clipPosArray(doc, array) { var out = []; for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); } return out } var SavedContext = function(state, lookAhead) { this.state = state; this.lookAhead = lookAhead; }; var Context = function(doc, state, line, lookAhead) { this.state = state; this.doc = doc; this.line = line; this.maxLookAhead = lookAhead || 0; this.baseTokens = null; this.baseTokenPos = 1; }; Context.prototype.lookAhead = function (n) { var line = this.doc.getLine(this.line + n); if (line != null && n > this.maxLookAhead) { this.maxLookAhead = n; } return line }; Context.prototype.baseToken = function (n) { if (!this.baseTokens) { return null } while (this.baseTokens[this.baseTokenPos] <= n) { this.baseTokenPos += 2; } var type = this.baseTokens[this.baseTokenPos + 1]; return {type: type && type.replace(/( |^)overlay .*/, ""), size: this.baseTokens[this.baseTokenPos] - n} }; Context.prototype.nextLine = function () { this.line++; if (this.maxLookAhead > 0) { this.maxLookAhead--; } }; Context.fromSaved = function (doc, saved, line) { if (saved instanceof SavedContext) { return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead) } else { return new Context(doc, copyState(doc.mode, saved), line) } }; Context.prototype.save = function (copy) { var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state; return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state }; // Compute a style array (an array starting with a mode generation // -- for invalidation -- followed by pairs of end positions and // style strings), which is used to highlight the tokens on the // line. function highlightLine(cm, line, context, forceToEnd) { // A styles array always starts with a number identifying the // mode/overlays that it is based on (for easy invalidation). var st = [cm.state.modeGen], lineClasses = {}; // Compute the base array of styles runMode(cm, line.text, cm.doc.mode, context, function (end, style) { return st.push(end, style); }, lineClasses, forceToEnd); var state = context.state; // Run overlays, adjust style array. var loop = function ( o ) { context.baseTokens = st; var overlay = cm.state.overlays[o], i = 1, at = 0; context.state = true; runMode(cm, line.text, overlay.mode, context, function (end, style) { var start = i; // Ensure there's a token end at the current position, and that i points at it while (at < end) { var i_end = st[i]; if (i_end > end) { st.splice(i, 1, end, st[i+1], i_end); } i += 2; at = Math.min(end, i_end); } if (!style) { return } if (overlay.opaque) { st.splice(start, i - start, end, "overlay " + style); i = start + 2; } else { for (; start < i; start += 2) { var cur = st[start+1]; st[start+1] = (cur ? cur + " " : "") + "overlay " + style; } } }, lineClasses); context.state = state; context.baseTokens = null; context.baseTokenPos = 1; }; for (var o = 0; o < cm.state.overlays.length; ++o) loop( o ); return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null} } function getLineStyles(cm, line, updateFrontier) { if (!line.styles || line.styles[0] != cm.state.modeGen) { var context = getContextBefore(cm, lineNo(line)); var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state); var result = highlightLine(cm, line, context); if (resetState) { context.state = resetState; } line.stateAfter = context.save(!resetState); line.styles = result.styles; if (result.classes) { line.styleClasses = result.classes; } else if (line.styleClasses) { line.styleClasses = null; } if (updateFrontier === cm.doc.highlightFrontier) { cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier); } } return line.styles } function getContextBefore(cm, n, precise) { var doc = cm.doc, display = cm.display; if (!doc.mode.startState) { return new Context(doc, true, n) } var start = findStartLine(cm, n, precise); var saved = start > doc.first && getLine(doc, start - 1).stateAfter; var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start); doc.iter(start, n, function (line) { processLine(cm, line.text, context); var pos = context.line; line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null; context.nextLine(); }); if (precise) { doc.modeFrontier = context.line; } return context } // Lightweight form of highlight -- proceed over this line and // update state, but don't save a style array. Used for lines that // aren't currently visible. function processLine(cm, text, context, startAt) { var mode = cm.doc.mode; var stream = new StringStream(text, cm.options.tabSize, context); stream.start = stream.pos = startAt || 0; if (text == "") { callBlankLine(mode, context.state); } while (!stream.eol()) { readToken(mode, stream, context.state); stream.start = stream.pos; } } function callBlankLine(mode, state) { if (mode.blankLine) { return mode.blankLine(state) } if (!mode.innerMode) { return } var inner = innerMode(mode, state); if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) } } function readToken(mode, stream, state, inner) { for (var i = 0; i < 10; i++) { if (inner) { inner[0] = innerMode(mode, state).mode; } var style = mode.token(stream, state); if (stream.pos > stream.start) { return style } } throw new Error("Mode " + mode.name + " failed to advance stream.") } var Token = function(stream, type, state) { this.start = stream.start; this.end = stream.pos; this.string = stream.current(); this.type = type || null; this.state = state; }; // Utility for getTokenAt and getLineTokens function takeToken(cm, pos, precise, asArray) { var doc = cm.doc, mode = doc.mode, style; pos = clipPos(doc, pos); var line = getLine(doc, pos.line), context = getContextBefore(cm, pos.line, precise); var stream = new StringStream(line.text, cm.options.tabSize, context), tokens; if (asArray) { tokens = []; } while ((asArray || stream.pos < pos.ch) && !stream.eol()) { stream.start = stream.pos; style = readToken(mode, stream, context.state); if (asArray) { tokens.push(new Token(stream, style, copyState(doc.mode, context.state))); } } return asArray ? tokens : new Token(stream, style, context.state) } function extractLineClasses(type, output) { if (type) { for (;;) { var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/); if (!lineClass) { break } type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length); var prop = lineClass[1] ? "bgClass" : "textClass"; if (output[prop] == null) { output[prop] = lineClass[2]; } else if (!(new RegExp("(?:^|\\s)" + lineClass[2] + "(?:$|\\s)")).test(output[prop])) { output[prop] += " " + lineClass[2]; } } } return type } // Run the given mode's parser over a line, calling f for each token. function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) { var flattenSpans = mode.flattenSpans; if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans; } var curStart = 0, curStyle = null; var stream = new StringStream(text, cm.options.tabSize, context), style; var inner = cm.options.addModeClass && [null]; if (text == "") { extractLineClasses(callBlankLine(mode, context.state), lineClasses); } while (!stream.eol()) { if (stream.pos > cm.options.maxHighlightLength) { flattenSpans = false; if (forceToEnd) { processLine(cm, text, context, stream.pos); } stream.pos = text.length; style = null; } else { style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses); } if (inner) { var mName = inner[0].name; if (mName) { style = "m-" + (style ? mName + " " + style : mName); } } if (!flattenSpans || curStyle != style) { while (curStart < stream.start) { curStart = Math.min(stream.start, curStart + 5000); f(curStart, curStyle); } curStyle = style; } stream.start = stream.pos; } while (curStart < stream.pos) { // Webkit seems to refuse to render text nodes longer than 57444 // characters, and returns inaccurate measurements in nodes // starting around 5000 chars. var pos = Math.min(stream.pos, curStart + 5000); f(pos, curStyle); curStart = pos; } } // Finds the line to start with when starting a parse. Tries to // find a line with a stateAfter, so that it can start with a // valid state. If that fails, it returns the line with the // smallest indentation, which tends to need the least context to // parse correctly. function findStartLine(cm, n, precise) { var minindent, minline, doc = cm.doc; var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); for (var search = n; search > lim; --search) { if (search <= doc.first) { return doc.first } var line = getLine(doc, search - 1), after = line.stateAfter; if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier)) { return search } var indented = countColumn(line.text, null, cm.options.tabSize); if (minline == null || minindent > indented) { minline = search - 1; minindent = indented; } } return minline } function retreatFrontier(doc, n) { doc.modeFrontier = Math.min(doc.modeFrontier, n); if (doc.highlightFrontier < n - 10) { return } var start = doc.first; for (var line = n - 1; line > start; line--) { var saved = getLine(doc, line).stateAfter; // change is on 3 // state on line 1 looked ahead 2 -- so saw 3 // test 1 + 2 < 3 should cover this if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) { start = line + 1; break } } doc.highlightFrontier = Math.min(doc.highlightFrontier, start); } // Optimize some code when these features are not used. var sawReadOnlySpans = false, sawCollapsedSpans = false; function seeReadOnlySpans() { sawReadOnlySpans = true; } function seeCollapsedSpans() { sawCollapsedSpans = true; } // TEXTMARKER SPANS function MarkedSpan(marker, from, to) { this.marker = marker; this.from = from; this.to = to; } // Search an array of spans for a span matching the given marker. function getMarkedSpanFor(spans, marker) { if (spans) { for (var i = 0; i < spans.length; ++i) { var span = spans[i]; if (span.marker == marker) { return span } } } } // Remove a span from an array, returning undefined if no spans are // left (we don't store arrays for lines without spans). function removeMarkedSpan(spans, span) { var r; for (var i = 0; i < spans.length; ++i) { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } } return r } // Add a span to a line. function addMarkedSpan(line, span, op) { var inThisOp = op && window.WeakSet && (op.markedSpans || (op.markedSpans = new WeakSet)); if (inThisOp && line.markedSpans && inThisOp.has(line.markedSpans)) { line.markedSpans.push(span); } else { line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; if (inThisOp) { inThisOp.add(line.markedSpans); } } span.marker.attachLine(line); } // Used for the algorithm that adjusts markers for a change in the // document. These functions cut an array of spans at a given // character position, returning an array of remaining chunks (or // undefined if nothing remains). function markedSpansBefore(old, startCh, isInsert) { var nw; if (old) { for (var i = 0; i < old.length; ++i) { var span = old[i], marker = span.marker; var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh) ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); } } } return nw } function markedSpansAfter(old, endCh, isInsert) { var nw; if (old) { for (var i = 0; i < old.length; ++i) { var span = old[i], marker = span.marker; var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh) ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, span.to == null ? null : span.to - endCh)); } } } return nw } // Given a change object, compute the new set of marker spans that // cover the line in which the change took place. Removes spans // entirely within the change, reconnects spans belonging to the // same marker that appear on both sides of the change, and cuts off // spans partially within the change. Returns an array of span // arrays with one element for each line in (after) the change. function stretchSpansOverChange(doc, change) { if (change.full) { return null } var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; if (!oldFirst && !oldLast) { return null } var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; // Get the spans that 'stick out' on both sides var first = markedSpansBefore(oldFirst, startCh, isInsert); var last = markedSpansAfter(oldLast, endCh, isInsert); // Next, merge those two ends var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); if (first) { // Fix up .to properties of first for (var i = 0; i < first.length; ++i) { var span = first[i]; if (span.to == null) { var found = getMarkedSpanFor(last, span.marker); if (!found) { span.to = startCh; } else if (sameLine) { span.to = found.to == null ? null : found.to + offset; } } } } if (last) { // Fix up .from in last (or move them into first in case of sameLine) for (var i$1 = 0; i$1 < last.length; ++i$1) { var span$1 = last[i$1]; if (span$1.to != null) { span$1.to += offset; } if (span$1.from == null) { var found$1 = getMarkedSpanFor(first, span$1.marker); if (!found$1) { span$1.from = offset; if (sameLine) { (first || (first = [])).push(span$1); } } } else { span$1.from += offset; if (sameLine) { (first || (first = [])).push(span$1); } } } } // Make sure we didn't create any zero-length spans if (first) { first = clearEmptySpans(first); } if (last && last != first) { last = clearEmptySpans(last); } var newMarkers = [first]; if (!sameLine) { // Fill gap with whole-line-spans var gap = change.text.length - 2, gapMarkers; if (gap > 0 && first) { for (var i$2 = 0; i$2 < first.length; ++i$2) { if (first[i$2].to == null) { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } } for (var i$3 = 0; i$3 < gap; ++i$3) { newMarkers.push(gapMarkers); } newMarkers.push(last); } return newMarkers } // Remove spans that are empty and don't have a clearWhenEmpty // option of false. function clearEmptySpans(spans) { for (var i = 0; i < spans.length; ++i) { var span = spans[i]; if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) { spans.splice(i--, 1); } } if (!spans.length) { return null } return spans } // Used to 'clip' out readOnly ranges when making a change. function removeReadOnlyRanges(doc, from, to) { var markers = null; doc.iter(from.line, to.line + 1, function (line) { if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { var mark = line.markedSpans[i].marker; if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) { (markers || (markers = [])).push(mark); } } } }); if (!markers) { return null } var parts = [{from: from, to: to}]; for (var i = 0; i < markers.length; ++i) { var mk = markers[i], m = mk.find(0); for (var j = 0; j < parts.length; ++j) { var p = parts[j]; if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue } var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) { newParts.push({from: p.from, to: m.from}); } if (dto > 0 || !mk.inclusiveRight && !dto) { newParts.push({from: m.to, to: p.to}); } parts.splice.apply(parts, newParts); j += newParts.length - 3; } } return parts } // Connect or disconnect spans from a line. function detachMarkedSpans(line) { var spans = line.markedSpans; if (!spans) { return } for (var i = 0; i < spans.length; ++i) { spans[i].marker.detachLine(line); } line.markedSpans = null; } function attachMarkedSpans(line, spans) { if (!spans) { return } for (var i = 0; i < spans.length; ++i) { spans[i].marker.attachLine(line); } line.markedSpans = spans; } // Helpers used when computing which overlapping collapsed span // counts as the larger one. function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 } function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 } // Returns a number indicating which of two overlapping collapsed // spans is larger (and thus includes the other). Falls back to // comparing ids when the spans cover exactly the same range. function compareCollapsedMarkers(a, b) { var lenDiff = a.lines.length - b.lines.length; if (lenDiff != 0) { return lenDiff } var aPos = a.find(), bPos = b.find(); var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); if (fromCmp) { return -fromCmp } var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); if (toCmp) { return toCmp } return b.id - a.id } // Find out whether a line ends or starts in a collapsed span. If // so, return the marker for that span. function collapsedSpanAtSide(line, start) { var sps = sawCollapsedSpans && line.markedSpans, found; if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { sp = sps[i]; if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker; } } } return found } function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) } function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) } function collapsedSpanAround(line, ch) { var sps = sawCollapsedSpans && line.markedSpans, found; if (sps) { for (var i = 0; i < sps.length; ++i) { var sp = sps[i]; if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) && (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker; } } } return found } // Test whether there exists a collapsed span that partially // overlaps (covers the start or end, but not both) of a new span. // Such overlap is not allowed. function conflictingCollapsedRange(doc, lineNo, from, to, marker) { var line = getLine(doc, lineNo); var sps = sawCollapsedSpans && line.markedSpans; if (sps) { for (var i = 0; i < sps.length; ++i) { var sp = sps[i]; if (!sp.marker.collapsed) { continue } var found = sp.marker.find(0); var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue } if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) { return true } } } } // A visual line is a line as drawn on the screen. Folding, for // example, can cause multiple logical lines to appear on the same // visual line. This finds the start of the visual line that the // given line is part of (usually that is the line itself). function visualLine(line) { var merged; while (merged = collapsedSpanAtStart(line)) { line = merged.find(-1, true).line; } return line } function visualLineEnd(line) { var merged; while (merged = collapsedSpanAtEnd(line)) { line = merged.find(1, true).line; } return line } // Returns an array of logical lines that continue the visual line // started by the argument, or undefined if there are no such lines. function visualLineContinued(line) { var merged, lines; while (merged = collapsedSpanAtEnd(line)) { line = merged.find(1, true).line ;(lines || (lines = [])).push(line); } return lines } // Get the line number of the start of the visual line that the // given line number is part of. function visualLineNo(doc, lineN) { var line = getLine(doc, lineN), vis = visualLine(line); if (line == vis) { return lineN } return lineNo(vis) } // Get the line number of the start of the next visual line after // the given line. function visualLineEndNo(doc, lineN) { if (lineN > doc.lastLine()) { return lineN } var line = getLine(doc, lineN), merged; if (!lineIsHidden(doc, line)) { return lineN } while (merged = collapsedSpanAtEnd(line)) { line = merged.find(1, true).line; } return lineNo(line) + 1 } // Compute whether a line is hidden. Lines count as hidden when they // are part of a visual line that starts with another line, or when // they are entirely covered by collapsed, non-widget span. function lineIsHidden(doc, line) { var sps = sawCollapsedSpans && line.markedSpans; if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { sp = sps[i]; if (!sp.marker.collapsed) { continue } if (sp.from == null) { return true } if (sp.marker.widgetNode) { continue } if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) { return true } } } } function lineIsHiddenInner(doc, line, span) { if (span.to == null) { var end = span.marker.find(1, true); return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)) } if (span.marker.inclusiveRight && span.to == line.text.length) { return true } for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) { sp = line.markedSpans[i]; if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && (sp.to == null || sp.to != span.from) && (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && lineIsHiddenInner(doc, line, sp)) { return true } } } // Find the height above the given line. function heightAtLine(lineObj) { lineObj = visualLine(lineObj); var h = 0, chunk = lineObj.parent; for (var i = 0; i < chunk.lines.length; ++i) { var line = chunk.lines[i]; if (line == lineObj) { break } else { h += line.height; } } for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { for (var i$1 = 0; i$1 < p.children.length; ++i$1) { var cur = p.children[i$1]; if (cur == chunk) { break } else { h += cur.height; } } } return h } // Compute the character length of a line, taking into account // collapsed ranges (see markText) that might hide parts, and join // other lines onto it. function lineLength(line) { if (line.height == 0) { return 0 } var len = line.text.length, merged, cur = line; while (merged = collapsedSpanAtStart(cur)) { var found = merged.find(0, true); cur = found.from.line; len += found.from.ch - found.to.ch; } cur = line; while (merged = collapsedSpanAtEnd(cur)) { var found$1 = merged.find(0, true); len -= cur.text.length - found$1.from.ch; cur = found$1.to.line; len += cur.text.length - found$1.to.ch; } return len } // Find the longest line in the document. function findMaxLine(cm) { var d = cm.display, doc = cm.doc; d.maxLine = getLine(doc, doc.first); d.maxLineLength = lineLength(d.maxLine); d.maxLineChanged = true; doc.iter(function (line) { var len = lineLength(line); if (len > d.maxLineLength) { d.maxLineLength = len; d.maxLine = line; } }); } // LINE DATA STRUCTURE // Line objects. These hold state related to a line, including // highlighting info (the styles array). var Line = function(text, markedSpans, estimateHeight) { this.text = text; attachMarkedSpans(this, markedSpans); this.height = estimateHeight ? estimateHeight(this) : 1; }; Line.prototype.lineNo = function () { return lineNo(this) }; eventMixin(Line); // Change the content (text, markers) of a line. Automatically // invalidates cached information and tries to re-estimate the // line's height. function updateLine(line, text, markedSpans, estimateHeight) { line.text = text; if (line.stateAfter) { line.stateAfter = null; } if (line.styles) { line.styles = null; } if (line.order != null) { line.order = null; } detachMarkedSpans(line); attachMarkedSpans(line, markedSpans); var estHeight = estimateHeight ? estimateHeight(line) : 1; if (estHeight != line.height) { updateLineHeight(line, estHeight); } } // Detach a line from the document tree and its markers. function cleanUpLine(line) { line.parent = null; detachMarkedSpans(line); } // Convert a style as returned by a mode (either null, or a string // containing one or more styles) to a CSS style. This is cached, // and also looks for line-wide styles. var styleToClassCache = {}, styleToClassCacheWithMode = {}; function interpretTokenStyle(style, options) { if (!style || /^\s*$/.test(style)) { return null } var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; return cache[style] || (cache[style] = style.replace(/\S+/g, "cm-$&")) } // Render the DOM representation of the text of a line. Also builds // up a 'line map', which points at the DOM nodes that represent // specific stretches of text, and is used by the measuring code. // The returned object contains the DOM node, this map, and // information about line-wide styles that were set by the mode. function buildLineContent(cm, lineView) { // The padding-right forces the element to have a 'border', which // is needed on Webkit to be able to get line-level bounding // rectangles for it (in measureChar). var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null); var builder = {pre: eltP("pre", [content], "CodeMirror-line"), content: content, col: 0, pos: 0, cm: cm, trailingSpace: false, splitSpaces: cm.getOption("lineWrapping")}; lineView.measure = {}; // Iterate over the logical lines that make up this visual line. for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0); builder.pos = 0; builder.addToken = buildToken; // Optionally wire in some hacks into the token-rendering // algorithm, to deal with browser quirks. if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction))) { builder.addToken = buildTokenBadBidi(builder.addToken, order); } builder.map = []; var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); if (line.styleClasses) { if (line.styleClasses.bgClass) { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); } if (line.styleClasses.textClass) { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); } } // Ensure at least a single node is present, for measuring. if (builder.map.length == 0) { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); } // Store the map and a cache object for the current logical line if (i == 0) { lineView.measure.map = builder.map; lineView.measure.cache = {}; } else { (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map) ;(lineView.measure.caches || (lineView.measure.caches = [])).push({}); } } // See issue #2901 if (webkit) { var last = builder.content.lastChild; if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab"))) { builder.content.className = "cm-tab-wrap-hack"; } } signal(cm, "renderLine", cm, lineView.line, builder.pre); if (builder.pre.className) { builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); } return builder } function defaultSpecialCharPlaceholder(ch) { var token = elt("span", "\u2022", "cm-invalidchar"); token.title = "\\u" + ch.charCodeAt(0).toString(16); token.setAttribute("aria-label", token.title); return token } // Build up the DOM representation for a single token, and add it to // the line map. Takes care to render special characters separately. function buildToken(builder, text, style, startStyle, endStyle, css, attributes) { if (!text) { return } var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text; var special = builder.cm.state.specialChars, mustWrap = false; var content; if (!special.test(text)) { builder.col += text.length; content = document.createTextNode(displayText); builder.map.push(builder.pos, builder.pos + text.length, content); if (ie && ie_version < 9) { mustWrap = true; } builder.pos += text.length; } else { content = document.createDocumentFragment(); var pos = 0; while (true) { special.lastIndex = pos; var m = special.exec(text); var skipped = m ? m.index - pos : text.length - pos; if (skipped) { var txt = document.createTextNode(displayText.slice(pos, pos + skipped)); if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])); } else { content.appendChild(txt); } builder.map.push(builder.pos, builder.pos + skipped, txt); builder.col += skipped; builder.pos += skipped; } if (!m) { break } pos += skipped + 1; var txt$1 = (void 0); if (m[0] == "\t") { var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); txt$1.setAttribute("role", "presentation"); txt$1.setAttribute("cm-text", "\t"); builder.col += tabWidth; } else if (m[0] == "\r" || m[0] == "\n") { txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")); txt$1.setAttribute("cm-text", m[0]); builder.col += 1; } else { txt$1 = builder.cm.options.specialCharPlaceholder(m[0]); txt$1.setAttribute("cm-text", m[0]); if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])); } else { content.appendChild(txt$1); } builder.col += 1; } builder.map.push(builder.pos, builder.pos + 1, txt$1); builder.pos++; } } builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32; if (style || startStyle || endStyle || mustWrap || css || attributes) { var fullStyle = style || ""; if (startStyle) { fullStyle += startStyle; } if (endStyle) { fullStyle += endStyle; } var token = elt("span", [content], fullStyle, css); if (attributes) { for (var attr in attributes) { if (attributes.hasOwnProperty(attr) && attr != "style" && attr != "class") { token.setAttribute(attr, attributes[attr]); } } } return builder.content.appendChild(token) } builder.content.appendChild(content); } // Change some spaces to NBSP to prevent the browser from collapsing // trailing spaces at the end of a line when rendering text (issue #1362). function splitSpaces(text, trailingBefore) { if (text.length > 1 && !/ /.test(text)) { return text } var spaceBefore = trailingBefore, result = ""; for (var i = 0; i < text.length; i++) { var ch = text.charAt(i); if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32)) { ch = "\u00a0"; } result += ch; spaceBefore = ch == " "; } return result } // Work around nonsense dimensions being reported for stretches of // right-to-left text. function buildTokenBadBidi(inner, order) { return function (builder, text, style, startStyle, endStyle, css, attributes) { style = style ? style + " cm-force-border" : "cm-force-border"; var start = builder.pos, end = start + text.length; for (;;) { // Find the part that overlaps with the start of this text var part = (void 0); for (var i = 0; i < order.length; i++) { part = order[i]; if (part.to > start && part.from <= start) { break } } if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, css, attributes) } inner(builder, text.slice(0, part.to - start), style, startStyle, null, css, attributes); startStyle = null; text = text.slice(part.to - start); start = part.to; } } } function buildCollapsedSpan(builder, size, marker, ignoreWidget) { var widget = !ignoreWidget && marker.widgetNode; if (widget) { builder.map.push(builder.pos, builder.pos + size, widget); } if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { if (!widget) { widget = builder.content.appendChild(document.createElement("span")); } widget.setAttribute("cm-marker", marker.id); } if (widget) { builder.cm.display.input.setUneditable(widget); builder.content.appendChild(widget); } builder.pos += size; builder.trailingSpace = false; } // Outputs a number of spans to make up a line, taking highlighting // and marked text into account. function insertLineContent(line, builder, styles) { var spans = line.markedSpans, allText = line.text, at = 0; if (!spans) { for (var i$1 = 1; i$1 < styles.length; i$1+=2) { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)); } return } var len = allText.length, pos = 0, i = 1, text = "", style, css; var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed, attributes; for (;;) { if (nextChange == pos) { // Update current marker set spanStyle = spanEndStyle = spanStartStyle = css = ""; attributes = null; collapsed = null; nextChange = Infinity; var foundBookmarks = [], endStyles = (void 0); for (var j = 0; j < spans.length; ++j) { var sp = spans[j], m = sp.marker; if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { foundBookmarks.push(m); } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { if (sp.to != null && sp.to != pos && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; } if (m.className) { spanStyle += " " + m.className; } if (m.css) { css = (css ? css + ";" : "") + m.css; } if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle; } if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to); } // support for the old title property // https://github.com/codemirror/CodeMirror/pull/5673 if (m.title) { (attributes || (attributes = {})).title = m.title; } if (m.attributes) { for (var attr in m.attributes) { (attributes || (attributes = {}))[attr] = m.attributes[attr]; } } if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) { collapsed = sp; } } else if (sp.from > pos && nextChange > sp.from) { nextChange = sp.from; } } if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2) { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1]; } } } if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2) { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]); } } if (collapsed && (collapsed.from || 0) == pos) { buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, collapsed.marker, collapsed.from == null); if (collapsed.to == null) { return } if (collapsed.to == pos) { collapsed = false; } } } if (pos >= len) { break } var upto = Math.min(len, nextChange); while (true) { if (text) { var end = pos + text.length; if (!collapsed) { var tokenText = end > upto ? text.slice(0, upto - pos) : text; builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", css, attributes); } if (end >= upto) {text = text.slice(upto - pos); pos = upto; break} pos = end; spanStartStyle = ""; } text = allText.slice(at, at = styles[i++]); style = interpretTokenStyle(styles[i++], builder.cm.options); } } } // These objects are used to represent the visible (currently drawn) // part of the document. A LineView may correspond to multiple // logical lines, if those are connected by collapsed ranges. function LineView(doc, line, lineN) { // The starting line this.line = line; // Continuing lines, if any this.rest = visualLineContinued(line); // Number of logical lines in this visual line this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1; this.node = this.text = null; this.hidden = lineIsHidden(doc, line); } // Create a range of LineView objects for the given lines. function buildViewArray(cm, from, to) { var array = [], nextPos; for (var pos = from; pos < to; pos = nextPos) { var view = new LineView(cm.doc, getLine(cm.doc, pos), pos); nextPos = pos + view.size; array.push(view); } return array } var operationGroup = null; function pushOperation(op) { if (operationGroup) { operationGroup.ops.push(op); } else { op.ownsGroup = operationGroup = { ops: [op], delayedCallbacks: [] }; } } function fireCallbacksForOps(group) { // Calls delayed callbacks and cursorActivity handlers until no // new ones appear var callbacks = group.delayedCallbacks, i = 0; do { for (; i < callbacks.length; i++) { callbacks[i].call(null); } for (var j = 0; j < group.ops.length; j++) { var op = group.ops[j]; if (op.cursorActivityHandlers) { while (op.cursorActivityCalled < op.cursorActivityHandlers.length) { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); } } } } while (i < callbacks.length) } function finishOperation(op, endCb) { var group = op.ownsGroup; if (!group) { return } try { fireCallbacksForOps(group); } finally { operationGroup = null; endCb(group); } } var orphanDelayedCallbacks = null; // Often, we want to signal events at a point where we are in the // middle of some work, but don't want the handler to start calling // other methods on the editor, which might be in an inconsistent // state or simply not expect any other events to happen. // signalLater looks whether there are any handlers, and schedules // them to be executed when the last operation ends, or, if no // operation is active, when a timeout fires. function signalLater(emitter, type /*, values...*/) { var arr = getHandlers(emitter, type); if (!arr.length) { return } var args = Array.prototype.slice.call(arguments, 2), list; if (operationGroup) { list = operationGroup.delayedCallbacks; } else if (orphanDelayedCallbacks) { list = orphanDelayedCallbacks; } else { list = orphanDelayedCallbacks = []; setTimeout(fireOrphanDelayed, 0); } var loop = function ( i ) { list.push(function () { return arr[i].apply(null, args); }); }; for (var i = 0; i < arr.length; ++i) loop( i ); } function fireOrphanDelayed() { var delayed = orphanDelayedCallbacks; orphanDelayedCallbacks = null; for (var i = 0; i < delayed.length; ++i) { delayed[i](); } } // When an aspect of a line changes, a string is added to // lineView.changes. This updates the relevant part of the line's // DOM structure. function updateLineForChanges(cm, lineView, lineN, dims) { for (var j = 0; j < lineView.changes.length; j++) { var type = lineView.changes[j]; if (type == "text") { updateLineText(cm, lineView); } else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims); } else if (type == "class") { updateLineClasses(cm, lineView); } else if (type == "widget") { updateLineWidgets(cm, lineView, dims); } } lineView.changes = null; } // Lines with gutter elements, widgets or a background class need to // be wrapped, and have the extra elements added to the wrapper div function ensureLineWrapped(lineView) { if (lineView.node == lineView.text) { lineView.node = elt("div", null, null, "position: relative"); if (lineView.text.parentNode) { lineView.text.parentNode.replaceChild(lineView.node, lineView.text); } lineView.node.appendChild(lineView.text); if (ie && ie_version < 8) { lineView.node.style.zIndex = 2; } } return lineView.node } function updateLineBackground(cm, lineView) { var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass; if (cls) { cls += " CodeMirror-linebackground"; } if (lineView.background) { if (cls) { lineView.background.className = cls; } else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; } } else if (cls) { var wrap = ensureLineWrapped(lineView); lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild); cm.display.input.setUneditable(lineView.background); } } // Wrapper around buildLineContent which will reuse the structure // in display.externalMeasured when possible. function getLineContent(cm, lineView) { var ext = cm.display.externalMeasured; if (ext && ext.line == lineView.line) { cm.display.externalMeasured = null; lineView.measure = ext.measure; return ext.built } return buildLineContent(cm, lineView) } // Redraw the line's text. Interacts with the background and text // classes because the mode may output tokens that influence these // classes. function updateLineText(cm, lineView) { var cls = lineView.text.className; var built = getLineContent(cm, lineView); if (lineView.text == lineView.node) { lineView.node = built.pre; } lineView.text.parentNode.replaceChild(built.pre, lineView.text); lineView.text = built.pre; if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { lineView.bgClass = built.bgClass; lineView.textClass = built.textClass; updateLineClasses(cm, lineView); } else if (cls) { lineView.text.className = cls; } } function updateLineClasses(cm, lineView) { updateLineBackground(cm, lineView); if (lineView.line.wrapClass) { ensureLineWrapped(lineView).className = lineView.line.wrapClass; } else if (lineView.node != lineView.text) { lineView.node.className = ""; } var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass; lineView.text.className = textClass || ""; } function updateLineGutter(cm, lineView, lineN, dims) { if (lineView.gutter) { lineView.node.removeChild(lineView.gutter); lineView.gutter = null; } if (lineView.gutterBackground) { lineView.node.removeChild(lineView.gutterBackground); lineView.gutterBackground = null; } if (lineView.line.gutterClass) { var wrap = ensureLineWrapped(lineView); lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px")); cm.display.input.setUneditable(lineView.gutterBackground); wrap.insertBefore(lineView.gutterBackground, lineView.text); } var markers = lineView.line.gutterMarkers; if (cm.options.lineNumbers || markers) { var wrap$1 = ensureLineWrapped(lineView); var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px")); gutterWrap.setAttribute("aria-hidden", "true"); cm.display.input.setUneditable(gutterWrap); wrap$1.insertBefore(gutterWrap, lineView.text); if (lineView.line.gutterClass) { gutterWrap.className += " " + lineView.line.gutterClass; } if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) { lineView.lineNumber = gutterWrap.appendChild( elt("div", lineNumberFor(cm.options, lineN), "CodeMirror-linenumber CodeMirror-gutter-elt", ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))); } if (markers) { for (var k = 0; k < cm.display.gutterSpecs.length; ++k) { var id = cm.display.gutterSpecs[k].className, found = markers.hasOwnProperty(id) && markers[id]; if (found) { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))); } } } } } function updateLineWidgets(cm, lineView, dims) { if (lineView.alignable) { lineView.alignable = null; } var isWidget = classTest("CodeMirror-linewidget"); for (var node = lineView.node.firstChild, next = (void 0); node; node = next) { next = node.nextSibling; if (isWidget.test(node.className)) { lineView.node.removeChild(node); } } insertLineWidgets(cm, lineView, dims); } // Build a line's DOM representation from scratch function buildLineElement(cm, lineView, lineN, dims) { var built = getLineContent(cm, lineView); lineView.text = lineView.node = built.pre; if (built.bgClass) { lineView.bgClass = built.bgClass; } if (built.textClass) { lineView.textClass = built.textClass; } updateLineClasses(cm, lineView); updateLineGutter(cm, lineView, lineN, dims); insertLineWidgets(cm, lineView, dims); return lineView.node } // A lineView may contain multiple logical lines (when merged by // collapsed spans). The widgets for all of them need to be drawn. function insertLineWidgets(cm, lineView, dims) { insertLineWidgetsFor(cm, lineView.line, lineView, dims, true); if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); } } } function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { if (!line.widgets) { return } var wrap = ensureLineWrapped(lineView); for (var i = 0, ws = line.widgets; i < ws.length; ++i) { var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget" + (widget.className ? " " + widget.className : "")); if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true"); } positionLineWidget(widget, node, lineView, dims); cm.display.input.setUneditable(node); if (allowAbove && widget.above) { wrap.insertBefore(node, lineView.gutter || lineView.text); } else { wrap.appendChild(node); } signalLater(widget, "redraw"); } } function positionLineWidget(widget, node, lineView, dims) { if (widget.noHScroll) { (lineView.alignable || (lineView.alignable = [])).push(node); var width = dims.wrapperWidth; node.style.left = dims.fixedPos + "px"; if (!widget.coverGutter) { width -= dims.gutterTotalWidth; node.style.paddingLeft = dims.gutterTotalWidth + "px"; } node.style.width = width + "px"; } if (widget.coverGutter) { node.style.zIndex = 5; node.style.position = "relative"; if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px"; } } } function widgetHeight(widget) { if (widget.height != null) { return widget.height } var cm = widget.doc.cm; if (!cm) { return 0 } if (!contains(document.body, widget.node)) { var parentStyle = "position: relative;"; if (widget.coverGutter) { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; } if (widget.noHScroll) { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; } removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)); } return widget.height = widget.node.parentNode.offsetHeight } // Return true when the given mouse event happened in a widget function eventInWidget(display, e) { for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || (n.parentNode == display.sizer && n != display.mover)) { return true } } } // POSITION MEASUREMENT function paddingTop(display) {return display.lineSpace.offsetTop} function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight} function paddingH(display) { if (display.cachedPaddingH) { return display.cachedPaddingH } var e = removeChildrenAndAdd(display.measure, elt("pre", "x", "CodeMirror-line-like")); var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}; if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data; } return data } function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth } function displayWidth(cm) { return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth } function displayHeight(cm) { return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight } // Ensure the lineView.wrapping.heights array is populated. This is // an array of bottom offsets for the lines that make up a drawn // line. When lineWrapping is on, there might be more than one // height. function ensureLineHeights(cm, lineView, rect) { var wrapping = cm.options.lineWrapping; var curWidth = wrapping && displayWidth(cm); if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { var heights = lineView.measure.heights = []; if (wrapping) { lineView.measure.width = curWidth; var rects = lineView.text.firstChild.getClientRects(); for (var i = 0; i < rects.length - 1; i++) { var cur = rects[i], next = rects[i + 1]; if (Math.abs(cur.bottom - next.bottom) > 2) { heights.push((cur.bottom + next.top) / 2 - rect.top); } } } heights.push(rect.bottom - rect.top); } } // Find a line map (mapping character offsets to text nodes) and a // measurement cache for the given line number. (A line view might // contain multiple lines when collapsed ranges are present.) function mapFromLineView(lineView, line, lineN) { if (lineView.line == line) { return {map: lineView.measure.map, cache: lineView.measure.cache} } if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) { if (lineView.rest[i] == line) { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } } for (var i$1 = 0; i$1 < lineView.rest.length; i$1++) { if (lineNo(lineView.rest[i$1]) > lineN) { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } } } } // Render a line into the hidden node display.externalMeasured. Used // when measurement is needed for a line that's not in the viewport. function updateExternalMeasurement(cm, line) { line = visualLine(line); var lineN = lineNo(line); var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN); view.lineN = lineN; var built = view.built = buildLineContent(cm, view); view.text = built.pre; removeChildrenAndAdd(cm.display.lineMeasure, built.pre); return view } // Get a {top, bottom, left, right} box (in line-local coordinates) // for a given character. function measureChar(cm, line, ch, bias) { return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias) } // Find a line view that corresponds to the given line number. function findViewForLine(cm, lineN) { if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) { return cm.display.view[findViewIndex(cm, lineN)] } var ext = cm.display.externalMeasured; if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) { return ext } } // Measurement can be split in two steps, the set-up work that // applies to the whole line, and the measurement of the actual // character. Functions like coordsChar, that need to do a lot of // measurements in a row, can thus ensure that the set-up work is // only done once. function prepareMeasureForLine(cm, line) { var lineN = lineNo(line); var view = findViewForLine(cm, lineN); if (view && !view.text) { view = null; } else if (view && view.changes) { updateLineForChanges(cm, view, lineN, getDimensions(cm)); cm.curOp.forceUpdate = true; } if (!view) { view = updateExternalMeasurement(cm, line); } var info = mapFromLineView(view, line, lineN); return { line: line, view: view, rect: null, map: info.map, cache: info.cache, before: info.before, hasHeights: false } } // Given a prepared measurement object, measures the position of an // actual character (or fetches it from the cache). function measureCharPrepared(cm, prepared, ch, bias, varHeight) { if (prepared.before) { ch = -1; } var key = ch + (bias || ""), found; if (prepared.cache.hasOwnProperty(key)) { found = prepared.cache[key]; } else { if (!prepared.rect) { prepared.rect = prepared.view.text.getBoundingClientRect(); } if (!prepared.hasHeights) { ensureLineHeights(cm, prepared.view, prepared.rect); prepared.hasHeights = true; } found = measureCharInner(cm, prepared, ch, bias); if (!found.bogus) { prepared.cache[key] = found; } } return {left: found.left, right: found.right, top: varHeight ? found.rtop : found.top, bottom: varHeight ? found.rbottom : found.bottom} } var nullRect = {left: 0, right: 0, top: 0, bottom: 0}; function nodeAndOffsetInLineMap(map, ch, bias) { var node, start, end, collapse, mStart, mEnd; // First, search the line map for the text node corresponding to, // or closest to, the target character. for (var i = 0; i < map.length; i += 3) { mStart = map[i]; mEnd = map[i + 1]; if (ch < mStart) { start = 0; end = 1; collapse = "left"; } else if (ch < mEnd) { start = ch - mStart; end = start + 1; } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) { end = mEnd - mStart; start = end - 1; if (ch >= mEnd) { collapse = "right"; } } if (start != null) { node = map[i + 2]; if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) { collapse = bias; } if (bias == "left" && start == 0) { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) { node = map[(i -= 3) + 2]; collapse = "left"; } } if (bias == "right" && start == mEnd - mStart) { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) { node = map[(i += 3) + 2]; collapse = "right"; } } break } } return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd} } function getUsefulRect(rects, bias) { var rect = nullRect; if (bias == "left") { for (var i = 0; i < rects.length; i++) { if ((rect = rects[i]).left != rect.right) { break } } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) { if ((rect = rects[i$1]).left != rect.right) { break } } } return rect } function measureCharInner(cm, prepared, ch, bias) { var place = nodeAndOffsetInLineMap(prepared.map, ch, bias); var node = place.node, start = place.start, end = place.end, collapse = place.collapse; var rect; if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start; } while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end; } if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) { rect = node.parentNode.getBoundingClientRect(); } else { rect = getUsefulRect(range(node, start, end).getClientRects(), bias); } if (rect.left || rect.right || start == 0) { break } end = start; start = start - 1; collapse = "right"; } if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect); } } else { // If it is a widget, simply get the box for the whole widget. if (start > 0) { collapse = bias = "right"; } var rects; if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) { rect = rects[bias == "right" ? rects.length - 1 : 0]; } else { rect = node.getBoundingClientRect(); } } if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { var rSpan = node.parentNode.getClientRects()[0]; if (rSpan) { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; } else { rect = nullRect; } } var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; var mid = (rtop + rbot) / 2; var heights = prepared.view.measure.heights; var i = 0; for (; i < heights.length - 1; i++) { if (mid < heights[i]) { break } } var top = i ? heights[i - 1] : 0, bot = heights[i]; var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, top: top, bottom: bot}; if (!rect.left && !rect.right) { result.bogus = true; } if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } return result } // Work around problem with bounding client rects on ranges being // returned incorrectly when zoomed on IE10 and below. function maybeUpdateRectForZooming(measure, rect) { if (!window.screen || screen.logicalXDPI == null || screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) { return rect } var scaleX = screen.logicalXDPI / screen.deviceXDPI; var scaleY = screen.logicalYDPI / screen.deviceYDPI; return {left: rect.left * scaleX, right: rect.right * scaleX, top: rect.top * scaleY, bottom: rect.bottom * scaleY} } function clearLineMeasurementCacheFor(lineView) { if (lineView.measure) { lineView.measure.cache = {}; lineView.measure.heights = null; if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) { lineView.measure.caches[i] = {}; } } } } function clearLineMeasurementCache(cm) { cm.display.externalMeasure = null; removeChildren(cm.display.lineMeasure); for (var i = 0; i < cm.display.view.length; i++) { clearLineMeasurementCacheFor(cm.display.view[i]); } } function clearCaches(cm) { clearLineMeasurementCache(cm); cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true; } cm.display.lineNumChars = null; } function pageScrollX(doc) { // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206 // which causes page_Offset and bounding client rects to use // different reference viewports and invalidate our calculations. if (chrome && android) { return -(doc.body.getBoundingClientRect().left - parseInt(getComputedStyle(doc.body).marginLeft)) } return doc.defaultView.pageXOffset || (doc.documentElement || doc.body).scrollLeft } function pageScrollY(doc) { if (chrome && android) { return -(doc.body.getBoundingClientRect().top - parseInt(getComputedStyle(doc.body).marginTop)) } return doc.defaultView.pageYOffset || (doc.documentElement || doc.body).scrollTop } function widgetTopHeight(lineObj) { var ref = visualLine(lineObj); var widgets = ref.widgets; var height = 0; if (widgets) { for (var i = 0; i < widgets.length; ++i) { if (widgets[i].above) { height += widgetHeight(widgets[i]); } } } return height } // Converts a {top, bottom, left, right} box from line-local // coordinates into another coordinate system. Context may be one of // "line", "div" (display.lineDiv), "local"./null (editor), "window", // or "page". function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) { if (!includeWidgets) { var height = widgetTopHeight(lineObj); rect.top += height; rect.bottom += height; } if (context == "line") { return rect } if (!context) { context = "local"; } var yOff = heightAtLine(lineObj); if (context == "local") { yOff += paddingTop(cm.display); } else { yOff -= cm.display.viewOffset; } if (context == "page" || context == "window") { var lOff = cm.display.lineSpace.getBoundingClientRect(); yOff += lOff.top + (context == "window" ? 0 : pageScrollY(doc(cm))); var xOff = lOff.left + (context == "window" ? 0 : pageScrollX(doc(cm))); rect.left += xOff; rect.right += xOff; } rect.top += yOff; rect.bottom += yOff; return rect } // Coverts a box from "div" coords to another coordinate system. // Context may be "window", "page", "div", or "local"./null. function fromCoordSystem(cm, coords, context) { if (context == "div") { return coords } var left = coords.left, top = coords.top; // First move into "page" coordinate system if (context == "page") { left -= pageScrollX(doc(cm)); top -= pageScrollY(doc(cm)); } else if (context == "local" || !context) { var localBox = cm.display.sizer.getBoundingClientRect(); left += localBox.left; top += localBox.top; } var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect(); return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top} } function charCoords(cm, pos, context, lineObj, bias) { if (!lineObj) { lineObj = getLine(cm.doc, pos.line); } return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context) } // Returns a box for a given cursor position, which may have an // 'other' property containing the position of the secondary cursor // on a bidi boundary. // A cursor Pos(line, char, "before") is on the same visual line as `char - 1` // and after `char - 1` in writing order of `char - 1` // A cursor Pos(line, char, "after") is on the same visual line as `char` // and before `char` in writing order of `char` // Examples (upper-case letters are RTL, lower-case are LTR): // Pos(0, 1, ...) // before after // ab a|b a|b // aB a|B aB| // Ab |Ab A|b // AB B|A B|A // Every position after the last character on a line is considered to stick // to the last character on the line. function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { lineObj = lineObj || getLine(cm.doc, pos.line); if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); } function get(ch, right) { var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight); if (right) { m.left = m.right; } else { m.right = m.left; } return intoCoordSystem(cm, lineObj, m, context) } var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky; if (ch >= lineObj.text.length) { ch = lineObj.text.length; sticky = "before"; } else if (ch <= 0) { ch = 0; sticky = "after"; } if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") } function getBidi(ch, partPos, invert) { var part = order[partPos], right = part.level == 1; return get(invert ? ch - 1 : ch, right != invert) } var partPos = getBidiPartAt(order, ch, sticky); var other = bidiOther; var val = getBidi(ch, partPos, sticky == "before"); if (other != null) { val.other = getBidi(ch, other, sticky != "before"); } return val } // Used to cheaply estimate the coordinates for a position. Used for // intermediate scroll updates. function estimateCoords(cm, pos) { var left = 0; pos = clipPos(cm.doc, pos); if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch; } var lineObj = getLine(cm.doc, pos.line); var top = heightAtLine(lineObj) + paddingTop(cm.display); return {left: left, right: left, top: top, bottom: top + lineObj.height} } // Positions returned by coordsChar contain some extra information. // xRel is the relative x position of the input coordinates compared // to the found position (so xRel > 0 means the coordinates are to // the right of the character position, for example). When outside // is true, that means the coordinates lie outside the line's // vertical range. function PosWithInfo(line, ch, sticky, outside, xRel) { var pos = Pos(line, ch, sticky); pos.xRel = xRel; if (outside) { pos.outside = outside; } return pos } // Compute the character position closest to the given coordinates. // Input must be lineSpace-local ("div" coordinate system). function coordsChar(cm, x, y) { var doc = cm.doc; y += cm.display.viewOffset; if (y < 0) { return PosWithInfo(doc.first, 0, null, -1, -1) } var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1; if (lineN > last) { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, 1, 1) } if (x < 0) { x = 0; } var lineObj = getLine(doc, lineN); for (;;) { var found = coordsCharInner(cm, lineObj, lineN, x, y); var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 || found.outside > 0 ? 1 : 0)); if (!collapsed) { return found } var rangeEnd = collapsed.find(1); if (rangeEnd.line == lineN) { return rangeEnd } lineObj = getLine(doc, lineN = rangeEnd.line); } } function wrappedLineExtent(cm, lineObj, preparedMeasure, y) { y -= widgetTopHeight(lineObj); var end = lineObj.text.length; var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0); end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end); return {begin: begin, end: end} } function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) { if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); } var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top; return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop) } // Returns true if the given side of a box is after the given // coordinates, in top-to-bottom, left-to-right order. function boxIsAfter(box, x, y, left) { return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x } function coordsCharInner(cm, lineObj, lineNo, x, y) { // Move y into line-local coordinate space y -= heightAtLine(lineObj); var preparedMeasure = prepareMeasureForLine(cm, lineObj); // When directly calling `measureCharPrepared`, we have to adjust // for the widgets at this line. var widgetHeight = widgetTopHeight(lineObj); var begin = 0, end = lineObj.text.length, ltr = true; var order = getOrder(lineObj, cm.doc.direction); // If the line isn't plain left-to-right text, first figure out // which bidi section the coordinates fall into. if (order) { var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart) (cm, lineObj, lineNo, preparedMeasure, order, x, y); ltr = part.level != 1; // The awkward -1 offsets are needed because findFirst (called // on these below) will treat its first bound as inclusive, // second as exclusive, but we want to actually address the // characters in the part's range begin = ltr ? part.from : part.to - 1; end = ltr ? part.to : part.from - 1; } // A binary search to find the first character whose bounding box // starts after the coordinates. If we run across any whose box wrap // the coordinates, store that. var chAround = null, boxAround = null; var ch = findFirst(function (ch) { var box = measureCharPrepared(cm, preparedMeasure, ch); box.top += widgetHeight; box.bottom += widgetHeight; if (!boxIsAfter(box, x, y, false)) { return false } if (box.top <= y && box.left <= x) { chAround = ch; boxAround = box; } return true }, begin, end); var baseX, sticky, outside = false; // If a box around the coordinates was found, use that if (boxAround) { // Distinguish coordinates nearer to the left or right side of the box var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr; ch = chAround + (atStart ? 0 : 1); sticky = atStart ? "after" : "before"; baseX = atLeft ? boxAround.left : boxAround.right; } else { // (Adjust for extended bound, if necessary.) if (!ltr && (ch == end || ch == begin)) { ch++; } // To determine which side to associate with, get the box to the // left of the character and compare it's vertical position to the // coordinates sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" : (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight <= y) == ltr ? "after" : "before"; // Now get accurate coordinates for this place, in order to get a // base X position var coords = cursorCoords(cm, Pos(lineNo, ch, sticky), "line", lineObj, preparedMeasure); baseX = coords.left; outside = y < coords.top ? -1 : y >= coords.bottom ? 1 : 0; } ch = skipExtendingChars(lineObj.text, ch, 1); return PosWithInfo(lineNo, ch, sticky, outside, x - baseX) } function coordsBidiPart(cm, lineObj, lineNo, preparedMeasure, order, x, y) { // Bidi parts are sorted left-to-right, and in a non-line-wrapping // situation, we can take this ordering to correspond to the visual // ordering. This finds the first part whose end is after the given // coordinates. var index = findFirst(function (i) { var part = order[i], ltr = part.level != 1; return boxIsAfter(cursorCoords(cm, Pos(lineNo, ltr ? part.to : part.from, ltr ? "before" : "after"), "line", lineObj, preparedMeasure), x, y, true) }, 0, order.length - 1); var part = order[index]; // If this isn't the first part, the part's start is also after // the coordinates, and the coordinates aren't on the same line as // that start, move one part back. if (index > 0) { var ltr = part.level != 1; var start = cursorCoords(cm, Pos(lineNo, ltr ? part.from : part.to, ltr ? "after" : "before"), "line", lineObj, preparedMeasure); if (boxIsAfter(start, x, y, true) && start.top > y) { part = order[index - 1]; } } return part } function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) { // In a wrapped line, rtl text on wrapping boundaries can do things // that don't correspond to the ordering in our `order` array at // all, so a binary search doesn't work, and we want to return a // part that only spans one line so that the binary search in // coordsCharInner is safe. As such, we first find the extent of the // wrapped line, and then do a flat search in which we discard any // spans that aren't on the line. var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y); var begin = ref.begin; var end = ref.end; if (/\s/.test(lineObj.text.charAt(end - 1))) { end--; } var part = null, closestDist = null; for (var i = 0; i < order.length; i++) { var p = order[i]; if (p.from >= end || p.to <= begin) { continue } var ltr = p.level != 1; var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right; // Weigh against spans ending before this, so that they are only // picked if nothing ends after var dist = endX < x ? x - endX + 1e9 : endX - x; if (!part || closestDist > dist) { part = p; closestDist = dist; } } if (!part) { part = order[order.length - 1]; } // Clip the part to the wrapped line. if (part.from < begin) { part = {from: begin, to: part.to, level: part.level}; } if (part.to > end) { part = {from: part.from, to: end, level: part.level}; } return part } var measureText; // Compute the default text height. function textHeight(display) { if (display.cachedTextHeight != null) { return display.cachedTextHeight } if (measureText == null) { measureText = elt("pre", null, "CodeMirror-line-like"); // Measure a bunch of lines, for browsers that compute // fractional heights. for (var i = 0; i < 49; ++i) { measureText.appendChild(document.createTextNode("x")); measureText.appendChild(elt("br")); } measureText.appendChild(document.createTextNode("x")); } removeChildrenAndAdd(display.measure, measureText); var height = measureText.offsetHeight / 50; if (height > 3) { display.cachedTextHeight = height; } removeChildren(display.measure); return height || 1 } // Compute the default character width. function charWidth(display) { if (display.cachedCharWidth != null) { return display.cachedCharWidth } var anchor = elt("span", "xxxxxxxxxx"); var pre = elt("pre", [anchor], "CodeMirror-line-like"); removeChildrenAndAdd(display.measure, pre); var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10; if (width > 2) { display.cachedCharWidth = width; } return width || 10 } // Do a bulk-read of the DOM positions and sizes needed to draw the // view, so that we don't interleave reading and writing to the DOM. function getDimensions(cm) { var d = cm.display, left = {}, width = {}; var gutterLeft = d.gutters.clientLeft; for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { var id = cm.display.gutterSpecs[i].className; left[id] = n.offsetLeft + n.clientLeft + gutterLeft; width[id] = n.clientWidth; } return {fixedPos: compensateForHScroll(d), gutterTotalWidth: d.gutters.offsetWidth, gutterLeft: left, gutterWidth: width, wrapperWidth: d.wrapper.clientWidth} } // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, // but using getBoundingClientRect to get a sub-pixel-accurate // result. function compensateForHScroll(display) { return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left } // Returns a function that estimates the height of a line, to use as // first approximation until the line becomes visible (and is thus // properly measurable). function estimateHeight(cm) { var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); return function (line) { if (lineIsHidden(cm.doc, line)) { return 0 } var widgetsHeight = 0; if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) { if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height; } } } if (wrapping) { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th } else { return widgetsHeight + th } } } function estimateLineHeights(cm) { var doc = cm.doc, est = estimateHeight(cm); doc.iter(function (line) { var estHeight = est(line); if (estHeight != line.height) { updateLineHeight(line, estHeight); } }); } // Given a mouse event, find the corresponding position. If liberal // is false, it checks whether a gutter or scrollbar was clicked, // and returns null if it was. forRect is used by rectangular // selections, and tries to estimate a character position even for // coordinates beyond the right of the text. function posFromMouse(cm, e, liberal, forRect) { var display = cm.display; if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null } var x, y, space = display.lineSpace.getBoundingClientRect(); // Fails unpredictably on IE[67] when mouse is dragged around quickly. try { x = e.clientX - space.left; y = e.clientY - space.top; } catch (e$1) { return null } var coords = coordsChar(cm, x, y), line; if (forRect && coords.xRel > 0 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length; coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)); } return coords } // Find the view element corresponding to a given line. Return null // when the line isn't visible. function findViewIndex(cm, n) { if (n >= cm.display.viewTo) { return null } n -= cm.display.viewFrom; if (n < 0) { return null } var view = cm.display.view; for (var i = 0; i < view.length; i++) { n -= view[i].size; if (n < 0) { return i } } } // Updates the display.view data structure for a given change to the // document. From and to are in pre-change coordinates. Lendiff is // the amount of lines added or subtracted by the change. This is // used for changes that span multiple lines, or change the way // lines are divided into visual lines. regLineChange (below) // registers single-line changes. function regChange(cm, from, to, lendiff) { if (from == null) { from = cm.doc.first; } if (to == null) { to = cm.doc.first + cm.doc.size; } if (!lendiff) { lendiff = 0; } var display = cm.display; if (lendiff && to < display.viewTo && (display.updateLineNumbers == null || display.updateLineNumbers > from)) { display.updateLineNumbers = from; } cm.curOp.viewChanged = true; if (from >= display.viewTo) { // Change after if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) { resetView(cm); } } else if (to <= display.viewFrom) { // Change before if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { resetView(cm); } else { display.viewFrom += lendiff; display.viewTo += lendiff; } } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap resetView(cm); } else if (from <= display.viewFrom) { // Top overlap var cut = viewCuttingPoint(cm, to, to + lendiff, 1); if (cut) { display.view = display.view.slice(cut.index); display.viewFrom = cut.lineN; display.viewTo += lendiff; } else { resetView(cm); } } else if (to >= display.viewTo) { // Bottom overlap var cut$1 = viewCuttingPoint(cm, from, from, -1); if (cut$1) { display.view = display.view.slice(0, cut$1.index); display.viewTo = cut$1.lineN; } else { resetView(cm); } } else { // Gap in the middle var cutTop = viewCuttingPoint(cm, from, from, -1); var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); if (cutTop && cutBot) { display.view = display.view.slice(0, cutTop.index) .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) .concat(display.view.slice(cutBot.index)); display.viewTo += lendiff; } else { resetView(cm); } } var ext = display.externalMeasured; if (ext) { if (to < ext.lineN) { ext.lineN += lendiff; } else if (from < ext.lineN + ext.size) { display.externalMeasured = null; } } } // Register a change to a single line. Type must be one of "text", // "gutter", "class", "widget" function regLineChange(cm, line, type) { cm.curOp.viewChanged = true; var display = cm.display, ext = cm.display.externalMeasured; if (ext && line >= ext.lineN && line < ext.lineN + ext.size) { display.externalMeasured = null; } if (line < display.viewFrom || line >= display.viewTo) { return } var lineView = display.view[findViewIndex(cm, line)]; if (lineView.node == null) { return } var arr = lineView.changes || (lineView.changes = []); if (indexOf(arr, type) == -1) { arr.push(type); } } // Clear the view. function resetView(cm) { cm.display.viewFrom = cm.display.viewTo = cm.doc.first; cm.display.view = []; cm.display.viewOffset = 0; } function viewCuttingPoint(cm, oldN, newN, dir) { var index = findViewIndex(cm, oldN), diff, view = cm.display.view; if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) { return {index: index, lineN: newN} } var n = cm.display.viewFrom; for (var i = 0; i < index; i++) { n += view[i].size; } if (n != oldN) { if (dir > 0) { if (index == view.length - 1) { return null } diff = (n + view[index].size) - oldN; index++; } else { diff = n - oldN; } oldN += diff; newN += diff; } while (visualLineNo(cm.doc, newN) != newN) { if (index == (dir < 0 ? 0 : view.length - 1)) { return null } newN += dir * view[index - (dir < 0 ? 1 : 0)].size; index += dir; } return {index: index, lineN: newN} } // Force the view to cover a given range, adding empty view element // or clipping off existing ones as needed. function adjustView(cm, from, to) { var display = cm.display, view = display.view; if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { display.view = buildViewArray(cm, from, to); display.viewFrom = from; } else { if (display.viewFrom > from) { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); } else if (display.viewFrom < from) { display.view = display.view.slice(findViewIndex(cm, from)); } display.viewFrom = from; if (display.viewTo < to) { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); } else if (display.viewTo > to) { display.view = display.view.slice(0, findViewIndex(cm, to)); } } display.viewTo = to; } // Count the number of lines in the view whose DOM representation is // out of date (or nonexistent). function countDirtyView(cm) { var view = cm.display.view, dirty = 0; for (var i = 0; i < view.length; i++) { var lineView = view[i]; if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; } } return dirty } function updateSelection(cm) { cm.display.input.showSelection(cm.display.input.prepareSelection()); } function prepareSelection(cm, primary) { if ( primary === void 0 ) primary = true; var doc = cm.doc, result = {}; var curFragment = result.cursors = document.createDocumentFragment(); var selFragment = result.selection = document.createDocumentFragment(); var customCursor = cm.options.$customCursor; if (customCursor) { primary = true; } for (var i = 0; i < doc.sel.ranges.length; i++) { if (!primary && i == doc.sel.primIndex) { continue } var range = doc.sel.ranges[i]; if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue } var collapsed = range.empty(); if (customCursor) { var head = customCursor(cm, range); if (head) { drawSelectionCursor(cm, head, curFragment); } } else if (collapsed || cm.options.showCursorWhenSelecting) { drawSelectionCursor(cm, range.head, curFragment); } if (!collapsed) { drawSelectionRange(cm, range, selFragment); } } return result } // Draws a cursor for the given range function drawSelectionCursor(cm, head, output) { var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine); var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")); cursor.style.left = pos.left + "px"; cursor.style.top = pos.top + "px"; cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; if (/\bcm-fat-cursor\b/.test(cm.getWrapperElement().className)) { var charPos = charCoords(cm, head, "div", null, null); var width = charPos.right - charPos.left; cursor.style.width = (width > 0 ? width : cm.defaultCharWidth()) + "px"; } if (pos.other) { // Secondary cursor, shown when on a 'jump' in bi-directional text var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")); otherCursor.style.display = ""; otherCursor.style.left = pos.other.left + "px"; otherCursor.style.top = pos.other.top + "px"; otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; } } function cmpCoords(a, b) { return a.top - b.top || a.left - b.left } // Draws the given range as a highlighted selection function drawSelectionRange(cm, range, output) { var display = cm.display, doc = cm.doc; var fragment = document.createDocumentFragment(); var padding = paddingH(cm.display), leftSide = padding.left; var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right; var docLTR = doc.direction == "ltr"; function add(left, top, width, bottom) { if (top < 0) { top = 0; } top = Math.round(top); bottom = Math.round(bottom); fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px"))); } function drawForLine(line, fromArg, toArg) { var lineObj = getLine(doc, line); var lineLen = lineObj.text.length; var start, end; function coords(ch, bias) { return charCoords(cm, Pos(line, ch), "div", lineObj, bias) } function wrapX(pos, dir, side) { var extent = wrappedLineExtentChar(cm, lineObj, null, pos); var prop = (dir == "ltr") == (side == "after") ? "left" : "right"; var ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1); return coords(ch, prop)[prop] } var order = getOrder(lineObj, doc.direction); iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) { var ltr = dir == "ltr"; var fromPos = coords(from, ltr ? "left" : "right"); var toPos = coords(to - 1, ltr ? "right" : "left"); var openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen; var first = i == 0, last = !order || i == order.length - 1; if (toPos.top - fromPos.top <= 3) { // Single line var openLeft = (docLTR ? openStart : openEnd) && first; var openRight = (docLTR ? openEnd : openStart) && last; var left = openLeft ? leftSide : (ltr ? fromPos : toPos).left; var right = openRight ? rightSide : (ltr ? toPos : fromPos).right; add(left, fromPos.top, right - left, fromPos.bottom); } else { // Multiple lines var topLeft, topRight, botLeft, botRight; if (ltr) { topLeft = docLTR && openStart && first ? leftSide : fromPos.left; topRight = docLTR ? rightSide : wrapX(from, dir, "before"); botLeft = docLTR ? leftSide : wrapX(to, dir, "after"); botRight = docLTR && openEnd && last ? rightSide : toPos.right; } else { topLeft = !docLTR ? leftSide : wrapX(from, dir, "before"); topRight = !docLTR && openStart && first ? rightSide : fromPos.right; botLeft = !docLTR && openEnd && last ? leftSide : toPos.left; botRight = !docLTR ? rightSide : wrapX(to, dir, "after"); } add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom); if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); } add(botLeft, toPos.top, botRight - botLeft, toPos.bottom); } if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos; } if (cmpCoords(toPos, start) < 0) { start = toPos; } if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos; } if (cmpCoords(toPos, end) < 0) { end = toPos; } }); return {start: start, end: end} } var sFrom = range.from(), sTo = range.to(); if (sFrom.line == sTo.line) { drawForLine(sFrom.line, sFrom.ch, sTo.ch); } else { var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line); var singleVLine = visualLine(fromLine) == visualLine(toLine); var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end; var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; if (singleVLine) { if (leftEnd.top < rightStart.top - 2) { add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); } else { add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); } } if (leftEnd.bottom < rightStart.top) { add(leftSide, leftEnd.bottom, null, rightStart.top); } } output.appendChild(fragment); } // Cursor-blinking function restartBlink(cm) { if (!cm.state.focused) { return } var display = cm.display; clearInterval(display.blinker); var on = true; display.cursorDiv.style.visibility = ""; if (cm.options.cursorBlinkRate > 0) { display.blinker = setInterval(function () { if (!cm.hasFocus()) { onBlur(cm); } display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; }, cm.options.cursorBlinkRate); } else if (cm.options.cursorBlinkRate < 0) { display.cursorDiv.style.visibility = "hidden"; } } function ensureFocus(cm) { if (!cm.hasFocus()) { cm.display.input.focus(); if (!cm.state.focused) { onFocus(cm); } } } function delayBlurEvent(cm) { cm.state.delayingBlurEvent = true; setTimeout(function () { if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false; if (cm.state.focused) { onBlur(cm); } } }, 100); } function onFocus(cm, e) { if (cm.state.delayingBlurEvent && !cm.state.draggingText) { cm.state.delayingBlurEvent = false; } if (cm.options.readOnly == "nocursor") { return } if (!cm.state.focused) { signal(cm, "focus", cm, e); cm.state.focused = true; addClass(cm.display.wrapper, "CodeMirror-focused"); // This test prevents this from firing when a context // menu is closed (since the input reset would kill the // select-all detection hack) if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { cm.display.input.reset(); if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20); } // Issue #1730 } cm.display.input.receivedFocus(); } restartBlink(cm); } function onBlur(cm, e) { if (cm.state.delayingBlurEvent) { return } if (cm.state.focused) { signal(cm, "blur", cm, e); cm.state.focused = false; rmClass(cm.display.wrapper, "CodeMirror-focused"); } clearInterval(cm.display.blinker); setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150); } // Read the actual heights of the rendered lines, and update their // stored heights to match. function updateHeightsInViewport(cm) { var display = cm.display; var prevBottom = display.lineDiv.offsetTop; var viewTop = Math.max(0, display.scroller.getBoundingClientRect().top); var oldHeight = display.lineDiv.getBoundingClientRect().top; var mustScroll = 0; for (var i = 0; i < display.view.length; i++) { var cur = display.view[i], wrapping = cm.options.lineWrapping; var height = (void 0), width = 0; if (cur.hidden) { continue } oldHeight += cur.line.height; if (ie && ie_version < 8) { var bot = cur.node.offsetTop + cur.node.offsetHeight; height = bot - prevBottom; prevBottom = bot; } else { var box = cur.node.getBoundingClientRect(); height = box.bottom - box.top; // Check that lines don't extend past the right of the current // editor width if (!wrapping && cur.text.firstChild) { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; } } var diff = cur.line.height - height; if (diff > .005 || diff < -.005) { if (oldHeight < viewTop) { mustScroll -= diff; } updateLineHeight(cur.line, height); updateWidgetHeight(cur.line); if (cur.rest) { for (var j = 0; j < cur.rest.length; j++) { updateWidgetHeight(cur.rest[j]); } } } if (width > cm.display.sizerWidth) { var chWidth = Math.ceil(width / charWidth(cm.display)); if (chWidth > cm.display.maxLineLength) { cm.display.maxLineLength = chWidth; cm.display.maxLine = cur.line; cm.display.maxLineChanged = true; } } } if (Math.abs(mustScroll) > 2) { display.scroller.scrollTop += mustScroll; } } // Read and store the height of line widgets associated with the // given line. function updateWidgetHeight(line) { if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) { var w = line.widgets[i], parent = w.node.parentNode; if (parent) { w.height = parent.offsetHeight; } } } } // Compute the lines that are visible in a given viewport (defaults // the the current scroll position). viewport may contain top, // height, and ensure (see op.scrollToPos) properties. function visibleLines(display, doc, viewport) { var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; top = Math.floor(top - paddingTop(display)); var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); // Ensure is a {from: {line, ch}, to: {line, ch}} object, and // forces those lines into the viewport (if possible). if (viewport && viewport.ensure) { var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line; if (ensureFrom < from) { from = ensureFrom; to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight); } else if (Math.min(ensureTo, doc.lastLine()) >= to) { from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight); to = ensureTo; } } return {from: from, to: Math.max(to, from + 1)} } // SCROLLING THINGS INTO VIEW // If an editor sits on the top or bottom of the window, partially // scrolled out of view, this ensures that the cursor is visible. function maybeScrollWindow(cm, rect) { if (signalDOMEvent(cm, "scrollCursorIntoView")) { return } var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; var doc = display.wrapper.ownerDocument; if (rect.top + box.top < 0) { doScroll = true; } else if (rect.bottom + box.top > (doc.defaultView.innerHeight || doc.documentElement.clientHeight)) { doScroll = false; } if (doScroll != null && !phantom) { var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;")); cm.display.lineSpace.appendChild(scrollNode); scrollNode.scrollIntoView(doScroll); cm.display.lineSpace.removeChild(scrollNode); } } // Scroll a given position into view (immediately), verifying that // it actually became visible (as line heights are accurately // measured, the position of something may 'drift' during drawing). function scrollPosIntoView(cm, pos, end, margin) { if (margin == null) { margin = 0; } var rect; if (!cm.options.lineWrapping && pos == end) { // Set pos and end to the cursor positions around the character pos sticks to // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch // If pos == Pos(_, 0, "before"), pos and end are unchanged end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos; pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos; } for (var limit = 0; limit < 5; limit++) { var changed = false; var coords = cursorCoords(cm, pos); var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); rect = {left: Math.min(coords.left, endCoords.left), top: Math.min(coords.top, endCoords.top) - margin, right: Math.max(coords.left, endCoords.left), bottom: Math.max(coords.bottom, endCoords.bottom) + margin}; var scrollPos = calculateScrollPos(cm, rect); var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; } } if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; } } if (!changed) { break } } return rect } // Scroll a given set of coordinates into view (immediately). function scrollIntoView(cm, rect) { var scrollPos = calculateScrollPos(cm, rect); if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); } if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); } } // Calculate a new scroll position needed to scroll the given // rectangle into view. Returns an object with scrollTop and // scrollLeft properties. When these are undefined, the // vertical/horizontal position does not need to be adjusted. function calculateScrollPos(cm, rect) { var display = cm.display, snapMargin = textHeight(cm.display); if (rect.top < 0) { rect.top = 0; } var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop; var screen = displayHeight(cm), result = {}; if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; } var docBottom = cm.doc.height + paddingVert(display); var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin; if (rect.top < screentop) { result.scrollTop = atTop ? 0 : rect.top; } else if (rect.bottom > screentop + screen) { var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen); if (newTop != screentop) { result.scrollTop = newTop; } } var gutterSpace = cm.options.fixedGutter ? 0 : display.gutters.offsetWidth; var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft - gutterSpace; var screenw = displayWidth(cm) - display.gutters.offsetWidth; var tooWide = rect.right - rect.left > screenw; if (tooWide) { rect.right = rect.left + screenw; } if (rect.left < 10) { result.scrollLeft = 0; } else if (rect.left < screenleft) { result.scrollLeft = Math.max(0, rect.left + gutterSpace - (tooWide ? 0 : 10)); } else if (rect.right > screenw + screenleft - 3) { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; } return result } // Store a relative adjustment to the scroll position in the current // operation (to be applied when the operation finishes). function addToScrollTop(cm, top) { if (top == null) { return } resolveScrollToPos(cm); cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; } // Make sure that at the end of the operation the current cursor is // shown. function ensureCursorVisible(cm) { resolveScrollToPos(cm); var cur = cm.getCursor(); cm.curOp.scrollToPos = {from: cur, to: cur, margin: cm.options.cursorScrollMargin}; } function scrollToCoords(cm, x, y) { if (x != null || y != null) { resolveScrollToPos(cm); } if (x != null) { cm.curOp.scrollLeft = x; } if (y != null) { cm.curOp.scrollTop = y; } } function scrollToRange(cm, range) { resolveScrollToPos(cm); cm.curOp.scrollToPos = range; } // When an operation has its scrollToPos property set, and another // scroll action is applied before the end of the operation, this // 'simulates' scrolling that position into view in a cheap way, so // that the effect of intermediate scroll commands is not ignored. function resolveScrollToPos(cm) { var range = cm.curOp.scrollToPos; if (range) { cm.curOp.scrollToPos = null; var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to); scrollToCoordsRange(cm, from, to, range.margin); } } function scrollToCoordsRange(cm, from, to, margin) { var sPos = calculateScrollPos(cm, { left: Math.min(from.left, to.left), top: Math.min(from.top, to.top) - margin, right: Math.max(from.right, to.right), bottom: Math.max(from.bottom, to.bottom) + margin }); scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop); } // Sync the scrollable area and scrollbars, ensure the viewport // covers the visible area. function updateScrollTop(cm, val) { if (Math.abs(cm.doc.scrollTop - val) < 2) { return } if (!gecko) { updateDisplaySimple(cm, {top: val}); } setScrollTop(cm, val, true); if (gecko) { updateDisplaySimple(cm); } startWorker(cm, 100); } function setScrollTop(cm, val, forceScroll) { val = Math.max(0, Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val)); if (cm.display.scroller.scrollTop == val && !forceScroll) { return } cm.doc.scrollTop = val; cm.display.scrollbars.setScrollTop(val); if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; } } // Sync scroller and scrollbar, ensure the gutter elements are // aligned. function setScrollLeft(cm, val, isScroller, forceScroll) { val = Math.max(0, Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth)); if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return } cm.doc.scrollLeft = val; alignHorizontally(cm); if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; } cm.display.scrollbars.setScrollLeft(val); } // SCROLLBARS // Prepare DOM reads needed to update the scrollbars. Done in one // shot to minimize update/measure roundtrips. function measureForScrollbars(cm) { var d = cm.display, gutterW = d.gutters.offsetWidth; var docH = Math.round(cm.doc.height + paddingVert(cm.display)); return { clientHeight: d.scroller.clientHeight, viewHeight: d.wrapper.clientHeight, scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, viewWidth: d.wrapper.clientWidth, barLeft: cm.options.fixedGutter ? gutterW : 0, docHeight: docH, scrollHeight: docH + scrollGap(cm) + d.barHeight, nativeBarWidth: d.nativeBarWidth, gutterWidth: gutterW } } var NativeScrollbars = function(place, scroll, cm) { this.cm = cm; var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar"); var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar"); vert.tabIndex = horiz.tabIndex = -1; place(vert); place(horiz); on(vert, "scroll", function () { if (vert.clientHeight) { scroll(vert.scrollTop, "vertical"); } }); on(horiz, "scroll", function () { if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal"); } }); this.checkedZeroWidth = false; // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; } }; NativeScrollbars.prototype.update = function (measure) { var needsH = measure.scrollWidth > measure.clientWidth + 1; var needsV = measure.scrollHeight > measure.clientHeight + 1; var sWidth = measure.nativeBarWidth; if (needsV) { this.vert.style.display = "block"; this.vert.style.bottom = needsH ? sWidth + "px" : "0"; var totalHeight = measure.viewHeight - (needsH ? sWidth : 0); // A bug in IE8 can cause this value to be negative, so guard it. this.vert.firstChild.style.height = Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"; } else { this.vert.scrollTop = 0; this.vert.style.display = ""; this.vert.firstChild.style.height = "0"; } if (needsH) { this.horiz.style.display = "block"; this.horiz.style.right = needsV ? sWidth + "px" : "0"; this.horiz.style.left = measure.barLeft + "px"; var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0); this.horiz.firstChild.style.width = Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px"; } else { this.horiz.style.display = ""; this.horiz.firstChild.style.width = "0"; } if (!this.checkedZeroWidth && measure.clientHeight > 0) { if (sWidth == 0) { this.zeroWidthHack(); } this.checkedZeroWidth = true; } return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0} }; NativeScrollbars.prototype.setScrollLeft = function (pos) { if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos; } if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz, "horiz"); } }; NativeScrollbars.prototype.setScrollTop = function (pos) { if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos; } if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert, "vert"); } }; NativeScrollbars.prototype.zeroWidthHack = function () { var w = mac && !mac_geMountainLion ? "12px" : "18px"; this.horiz.style.height = this.vert.style.width = w; this.horiz.style.visibility = this.vert.style.visibility = "hidden"; this.disableHoriz = new Delayed; this.disableVert = new Delayed; }; NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) { bar.style.visibility = ""; function maybeDisable() { // To find out whether the scrollbar is still visible, we // check whether the element under the pixel in the bottom // right corner of the scrollbar box is the scrollbar box // itself (when the bar is still visible) or its filler child // (when the bar is hidden). If it is still visible, we keep // it enabled, if it's hidden, we disable pointer events. var box = bar.getBoundingClientRect(); var elt = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2) : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1); if (elt != bar) { bar.style.visibility = "hidden"; } else { delay.set(1000, maybeDisable); } } delay.set(1000, maybeDisable); }; NativeScrollbars.prototype.clear = function () { var parent = this.horiz.parentNode; parent.removeChild(this.horiz); parent.removeChild(this.vert); }; var NullScrollbars = function () {}; NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} }; NullScrollbars.prototype.setScrollLeft = function () {}; NullScrollbars.prototype.setScrollTop = function () {}; NullScrollbars.prototype.clear = function () {}; function updateScrollbars(cm, measure) { if (!measure) { measure = measureForScrollbars(cm); } var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight; updateScrollbarsInner(cm, measure); for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { if (startWidth != cm.display.barWidth && cm.options.lineWrapping) { updateHeightsInViewport(cm); } updateScrollbarsInner(cm, measureForScrollbars(cm)); startWidth = cm.display.barWidth; startHeight = cm.display.barHeight; } } // Re-synchronize the fake scrollbars with the actual size of the // content. function updateScrollbarsInner(cm, measure) { var d = cm.display; var sizes = d.scrollbars.update(measure); d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"; d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"; d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent"; if (sizes.right && sizes.bottom) { d.scrollbarFiller.style.display = "block"; d.scrollbarFiller.style.height = sizes.bottom + "px"; d.scrollbarFiller.style.width = sizes.right + "px"; } else { d.scrollbarFiller.style.display = ""; } if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { d.gutterFiller.style.display = "block"; d.gutterFiller.style.height = sizes.bottom + "px"; d.gutterFiller.style.width = measure.gutterWidth + "px"; } else { d.gutterFiller.style.display = ""; } } var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}; function initScrollbars(cm) { if (cm.display.scrollbars) { cm.display.scrollbars.clear(); if (cm.display.scrollbars.addClass) { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); } } cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) { cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller); // Prevent clicks in the scrollbars from killing focus on(node, "mousedown", function () { if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0); } }); node.setAttribute("cm-not-content", "true"); }, function (pos, axis) { if (axis == "horizontal") { setScrollLeft(cm, pos); } else { updateScrollTop(cm, pos); } }, cm); if (cm.display.scrollbars.addClass) { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); } } // Operations are used to wrap a series of changes to the editor // state in such a way that each change won't have to update the // cursor and display (which would be awkward, slow, and // error-prone). Instead, display updates are batched and then all // combined and executed at once. var nextOpId = 0; // Start a new operation. function startOperation(cm) { cm.curOp = { cm: cm, viewChanged: false, // Flag that indicates that lines might need to be redrawn startHeight: cm.doc.height, // Used to detect need to update scrollbar forceUpdate: false, // Used to force a redraw updateInput: 0, // Whether to reset the input textarea typing: false, // Whether this reset should be careful to leave existing text (for compositing) changeObjs: null, // Accumulated changes, for firing change events cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already selectionChanged: false, // Whether the selection needs to be redrawn updateMaxLine: false, // Set when the widest line needs to be determined anew scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet scrollToPos: null, // Used to scroll to a specific position focus: false, id: ++nextOpId, // Unique ID markArrays: null // Used by addMarkedSpan }; pushOperation(cm.curOp); } // Finish an operation, updating the display and signalling delayed events function endOperation(cm) { var op = cm.curOp; if (op) { finishOperation(op, function (group) { for (var i = 0; i < group.ops.length; i++) { group.ops[i].cm.curOp = null; } endOperations(group); }); } } // The DOM updates done when an operation finishes are batched so // that the minimum number of relayouts are required. function endOperations(group) { var ops = group.ops; for (var i = 0; i < ops.length; i++) // Read DOM { endOperation_R1(ops[i]); } for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe) { endOperation_W1(ops[i$1]); } for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM { endOperation_R2(ops[i$2]); } for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe) { endOperation_W2(ops[i$3]); } for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM { endOperation_finish(ops[i$4]); } } function endOperation_R1(op) { var cm = op.cm, display = cm.display; maybeClipScrollbars(cm); if (op.updateMaxLine) { findMaxLine(cm); } op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || op.scrollToPos.to.line >= display.viewTo) || display.maxLineChanged && cm.options.lineWrapping; op.update = op.mustUpdate && new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); } function endOperation_W1(op) { op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); } function endOperation_R2(op) { var cm = op.cm, display = cm.display; if (op.updatedDisplay) { updateHeightsInViewport(cm); } op.barMeasure = measureForScrollbars(cm); // If the max line changed since it was last measured, measure it, // and ensure the document's width matches it. // updateDisplay_W2 will use these properties to do the actual resizing if (display.maxLineChanged && !cm.options.lineWrapping) { op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3; cm.display.sizerWidth = op.adjustWidthTo; op.barMeasure.scrollWidth = Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth); op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)); } if (op.updatedDisplay || op.selectionChanged) { op.preparedSelection = display.input.prepareSelection(); } } function endOperation_W2(op) { var cm = op.cm; if (op.adjustWidthTo != null) { cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; if (op.maxScrollLeft < cm.doc.scrollLeft) { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); } cm.display.maxLineChanged = false; } var takeFocus = op.focus && op.focus == activeElt(root(cm)); if (op.preparedSelection) { cm.display.input.showSelection(op.preparedSelection, takeFocus); } if (op.updatedDisplay || op.startHeight != cm.doc.height) { updateScrollbars(cm, op.barMeasure); } if (op.updatedDisplay) { setDocumentHeight(cm, op.barMeasure); } if (op.selectionChanged) { restartBlink(cm); } if (cm.state.focused && op.updateInput) { cm.display.input.reset(op.typing); } if (takeFocus) { ensureFocus(op.cm); } } function endOperation_finish(op) { var cm = op.cm, display = cm.display, doc = cm.doc; if (op.updatedDisplay) { postUpdateDisplay(cm, op.update); } // Abort mouse wheel delta measurement, when scrolling explicitly if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) { display.wheelStartX = display.wheelStartY = null; } // Propagate the scroll position to the actual DOM scroller if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll); } if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true); } // If we need to scroll a specific position into view, do so. if (op.scrollToPos) { var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); maybeScrollWindow(cm, rect); } // Fire events for markers that are hidden/unidden by editing or // undoing var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; if (hidden) { for (var i = 0; i < hidden.length; ++i) { if (!hidden[i].lines.length) { signal(hidden[i], "hide"); } } } if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1) { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide"); } } } if (display.wrapper.offsetHeight) { doc.scrollTop = cm.display.scroller.scrollTop; } // Fire change events, and delayed event handlers if (op.changeObjs) { signal(cm, "changes", cm, op.changeObjs); } if (op.update) { op.update.finish(); } } // Run the given function in an operation function runInOp(cm, f) { if (cm.curOp) { return f() } startOperation(cm); try { return f() } finally { endOperation(cm); } } // Wraps a function in an operation. Returns the wrapped function. function operation(cm, f) { return function() { if (cm.curOp) { return f.apply(cm, arguments) } startOperation(cm); try { return f.apply(cm, arguments) } finally { endOperation(cm); } } } // Used to add methods to editor and doc instances, wrapping them in // operations. function methodOp(f) { return function() { if (this.curOp) { return f.apply(this, arguments) } startOperation(this); try { return f.apply(this, arguments) } finally { endOperation(this); } } } function docMethodOp(f) { return function() { var cm = this.cm; if (!cm || cm.curOp) { return f.apply(this, arguments) } startOperation(cm); try { return f.apply(this, arguments) } finally { endOperation(cm); } } } // HIGHLIGHT WORKER function startWorker(cm, time) { if (cm.doc.highlightFrontier < cm.display.viewTo) { cm.state.highlight.set(time, bind(highlightWorker, cm)); } } function highlightWorker(cm) { var doc = cm.doc; if (doc.highlightFrontier >= cm.display.viewTo) { return } var end = +new Date + cm.options.workTime; var context = getContextBefore(cm, doc.highlightFrontier); var changedLines = []; doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) { if (context.line >= cm.display.viewFrom) { // Visible var oldStyles = line.styles; var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null; var highlighted = highlightLine(cm, line, context, true); if (resetState) { context.state = resetState; } line.styles = highlighted.styles; var oldCls = line.styleClasses, newCls = highlighted.classes; if (newCls) { line.styleClasses = newCls; } else if (oldCls) { line.styleClasses = null; } var ischange = !oldStyles || oldStyles.length != line.styles.length || oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i]; } if (ischange) { changedLines.push(context.line); } line.stateAfter = context.save(); context.nextLine(); } else { if (line.text.length <= cm.options.maxHighlightLength) { processLine(cm, line.text, context); } line.stateAfter = context.line % 5 == 0 ? context.save() : null; context.nextLine(); } if (+new Date > end) { startWorker(cm, cm.options.workDelay); return true } }); doc.highlightFrontier = context.line; doc.modeFrontier = Math.max(doc.modeFrontier, context.line); if (changedLines.length) { runInOp(cm, function () { for (var i = 0; i < changedLines.length; i++) { regLineChange(cm, changedLines[i], "text"); } }); } } // DISPLAY DRAWING var DisplayUpdate = function(cm, viewport, force) { var display = cm.display; this.viewport = viewport; // Store some values that we'll need later (but don't want to force a relayout for) this.visible = visibleLines(display, cm.doc, viewport); this.editorIsHidden = !display.wrapper.offsetWidth; this.wrapperHeight = display.wrapper.clientHeight; this.wrapperWidth = display.wrapper.clientWidth; this.oldDisplayWidth = displayWidth(cm); this.force = force; this.dims = getDimensions(cm); this.events = []; }; DisplayUpdate.prototype.signal = function (emitter, type) { if (hasHandler(emitter, type)) { this.events.push(arguments); } }; DisplayUpdate.prototype.finish = function () { for (var i = 0; i < this.events.length; i++) { signal.apply(null, this.events[i]); } }; function maybeClipScrollbars(cm) { var display = cm.display; if (!display.scrollbarsClipped && display.scroller.offsetWidth) { display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth; display.heightForcer.style.height = scrollGap(cm) + "px"; display.sizer.style.marginBottom = -display.nativeBarWidth + "px"; display.sizer.style.borderRightWidth = scrollGap(cm) + "px"; display.scrollbarsClipped = true; } } function selectionSnapshot(cm) { if (cm.hasFocus()) { return null } var active = activeElt(root(cm)); if (!active || !contains(cm.display.lineDiv, active)) { return null } var result = {activeElt: active}; if (window.getSelection) { var sel = win(cm).getSelection(); if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) { result.anchorNode = sel.anchorNode; result.anchorOffset = sel.anchorOffset; result.focusNode = sel.focusNode; result.focusOffset = sel.focusOffset; } } return result } function restoreSelection(snapshot) { if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt(rootNode(snapshot.activeElt))) { return } snapshot.activeElt.focus(); if (!/^(INPUT|TEXTAREA)$/.test(snapshot.activeElt.nodeName) && snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) { var doc = snapshot.activeElt.ownerDocument; var sel = doc.defaultView.getSelection(), range = doc.createRange(); range.setEnd(snapshot.anchorNode, snapshot.anchorOffset); range.collapse(false); sel.removeAllRanges(); sel.addRange(range); sel.extend(snapshot.focusNode, snapshot.focusOffset); } } // Does the actual updating of the line display. Bails out // (returning false) when there is nothing to be done and forced is // false. function updateDisplayIfNeeded(cm, update) { var display = cm.display, doc = cm.doc; if (update.editorIsHidden) { resetView(cm); return false } // Bail out if the visible area is already rendered and nothing changed. if (!update.force && update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && display.renderedView == display.view && countDirtyView(cm) == 0) { return false } if (maybeUpdateLineNumberWidth(cm)) { resetView(cm); update.dims = getDimensions(cm); } // Compute a suitable new viewport (from & to) var end = doc.first + doc.size; var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); var to = Math.min(end, update.visible.to + cm.options.viewportMargin); if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom); } if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo); } if (sawCollapsedSpans) { from = visualLineNo(cm.doc, from); to = visualLineEndNo(cm.doc, to); } var different = from != display.viewFrom || to != display.viewTo || display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth; adjustView(cm, from, to); display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)); // Position the mover div to align with the current scroll position cm.display.mover.style.top = display.viewOffset + "px"; var toUpdate = countDirtyView(cm); if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) { return false } // For big changes, we hide the enclosing element during the // update, since that speeds up the operations on most browsers. var selSnapshot = selectionSnapshot(cm); if (toUpdate > 4) { display.lineDiv.style.display = "none"; } patchDisplay(cm, display.updateLineNumbers, update.dims); if (toUpdate > 4) { display.lineDiv.style.display = ""; } display.renderedView = display.view; // There might have been a widget with a focused element that got // hidden or updated, if so re-focus it. restoreSelection(selSnapshot); // Prevent selection and cursors from interfering with the scroll // width and height. removeChildren(display.cursorDiv); removeChildren(display.selectionDiv); display.gutters.style.height = display.sizer.style.minHeight = 0; if (different) { display.lastWrapHeight = update.wrapperHeight; display.lastWrapWidth = update.wrapperWidth; startWorker(cm, 400); } display.updateLineNumbers = null; return true } function postUpdateDisplay(cm, update) { var viewport = update.viewport; for (var first = true;; first = false) { if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { // Clip forced viewport to actual scrollable area. if (viewport && viewport.top != null) { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; } // Updated line heights might result in the drawn area not // actually covering the viewport. Keep looping until it does. update.visible = visibleLines(cm.display, cm.doc, viewport); if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) { break } } else if (first) { update.visible = visibleLines(cm.display, cm.doc, viewport); } if (!updateDisplayIfNeeded(cm, update)) { break } updateHeightsInViewport(cm); var barMeasure = measureForScrollbars(cm); updateSelection(cm); updateScrollbars(cm, barMeasure); setDocumentHeight(cm, barMeasure); update.force = false; } update.signal(cm, "update", cm); if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo; } } function updateDisplaySimple(cm, viewport) { var update = new DisplayUpdate(cm, viewport); if (updateDisplayIfNeeded(cm, update)) { updateHeightsInViewport(cm); postUpdateDisplay(cm, update); var barMeasure = measureForScrollbars(cm); updateSelection(cm); updateScrollbars(cm, barMeasure); setDocumentHeight(cm, barMeasure); update.finish(); } } // Sync the actual display DOM structure with display.view, removing // nodes for lines that are no longer in view, and creating the ones // that are not there yet, and updating the ones that are out of // date. function patchDisplay(cm, updateNumbersFrom, dims) { var display = cm.display, lineNumbers = cm.options.lineNumbers; var container = display.lineDiv, cur = container.firstChild; function rm(node) { var next = node.nextSibling; // Works around a throw-scroll bug in OS X Webkit if (webkit && mac && cm.display.currentWheelTarget == node) { node.style.display = "none"; } else { node.parentNode.removeChild(node); } return next } var view = display.view, lineN = display.viewFrom; // Loop over the elements in the view, syncing cur (the DOM nodes // in display.lineDiv) with the view as we go. for (var i = 0; i < view.length; i++) { var lineView = view[i]; if (lineView.hidden) ; else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet var node = buildLineElement(cm, lineView, lineN, dims); container.insertBefore(node, cur); } else { // Already drawn while (cur != lineView.node) { cur = rm(cur); } var updateNumber = lineNumbers && updateNumbersFrom != null && updateNumbersFrom <= lineN && lineView.lineNumber; if (lineView.changes) { if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false; } updateLineForChanges(cm, lineView, lineN, dims); } if (updateNumber) { removeChildren(lineView.lineNumber); lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))); } cur = lineView.node.nextSibling; } lineN += lineView.size; } while (cur) { cur = rm(cur); } } function updateGutterSpace(display) { var width = display.gutters.offsetWidth; display.sizer.style.marginLeft = width + "px"; // Send an event to consumers responding to changes in gutter width. signalLater(display, "gutterChanged", display); } function setDocumentHeight(cm, measure) { cm.display.sizer.style.minHeight = measure.docHeight + "px"; cm.display.heightForcer.style.top = measure.docHeight + "px"; cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px"; } // Re-align line numbers and gutter marks to compensate for // horizontal scrolling. function alignHorizontally(cm) { var display = cm.display, view = display.view; if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return } var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; var gutterW = display.gutters.offsetWidth, left = comp + "px"; for (var i = 0; i < view.length; i++) { if (!view[i].hidden) { if (cm.options.fixedGutter) { if (view[i].gutter) { view[i].gutter.style.left = left; } if (view[i].gutterBackground) { view[i].gutterBackground.style.left = left; } } var align = view[i].alignable; if (align) { for (var j = 0; j < align.length; j++) { align[j].style.left = left; } } } } if (cm.options.fixedGutter) { display.gutters.style.left = (comp + gutterW) + "px"; } } // Used to ensure that the line number gutter is still the right // size for the current document size. Returns true when an update // is needed. function maybeUpdateLineNumberWidth(cm) { if (!cm.options.lineNumbers) { return false } var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; if (last.length != display.lineNumChars) { var test = display.measure.appendChild(elt("div", [elt("div", last)], "CodeMirror-linenumber CodeMirror-gutter-elt")); var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; display.lineGutter.style.width = ""; display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; display.lineNumWidth = display.lineNumInnerWidth + padding; display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; display.lineGutter.style.width = display.lineNumWidth + "px"; updateGutterSpace(cm.display); return true } return false } function getGutters(gutters, lineNumbers) { var result = [], sawLineNumbers = false; for (var i = 0; i < gutters.length; i++) { var name = gutters[i], style = null; if (typeof name != "string") { style = name.style; name = name.className; } if (name == "CodeMirror-linenumbers") { if (!lineNumbers) { continue } else { sawLineNumbers = true; } } result.push({className: name, style: style}); } if (lineNumbers && !sawLineNumbers) { result.push({className: "CodeMirror-linenumbers", style: null}); } return result } // Rebuild the gutter elements, ensure the margin to the left of the // code matches their width. function renderGutters(display) { var gutters = display.gutters, specs = display.gutterSpecs; removeChildren(gutters); display.lineGutter = null; for (var i = 0; i < specs.length; ++i) { var ref = specs[i]; var className = ref.className; var style = ref.style; var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + className)); if (style) { gElt.style.cssText = style; } if (className == "CodeMirror-linenumbers") { display.lineGutter = gElt; gElt.style.width = (display.lineNumWidth || 1) + "px"; } } gutters.style.display = specs.length ? "" : "none"; updateGutterSpace(display); } function updateGutters(cm) { renderGutters(cm.display); regChange(cm); alignHorizontally(cm); } // The display handles the DOM integration, both for input reading // and content drawing. It holds references to DOM nodes and // display-related state. function Display(place, doc, input, options) { var d = this; this.input = input; // Covers bottom-right square when both scrollbars are present. d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); d.scrollbarFiller.setAttribute("cm-not-content", "true"); // Covers bottom of gutter when coverGutterNextToScrollbar is on // and h scrollbar is present. d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); d.gutterFiller.setAttribute("cm-not-content", "true"); // Will contain the actual code, positioned to cover the viewport. d.lineDiv = eltP("div", null, "CodeMirror-code"); // Elements are added to these to represent selection and cursors. d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); d.cursorDiv = elt("div", null, "CodeMirror-cursors"); // A visibility: hidden element used to find the size of things. d.measure = elt("div", null, "CodeMirror-measure"); // When lines outside of the viewport are measured, they are drawn in this. d.lineMeasure = elt("div", null, "CodeMirror-measure"); // Wraps everything that needs to exist inside the vertically-padded coordinate system d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], null, "position: relative; outline: none"); var lines = eltP("div", [d.lineSpace], "CodeMirror-lines"); // Moved around its parent to cover visible view. d.mover = elt("div", [lines], null, "position: relative"); // Set to the height of the document, allowing scrolling. d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); d.sizerWidth = null; // Behavior of elts with overflow: auto and padding is // inconsistent across browsers. This is used to ensure the // scrollable area is big enough. d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); // Will contain the gutters, if any. d.gutters = elt("div", null, "CodeMirror-gutters"); d.lineGutter = null; // Actual scrollable element. d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); d.scroller.setAttribute("tabIndex", "-1"); // The element in which the editor lives. d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); // See #6982. FIXME remove when this has been fixed for a while in Chrome if (chrome && chrome_version >= 105) { d.wrapper.style.clipPath = "inset(0px)"; } // This attribute is respected by automatic translation systems such as Google Translate, // and may also be respected by tools used by human translators. d.wrapper.setAttribute('translate', 'no'); // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; } if (place) { if (place.appendChild) { place.appendChild(d.wrapper); } else { place(d.wrapper); } } // Current rendered range (may be bigger than the view window). d.viewFrom = d.viewTo = doc.first; d.reportedViewFrom = d.reportedViewTo = doc.first; // Information about the rendered lines. d.view = []; d.renderedView = null; // Holds info about a single rendered line when it was rendered // for measurement, while not in view. d.externalMeasured = null; // Empty space (in pixels) above the view d.viewOffset = 0; d.lastWrapHeight = d.lastWrapWidth = 0; d.updateLineNumbers = null; d.nativeBarWidth = d.barHeight = d.barWidth = 0; d.scrollbarsClipped = false; // Used to only resize the line number gutter when necessary (when // the amount of lines crosses a boundary that makes its width change) d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; // Set to true when a non-horizontal-scrolling line widget is // added. As an optimization, line widget aligning is skipped when // this is false. d.alignWidgets = false; d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; // Tracks the maximum line length so that the horizontal scrollbar // can be kept static when scrolling. d.maxLine = null; d.maxLineLength = 0; d.maxLineChanged = false; // Used for measuring wheel scrolling granularity d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; // True when shift is held down. d.shift = false; // Used to track whether anything happened since the context menu // was opened. d.selForContextMenu = null; d.activeTouch = null; d.gutterSpecs = getGutters(options.gutters, options.lineNumbers); renderGutters(d); input.init(d); } // Since the delta values reported on mouse wheel events are // unstandardized between browsers and even browser versions, and // generally horribly unpredictable, this code starts by measuring // the scroll effect that the first few mouse wheel events have, // and, from that, detects the way it can convert deltas to pixel // offsets afterwards. // // The reason we want to know the amount a wheel event will scroll // is that it gives us a chance to update the display before the // actual scrolling happens, reducing flickering. var wheelSamples = 0, wheelPixelsPerUnit = null; // Fill in a browser-detected starting value on browsers where we // know one. These don't have to be accurate -- the result of them // being wrong would just be a slight flicker on the first wheel // scroll (if it is large enough). if (ie) { wheelPixelsPerUnit = -.53; } else if (gecko) { wheelPixelsPerUnit = 15; } else if (chrome) { wheelPixelsPerUnit = -.7; } else if (safari) { wheelPixelsPerUnit = -1/3; } function wheelEventDelta(e) { var dx = e.wheelDeltaX, dy = e.wheelDeltaY; if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; } if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; } else if (dy == null) { dy = e.wheelDelta; } return {x: dx, y: dy} } function wheelEventPixels(e) { var delta = wheelEventDelta(e); delta.x *= wheelPixelsPerUnit; delta.y *= wheelPixelsPerUnit; return delta } function onScrollWheel(cm, e) { // On Chrome 102, viewport updates somehow stop wheel-based // scrolling. Turning off pointer events during the scroll seems // to avoid the issue. if (chrome && chrome_version == 102) { if (cm.display.chromeScrollHack == null) { cm.display.sizer.style.pointerEvents = "none"; } else { clearTimeout(cm.display.chromeScrollHack); } cm.display.chromeScrollHack = setTimeout(function () { cm.display.chromeScrollHack = null; cm.display.sizer.style.pointerEvents = ""; }, 100); } var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y; var pixelsPerUnit = wheelPixelsPerUnit; if (e.deltaMode === 0) { dx = e.deltaX; dy = e.deltaY; pixelsPerUnit = 1; } var display = cm.display, scroll = display.scroller; // Quit if there's nothing to scroll here var canScrollX = scroll.scrollWidth > scroll.clientWidth; var canScrollY = scroll.scrollHeight > scroll.clientHeight; if (!(dx && canScrollX || dy && canScrollY)) { return } // Webkit browsers on OS X abort momentum scrolls when the target // of the scroll event is removed from the scrollable element. // This hack (see related code in patchDisplay) makes sure the // element is kept around. if (dy && mac && webkit) { outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { for (var i = 0; i < view.length; i++) { if (view[i].node == cur) { cm.display.currentWheelTarget = cur; break outer } } } } // On some browsers, horizontal scrolling will cause redraws to // happen before the gutter has been realigned, causing it to // wriggle around in a most unseemly way. When we have an // estimated pixels/delta value, we just handle horizontal // scrolling entirely here. It'll be slightly off from native, but // better than glitching out. if (dx && !gecko && !presto && pixelsPerUnit != null) { if (dy && canScrollY) { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * pixelsPerUnit)); } setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * pixelsPerUnit)); // Only prevent default scrolling if vertical scrolling is // actually possible. Otherwise, it causes vertical scroll // jitter on OSX trackpads when deltaX is small and deltaY // is large (issue #3579) if (!dy || (dy && canScrollY)) { e_preventDefault(e); } display.wheelStartX = null; // Abort measurement, if in progress return } // 'Project' the visible viewport to cover the area that is being // scrolled into view (if we know enough to estimate it). if (dy && pixelsPerUnit != null) { var pixels = dy * pixelsPerUnit; var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; if (pixels < 0) { top = Math.max(0, top + pixels - 50); } else { bot = Math.min(cm.doc.height, bot + pixels + 50); } updateDisplaySimple(cm, {top: top, bottom: bot}); } if (wheelSamples < 20 && e.deltaMode !== 0) { if (display.wheelStartX == null) { display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; display.wheelDX = dx; display.wheelDY = dy; setTimeout(function () { if (display.wheelStartX == null) { return } var movedX = scroll.scrollLeft - display.wheelStartX; var movedY = scroll.scrollTop - display.wheelStartY; var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || (movedX && display.wheelDX && movedX / display.wheelDX); display.wheelStartX = display.wheelStartY = null; if (!sample) { return } wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); ++wheelSamples; }, 200); } else { display.wheelDX += dx; display.wheelDY += dy; } } } // Selection objects are immutable. A new one is created every time // the selection changes. A selection is one or more non-overlapping // (and non-touching) ranges, sorted, and an integer that indicates // which one is the primary selection (the one that's scrolled into // view, that getCursor returns, etc). var Selection = function(ranges, primIndex) { this.ranges = ranges; this.primIndex = primIndex; }; Selection.prototype.primary = function () { return this.ranges[this.primIndex] }; Selection.prototype.equals = function (other) { if (other == this) { return true } if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false } for (var i = 0; i < this.ranges.length; i++) { var here = this.ranges[i], there = other.ranges[i]; if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false } } return true }; Selection.prototype.deepCopy = function () { var out = []; for (var i = 0; i < this.ranges.length; i++) { out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); } return new Selection(out, this.primIndex) }; Selection.prototype.somethingSelected = function () { for (var i = 0; i < this.ranges.length; i++) { if (!this.ranges[i].empty()) { return true } } return false }; Selection.prototype.contains = function (pos, end) { if (!end) { end = pos; } for (var i = 0; i < this.ranges.length; i++) { var range = this.ranges[i]; if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) { return i } } return -1 }; var Range = function(anchor, head) { this.anchor = anchor; this.head = head; }; Range.prototype.from = function () { return minPos(this.anchor, this.head) }; Range.prototype.to = function () { return maxPos(this.anchor, this.head) }; Range.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch }; // Take an unsorted, potentially overlapping set of ranges, and // build a selection out of it. 'Consumes' ranges array (modifying // it). function normalizeSelection(cm, ranges, primIndex) { var mayTouch = cm && cm.options.selectionsMayTouch; var prim = ranges[primIndex]; ranges.sort(function (a, b) { return cmp(a.from(), b.from()); }); primIndex = indexOf(ranges, prim); for (var i = 1; i < ranges.length; i++) { var cur = ranges[i], prev = ranges[i - 1]; var diff = cmp(prev.to(), cur.from()); if (mayTouch && !cur.empty() ? diff > 0 : diff >= 0) { var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()); var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head; if (i <= primIndex) { --primIndex; } ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)); } } return new Selection(ranges, primIndex) } function simpleSelection(anchor, head) { return new Selection([new Range(anchor, head || anchor)], 0) } // Compute the position of the end of a change (its 'to' property // refers to the pre-change end). function changeEnd(change) { if (!change.text) { return change.to } return Pos(change.from.line + change.text.length - 1, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)) } // Adjust a position to refer to the post-change position of the // same text, or the end of the change if the change covers it. function adjustForChange(pos, change) { if (cmp(pos, change.from) < 0) { return pos } if (cmp(pos, change.to) <= 0) { return changeEnd(change) } var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch; } return Pos(line, ch) } function computeSelAfterChange(doc, change) { var out = []; for (var i = 0; i < doc.sel.ranges.length; i++) { var range = doc.sel.ranges[i]; out.push(new Range(adjustForChange(range.anchor, change), adjustForChange(range.head, change))); } return normalizeSelection(doc.cm, out, doc.sel.primIndex) } function offsetPos(pos, old, nw) { if (pos.line == old.line) { return Pos(nw.line, pos.ch - old.ch + nw.ch) } else { return Pos(nw.line + (pos.line - old.line), pos.ch) } } // Used by replaceSelections to allow moving the selection to the // start or around the replaced test. Hint may be "start" or "around". function computeReplacedSel(doc, changes, hint) { var out = []; var oldPrev = Pos(doc.first, 0), newPrev = oldPrev; for (var i = 0; i < changes.length; i++) { var change = changes[i]; var from = offsetPos(change.from, oldPrev, newPrev); var to = offsetPos(changeEnd(change), oldPrev, newPrev); oldPrev = change.to; newPrev = to; if (hint == "around") { var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0; out[i] = new Range(inv ? to : from, inv ? from : to); } else { out[i] = new Range(from, from); } } return new Selection(out, doc.sel.primIndex) } // Used to get the editor into a consistent state again when options change. function loadMode(cm) { cm.doc.mode = getMode(cm.options, cm.doc.modeOption); resetModeState(cm); } function resetModeState(cm) { cm.doc.iter(function (line) { if (line.stateAfter) { line.stateAfter = null; } if (line.styles) { line.styles = null; } }); cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first; startWorker(cm, 100); cm.state.modeGen++; if (cm.curOp) { regChange(cm); } } // DOCUMENT DATA STRUCTURE // By default, updates that start and end at the beginning of a line // are treated specially, in order to make the association of line // widgets and marker elements with the text behave more intuitive. function isWholeLineUpdate(doc, change) { return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && (!doc.cm || doc.cm.options.wholeLineUpdateBefore) } // Perform a change on the document data structure. function updateDoc(doc, change, markedSpans, estimateHeight) { function spansFor(n) {return markedSpans ? markedSpans[n] : null} function update(line, text, spans) { updateLine(line, text, spans, estimateHeight); signalLater(line, "change", line, change); } function linesFor(start, end) { var result = []; for (var i = start; i < end; ++i) { result.push(new Line(text[i], spansFor(i), estimateHeight)); } return result } var from = change.from, to = change.to, text = change.text; var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; // Adjust the line structure if (change.full) { doc.insert(0, linesFor(0, text.length)); doc.remove(text.length, doc.size - text.length); } else if (isWholeLineUpdate(doc, change)) { // This is a whole-line replace. Treated specially to make // sure line objects move the way they are supposed to. var added = linesFor(0, text.length - 1); update(lastLine, lastLine.text, lastSpans); if (nlines) { doc.remove(from.line, nlines); } if (added.length) { doc.insert(from.line, added); } } else if (firstLine == lastLine) { if (text.length == 1) { update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); } else { var added$1 = linesFor(1, text.length - 1); added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)); update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); doc.insert(from.line + 1, added$1); } } else if (text.length == 1) { update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); doc.remove(from.line + 1, nlines); } else { update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); var added$2 = linesFor(1, text.length - 1); if (nlines > 1) { doc.remove(from.line + 1, nlines - 1); } doc.insert(from.line + 1, added$2); } signalLater(doc, "change", doc, change); } // Call f for all linked documents. function linkedDocs(doc, f, sharedHistOnly) { function propagate(doc, skip, sharedHist) { if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) { var rel = doc.linked[i]; if (rel.doc == skip) { continue } var shared = sharedHist && rel.sharedHist; if (sharedHistOnly && !shared) { continue } f(rel.doc, shared); propagate(rel.doc, doc, shared); } } } propagate(doc, null, true); } // Attach a document to an editor. function attachDoc(cm, doc) { if (doc.cm) { throw new Error("This document is already in use.") } cm.doc = doc; doc.cm = cm; estimateLineHeights(cm); loadMode(cm); setDirectionClass(cm); cm.options.direction = doc.direction; if (!cm.options.lineWrapping) { findMaxLine(cm); } cm.options.mode = doc.modeOption; regChange(cm); } function setDirectionClass(cm) { (cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl"); } function directionChanged(cm) { runInOp(cm, function () { setDirectionClass(cm); regChange(cm); }); } function History(prev) { // Arrays of change events and selections. Doing something adds an // event to done and clears undo. Undoing moves events from done // to undone, redoing moves them in the other direction. this.done = []; this.undone = []; this.undoDepth = prev ? prev.undoDepth : Infinity; // Used to track when changes can be merged into a single undo // event this.lastModTime = this.lastSelTime = 0; this.lastOp = this.lastSelOp = null; this.lastOrigin = this.lastSelOrigin = null; // Used by the isClean() method this.generation = this.maxGeneration = prev ? prev.maxGeneration : 1; } // Create a history change event from an updateDoc-style change // object. function historyChangeFromChange(doc, change) { var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true); return histChange } // Pop all selection events off the end of a history array. Stop at // a change event. function clearSelectionEvents(array) { while (array.length) { var last = lst(array); if (last.ranges) { array.pop(); } else { break } } } // Find the top change event in the history. Pop off selection // events that are in the way. function lastChangeEvent(hist, force) { if (force) { clearSelectionEvents(hist.done); return lst(hist.done) } else if (hist.done.length && !lst(hist.done).ranges) { return lst(hist.done) } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { hist.done.pop(); return lst(hist.done) } } // Register a change in the history. Merges changes that are within // a single operation, or are close together with an origin that // allows merging (starting with "+") into a single event. function addChangeToHistory(doc, change, selAfter, opId) { var hist = doc.history; hist.undone.length = 0; var time = +new Date, cur; var last; if ((hist.lastOp == opId || hist.lastOrigin == change.origin && change.origin && ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) || change.origin.charAt(0) == "*")) && (cur = lastChangeEvent(hist, hist.lastOp == opId))) { // Merge this change into the last event last = lst(cur.changes); if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { // Optimized case for simple insertion -- don't want to add // new changesets for every character typed last.to = changeEnd(change); } else { // Add new sub-event cur.changes.push(historyChangeFromChange(doc, change)); } } else { // Can not be merged, start a new event. var before = lst(hist.done); if (!before || !before.ranges) { pushSelectionToHistory(doc.sel, hist.done); } cur = {changes: [historyChangeFromChange(doc, change)], generation: hist.generation}; hist.done.push(cur); while (hist.done.length > hist.undoDepth) { hist.done.shift(); if (!hist.done[0].ranges) { hist.done.shift(); } } } hist.done.push(selAfter); hist.generation = ++hist.maxGeneration; hist.lastModTime = hist.lastSelTime = time; hist.lastOp = hist.lastSelOp = opId; hist.lastOrigin = hist.lastSelOrigin = change.origin; if (!last) { signal(doc, "historyAdded"); } } function selectionEventCanBeMerged(doc, origin, prev, sel) { var ch = origin.charAt(0); return ch == "*" || ch == "+" && prev.ranges.length == sel.ranges.length && prev.somethingSelected() == sel.somethingSelected() && new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500) } // Called whenever the selection changes, sets the new selection as // the pending selection in the history, and pushes the old pending // selection into the 'done' array when it was significantly // different (in number of selected ranges, emptiness, or time). function addSelectionToHistory(doc, sel, opId, options) { var hist = doc.history, origin = options && options.origin; // A new event is started when the previous origin does not match // the current, or the origins don't allow matching. Origins // starting with * are always merged, those starting with + are // merged when similar and close together in time. if (opId == hist.lastSelOp || (origin && hist.lastSelOrigin == origin && (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) { hist.done[hist.done.length - 1] = sel; } else { pushSelectionToHistory(sel, hist.done); } hist.lastSelTime = +new Date; hist.lastSelOrigin = origin; hist.lastSelOp = opId; if (options && options.clearRedo !== false) { clearSelectionEvents(hist.undone); } } function pushSelectionToHistory(sel, dest) { var top = lst(dest); if (!(top && top.ranges && top.equals(sel))) { dest.push(sel); } } // Used to store marked span information in the history. function attachLocalSpans(doc, change, from, to) { var existing = change["spans_" + doc.id], n = 0; doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) { if (line.markedSpans) { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; } ++n; }); } // When un/re-doing restores text containing marked spans, those // that have been explicitly cleared should not be restored. function removeClearedSpans(spans) { if (!spans) { return null } var out; for (var i = 0; i < spans.length; ++i) { if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i); } } else if (out) { out.push(spans[i]); } } return !out ? spans : out.length ? out : null } // Retrieve and filter the old marked spans stored in a change event. function getOldSpans(doc, change) { var found = change["spans_" + doc.id]; if (!found) { return null } var nw = []; for (var i = 0; i < change.text.length; ++i) { nw.push(removeClearedSpans(found[i])); } return nw } // Used for un/re-doing changes from the history. Combines the // result of computing the existing spans with the set of spans that // existed in the history (so that deleting around a span and then // undoing brings back the span). function mergeOldSpans(doc, change) { var old = getOldSpans(doc, change); var stretched = stretchSpansOverChange(doc, change); if (!old) { return stretched } if (!stretched) { return old } for (var i = 0; i < old.length; ++i) { var oldCur = old[i], stretchCur = stretched[i]; if (oldCur && stretchCur) { spans: for (var j = 0; j < stretchCur.length; ++j) { var span = stretchCur[j]; for (var k = 0; k < oldCur.length; ++k) { if (oldCur[k].marker == span.marker) { continue spans } } oldCur.push(span); } } else if (stretchCur) { old[i] = stretchCur; } } return old } // Used both to provide a JSON-safe object in .getHistory, and, when // detaching a document, to split the history in two function copyHistoryArray(events, newGroup, instantiateSel) { var copy = []; for (var i = 0; i < events.length; ++i) { var event = events[i]; if (event.ranges) { copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event); continue } var changes = event.changes, newChanges = []; copy.push({changes: newChanges}); for (var j = 0; j < changes.length; ++j) { var change = changes[j], m = (void 0); newChanges.push({from: change.from, to: change.to, text: change.text}); if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) { if (indexOf(newGroup, Number(m[1])) > -1) { lst(newChanges)[prop] = change[prop]; delete change[prop]; } } } } } } return copy } // The 'scroll' parameter given to many of these indicated whether // the new cursor position should be scrolled into view after // modifying the selection. // If shift is held or the extend flag is set, extends a range to // include a given position (and optionally a second position). // Otherwise, simply returns the range between the given positions. // Used for cursor motion and such. function extendRange(range, head, other, extend) { if (extend) { var anchor = range.anchor; if (other) { var posBefore = cmp(head, anchor) < 0; if (posBefore != (cmp(other, anchor) < 0)) { anchor = head; head = other; } else if (posBefore != (cmp(head, other) < 0)) { head = other; } } return new Range(anchor, head) } else { return new Range(other || head, head) } } // Extend the primary selection range, discard the rest. function extendSelection(doc, head, other, options, extend) { if (extend == null) { extend = doc.cm && (doc.cm.display.shift || doc.extend); } setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options); } // Extend all selections (pos is an array of selections with length // equal the number of selections) function extendSelections(doc, heads, options) { var out = []; var extend = doc.cm && (doc.cm.display.shift || doc.extend); for (var i = 0; i < doc.sel.ranges.length; i++) { out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend); } var newSel = normalizeSelection(doc.cm, out, doc.sel.primIndex); setSelection(doc, newSel, options); } // Updates a single range in the selection. function replaceOneSelection(doc, i, range, options) { var ranges = doc.sel.ranges.slice(0); ranges[i] = range; setSelection(doc, normalizeSelection(doc.cm, ranges, doc.sel.primIndex), options); } // Reset the selection to a single range. function setSimpleSelection(doc, anchor, head, options) { setSelection(doc, simpleSelection(anchor, head), options); } // Give beforeSelectionChange handlers a change to influence a // selection update. function filterSelectionChange(doc, sel, options) { var obj = { ranges: sel.ranges, update: function(ranges) { this.ranges = []; for (var i = 0; i < ranges.length; i++) { this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), clipPos(doc, ranges[i].head)); } }, origin: options && options.origin }; signal(doc, "beforeSelectionChange", doc, obj); if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj); } if (obj.ranges != sel.ranges) { return normalizeSelection(doc.cm, obj.ranges, obj.ranges.length - 1) } else { return sel } } function setSelectionReplaceHistory(doc, sel, options) { var done = doc.history.done, last = lst(done); if (last && last.ranges) { done[done.length - 1] = sel; setSelectionNoUndo(doc, sel, options); } else { setSelection(doc, sel, options); } } // Set a new selection. function setSelection(doc, sel, options) { setSelectionNoUndo(doc, sel, options); addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); } function setSelectionNoUndo(doc, sel, options) { if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) { sel = filterSelectionChange(doc, sel, options); } var bias = options && options.bias || (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)); if (!(options && options.scroll === false) && doc.cm && doc.cm.getOption("readOnly") != "nocursor") { ensureCursorVisible(doc.cm); } } function setSelectionInner(doc, sel) { if (sel.equals(doc.sel)) { return } doc.sel = sel; if (doc.cm) { doc.cm.curOp.updateInput = 1; doc.cm.curOp.selectionChanged = true; signalCursorActivity(doc.cm); } signalLater(doc, "cursorActivity", doc); } // Verify that the selection does not partially select any atomic // marked ranges. function reCheckSelection(doc) { setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false)); } // Return a selection that does not partially select any atomic // ranges. function skipAtomicInSelection(doc, sel, bias, mayClear) { var out; for (var i = 0; i < sel.ranges.length; i++) { var range = sel.ranges[i]; var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i]; var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear); var newHead = range.head == range.anchor ? newAnchor : skipAtomic(doc, range.head, old && old.head, bias, mayClear); if (out || newAnchor != range.anchor || newHead != range.head) { if (!out) { out = sel.ranges.slice(0, i); } out[i] = new Range(newAnchor, newHead); } } return out ? normalizeSelection(doc.cm, out, sel.primIndex) : sel } function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { var line = getLine(doc, pos.line); if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { var sp = line.markedSpans[i], m = sp.marker; // Determine if we should prevent the cursor being placed to the left/right of an atomic marker // Historically this was determined using the inclusiveLeft/Right option, but the new way to control it // is with selectLeft/Right var preventCursorLeft = ("selectLeft" in m) ? !m.selectLeft : m.inclusiveLeft; var preventCursorRight = ("selectRight" in m) ? !m.selectRight : m.inclusiveRight; if ((sp.from == null || (preventCursorLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && (sp.to == null || (preventCursorRight ? sp.to >= pos.ch : sp.to > pos.ch))) { if (mayClear) { signal(m, "beforeCursorEnter"); if (m.explicitlyCleared) { if (!line.markedSpans) { break } else {--i; continue} } } if (!m.atomic) { continue } if (oldPos) { var near = m.find(dir < 0 ? 1 : -1), diff = (void 0); if (dir < 0 ? preventCursorRight : preventCursorLeft) { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); } if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) { return skipAtomicInner(doc, near, pos, dir, mayClear) } } var far = m.find(dir < 0 ? -1 : 1); if (dir < 0 ? preventCursorLeft : preventCursorRight) { far = movePos(doc, far, dir, far.line == pos.line ? line : null); } return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null } } } return pos } // Ensure a given position is not inside an atomic range. function skipAtomic(doc, pos, oldPos, bias, mayClear) { var dir = bias || 1; var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) || skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true)); if (!found) { doc.cantEdit = true; return Pos(doc.first, 0) } return found } function movePos(doc, pos, dir, line) { if (dir < 0 && pos.ch == 0) { if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) } else { return null } } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) } else { return null } } else { return new Pos(pos.line, pos.ch + dir) } } function selectAll(cm) { cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll); } // UPDATING // Allow "beforeChange" event handlers to influence a change function filterChange(doc, change, update) { var obj = { canceled: false, from: change.from, to: change.to, text: change.text, origin: change.origin, cancel: function () { return obj.canceled = true; } }; if (update) { obj.update = function (from, to, text, origin) { if (from) { obj.from = clipPos(doc, from); } if (to) { obj.to = clipPos(doc, to); } if (text) { obj.text = text; } if (origin !== undefined) { obj.origin = origin; } }; } signal(doc, "beforeChange", doc, obj); if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj); } if (obj.canceled) { if (doc.cm) { doc.cm.curOp.updateInput = 2; } return null } return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin} } // Apply a change to a document, and add it to the document's // history, and propagating it to all linked documents. function makeChange(doc, change, ignoreReadOnly) { if (doc.cm) { if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) } if (doc.cm.state.suppressEdits) { return } } if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { change = filterChange(doc, change, true); if (!change) { return } } // Possibly split or suppress the update based on the presence // of read-only spans in its range. var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); if (split) { for (var i = split.length - 1; i >= 0; --i) { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text, origin: change.origin}); } } else { makeChangeInner(doc, change); } } function makeChangeInner(doc, change) { if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return } var selAfter = computeSelAfterChange(doc, change); addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); var rebased = []; linkedDocs(doc, function (doc, sharedHist) { if (!sharedHist && indexOf(rebased, doc.history) == -1) { rebaseHist(doc.history, change); rebased.push(doc.history); } makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); }); } // Revert a change stored in a document's history. function makeChangeFromHistory(doc, type, allowSelectionOnly) { var suppress = doc.cm && doc.cm.state.suppressEdits; if (suppress && !allowSelectionOnly) { return } var hist = doc.history, event, selAfter = doc.sel; var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done; // Verify that there is a useable event (so that ctrl-z won't // needlessly clear selection events) var i = 0; for (; i < source.length; i++) { event = source[i]; if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) { break } } if (i == source.length) { return } hist.lastOrigin = hist.lastSelOrigin = null; for (;;) { event = source.pop(); if (event.ranges) { pushSelectionToHistory(event, dest); if (allowSelectionOnly && !event.equals(doc.sel)) { setSelection(doc, event, {clearRedo: false}); return } selAfter = event; } else if (suppress) { source.push(event); return } else { break } } // Build up a reverse change object to add to the opposite history // stack (redo when undoing, and vice versa). var antiChanges = []; pushSelectionToHistory(selAfter, dest); dest.push({changes: antiChanges, generation: hist.generation}); hist.generation = event.generation || ++hist.maxGeneration; var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); var loop = function ( i ) { var change = event.changes[i]; change.origin = type; if (filter && !filterChange(doc, change, false)) { source.length = 0; return {} } antiChanges.push(historyChangeFromChange(doc, change)); var after = i ? computeSelAfterChange(doc, change) : lst(source); makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); } var rebased = []; // Propagate to the linked documents linkedDocs(doc, function (doc, sharedHist) { if (!sharedHist && indexOf(rebased, doc.history) == -1) { rebaseHist(doc.history, change); rebased.push(doc.history); } makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); }); }; for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) { var returned = loop( i$1 ); if ( returned ) return returned.v; } } // Sub-views need their line numbers shifted when text is added // above or below them in the parent document. function shiftDoc(doc, distance) { if (distance == 0) { return } doc.first += distance; doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range( Pos(range.anchor.line + distance, range.anchor.ch), Pos(range.head.line + distance, range.head.ch) ); }), doc.sel.primIndex); if (doc.cm) { regChange(doc.cm, doc.first, doc.first - distance, distance); for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) { regLineChange(doc.cm, l, "gutter"); } } } // More lower-level change function, handling only a single document // (not linked ones). function makeChangeSingleDoc(doc, change, selAfter, spans) { if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) } if (change.to.line < doc.first) { shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); return } if (change.from.line > doc.lastLine()) { return } // Clip the change to the size of this doc if (change.from.line < doc.first) { var shift = change.text.length - 1 - (doc.first - change.from.line); shiftDoc(doc, shift); change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), text: [lst(change.text)], origin: change.origin}; } var last = doc.lastLine(); if (change.to.line > last) { change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), text: [change.text[0]], origin: change.origin}; } change.removed = getBetween(doc, change.from, change.to); if (!selAfter) { selAfter = computeSelAfterChange(doc, change); } if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans); } else { updateDoc(doc, change, spans); } setSelectionNoUndo(doc, selAfter, sel_dontScroll); if (doc.cantEdit && skipAtomic(doc, Pos(doc.firstLine(), 0))) { doc.cantEdit = false; } } // Handle the interaction of a change to a document with the editor // that this document is part of. function makeChangeSingleDocInEditor(cm, change, spans) { var doc = cm.doc, display = cm.display, from = change.from, to = change.to; var recomputeMaxLength = false, checkWidthStart = from.line; if (!cm.options.lineWrapping) { checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); doc.iter(checkWidthStart, to.line + 1, function (line) { if (line == display.maxLine) { recomputeMaxLength = true; return true } }); } if (doc.sel.contains(change.from, change.to) > -1) { signalCursorActivity(cm); } updateDoc(doc, change, spans, estimateHeight(cm)); if (!cm.options.lineWrapping) { doc.iter(checkWidthStart, from.line + change.text.length, function (line) { var len = lineLength(line); if (len > display.maxLineLength) { display.maxLine = line; display.maxLineLength = len; display.maxLineChanged = true; recomputeMaxLength = false; } }); if (recomputeMaxLength) { cm.curOp.updateMaxLine = true; } } retreatFrontier(doc, from.line); startWorker(cm, 400); var lendiff = change.text.length - (to.line - from.line) - 1; // Remember that these lines changed, for updating the display if (change.full) { regChange(cm); } else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) { regLineChange(cm, from.line, "text"); } else { regChange(cm, from.line, to.line + 1, lendiff); } var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change"); if (changeHandler || changesHandler) { var obj = { from: from, to: to, text: change.text, removed: change.removed, origin: change.origin }; if (changeHandler) { signalLater(cm, "change", cm, obj); } if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); } } cm.display.selForContextMenu = null; } function replaceRange(doc, code, from, to, origin) { var assign; if (!to) { to = from; } if (cmp(to, from) < 0) { (assign = [to, from], from = assign[0], to = assign[1]); } if (typeof code == "string") { code = doc.splitLines(code); } makeChange(doc, {from: from, to: to, text: code, origin: origin}); } // Rebasing/resetting history to deal with externally-sourced changes function rebaseHistSelSingle(pos, from, to, diff) { if (to < pos.line) { pos.line += diff; } else if (from < pos.line) { pos.line = from; pos.ch = 0; } } // Tries to rebase an array of history events given a change in the // document. If the change touches the same lines as the event, the // event, and everything 'behind' it, is discarded. If the change is // before the event, the event's positions are updated. Uses a // copy-on-write scheme for the positions, to avoid having to // reallocate them all on every rebase, but also avoid problems with // shared position objects being unsafely updated. function rebaseHistArray(array, from, to, diff) { for (var i = 0; i < array.length; ++i) { var sub = array[i], ok = true; if (sub.ranges) { if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; } for (var j = 0; j < sub.ranges.length; j++) { rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff); rebaseHistSelSingle(sub.ranges[j].head, from, to, diff); } continue } for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) { var cur = sub.changes[j$1]; if (to < cur.from.line) { cur.from = Pos(cur.from.line + diff, cur.from.ch); cur.to = Pos(cur.to.line + diff, cur.to.ch); } else if (from <= cur.to.line) { ok = false; break } } if (!ok) { array.splice(0, i + 1); i = 0; } } } function rebaseHist(hist, change) { var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; rebaseHistArray(hist.done, from, to, diff); rebaseHistArray(hist.undone, from, to, diff); } // Utility for applying a change to a line by handle or number, // returning the number and optionally registering the line as // changed. function changeLine(doc, handle, changeType, op) { var no = handle, line = handle; if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)); } else { no = lineNo(handle); } if (no == null) { return null } if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType); } return line } // The document is represented as a BTree consisting of leaves, with // chunk of lines in them, and branches, with up to ten leaves or // other branch nodes below them. The top node is always a branch // node, and is the document object itself (meaning it has // additional methods and properties). // // All nodes have parent links. The tree is used both to go from // line numbers to line objects, and to go from objects to numbers. // It also indexes by height, and is used to convert between height // and line object, and to find the total height of the document. // // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html function LeafChunk(lines) { this.lines = lines; this.parent = null; var height = 0; for (var i = 0; i < lines.length; ++i) { lines[i].parent = this; height += lines[i].height; } this.height = height; } LeafChunk.prototype = { chunkSize: function() { return this.lines.length }, // Remove the n lines at offset 'at'. removeInner: function(at, n) { for (var i = at, e = at + n; i < e; ++i) { var line = this.lines[i]; this.height -= line.height; cleanUpLine(line); signalLater(line, "delete"); } this.lines.splice(at, n); }, // Helper used to collapse a small branch into a single leaf. collapse: function(lines) { lines.push.apply(lines, this.lines); }, // Insert the given array of lines at offset 'at', count them as // having the given height. insertInner: function(at, lines, height) { this.height += height; this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); for (var i = 0; i < lines.length; ++i) { lines[i].parent = this; } }, // Used to iterate over a part of the tree. iterN: function(at, n, op) { for (var e = at + n; at < e; ++at) { if (op(this.lines[at])) { return true } } } }; function BranchChunk(children) { this.children = children; var size = 0, height = 0; for (var i = 0; i < children.length; ++i) { var ch = children[i]; size += ch.chunkSize(); height += ch.height; ch.parent = this; } this.size = size; this.height = height; this.parent = null; } BranchChunk.prototype = { chunkSize: function() { return this.size }, removeInner: function(at, n) { this.size -= n; for (var i = 0; i < this.children.length; ++i) { var child = this.children[i], sz = child.chunkSize(); if (at < sz) { var rm = Math.min(n, sz - at), oldHeight = child.height; child.removeInner(at, rm); this.height -= oldHeight - child.height; if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } if ((n -= rm) == 0) { break } at = 0; } else { at -= sz; } } // If the result is smaller than 25 lines, ensure that it is a // single leaf node. if (this.size - n < 25 && (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { var lines = []; this.collapse(lines); this.children = [new LeafChunk(lines)]; this.children[0].parent = this; } }, collapse: function(lines) { for (var i = 0; i < this.children.length; ++i) { this.children[i].collapse(lines); } }, insertInner: function(at, lines, height) { this.size += lines.length; this.height += height; for (var i = 0; i < this.children.length; ++i) { var child = this.children[i], sz = child.chunkSize(); if (at <= sz) { child.insertInner(at, lines, height); if (child.lines && child.lines.length > 50) { // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. var remaining = child.lines.length % 25 + 25; for (var pos = remaining; pos < child.lines.length;) { var leaf = new LeafChunk(child.lines.slice(pos, pos += 25)); child.height -= leaf.height; this.children.splice(++i, 0, leaf); leaf.parent = this; } child.lines = child.lines.slice(0, remaining); this.maybeSpill(); } break } at -= sz; } }, // When a node has grown, check whether it should be split. maybeSpill: function() { if (this.children.length <= 10) { return } var me = this; do { var spilled = me.children.splice(me.children.length - 5, 5); var sibling = new BranchChunk(spilled); if (!me.parent) { // Become the parent node var copy = new BranchChunk(me.children); copy.parent = me; me.children = [copy, sibling]; me = copy; } else { me.size -= sibling.size; me.height -= sibling.height; var myIndex = indexOf(me.parent.children, me); me.parent.children.splice(myIndex + 1, 0, sibling); } sibling.parent = me.parent; } while (me.children.length > 10) me.parent.maybeSpill(); }, iterN: function(at, n, op) { for (var i = 0; i < this.children.length; ++i) { var child = this.children[i], sz = child.chunkSize(); if (at < sz) { var used = Math.min(n, sz - at); if (child.iterN(at, used, op)) { return true } if ((n -= used) == 0) { break } at = 0; } else { at -= sz; } } } }; // Line widgets are block elements displayed above or below a line. var LineWidget = function(doc, node, options) { if (options) { for (var opt in options) { if (options.hasOwnProperty(opt)) { this[opt] = options[opt]; } } } this.doc = doc; this.node = node; }; LineWidget.prototype.clear = function () { var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); if (no == null || !ws) { return } for (var i = 0; i < ws.length; ++i) { if (ws[i] == this) { ws.splice(i--, 1); } } if (!ws.length) { line.widgets = null; } var height = widgetHeight(this); updateLineHeight(line, Math.max(0, line.height - height)); if (cm) { runInOp(cm, function () { adjustScrollWhenAboveVisible(cm, line, -height); regLineChange(cm, no, "widget"); }); signalLater(cm, "lineWidgetCleared", cm, this, no); } }; LineWidget.prototype.changed = function () { var this$1 = this; var oldH = this.height, cm = this.doc.cm, line = this.line; this.height = null; var diff = widgetHeight(this) - oldH; if (!diff) { return } if (!lineIsHidden(this.doc, line)) { updateLineHeight(line, line.height + diff); } if (cm) { runInOp(cm, function () { cm.curOp.forceUpdate = true; adjustScrollWhenAboveVisible(cm, line, diff); signalLater(cm, "lineWidgetChanged", cm, this$1, lineNo(line)); }); } }; eventMixin(LineWidget); function adjustScrollWhenAboveVisible(cm, line, diff) { if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) { addToScrollTop(cm, diff); } } function addLineWidget(doc, handle, node, options) { var widget = new LineWidget(doc, node, options); var cm = doc.cm; if (cm && widget.noHScroll) { cm.display.alignWidgets = true; } changeLine(doc, handle, "widget", function (line) { var widgets = line.widgets || (line.widgets = []); if (widget.insertAt == null) { widgets.push(widget); } else { widgets.splice(Math.min(widgets.length, Math.max(0, widget.insertAt)), 0, widget); } widget.line = line; if (cm && !lineIsHidden(doc, line)) { var aboveVisible = heightAtLine(line) < doc.scrollTop; updateLineHeight(line, line.height + widgetHeight(widget)); if (aboveVisible) { addToScrollTop(cm, widget.height); } cm.curOp.forceUpdate = true; } return true }); if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)); } return widget } // TEXTMARKERS // Created with markText and setBookmark methods. A TextMarker is a // handle that can be used to clear or find a marked position in the // document. Line objects hold arrays (markedSpans) containing // {from, to, marker} object pointing to such marker objects, and // indicating that such a marker is present on that line. Multiple // lines may point to the same marker when it spans across lines. // The spans will have null for their from/to properties when the // marker continues beyond the start/end of the line. Markers have // links back to the lines they currently touch. // Collapsed markers have unique ids, in order to be able to order // them, which is needed for uniquely determining an outer marker // when they overlap (they may nest, but not partially overlap). var nextMarkerId = 0; var TextMarker = function(doc, type) { this.lines = []; this.type = type; this.doc = doc; this.id = ++nextMarkerId; }; // Clear the marker. TextMarker.prototype.clear = function () { if (this.explicitlyCleared) { return } var cm = this.doc.cm, withOp = cm && !cm.curOp; if (withOp) { startOperation(cm); } if (hasHandler(this, "clear")) { var found = this.find(); if (found) { signalLater(this, "clear", found.from, found.to); } } var min = null, max = null; for (var i = 0; i < this.lines.length; ++i) { var line = this.lines[i]; var span = getMarkedSpanFor(line.markedSpans, this); if (cm && !this.collapsed) { regLineChange(cm, lineNo(line), "text"); } else if (cm) { if (span.to != null) { max = lineNo(line); } if (span.from != null) { min = lineNo(line); } } line.markedSpans = removeMarkedSpan(line.markedSpans, span); if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm) { updateLineHeight(line, textHeight(cm.display)); } } if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) { var visual = visualLine(this.lines[i$1]), len = lineLength(visual); if (len > cm.display.maxLineLength) { cm.display.maxLine = visual; cm.display.maxLineLength = len; cm.display.maxLineChanged = true; } } } if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1); } this.lines.length = 0; this.explicitlyCleared = true; if (this.atomic && this.doc.cantEdit) { this.doc.cantEdit = false; if (cm) { reCheckSelection(cm.doc); } } if (cm) { signalLater(cm, "markerCleared", cm, this, min, max); } if (withOp) { endOperation(cm); } if (this.parent) { this.parent.clear(); } }; // Find the position of the marker in the document. Returns a {from, // to} object by default. Side can be passed to get a specific side // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the // Pos objects returned contain a line object, rather than a line // number (used to prevent looking up the same line twice). TextMarker.prototype.find = function (side, lineObj) { if (side == null && this.type == "bookmark") { side = 1; } var from, to; for (var i = 0; i < this.lines.length; ++i) { var line = this.lines[i]; var span = getMarkedSpanFor(line.markedSpans, this); if (span.from != null) { from = Pos(lineObj ? line : lineNo(line), span.from); if (side == -1) { return from } } if (span.to != null) { to = Pos(lineObj ? line : lineNo(line), span.to); if (side == 1) { return to } } } return from && {from: from, to: to} }; // Signals that the marker's widget changed, and surrounding layout // should be recomputed. TextMarker.prototype.changed = function () { var this$1 = this; var pos = this.find(-1, true), widget = this, cm = this.doc.cm; if (!pos || !cm) { return } runInOp(cm, function () { var line = pos.line, lineN = lineNo(pos.line); var view = findViewForLine(cm, lineN); if (view) { clearLineMeasurementCacheFor(view); cm.curOp.selectionChanged = cm.curOp.forceUpdate = true; } cm.curOp.updateMaxLine = true; if (!lineIsHidden(widget.doc, line) && widget.height != null) { var oldHeight = widget.height; widget.height = null; var dHeight = widgetHeight(widget) - oldHeight; if (dHeight) { updateLineHeight(line, line.height + dHeight); } } signalLater(cm, "markerChanged", cm, this$1); }); }; TextMarker.prototype.attachLine = function (line) { if (!this.lines.length && this.doc.cm) { var op = this.doc.cm.curOp; if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); } } this.lines.push(line); }; TextMarker.prototype.detachLine = function (line) { this.lines.splice(indexOf(this.lines, line), 1); if (!this.lines.length && this.doc.cm) { var op = this.doc.cm.curOp ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); } }; eventMixin(TextMarker); // Create a marker, wire it up to the right lines, and function markText(doc, from, to, options, type) { // Shared markers (across linked documents) are handled separately // (markTextShared will call out to this again, once per // document). if (options && options.shared) { return markTextShared(doc, from, to, options, type) } // Ensure we are in an operation. if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) } var marker = new TextMarker(doc, type), diff = cmp(from, to); if (options) { copyObj(options, marker, false); } // Don't connect empty markers unless clearWhenEmpty is false if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) { return marker } if (marker.replacedWith) { // Showing up as a widget implies collapsed (widget replaces text) marker.collapsed = true; marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget"); if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true"); } if (options.insertLeft) { marker.widgetNode.insertLeft = true; } } if (marker.collapsed) { if (conflictingCollapsedRange(doc, from.line, from, to, marker) || from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) { throw new Error("Inserting collapsed marker partially overlapping an existing one") } seeCollapsedSpans(); } if (marker.addToHistory) { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); } var curLine = from.line, cm = doc.cm, updateMaxLine; doc.iter(curLine, to.line + 1, function (line) { if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) { updateMaxLine = true; } if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); } addMarkedSpan(line, new MarkedSpan(marker, curLine == from.line ? from.ch : null, curLine == to.line ? to.ch : null), doc.cm && doc.cm.curOp); ++curLine; }); // lineIsHidden depends on the presence of the spans, so needs a second pass if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) { if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); } }); } if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }); } if (marker.readOnly) { seeReadOnlySpans(); if (doc.history.done.length || doc.history.undone.length) { doc.clearHistory(); } } if (marker.collapsed) { marker.id = ++nextMarkerId; marker.atomic = true; } if (cm) { // Sync editor state if (updateMaxLine) { cm.curOp.updateMaxLine = true; } if (marker.collapsed) { regChange(cm, from.line, to.line + 1); } else if (marker.className || marker.startStyle || marker.endStyle || marker.css || marker.attributes || marker.title) { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text"); } } if (marker.atomic) { reCheckSelection(cm.doc); } signalLater(cm, "markerAdded", cm, marker); } return marker } // SHARED TEXTMARKERS // A shared marker spans multiple linked documents. It is // implemented as a meta-marker-object controlling multiple normal // markers. var SharedTextMarker = function(markers, primary) { this.markers = markers; this.primary = primary; for (var i = 0; i < markers.length; ++i) { markers[i].parent = this; } }; SharedTextMarker.prototype.clear = function () { if (this.explicitlyCleared) { return } this.explicitlyCleared = true; for (var i = 0; i < this.markers.length; ++i) { this.markers[i].clear(); } signalLater(this, "clear"); }; SharedTextMarker.prototype.find = function (side, lineObj) { return this.primary.find(side, lineObj) }; eventMixin(SharedTextMarker); function markTextShared(doc, from, to, options, type) { options = copyObj(options); options.shared = false; var markers = [markText(doc, from, to, options, type)], primary = markers[0]; var widget = options.widgetNode; linkedDocs(doc, function (doc) { if (widget) { options.widgetNode = widget.cloneNode(true); } markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); for (var i = 0; i < doc.linked.length; ++i) { if (doc.linked[i].isParent) { return } } primary = lst(markers); }); return new SharedTextMarker(markers, primary) } function findSharedMarkers(doc) { return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; }) } function copySharedMarkers(doc, markers) { for (var i = 0; i < markers.length; i++) { var marker = markers[i], pos = marker.find(); var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to); if (cmp(mFrom, mTo)) { var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type); marker.markers.push(subMark); subMark.parent = marker; } } } function detachSharedMarkers(markers) { var loop = function ( i ) { var marker = markers[i], linked = [marker.primary.doc]; linkedDocs(marker.primary.doc, function (d) { return linked.push(d); }); for (var j = 0; j < marker.markers.length; j++) { var subMarker = marker.markers[j]; if (indexOf(linked, subMarker.doc) == -1) { subMarker.parent = null; marker.markers.splice(j--, 1); } } }; for (var i = 0; i < markers.length; i++) loop( i ); } var nextDocId = 0; var Doc = function(text, mode, firstLine, lineSep, direction) { if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) } if (firstLine == null) { firstLine = 0; } BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); this.first = firstLine; this.scrollTop = this.scrollLeft = 0; this.cantEdit = false; this.cleanGeneration = 1; this.modeFrontier = this.highlightFrontier = firstLine; var start = Pos(firstLine, 0); this.sel = simpleSelection(start); this.history = new History(null); this.id = ++nextDocId; this.modeOption = mode; this.lineSep = lineSep; this.direction = (direction == "rtl") ? "rtl" : "ltr"; this.extend = false; if (typeof text == "string") { text = this.splitLines(text); } updateDoc(this, {from: start, to: start, text: text}); setSelection(this, simpleSelection(start), sel_dontScroll); }; Doc.prototype = createObj(BranchChunk.prototype, { constructor: Doc, // Iterate over the document. Supports two forms -- with only one // argument, it calls that for each line in the document. With // three, it iterates over the range given by the first two (with // the second being non-inclusive). iter: function(from, to, op) { if (op) { this.iterN(from - this.first, to - from, op); } else { this.iterN(this.first, this.first + this.size, from); } }, // Non-public interface for adding and removing lines. insert: function(at, lines) { var height = 0; for (var i = 0; i < lines.length; ++i) { height += lines[i].height; } this.insertInner(at - this.first, lines, height); }, remove: function(at, n) { this.removeInner(at - this.first, n); }, // From here, the methods are part of the public interface. Most // are also available from CodeMirror (editor) instances. getValue: function(lineSep) { var lines = getLines(this, this.first, this.first + this.size); if (lineSep === false) { return lines } return lines.join(lineSep || this.lineSeparator()) }, setValue: docMethodOp(function(code) { var top = Pos(this.first, 0), last = this.first + this.size - 1; makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), text: this.splitLines(code), origin: "setValue", full: true}, true); if (this.cm) { scrollToCoords(this.cm, 0, 0); } setSelection(this, simpleSelection(top), sel_dontScroll); }), replaceRange: function(code, from, to, origin) { from = clipPos(this, from); to = to ? clipPos(this, to) : from; replaceRange(this, code, from, to, origin); }, getRange: function(from, to, lineSep) { var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); if (lineSep === false) { return lines } if (lineSep === '') { return lines.join('') } return lines.join(lineSep || this.lineSeparator()) }, getLine: function(line) {var l = this.getLineHandle(line); return l && l.text}, getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }}, getLineNumber: function(line) {return lineNo(line)}, getLineHandleVisualStart: function(line) { if (typeof line == "number") { line = getLine(this, line); } return visualLine(line) }, lineCount: function() {return this.size}, firstLine: function() {return this.first}, lastLine: function() {return this.first + this.size - 1}, clipPos: function(pos) {return clipPos(this, pos)}, getCursor: function(start) { var range = this.sel.primary(), pos; if (start == null || start == "head") { pos = range.head; } else if (start == "anchor") { pos = range.anchor; } else if (start == "end" || start == "to" || start === false) { pos = range.to(); } else { pos = range.from(); } return pos }, listSelections: function() { return this.sel.ranges }, somethingSelected: function() {return this.sel.somethingSelected()}, setCursor: docMethodOp(function(line, ch, options) { setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options); }), setSelection: docMethodOp(function(anchor, head, options) { setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options); }), extendSelection: docMethodOp(function(head, other, options) { extendSelection(this, clipPos(this, head), other && clipPos(this, other), options); }), extendSelections: docMethodOp(function(heads, options) { extendSelections(this, clipPosArray(this, heads), options); }), extendSelectionsBy: docMethodOp(function(f, options) { var heads = map(this.sel.ranges, f); extendSelections(this, clipPosArray(this, heads), options); }), setSelections: docMethodOp(function(ranges, primary, options) { if (!ranges.length) { return } var out = []; for (var i = 0; i < ranges.length; i++) { out[i] = new Range(clipPos(this, ranges[i].anchor), clipPos(this, ranges[i].head || ranges[i].anchor)); } if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); } setSelection(this, normalizeSelection(this.cm, out, primary), options); }), addSelection: docMethodOp(function(anchor, head, options) { var ranges = this.sel.ranges.slice(0); ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))); setSelection(this, normalizeSelection(this.cm, ranges, ranges.length - 1), options); }), getSelection: function(lineSep) { var ranges = this.sel.ranges, lines; for (var i = 0; i < ranges.length; i++) { var sel = getBetween(this, ranges[i].from(), ranges[i].to()); lines = lines ? lines.concat(sel) : sel; } if (lineSep === false) { return lines } else { return lines.join(lineSep || this.lineSeparator()) } }, getSelections: function(lineSep) { var parts = [], ranges = this.sel.ranges; for (var i = 0; i < ranges.length; i++) { var sel = getBetween(this, ranges[i].from(), ranges[i].to()); if (lineSep !== false) { sel = sel.join(lineSep || this.lineSeparator()); } parts[i] = sel; } return parts }, replaceSelection: function(code, collapse, origin) { var dup = []; for (var i = 0; i < this.sel.ranges.length; i++) { dup[i] = code; } this.replaceSelections(dup, collapse, origin || "+input"); }, replaceSelections: docMethodOp(function(code, collapse, origin) { var changes = [], sel = this.sel; for (var i = 0; i < sel.ranges.length; i++) { var range = sel.ranges[i]; changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin}; } var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse); for (var i$1 = changes.length - 1; i$1 >= 0; i$1--) { makeChange(this, changes[i$1]); } if (newSel) { setSelectionReplaceHistory(this, newSel); } else if (this.cm) { ensureCursorVisible(this.cm); } }), undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}), redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}), undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}), redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}), setExtending: function(val) {this.extend = val;}, getExtending: function() {return this.extend}, historySize: function() { var hist = this.history, done = 0, undone = 0; for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done; } } for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone; } } return {undo: done, redo: undone} }, clearHistory: function() { var this$1 = this; this.history = new History(this.history); linkedDocs(this, function (doc) { return doc.history = this$1.history; }, true); }, markClean: function() { this.cleanGeneration = this.changeGeneration(true); }, changeGeneration: function(forceSplit) { if (forceSplit) { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; } return this.history.generation }, isClean: function (gen) { return this.history.generation == (gen || this.cleanGeneration) }, getHistory: function() { return {done: copyHistoryArray(this.history.done), undone: copyHistoryArray(this.history.undone)} }, setHistory: function(histData) { var hist = this.history = new History(this.history); hist.done = copyHistoryArray(histData.done.slice(0), null, true); hist.undone = copyHistoryArray(histData.undone.slice(0), null, true); }, setGutterMarker: docMethodOp(function(line, gutterID, value) { return changeLine(this, line, "gutter", function (line) { var markers = line.gutterMarkers || (line.gutterMarkers = {}); markers[gutterID] = value; if (!value && isEmpty(markers)) { line.gutterMarkers = null; } return true }) }), clearGutter: docMethodOp(function(gutterID) { var this$1 = this; this.iter(function (line) { if (line.gutterMarkers && line.gutterMarkers[gutterID]) { changeLine(this$1, line, "gutter", function () { line.gutterMarkers[gutterID] = null; if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null; } return true }); } }); }), lineInfo: function(line) { var n; if (typeof line == "number") { if (!isLine(this, line)) { return null } n = line; line = getLine(this, line); if (!line) { return null } } else { n = lineNo(line); if (n == null) { return null } } return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, widgets: line.widgets} }, addLineClass: docMethodOp(function(handle, where, cls) { return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : where == "gutter" ? "gutterClass" : "wrapClass"; if (!line[prop]) { line[prop] = cls; } else if (classTest(cls).test(line[prop])) { return false } else { line[prop] += " " + cls; } return true }) }), removeLineClass: docMethodOp(function(handle, where, cls) { return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : where == "gutter" ? "gutterClass" : "wrapClass"; var cur = line[prop]; if (!cur) { return false } else if (cls == null) { line[prop] = null; } else { var found = cur.match(classTest(cls)); if (!found) { return false } var end = found.index + found[0].length; line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; } return true }) }), addLineWidget: docMethodOp(function(handle, node, options) { return addLineWidget(this, handle, node, options) }), removeLineWidget: function(widget) { widget.clear(); }, markText: function(from, to, options) { return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range") }, setBookmark: function(pos, options) { var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), insertLeft: options && options.insertLeft, clearWhenEmpty: false, shared: options && options.shared, handleMouseEvents: options && options.handleMouseEvents}; pos = clipPos(this, pos); return markText(this, pos, pos, realOpts, "bookmark") }, findMarksAt: function(pos) { pos = clipPos(this, pos); var markers = [], spans = getLine(this, pos.line).markedSpans; if (spans) { for (var i = 0; i < spans.length; ++i) { var span = spans[i]; if ((span.from == null || span.from <= pos.ch) && (span.to == null || span.to >= pos.ch)) { markers.push(span.marker.parent || span.marker); } } } return markers }, findMarks: function(from, to, filter) { from = clipPos(this, from); to = clipPos(this, to); var found = [], lineNo = from.line; this.iter(from.line, to.line + 1, function (line) { var spans = line.markedSpans; if (spans) { for (var i = 0; i < spans.length; i++) { var span = spans[i]; if (!(span.to != null && lineNo == from.line && from.ch >= span.to || span.from == null && lineNo != from.line || span.from != null && lineNo == to.line && span.from >= to.ch) && (!filter || filter(span.marker))) { found.push(span.marker.parent || span.marker); } } } ++lineNo; }); return found }, getAllMarks: function() { var markers = []; this.iter(function (line) { var sps = line.markedSpans; if (sps) { for (var i = 0; i < sps.length; ++i) { if (sps[i].from != null) { markers.push(sps[i].marker); } } } }); return markers }, posFromIndex: function(off) { var ch, lineNo = this.first, sepSize = this.lineSeparator().length; this.iter(function (line) { var sz = line.text.length + sepSize; if (sz > off) { ch = off; return true } off -= sz; ++lineNo; }); return clipPos(this, Pos(lineNo, ch)) }, indexFromPos: function (coords) { coords = clipPos(this, coords); var index = coords.ch; if (coords.line < this.first || coords.ch < 0) { return 0 } var sepSize = this.lineSeparator().length; this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value index += line.text.length + sepSize; }); return index }, copy: function(copyHistory) { var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first, this.lineSep, this.direction); doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; doc.sel = this.sel; doc.extend = false; if (copyHistory) { doc.history.undoDepth = this.history.undoDepth; doc.setHistory(this.getHistory()); } return doc }, linkedDoc: function(options) { if (!options) { options = {}; } var from = this.first, to = this.first + this.size; if (options.from != null && options.from > from) { from = options.from; } if (options.to != null && options.to < to) { to = options.to; } var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction); if (options.sharedHist) { copy.history = this.history ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; copySharedMarkers(copy, findSharedMarkers(this)); return copy }, unlinkDoc: function(other) { if (other instanceof CodeMirror) { other = other.doc; } if (this.linked) { for (var i = 0; i < this.linked.length; ++i) { var link = this.linked[i]; if (link.doc != other) { continue } this.linked.splice(i, 1); other.unlinkDoc(this); detachSharedMarkers(findSharedMarkers(this)); break } } // If the histories were shared, split them again if (other.history == this.history) { var splitIds = [other.id]; linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true); other.history = new History(null); other.history.done = copyHistoryArray(this.history.done, splitIds); other.history.undone = copyHistoryArray(this.history.undone, splitIds); } }, iterLinkedDocs: function(f) {linkedDocs(this, f);}, getMode: function() {return this.mode}, getEditor: function() {return this.cm}, splitLines: function(str) { if (this.lineSep) { return str.split(this.lineSep) } return splitLinesAuto(str) }, lineSeparator: function() { return this.lineSep || "\n" }, setDirection: docMethodOp(function (dir) { if (dir != "rtl") { dir = "ltr"; } if (dir == this.direction) { return } this.direction = dir; this.iter(function (line) { return line.order = null; }); if (this.cm) { directionChanged(this.cm); } }) }); // Public alias. Doc.prototype.eachLine = Doc.prototype.iter; // Kludge to work around strange IE behavior where it'll sometimes // re-fire a series of drag-related events right after the drop (#1551) var lastDrop = 0; function onDrop(e) { var cm = this; clearDragCursor(cm); if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return } e_preventDefault(e); if (ie) { lastDrop = +new Date; } var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; if (!pos || cm.isReadOnly()) { return } // Might be a file drop, in which case we simply extract the text // and insert it. if (files && files.length && window.FileReader && window.File) { var n = files.length, text = Array(n), read = 0; var markAsReadAndPasteIfAllFilesAreRead = function () { if (++read == n) { operation(cm, function () { pos = clipPos(cm.doc, pos); var change = {from: pos, to: pos, text: cm.doc.splitLines( text.filter(function (t) { return t != null; }).join(cm.doc.lineSeparator())), origin: "paste"}; makeChange(cm.doc, change); setSelectionReplaceHistory(cm.doc, simpleSelection(clipPos(cm.doc, pos), clipPos(cm.doc, changeEnd(change)))); })(); } }; var readTextFromFile = function (file, i) { if (cm.options.allowDropFileTypes && indexOf(cm.options.allowDropFileTypes, file.type) == -1) { markAsReadAndPasteIfAllFilesAreRead(); return } var reader = new FileReader; reader.onerror = function () { return markAsReadAndPasteIfAllFilesAreRead(); }; reader.onload = function () { var content = reader.result; if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { markAsReadAndPasteIfAllFilesAreRead(); return } text[i] = content; markAsReadAndPasteIfAllFilesAreRead(); }; reader.readAsText(file); }; for (var i = 0; i < files.length; i++) { readTextFromFile(files[i], i); } } else { // Normal drop // Don't do a replace if the drop happened inside of the selected text. if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { cm.state.draggingText(e); // Ensure the editor is re-focused setTimeout(function () { return cm.display.input.focus(); }, 20); return } try { var text$1 = e.dataTransfer.getData("Text"); if (text$1) { var selected; if (cm.state.draggingText && !cm.state.draggingText.copy) { selected = cm.listSelections(); } setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1) { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag"); } } cm.replaceSelection(text$1, "around", "paste"); cm.display.input.focus(); } } catch(e$1){} } } function onDragStart(cm, e) { if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return } if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return } e.dataTransfer.setData("Text", cm.getSelection()); e.dataTransfer.effectAllowed = "copyMove"; // Use dummy image instead of default browsers image. // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. if (e.dataTransfer.setDragImage && !safari) { var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; if (presto) { img.width = img.height = 1; cm.display.wrapper.appendChild(img); // Force a relayout, or Opera won't use our image for some obscure reason img._top = img.offsetTop; } e.dataTransfer.setDragImage(img, 0, 0); if (presto) { img.parentNode.removeChild(img); } } } function onDragOver(cm, e) { var pos = posFromMouse(cm, e); if (!pos) { return } var frag = document.createDocumentFragment(); drawSelectionCursor(cm, pos, frag); if (!cm.display.dragCursor) { cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors"); cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv); } removeChildrenAndAdd(cm.display.dragCursor, frag); } function clearDragCursor(cm) { if (cm.display.dragCursor) { cm.display.lineSpace.removeChild(cm.display.dragCursor); cm.display.dragCursor = null; } } // These must be handled carefully, because naively registering a // handler for each editor will cause the editors to never be // garbage collected. function forEachCodeMirror(f) { if (!document.getElementsByClassName) { return } var byClass = document.getElementsByClassName("CodeMirror"), editors = []; for (var i = 0; i < byClass.length; i++) { var cm = byClass[i].CodeMirror; if (cm) { editors.push(cm); } } if (editors.length) { editors[0].operation(function () { for (var i = 0; i < editors.length; i++) { f(editors[i]); } }); } } var globalsRegistered = false; function ensureGlobalHandlers() { if (globalsRegistered) { return } registerGlobalHandlers(); globalsRegistered = true; } function registerGlobalHandlers() { // When the window resizes, we need to refresh active editors. var resizeTimer; on(window, "resize", function () { if (resizeTimer == null) { resizeTimer = setTimeout(function () { resizeTimer = null; forEachCodeMirror(onResize); }, 100); } }); // When the window loses focus, we want to show the editor as blurred on(window, "blur", function () { return forEachCodeMirror(onBlur); }); } // Called when the window resizes function onResize(cm) { var d = cm.display; // Might be a text scaling operation, clear size caches. d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; d.scrollbarsClipped = false; cm.setSize(); } var keyNames = { 3: "Pause", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock", 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'", 224: "Mod", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" }; // Number keys for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i); } // Alphabetic keys for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1); } // Function keys for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2; } var keyMap = {}; keyMap.basic = { "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto", "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", "Esc": "singleSelection" }; // Note that the save and find-related commands aren't defined by // default. User code or addons can define them. Unknown commands // are simply ignored. keyMap.pcDefault = { "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", "fallthrough": "basic" }; // Very basic readline/emacs-style bindings, which are standard on Mac. keyMap.emacsy = { "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars", "Ctrl-O": "openLine" }; keyMap.macDefault = { "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", "fallthrough": ["basic", "emacsy"] }; keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; // KEYMAP DISPATCH function normalizeKeyName(name) { var parts = name.split(/-(?!$)/); name = parts[parts.length - 1]; var alt, ctrl, shift, cmd; for (var i = 0; i < parts.length - 1; i++) { var mod = parts[i]; if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; } else if (/^a(lt)?$/i.test(mod)) { alt = true; } else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; } else if (/^s(hift)?$/i.test(mod)) { shift = true; } else { throw new Error("Unrecognized modifier name: " + mod) } } if (alt) { name = "Alt-" + name; } if (ctrl) { name = "Ctrl-" + name; } if (cmd) { name = "Cmd-" + name; } if (shift) { name = "Shift-" + name; } return name } // This is a kludge to keep keymaps mostly working as raw objects // (backwards compatibility) while at the same time support features // like normalization and multi-stroke key bindings. It compiles a // new normalized keymap, and then updates the old object to reflect // this. function normalizeKeyMap(keymap) { var copy = {}; for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) { var value = keymap[keyname]; if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue } if (value == "...") { delete keymap[keyname]; continue } var keys = map(keyname.split(" "), normalizeKeyName); for (var i = 0; i < keys.length; i++) { var val = (void 0), name = (void 0); if (i == keys.length - 1) { name = keys.join(" "); val = value; } else { name = keys.slice(0, i + 1).join(" "); val = "..."; } var prev = copy[name]; if (!prev) { copy[name] = val; } else if (prev != val) { throw new Error("Inconsistent bindings for " + name) } } delete keymap[keyname]; } } for (var prop in copy) { keymap[prop] = copy[prop]; } return keymap } function lookupKey(key, map, handle, context) { map = getKeyMap(map); var found = map.call ? map.call(key, context) : map[key]; if (found === false) { return "nothing" } if (found === "...") { return "multi" } if (found != null && handle(found)) { return "handled" } if (map.fallthrough) { if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") { return lookupKey(key, map.fallthrough, handle, context) } for (var i = 0; i < map.fallthrough.length; i++) { var result = lookupKey(key, map.fallthrough[i], handle, context); if (result) { return result } } } } // Modifier key presses don't count as 'real' key presses for the // purpose of keymap fallthrough. function isModifierKey(value) { var name = typeof value == "string" ? value : keyNames[value.keyCode]; return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod" } function addModifierNames(name, event, noShift) { var base = name; if (event.altKey && base != "Alt") { name = "Alt-" + name; } if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name; } if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Mod") { name = "Cmd-" + name; } if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name; } return name } // Look up the name of a key as indicated by an event object. function keyName(event, noShift) { if (presto && event.keyCode == 34 && event["char"]) { return false } var name = keyNames[event.keyCode]; if (name == null || event.altGraphKey) { return false } // Ctrl-ScrollLock has keyCode 3, same as Ctrl-Pause, // so we'll use event.code when available (Chrome 48+, FF 38+, Safari 10.1+) if (event.keyCode == 3 && event.code) { name = event.code; } return addModifierNames(name, event, noShift) } function getKeyMap(val) { return typeof val == "string" ? keyMap[val] : val } // Helper for deleting text near the selection(s), used to implement // backspace, delete, and similar functionality. function deleteNearSelection(cm, compute) { var ranges = cm.doc.sel.ranges, kill = []; // Build up a set of ranges to kill first, merging overlapping // ranges. for (var i = 0; i < ranges.length; i++) { var toKill = compute(ranges[i]); while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { var replaced = kill.pop(); if (cmp(replaced.from, toKill.from) < 0) { toKill.from = replaced.from; break } } kill.push(toKill); } // Next, remove those actual ranges. runInOp(cm, function () { for (var i = kill.length - 1; i >= 0; i--) { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); } ensureCursorVisible(cm); }); } function moveCharLogically(line, ch, dir) { var target = skipExtendingChars(line.text, ch + dir, dir); return target < 0 || target > line.text.length ? null : target } function moveLogically(line, start, dir) { var ch = moveCharLogically(line, start.ch, dir); return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before") } function endOfLine(visually, cm, lineObj, lineNo, dir) { if (visually) { if (cm.doc.direction == "rtl") { dir = -dir; } var order = getOrder(lineObj, cm.doc.direction); if (order) { var part = dir < 0 ? lst(order) : order[0]; var moveInStorageOrder = (dir < 0) == (part.level == 1); var sticky = moveInStorageOrder ? "after" : "before"; var ch; // With a wrapped rtl chunk (possibly spanning multiple bidi parts), // it could be that the last bidi part is not on the last visual line, // since visual lines contain content order-consecutive chunks. // Thus, in rtl, we are looking for the first (content-order) character // in the rtl chunk that is on the last line (that is, the same line // as the last (content-order) character). if (part.level > 0 || cm.doc.direction == "rtl") { var prep = prepareMeasureForLine(cm, lineObj); ch = dir < 0 ? lineObj.text.length - 1 : 0; var targetTop = measureCharPrepared(cm, prep, ch).top; ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch); if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); } } else { ch = dir < 0 ? part.to : part.from; } return new Pos(lineNo, ch, sticky) } } return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") } function moveVisually(cm, line, start, dir) { var bidi = getOrder(line, cm.doc.direction); if (!bidi) { return moveLogically(line, start, dir) } if (start.ch >= line.text.length) { start.ch = line.text.length; start.sticky = "before"; } else if (start.ch <= 0) { start.ch = 0; start.sticky = "after"; } var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos]; if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, // nothing interesting happens. return moveLogically(line, start, dir) } var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); }; var prep; var getWrappedLineExtent = function (ch) { if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} } prep = prep || prepareMeasureForLine(cm, line); return wrappedLineExtentChar(cm, line, prep, ch) }; var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch); if (cm.doc.direction == "rtl" || part.level == 1) { var moveInStorageOrder = (part.level == 1) == (dir < 0); var ch = mv(start, moveInStorageOrder ? 1 : -1); if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { // Case 2: We move within an rtl part or in an rtl editor on the same visual line var sticky = moveInStorageOrder ? "before" : "after"; return new Pos(start.line, ch, sticky) } } // Case 3: Could not move within this bidi part in this visual line, so leave // the current bidi part var searchInVisualLine = function (partPos, dir, wrappedLineExtent) { var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder ? new Pos(start.line, mv(ch, 1), "before") : new Pos(start.line, ch, "after"); }; for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { var part = bidi[partPos]; var moveInStorageOrder = (dir > 0) == (part.level != 1); var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1); if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) } ch = moveInStorageOrder ? part.from : mv(part.to, -1); if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) } } }; // Case 3a: Look for other bidi parts on the same visual line var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent); if (res) { return res } // Case 3b: Look for other bidi parts on the next visual line var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1); if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)); if (res) { return res } } // Case 4: Nowhere to move return null } // Commands are parameter-less actions that can be performed on an // editor, mostly used for keybindings. var commands = { selectAll: selectAll, singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); }, killLine: function (cm) { return deleteNearSelection(cm, function (range) { if (range.empty()) { var len = getLine(cm.doc, range.head.line).text.length; if (range.head.ch == len && range.head.line < cm.lastLine()) { return {from: range.head, to: Pos(range.head.line + 1, 0)} } else { return {from: range.head, to: Pos(range.head.line, len)} } } else { return {from: range.from(), to: range.to()} } }); }, deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({ from: Pos(range.from().line, 0), to: clipPos(cm.doc, Pos(range.to().line + 1, 0)) }); }); }, delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({ from: Pos(range.from().line, 0), to: range.from() }); }); }, delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { var top = cm.charCoords(range.head, "div").top + 5; var leftPos = cm.coordsChar({left: 0, top: top}, "div"); return {from: leftPos, to: range.from()} }); }, delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) { var top = cm.charCoords(range.head, "div").top + 5; var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); return {from: range.from(), to: rightPos } }); }, undo: function (cm) { return cm.undo(); }, redo: function (cm) { return cm.redo(); }, undoSelection: function (cm) { return cm.undoSelection(); }, redoSelection: function (cm) { return cm.redoSelection(); }, goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); }, goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); }, goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); }, {origin: "+move", bias: 1} ); }, goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); }, {origin: "+move", bias: 1} ); }, goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); }, {origin: "+move", bias: -1} ); }, goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) { var top = cm.cursorCoords(range.head, "div").top + 5; return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") }, sel_move); }, goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) { var top = cm.cursorCoords(range.head, "div").top + 5; return cm.coordsChar({left: 0, top: top}, "div") }, sel_move); }, goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) { var top = cm.cursorCoords(range.head, "div").top + 5; var pos = cm.coordsChar({left: 0, top: top}, "div"); if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) } return pos }, sel_move); }, goLineUp: function (cm) { return cm.moveV(-1, "line"); }, goLineDown: function (cm) { return cm.moveV(1, "line"); }, goPageUp: function (cm) { return cm.moveV(-1, "page"); }, goPageDown: function (cm) { return cm.moveV(1, "page"); }, goCharLeft: function (cm) { return cm.moveH(-1, "char"); }, goCharRight: function (cm) { return cm.moveH(1, "char"); }, goColumnLeft: function (cm) { return cm.moveH(-1, "column"); }, goColumnRight: function (cm) { return cm.moveH(1, "column"); }, goWordLeft: function (cm) { return cm.moveH(-1, "word"); }, goGroupRight: function (cm) { return cm.moveH(1, "group"); }, goGroupLeft: function (cm) { return cm.moveH(-1, "group"); }, goWordRight: function (cm) { return cm.moveH(1, "word"); }, delCharBefore: function (cm) { return cm.deleteH(-1, "codepoint"); }, delCharAfter: function (cm) { return cm.deleteH(1, "char"); }, delWordBefore: function (cm) { return cm.deleteH(-1, "word"); }, delWordAfter: function (cm) { return cm.deleteH(1, "word"); }, delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); }, delGroupAfter: function (cm) { return cm.deleteH(1, "group"); }, indentAuto: function (cm) { return cm.indentSelection("smart"); }, indentMore: function (cm) { return cm.indentSelection("add"); }, indentLess: function (cm) { return cm.indentSelection("subtract"); }, insertTab: function (cm) { return cm.replaceSelection("\t"); }, insertSoftTab: function (cm) { var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize; for (var i = 0; i < ranges.length; i++) { var pos = ranges[i].from(); var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize); spaces.push(spaceStr(tabSize - col % tabSize)); } cm.replaceSelections(spaces); }, defaultTab: function (cm) { if (cm.somethingSelected()) { cm.indentSelection("add"); } else { cm.execCommand("insertTab"); } }, // Swap the two chars left and right of each selection's head. // Move cursor behind the two swapped characters afterwards. // // Doesn't consider line feeds a character. // Doesn't scan more than one line above to find a character. // Doesn't do anything on an empty line. // Doesn't do anything with non-empty selections. transposeChars: function (cm) { return runInOp(cm, function () { var ranges = cm.listSelections(), newSel = []; for (var i = 0; i < ranges.length; i++) { if (!ranges[i].empty()) { continue } var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text; if (line) { if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1); } if (cur.ch > 0) { cur = new Pos(cur.line, cur.ch + 1); cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), Pos(cur.line, cur.ch - 2), cur, "+transpose"); } else if (cur.line > cm.doc.first) { var prev = getLine(cm.doc, cur.line - 1).text; if (prev) { cur = new Pos(cur.line, 1); cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + prev.charAt(prev.length - 1), Pos(cur.line - 1, prev.length - 1), cur, "+transpose"); } } } newSel.push(new Range(cur, cur)); } cm.setSelections(newSel); }); }, newlineAndIndent: function (cm) { return runInOp(cm, function () { var sels = cm.listSelections(); for (var i = sels.length - 1; i >= 0; i--) { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input"); } sels = cm.listSelections(); for (var i$1 = 0; i$1 < sels.length; i$1++) { cm.indentLine(sels[i$1].from().line, null, true); } ensureCursorVisible(cm); }); }, openLine: function (cm) { return cm.replaceSelection("\n", "start"); }, toggleOverwrite: function (cm) { return cm.toggleOverwrite(); } }; function lineStart(cm, lineN) { var line = getLine(cm.doc, lineN); var visual = visualLine(line); if (visual != line) { lineN = lineNo(visual); } return endOfLine(true, cm, visual, lineN, 1) } function lineEnd(cm, lineN) { var line = getLine(cm.doc, lineN); var visual = visualLineEnd(line); if (visual != line) { lineN = lineNo(visual); } return endOfLine(true, cm, line, lineN, -1) } function lineStartSmart(cm, pos) { var start = lineStart(cm, pos.line); var line = getLine(cm.doc, start.line); var order = getOrder(line, cm.doc.direction); if (!order || order[0].level == 0) { var firstNonWS = Math.max(start.ch, line.text.search(/\S/)); var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky) } return start } // Run a handler that was bound to a key. function doHandleBinding(cm, bound, dropShift) { if (typeof bound == "string") { bound = commands[bound]; if (!bound) { return false } } // Ensure previous input has been read, so that the handler sees a // consistent view of the document cm.display.input.ensurePolled(); var prevShift = cm.display.shift, done = false; try { if (cm.isReadOnly()) { cm.state.suppressEdits = true; } if (dropShift) { cm.display.shift = false; } done = bound(cm) != Pass; } finally { cm.display.shift = prevShift; cm.state.suppressEdits = false; } return done } function lookupKeyForEditor(cm, name, handle) { for (var i = 0; i < cm.state.keyMaps.length; i++) { var result = lookupKey(name, cm.state.keyMaps[i], handle, cm); if (result) { return result } } return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) || lookupKey(name, cm.options.keyMap, handle, cm) } // Note that, despite the name, this function is also used to check // for bound mouse clicks. var stopSeq = new Delayed; function dispatchKey(cm, name, e, handle) { var seq = cm.state.keySeq; if (seq) { if (isModifierKey(name)) { return "handled" } if (/\'$/.test(name)) { cm.state.keySeq = null; } else { stopSeq.set(50, function () { if (cm.state.keySeq == seq) { cm.state.keySeq = null; cm.display.input.reset(); } }); } if (dispatchKeyInner(cm, seq + " " + name, e, handle)) { return true } } return dispatchKeyInner(cm, name, e, handle) } function dispatchKeyInner(cm, name, e, handle) { var result = lookupKeyForEditor(cm, name, handle); if (result == "multi") { cm.state.keySeq = name; } if (result == "handled") { signalLater(cm, "keyHandled", cm, name, e); } if (result == "handled" || result == "multi") { e_preventDefault(e); restartBlink(cm); } return !!result } // Handle a key from the keydown event. function handleKeyBinding(cm, e) { var name = keyName(e, true); if (!name) { return false } if (e.shiftKey && !cm.state.keySeq) { // First try to resolve full name (including 'Shift-'). Failing // that, see if there is a cursor-motion command (starting with // 'go') bound to the keyname without 'Shift-'. return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); }) || dispatchKey(cm, name, e, function (b) { if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) { return doHandleBinding(cm, b) } }) } else { return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); }) } } // Handle a key from the keypress event function handleCharBinding(cm, e, ch) { return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); }) } var lastStoppedKey = null; function onKeyDown(e) { var cm = this; if (e.target && e.target != cm.display.input.getField()) { return } cm.curOp.focus = activeElt(root(cm)); if (signalDOMEvent(cm, e)) { return } // IE does strange things with escape. if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false; } var code = e.keyCode; cm.display.shift = code == 16 || e.shiftKey; var handled = handleKeyBinding(cm, e); if (presto) { lastStoppedKey = handled ? code : null; // Opera has no cut event... we try to at least catch the key combo if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) { cm.replaceSelection("", null, "cut"); } } if (gecko && !mac && !handled && code == 46 && e.shiftKey && !e.ctrlKey && document.execCommand) { document.execCommand("cut"); } // Turn mouse into crosshair when Alt is held on Mac. if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) { showCrossHair(cm); } } function showCrossHair(cm) { var lineDiv = cm.display.lineDiv; addClass(lineDiv, "CodeMirror-crosshair"); function up(e) { if (e.keyCode == 18 || !e.altKey) { rmClass(lineDiv, "CodeMirror-crosshair"); off(document, "keyup", up); off(document, "mouseover", up); } } on(document, "keyup", up); on(document, "mouseover", up); } function onKeyUp(e) { if (e.keyCode == 16) { this.doc.sel.shift = false; } signalDOMEvent(this, e); } function onKeyPress(e) { var cm = this; if (e.target && e.target != cm.display.input.getField()) { return } if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return } var keyCode = e.keyCode, charCode = e.charCode; if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return} if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return } var ch = String.fromCharCode(charCode == null ? keyCode : charCode); // Some browsers fire keypress events for backspace if (ch == "\x08") { return } if (handleCharBinding(cm, e, ch)) { return } cm.display.input.onKeyPress(e); } var DOUBLECLICK_DELAY = 400; var PastClick = function(time, pos, button) { this.time = time; this.pos = pos; this.button = button; }; PastClick.prototype.compare = function (time, pos, button) { return this.time + DOUBLECLICK_DELAY > time && cmp(pos, this.pos) == 0 && button == this.button }; var lastClick, lastDoubleClick; function clickRepeat(pos, button) { var now = +new Date; if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) { lastClick = lastDoubleClick = null; return "triple" } else if (lastClick && lastClick.compare(now, pos, button)) { lastDoubleClick = new PastClick(now, pos, button); lastClick = null; return "double" } else { lastClick = new PastClick(now, pos, button); lastDoubleClick = null; return "single" } } // A mouse down can be a single click, double click, triple click, // start of selection drag, start of text drag, new cursor // (ctrl-click), rectangle drag (alt-drag), or xwin // middle-click-paste. Or it might be a click on something we should // not interfere with, such as a scrollbar or widget. function onMouseDown(e) { var cm = this, display = cm.display; if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return } display.input.ensurePolled(); display.shift = e.shiftKey; if (eventInWidget(display, e)) { if (!webkit) { // Briefly turn off draggability, to allow widgets to do // normal dragging things. display.scroller.draggable = false; setTimeout(function () { return display.scroller.draggable = true; }, 100); } return } if (clickInGutter(cm, e)) { return } var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single"; win(cm).focus(); // #3261: make sure, that we're not starting a second selection if (button == 1 && cm.state.selectingText) { cm.state.selectingText(e); } if (pos && handleMappedButton(cm, button, pos, repeat, e)) { return } if (button == 1) { if (pos) { leftButtonDown(cm, pos, repeat, e); } else if (e_target(e) == display.scroller) { e_preventDefault(e); } } else if (button == 2) { if (pos) { extendSelection(cm.doc, pos); } setTimeout(function () { return display.input.focus(); }, 20); } else if (button == 3) { if (captureRightClick) { cm.display.input.onContextMenu(e); } else { delayBlurEvent(cm); } } } function handleMappedButton(cm, button, pos, repeat, event) { var name = "Click"; if (repeat == "double") { name = "Double" + name; } else if (repeat == "triple") { name = "Triple" + name; } name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name; return dispatchKey(cm, addModifierNames(name, event), event, function (bound) { if (typeof bound == "string") { bound = commands[bound]; } if (!bound) { return false } var done = false; try { if (cm.isReadOnly()) { cm.state.suppressEdits = true; } done = bound(cm, pos) != Pass; } finally { cm.state.suppressEdits = false; } return done }) } function configureMouse(cm, repeat, event) { var option = cm.getOption("configureMouse"); var value = option ? option(cm, repeat, event) : {}; if (value.unit == null) { var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey; value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line"; } if (value.extend == null || cm.doc.extend) { value.extend = cm.doc.extend || event.shiftKey; } if (value.addNew == null) { value.addNew = mac ? event.metaKey : event.ctrlKey; } if (value.moveOnDrag == null) { value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey); } return value } function leftButtonDown(cm, pos, repeat, event) { if (ie) { setTimeout(bind(ensureFocus, cm), 0); } else { cm.curOp.focus = activeElt(root(cm)); } var behavior = configureMouse(cm, repeat, event); var sel = cm.doc.sel, contained; if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && repeat == "single" && (contained = sel.contains(pos)) > -1 && (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) && (cmp(contained.to(), pos) > 0 || pos.xRel < 0)) { leftButtonStartDrag(cm, event, pos, behavior); } else { leftButtonSelect(cm, event, pos, behavior); } } // Start a text drag. When it ends, see if any dragging actually // happen, and treat as a click if it didn't. function leftButtonStartDrag(cm, event, pos, behavior) { var display = cm.display, moved = false; var dragEnd = operation(cm, function (e) { if (webkit) { display.scroller.draggable = false; } cm.state.draggingText = false; if (cm.state.delayingBlurEvent) { if (cm.hasFocus()) { cm.state.delayingBlurEvent = false; } else { delayBlurEvent(cm); } } off(display.wrapper.ownerDocument, "mouseup", dragEnd); off(display.wrapper.ownerDocument, "mousemove", mouseMove); off(display.scroller, "dragstart", dragStart); off(display.scroller, "drop", dragEnd); if (!moved) { e_preventDefault(e); if (!behavior.addNew) { extendSelection(cm.doc, pos, null, null, behavior.extend); } // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) if ((webkit && !safari) || ie && ie_version == 9) { setTimeout(function () {display.wrapper.ownerDocument.body.focus({preventScroll: true}); display.input.focus();}, 20); } else { display.input.focus(); } } }); var mouseMove = function(e2) { moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10; }; var dragStart = function () { return moved = true; }; // Let the drag handler handle this. if (webkit) { display.scroller.draggable = true; } cm.state.draggingText = dragEnd; dragEnd.copy = !behavior.moveOnDrag; on(display.wrapper.ownerDocument, "mouseup", dragEnd); on(display.wrapper.ownerDocument, "mousemove", mouseMove); on(display.scroller, "dragstart", dragStart); on(display.scroller, "drop", dragEnd); cm.state.delayingBlurEvent = true; setTimeout(function () { return display.input.focus(); }, 20); // IE's approach to draggable if (display.scroller.dragDrop) { display.scroller.dragDrop(); } } function rangeForUnit(cm, pos, unit) { if (unit == "char") { return new Range(pos, pos) } if (unit == "word") { return cm.findWordAt(pos) } if (unit == "line") { return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) } var result = unit(cm, pos); return new Range(result.from, result.to) } // Normal selection, as opposed to text dragging. function leftButtonSelect(cm, event, start, behavior) { if (ie) { delayBlurEvent(cm); } var display = cm.display, doc = cm.doc; e_preventDefault(event); var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges; if (behavior.addNew && !behavior.extend) { ourIndex = doc.sel.contains(start); if (ourIndex > -1) { ourRange = ranges[ourIndex]; } else { ourRange = new Range(start, start); } } else { ourRange = doc.sel.primary(); ourIndex = doc.sel.primIndex; } if (behavior.unit == "rectangle") { if (!behavior.addNew) { ourRange = new Range(start, start); } start = posFromMouse(cm, event, true, true); ourIndex = -1; } else { var range = rangeForUnit(cm, start, behavior.unit); if (behavior.extend) { ourRange = extendRange(ourRange, range.anchor, range.head, behavior.extend); } else { ourRange = range; } } if (!behavior.addNew) { ourIndex = 0; setSelection(doc, new Selection([ourRange], 0), sel_mouse); startSel = doc.sel; } else if (ourIndex == -1) { ourIndex = ranges.length; setSelection(doc, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex), {scroll: false, origin: "*mouse"}); } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) { setSelection(doc, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), {scroll: false, origin: "*mouse"}); startSel = doc.sel; } else { replaceOneSelection(doc, ourIndex, ourRange, sel_mouse); } var lastPos = start; function extendTo(pos) { if (cmp(lastPos, pos) == 0) { return } lastPos = pos; if (behavior.unit == "rectangle") { var ranges = [], tabSize = cm.options.tabSize; var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize); var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize); var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol); for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); line <= end; line++) { var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize); if (left == right) { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); } else if (text.length > leftPos) { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); } } if (!ranges.length) { ranges.push(new Range(start, start)); } setSelection(doc, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), {origin: "*mouse", scroll: false}); cm.scrollIntoView(pos); } else { var oldRange = ourRange; var range = rangeForUnit(cm, pos, behavior.unit); var anchor = oldRange.anchor, head; if (cmp(range.anchor, anchor) > 0) { head = range.head; anchor = minPos(oldRange.from(), range.anchor); } else { head = range.anchor; anchor = maxPos(oldRange.to(), range.head); } var ranges$1 = startSel.ranges.slice(0); ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head)); setSelection(doc, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse); } } var editorSize = display.wrapper.getBoundingClientRect(); // Used to ensure timeout re-tries don't fire when another extend // happened in the meantime (clearTimeout isn't reliable -- at // least on Chrome, the timeouts still happen even when cleared, // if the clear happens after their scheduled firing time). var counter = 0; function extend(e) { var curCount = ++counter; var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle"); if (!cur) { return } if (cmp(cur, lastPos) != 0) { cm.curOp.focus = activeElt(root(cm)); extendTo(cur); var visible = visibleLines(display, doc); if (cur.line >= visible.to || cur.line < visible.from) { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e); }}), 150); } } else { var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; if (outside) { setTimeout(operation(cm, function () { if (counter != curCount) { return } display.scroller.scrollTop += outside; extend(e); }), 50); } } } function done(e) { cm.state.selectingText = false; counter = Infinity; // If e is null or undefined we interpret this as someone trying // to explicitly cancel the selection rather than the user // letting go of the mouse button. if (e) { e_preventDefault(e); display.input.focus(); } off(display.wrapper.ownerDocument, "mousemove", move); off(display.wrapper.ownerDocument, "mouseup", up); doc.history.lastSelOrigin = null; } var move = operation(cm, function (e) { if (e.buttons === 0 || !e_button(e)) { done(e); } else { extend(e); } }); var up = operation(cm, done); cm.state.selectingText = up; on(display.wrapper.ownerDocument, "mousemove", move); on(display.wrapper.ownerDocument, "mouseup", up); } // Used when mouse-selecting to adjust the anchor to the proper side // of a bidi jump depending on the visual position of the head. function bidiSimplify(cm, range) { var anchor = range.anchor; var head = range.head; var anchorLine = getLine(cm.doc, anchor.line); if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range } var order = getOrder(anchorLine); if (!order) { return range } var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index]; if (part.from != anchor.ch && part.to != anchor.ch) { return range } var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1); if (boundary == 0 || boundary == order.length) { return range } // Compute the relative visual position of the head compared to the // anchor (<0 is to the left, >0 to the right) var leftSide; if (head.line != anchor.line) { leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0; } else { var headIndex = getBidiPartAt(order, head.ch, head.sticky); var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1); if (headIndex == boundary - 1 || headIndex == boundary) { leftSide = dir < 0; } else { leftSide = dir > 0; } } var usePart = order[boundary + (leftSide ? -1 : 0)]; var from = leftSide == (usePart.level == 1); var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before"; return anchor.ch == ch && anchor.sticky == sticky ? range : new Range(new Pos(anchor.line, ch, sticky), head) } // Determines whether an event happened in the gutter, and fires the // handlers for the corresponding event. function gutterEvent(cm, e, type, prevent) { var mX, mY; if (e.touches) { mX = e.touches[0].clientX; mY = e.touches[0].clientY; } else { try { mX = e.clientX; mY = e.clientY; } catch(e$1) { return false } } if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false } if (prevent) { e_preventDefault(e); } var display = cm.display; var lineBox = display.lineDiv.getBoundingClientRect(); if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) } mY -= lineBox.top - display.viewOffset; for (var i = 0; i < cm.display.gutterSpecs.length; ++i) { var g = display.gutters.childNodes[i]; if (g && g.getBoundingClientRect().right >= mX) { var line = lineAtHeight(cm.doc, mY); var gutter = cm.display.gutterSpecs[i]; signal(cm, type, cm, line, gutter.className, e); return e_defaultPrevented(e) } } } function clickInGutter(cm, e) { return gutterEvent(cm, e, "gutterClick", true) } // CONTEXT MENU HANDLING // To make the context menu work, we need to briefly unhide the // textarea (making it as unobtrusive as possible) to let the // right-click take effect on it. function onContextMenu(cm, e) { if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return } if (signalDOMEvent(cm, e, "contextmenu")) { return } if (!captureRightClick) { cm.display.input.onContextMenu(e); } } function contextMenuInGutter(cm, e) { if (!hasHandler(cm, "gutterContextMenu")) { return false } return gutterEvent(cm, e, "gutterContextMenu", false) } function themeChanged(cm) { cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); clearCaches(cm); } var Init = {toString: function(){return "CodeMirror.Init"}}; var defaults = {}; var optionHandlers = {}; function defineOptions(CodeMirror) { var optionHandlers = CodeMirror.optionHandlers; function option(name, deflt, handle, notOnInit) { CodeMirror.defaults[name] = deflt; if (handle) { optionHandlers[name] = notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old); }} : handle; } } CodeMirror.defineOption = option; // Passed to option handlers when there is no old value. CodeMirror.Init = Init; // These two are, on init, called from the constructor because they // have to be initialized before the editor can start at all. option("value", "", function (cm, val) { return cm.setValue(val); }, true); option("mode", null, function (cm, val) { cm.doc.modeOption = val; loadMode(cm); }, true); option("indentUnit", 2, loadMode, true); option("indentWithTabs", false); option("smartIndent", true); option("tabSize", 4, function (cm) { resetModeState(cm); clearCaches(cm); regChange(cm); }, true); option("lineSeparator", null, function (cm, val) { cm.doc.lineSep = val; if (!val) { return } var newBreaks = [], lineNo = cm.doc.first; cm.doc.iter(function (line) { for (var pos = 0;;) { var found = line.text.indexOf(val, pos); if (found == -1) { break } pos = found + val.length; newBreaks.push(Pos(lineNo, found)); } lineNo++; }); for (var i = newBreaks.length - 1; i >= 0; i--) { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); } }); option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\u202d\u202e\u2066\u2067\u2069\ufeff\ufff9-\ufffc]/g, function (cm, val, old) { cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); if (old != Init) { cm.refresh(); } }); option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true); option("electricChars", true); option("inputStyle", mobile ? "contenteditable" : "textarea", function () { throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME }, true); option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true); option("autocorrect", false, function (cm, val) { return cm.getInputField().autocorrect = val; }, true); option("autocapitalize", false, function (cm, val) { return cm.getInputField().autocapitalize = val; }, true); option("rtlMoveVisually", !windows); option("wholeLineUpdateBefore", true); option("theme", "default", function (cm) { themeChanged(cm); updateGutters(cm); }, true); option("keyMap", "default", function (cm, val, old) { var next = getKeyMap(val); var prev = old != Init && getKeyMap(old); if (prev && prev.detach) { prev.detach(cm, next); } if (next.attach) { next.attach(cm, prev || null); } }); option("extraKeys", null); option("configureMouse", null); option("lineWrapping", false, wrappingChanged, true); option("gutters", [], function (cm, val) { cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers); updateGutters(cm); }, true); option("fixedGutter", true, function (cm, val) { cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; cm.refresh(); }, true); option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true); option("scrollbarStyle", "native", function (cm) { initScrollbars(cm); updateScrollbars(cm); cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); }, true); option("lineNumbers", false, function (cm, val) { cm.display.gutterSpecs = getGutters(cm.options.gutters, val); updateGutters(cm); }, true); option("firstLineNumber", 1, updateGutters, true); option("lineNumberFormatter", function (integer) { return integer; }, updateGutters, true); option("showCursorWhenSelecting", false, updateSelection, true); option("resetSelectionOnContextMenu", true); option("lineWiseCopyCut", true); option("pasteLinesPerSelection", true); option("selectionsMayTouch", false); option("readOnly", false, function (cm, val) { if (val == "nocursor") { onBlur(cm); cm.display.input.blur(); } cm.display.input.readOnlyChanged(val); }); option("screenReaderLabel", null, function (cm, val) { val = (val === '') ? null : val; cm.display.input.screenReaderLabelChanged(val); }); option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true); option("dragDrop", true, dragDropChanged); option("allowDropFileTypes", null); option("cursorBlinkRate", 530); option("cursorScrollMargin", 0); option("cursorHeight", 1, updateSelection, true); option("singleCursorHeightPerLine", true, updateSelection, true); option("workTime", 100); option("workDelay", 100); option("flattenSpans", true, resetModeState, true); option("addModeClass", false, resetModeState, true); option("pollInterval", 100); option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; }); option("historyEventDelay", 1250); option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true); option("maxHighlightLength", 10000, resetModeState, true); option("moveInputWithCursor", true, function (cm, val) { if (!val) { cm.display.input.resetPosition(); } }); option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; }); option("autofocus", null); option("direction", "ltr", function (cm, val) { return cm.doc.setDirection(val); }, true); option("phrases", null); } function dragDropChanged(cm, value, old) { var wasOn = old && old != Init; if (!value != !wasOn) { var funcs = cm.display.dragFunctions; var toggle = value ? on : off; toggle(cm.display.scroller, "dragstart", funcs.start); toggle(cm.display.scroller, "dragenter", funcs.enter); toggle(cm.display.scroller, "dragover", funcs.over); toggle(cm.display.scroller, "dragleave", funcs.leave); toggle(cm.display.scroller, "drop", funcs.drop); } } function wrappingChanged(cm) { if (cm.options.lineWrapping) { addClass(cm.display.wrapper, "CodeMirror-wrap"); cm.display.sizer.style.minWidth = ""; cm.display.sizerWidth = null; } else { rmClass(cm.display.wrapper, "CodeMirror-wrap"); findMaxLine(cm); } estimateLineHeights(cm); regChange(cm); clearCaches(cm); setTimeout(function () { return updateScrollbars(cm); }, 100); } // A CodeMirror instance represents an editor. This is the object // that user code is usually dealing with. function CodeMirror(place, options) { var this$1 = this; if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) } this.options = options = options ? copyObj(options) : {}; // Determine effective options based on given values and defaults. copyObj(defaults, options, false); var doc = options.value; if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); } else if (options.mode) { doc.modeOption = options.mode; } this.doc = doc; var input = new CodeMirror.inputStyles[options.inputStyle](this); var display = this.display = new Display(place, doc, input, options); display.wrapper.CodeMirror = this; themeChanged(this); if (options.lineWrapping) { this.display.wrapper.className += " CodeMirror-wrap"; } initScrollbars(this); this.state = { keyMaps: [], // stores maps added by addKeyMap overlays: [], // highlighting overlays, as added by addOverlay modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info overwrite: false, delayingBlurEvent: false, focused: false, suppressEdits: false, // used to disable editing during key handlers when in readOnly mode pasteIncoming: -1, cutIncoming: -1, // help recognize paste/cut edits in input.poll selectingText: false, draggingText: false, highlight: new Delayed(), // stores highlight worker timeout keySeq: null, // Unfinished key sequence specialChars: null }; if (options.autofocus && !mobile) { display.input.focus(); } // Override magic textarea content restore that IE sometimes does // on our hidden textarea on reload if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20); } registerEventHandlers(this); ensureGlobalHandlers(); startOperation(this); this.curOp.forceUpdate = true; attachDoc(this, doc); if ((options.autofocus && !mobile) || this.hasFocus()) { setTimeout(function () { if (this$1.hasFocus() && !this$1.state.focused) { onFocus(this$1); } }, 20); } else { onBlur(this); } for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt)) { optionHandlers[opt](this, options[opt], Init); } } maybeUpdateLineNumberWidth(this); if (options.finishInit) { options.finishInit(this); } for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this); } endOperation(this); // Suppress optimizelegibility in Webkit, since it breaks text // measuring on line wrapping boundaries. if (webkit && options.lineWrapping && getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") { display.lineDiv.style.textRendering = "auto"; } } // The default configuration options. CodeMirror.defaults = defaults; // Functions to run when options are changed. CodeMirror.optionHandlers = optionHandlers; // Attach the necessary event handlers when initializing the editor function registerEventHandlers(cm) { var d = cm.display; on(d.scroller, "mousedown", operation(cm, onMouseDown)); // Older IE's will not fire a second mousedown for a double click if (ie && ie_version < 11) { on(d.scroller, "dblclick", operation(cm, function (e) { if (signalDOMEvent(cm, e)) { return } var pos = posFromMouse(cm, e); if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return } e_preventDefault(e); var word = cm.findWordAt(pos); extendSelection(cm.doc, word.anchor, word.head); })); } else { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }); } // Some browsers fire contextmenu *after* opening the menu, at // which point we can't mess with it anymore. Context menu is // handled in onMouseDown for these browsers. on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }); on(d.input.getField(), "contextmenu", function (e) { if (!d.scroller.contains(e.target)) { onContextMenu(cm, e); } }); // Used to suppress mouse event handling when a touch happens var touchFinished, prevTouch = {end: 0}; function finishTouch() { if (d.activeTouch) { touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000); prevTouch = d.activeTouch; prevTouch.end = +new Date; } } function isMouseLikeTouchEvent(e) { if (e.touches.length != 1) { return false } var touch = e.touches[0]; return touch.radiusX <= 1 && touch.radiusY <= 1 } function farAway(touch, other) { if (other.left == null) { return true } var dx = other.left - touch.left, dy = other.top - touch.top; return dx * dx + dy * dy > 20 * 20 } on(d.scroller, "touchstart", function (e) { if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) { d.input.ensurePolled(); clearTimeout(touchFinished); var now = +new Date; d.activeTouch = {start: now, moved: false, prev: now - prevTouch.end <= 300 ? prevTouch : null}; if (e.touches.length == 1) { d.activeTouch.left = e.touches[0].pageX; d.activeTouch.top = e.touches[0].pageY; } } }); on(d.scroller, "touchmove", function () { if (d.activeTouch) { d.activeTouch.moved = true; } }); on(d.scroller, "touchend", function (e) { var touch = d.activeTouch; if (touch && !eventInWidget(d, e) && touch.left != null && !touch.moved && new Date - touch.start < 300) { var pos = cm.coordsChar(d.activeTouch, "page"), range; if (!touch.prev || farAway(touch, touch.prev)) // Single tap { range = new Range(pos, pos); } else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap { range = cm.findWordAt(pos); } else // Triple tap { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); } cm.setSelection(range.anchor, range.head); cm.focus(); e_preventDefault(e); } finishTouch(); }); on(d.scroller, "touchcancel", finishTouch); // Sync scrolling between fake scrollbars and real scrollable // area, ensure viewport is updated when scrolling. on(d.scroller, "scroll", function () { if (d.scroller.clientHeight) { updateScrollTop(cm, d.scroller.scrollTop); setScrollLeft(cm, d.scroller.scrollLeft, true); signal(cm, "scroll", cm); } }); // Listen to wheel events in order to try and update the viewport on time. on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); }); on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); }); // Prevent wrapper from ever scrolling on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); d.dragFunctions = { enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e); }}, over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }}, start: function (e) { return onDragStart(cm, e); }, drop: operation(cm, onDrop), leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }} }; var inp = d.input.getField(); on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); }); on(inp, "keydown", operation(cm, onKeyDown)); on(inp, "keypress", operation(cm, onKeyPress)); on(inp, "focus", function (e) { return onFocus(cm, e); }); on(inp, "blur", function (e) { return onBlur(cm, e); }); } var initHooks = []; CodeMirror.defineInitHook = function (f) { return initHooks.push(f); }; // Indent the given line. The how parameter can be "smart", // "add"/null, "subtract", or "prev". When aggressive is false // (typically set to true for forced single-line indents), empty // lines are not indented, and places where the mode returns Pass // are left alone. function indentLine(cm, n, how, aggressive) { var doc = cm.doc, state; if (how == null) { how = "add"; } if (how == "smart") { // Fall back to "prev" when the mode doesn't have an indentation // method. if (!doc.mode.indent) { how = "prev"; } else { state = getContextBefore(cm, n).state; } } var tabSize = cm.options.tabSize; var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); if (line.stateAfter) { line.stateAfter = null; } var curSpaceString = line.text.match(/^\s*/)[0], indentation; if (!aggressive && !/\S/.test(line.text)) { indentation = 0; how = "not"; } else if (how == "smart") { indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); if (indentation == Pass || indentation > 150) { if (!aggressive) { return } how = "prev"; } } if (how == "prev") { if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize); } else { indentation = 0; } } else if (how == "add") { indentation = curSpace + cm.options.indentUnit; } else if (how == "subtract") { indentation = curSpace - cm.options.indentUnit; } else if (typeof how == "number") { indentation = curSpace + how; } indentation = Math.max(0, indentation); var indentString = "", pos = 0; if (cm.options.indentWithTabs) { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} } if (pos < indentation) { indentString += spaceStr(indentation - pos); } if (indentString != curSpaceString) { replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); line.stateAfter = null; return true } else { // Ensure that, if the cursor was in the whitespace at the start // of the line, it is moved to the end of that space. for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) { var range = doc.sel.ranges[i$1]; if (range.head.line == n && range.head.ch < curSpaceString.length) { var pos$1 = Pos(n, curSpaceString.length); replaceOneSelection(doc, i$1, new Range(pos$1, pos$1)); break } } } } // This will be set to a {lineWise: bool, text: [string]} object, so // that, when pasting, we know what kind of selections the copied // text was made out of. var lastCopied = null; function setLastCopied(newLastCopied) { lastCopied = newLastCopied; } function applyTextInput(cm, inserted, deleted, sel, origin) { var doc = cm.doc; cm.display.shift = false; if (!sel) { sel = doc.sel; } var recent = +new Date - 200; var paste = origin == "paste" || cm.state.pasteIncoming > recent; var textLines = splitLinesAuto(inserted), multiPaste = null; // When pasting N lines into N selections, insert one line per selection if (paste && sel.ranges.length > 1) { if (lastCopied && lastCopied.text.join("\n") == inserted) { if (sel.ranges.length % lastCopied.text.length == 0) { multiPaste = []; for (var i = 0; i < lastCopied.text.length; i++) { multiPaste.push(doc.splitLines(lastCopied.text[i])); } } } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) { multiPaste = map(textLines, function (l) { return [l]; }); } } var updateInput = cm.curOp.updateInput; // Normal behavior is to insert the new text into every selection for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) { var range = sel.ranges[i$1]; var from = range.from(), to = range.to(); if (range.empty()) { if (deleted && deleted > 0) // Handle deletion { from = Pos(from.line, from.ch - deleted); } else if (cm.state.overwrite && !paste) // Handle overwrite { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); } else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == textLines.join("\n")) { from = to = Pos(from.line, 0); } } var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines, origin: origin || (paste ? "paste" : cm.state.cutIncoming > recent ? "cut" : "+input")}; makeChange(cm.doc, changeEvent); signalLater(cm, "inputRead", cm, changeEvent); } if (inserted && !paste) { triggerElectric(cm, inserted); } ensureCursorVisible(cm); if (cm.curOp.updateInput < 2) { cm.curOp.updateInput = updateInput; } cm.curOp.typing = true; cm.state.pasteIncoming = cm.state.cutIncoming = -1; } function handlePaste(e, cm) { var pasted = e.clipboardData && e.clipboardData.getData("Text"); if (pasted) { e.preventDefault(); if (!cm.isReadOnly() && !cm.options.disableInput && cm.hasFocus()) { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }); } return true } } function triggerElectric(cm, inserted) { // When an 'electric' character is inserted, immediately trigger a reindent if (!cm.options.electricChars || !cm.options.smartIndent) { return } var sel = cm.doc.sel; for (var i = sel.ranges.length - 1; i >= 0; i--) { var range = sel.ranges[i]; if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue } var mode = cm.getModeAt(range.head); var indented = false; if (mode.electricChars) { for (var j = 0; j < mode.electricChars.length; j++) { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { indented = indentLine(cm, range.head.line, "smart"); break } } } else if (mode.electricInput) { if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch))) { indented = indentLine(cm, range.head.line, "smart"); } } if (indented) { signalLater(cm, "electricInput", cm, range.head.line); } } } function copyableRanges(cm) { var text = [], ranges = []; for (var i = 0; i < cm.doc.sel.ranges.length; i++) { var line = cm.doc.sel.ranges[i].head.line; var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}; ranges.push(lineRange); text.push(cm.getRange(lineRange.anchor, lineRange.head)); } return {text: text, ranges: ranges} } function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) { field.setAttribute("autocorrect", autocorrect ? "on" : "off"); field.setAttribute("autocapitalize", autocapitalize ? "on" : "off"); field.setAttribute("spellcheck", !!spellcheck); } function hiddenTextarea() { var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; min-height: 1em; outline: none"); var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); // The textarea is kept positioned near the cursor to prevent the // fact that it'll be scrolled into view on input from scrolling // our fake cursor out of view. On webkit, when wrap=off, paste is // very slow. So make the area wide instead. if (webkit) { te.style.width = "1000px"; } else { te.setAttribute("wrap", "off"); } // If border: 0; -- iOS fails to open keyboard (issue #1287) if (ios) { te.style.border = "1px solid black"; } return div } // The publicly visible API. Note that methodOp(f) means // 'wrap f in an operation, performed on its `this` parameter'. // This is not the complete set of editor methods. Most of the // methods defined on the Doc type are also injected into // CodeMirror.prototype, for backwards compatibility and // convenience. function addEditorMethods(CodeMirror) { var optionHandlers = CodeMirror.optionHandlers; var helpers = CodeMirror.helpers = {}; CodeMirror.prototype = { constructor: CodeMirror, focus: function(){win(this).focus(); this.display.input.focus();}, setOption: function(option, value) { var options = this.options, old = options[option]; if (options[option] == value && option != "mode") { return } options[option] = value; if (optionHandlers.hasOwnProperty(option)) { operation(this, optionHandlers[option])(this, value, old); } signal(this, "optionChange", this, option); }, getOption: function(option) {return this.options[option]}, getDoc: function() {return this.doc}, addKeyMap: function(map, bottom) { this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)); }, removeKeyMap: function(map) { var maps = this.state.keyMaps; for (var i = 0; i < maps.length; ++i) { if (maps[i] == map || maps[i].name == map) { maps.splice(i, 1); return true } } }, addOverlay: methodOp(function(spec, options) { var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); if (mode.startState) { throw new Error("Overlays may not be stateful.") } insertSorted(this.state.overlays, {mode: mode, modeSpec: spec, opaque: options && options.opaque, priority: (options && options.priority) || 0}, function (overlay) { return overlay.priority; }); this.state.modeGen++; regChange(this); }), removeOverlay: methodOp(function(spec) { var overlays = this.state.overlays; for (var i = 0; i < overlays.length; ++i) { var cur = overlays[i].modeSpec; if (cur == spec || typeof spec == "string" && cur.name == spec) { overlays.splice(i, 1); this.state.modeGen++; regChange(this); return } } }), indentLine: methodOp(function(n, dir, aggressive) { if (typeof dir != "string" && typeof dir != "number") { if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev"; } else { dir = dir ? "add" : "subtract"; } } if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive); } }), indentSelection: methodOp(function(how) { var ranges = this.doc.sel.ranges, end = -1; for (var i = 0; i < ranges.length; i++) { var range = ranges[i]; if (!range.empty()) { var from = range.from(), to = range.to(); var start = Math.max(end, from.line); end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1; for (var j = start; j < end; ++j) { indentLine(this, j, how); } var newRanges = this.doc.sel.ranges; if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) { replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); } } else if (range.head.line > end) { indentLine(this, range.head.line, how, true); end = range.head.line; if (i == this.doc.sel.primIndex) { ensureCursorVisible(this); } } } }), // Fetch the parser token for a given character. Useful for hacks // that want to inspect the mode state (say, for completion). getTokenAt: function(pos, precise) { return takeToken(this, pos, precise) }, getLineTokens: function(line, precise) { return takeToken(this, Pos(line), precise, true) }, getTokenTypeAt: function(pos) { pos = clipPos(this.doc, pos); var styles = getLineStyles(this, getLine(this.doc, pos.line)); var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; var type; if (ch == 0) { type = styles[2]; } else { for (;;) { var mid = (before + after) >> 1; if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid; } else if (styles[mid * 2 + 1] < ch) { before = mid + 1; } else { type = styles[mid * 2 + 2]; break } } } var cut = type ? type.indexOf("overlay ") : -1; return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1) }, getModeAt: function(pos) { var mode = this.doc.mode; if (!mode.innerMode) { return mode } return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode }, getHelper: function(pos, type) { return this.getHelpers(pos, type)[0] }, getHelpers: function(pos, type) { var found = []; if (!helpers.hasOwnProperty(type)) { return found } var help = helpers[type], mode = this.getModeAt(pos); if (typeof mode[type] == "string") { if (help[mode[type]]) { found.push(help[mode[type]]); } } else if (mode[type]) { for (var i = 0; i < mode[type].length; i++) { var val = help[mode[type][i]]; if (val) { found.push(val); } } } else if (mode.helperType && help[mode.helperType]) { found.push(help[mode.helperType]); } else if (help[mode.name]) { found.push(help[mode.name]); } for (var i$1 = 0; i$1 < help._global.length; i$1++) { var cur = help._global[i$1]; if (cur.pred(mode, this) && indexOf(found, cur.val) == -1) { found.push(cur.val); } } return found }, getStateAfter: function(line, precise) { var doc = this.doc; line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); return getContextBefore(this, line + 1, precise).state }, cursorCoords: function(start, mode) { var pos, range = this.doc.sel.primary(); if (start == null) { pos = range.head; } else if (typeof start == "object") { pos = clipPos(this.doc, start); } else { pos = start ? range.from() : range.to(); } return cursorCoords(this, pos, mode || "page") }, charCoords: function(pos, mode) { return charCoords(this, clipPos(this.doc, pos), mode || "page") }, coordsChar: function(coords, mode) { coords = fromCoordSystem(this, coords, mode || "page"); return coordsChar(this, coords.left, coords.top) }, lineAtHeight: function(height, mode) { height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top; return lineAtHeight(this.doc, height + this.display.viewOffset) }, heightAtLine: function(line, mode, includeWidgets) { var end = false, lineObj; if (typeof line == "number") { var last = this.doc.first + this.doc.size - 1; if (line < this.doc.first) { line = this.doc.first; } else if (line > last) { line = last; end = true; } lineObj = getLine(this.doc, line); } else { lineObj = line; } return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top + (end ? this.doc.height - heightAtLine(lineObj) : 0) }, defaultTextHeight: function() { return textHeight(this.display) }, defaultCharWidth: function() { return charWidth(this.display) }, getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}}, addWidget: function(pos, node, scroll, vert, horiz) { var display = this.display; pos = cursorCoords(this, clipPos(this.doc, pos)); var top = pos.bottom, left = pos.left; node.style.position = "absolute"; node.setAttribute("cm-ignore-events", "true"); this.display.input.setUneditable(node); display.sizer.appendChild(node); if (vert == "over") { top = pos.top; } else if (vert == "above" || vert == "near") { var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); // Default to positioning above (if specified and possible); otherwise default to positioning below if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) { top = pos.top - node.offsetHeight; } else if (pos.bottom + node.offsetHeight <= vspace) { top = pos.bottom; } if (left + node.offsetWidth > hspace) { left = hspace - node.offsetWidth; } } node.style.top = top + "px"; node.style.left = node.style.right = ""; if (horiz == "right") { left = display.sizer.clientWidth - node.offsetWidth; node.style.right = "0px"; } else { if (horiz == "left") { left = 0; } else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2; } node.style.left = left + "px"; } if (scroll) { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}); } }, triggerOnKeyDown: methodOp(onKeyDown), triggerOnKeyPress: methodOp(onKeyPress), triggerOnKeyUp: onKeyUp, triggerOnMouseDown: methodOp(onMouseDown), execCommand: function(cmd) { if (commands.hasOwnProperty(cmd)) { return commands[cmd].call(null, this) } }, triggerElectric: methodOp(function(text) { triggerElectric(this, text); }), findPosH: function(from, amount, unit, visually) { var dir = 1; if (amount < 0) { dir = -1; amount = -amount; } var cur = clipPos(this.doc, from); for (var i = 0; i < amount; ++i) { cur = findPosH(this.doc, cur, dir, unit, visually); if (cur.hitSide) { break } } return cur }, moveH: methodOp(function(dir, unit) { var this$1 = this; this.extendSelectionsBy(function (range) { if (this$1.display.shift || this$1.doc.extend || range.empty()) { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) } else { return dir < 0 ? range.from() : range.to() } }, sel_move); }), deleteH: methodOp(function(dir, unit) { var sel = this.doc.sel, doc = this.doc; if (sel.somethingSelected()) { doc.replaceSelection("", null, "+delete"); } else { deleteNearSelection(this, function (range) { var other = findPosH(doc, range.head, dir, unit, false); return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other} }); } }), findPosV: function(from, amount, unit, goalColumn) { var dir = 1, x = goalColumn; if (amount < 0) { dir = -1; amount = -amount; } var cur = clipPos(this.doc, from); for (var i = 0; i < amount; ++i) { var coords = cursorCoords(this, cur, "div"); if (x == null) { x = coords.left; } else { coords.left = x; } cur = findPosV(this, coords, dir, unit); if (cur.hitSide) { break } } return cur }, moveV: methodOp(function(dir, unit) { var this$1 = this; var doc = this.doc, goals = []; var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected(); doc.extendSelectionsBy(function (range) { if (collapse) { return dir < 0 ? range.from() : range.to() } var headPos = cursorCoords(this$1, range.head, "div"); if (range.goalColumn != null) { headPos.left = range.goalColumn; } goals.push(headPos.left); var pos = findPosV(this$1, headPos, dir, unit); if (unit == "page" && range == doc.sel.primary()) { addToScrollTop(this$1, charCoords(this$1, pos, "div").top - headPos.top); } return pos }, sel_move); if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++) { doc.sel.ranges[i].goalColumn = goals[i]; } } }), // Find the word at the given position (as returned by coordsChar). findWordAt: function(pos) { var doc = this.doc, line = getLine(doc, pos.line).text; var start = pos.ch, end = pos.ch; if (line) { var helper = this.getHelper(pos, "wordChars"); if ((pos.sticky == "before" || end == line.length) && start) { --start; } else { ++end; } var startChar = line.charAt(start); var check = isWordChar(startChar, helper) ? function (ch) { return isWordChar(ch, helper); } : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); } : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); }; while (start > 0 && check(line.charAt(start - 1))) { --start; } while (end < line.length && check(line.charAt(end))) { ++end; } } return new Range(Pos(pos.line, start), Pos(pos.line, end)) }, toggleOverwrite: function(value) { if (value != null && value == this.state.overwrite) { return } if (this.state.overwrite = !this.state.overwrite) { addClass(this.display.cursorDiv, "CodeMirror-overwrite"); } else { rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); } signal(this, "overwriteToggle", this, this.state.overwrite); }, hasFocus: function() { return this.display.input.getField() == activeElt(root(this)) }, isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) }, scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }), getScrollInfo: function() { var scroller = this.display.scroller; return {left: scroller.scrollLeft, top: scroller.scrollTop, height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, clientHeight: displayHeight(this), clientWidth: displayWidth(this)} }, scrollIntoView: methodOp(function(range, margin) { if (range == null) { range = {from: this.doc.sel.primary().head, to: null}; if (margin == null) { margin = this.options.cursorScrollMargin; } } else if (typeof range == "number") { range = {from: Pos(range, 0), to: null}; } else if (range.from == null) { range = {from: range, to: null}; } if (!range.to) { range.to = range.from; } range.margin = margin || 0; if (range.from.line != null) { scrollToRange(this, range); } else { scrollToCoordsRange(this, range.from, range.to, range.margin); } }), setSize: methodOp(function(width, height) { var this$1 = this; var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; }; if (width != null) { this.display.wrapper.style.width = interpret(width); } if (height != null) { this.display.wrapper.style.height = interpret(height); } if (this.options.lineWrapping) { clearLineMeasurementCache(this); } var lineNo = this.display.viewFrom; this.doc.iter(lineNo, this.display.viewTo, function (line) { if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } } ++lineNo; }); this.curOp.forceUpdate = true; signal(this, "refresh", this); }), operation: function(f){return runInOp(this, f)}, startOperation: function(){return startOperation(this)}, endOperation: function(){return endOperation(this)}, refresh: methodOp(function() { var oldHeight = this.display.cachedTextHeight; regChange(this); this.curOp.forceUpdate = true; clearCaches(this); scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop); updateGutterSpace(this.display); if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5 || this.options.lineWrapping) { estimateLineHeights(this); } signal(this, "refresh", this); }), swapDoc: methodOp(function(doc) { var old = this.doc; old.cm = null; // Cancel the current text selection if any (#5821) if (this.state.selectingText) { this.state.selectingText(); } attachDoc(this, doc); clearCaches(this); this.display.input.reset(); scrollToCoords(this, doc.scrollLeft, doc.scrollTop); this.curOp.forceScroll = true; signalLater(this, "swapDoc", this, old); return old }), phrase: function(phraseText) { var phrases = this.options.phrases; return phrases && Object.prototype.hasOwnProperty.call(phrases, phraseText) ? phrases[phraseText] : phraseText }, getInputField: function(){return this.display.input.getField()}, getWrapperElement: function(){return this.display.wrapper}, getScrollerElement: function(){return this.display.scroller}, getGutterElement: function(){return this.display.gutters} }; eventMixin(CodeMirror); CodeMirror.registerHelper = function(type, name, value) { if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []}; } helpers[type][name] = value; }; CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { CodeMirror.registerHelper(type, name, value); helpers[type]._global.push({pred: predicate, val: value}); }; } // Used for horizontal relative motion. Dir is -1 or 1 (left or // right), unit can be "codepoint", "char", "column" (like char, but // doesn't cross line boundaries), "word" (across next word), or // "group" (to the start of next group of word or // non-word-non-whitespace chars). The visually param controls // whether, in right-to-left text, direction 1 means to move towards // the next index in the string, or towards the character to the right // of the current position. The resulting position will have a // hitSide=true property if it reached the end of the document. function findPosH(doc, pos, dir, unit, visually) { var oldPos = pos; var origDir = dir; var lineObj = getLine(doc, pos.line); var lineDir = visually && doc.direction == "rtl" ? -dir : dir; function findNextLine() { var l = pos.line + lineDir; if (l < doc.first || l >= doc.first + doc.size) { return false } pos = new Pos(l, pos.ch, pos.sticky); return lineObj = getLine(doc, l) } function moveOnce(boundToLine) { var next; if (unit == "codepoint") { var ch = lineObj.text.charCodeAt(pos.ch + (dir > 0 ? 0 : -1)); if (isNaN(ch)) { next = null; } else { var astral = dir > 0 ? ch >= 0xD800 && ch < 0xDC00 : ch >= 0xDC00 && ch < 0xDFFF; next = new Pos(pos.line, Math.max(0, Math.min(lineObj.text.length, pos.ch + dir * (astral ? 2 : 1))), -dir); } } else if (visually) { next = moveVisually(doc.cm, lineObj, pos, dir); } else { next = moveLogically(lineObj, pos, dir); } if (next == null) { if (!boundToLine && findNextLine()) { pos = endOfLine(visually, doc.cm, lineObj, pos.line, lineDir); } else { return false } } else { pos = next; } return true } if (unit == "char" || unit == "codepoint") { moveOnce(); } else if (unit == "column") { moveOnce(true); } else if (unit == "word" || unit == "group") { var sawType = null, group = unit == "group"; var helper = doc.cm && doc.cm.getHelper(pos, "wordChars"); for (var first = true;; first = false) { if (dir < 0 && !moveOnce(!first)) { break } var cur = lineObj.text.charAt(pos.ch) || "\n"; var type = isWordChar(cur, helper) ? "w" : group && cur == "\n" ? "n" : !group || /\s/.test(cur) ? null : "p"; if (group && !first && !type) { type = "s"; } if (sawType && sawType != type) { if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after";} break } if (type) { sawType = type; } if (dir > 0 && !moveOnce(!first)) { break } } } var result = skipAtomic(doc, pos, oldPos, origDir, true); if (equalCursorPos(oldPos, result)) { result.hitSide = true; } return result } // For relative vertical movement. Dir may be -1 or 1. Unit can be // "page" or "line". The resulting position will have a hitSide=true // property if it reached the end of the document. function findPosV(cm, pos, dir, unit) { var doc = cm.doc, x = pos.left, y; if (unit == "page") { var pageSize = Math.min(cm.display.wrapper.clientHeight, win(cm).innerHeight || doc(cm).documentElement.clientHeight); var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3); y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount; } else if (unit == "line") { y = dir > 0 ? pos.bottom + 3 : pos.top - 3; } var target; for (;;) { target = coordsChar(cm, x, y); if (!target.outside) { break } if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break } y += dir * 5; } return target } // CONTENTEDITABLE INPUT STYLE var ContentEditableInput = function(cm) { this.cm = cm; this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null; this.polling = new Delayed(); this.composing = null; this.gracePeriod = false; this.readDOMTimeout = null; }; ContentEditableInput.prototype.init = function (display) { var this$1 = this; var input = this, cm = input.cm; var div = input.div = display.lineDiv; div.contentEditable = true; disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize); function belongsToInput(e) { for (var t = e.target; t; t = t.parentNode) { if (t == div) { return true } if (/\bCodeMirror-(?:line)?widget\b/.test(t.className)) { break } } return false } on(div, "paste", function (e) { if (!belongsToInput(e) || signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } // IE doesn't fire input events, so we schedule a read for the pasted content in this way if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20); } }); on(div, "compositionstart", function (e) { this$1.composing = {data: e.data, done: false}; }); on(div, "compositionupdate", function (e) { if (!this$1.composing) { this$1.composing = {data: e.data, done: false}; } }); on(div, "compositionend", function (e) { if (this$1.composing) { if (e.data != this$1.composing.data) { this$1.readFromDOMSoon(); } this$1.composing.done = true; } }); on(div, "touchstart", function () { return input.forceCompositionEnd(); }); on(div, "input", function () { if (!this$1.composing) { this$1.readFromDOMSoon(); } }); function onCopyCut(e) { if (!belongsToInput(e) || signalDOMEvent(cm, e)) { return } if (cm.somethingSelected()) { setLastCopied({lineWise: false, text: cm.getSelections()}); if (e.type == "cut") { cm.replaceSelection("", null, "cut"); } } else if (!cm.options.lineWiseCopyCut) { return } else { var ranges = copyableRanges(cm); setLastCopied({lineWise: true, text: ranges.text}); if (e.type == "cut") { cm.operation(function () { cm.setSelections(ranges.ranges, 0, sel_dontScroll); cm.replaceSelection("", null, "cut"); }); } } if (e.clipboardData) { e.clipboardData.clearData(); var content = lastCopied.text.join("\n"); // iOS exposes the clipboard API, but seems to discard content inserted into it e.clipboardData.setData("Text", content); if (e.clipboardData.getData("Text") == content) { e.preventDefault(); return } } // Old-fashioned briefly-focus-a-textarea hack var kludge = hiddenTextarea(), te = kludge.firstChild; disableBrowserMagic(te); cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); te.value = lastCopied.text.join("\n"); var hadFocus = activeElt(rootNode(div)); selectInput(te); setTimeout(function () { cm.display.lineSpace.removeChild(kludge); hadFocus.focus(); if (hadFocus == div) { input.showPrimarySelection(); } }, 50); } on(div, "copy", onCopyCut); on(div, "cut", onCopyCut); }; ContentEditableInput.prototype.screenReaderLabelChanged = function (label) { // Label for screenreaders, accessibility if(label) { this.div.setAttribute('aria-label', label); } else { this.div.removeAttribute('aria-label'); } }; ContentEditableInput.prototype.prepareSelection = function () { var result = prepareSelection(this.cm, false); result.focus = activeElt(rootNode(this.div)) == this.div; return result }; ContentEditableInput.prototype.showSelection = function (info, takeFocus) { if (!info || !this.cm.display.view.length) { return } if (info.focus || takeFocus) { this.showPrimarySelection(); } this.showMultipleSelections(info); }; ContentEditableInput.prototype.getSelection = function () { return this.cm.display.wrapper.ownerDocument.getSelection() }; ContentEditableInput.prototype.showPrimarySelection = function () { var sel = this.getSelection(), cm = this.cm, prim = cm.doc.sel.primary(); var from = prim.from(), to = prim.to(); if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) { sel.removeAllRanges(); return } var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset); if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && cmp(minPos(curAnchor, curFocus), from) == 0 && cmp(maxPos(curAnchor, curFocus), to) == 0) { return } var view = cm.display.view; var start = (from.line >= cm.display.viewFrom && posToDOM(cm, from)) || {node: view[0].measure.map[2], offset: 0}; var end = to.line < cm.display.viewTo && posToDOM(cm, to); if (!end) { var measure = view[view.length - 1].measure; var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map; end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]}; } if (!start || !end) { sel.removeAllRanges(); return } var old = sel.rangeCount && sel.getRangeAt(0), rng; try { rng = range(start.node, start.offset, end.offset, end.node); } catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible if (rng) { if (!gecko && cm.state.focused) { sel.collapse(start.node, start.offset); if (!rng.collapsed) { sel.removeAllRanges(); sel.addRange(rng); } } else { sel.removeAllRanges(); sel.addRange(rng); } if (old && sel.anchorNode == null) { sel.addRange(old); } else if (gecko) { this.startGracePeriod(); } } this.rememberSelection(); }; ContentEditableInput.prototype.startGracePeriod = function () { var this$1 = this; clearTimeout(this.gracePeriod); this.gracePeriod = setTimeout(function () { this$1.gracePeriod = false; if (this$1.selectionChanged()) { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }); } }, 20); }; ContentEditableInput.prototype.showMultipleSelections = function (info) { removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors); removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection); }; ContentEditableInput.prototype.rememberSelection = function () { var sel = this.getSelection(); this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset; this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset; }; ContentEditableInput.prototype.selectionInEditor = function () { var sel = this.getSelection(); if (!sel.rangeCount) { return false } var node = sel.getRangeAt(0).commonAncestorContainer; return contains(this.div, node) }; ContentEditableInput.prototype.focus = function () { if (this.cm.options.readOnly != "nocursor") { if (!this.selectionInEditor() || activeElt(rootNode(this.div)) != this.div) { this.showSelection(this.prepareSelection(), true); } this.div.focus(); } }; ContentEditableInput.prototype.blur = function () { this.div.blur(); }; ContentEditableInput.prototype.getField = function () { return this.div }; ContentEditableInput.prototype.supportsTouch = function () { return true }; ContentEditableInput.prototype.receivedFocus = function () { var this$1 = this; var input = this; if (this.selectionInEditor()) { setTimeout(function () { return this$1.pollSelection(); }, 20); } else { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); } function poll() { if (input.cm.state.focused) { input.pollSelection(); input.polling.set(input.cm.options.pollInterval, poll); } } this.polling.set(this.cm.options.pollInterval, poll); }; ContentEditableInput.prototype.selectionChanged = function () { var sel = this.getSelection(); return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset }; ContentEditableInput.prototype.pollSelection = function () { if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return } var sel = this.getSelection(), cm = this.cm; // On Android Chrome (version 56, at least), backspacing into an // uneditable block element will put the cursor in that element, // and then, because it's not editable, hide the virtual keyboard. // Because Android doesn't allow us to actually detect backspace // presses in a sane way, this code checks for when that happens // and simulates a backspace press in this case. if (android && chrome && this.cm.display.gutterSpecs.length && isInGutter(sel.anchorNode)) { this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs}); this.blur(); this.focus(); return } if (this.composing) { return } this.rememberSelection(); var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); var head = domToPos(cm, sel.focusNode, sel.focusOffset); if (anchor && head) { runInOp(cm, function () { setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll); if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true; } }); } }; ContentEditableInput.prototype.pollContent = function () { if (this.readDOMTimeout != null) { clearTimeout(this.readDOMTimeout); this.readDOMTimeout = null; } var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary(); var from = sel.from(), to = sel.to(); if (from.ch == 0 && from.line > cm.firstLine()) { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length); } if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine()) { to = Pos(to.line + 1, 0); } if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false } var fromIndex, fromLine, fromNode; if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { fromLine = lineNo(display.view[0].line); fromNode = display.view[0].node; } else { fromLine = lineNo(display.view[fromIndex].line); fromNode = display.view[fromIndex - 1].node.nextSibling; } var toIndex = findViewIndex(cm, to.line); var toLine, toNode; if (toIndex == display.view.length - 1) { toLine = display.viewTo - 1; toNode = display.lineDiv.lastChild; } else { toLine = lineNo(display.view[toIndex + 1].line) - 1; toNode = display.view[toIndex + 1].node.previousSibling; } if (!fromNode) { return false } var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)); var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)); while (newText.length > 1 && oldText.length > 1) { if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; } else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; } else { break } } var cutFront = 0, cutEnd = 0; var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length); while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) { ++cutFront; } var newBot = lst(newText), oldBot = lst(oldText); var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), oldBot.length - (oldText.length == 1 ? cutFront : 0)); while (cutEnd < maxCutEnd && newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) { ++cutEnd; } // Try to move start of change to start of selection if ambiguous if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) { while (cutFront && cutFront > from.ch && newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) { cutFront--; cutEnd++; } } newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, ""); newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, ""); var chFrom = Pos(fromLine, cutFront); var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0); if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { replaceRange(cm.doc, newText, chFrom, chTo, "+input"); return true } }; ContentEditableInput.prototype.ensurePolled = function () { this.forceCompositionEnd(); }; ContentEditableInput.prototype.reset = function () { this.forceCompositionEnd(); }; ContentEditableInput.prototype.forceCompositionEnd = function () { if (!this.composing) { return } clearTimeout(this.readDOMTimeout); this.composing = null; this.updateFromDOM(); this.div.blur(); this.div.focus(); }; ContentEditableInput.prototype.readFromDOMSoon = function () { var this$1 = this; if (this.readDOMTimeout != null) { return } this.readDOMTimeout = setTimeout(function () { this$1.readDOMTimeout = null; if (this$1.composing) { if (this$1.composing.done) { this$1.composing = null; } else { return } } this$1.updateFromDOM(); }, 80); }; ContentEditableInput.prototype.updateFromDOM = function () { var this$1 = this; if (this.cm.isReadOnly() || !this.pollContent()) { runInOp(this.cm, function () { return regChange(this$1.cm); }); } }; ContentEditableInput.prototype.setUneditable = function (node) { node.contentEditable = "false"; }; ContentEditableInput.prototype.onKeyPress = function (e) { if (e.charCode == 0 || this.composing) { return } e.preventDefault(); if (!this.cm.isReadOnly()) { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); } }; ContentEditableInput.prototype.readOnlyChanged = function (val) { this.div.contentEditable = String(val != "nocursor"); }; ContentEditableInput.prototype.onContextMenu = function () {}; ContentEditableInput.prototype.resetPosition = function () {}; ContentEditableInput.prototype.needsContentAttribute = true; function posToDOM(cm, pos) { var view = findViewForLine(cm, pos.line); if (!view || view.hidden) { return null } var line = getLine(cm.doc, pos.line); var info = mapFromLineView(view, line, pos.line); var order = getOrder(line, cm.doc.direction), side = "left"; if (order) { var partPos = getBidiPartAt(order, pos.ch); side = partPos % 2 ? "right" : "left"; } var result = nodeAndOffsetInLineMap(info.map, pos.ch, side); result.offset = result.collapse == "right" ? result.end : result.start; return result } function isInGutter(node) { for (var scan = node; scan; scan = scan.parentNode) { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } } return false } function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos } function domTextBetween(cm, from, to, fromLine, toLine) { var text = "", closing = false, lineSep = cm.doc.lineSeparator(), extraLinebreak = false; function recognizeMarker(id) { return function (marker) { return marker.id == id; } } function close() { if (closing) { text += lineSep; if (extraLinebreak) { text += lineSep; } closing = extraLinebreak = false; } } function addText(str) { if (str) { close(); text += str; } } function walk(node) { if (node.nodeType == 1) { var cmText = node.getAttribute("cm-text"); if (cmText) { addText(cmText); return } var markerID = node.getAttribute("cm-marker"), range; if (markerID) { var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)); if (found.length && (range = found[0].find(0))) { addText(getBetween(cm.doc, range.from, range.to).join(lineSep)); } return } if (node.getAttribute("contenteditable") == "false") { return } var isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName); if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) { return } if (isBlock) { close(); } for (var i = 0; i < node.childNodes.length; i++) { walk(node.childNodes[i]); } if (/^(pre|p)$/i.test(node.nodeName)) { extraLinebreak = true; } if (isBlock) { closing = true; } } else if (node.nodeType == 3) { addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " ")); } } for (;;) { walk(from); if (from == to) { break } from = from.nextSibling; extraLinebreak = false; } return text } function domToPos(cm, node, offset) { var lineNode; if (node == cm.display.lineDiv) { lineNode = cm.display.lineDiv.childNodes[offset]; if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) } node = null; offset = 0; } else { for (lineNode = node;; lineNode = lineNode.parentNode) { if (!lineNode || lineNode == cm.display.lineDiv) { return null } if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break } } } for (var i = 0; i < cm.display.view.length; i++) { var lineView = cm.display.view[i]; if (lineView.node == lineNode) { return locateNodeInLineView(lineView, node, offset) } } } function locateNodeInLineView(lineView, node, offset) { var wrapper = lineView.text.firstChild, bad = false; if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) } if (node == wrapper) { bad = true; node = wrapper.childNodes[offset]; offset = 0; if (!node) { var line = lineView.rest ? lst(lineView.rest) : lineView.line; return badPos(Pos(lineNo(line), line.text.length), bad) } } var textNode = node.nodeType == 3 ? node : null, topNode = node; if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { textNode = node.firstChild; if (offset) { offset = textNode.nodeValue.length; } } while (topNode.parentNode != wrapper) { topNode = topNode.parentNode; } var measure = lineView.measure, maps = measure.maps; function find(textNode, topNode, offset) { for (var i = -1; i < (maps ? maps.length : 0); i++) { var map = i < 0 ? measure.map : maps[i]; for (var j = 0; j < map.length; j += 3) { var curNode = map[j + 2]; if (curNode == textNode || curNode == topNode) { var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]); var ch = map[j] + offset; if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)]; } return Pos(line, ch) } } } } var found = find(textNode, topNode, offset); if (found) { return badPos(found, bad) } // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { found = find(after, after.firstChild, 0); if (found) { return badPos(Pos(found.line, found.ch - dist), bad) } else { dist += after.textContent.length; } } for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) { found = find(before, before.firstChild, -1); if (found) { return badPos(Pos(found.line, found.ch + dist$1), bad) } else { dist$1 += before.textContent.length; } } } // TEXTAREA INPUT STYLE var TextareaInput = function(cm) { this.cm = cm; // See input.poll and input.reset this.prevInput = ""; // Flag that indicates whether we expect input to appear real soon // now (after some event like 'keypress' or 'input') and are // polling intensively. this.pollingFast = false; // Self-resetting timeout for the poller this.polling = new Delayed(); // Used to work around IE issue with selection being forgotten when focus moves away from textarea this.hasSelection = false; this.composing = null; this.resetting = false; }; TextareaInput.prototype.init = function (display) { var this$1 = this; var input = this, cm = this.cm; this.createField(display); var te = this.textarea; display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild); // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) if (ios) { te.style.width = "0px"; } on(te, "input", function () { if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null; } input.poll(); }); on(te, "paste", function (e) { if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } cm.state.pasteIncoming = +new Date; input.fastPoll(); }); function prepareCopyCut(e) { if (signalDOMEvent(cm, e)) { return } if (cm.somethingSelected()) { setLastCopied({lineWise: false, text: cm.getSelections()}); } else if (!cm.options.lineWiseCopyCut) { return } else { var ranges = copyableRanges(cm); setLastCopied({lineWise: true, text: ranges.text}); if (e.type == "cut") { cm.setSelections(ranges.ranges, null, sel_dontScroll); } else { input.prevInput = ""; te.value = ranges.text.join("\n"); selectInput(te); } } if (e.type == "cut") { cm.state.cutIncoming = +new Date; } } on(te, "cut", prepareCopyCut); on(te, "copy", prepareCopyCut); on(display.scroller, "paste", function (e) { if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return } if (!te.dispatchEvent) { cm.state.pasteIncoming = +new Date; input.focus(); return } // Pass the `paste` event to the textarea so it's handled by its event listener. var event = new Event("paste"); event.clipboardData = e.clipboardData; te.dispatchEvent(event); }); // Prevent normal selection in the editor (we handle our own) on(display.lineSpace, "selectstart", function (e) { if (!eventInWidget(display, e)) { e_preventDefault(e); } }); on(te, "compositionstart", function () { var start = cm.getCursor("from"); if (input.composing) { input.composing.range.clear(); } input.composing = { start: start, range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) }; }); on(te, "compositionend", function () { if (input.composing) { input.poll(); input.composing.range.clear(); input.composing = null; } }); }; TextareaInput.prototype.createField = function (_display) { // Wraps and hides input textarea this.wrapper = hiddenTextarea(); // The semihidden textarea that is focused when the editor is // focused, and receives input. this.textarea = this.wrapper.firstChild; var opts = this.cm.options; disableBrowserMagic(this.textarea, opts.spellcheck, opts.autocorrect, opts.autocapitalize); }; TextareaInput.prototype.screenReaderLabelChanged = function (label) { // Label for screenreaders, accessibility if(label) { this.textarea.setAttribute('aria-label', label); } else { this.textarea.removeAttribute('aria-label'); } }; TextareaInput.prototype.prepareSelection = function () { // Redraw the selection and/or cursor var cm = this.cm, display = cm.display, doc = cm.doc; var result = prepareSelection(cm); // Move the hidden textarea near the cursor to prevent scrolling artifacts if (cm.options.moveInputWithCursor) { var headPos = cursorCoords(cm, doc.sel.primary().head, "div"); var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, headPos.top + lineOff.top - wrapOff.top)); result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, headPos.left + lineOff.left - wrapOff.left)); } return result }; TextareaInput.prototype.showSelection = function (drawn) { var cm = this.cm, display = cm.display; removeChildrenAndAdd(display.cursorDiv, drawn.cursors); removeChildrenAndAdd(display.selectionDiv, drawn.selection); if (drawn.teTop != null) { this.wrapper.style.top = drawn.teTop + "px"; this.wrapper.style.left = drawn.teLeft + "px"; } }; // Reset the input to correspond to the selection (or to be empty, // when not typing and nothing is selected) TextareaInput.prototype.reset = function (typing) { if (this.contextMenuPending || this.composing && typing) { return } var cm = this.cm; this.resetting = true; if (cm.somethingSelected()) { this.prevInput = ""; var content = cm.getSelection(); this.textarea.value = content; if (cm.state.focused) { selectInput(this.textarea); } if (ie && ie_version >= 9) { this.hasSelection = content; } } else if (!typing) { this.prevInput = this.textarea.value = ""; if (ie && ie_version >= 9) { this.hasSelection = null; } } this.resetting = false; }; TextareaInput.prototype.getField = function () { return this.textarea }; TextareaInput.prototype.supportsTouch = function () { return false }; TextareaInput.prototype.focus = function () { if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt(rootNode(this.textarea)) != this.textarea)) { try { this.textarea.focus(); } catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM } }; TextareaInput.prototype.blur = function () { this.textarea.blur(); }; TextareaInput.prototype.resetPosition = function () { this.wrapper.style.top = this.wrapper.style.left = 0; }; TextareaInput.prototype.receivedFocus = function () { this.slowPoll(); }; // Poll for input changes, using the normal rate of polling. This // runs as long as the editor is focused. TextareaInput.prototype.slowPoll = function () { var this$1 = this; if (this.pollingFast) { return } this.polling.set(this.cm.options.pollInterval, function () { this$1.poll(); if (this$1.cm.state.focused) { this$1.slowPoll(); } }); }; // When an event has just come in that is likely to add or change // something in the input textarea, we poll faster, to ensure that // the change appears on the screen quickly. TextareaInput.prototype.fastPoll = function () { var missed = false, input = this; input.pollingFast = true; function p() { var changed = input.poll(); if (!changed && !missed) {missed = true; input.polling.set(60, p);} else {input.pollingFast = false; input.slowPoll();} } input.polling.set(20, p); }; // Read input from the textarea, and update the document to match. // When something is selected, it is present in the textarea, and // selected (unless it is huge, in which case a placeholder is // used). When nothing is selected, the cursor sits after previously // seen text (can be empty), which is stored in prevInput (we must // not reset the textarea when typing, because that breaks IME). TextareaInput.prototype.poll = function () { var this$1 = this; var cm = this.cm, input = this.textarea, prevInput = this.prevInput; // Since this is called a *lot*, try to bail out as cheaply as // possible when it is clear that nothing happened. hasSelection // will be the case when there is a lot of text in the textarea, // in which case reading its value would be expensive. if (this.contextMenuPending || this.resetting || !cm.state.focused || (hasSelection(input) && !prevInput && !this.composing) || cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) { return false } var text = input.value; // If nothing changed, bail. if (text == prevInput && !cm.somethingSelected()) { return false } // Work around nonsensical selection resetting in IE9/10, and // inexplicable appearance of private area unicode characters on // some key combos in Mac (#2689). if (ie && ie_version >= 9 && this.hasSelection === text || mac && /[\uf700-\uf7ff]/.test(text)) { cm.display.input.reset(); return false } if (cm.doc.sel == cm.display.selForContextMenu) { var first = text.charCodeAt(0); if (first == 0x200b && !prevInput) { prevInput = "\u200b"; } if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") } } // Find the part of the input that is actually new var same = 0, l = Math.min(prevInput.length, text.length); while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same; } runInOp(cm, function () { applyTextInput(cm, text.slice(same), prevInput.length - same, null, this$1.composing ? "*compose" : null); // Don't leave long text in the textarea, since it makes further polling slow if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = ""; } else { this$1.prevInput = text; } if (this$1.composing) { this$1.composing.range.clear(); this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"), {className: "CodeMirror-composing"}); } }); return true }; TextareaInput.prototype.ensurePolled = function () { if (this.pollingFast && this.poll()) { this.pollingFast = false; } }; TextareaInput.prototype.onKeyPress = function () { if (ie && ie_version >= 9) { this.hasSelection = null; } this.fastPoll(); }; TextareaInput.prototype.onContextMenu = function (e) { var input = this, cm = input.cm, display = cm.display, te = input.textarea; if (input.contextMenuPending) { input.contextMenuPending(); } var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; if (!pos || presto) { return } // Opera is difficult. // Reset the current text selection only if the click is done outside of the selection // and 'resetSelectionOnContextMenu' option is true. var reset = cm.options.resetSelectionOnContextMenu; if (reset && cm.doc.sel.contains(pos) == -1) { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); } var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText; var wrapperBox = input.wrapper.offsetParent.getBoundingClientRect(); input.wrapper.style.cssText = "position: static"; te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; var oldScrollY; if (webkit) { oldScrollY = te.ownerDocument.defaultView.scrollY; } // Work around Chrome issue (#2712) display.input.focus(); if (webkit) { te.ownerDocument.defaultView.scrollTo(null, oldScrollY); } display.input.reset(); // Adds "Select all" to context menu in FF if (!cm.somethingSelected()) { te.value = input.prevInput = " "; } input.contextMenuPending = rehide; display.selForContextMenu = cm.doc.sel; clearTimeout(display.detectingSelectAll); // Select-all will be greyed out if there's nothing to select, so // this adds a zero-width space so that we can later check whether // it got selected. function prepareSelectAllHack() { if (te.selectionStart != null) { var selected = cm.somethingSelected(); var extval = "\u200b" + (selected ? te.value : ""); te.value = "\u21da"; // Used to catch context-menu undo te.value = extval; input.prevInput = selected ? "" : "\u200b"; te.selectionStart = 1; te.selectionEnd = extval.length; // Re-set this, in case some other handler touched the // selection in the meantime. display.selForContextMenu = cm.doc.sel; } } function rehide() { if (input.contextMenuPending != rehide) { return } input.contextMenuPending = false; input.wrapper.style.cssText = oldWrapperCSS; te.style.cssText = oldCSS; if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); } // Try to detect the user choosing select-all if (te.selectionStart != null) { if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack(); } var i = 0, poll = function () { if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && te.selectionEnd > 0 && input.prevInput == "\u200b") { operation(cm, selectAll)(cm); } else if (i++ < 10) { display.detectingSelectAll = setTimeout(poll, 500); } else { display.selForContextMenu = null; display.input.reset(); } }; display.detectingSelectAll = setTimeout(poll, 200); } } if (ie && ie_version >= 9) { prepareSelectAllHack(); } if (captureRightClick) { e_stop(e); var mouseup = function () { off(window, "mouseup", mouseup); setTimeout(rehide, 20); }; on(window, "mouseup", mouseup); } else { setTimeout(rehide, 50); } }; TextareaInput.prototype.readOnlyChanged = function (val) { if (!val) { this.reset(); } this.textarea.disabled = val == "nocursor"; this.textarea.readOnly = !!val; }; TextareaInput.prototype.setUneditable = function () {}; TextareaInput.prototype.needsContentAttribute = false; function fromTextArea(textarea, options) { options = options ? copyObj(options) : {}; options.value = textarea.value; if (!options.tabindex && textarea.tabIndex) { options.tabindex = textarea.tabIndex; } if (!options.placeholder && textarea.placeholder) { options.placeholder = textarea.placeholder; } // Set autofocus to true if this textarea is focused, or if it has // autofocus and no other element is focused. if (options.autofocus == null) { var hasFocus = activeElt(rootNode(textarea)); options.autofocus = hasFocus == textarea || textarea.getAttribute("autofocus") != null && hasFocus == document.body; } function save() {textarea.value = cm.getValue();} var realSubmit; if (textarea.form) { on(textarea.form, "submit", save); // Deplorable hack to make the submit method do the right thing. if (!options.leaveSubmitMethodAlone) { var form = textarea.form; realSubmit = form.submit; try { var wrappedSubmit = form.submit = function () { save(); form.submit = realSubmit; form.submit(); form.submit = wrappedSubmit; }; } catch(e) {} } } options.finishInit = function (cm) { cm.save = save; cm.getTextArea = function () { return textarea; }; cm.toTextArea = function () { cm.toTextArea = isNaN; // Prevent this from being ran twice save(); textarea.parentNode.removeChild(cm.getWrapperElement()); textarea.style.display = ""; if (textarea.form) { off(textarea.form, "submit", save); if (!options.leaveSubmitMethodAlone && typeof textarea.form.submit == "function") { textarea.form.submit = realSubmit; } } }; }; textarea.style.display = "none"; var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); }, options); return cm } function addLegacyProps(CodeMirror) { CodeMirror.off = off; CodeMirror.on = on; CodeMirror.wheelEventPixels = wheelEventPixels; CodeMirror.Doc = Doc; CodeMirror.splitLines = splitLinesAuto; CodeMirror.countColumn = countColumn; CodeMirror.findColumn = findColumn; CodeMirror.isWordChar = isWordCharBasic; CodeMirror.Pass = Pass; CodeMirror.signal = signal; CodeMirror.Line = Line; CodeMirror.changeEnd = changeEnd; CodeMirror.scrollbarModel = scrollbarModel; CodeMirror.Pos = Pos; CodeMirror.cmpPos = cmp; CodeMirror.modes = modes; CodeMirror.mimeModes = mimeModes; CodeMirror.resolveMode = resolveMode; CodeMirror.getMode = getMode; CodeMirror.modeExtensions = modeExtensions; CodeMirror.extendMode = extendMode; CodeMirror.copyState = copyState; CodeMirror.startState = startState; CodeMirror.innerMode = innerMode; CodeMirror.commands = commands; CodeMirror.keyMap = keyMap; CodeMirror.keyName = keyName; CodeMirror.isModifierKey = isModifierKey; CodeMirror.lookupKey = lookupKey; CodeMirror.normalizeKeyMap = normalizeKeyMap; CodeMirror.StringStream = StringStream; CodeMirror.SharedTextMarker = SharedTextMarker; CodeMirror.TextMarker = TextMarker; CodeMirror.LineWidget = LineWidget; CodeMirror.e_preventDefault = e_preventDefault; CodeMirror.e_stopPropagation = e_stopPropagation; CodeMirror.e_stop = e_stop; CodeMirror.addClass = addClass; CodeMirror.contains = contains; CodeMirror.rmClass = rmClass; CodeMirror.keyNames = keyNames; } // EDITOR CONSTRUCTOR defineOptions(CodeMirror); addEditorMethods(CodeMirror); // Set up methods on CodeMirror's prototype to redirect to the editor's document. var dontDelegate = "iter insert remove copy getEditor constructor".split(" "); for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) { CodeMirror.prototype[prop] = (function(method) { return function() {return method.apply(this.doc, arguments)} })(Doc.prototype[prop]); } } eventMixin(Doc); CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}; // Extra arguments are stored as the mode's dependencies, which is // used by (legacy) mechanisms like loadmode.js to automatically // load a mode. (Preferred mechanism is the require/define calls.) CodeMirror.defineMode = function(name/*, mode, …*/) { if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name; } defineMode.apply(this, arguments); }; CodeMirror.defineMIME = defineMIME; // Minimal default mode. CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); }); CodeMirror.defineMIME("text/plain", "null"); // EXTENSIONS CodeMirror.defineExtension = function (name, func) { CodeMirror.prototype[name] = func; }; CodeMirror.defineDocExtension = function (name, func) { Doc.prototype[name] = func; }; CodeMirror.fromTextArea = fromTextArea; addLegacyProps(CodeMirror); CodeMirror.version = "5.65.16"; return CodeMirror; }))); icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/mode/000077500000000000000000000000001473125420300260115ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/public/js/vendor/codemirror/mode/yaml.js000066400000000000000000000072261473125420300273200ustar00rootroot00000000000000// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/5/LICENSE (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; CodeMirror.defineMode("yaml", function() { var cons = ['true', 'false', 'on', 'off', 'yes', 'no']; var keywordRegex = new RegExp("\\b(("+cons.join(")|(")+"))$", 'i'); return { token: function(stream, state) { var ch = stream.peek(); var esc = state.escaped; state.escaped = false; /* comments */ if (ch == "#" && (stream.pos == 0 || /\s/.test(stream.string.charAt(stream.pos - 1)))) { stream.skipToEnd(); return "comment"; } if (stream.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/)) return "string"; if (state.literal && stream.indentation() > state.keyCol) { stream.skipToEnd(); return "string"; } else if (state.literal) { state.literal = false; } if (stream.sol()) { state.keyCol = 0; state.pair = false; state.pairStart = false; /* document start */ if(stream.match('---')) { return "def"; } /* document end */ if (stream.match('...')) { return "def"; } /* array list item */ if (stream.match(/\s*-\s+/)) { return 'meta'; } } /* inline pairs/lists */ if (stream.match(/^(\{|\}|\[|\])/)) { if (ch == '{') state.inlinePairs++; else if (ch == '}') state.inlinePairs--; else if (ch == '[') state.inlineList++; else state.inlineList--; return 'meta'; } /* list separator */ if (state.inlineList > 0 && !esc && ch == ',') { stream.next(); return 'meta'; } /* pairs separator */ if (state.inlinePairs > 0 && !esc && ch == ',') { state.keyCol = 0; state.pair = false; state.pairStart = false; stream.next(); return 'meta'; } /* start of value of a pair */ if (state.pairStart) { /* block literals */ if (stream.match(/^\s*(\||\>)\s*/)) { state.literal = true; return 'meta'; }; /* references */ if (stream.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i)) { return 'variable-2'; } /* numbers */ if (state.inlinePairs == 0 && stream.match(/^\s*-?[0-9\.\,]+\s?$/)) { return 'number'; } if (state.inlinePairs > 0 && stream.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/)) { return 'number'; } /* keywords */ if (stream.match(keywordRegex)) { return 'keyword'; } } /* pairs (associative arrays) -> key */ if (!state.pair && stream.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^\s,\[\]{}#&*!|>'"%@`])[^#:]*(?=:($|\s))/)) { state.pair = true; state.keyCol = stream.indentation(); return "atom"; } if (state.pair && stream.match(/^:\s*/)) { state.pairStart = true; return 'meta'; } /* nothing found, continue */ state.pairStart = false; state.escaped = (ch == '\\'); stream.next(); return null; }, startState: function() { return { pair: false, pairStart: false, keyCol: 0, inlinePairs: 0, inlineList: 0, literal: false, escaped: false }; }, lineComment: "#", fold: "indent" }; }); CodeMirror.defineMIME("text/x-yaml", "yaml"); CodeMirror.defineMIME("text/yaml", "yaml"); }); icingaweb2-module-toplevelview-1.0.0/test/000077500000000000000000000000001473125420300205105ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/test/php/000077500000000000000000000000001473125420300212775ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/test/php/library/000077500000000000000000000000001473125420300227435ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/000077500000000000000000000000001473125420300254305ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/Model/000077500000000000000000000000001473125420300264705ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/Model/ViewTest.php000066400000000000000000000017441473125420300307610ustar00rootroot00000000000000assertSame('myview', $v->getName()); $tests = [ 'example' => true, 'Example' => true, 'ex_ample' => true, 'ex_am-ple' => true, '1ex_am-ple2' => true, 'Ex_a2m-ple123' => true, '1ex_am-ple2' => true, 'example.yaml' => true, 'e#x(_)am_123-ple' => false, 'ex/ample' => false, 'ex\ample' => false, '' => false, 'Филе' => true, '😺' => true, '../../example' => false ]; foreach ($tests as $name => $value) { $v->setName($name); $this->assertSame($v->validateName(), $value); } } } icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/Tree/000077500000000000000000000000001473125420300263275ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/Tree/TLVHostGroupNodeTest.php000066400000000000000000000044721473125420300330350ustar00rootroot00000000000000setProperties(['hostgroup'=>'unit']); $this->assertSame('unit', $n->getKey()); $mockRoot = new class { public function getFetched($type, $key) { $h = new stdClass; $h->display_name = 'host'; } }; $reflection = new ReflectionClass($n); $reflection_root = $reflection->getProperty('root'); $reflection_root->setAccessible(true); $reflection_root->setValue($n, $mockRoot); $this->assertSame('unit', $n->getTitle()); } public function testGetStatus() { $n = new TLVHostGroupNode(); $n->setProperties(['hostgroup'=>'unit']); $mockRoot = new class { public function get($thing) { return false; } public function getFetched($type, $key) { $h = new stdClass; $s = new stdClass; $s->hard_state = 1; $s->is_handled = true; $s->in_downtime = true; $h->display_name = 'hostgroup'; $h->hosts_total = 1; $h->hosts_up = 1; $h->hosts_total = 1; $h->services_total = 1; $h->hosts_up = 1; $h->services_ok = 1; $h->hosts_down_handled = 1; $h->hosts_down_unhandled = 1; $h->services_warning_handled = 1; $h->services_warning_unhandled = 1; $h->services_critical_handled = 1; $h->services_critical_unhandled = 1; $h->services_unknown_handled = 1; $h->services_unknown_unhandled = 1; return $h; } }; $reflection = new ReflectionClass($n); $reflection_root = $reflection->getProperty('root'); $reflection_root->setAccessible(true); $reflection_root->setValue($n, $mockRoot); $this->assertSame('critical unhandled', $n->getStatus()->getOverall()); } } icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/Tree/TLVHostNodeTest.php000066400000000000000000000034011473125420300320070ustar00rootroot00000000000000setProperties(['host'=>'unit']); $this->assertSame('unit', $n->getKey()); $mockRoot = new class { public function getFetched($type, $key) { $h = new stdClass; $h->display_name = 'host'; } }; $reflection = new ReflectionClass($n); $reflection_root = $reflection->getProperty('root'); $reflection_root->setAccessible(true); $reflection_root->setValue($n, $mockRoot); $this->assertSame('unit', $n->getTitle()); } public function testGetStatus() { $n = new TLVHostNode(); $n->setProperties(['host'=>'unit']); $mockRoot = new class { public function get($thing) { return false; } public function getFetched($type, $key) { $h = new stdClass; $h->display_name = 'host'; $s = new stdClass; $s->hard_state = 2; $s->is_handled = false; $s->in_downtime = false; $h->notifications_enabled = false; $h->state = $s; return $h; } }; $reflection = new ReflectionClass($n); $reflection_root = $reflection->getProperty('root'); $reflection_root->setAccessible(true); $reflection_root->setValue($n, $mockRoot); $this->assertSame('critical unhandled', $n->getStatus()->getOverall()); } } icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/Tree/TLVServiceGroupNodeTest.php000066400000000000000000000041521473125420300335130ustar00rootroot00000000000000setProperties(['servicegroup'=>'unit']); $this->assertSame('unit', $n->getKey()); $mockRoot = new class { public function getFetched($type, $key) { $h = new stdClass; $h->display_name = 'service'; } }; $reflection = new ReflectionClass($n); $reflection_root = $reflection->getProperty('root'); $reflection_root->setAccessible(true); $reflection_root->setValue($n, $mockRoot); $this->assertSame('unit', $n->getTitle()); } public function testGetStatus() { $n = new TLVServiceGroupNode(); $n->setProperties(['servicegroup'=>'unit']); $mockRoot = new class { public function get($thing) { return false; } public function getFetched($type, $key) { $h = new stdClass; $s = new stdClass; $s->hard_state = 1; $s->is_handled = true; $s->in_downtime = true; $h->display_name = 'servicegroup'; $h->services_total = 1; $h->services_ok = 1; $h->services_warning_handled = 1; $h->services_warning_unhandled = 1; $h->services_critical_handled = 1; $h->services_critical_unhandled = 1; $h->services_unknown_handled = 1; $h->services_unknown_unhandled = 1; return $h; } }; $reflection = new ReflectionClass($n); $reflection_root = $reflection->getProperty('root'); $reflection_root->setAccessible(true); $reflection_root->setValue($n, $mockRoot); $this->assertSame('critical unhandled', $n->getStatus()->getOverall()); } } icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/Tree/TLVServiceNodeTest.php000066400000000000000000000035001473125420300324720ustar00rootroot00000000000000setProperties(['service'=>'unit', 'host'=>'test']); $this->assertSame('test!unit', $n->getKey()); $mockRoot = new class { public function getFetched($type, $key) { $h = new stdClass; $h->display_name = 'service'; } }; $reflection = new ReflectionClass($n); $reflection_root = $reflection->getProperty('root'); $reflection_root->setAccessible(true); $reflection_root->setValue($n, $mockRoot); $this->assertSame('test: unit', $n->getTitle()); } public function testGetStatus() { $n = new TLVServiceNode(); $n->setProperties(['service'=>'unit', 'host'=>'test']); $mockRoot = new class { public function get($thing) { return false; } public function getFetched($type, $key) { $h = new stdClass; $s = new stdClass; $s->hard_state = 1; $s->is_handled = true; $s->in_downtime = true; $h->display_name = 'service'; $h->notifications_enabled = false; $h->state = $s; return $h; } }; $reflection = new ReflectionClass($n); $reflection_root = $reflection->getProperty('root'); $reflection_root->setAccessible(true); $reflection_root->setValue($n, $mockRoot); $this->assertSame('downtime handled', $n->getStatus()->getOverall()); } } icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/Tree/TLVStatusTest.php000066400000000000000000000034761473125420300315630ustar00rootroot00000000000000add('ok', 1); $this->assertSame('ok', $t->getOverall()); $t->add('missing', 1); $this->assertSame('ok', $t->getOverall()); $t->add('critical_handled', 1); $this->assertSame('critical handled', $t->getOverall()); $t->zero(); $t->add('total'); $this->assertSame(1, $t->get('total')); $this->assertSame(0, $t->get('missing')); } public function testGetOverallWithMissing() { $t = new TLVStatus(); $this->assertSame('missing', $t->getOverall()); } public function testGetterSetter() { $t = new TLVStatus(); $t->set('missing', 123); $this->assertSame(123, $t->get('missing')); $t->setMeta('hosts_total', 321); $this->assertSame(321, $t->getMeta('hosts_total')); $this->assertSame(null, $t->getMeta('services_total')); } public function testMerge() { $b = new TLVStatus(); $b->set('ok', 1); $b->set('missing', 2); $b->set('warning_handled', 3); $b->set('critical_unhandled', 4); $a = new TLVStatus(); $a->set('ok', 3); $a->set('unknown_unhandled', 2); $a->set('missing', 1); $a->merge($b); $this->assertSame(3, $a->get('missing')); $this->assertSame(4, $a->get('ok')); $this->assertSame(3, $a->get('warning_handled')); $this->assertSame(4, $a->get('critical_unhandled')); $this->assertSame(2, $a->get('unknown_unhandled')); $this->assertSame(null, $a->get('warning_unhandled')); } } icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/Tree/TLVTreeNodeTest.php000066400000000000000000000012121473125420300317670ustar00rootroot00000000000000setProperties(['name' => 'bar']); $this->assertSame('bar', $n->getTitle()); $this->assertSame(['name' => 'bar'], $n->getProperties()); $n->set('name', 'foo'); $this->assertSame('foo', $n->getTitle()); } public function testGetBreadCrumb() { $n = new TLVTreeNode(); $this->assertSame([$n], $n->getBreadCrumb()); } } icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/Util/000077500000000000000000000000001473125420300263455ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/Util/StrTest.php000066400000000000000000000033411473125420300304670ustar00rootroot00000000000000assertSame('', Str::limit(null)); $this->assertSame('', Str::limit('')); $this->assertSame('noop', Str::limit('noop')); } public function testLimitWithLongerStringAndSpecificLimit() { $this->assertSame( 'Lorem ipsu...', Str::limit('Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 10) ); $this->assertSame( '🍔🍔🍔🍔🍔...', Str::limit('🍔🍔🍔🍔🍔🍔🍔🍔', 10) ); } public function testLimitWithLongerStringAndSpecificEnd() { $this->assertSame( 'L (...)', Str::limit('Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 1, ' (...)') ); $this->assertSame( 'К (...)', Str::limit('Кто это читает, тот дурак', 1, ' (...)') ); $this->assertSame( 'К (🦔🦔🦔)', Str::limit('Кто это читает, тот дурак', 1, ' (🦔🦔🦔)') ); } public function testPrettyPrint() { $this->assertSame('Critical Unhandled', Str::prettyTitle('critical_unhandled')); $this->assertSame('Warning Handled', Str::prettyTitle('warning_handled')); $this->assertSame('Foo Bar', Str::prettyTitle('foo_bar')); $this->assertSame('XXX YYY', Str::prettyTitle('XXX_YYY')); $this->assertSame('', Str::prettyTitle('')); $this->assertSame('Ok', Str::prettyTitle('ok')); } } icingaweb2-module-toplevelview-1.0.0/test/php/library/Toplevelview/ViewConfigTest.php000066400000000000000000000065171473125420300310520ustar00rootroot00000000000000expectException(NotReadableError::class); $c = new ViewConfig('test/testdata'); $view = $c->loadByName('nosuchview'); } public function testViewConfigDelete() { $c = new ViewConfig('test/testdata'); $v = new View('deleteme', 'yml'); // Generate the file $c->storeToFile($v); $this->assertFileExists('test/testdata/views/deleteme.yml'); // Generate the backup dir $c->storeToFile($v); $this->assertDirectoryExists('test/testdata/views/deleteme'); // Delete the file $c->delete($v); $this->assertFalse(file_exists('test/testdata/views/deleteme.yml')); // Remove generated files afterwards array_map('unlink', array_filter((array) glob("test/testdata/views/deleteme/*"))); rmdir('test/testdata/views/deleteme/'); } public function testViewConfigLoadAll() { $c = new ViewConfig('test/testdata'); $views = $c->loadAll(); $this->assertArrayHasKey('example', $views); } public function testViewConfigWithNoError() { $c = new ViewConfig('test/testdata'); $view = $c->loadByName('example'); $this->assertStringContainsString('linux-servers', $view->getText()); $this->assertSame('5fc0ad55066b871d376eee60c84300d32ac7cb1d', $view->getTextChecksum()); $this->assertSame('yml', $view->getFormat()); $this->assertSame('example', $view->getName()); $this->assertSame(['name' => 'My View'], $view->getMetaData()); $clone = clone $view; $this->assertSame(null, $clone->getName()); $this->assertFalse($clone->hasBeenLoaded()); } public function testViewConfigWithTreeWithError() { $this->expectException(NotFoundError::class); $c = new ViewConfig('test/testdata'); $view = $c->loadByName('example'); $t = $view->getTree(); $t->getById('0-1-2'); } public function testViewConfigWithSession() { $c = new ViewConfig('test/testdata'); $view = $c->loadByName('example'); $view->setMeta('foo', 'bar'); $this->assertSame('bar', $view->getMeta('foo')); $this->assertSame(null, $view->getMeta('bar')); $this->assertSame(['foo' => 'bar'], $view->getMetaData()); $c->storeToSession($view); $view2 = $c->loadByName('example'); $this->assertSame($view->getTextChecksum(), $view2->getTextChecksum()); $this->assertFalse($view->hasBeenLoadedFromSession()); $this->assertTrue($view2->hasBeenLoadedFromSession()); } public function testViewConfigTree() { $c = new ViewConfig('test/testdata'); $view = $c->loadByName('example'); $t = $view->getTree(); $this->assertSame('5fc0ad55066b871d376eee60c84300d32ac7cb1d', $t->getViewChecksum()); $this->assertSame('example', $t->getViewName()); $t->setCacheLifetime(120); $this->assertSame(120, $t->getCacheLifetime()); } } icingaweb2-module-toplevelview-1.0.0/test/testdata/000077500000000000000000000000001473125420300223215ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/test/testdata/views/000077500000000000000000000000001473125420300234565ustar00rootroot00000000000000icingaweb2-module-toplevelview-1.0.0/test/testdata/views/example.yml000066400000000000000000000003771473125420300256430ustar00rootroot00000000000000name: My View children: - name: Section 1 children: - name: Tile 1 children: - host: localhost - host: localhost service: disk - host: anotherhost service: ssh - name: Tile 2 hostgroup: linux-servers - name: Tile 3