pax_global_header00006660000000000000000000000064152237530150014515gustar00rootroot0000000000000052 comment=ca125f2df3ca3571e4ba8b6e771ca6be47891121 flask-peewee-4.0.1/000077500000000000000000000000001522375301500140675ustar00rootroot00000000000000flask-peewee-4.0.1/.github/000077500000000000000000000000001522375301500154275ustar00rootroot00000000000000flask-peewee-4.0.1/.github/workflows/000077500000000000000000000000001522375301500174645ustar00rootroot00000000000000flask-peewee-4.0.1/.github/workflows/tests.yaml000066400000000000000000000007601522375301500215150ustar00rootroot00000000000000name: Tests on: [push] jobs: tests: name: ${{ matrix.python-version }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: python-version: [3.8, "3.10", "3.12", "3.14"] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: pip deps run: pip install peewee flask wtforms wtf-peewee - name: runtests run: python runtests.py flask-peewee-4.0.1/.github/workflows/wheels.yaml000066400000000000000000000016651522375301500216470ustar00rootroot00000000000000name: Build wheels on: push: tags: - "[0-9]+.[0-9]+.[0-9]+" - "[0-9]+.[0-9]+.[0-9]+-**" jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: Install build tools run: | python -m pip install -U pip pip install setuptools build - name: Build sdist and wheel run: | python -m build . - uses: actions/upload-artifact@v4 with: name: package path: dist/flask_peewee* publish: needs: [build] runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v4 with: name: package path: dist merge-multiple: true - uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} flask-peewee-4.0.1/.readthedocs.yaml000066400000000000000000000001471522375301500173200ustar00rootroot00000000000000version: 2 build: os: ubuntu-22.04 tools: python: "3.11" sphinx: configuration: docs/conf.py flask-peewee-4.0.1/LICENSE000066400000000000000000000020421522375301500150720ustar00rootroot00000000000000Copyright (c) 2011 Charles Leifer 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. flask-peewee-4.0.1/MANIFEST.in000066400000000000000000000003011522375301500156170ustar00rootroot00000000000000include LICENSE include README.rst recursive-include docs * recursive-include example * recursive-include flask_peewee * prune docs/_build recursive-exclude * __pycache__/ global-exclude *.pyc flask-peewee-4.0.1/README.rst000066400000000000000000000041341522375301500155600ustar00rootroot00000000000000flask-peewee ============ provides a layer of integration between the `flask `_ web framework and the `peewee orm `_. batteries included: * admin interface * authentication * rest api requirements: * `flask `_ * `peewee `_ * `wtforms `_ * `wtf-peewee `_ * python 3.8 or greater check out the `documentation `_. admin interface --------------- influenced heavily by the `django `_ admin, provides easy create/edit/delete functionality for your project's models. .. image:: https://media.charlesleifer.com/blog/photos/im-1783454777-579.png or you can use one of the themes. Here is the *crux* theme: .. image:: https://media.charlesleifer.com/blog/photos/fp-crux-full.png rest api -------- provides a RESTful interface for your project's models. :: curl localhost:5000/api/user/ { "meta": { "model": "user", "next": "", "page": 1, "previous": "" }, "objects": [ { "username": "admin", "admin": true, "email": "", "join_date": "2025-09-16 18:34:49", "active": true, "id": 1 }, { "username": "coleifer", "admin": false, "email": "coleifer@gmail.com", "join_date": "2025-09-16 18:35:56", "active": true, "id": 2 } ] } installing ---------- :: pip install flask-peewee example app ----------- the project ships with an example app, which is a silly twitter clone. to start the example app, ``cd`` into the "example" directory and execute the ``run_example.py`` script:: cd example/ python run_example.py if you would like to test out the admin area, log in as "admin/admin" and navigate to: http://127.0.0.1:5000/admin/ you can check out the REST api at the following url: http://127.0.0.1:5000/api/message/ flask-peewee-4.0.1/docs/000077500000000000000000000000001522375301500150175ustar00rootroot00000000000000flask-peewee-4.0.1/docs/Makefile000066400000000000000000000110061522375301500164550ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/flask-peewee.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/flask-peewee.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/flask-peewee" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/flask-peewee" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." flask-peewee-4.0.1/docs/_static/000077500000000000000000000000001522375301500164455ustar00rootroot00000000000000flask-peewee-4.0.1/docs/_static/peewee.jpg000066400000000000000000000271501522375301500204260ustar00rootroot00000000000000JFIF``C    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;(" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?7|$g>•O#Ҙsϣ r3(X@r{t4I91=47 uCq nH"j$dpW< i c~P}Ȥ"B/_ {wۀ*K|V%Fp;j;ɭ"6F1 9!y'<)NGA1r0F,sPs_4s Q9,Uy89iqOj@!$1J Lyk߅rw5mclbMyj0rSQn.͹8S'4͓p~5fY$٦y-Ý?Z9v_ ݜxcZqvǨ#BH8j ycB}T[4YUw_ُݒ,bhA w^4:]>HuxgdHFe5(U}`qmpRK҇Q{{o87$γr 4`/4)iv cp@a^ ¶sӌzJN*ᖛqspW FXcjD zPe#JRYO9#SR>##+;9qnە@, ȗ|<8Tɞц +v_G>h _$R^i,%+ɇ4ўq{"&]{E)XT1*KՉR)wڼ°$d쬍'v:indu/ TXXuޜpO3*&F8 XqW'MhG('BƭFli=:3ˍpv[163Y1S2}*lAbr>\'rLFg*裌W@3=M0qr69R`l>9k(${Q`:oe &㯽W{s"q?Lm? R=pæ5[Hx#!ޠm ~au1bH##y>.TpJvOck;K 5/'}yp~$T7v~!aK>YHOz ڻ(-C :$2|g5TI$9.0ki#=OZp$ Bvqg¬J+Wvy{C&;rqdctk< rncJw[Iwl~^{MGs *?j&lCՒQX>?94|jpLӥRXЯcc=jŽȸS-M.pR\֚"ŏ}Pҫ&<=S2ͷ,p=4aʰ cޱ.teHɁ?εXlHQ#2S`bHHP۱$#,phǥ!anzzT^ ԃ85o|=y$sR'gɬ?k i 6ZP,Ey{%bQW)")k˹''nƱgzI\NJԳ38Tn˔1jK)W޹S$sv%m(=֙ \Sy C1ژ;Tq؊x gE("$q;wi(Ӗw݀WOs=xҋ BG׶N*bA?( x'ShUk%9m?,6gqRj}E7Me`B썱݄/x+ė6icPY\nӭy3C3,l q^g RY|5um\IE1XuֺiIY)7{eZ:Mܬ(2X T⻟ѯe_ڤxCSF5kp"<`1sfD /^*)28ҸԬVqmipσqyq3s^} # 8l5?a#}I$~eZ&&*/8)~ZxF;;$x&bv7.٭ٰ%Cչk~<7 :{c~ػ۩jcڪY]nCSXw[C2r|x?cJo ܌s2+/yr m >o\ kK_B- *@0qڲ!re'麮Gxߕesl]pje?4ָDPĎ:\5C ozk]QֵVYȽ@$?k֭HȎ5;wڵeu2m%$**hl鍬uFr>8<ӌm8Ssj7$p1Tlvy$zvC? ?ۮ*̪ޘ\ |1ZpW= NZ\d[v6~0Cڝ< n02քHs>01ڞFFI֚F1"g;RO=:p7};q~ B6.\L=lғ$ C%so$d;*&GW?gxfmIaY&kG:N`P)TZi Eӎiˡ/˅Gݮ,㶈e5[mcUA$bmr(gh* [s*'Fjݔݞ+TEU\Os&s;P*}^iZqiGn>Cz:> )jǟŸp:Ktsڱ2<,VĺPy{V(N1ߨKRTaT]4nd~I?J1 GSZ:.itڜeaHߊI_a]s36)Y< se,? -uZH_ ƹߋb.׉'${NA+KóO'KٹP%82ȹ,[27s9y^J;[^kP7AXε25MaJqێ+&G,ܓK#,yU?+ ZBW__~lhLnZ9n)RͬmnVZ! \zQX9;O=ym 81|H'gh* dz,Z}= `|Vi#/#5}؞k1KroJjʻHۃtSMŇbyІ@ydd`S)c;6:d_Ii4{?G\ǴI>O-_GbNGcG'$Nua)>칣09A^=T+=vFz{zvcp=3X!@zԭΣQc9c*R6S(eG@^3vmፖ6=9Qn!Қ|<e?#կQHj ~sWJ9C|{S(sIGzոy@w[1tc%pAnKR]ە;e7q݁=4o!?(֞7Gi2;VP: ep#Z(ܒ8L$lMJn}dJs̍NhCƒ+!${Vkg<GPN=(N”y&3u[6&F#Mh=3XnY]cirCN8{w x“*&Eݸ${U`x֖f,AVT rLG(Y~XڔyE"NP)qXbb:oDiV'?\J|d @JgX)kq8${W%s`VvIs^ կ&t |,If(~Sq'$9մ6NK#,{K}vIzS<@=xHh\\C~UAsgjGv-0=ZosqKA9Ur9Unn+m pNF+H129O89 iץ[.,r}R6G&N1ʑ`G'*Ұ qКtSֹLK6f T>"BW+[=Е0O]EIpdl'ZۘO~+ȣ+G)ڠQKk$"@ S85= n#'r;3Cڝ 8rE™ 8!H8Mi.)$5=ADZ5Aw+n#l|ǞOQFpA-$5>jpnI8$zաڥ֨Xvb1]TMi{>fc!mմ2K46$}+ p8HAfP*(l`+- EKI=*94_|-t&EG Nj̯ځX܎Ɲt%߷(X^ b'cs]%Gu+P]]Ɠ;Om#g'5oͬo&1ymk^}eb`=V..lH0)Zfn[͸E G0e/<3gqA4hԅy$'%+wO.fA; $\FJM+!I'oaaەS!՝WP G.zUky6qVՙ`(H#>5夐NW?x5=tے=G ha@tMTSҥ@H=h` gZ2ŲҞ |0 m$`мlGqY m 9+e9RRS.r` <q6nۗT4kj$% 9#T/bflȷmI[ϋ?:ɸ8&gKҴǟ->7ID*˕e=sJ.,>hӡw|u=+&@SC[9Y .yϭ ’ԩ [I|jt[j)'*zsֹ-O0q+Ga֪NǨޤZ.>lf[hFHZܵVaz'WcG/^lLX|?RYus8*WqfJ/d˷AZ(桹Jsֺmn.m#%qt8 "@T͜ԣ^6[h+-BۓWYw."1HÑJj̺R#94sPC)ç#'gsPp?&̉ьd`Ҟ>n }(=~x$PQ]lE@&ymtCܑ1O~NAMGccE" r*ͱcV-y^08䊟h+ǩ",5z++)<]n`|=jxfSEmVʸjo|1's61[;oM8+1=oWh k#y>f5=1K]X}4Eas4jPS /sfoۆVk&fێFLJgw:DP6'kG4%ʐ# 0ݩq]K m]n;݇*dݘP1 _SEC<(ܣ' [ZΉv3 >f|_ұMk 4SRF:baޕPd* Š3@@+\k| ZAk, ǭ`G,L:`22zjv!#!9#t-dj{B8\~SVU.RRvPI}jxÇTnCKCZ-sQx>PWEH\ZΑE$d]jAa)?,dYݷLvj:=MA9D*Fx5%60UC `pw|~5QcH03`F*t2v%5hy2\Jf,aӓ]f(P!~|ϭr:/dـ$ ۬IkQ!_L66uLŤ]wړU MڡpA ;/}wM Hߵ ,xU۷ y<'qq 6,W5k_I#>G}A#1hh[C7$'"[m5A*E929TcWӅߕm)6~mpgKִEpp©M\Cƈ>h9#1F TKi+,`K!zb|Y QbNE%`zWV0rЏJo_۴Ypq94qyxlQ]e2U47 a|ϸ,3Zv[UV|Kem0VZO8짊"BCGklkՌ O~ֻT-jGk& 3iwJ$ q+EVivv(ٵQ)v y:Eq^-#I6=ܒh!dUXnJ_i{Ң9t-EΟ lu"ӭsz]ȵ>plgškoݏ=%`SKɽy= u3${,L*]0;>x R)Ppx4j_Fz˓u-}#|o#:j{븏~2o)f &G+IG .X!b !\mbRO"Zv3DoXzܿA!9=k|Ł$q\ Lٟ@OZ:DB#y0OJ ʪyҡ#n=GR UZ% odnhr@'}64[OI |n#~T5%PAcϭ^h#ݸeF)ZՐҥh;2"HqO,Hzm_hPW9#'>#I ѡIz1'ޤhYB<'jƮ@1 3*D`I&F3 J dhFyJ( Vt{of5Sߎ#fSc6z|(2/ǜSersp1-ϚGXj`{EsKsѦflask-peewee-4.0.1/docs/_themes/000077500000000000000000000000001522375301500164435ustar00rootroot00000000000000flask-peewee-4.0.1/docs/_themes/flask/000077500000000000000000000000001522375301500175435ustar00rootroot00000000000000flask-peewee-4.0.1/docs/_themes/flask/layout.html000066400000000000000000000013561522375301500217530ustar00rootroot00000000000000{%- extends "basic/layout.html" %} {%- block extrahead %} {{ super() }} {% if theme_touch_icon %} {% endif %} {% endblock %} {%- block relbar2 %}{% endblock %} {% block header %} {{ super() }} {% if pagename == 'index' %}
{% endif %} {% endblock %} {%- block footer %} {% if pagename == 'index' %}
{% endif %} {%- endblock %} flask-peewee-4.0.1/docs/_themes/flask/relations.html000066400000000000000000000011161522375301500224300ustar00rootroot00000000000000

Related Topics

flask-peewee-4.0.1/docs/_themes/flask/static/000077500000000000000000000000001522375301500210325ustar00rootroot00000000000000flask-peewee-4.0.1/docs/_themes/flask/static/flasky.css_t000066400000000000000000000144441522375301500233670ustar00rootroot00000000000000/* * flasky.css_t * ~~~~~~~~~~~~ * * :copyright: Copyright 2010 by Armin Ronacher. * :license: Flask Design License, see LICENSE for details. */ {% set page_width = '940px' %} {% set sidebar_width = '220px' %} @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: 'Georgia', serif; font-size: 17px; background-color: white; color: #000; margin: 0; padding: 0; } div.document { width: {{ page_width }}; margin: 30px auto 0 auto; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 {{ sidebar_width }}; } div.sphinxsidebar { width: {{ sidebar_width }}; } hr { border: 1px solid #B1B4B6; } div.body { background-color: #ffffff; color: #3E4349; padding: 0 30px 0 30px; } img.floatingflask { padding: 0 0 10px 10px; float: right; } div.footer { width: {{ page_width }}; margin: 20px auto 30px auto; font-size: 14px; color: #888; text-align: right; } div.footer a { color: #888; } div.related { display: none; } div.sphinxsidebar a { color: #444; text-decoration: none; border-bottom: 1px dotted #999; } div.sphinxsidebar a:hover { border-bottom: 1px solid #999; } div.sphinxsidebar { font-size: 14px; line-height: 1.5; } div.sphinxsidebarwrapper { padding: 18px 10px; } div.sphinxsidebarwrapper p.logo { padding: 0 0 20px 0; margin: 0; text-align: center; } div.sphinxsidebar h3, div.sphinxsidebar h4 { font-family: 'Garamond', 'Georgia', serif; color: #444; font-size: 24px; font-weight: normal; margin: 0 0 5px 0; padding: 0; } div.sphinxsidebar h4 { font-size: 20px; } div.sphinxsidebar h3 a { color: #444; } div.sphinxsidebar p.logo a, div.sphinxsidebar h3 a, div.sphinxsidebar p.logo a:hover, div.sphinxsidebar h3 a:hover { border: none; } div.sphinxsidebar p { color: #555; margin: 10px 0; } div.sphinxsidebar ul { margin: 10px 0; padding: 0; color: #000; } div.sphinxsidebar input { border: 1px solid #ccc; font-family: 'Georgia', serif; font-size: 1em; } /* -- body styles ----------------------------------------------------------- */ a { color: #004B6B; text-decoration: underline; } a:hover { color: #6D4100; text-decoration: underline; } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; margin: 30px 0px 10px 0px; padding: 0; } {% if theme_index_logo %} div.indexwrapper h1 { text-indent: -999999px; background: url({{ theme_index_logo }}) no-repeat center center; height: {{ theme_index_logo_height }}; } {% endif %} div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } div.body h2 { font-size: 180%; } div.body h3 { font-size: 150%; } div.body h4 { font-size: 130%; } div.body h5 { font-size: 100%; } div.body h6 { font-size: 100%; } a.headerlink { color: #ddd; padding: 0 4px; text-decoration: none; } a.headerlink:hover { color: #444; background: #eaeaea; } div.body p, div.body dd, div.body li { line-height: 1.4em; } div.admonition { background: #fafafa; margin: 20px -30px; padding: 10px 30px; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; } div.admonition tt.xref, div.admonition a tt { border-bottom: 1px solid #fafafa; } dd div.admonition { margin-left: -60px; padding-left: 60px; } div.admonition p.admonition-title { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; font-size: 24px; margin: 0 0 10px 0; padding: 0; line-height: 1; } div.admonition p.last { margin-bottom: 0; } div.highlight { background-color: white; } dt:target, .highlight { background: #FAF3E8; } div.note { background-color: #eee; border: 1px solid #ccc; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eee; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre, tt { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 0.9em; } img.screenshot { } tt.descname, tt.descclassname { font-size: 0.95em; } tt.descname { padding-right: 0.08em; } img.screenshot { -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils { border: 1px solid #888; -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils td, table.docutils th { border: 1px solid #888; padding: 0.25em 0.7em; } table.field-list, table.footnote { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } table.footnote { margin: 15px 0; width: 100%; border: 1px solid #eee; background: #fdfdfd; font-size: 0.9em; } table.footnote + table.footnote { margin-top: -15px; border-top: none; } table.field-list th { padding: 0 0.8em 0 0; } table.field-list td { padding: 0; } table.footnote td.label { width: 0px; padding: 0.3em 0 0.3em 0.5em; } table.footnote td { padding: 0.3em 0.5em; } dl { margin: 0; padding: 0; } dl dd { margin-left: 30px; } blockquote { margin: 0 0 0 30px; padding: 0; } ul, ol { margin: 10px 0 10px 30px; padding: 0; } pre { background: #eee; padding: 7px 30px; margin: 15px -30px; line-height: 1.3em; } dl pre, blockquote pre, li pre { margin-left: -60px; padding-left: 60px; } dl dl pre { margin-left: -90px; padding-left: 90px; } tt { background-color: #ecf0f3; color: #222; /* padding: 1px 2px; */ } tt.xref, a tt { background-color: #FBFBFB; border-bottom: 1px solid white; } a.reference { text-decoration: none; border-bottom: 1px dotted #004B6B; } a.reference:hover { border-bottom: 1px solid #6D4100; } a.footnote-reference { text-decoration: none; font-size: 0.7em; vertical-align: top; border-bottom: 1px dotted #004B6B; } a.footnote-reference:hover { border-bottom: 1px solid #6D4100; } a:hover tt { background: #EEE; } flask-peewee-4.0.1/docs/_themes/flask/static/small_flask.css000066400000000000000000000017201522375301500240340ustar00rootroot00000000000000/* * small_flask.css_t * ~~~~~~~~~~~~~~~~~ * * :copyright: Copyright 2010 by Armin Ronacher. * :license: Flask Design License, see LICENSE for details. */ body { margin: 0; padding: 20px 30px; } div.documentwrapper { float: none; background: white; } div.sphinxsidebar { display: block; float: none; width: 102.5%; margin: 50px -30px -20px -30px; padding: 10px 20px; background: #333; color: white; } div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, div.sphinxsidebar h3 a { color: white; } div.sphinxsidebar a { color: #aaa; } div.sphinxsidebar p.logo { display: none; } div.document { width: 100%; margin: 0; } div.related { display: block; margin: 0; padding: 10px 0 20px 0; } div.related ul, div.related ul li { margin: 0; padding: 0; } div.footer { display: none; } div.bodywrapper { margin: 0; } div.body { min-height: 0; padding: 0; } flask-peewee-4.0.1/docs/_themes/flask/theme.conf000066400000000000000000000002441522375301500215140ustar00rootroot00000000000000[theme] inherit = basic stylesheet = flasky.css pygments_style = flask_theme_support.FlaskyStyle [options] index_logo = '' index_logo_height = 120px touch_icon = flask-peewee-4.0.1/docs/admin.rst000066400000000000000000000374441522375301500166550ustar00rootroot00000000000000.. _admin-interface: Admin Interface =============== Many web applications ship with an "admin area", where priveleged users can view and modify content. By introspecting your application's models, flask-peewee can provide you with straightforward, easily-extensible forms for managing your application content. Here's a screen-shot of the admin dashboard: .. image:: fp-admin.png You can also try out a custom theme. Here is the *crux* theme: .. image:: fp-crux-full.png Getting started --------------- To get started with the admin, there are just a couple steps: 1. Instantiate an :py:class:`Auth` backend for your project -- this component is responsible for providing the security for the admin area .. code-block:: python from flask import Flask from flask_peewee.auth import Auth from flask_peewee.db import Database app = Flask(__name__) db = Database(app) # needed for authentication auth = Auth(app, db) 2. Instantiate an :py:class:`Admin` object .. code-block:: python # continued from above... from flask_peewee.admin import Admin admin = Admin(app, auth) 3. Register any :py:class:`ModelAdmin` or :py:class:`AdminPanel` objects you would like to expose via the admin .. code-block:: python # continuing... assuming "Blog" and "Entry" models admin.register(Blog) # register "Blog" with vanilla ModelAdmin admin.register(Entry, EntryAdmin) # register "Entry" with a custom ModelAdmin subclass # assume we have an "AdminPanel" called "NotePanel" admin.register_panel('Notes', NotePanel) 4. Call :py:meth:`Admin.setup()`, which registers the admin blueprint and configures the urls .. code-block:: python # after all models and panels are registered, configure the urls admin.setup() .. note:: For a complete example, check the `example app `_ which ships with the project. Customizing how models are displayed ------------------------------------ We'll use the "Message" model taken from the `example app `_, which looks like this: .. code-block:: python class Message(db.Model): user = ForeignKeyField(User) content = TextField() pub_date = DateTimeField(default=datetime.datetime.now) def __str__(self): return '%s: %s' % (self.user, self.content) If we were to simply register this model with the admin, it would look something like this: .. code-block:: python admin = Admin(app, auth) admin.register(Message) admin.setup() .. image:: fp-message-admin-plain.png A quick way to improve the appearance of this view is to specify which columns to display. To start customizing how the ``Message`` model is displayed in the admin, we'll subclass :py:class:`ModelAdmin`. .. code-block:: python from flask_peewee.admin import ModelAdmin class MessageAdmin(ModelAdmin): columns = ('user', 'content', 'pub_date',) foreign_key_lookups = {'user': 'username'} filter_fields = ('user', 'content', 'pub_date', 'user__username') search_fields = ('content', 'user__username') admin.register(Message, MessageAdmin) admin.setup() Now the admin shows all the columns and they can be clicked to sort the data. Filtering is available, as is search: .. image:: fp-message-admin.png Searching ^^^^^^^^^ Set ``search_fields`` to add a quick-search box above the list. It runs a case-insensitive substring match over char/text fields and supports ``__`` traversal into related models -- so ``('content', 'user__username')`` searches both the message body and the author's username, joining ``User`` automatically: .. code-block:: python class MessageAdmin(ModelAdmin): columns = ('user', 'content', 'pub_date',) search_fields = ('content', 'user__username') Leaving ``search_fields`` empty (the default) hides the search box entirely. Filtering ^^^^^^^^^ The list and export views expose per-field filters (equals, less-than, contains, etc., chosen by field type). By default every field is filterable; two attributes narrow that: * ``filter_fields`` -- a whitelist of the only fields that may be filtered * ``filter_exclude`` -- a blacklist of fields to hide from filtering Both accept ``__`` notation for related fields, so ``filter_exclude = ('user__password',)`` keeps a sensitive related column out of the filter UI entirely. Restricting the queryset ^^^^^^^^^^^^^^^^^^^^^^^^^ Suppose privacy is a big concern, and under no circumstances should a user be able to see another user's messages -- even in the admin. This can be done by overriding the :py:meth:`~ModelAdmin.get_query` method: .. code-block:: python def get_query(self): return self.model.select().where(self.model.user == g.user) Now a user will only be able to see and edit their own messages. Overriding Admin Templates ^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the :py:meth:`ModelAdmin.get_template_overrides` method to override templates for an individual ``Model``: .. code-block:: python class MessageAdmin(ModelAdmin): # ... def get_template_overrides(self): # override the edit template with a custom one return {'edit': 'messages/admin/edit.html'} admin.register(Message, MessageAdmin) This instructs the admin to use a custom template for the edit page in the Message admin. That template is stored in the application's templates. It might look something like this: .. code-block:: jinja {% extends "admin/models/edit.html" %} {# override the default edit template #} {# override any blocks here #} There are five templates that can be overridden: * index * add * edit * delete * export Nicer display for Foreign Key fields ------------------------------------ By default a foreign key renders as a ```` is automatically capped at the first 20 rows (plus whichever row is currently selected), so the page never balloons -- but only those 20 rows are reachable. * In **model forms** (add/edit), the ```` with a paginated, type-ahead search backed by the model admin's ``ajax_list`` endpoint (matching `` LIKE '%query%'``, a page at a time), so any row is reachable no matter how large the table: .. code-block:: python class MessageAdmin(ModelAdmin): columns = ('user', 'content', 'pub_date',) foreign_key_lookups = {'user': 'username'} The widget differs between the two contexts: Filters ^^^^^^^ Without ``foreign_key_lookups`` the ``user`` filter is a ```` gains an inline type-ahead search that repopulates its options from ``ajax_list`` as you type, so any user can be selected. Model forms ^^^^^^^^^^^ Without ``foreign_key_lookups`` an add or edit form renders every related row in a single ``

{% endblock %} A panel can provide as many urls and views as you like. These views will all be protected by the same authentication as other parts of the admin area. Handling File Uploads --------------------- Flask and wtforms both provide support for handling file uploads (on the server and generating form fields). Peewee, however, does not have a "file field" -- generally I store a path to a file on disk and thus use a ``CharField`` for the storage. Here's a very simple example of a "photo" model and a ``ModelAdmin`` that enables file uploads. .. code-block:: python # models.py import datetime import os from markupsafe import Markup from peewee import * from werkzeug.utils import secure_filename from app import app, db class Photo(db.Model): image = CharField() def __str__(self): return self.image def save_image(self, file_obj): self.image = secure_filename(file_obj.filename) full_path = os.path.join(app.config['MEDIA_ROOT'], self.image) file_obj.save(full_path) self.save() def url(self): return os.path.join(app.config['MEDIA_URL'], self.image) def thumb(self): return Markup('' % self.url()) .. code-block:: python # admin.py from flask import request from flask_peewee.admin import Admin, ModelAdmin from wtforms.fields import FileField, HiddenField from wtforms.form import Form from app import app, db from auth import auth from models import Photo admin = Admin(app, auth) class PhotoAdmin(ModelAdmin): columns = ['image', 'thumb'] def get_form(self, adding=False): class PhotoForm(Form): image = HiddenField() image_file = FileField('Image file') return PhotoForm def save_model(self, instance, form, adding=False): instance = super(PhotoAdmin, self).save_model(instance, form, adding) if 'image_file' in request.files: file = request.files['image_file'] instance.save_image(file) return instance admin.register(Photo, PhotoAdmin) flask-peewee-4.0.1/docs/api.rst000066400000000000000000001216361522375301500163330ustar00rootroot00000000000000.. _api: API === Admin ----- .. py:class:: Admin(app, auth[, prefix[, name[, branding[, theme]]]]) Class used to expose an admin area at a certain url in your application. The Admin object implements a flask blueprint and acts as the central registry for models and panels you wish to expose in the admin. The Admin object coordinates the registration of models and panels and provides a method for ensuring a user has permission to access the admin area. The Admin object requires an :py:class:`Auth` instance when being instantiated, which in turn requires a Flask app and a py:class:`Database` wrapper. Here is an example of how you might instantiate an Admin object: .. code-block:: python from flask import Flask from flask_peewee.admin import Admin from flask_peewee.auth import Auth from flask_peewee.db import Database app = Flask(__name__) db = Database(app) # needed for authentication auth = Auth(app, db) # instantiate the Admin object for our project admin = Admin(app, auth) :param app: flask application to bind admin to :param auth: :py:class:`Auth` instance which will provide authentication :param prefix: url to bind admin to, defaults to ``/admin`` :param name: name of the admin blueprint, defaults to ``admin`` :param branding: display name shown in the navbar and page titles :param theme: name of an admin theme stylesheet; ``''`` loads ``static/css/admin-.css`` on top of the base ``admin.css``, e.g. ``theme='crisp'``. Defaults to ``None``, which serves the base stylesheet only. For full control (e.g. a stylesheet hosted outside the admin's static folder), override the ``theme_css`` block in ``admin/base.html`` instead. .. py:method:: register(model[, admin_class=ModelAdmin]) Register a model to expose in the admin area. A :py:class:`ModelAdmin` subclass can be provided along with the model, allowing for customization of the model's display and behavior. Example usage: .. code-block:: python # will use the default ModelAdmin subclass to display model admin.register(BlogModel) class EntryAdmin(ModelAdmin): columns = ('title', 'blog', 'pub_date',) admin.register(EntryModel, EntryAdmin) .. warning:: All models must be registered before calling :py:meth:`~Admin.setup` :param model: peewee model to expose via the admin :param admin_class: :py:class:`ModelAdmin` or subclass to use with given model .. py:method:: register_panel(title, panel) Register a :py:class:`AdminPanel` subclass for display in the admin dashboard. Example usage: .. code-block:: python class HelloWorldPanel(AdminPanel): template_name = 'admin/panels/hello.html' def get_context(self): return { 'message': 'Hello world', } admin.register_panel('Hello world', HelloWorldPanel) .. warning:: All panels must be registered before calling :py:meth:`~Admin.setup` :param title: identifier for panel, example might be "Site Stats" :param panel: subclass of :py:class:`AdminPanel` to display .. py:method:: setup() Configures urls for models and panels, then registers blueprint with the Flask application. Use this method when you have finished registering all the models and panels with the admin object, but before starting the WSGI application. For a sample implementation, check out ``main.py`` in the `example application `_ supplied with flask-peewee. .. code-block:: python # register all models, etc admin.register(...) # finish up initialization of the admin object admin.setup() if __name__ == '__main__': # run the WSGI application app.run() .. note:: call ``setup()`` **after** registering your models and panels .. py:method:: check_user_permission(user) Check whether the given user has permission to access to the admin area. The default implementation simply checks whether the ``admin`` field is checked, but you can provide your own logic. This method simply controls access to the admin area as a whole. In the event the user is **not** permitted to access the admin (this function returns ``False``), they will receive a HTTP Response Forbidden (403). Default implementation: .. code-block:: python def check_user_permission(self, user): return user.admin :param user: the currently logged-in user, exposed by the :py:class:`Auth` instance :rtype: Boolean .. py:method:: auth_required(func) Decorator that ensures the requesting user has permission. The implementation first checks whether the requesting user is logged in, and if not redirects to the login view. If the user *is* logged in, it calls :py:meth:`~Admin.check_user_permission`. Only if this call returns ``True`` is the actual view function called. .. py:method:: get_urls() Get a tuple of 2-tuples mapping urls to view functions that will be exposed by the admin. The default implementation looks like this: .. code-block:: python def get_urls(self): return ( ('/', self.auth_required(self.index)), ) This method provides an extension point for providing any additional "global" urls you would like to expose. .. note:: Remember to decorate any additional urls you might add with :py:meth:`~Admin.auth_required` to ensure they are not accessible by unauthenticated users. Exposing Models with the ModelAdmin ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. py:class:: ModelAdmin Class that determines how a peewee ``Model`` is exposed in the admin area. Provides a way of encapsulating model-specific configuration and behaviors. Provided when registering a model with the :py:class:`Admin` instance (see :py:meth:`Admin.register`). .. py:attribute:: columns List or tuple of columns should be displayed in the list index. By default if no columns are specified the ``Model``'s ``__str__()`` will be used. .. note:: Valid values for columns are the following: * field on a model * attribute on a model instance * callable on a model instance (called with no parameters) If a column is a model field, it will be sortable. .. code-block:: python class EntryAdmin(ModelAdmin): columns = ['title', 'pub_date', 'blog'] .. py:attribute:: filter_exclude Exclude certain fields from being exposed as filters. Related fields can be excluded using "__" notation, e.g. ``user__password`` .. py:attribute:: filter_fields Only allow filtering on the given fields .. py:attribute:: exclude A list of field names to exclude from the "add" and "edit" forms .. py:attribute:: fields Only display the given fields on the "add" and "edit" form .. py:attribute:: paginate_by = 20 Number of records to display on index pages .. py:attribute:: filter_paginate_by = 15 Default pagination when filtering in a modal dialog .. py:attribute:: delete_collect_objects = True Collect and display a list of "dependencies" when deleting .. py:attribute:: delete_recursive = True Delete "dependencies" recursively .. py:method:: get_query() Determines the list of objects that will be exposed in the admin. By default this will be all objects, but you can use this method to further restrict the query. This method is called within the context of a request, so you can access the ``Flask.request`` object or use the :py:class:`Auth` instance to determine the currently-logged-in user. Here's an example showing how the query is restricted based on whether the given user is a "super user" or not: .. code-block:: python class UserAdmin(ModelAdmin): def get_query(): # ask the auth system for the currently logged-in user current_user = self.auth.get_logged_in_user() # if they are not a superuser, only show them their own # account in the admin if not current_user.is_superuser: return User.select().where(User.id==current_user.id) # otherwise, show them all users return User.select() :rtype: A ``SelectQuery`` that represents the list of objects to expose .. py:method:: get_object(pk) This method retrieves the object matching the given primary key. The implementation uses :py:meth:`~ModelAdmin.get_query` to retrieve the base list of objects, then queries within that for the given primary key. :rtype: The model instance with the given pk, raising a ``DoesNotExist`` in the event the model instance does not exist. .. py:method:: get_form([adding=False]) Provides a useful extension point in the event you want to define custom fields or custom validation behavior. :param boolean adding: indicates whether adding a new instance or editing existing :rtype: A `wtf-peewee `_ Form subclass that will be used when adding or editing model instances in the admin. .. py:method:: get_add_form() Allows you to specify a different form when adding new instances versus editing existing instances. The default implementation simply calls :py:meth:`~ModelAdmin.get_form`. .. py:method:: get_edit_form() Allows you to specify a different form when editing existing instances versus adding new instances. The default implementation simply calls :py:meth:`~ModelAdmin.get_form`. .. py:method:: get_filter_form() Provide a special form for use when filtering the list of objects in the model admin's index/export views. This form is slightly different in that it is tailored for use when filtering the list of models. :rtype: A special Form instance (:py:class:`FilterForm`) that will be used when filtering the list of objects in the index view. .. py:method:: save_model(instance, form, adding=False) Method responsible for persisting changes to the database. Called by both the add and the edit views. Here is an example from the default ``auth.User`` :py:class:`ModelAdmin`, in which the password is displayed as a sha1, but if the user is adding or edits the existing password, it re-hashes: .. code-block:: python def save_model(self, instance, form, adding=False): orig_password = instance.password user = super(UserAdmin, self).save_model(instance, form, adding) if orig_password != form.password.data: user.set_password(form.password.data) user.save() return user :param instance: an unsaved model instance :param form: a validated form instance :param adding: boolean to indicate whether we are adding a new instance or saving an existing .. py:method:: get_template_overrides() Hook for specifying template overrides. Should return a dictionary containing view names as keys and template names as values. Possible choices for keys are: * index * add * edit * delete * export .. code-block:: python class UserModelAdmin(ModelAdmin): def get_template_overrides(self): return {'index': 'users/admin/index_override.html'} .. py:method:: get_urls() Useful as a hook for extending :py:class:`ModelAdmin` functionality with additional urls. .. note:: It is not necessary to decorate the views specified by this method since the :py:class:`Admin` instance will handle this during registration and setup. :rtype: tuple of 2-tuples consisting of a mapping between url and view .. py:method:: get_url_name(name) Since urls are namespaced, this function provides an easy way to get full urls to views provided by this ModelAdmin .. py:method:: process_filters(query) Applies any filters specified by the user to the given query, returning metadata about the filters. Returns a 4-tuple containing: * special ``Form`` instance containing fields for filtering * filtered query * a list containing the currently selected filters * a tree-structure containing the fields available for filtering (:py:class:`FieldTreeNode`) :rtype: A tuple as described above Extending admin functionality using AdminPanel ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. py:class:: AdminPanel Class that provides a simple interface for providing arbitrary extensions to the admin. These are displayed as "panels" on the admin dashboard with a customizable template. They may additionally, however, define any views and urls. These views will automatically be protected by the same authentication used throughout the admin area. Some example use-cases for AdminPanels might be: * Display some at-a-glance functionality in the dashboard, like stats on new user signups. * Provide a set of views that should only be visible to site administrators, for example a mailing-list app. * Control global site settings, turn on and off features, etc. .. py:attribute:: template_name What template to use to render the panel in the admin dashboard, defaults to ``'admin/panels/default.html'``. .. py:method:: get_urls() Useful as a hook for extending :py:class:`AdminPanel` functionality with custom urls and views. .. note:: It is not necessary to decorate the views specified by this method since the :py:class:`Admin` instance will handle this during registration and setup. :rtype: Returns a tuple of 2-tuples mapping url to view .. py:method:: get_url_name(name) Since urls are namespaced, this function provides an easy way to get full urls to views provided by this panel :param name: string representation of the view function whose url you want :rtype: String representing url .. code-block:: html {{ url_for(panel.get_url_name('create')) }} .. py:method:: get_template_name() Return the template used to render this panel in the dashboard. By default simply returns the template stored under :py:attr:`AdminPanel.template_name`. .. py:method:: get_context() Return the context to be used when rendering the dashboard template. :rtype: Dictionary .. py:method:: render() Render the panel template with the context -- this is what gets displayed in the admin dashboard. Auth ---- .. py:class:: Auth(app, db[, user_model=None[, prefix='/accounts']], db_table='user') The class that provides methods for authenticating users and tracking users across requests. It also provides a model for persisting users to the database, though this can be customized. The auth framework is used by the :py:class:`Admin` and can also be integrated with the :py:class:`RestAPI`. Here is an example of how to use the Auth framework: .. code-block:: python from flask import Flask from flask_peewee.auth import Auth from flask_peewee.db import Database app = Flask(__name__) db = Database(app) # needed for authentication auth = Auth(app, db) # mark a view as requiring login @app.route('/private/') @auth.login_required def private_timeline(): # get the currently-logged-in user user = auth.get_logged_in_user() Unlike the :py:class:`Admin` or the :py:class:`RestAPI`, there is no explicit ``setup()`` method call when using the Auth system. Creation of the auth blueprint and registration with the Flask app happen automatically during instantiation. .. note:: A context processor is automatically registered that provides the currently logged-in user across all templates, available as "user". If no user is logged in, the value of this will be ``None``. .. note:: A pre-request handler is automatically registered which attempts to retrieve the current logged-in user and store it on the global flask variable ``g``. :param app: flask application to bind admin to :param db: :py:class:`Database` database wrapper for flask app :param user_model: ``User`` model to use :param prefix: url to bind authentication views to, defaults to /accounts/ :param db_table: Create db table using db_table name. ``user`` is reserved keyword in postgres. .. py:attribute:: default_next_url = '/' The url to redirect to upon successful login in the event a ``?next=`` is not provided. .. py:method:: get_logged_in_user() .. note:: Since this method relies on the session storage to track users across requests, this method must be called while within a ``RequestContext``. :rtype: returns the currently logged-in ``User``, or ``None`` if session is anonymous .. py:method:: login_required(func) Function decorator that ensures a view is only accessible by authenticated users. If the user is not authed they are redirected to the login view. .. note:: this decorator should be applied closest to the original view function .. code-block:: python @app.route('/private/') @auth.login_required def private(): # this view is only accessible by logged-in users return render_template('private.html') :param func: a view function to be marked as login-required :rtype: if the user is logged in, return the view as normal, otherwise returns a redirect to the login page .. py:method:: get_user_model() :rtype: Peewee model to use for persisting user data and authentication .. py:method:: get_model_admin([model_admin=None]) Provide a :py:class:`ModelAdmin` class suitable for use with the User model. Specifically addresses the need to re-hash passwords when changing them via the admin. The default implementation includes an override of the :py:meth:`ModelAdmin.save_model` method to intelligently hash passwords: .. code-block:: python class UserAdmin(model_admin): columns = ['username', 'email', 'active', 'admin'] def save_model(self, instance, form, adding=False): orig_password = instance.password user = super(UserAdmin, self).save_model(instance, form, adding) if orig_password != form.password.data: user.set_password(form.password.data) user.save() return user :param model_admin: subclass of :py:class:`ModelAdmin` to use as the base class :rtype: a subclass of :py:class:`ModelAdmin` suitable for use with the ``User`` model .. py:method:: get_urls() A mapping of url to view. The default implementation provides views for login and logout only, but you might extend this to add registration and password change views. Default implementation: .. code-block:: python def get_urls(self): return ( ('/logout/', self.logout), ('/login/', self.login), ) :rtype: a tuple of 2-tuples mapping url to view function. .. py:method:: get_login_form() :rtype: a ``wtforms.Form`` subclass to use for retrieving any user info required for login .. py:method:: authenticate(username, password) Given the ``username`` and ``password``, retrieve the user with the matching credentials if they exist. No exceptions should be raised by this method. :rtype: ``User`` model if successful, otherwise ``False`` .. py:method:: login_user(user) Mark the given user as "logged-in". In the default implementation, this entails storing data in the ``Session`` to indicate the successful login. :param user: ``User`` instance .. py:method:: logout_user(user) Mark the requesting user as logged-out :param user: ``User`` instance The BaseUser mixin ^^^^^^^^^^^^^^^^^^ .. py:class:: BaseUser() Provides default implementations for password hashing and validation. The auth framework requires two methods be implemented by the ``User`` model. A default implementation of these methods is provided by the ``BaseUser`` mixin. .. py:method:: set_password(password) Encrypts the given password and stores the encrypted version on the model. This method is useful when registering a new user and storing the password, or modifying the password when a user elects to change. .. py:method:: check_password(password) Verifies if the given plaintext password matches the encrypted version stored on the model. This method on the User model is called specifically by the :py:meth:`Auth.authenticate` method. :rtype: Boolean Database -------- .. py:class:: Database([app=None[, database=None]]) The database wrapper provides integration between the peewee ORM and flask. It reads database configuration information from the flask app configuration and manages connections across requests. The db wrapper also provides a ``Model`` subclass which is configured to work with the database specified by the application's config. :param app: a ``Flask`` instance or ``None`` (for deferred initialization). :param db: a peewee database instance or ``None``. If None then the database can be configured via the ``app.config`` settings. To configure the database specify a database engine and name: .. code-block:: python DATABASE = { 'name': 'example.db', 'engine': 'peewee.SqliteDatabase', } Here is an example of how you might use the database wrapper: .. code-block:: python # instantiate the db wrapper db = Database(app) # start creating models class Blog(db.Model): # this model will automatically work with the database specified # in the application's config. name = CharField() Here is how to defer initialization via ``init_app``: .. code-block:: python db = Database() class Blog(db.Model): name = CharField() # ... # Some time later, we can initialize the database wrapper. app = Flask(__name__) app.config.update(DATABASE={'engine': 'peewee.SqliteDatabase', 'name': 'example.db'}) db.init_app(app) # Alternately, we can specify the peewee database instance directly: app = Flask(__name__) sqlite_db = SqliteDatabase('example.db') db.init_app(app, sqlite_db) .. py:method:: init_app([app=None[, database=None]]) :param app: a ``Flask`` instance. :param db: a peewee database instance or ``None``. If None then the database will be configured via the ``app.config`` settings. Initialize the Database wrapper with a Flask app you intend to use, optionally specifying a Peewee database instance. If ``database`` is None then the database will be loaded from ``app.config``. .. py:attribute:: Model Model subclass that works with the database specified by the app's config REST API -------- .. py:class:: RestAPI(app[, prefix='/api'[, default_auth=None[, name='api']]]) The :py:class:`RestAPI` acts as a container for the various :py:class:`RestResource` objects. By default it binds all resources to ``/api//``. Much like the :py:class:`Admin`, it is a centralized registry of resources. Example of creating a ``RestAPI`` instance for a flask app: .. code-block:: python from flask_peewee.rest import RestAPI from app import app # our project's Flask app # instantiate our api wrapper api = RestAPI(app) # register a model with the API api.register(SomeModel) # configure URLs api.setup() .. note:: Like the flask admin, the ``RestAPI`` has a ``setup()`` method which must be called after all resources have been registered. :param app: flask application to bind API to :param prefix: url to serve REST API from :param default_auth: default :py:class:`Authentication` type to use with registered resources :param name: the name for the API blueprint .. py:method:: register(model[, provider=RestResource[, auth=None[, allowed_methods=None]]]) Register a model to expose via the API. :param model: ``Model`` to expose via API :param provider: subclass of :py:class:`RestResource` to use for this model :param auth: authentication type to use for this resource, falling back to :py:attr:`RestAPI.default_auth` :param allowed_methods: ``list`` of HTTP verbs to allow, defaults to ``['GET', 'POST', 'PUT', 'DELETE']`` .. py:method:: setup() Register the API ``BluePrint`` and configure urls. .. warning:: This must be called **after** registering your resources. RESTful Resources and their subclasses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. py:class:: RestResource(rest_api, model, authentication[, allowed_methods=None]) Class that determines how a peewee ``Model`` is exposed by the Rest API. Provides a way of encapsulating model-specific configuration and behaviors. Provided when registering a model with the :py:class:`RestAPI` instance (see :py:meth:`RestAPI.register`). Should not be instantiated directly in most cases. Instead should be "registered" with a ``RestAPI`` instance. Example usage: .. code-block:: python # instantiate our api wrapper, passing in a reference to the Flask app api = RestAPI(app) # create a RestResource subclass class UserResource(RestResource): exclude = ('password', 'email',) # assume we have a "User" model, register it with the custom resource api.register(User, UserResource) .. py:attribute:: paginate_by = 20 Determines how many results to return for a given API query. .. note:: *Fewer* results can be requested by specifying a ``limit``, but ``paginate_by`` is the upper bound. .. py:attribute:: fields = None A list or tuple of fields to expose when serializing .. py:attribute:: exclude = None A list or tuple of fields to **not** expose when serializing .. py:attribute:: filter_exclude A list of fields that **cannot** be used to filter API results .. py:attribute:: filter_fields A list of fields that can be used to filter the API results .. py:attribute:: filter_recursive = True Allow filtering on related resources .. py:attribute:: include_resources A mapping of field name to resource class for handling of foreign-keys. When provided, foreign keys will be "nested". .. code-block:: python class UserResource(RestResource): exclude = ('password', 'email') class MessageResource(RestResource): include_resources = {'user': UserResource} # 'user' is a foreign key field .. code-block:: javascript /* messages without "include_resources" */ { "content": "flask and peewee, together at last!", "pub_date": "2026-09-16 18:36:15", "id": 1, "user": 2 }, /* messages with "include_resources = {'user': UserResource} */ { "content": "flask and peewee, together at last!", "pub_date": "2026-09-16 18:36:15", "id": 1, "user": { "username": "coleifer", "active": true, "join_date": "2026-09-16 18:35:56", "admin": false, "id": 2 } } .. py:attribute:: delete_recursive = True Recursively delete dependencies .. py:method:: get_query() Returns the list of objects to be exposed by the API. Provides an easy hook for restricting objects: .. code-block:: python class UserResource(RestResource): def get_query(self): # only return "active" users return self.model.select().where(active=True) :rtype: a ``SelectQuery`` containing the model instances to expose .. py:method:: prepare_data(obj, data) This method provides a hook for modifying outgoing data. The default implementation no-ops, but you could do any kind of munging here. The data returned by this method is passed to the serializer before being returned as a json response. :param obj: the object being serialized :param data: the dictionary representation of a model returned by the ``Serializer`` :rtype: a dictionary of data to hand off .. py:method:: save_object(instance, raw_data) Persist the instance to the database. The raw data supplied by the request is also available, but at the time this method is called the instance has already been updated and populated with the incoming data. :param instance: ``Model`` instance that has already been updated with the incoming ``raw_data`` :param raw_data: data provided in the request :rtype: a saved instance .. py:method:: api_list() A view that dispatches based on the HTTP verb to either: * GET: :py:meth:`~RestResource.object_list` * POST: :py:meth:`~RestResource.create` :rtype: ``Response`` .. py:method:: api_detail(pk) A view that dispatches based on the HTTP verb to either: * GET: :py:meth:`~RestResource.object_detail` * PUT: :py:meth:`~RestResource.edit` * DELETE: :py:meth:`~RestResource.delete` :rtype: ``Response`` .. py:method:: object_list() Returns a serialized list of ``Model`` instances. These objects may be filtered, ordered, and/or paginated. :rtype: ``Response`` .. py:method:: object_detail() Returns a serialized ``Model`` instance. :rtype: ``Response`` .. py:method:: create() Creates a new ``Model`` instance based on the deserialized POST body. :rtype: ``Response`` containing serialized new object .. py:method:: edit() Edits an existing ``Model`` instance, updating it with the deserialized PUT body. :rtype: ``Response`` containing serialized edited object .. py:method:: delete() Deletes an existing ``Model`` instance from the database. :rtype: ``Response`` indicating number of objects deleted, i.e. ``{'deleted': 1}`` .. py:method:: get_api_name() :rtype: URL-friendly name to expose this resource as, defaults to the model's name .. py:method:: check_get([obj=None]) A hook for pre-authorizing a GET request. By default returns ``True``. :rtype: Boolean indicating whether to allow the request to continue .. py:method:: check_post() A hook for pre-authorizing a POST request. By default returns ``True``. :rtype: Boolean indicating whether to allow the request to continue .. py:method:: check_put(obj) A hook for pre-authorizing a PUT request. By default returns ``True``. :rtype: Boolean indicating whether to allow the request to continue .. py:method:: check_delete(obj) A hook for pre-authorizing a DELETE request. By default returns ``True``. :rtype: Boolean indicating whether to allow the request to continue .. py:class:: RestrictOwnerResource(RestResource) This subclass of :py:class:`RestResource` allows only the "owner" of an object to make changes via the API. It works by verifying that the authenticated user matches the "owner" of the model instance, which is specified by setting :py:attr:`~RestrictOwnerResource.owner_field`. Additionally, it sets the "owner" to the authenticated user whenever saving or creating new instances. .. py:attribute:: owner_field = 'user' Field on the model to use to verify ownership of the given instance. .. py:method:: validate_owner(user, obj) :param user: an authenticated ``User`` instance :param obj: the ``Model`` instance being accessed via the API :rtype: Boolean indicating whether the user can modify the object .. py:method:: set_owner(obj, user) Mark the object as being owned by the provided user. The default implementation simply calls ``setattr``. :param obj: the ``Model`` instance being accessed via the API :param user: an authenticated ``User`` instance Authenticating requests to the API ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. py:class:: Authentication([protected_methods=None]) Not to be confused with the ``auth.Authentication`` class, this class provides a single method, ``authorize``, which is used to determine whether to allow a given request to the API. :param protected_methods: A list or tuple of HTTP verbs to require auth for .. py:method:: authorize() This single method is called per-API-request. :rtype: Boolean indicating whether to allow the given request through or not .. py:class:: UserAuthentication(auth[, protected_methods=None]) Authenticates API requests by requiring the requesting user be a registered ``auth.User``. Credentials are supplied using HTTP basic auth. Example usage: .. code-block:: python from auth import auth # import the Auth object used by our project from flask_peewee.rest import RestAPI, RestResource, UserAuthentication # create an instance of UserAuthentication user_auth = UserAuthentication(auth) # instantiate our api wrapper, specifying user_auth as the default api = RestAPI(app, default_auth=user_auth) # create a special resource for users that excludes email and password class UserResource(RestResource): exclude = ('password', 'email',) # register our models so they are exposed via /api// api.register(User, UserResource) # specify the UserResource # configure the urls api.setup() :param auth: an :ref:`authentication` instance :param protected_methods: A list or tuple of HTTP verbs to require auth for .. py:method:: authorize() Verifies, using HTTP Basic auth, that the username and password match a valid ``auth.User`` model before allowing the request to continue. :rtype: Boolean indicating whether to allow the given request through or not .. py:class:: AdminAuthentication(auth[, protected_methods=None]) Subclass of the :py:class:`UserAuthentication` that further restricts which users are allowed through. The default implementation checks whether the requesting user is an "admin" by checking whether the admin attribute is set to ``True``. Example usage: .. code-block:: python Authenticates API requests by requiring the requesting user be a registered ``auth.User``. Credentials are supplied using HTTP basic auth. Example usage: .. code-block:: python from auth import auth # import the Auth object used by our project from flask_peewee.rest import RestAPI, RestResource, UserAuthentication, AdminAuthentication # create an instance of UserAuthentication and AdminAuthentication user_auth = UserAuthentication(auth) admin_auth = AdminAuthentication(auth) # instantiate our api wrapper, specifying user_auth as the default api = RestAPI(app, default_auth=user_auth) # create a special resource for users that excludes email and password class UserResource(RestResource): exclude = ('password', 'email',) # register our models so they are exposed via /api// api.register(SomeModel) # specify the UserResource and require the requesting user be an admin api.register(User, UserResource, auth=admin_auth) # configure the urls api.setup() .. py:method:: verify_user(user) Verifies whether the requesting user is an administrator :param user: the ``auth.User`` instance of the requesting user :rtype: Boolean indicating whether the user is an administrator .. py:class:: APIKeyAuthentication(model, protected_methods=None) Subclass that allows you to provide an API Key model to authenticate requests with. .. note:: Must provide an API key model with at least the following two fields: * key * secret .. code-block:: python # example API key model class APIKey(db.Model): key = CharField() secret = CharField() user = ForeignKeyField(User) # instantiating the auth api_key_auth = APIKeyAuthentication(model=APIKey) :param model: a :py:class:`Database.Model` subclass to persist API keys. :param protected_methods: A list or tuple of HTTP verbs to require auth for Utilities --------- .. py:function:: get_object_or_404(query_or_model, *query) Provides a handy way of getting an object or 404ing if not found, useful for urls that match based on ID. :param query_or_model: a query or model to filter using the given expressions :param query: a list of query expressions .. code-block:: python @app.route('/blog//') def blog_detail(title): blog = get_object_or_404(Blog.select().where(Blog.active==True), Blog.title==title) return render_template('blog/detail.html', blog=blog) .. py:function:: object_list(template_name, qr[, var_name='object_list'[, **kwargs]]) Wraps the given query and handles pagination automatically. Pagination defaults to ``20`` but can be changed by passing in ``paginate_by=XX``. :param template_name: template to render :param qr: a select query :param var_name: the template variable name to use for the paginated query :param kwargs: arbitrary context to pass in to the template .. code-block:: python @app.route('/blog/') def blog_list(): active = Blog.select().where(Blog.active==True) return object_list('blog/index.html', active) .. code-block:: jinja <!-- template --> {% for blog in object_list %} {# render the blog here #} {% endfor %} {% if page > 1 %} <a href="./?page={{ page - 1 }}">Prev</a> {% endif %} {% if page < pagination.get_pages() %} <a href="./?page={{ page + 1 }}">Next</a> {% endif %} .. py:function:: get_next() :rtype: a URL suitable for redirecting to .. py:function:: slugify(s) Use a regular expression to make arbitrary string ``s`` URL-friendly :param s: any string to be slugified :rtype: url-friendly version of string ``s`` .. py:class:: PaginatedQuery(query_or_model, paginate_by) A wrapper around a query (or model class) that handles pagination. .. py:attribute:: page_var = 'page' The URL variable used to store the current page Example: .. code-block:: python query = Blog.select().where(Blog.active==True) pq = PaginatedQuery(query) # assume url was /?page=3 obj_list = pq.get_list() # returns 3rd page of results pq.get_page() # returns "3" pq.get_pages() # returns total objects / objects-per-page .. py:method:: get_list() :rtype: a list of objects for the request page .. py:method:: get_page() :rtype: an integer representing the currently requested page .. py:method:: get_pages() :rtype: the number of pages in the entire result set ��������������������������������������������������������������������������������������������������flask-peewee-4.0.1/docs/auth.rst��������������������������������������������������������������������0000664�0000000�0000000�00000016722�15223753015�0016522�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _authentication: Authentication ============== The :py:class:`Authentication` class provides a means of authenticating users of the site. It is designed to work out-of-the-box with a simple ``User`` model, but can be heavily customized. The :py:class:`Auth` system is comprised of a single class which is responsible for coordinating incoming requests to your project with known users. It provides the following: * views for login and logout * model to store user data (or you can provide your own) * mechanism for identifying users across requests (uses session storage) All of these pieces can be customized, but the default out-of-box implementation aims to provide a good starting place. The auth system is also designed to work closely with the :ref:`admin-interface`. Getting started --------------- In order to provide a method for users to authenticate with your site, instantiate an :py:class:`Auth` backend for your project: .. code-block:: python from flask import Flask from flask_peewee.auth import Auth from flask_peewee.db import Database app = Flask(__name__) db = Database(app) # needed for authentication auth = Auth(app, db) .. note:: ``user`` is reserverd keyword in Postgres. Pass db_table to Auth to override db table. Marking areas of the site as login required ------------------------------------------- If you want to mark specific areas of your site as requiring auth, you can decorate views using the :py:meth:`Auth.login_required` decorator: .. code-block:: python @app.route('/private/') @auth.login_required def private_timeline(): user = auth.get_logged_in_user() # ... display the private timeline for the logged-in user If the request comes from someone who has not logged-in with the site, they are redirected to the :py:meth:`Auth.login` view, which allows the user to authenticate. After successfully logging-in, they will be redirected to the page they requested initially. Requiring specific permissions ------------------------------ :py:meth:`Auth.login_required` only checks that *someone* is logged in. When a view should be restricted further, two more decorators are available: * :py:meth:`Auth.admin_required` -- additionally requires the user's ``admin`` flag to be set. * :py:meth:`Auth.test_user` -- takes a predicate ``fn(user)`` and builds a decorator that requires a logged-in user for whom it returns a truthy value. In fact ``login_required`` and ``admin_required`` are nothing more than ``test_user(lambda user: True)`` and ``test_user(lambda user: user.admin)``. Use ``test_user`` to express any rule you like: .. code-block:: python @app.route('/staff/') @auth.test_user(lambda user: user.is_staff) def staff_area(): # only reachable by a logged-in user whose is_staff attribute is truthy ... A request that fails the check is redirected to the login view, exactly like ``login_required``. Retrieving the current user --------------------------- Whenever in a `request context <https://flask.palletsprojects.com/en/stable/reqcontext/>`_, the currently logged-in user is available by calling :py:meth:`Auth.get_logged_in_user`, which will return ``None`` if the requesting user is not logged in. The auth system also registers a pre-request hook that stores the currently logged-in user in the special flask variable ``g``. Logging users in and out programmatically ----------------------------------------- Sometimes you need to establish the session yourself -- for instance, logging a user in immediately after they register. :py:meth:`Auth.login_user` and :py:meth:`Auth.logout_user` do exactly that from within a request: .. code-block:: python user = User.create(username='huey', email='huey@example.com', ...) user.set_password('meow') user.save() auth.login_user(user) # huey is now logged in for subsequent requests ``logout_user()`` ends the session. By default it removes only flask-peewee's own session keys, leaving any other data you've stored in the session intact. Pass ``clear_session=True`` when constructing :py:class:`Auth` to have logout wipe the *entire* session instead -- a simple hardening step against session fixation: .. code-block:: python auth = Auth(app, db, clear_session=True) Accessing the user in the templates ----------------------------------- The auth system registers a template context processor which makes the logged-in user available in any template: .. code-block:: html {% if user %} <p>Hello {{ user.username }}</p> {% else %} <p>Please <a href="{{ url_for('auth.login') }}?next={{ request.path }}">log in</a></p> {% endif %} Using a custom "User" model --------------------------- It is easy to use your own model for the ``User``, though depending on the amount of changes it may be necessary to override methods in both the :py:class:`Auth` and :py:class:`Admin` classes. Unless you want to override the default behavior of the :py:class:`Auth` class' mechanism for actually authenticating users (which you may want to do if relying on a 3rd-party for auth) -- you will want to be sure your ``User`` model implements two methods: * ``set_password(password)`` -- takes a raw password and stores an encrypted version on model * ``check_password(password)`` -- returns whether or not the supplied password matches the one stored on the model instance .. note:: The :py:class:`BaseUser` mixin provides default implementations of these two methods. Here's a simple example of extending the auth system to use a custom user model: .. code-block:: python from flask_peewee.auth import BaseUser # <-- implements set_password and check_password app = Flask(__name__) db = Database(app) # create our custom user model. note that we're mixing in BaseUser in order to # use the default auth methods it implements, "set_password" and "check_password" class User(db.Model, BaseUser): username = CharField() password = CharField() email = CharField() # ... our custom fields ... is_superuser = BooleanField() # create a modeladmin for it class UserAdmin(ModelAdmin): columns = ('username', 'email', 'is_superuser',) # Make sure the user's password is hashed, after it's been changed in # the admin interface. If we don't do this, the password will be saved # in clear text inside the database and login will be impossible. def save_model(self, instance, form, adding=False): orig_password = instance.password user = super(UserAdmin, self).save_model(instance, form, adding) if orig_password != form.password.data: user.set_password(form.password.data) user.save() return user # subclass Auth so we can return our custom classes class CustomAuth(Auth): def get_user_model(self): return User def get_model_admin(self, model_admin=None): return UserAdmin # instantiate the auth auth = CustomAuth(app, db) Here's how you might integrate the custom auth with the admin area of your site: .. code-block:: python # subclass Admin to check for whether the user is a superuser class CustomAdmin(Admin): def check_user_permission(self, user): return user.is_superuser # instantiate the admin admin = CustomAdmin(app, auth) admin.register(User, UserAdmin) admin.setup() ����������������������������������������������flask-peewee-4.0.1/docs/conf.py���������������������������������������������������������������������0000664�0000000�0000000�00000015675�15223753015�0016334�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- # # flask-peewee documentation build configuration file, created by # sphinx-quickstart on Tue Sep 20 13:19:30 2011. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. import datetime project = 'flask-peewee' copyright = '%s, charles leifer' % (datetime.datetime.now().year) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The version info is derived from the installed package so the docs never # advertise a stale release number. try: from flask_peewee import __version__ as release except Exception: release = '3.1.0' # The short X.Y version. version = '.'.join(release.split('.')[:2]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'alabaster' html_theme_options = { 'logo': 'peewee.jpg', } # Add any paths that contain custom themes here, relative to this directory. html_theme_path = ['_themes'] # The name for this set of Sphinx documents. If None, it defaults to # "<project> v<release> documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a <link> tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'flask-peeweedoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'flask-peewee.tex', u'flask-peewee Documentation', u'charles leifer', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'flask-peewee', u'flask-peewee Documentation', [u'charles leifer'], 1) ] �������������������������������������������������������������������flask-peewee-4.0.1/docs/database.rst����������������������������������������������������������������0000664�0000000�0000000�00000005773�15223753015�0017331�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _database: Database Wrapper ================ The Peewee database wrapper provides a thin layer of integration between flask apps and the peewee orm. The database wrapper is important because it ensures that a database connection is created for every incoming request, and closed upon request completion. It also provides a subclass of ``Model`` which works with the database specified in your app's configuration. Most features of ``flask-peewee`` require a database wrapper, so you very likely always create one. The database wrapper reads its configuration from the Flask application. The configuration requires only two arguments, but any additional arguments will be passed to the database driver when connecting: `name` The name of the database to connect to (or filename if using sqlite3) `engine` The database driver to use, must be a subclass of ``peewee.Database``. .. code-block:: python from flask import Flask from peewee import * from flask_peewee.db import Database DATABASE = { 'name': 'example.db', 'engine': 'peewee.SqliteDatabase', } app = Flask(__name__) app.config.from_object(__name__) # Load database configuration from module. # Instantiate the db wrapper. db = Database(app) # Start creating models. class Blog(db.Model): name = CharField() # .. etc. You can also directly pass the Peewee database instance to the :py:class:`Database` helper: .. code-block:: python app = Flask(__name__) app.config.from_object(__name__) sqlite_db = SqliteDatabase('example.db') db = Database(app, sqlite_db) class Blob(db.Model): name = CharField() # ... The database initialization can be deferred in order to support more dynamic behavior: .. code-block:: python from flask_peewee.db import Database # Defer initialization but define our models. db = Database() class Blog(db.Model): name = CharField() # .. etc. # Some time later, we can: app = Flask(__name__) app.config.from_object(__name__) db.init_app(app) # Or we can also specify the database directly. app = Flask(__name__) sqlite_db = SqliteDatabase('example.db') db.init_app(app, sqlite_db) Other examples -------------- Connection pooled Postgres or MySQL: .. code-block:: python DATABASE = { 'name': 'my_app', 'engine': 'playhouse.pool.PooledPostgresqlDatabase', # 'engine': 'playhouse.pool.PooledMySQLDatabase', # 'user': 'postgres', # 'password': 'secret password', # 'host': '127.0.0.1', } To connect to Postgres / MySQL without pool: .. code-block:: python DATABASE = { 'name': 'my_database', 'engine': 'peewee.PostgresqlDatabase', # 'engine': 'peewee.MySQLDatabase', 'user': 'db_user', 'password': 'secret password', } We can specify the database directly, as well: .. code-block:: python pg_db = PostgresqlDatabase('pg_database') db = Database(app, pg_db) �����flask-peewee-4.0.1/docs/fp-admin.png����������������������������������������������������������������0000664�0000000�0000000�00000213471�15223753015�0017230�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��)�����H��� pHYs����+��� tEXtlogicalX�427/_��� tEXtlogicalY�183v ���tEXtscreen�HDMI-A-1/ �� �IDATx^w|E]zA;Ry RDT@@)R.J*EE$tI%@ @w'QLffgo;<73kd̛DDDDDDDDofq/;(4A! )DDDDDDD$MPH!"""""""iB IRHBDDDDDDD"""""""&(4A! 6>tB&˿k3>"?ǸW+DDDDDD?O�r+dRThu^_FPH!""""""p%w_FPH!"""""""iB IRHp!E"f@TX~qu?/DLTX=~<M[ VtmƮ!.:b1ز<�]˘n?Bmov"""""""/r!<8 {$ڿ;+]f2zl}9sW,�ڷ(_'hP0<5,d@=hvwLuQaa\<F㌟5:^*95wQH%>xW)0khJ{_%=`ֈ(v8Ms{2dX4NQj?gA/9aԴM8ÃܫV2=90 !3 '[bxIL_+fY3p:<pg\3Y>�8BOso,`^^':`w?D~IDAŧksp^aH>RWҗ/'r=hlz <;Z`eRzu>Sӽ [y/>ݖ3>^3iԶyp&]{+fy9pFK`ƥ ):ap?P#oZto`,>]iQăQ`{PE~I\I؉Gn]Nfsof`fPZ7م˓tRxO/K8NORT&D-/> {3�2м]*ĸWP3Ao2}7Ev]}|TEۗ'8ςq{(=q.1d y nEl\:Kaa \s]{/3ߵ!~͹9(P 7xƌS%Arv&BBxC\}э6s1>b-.{9Qa9FۗG}єxh(o0[C]@đBK (Kl6 W6` )u3zxNW)Nv* zXb֜8pg�ڤ3:o.8�dG`҉DɡLu>)|TfS c:=~kvN_ndh3neqK)}z6-Dy?zaެ7Km)0ʦ7}݇ixa>OMMDȯ<kb+ tt'>əd}a>mSK8t\X.j{(R n,((϶]F\M%W� xFA)'jOY +0]QF:�^/AI1 ~ߊۭ y0Hy >0T6~̚6j r{mq0{C ߴtIDDDDrL۽oa�Zo?=xcdȂ=Lroڽt Yb?{5jSLF6cw9.%{N%ʖ5j ^| fX0=Bi휚7ôӡm{Ͱҹw '#~=Ty»U >dMłڋm&�TW0=;}yѽVqf~5 \xMf_O^\F߳n/ⱚo嗕\V~%k`w72-6='PE(ɏn ˲IW5�mNC&r[hd~$ȑ#q_ve#}" myBMI7A q?& )+_F_lVײ--Ióuٚ;~ѻ> FF�x•Ӹ ƽKkr<7[_0/Fݏ&@�33єgdZ禌M!3S0^|u!'m31*tύ,~ާӾd oξJf-(3<ugpvN*>�0Ba<pEA7@jYب;=ȁ(VQOQ""x.]"?V0(JOLկ=_(M3b.Fe0~3)7'mg˄.H.Sa V-,cq'uDDDDD neӃm;DZm!)ڽ:Et[fp8<ު@N1t|2 Hj 8v, _G m8Ϧu+7yBh4WjHG闿⼼ _t@MT&>:QA`A\?&vӠaTn":6ż,ԣxfbܐ/qgL0P*m\F}.gVc`<g\)Rd25_@u [1ô,o5v^+*xG|?#̸<gVP�aq4{՜aURTL%Q} S3�!*ݩ23Og@!8 O;F1~`oדb2XrI#g7&lՖ/f 'EM؁H H;+Esb9=4 yk2 5=+K1kgPD~n$y$ؾ9zd?Z7LY޿9zM|(MuBsዜ g9l(,Y]'ٷ3n,÷da>OiHoW9;#x2 ]K=*8޾C!+[?=we6t`ւ<X#K<ι{(Da |(V$=1cBRd̞9wj?C1q.Y?Nɉ81ILLt$S9+e1oFv<.Je GDDDDaZ [ bdR\z/~$ikO/\4]OlM8uXr)d! N<Ӎ\ `Է`ɜrG׀dO?u{9g# $M�+P?'on0gҥt47g4y='E6+LU;75a^4y}Hz:-76Mf0�fY\7 :N>?W2bŒ$oK9q;k{G/oZxqF.I ٌŃqL&?}'7�L=ʔJ尦oDZ:$' u r7{+v$2WyҾ|1:_M'nnjx rSwȇd,FytjC1?mZ?pyҨ8'cc7!eH:On }X2I0-b9m&mi@2Vͥf) DE^gkz9J`FXs 3'|Ϸ`kY~5~Z˕sq =nz.L 1!I4LOG^9 PeFB^׃ ytw``o dLJ | bpnl lA<"c9>uc8nO*xe/IO+`BBS!d-R2 6Jq}<v>b)jc`F kJ+Ƕ\߶Wh\{䫏;,pπÒ8DXiXά!{򘟾G9IAor~IsXc@"VW^"`-G6?mӤ67(gCZ;~~Z"6x)f(F�1%~8èu=0m1e-⥫|u.7+坮, 8S )<8V8!"I;p,I94Z%0xa+ �o KgkgP'pJ 9pKQ \81�/o/ntΛ/]1&#Ј9,[�췇Z1|Kayڔ:Xikw]vc_&hU ڴ~4⛓B~ 5.vnj])|,`P/m#� j@<9Z>,PNaW r43;O|]siPfEZUBef'u}iýpMp Np:~,ٌt(k{u eCR74M{�sB؎Tcc x;q,1- ze)&t5$ZS,:G'qM`FUDŨT$?l.rr緵wgK0cHޟR W\a93' DOF;R&~3nV ۡMH|4~*r!8t?4pliKB.}B9"9sf||#?Iͨۈ30<Ĺ8w6RC^ʎ88G ?l�JJ O}L;qcCɿO]+K�, �X0�ۗx`x&|)e8EӍ`뵩 |m9<?Ds?wz�b`tp+q? 6YK`yIڭ@2~>>@ e|f6]tKW2yA. = t`^s]drϝp *4r0ï ĮBR T.b@Ɗ5ΘP<o_zp@-C\u=wU+NK=�]7vk"80�O/Od�R(7G;ILú9lM~rQ> x*8VlA5l)_*?H,\ N5kU84BDDDD  qDDrV{XFBX=I֌v2s)ez_̸N4- mi%6^E qFu;Q/~gMj`]n$j 7S&!|�R{.|ƴxc#nƼSLOUwaJolѧ86 ^ƥ7hKL�\wZśǴڏXi>^)NfCIK_ʪAkNľMY!E\x O*Aj/BVfT� GnJ[=i:lKΝ<EF[:үK}<+cxHBtL\g<~;GtaŘT 8K]xy5̸_"YkF h;3~6p/DWaԆS׮^'|73Gsa_.FYxؽ_んv@6l_ M�8bܴ3b^&J!};x5fVD8x.0;"k˾0օ/dcnB (В dq_6y3!.ޤ@ޒ9Ƴ:^ˋH[VqyN0/cZLl^Q8&5#8Ϥ:qF4d !=[q$fˮ6pDZ1cWiؿd8$\moM`1`FPp&bM2Ğ']<\ u= <p>F_4uyKę}<NzV#SݞA.+.$`esI3Iņl1�??߾-؊pNl|c̤@jHZ6+ ~Ss�Q+˖vf`ŵkk,?�hJz/rk||@< 6Q�_k ?۝]ׯI$"׮0u3qszLZ8j)4 |"{i]3)yve ܓ5C:yu1&^kD:M/żH'{ħկ1wl.V҉7-wdؿg=ޣ &۱vNK=2ec('C?Hz={?f�BpAvKx^*C$'I0o_vWR!q.>Wj67և:9߮Fr/q4҅|7kCߜS@!""""Lo$E0r< vfb%ox'੬EpmKo5|xF+Cb0R<=kVyFIX+ &.|]pq%0iU1'9+4Á'Ӣ%S-ZsypDp6BEY 6 dC]c?bd̛FNY ^Uq #&oҽ;.:9=߁Wյ |y΀mȚ3Uu}LqtZzcru~lj/ _qd<6`CRﲌkbo,!qUw�iC/IƋj#pl|Sʃ<dDH_5,4rԡo2SN oftgӈh=+“X4m}͢mЁ}w@ 2y-7ۍaXHVOFWFwQR/ִQe$Ja+lZ 2}9=+2'u n2u$[I3Sp*[yW'"""""=[1l3uAA_Lt(O0sI\7pP6߅Ӝcx6óJ+v?.%/!46 dQ @P7́dz:C>%pv+D6xwd^Ӈ {FF5g>7|ifϳyR<k~*;<✍B`wͺ]^|a(;.#.4;}MWb:UW;QkѹO9 D:a?W玤jA3_K贶,ٖ]Ϧ0R{IaMiN)[nga:}'lGj7RL ;sɰwr|<kA^ڄM^<UprV>a'ƈw3dvlɻloCQ?_Fti�fO%<}R'"""""o,l^ n_wt :86�q�kpvRn v'FmY8Qb}<HС T__�jB �WXq9;Ʀ\2f+앞Wc6<%CX#˫Ɉq^Yw*neFݖ&99;w+f2yX$2[ܔt=ߏ"zI�=u¼t [mRpf{ $%\blKvҸDvonb^ٍ֒sd;!k~�� �IDATW|Vj4 ;{wHb/|@bb; f,No%-!Z$Wh$o|Z>޽Kqicb} F`$f3 %+_ = ,sPy/$A~0%eʉM~@jIV',Jp>V`< CDDDDDD.o8 p=""""""""B IS{Rȿܓ"-/I""""""sw'/\#(݋u @,dQN;c/\㿝4A=DDDDDDD$MPH!"""""""i¿k<Rٛ7w/%E"""""" I!"""""""i64A3)DDDDDDD$MPH!"""""""iB IRHBDDDDDDD"""""""&(4ys2GN3)DDDDDDD$M0b_7 EDDDDDDD5ͤ4A! )DDDDDDD$MPH!"""""""iB IRHBDDDDDDD"""""""&(4A! )DDDDDDD$MPH!"""""""iB IRHBDDDDDDD"""""""& ,4݋DaEi^""""""AtHa&bcILH 19<<&y1ݎۗ?Պjjbυv;W0%>N(rCN||< fȀ#|=IRRÁ^^^v;p8SJ1ׯv4t^^x{yWܷDɜ9z/4Iӓ""""""�\!1) o{ƙ7x` (ZlC """"""W�<=]qw!EbB>>>U" ½_vP@!"""""t8R�$&'?=f#19ٽ2Mo{Pȣḧ)0MSw4Mv;^Z$"""""xyyi!Žt" =ל]<DDDDDD!͆t/? )D-f!""""""^d )?^ """"""pL! )DDDDDDD$MPH!"""""""iB IiHIZ=[ W6\f8੗PZwN}ПC杦8^@yj :kҫ@{܇GRp _OY ݫ@pĺWiKMzW͘@$b㢈f!"""""""rl ,<m҉~`uorPmHyƀgf�sɖ0ҹ7̤`׹W\2Ob6ԨU^ .t9bɆxfUgm,OVϼsZ`K-!y�Bhi8jէh3K*TAwpd4{*nB3#fA&w0 i;?^7]/;G'(-#DLJZ_7؁VӎPJuߑf=SVCЈ3EDDDDDDo )y@Yw`i`Ƨ? qio=ӐE{0T؇_CLn0ٽ6ZXk[ yS8>K^Z1qh%*Lbj:(>gk�4hӪ*lROz` FRy8p-w&qx{k9H20aQ965c7kpڝRx_*&~ ĢT~N2}>:{bِFB$K'qedTKZ#U\?e<kKiWhʄзp^>Nkq_ 'y1xXTK)L\ۏj)Id#aF6ʤs(ϡ??%�h˯q(هS32.\]|xvuI2D?]{cja^ �LZS o?c٭xu|k4f܋BR`&vp:FI�T.%K9B9q\p͔0􁾀 @&f61]Z%KvXR*dDQx=0tW 4.SM.]Jʅ3MO˝7+ߣ\n>b`vtv0]5焈ȽB <[Y0="�9pƄPg%{R`g4L9$x XS*w eixeO$$ H~p'Y,(UBgE 7 l`W;\ݵ0z"` `V7@ǧӱ+\6Wl�sX0<0Ďqێ�n�j<mcOI"6y͟eM|ut ;^b\=N _,3dy$y98GIv�LLl1y/)x>Vںk.!Ad+ξ#1x;iײxN;[gR�@cxI){.v&)[Yo iBiq0тG*0V%X}aX#xr(? X�Jض%37q^/V; re̤˩�f>R)͸u(33U{3#44MN'##ɜ){?;G2ڡmYxA5{s\"{lX, õȃruGlܫEDDDDD!:Qtd.9"pR>=t'-rY}{s=Vx뭆8 fS\ՋAW޽M3)<WʫO}^%Zc7:n*p[~cLu3h^X2>TMISxVzK{Z>O)/d0|$R&#B$-`BNi �>xƒf.FvWMxcZ.<$t`~#3Io@6*mΗ¹2Tb4Yk-н~HZ⼓?q#LqreJ>;\ں#z wE&owr.:_b~k�/5e#~QH!9Ag1Wq~^8ܫ| 0|}݋6r{yZgy|N+]MDDDDD )DP]̛o U mPs`yRUᖖ,I& A:ἴѽZDDDDD~=)DN8ZK=nigUz7 uY_;L%^Rҍ_ݛ,@ (R0HtGI }9̣qoN ERDDDDDE!#d_qݫRD8ןVQ|waKg@EGUixvN9_Lq1kpV8;Qm�>,""""{<B{s,]sⶻW?DOܼ4 K*Mߧ*}'H-ۓ#<(UY<VU~xMJ٪h'׶,']}Ǯ|p-,%<ɗ% .+/5ug!Ʒk)eY`,'0k/] IYi[_j(7T }Ǟ_WsqlkO'Zz~%r$ޫ[^\>ɋWPj?)-sBs<*fÙx[-<sk5fz"޶9+<S}f{X޷8/ourh,Jvnƭ30nH\dՊ۽I$oT(YVut콘WcjNwF2YX\ԪX&M)\7S7`h7C})DJFji֮֌%]vvoYs<' +uxz;:[زgBڕH< ̔'I Tm ~C(4ҕec'sbFryXԮPiܟC'zYpEc�yp&Nf޵Qgy1a&3)}<?B G$XNpO)k|;ׂℵ7Ҭ0S߉ |*{!9ro%<61YLWg\U`$Q{gyse;l<t_-e3y�ymF0kL<h.ŗ/,f/%n¥p>V}y]Ʊ,Xɯݾ#\73+~|JJ݄WRcXy�ө2msLLUwã87+Ӵ~ҍRp\v3wRav0+v) ݓ4:j{'mfvLJ)61$E~`n+ wz|J6׊3,<3fHvr[cLzZ nK0x!=:[.;pb:#zsڬVQN^8#%sj<CY_/u(xLΝ 9:IuV Wx""""i{<"u?\%ԮNvsaKb^^Rv7۝I܌�$qk?1ƤÉ3#U@q+!< 浩KY=S]~™Erq&8-oy:\=h%lPfmgLqj[/_So ,;q^ tɄ6O޼- &gbj {u*@>{V&Evy,Yzd;o-ÝLE:';eqNneZ X8Wxkد`7y,}pʹcv}kZ[DDD$S3)Ξ;^$xy>)[ސN %kRbetZCBR6ǙDYN6M[+|0 36ؽ6N~{'Ξq/ ?�?tNV7^OW)ر?\rŒ)UXW?p68fI+)'w� ~^c2ѻ`N:,>WFqdG`&jo1ۃx`<ӄaۢ);=f+$p);g]k*irc)4;|s/]Jy"qaX't=)n,A$tY? ne7რWD{y'^`{$oOw/y`F (ڄu7jJW=;x<N!X͚ ȍ% &|7:\)F-;G򉹸j3X T)LǪp&΋rf6@@kV/c\:h3;l1ټ~Qn0.j꜓WQ7Z jAՉedؼy-UPݏV�r#UHdBDxpʸ%gGϧ4+Nᑥ2mak'3Ԥ`怕H5;�^*KX>/чz&L[Jaor;kvd.P8~|+7ysv݄Nxۗ3 |P ˦pƆq5Ө6 7' SP|. E3=?z൩XMb+ �a7ߤ�fѭ1k(3Fyf3ҷEXK+iX[DDD$-S!ܟUMb,Fv <Y_ '}It85ktPl?{E5p;I%*H+ Ć&(*6D' !қ.% ٝyX.RT|ݜ{wvv3{pk\˾Mޝw^gɟGxgN`peF~l'F^Wvd8 6a[@OTĩ}(mP7O$;/Ӂ^T!)B44W½aӀT@#E&/�ֽUۉAڒTA~z=9ln?@nY dz Q oe0aL?uIՋsx(WlukO诓 ЫϾS.Бc2O0#o0(Y`N+^z7clś{-̹2{kK>wL= ?^BSlugi3'>5ိ X?~F#�(L]HT6nw팰v^nPF%]iҶ >%+9B�XSB!DQ#I ! ih:L5Z~PNrm0&)�Nj'gp*3N|vz`b [u'zpdcK[n;oKP�,}I^ Ҷ:~ݖ�ka`+?W8J:`|gowG! &eh*ka0Pj@NN.jV�K9[{`P 6"&ly\Kː['@qr`0 _Ɂhm�(cnvc%*uSx|@R&6.kF5w]%Lڲ;6q&v.NI6}Q=GVmM5=J(đ\kU S>l?j9~ї˯Ƞn`*iW6+B!E$)(d*_u@~T mpM hVcԐl pl.łuаk1|G. A$;D觠x=b(]` ,7s _͡PGZ�~[Os*T عggzXPy(ish|^'[_.'BiK%)�8qRPn>>k3ֺ5DOR!Y4Rz(I@Zn ]On[3{c 9vk֮enI@͸1M{#nJP;B!IRQEX9UO4`�thS3?K~dE ܀F~B^M+xU1](`(uƛzƲ6` @oik@Rƛ??m۹vĸ(SQܼ&֨uPC.y T6Lz S&ujſ'KA&m@S| :LI 4*/]C7z.*հT9.q*\_ml`8o DE\ Z" o8p|sRcHB!$)(D`U%Sv:\괱tg#1')phFu�rƣ| 8۷J)h U#8 3&]~Wj3hdKdil;Ϯ_(4 e`v=�m'< >:yPQQIJLWW[/ 4;Ky6U 91?T@{x ~"W[F�� �IDAT}~ !B2IRQXLh(y+v乨7>Z fW]NֆaiVn|iWg V~va17'Se9K[tW>OL[,%|=iJzty0*8,Q9f44snD\pmZ?{ X_2z~ !B-TV2c`U7o1ҚP�'ƣ|9=i{ =zǥ1-:GF-ʕt -N}(R'ẘW~>G7ykul9… 8c-jV znDH039,*&x|=(ھ zL|9?25вoN֡*{2wAnbHI.ٴ+^\؜S^rB!LB`c`X%c:y5$=3[zR; [67jA:4�4[]σ7+⹀Ͼg혀uPuF99Įtt9Ů\o>]ɇs} j̧ o_oυd <@M,0+-xx-I\V|Jo %f|~ !B{3S&dAunPRЮ� R%AnWTvF*XWV @eP ?T̑ABF!|4t ;|ҍ[u4+SlV=z=} ۥ\P#.t@`p :*] ܳ :r6-OXqx}\?Z]3 o6¾t[!7-!bgbvk$l[Oޝݚ!cvu.XغPKV$pD�?bcp\BOwK<6QK] KX,7W'h.vLNhک:u"f8&;'e$;@:jJT4|̀^Ӯ OS5XrI`Tt (y)@`n:}ĭ'D>B! $)(ׁjh "N%GN~nj�M}UQpܺk8{`+c+,\=<j>2?D/[ɤb?% >cba޹L"pS<P|$<".DDa&EɛI9]cŤo ]|[e_~m;4rS0Uo@3wmՙ4 0ze &QQ21k>gz9s{OfAq[ +.ȵ o[!ב*|0)+ygBotEa$o)WõPd!I;x'm=WpohJ-#oڒ ۆ<͓ѕxR:h޻#LTF 5#"'HڽS)ۢPVru?CNe{"(kݨDTJR--aDʻEDfhzy! Щm*fnO>96U}s21BD-/%JUbͬ"Yr/ ۴[1n؁94?Kлx4x|Z-Fy *mC2^?p?~i(Gu'V= <R?(Cb Wߦ3C)(/˲$ yB'9B񰺯I<QSk[ :]4`dŝhֲ6(vlU_`ո/ DAkd9\ٿU5'Ǣ(@rNl]#OKh׃(:حdekYW\z$hej0~&l:ЗiT v_Ig앎Ev*z9 Ά!l2#ӞK@xo8e9rWc4`0\I?UEΟ¬? lWHB!P�o_}޽<޳]\x vۆ㒓uL MZr uyZ͓ "�L0j`tg}n^l7ȟOgMCƱM1wnG ɚm^  #p}$向|SBu ++L mݝWd]aHe*> ގ_?^j`݊ճe~i4(W-HLL)B!D!ft@^V܋{5t`ʟ,LBϤ2jO }e$SǽE‘eu Kט4c3/ ʆ?F~Yt0c敗79"~p$i+yi;*[-3<ST|E|:�DeW`5|[~q|p U<?%XamvO ]XV8ϛ1Ϳ>Q'LD+n+|M8_pG9l@ޘ߭t̉xT< 0WAhWa.RMai2+'C0sE>'tm #o~bvReT* 0:<VXKsױ轮t7b:TQNظ`!<G׳�®`]+jB!Da=4]qfJ=pu xl>El}=O~xW}'᧹7ڍL[xkֳ\[?/M`c+f}|q>ˎ$ pRp7fL]rG:%bk)z@3w m/>bҽ@=R520pD"tv~ƃj{+6F-ay;@ Xj7&F`H5Z-9Kk "ŽaʹFhW1+ջlhD]y2 `+xP!ؗUBܪUcԭ1o}nX¥I]Or<޺!m`z5瞵@)]e7rɦZC{~40{:X[]U)1lh% ؾ$džBs  2I:T`jy K`߮\:hF ҼmvG&lB-Y8o+Qa8+Fxo|kvc̫; ysShit< .M77[!(mMhR"8رoVaPޫD7?~ͥoMܖ< }7_>Pޙss=#x U=NkSi84LET_9\Ho~ ūIsfs,^kWc)oBq_~Va_ b營0T0 ;75?TG'sȚ1>N߸+QQP[7B8+#�b!B!(&6gW;HO sUnIڱ}կ}ȟ$Ci4NT W2jm5kѢS=USZ5֩k7:3~RU;BjUiY6|pN=;k=1aid5,eT@%:Nd; bCr%7a]\d'ӄB!Bq{@TBLV|CrP2AH@g kBCQU^iH@W�^.z IO=y0e:Ĥ9u6Nu'r Ͻ,'jԥ EA#P\ :_gxTUIe}T'B!B!> eW{/qDu@bd"M&b\΁u+v BB/Ů,p<+;WS'6܀9cTo]u´踪czٶ?j.-'X~yY.!B!<$@Rzh@Cn]3ЬM5V^3Ķ3L40`ݩT_H| D%> (^Dw,'.!cqILJ@=zÅ白;cUA˥xn"`th �4)#Jf6s9. ٽ!B!B'@+a5W3`XDڶ)Lj8WAҎf/4@E2,*߭_J)nq8g0vM_tnC^+/4cv| ^*ժ@G7%f&؈s V,N'{~);!B!B}]l0Up?k=_=B!"E_o=Kƽ3Յ~cPuTr.B!BI@^uX,1R߫;VB!B!Ŀ$I[PF%iZ_cB!B!B!B!DIR!B!H$B!B!IR!B!H$B!B!IR!B!H$B!B!IR!B!H$B!B!IR!B!H08n'!11$B!BqO$cH{&2*1$B!!"=rKQeT9f୯? @c ulҖ�ձGJǢB`rɱX!B!noBܽhUYӿ2;|9B!fғBBgGSD F'^8kgiXN!B!Ŀ's5^Z]G)޸!ؾ{-jj$mݷ-� \טd3"ؐɰeܭ/uMe:oErm lp-:qtp:K8~t IapR<ޣ7sI�u_8DIco5@.025/M㠱!nB_eӅkHf i$/B!>)?+񨨼'?p@uͩq*\o.?J}Iz1ǝ9ubBE1_ƟY7PcR!S_QΜkYd.hjTZ;|Yu ~�-kx<"=û$\J^Høl;?],֟_DօB!HO !'0AުFPȫ+(mRc6]G2hRx*PS}p=1M\E3@� ^S�GbݬtIv^.<уSeTo&OpjjշN9&z*%"KԤ"mt !B!;$I!}998yQ�OO'>r?|Kr54MàhqWJqne:|d۶r1{`W6r�xR%Y[y@=Jc;�;7q͜INQbJ%cҶrN:i !B!>IRq\�q#P\VwP qpuք^<Umv:Sgq UP LSt TejL/P:d`~AF$&B!*T`jex嚤h /\*x@VZ.�'a}9 +`P/r<Ƕ݇@n񿐣kѹRby@'2cIQ)}c@0bTe^~Ӻ|@ͱuTODž?k1L)B!''$)$$?ٿqGSwϏ'<jICE5̹0t hy�g;\r@WP]J>HSWw1Vn:<ڜoo�Nk_wMEP2tT|ٸe/>ՋdrϬ'e�cvz,_n*/ӏ6Q/B!"I ! ɔ03_O 7B`OC#&噘܁gfn[gϞZi9ϵelg|u\M=K8sQJEժócgAq'ߓte]N.5Уx{1k;HNV-(OjxܷQ|=8XU!B!nKIMOmlMPUXJ; qDFENCQ%8 0 X!B!D!ړ"Z&I]CGlI צbgP<x-UFt =N}cH!B!}MRxL w,+ghx;&E@b!i !B!?@V09h}8Z"!B!B<{O ^σks`TbH`ɶټKr8K3oKmg88K_KuPL,~CS'}vqB!B!(bHOGL wdQ'Wsw[F*%r?v#ȍʇ>OSeyu^ wsm÷DFά�r/m_!B!EIRh@gzv^ȶO"\0Å;ԡ8C�^Y2]8mF ::tF'.Y<۵4kv|?]h0_:h}!B!B=}Gwzhb(jFH/G^[znk>@dFNU_x~X{dkRQ!B!Bܕvo॰,\1=v:yhh*84il=ttus~E!B!BIdG0?;p| %I΍$kv%]AM!#K|g1/g[=!B!BM4IPR!#43�\ %*&$0gqJ\@HBޅ aQd$FRQRUsfsf|bY"3?-uk !B!yI .L4K^0?~]1yy&E:-�l2Z0eC<WNAO:S۫|.c>xb@Ubu_L!B!E~hR"8رX{&2*�t:?^;22 p,B!BQbbcqvuc{HB!B!$B!B!IR!B!H$B!B!IR!B!H$B!B!IR!B!H$B!B!c@Q84Ms !xH(z$vMr$I ! i$&'Nfv6EOB¤.NN}߿ 5I!D}MIRQsrE4\\\pwww"!k6FZz:A8LU \B8zPפ!sRqiFtl,b BFbFccː & !+t$I!=םV4BPo\/ K\B&+Bii鸸8 !6...Uhc$n܏k~!!ȨtRfvBq[Fkَ{NIB!~] 4MfLBqW w)P& ![}M;$I!=RTNj!-q(m !(\?$I!B!B"AB!B!($I!B!B"AB!B!(^ �� �IDAT$I!B!B"ABQPyg5oƅ/fr j5k؎!wr!^ftj5kF�Xq#5Vf$&%9 !wB-Y|˟|f=DëWM }WG[DZBo[p)]m8ߕĤ$Z@=q!N'T0 dǢmsWx,ԄCB!C!t~5-[ZBb"?̚fX,.HB�-CsBZnncH! A_�qq̝W1+O$b|.܍>=jԹu{=?+DMX EidiKA =’_r6L ,ˋQΨZğC1_=Uߠ0ֲBٳw дQ#?4^^^vuϜ;Ǐsrq232xlYݛ]|3}:ϧN͚4nЀKġ;۝e˘׶wVf ۗG� 19c=%$MUyu`J, @]bN` xim¥Kx2e4k<!x$E L �Dziг89<Þ|#u0Ttr[ͮ$6|BQ*ԼSR/K/OCYp ]V~G~ScUx(6:AQPuzųU9MWJu !%ȡ\i_ʸ*DV}0-'N![1l &/fZ1j ʊ& ogSPa1)|j?gP|;BϢyrD`@�QQ_-۷`L}>=�t:gΝc§r52a/Xp;qCG~V@ioo*p52iixSD �OH_$6>^'%ۖ-޷3fPT)B*V$>!/PlY믦ME� $+;CGrQF2|!hNjM}qƬf͟ Zc%VW>k>,(@ht σRE}O7Rp209VYyE�{V-h ,`>OϩW勧1SBv3Q</aʍ`rr[ 6oߓբsX"V \qK>(c/ٰWޚX}GzHB<,,]ʵJ|9+,ٳquq!&.7&LKOgCΝٹa6m!C�=>W## nBe ϙs$C֭Y0s&ujY{թU3gO�hrbf…[˖QdI_>e g{Ǎc̙%K�xkp6VW׮�8{-A#ړs7=AA\yP(n rO6A_/u}E=S7u`w:v͘I8V~6:x{(g%=B8|j g y`v%&盧Æsi|WVa߆n8ؽ{(^?SRR^zJ�Ы3C?[ֳ_!"5- �//yx�PGhxL�IRr2}M&�yŎ~8z-x}~`4 !U.^tx32*�eJ@S)$&^\!n=IHJ慖,u1&%~P�yěYx-SIcR8q%Y?#P"*'W솋\Xra7Otou4V(yl2ܧ> �z5-•[(Һz :a ,˞)]}%:~\+ ]oȲקS?9" ʺ3 7q#Sh6d0?7%P<] thfQhP-&N_Ά0p$8s* \e3Ǵ{ !֭z?SiҼjաw`G!Nm۲vN>Mgu4[fM`1S�X,^>ls<\1AwBBBg'&[C]LHj8voCi\ קoON !DAw~$%⮤g&4e m=3aj=33I}.0cjZfև,̅3QO}#=xs0O|<sX\ૹ>C{c3 ; ޙ޺*}Cbyg0rk<͊e!Ci R!~-G7Ʋ6 O͚? .~!-8Vsu&ѕ?X=0_v*B:`d;?\=M~n%䜷Anf ^tXp7LfZѿb�tqiN>͙ӧQӣЀ4k\&Nd#v^HY3|O B!Kn5/ݨۨ^=42Jq%f̙Æѱwo-_nt�kM޿tP,[nv΅1p`V[(tЁAO>c7z@ܭo&O{.h@͌:͈QrH!PY[g:^]@^ 7I`@҄P\ӜT (z: &CNfO&z)ƊM?B[n#o*iܱ$;lG L]2^֝2UDŽ>vh/tFMz+"L$7gh߮z:oA؃CHYaTFO Ɍ;{?`=\0BZ Z&(GSRs@MQйɉެf~]c5'`DR3\HìNlcXr.RDB!&ggHh4ڕ'''l֌͚v"d֭;uOLݝ.@HŊ:k^}f&=#ʏ=Ɯh~}Θ23g:ԾbLx]6Gի,g$B0I |cl( =zٗ(\dB;GL='W�3)@rUz8edĄF3mְQ)ph3eu QM\(V:٦ƕfh3~ TfATVuڠPL F*/`O4d3!&6t{ou#j=6@J9?tK;4cR\*x@e9sfDF_",paVr*ҰB'VhG>v #{ѩKU!GG@UU=Jz:@pPNNu5 BBrx_?#Gضs']ڷ Q؅ GDl�dbܺK�[-Am{Vw ۛ~ږ8iתCF <"KT(0a@nkě g踱(A(Gq^4Uk9ǿ2|4q,_z;'2ᗩKƔI#ux}[:EA(np#ih7&7PÓGϱ7օѓ5M,7 77gkiX:ŵRTV|?,HSЋ$nWEs/ 38AdfeнU0kmfk|,Ү@C@L6&,fЧ1Go�,>KYe2aNA�rB!& #Q޻iiDEGݏ?k^�tn{ΑcXd LNzF`]#wkNEUy{X΅YF<;t(1qq֍Mw�7& '%5CL?w;1qq-քn&~0r6�N9CFf&b1Yd 97>+Qy7+jP_#�= vcn}'jG25m'-awX(u,[Fqd8wŭҳ[ q C924 hLs=tjBh /b1iwN4I<q*?Vh‹>Pەuk#>ŧLXrr+5dd^ =UI>CɿS48݃q7 udScMQ4jFÓC{2wV>{9=PL tWۧ?ȜBe2<a~XXM̀z5^1}ҮG#3+ 7WWjLx}FO xb &mrࠠܭիz:.]B.]٥ }ggGDЩO:UH@@͇}Ƈ}F4nЀ͛uNEp` �Q11�tܙmB[LzVu%Rv-݂%ж'MX3}1G9q5 Қpl2GGޟ}pyfo<FsUrqV�gW^FrTh.5 ԑU-K3*es[sĀ�N~wQ{ < Eq \['K!הb@b)`!$@q8r$WHB_}ggf79.G=œ8fW@y;,%bTش4>'Y*Np{4@)\7BSJ#XT)y=|t1w^ ;++ٰ�&èy )+|XR&oFfܢhs@TĄsߞw_y GcYEBʗ-7+VдaC΍vv+]C0sҤo('_:r}eFzذlY Xh~^^dup�U%_޼kْq̖TC|6|V6uyrʧ2t~ 66888}>/_h4Cű"|XYX( ƍcH>(^Ϟ::2J1f0F##+ettTU`0Cg7؉T""c1|=811?Hd70-]女`W0k;uEt1aנyv <-ZtpKTbysy@ 8 r.2Q2/ C<OU )rBMFZP4 aȹz"bvT-&cSV_b~g4*4|4}&rȐk/£zG.kI|t*3ӲcC'?YQQΕ F1VyC7u\yB!D <hB& !H7)Ƀy )m R!$CIIB!B!H"A !B!Bd=ĻU ' !B! I!B!B AB!B!$H!B!B AB!B!$H!B!B AB!B!$H!B!B AB!B!,]IB!D VVIMB7)=>(H $!;vq1OB!R2OGoB[IAAIBm"͓B!B|DdN !B!BdB!B!D A !B!BdB!B!D A !B!BdB!B!D A !B!BdB!B!D A !B!BdB!B!D A !B!BdB!B!D)GEN.I~N"O!B!5H!B!B> OB!B!?0OE|~w#*%sQ�<ֳ5t'.6澟PV,vgvjX_9Έ`4>3[B!B!2 ד"F~ȣԜF~A[k.²p#P_Vk"➎@t + B!B!e@'uDV_4%KdTӯfVqƜ;6/+hAɝn!B!Bd\'EVb1[N)F*Lܻg6={w<3g/u`xdCVs<q{gIx&rK_`AH)ok853�Х =ģ̳2p�yBdHCBɽ\}HzJULѣY& [d?'g.YGqTSABǿ(FAM9^ zZ- Ъ#'בm>q=wP * [0ztF1#0n$m !ү7\=密 XXۚom{ٟē̳2,3qtށ0JUlv-[RO̓ϝSX0c͛<ټB׿z'S ND޹O'wqH&vn;3ԪR!_4&o!Z r$wD.''::a% po@ظ2֓yYW!)3eБ#^ ߫tv6O`0}.҅O(W }::ڼBӿ(b5r+._x=7XY /ٵnr]<cvEɊeNYUEyx7{4/.3vQN =3{o6GY?S1kyx�o,ҖP| tf I:pk8[zCEυ;p՜ xψ gm3G%d"*ԥi='}7 m t gƭV 5|=Y? Ȣ@Fe=(붦G5Fv +BQQYwܪ{ҭy-M̶4ޟѲwOxȍִ<ԩ!ONvQ{0A@�'+4 ^My 6_jn{z2{Sn`Lx"m<i8*xko?;BGiڰ!BB3~ˉShޱ#n^^4k׎#�L1}믔Zgϟ�??k*dٴ%EZfXn+WRA>S\qÔwCzHEooj7i Ly.i 7K5q'h^~mZ&I9`��*WfƍKԉ vb{<!tfߩm{/^PjUΞ?oJkL1 h-[@%__bNBBCBpdzNNBll)?qSW>=BUU6k͋C^GGSxqSZܺ};YI!x5Hzx;QEQci4uy}Aѣ&=1u-K&ba�ܔWKNh?eԴ>:YR=5_/g}fgn@37IJ1 cļ?D>cC|I -YrO*'pVbWwgEp-.\wq7T %R'v (g.6> rhYbލ@3_,ݎ@P9ƶ ^ʀW10bVtǚtBҕ 2ViBf^P4CYF~;1~?քr<W;f )o�v>W-[%ƌã8~wnYh�� �IDATX| ^Aj7,^U{u, èd]_gPk̏ z`޻ xg� r+|@U]Kx2 {>j<=ÆCZ#PHǪ{;B ՋX.[f7ڷ/eڵԫS/xTʩ3ga08t�ׯk?p~`٪U1V=[6뇪ѩgOecU ۗyK\|Ŋ~rÔ3~sx,.^įJF&0Pؤ)oMh(ta%(S^rm{rY(UNgpʜ8}�l;-^A]48Ԉ 8s<_ϙ9s_͙c+ɂKٱgg&WΜ(B`@�K2/�dlJsxwy]v *HY&ek)ӳ< ʹ7x)cb\307EXەp(D>zƜ#8gUwM! yS//e�4X{2[!lR P-7~O} 뛵ն ֕`z_| t3_$`)M :=Ʌ � VV~hԋC?vǫS@zq`]=Uk.5) փ#wl}1�#Y.?Kg(ß3R+@Jz. ,h27_,plVω*M4j[owlB*gЭljW�ך�-9i C[`ck[ ֶ`0lS8]Kӳ#Э3RT6:d3^tw!!zbԩ4_|SImzzҦE � i{{>Z5mNŋ+Saa43N<'%K!EqMr99QR%4 g^{� BBƍپkukdbtm}nQT)J(1cq)?5�IAaY�6kq!3mMU~$]:tБ#TRgr \ o1e�^/vAATҕ+8::s ..�ٓ:`,YųgSՔy۶'6IyB=H!H5Ϟ>r1l$ /7x`P- *IR"X�АF^Fx�VV$}oڰ5 :6aF/ 7#W#ns$*ok!i;* $ �VK7\A �t(ow4/n3n/-RzuzU\?Pl9ѡ}x*zt$ƃI_V XtD<S*eː4\91sR%U83}7ZKDXwH?9BGӆ ټ};Ne̙).EDqMi )U *+GSۣKLg.su:>GժjK�vGMˋ͛p<}Je??SyNs-R~vsU?IQ&-Yd1Ɔ HmyTPtz=¨K&{{*11Trs#&&1u֬#w##y ҼCSj0ga<`ԩxUNMR;iozkqF+=#A !2G*tqKp"y3& Me,,,-*P9J4즿 ]K[R<P,bNiSRZ%xyozۋZMη7ȯz8#,a,ٔy}=zmr}; q*®x&z)5(ITUE5y�k `ho")f{܅EQ5t(۷g׏?!YFtl:EzL�pEBp̞Nqiڷjbʗ7/;6np~AA-Sӧ�ŋcĉ)|oW߱aakGnۃHuۓH�([ Eٳ  6oΎcccC̛a ílupt(ƕ+Hy;&s7hw;wa|==S{a/^"ϛ^6/^& BHB bO5>'iC{g.<A.71_\\ pcBd1^D&KF -jȏ;T4>ebcAk|L5N2- pwe~Vԁ뻱(vJ O˪8n�X:5(JųtZ YfMNEEeVZ'/EcPy_3ۜ.,VVLrmBr* Ңcb3zժ,Xt}3ˋW@ҥM%ޞ77I=-;ӤM߼I…fVfjNHH@y\NEhҠjצ^ڔ e R>TZ۞VKJXl )gNWgĄ X[ZY:`z'wnn߾M@zcbUUѣsDĠ}DѢL9Y2rx# ɉ,3sEJ- {Xh|@!Rog!T~ Y$ĢNg(W�j^\xV:Y`k'JO5Y0|&/HVs~IgUoBZb$hw\u=ޣǂYӿ%yovGi2e!׏˕(N?FGhMQ9&g6 OBB8ja3Sʷ `Ī[\:(F- TjXJE&v[,M['q+&8QWmn\4ӧ{w mNqΞͭ۷9v$ [ȱc�/R{;;.GD^�5<=9{XgH@Rr;vʵk|5{6QQȨ(FOı'b?ckkK\[&YfP\!uz %K-K ?iӸrohx8 2/ @7=>OrӖڶKU9&dL2e '.ӥCVm#2*m;vP+ /_?_>֬I8rqht۴|>=z'Og[n;@( ?˖qi.\Ĭc T !DZ'FlwYs<6tlՌ2lWGe.4Y~w{7/lC5>乃Y%]'*N~Hny4dL=jZP\^Z ZS;k`~LVG|2V8Qr|>K`e{Oxe|ڛ@|i΢Y(O7],SsUkuS f힔%e%f, 3U yfŁA Q0/6%.dgh~ 9ҔVՕ3f0k} 9su``իTI!++GVUb*cγZ5ڷnͤ3NgDGGSՕ!!d`L mXYYQϏc07g4&͘AΝ( 1̈́| ~ fh4mȼHvsIv$M ͍۷)옴lڔ8.[ipuqaѦgY >x*+ѣM'`4mߞu|C@oD̙`_C0 xUƘ bB^T`Dz)Ȩ(rʅF]'%q11}2W%͛YBȨ(*oB'<x;4!=B!B!HB!B!B o B!B| R$`H}9!,6>I!B!WA 04Zk%"&6k P!B!G,]A �;[[bcbH̳Ku:bcb5B!B0OxEQP< [;;lmh 1Đt !B!8;Hhf%..'OR?C8ω Yh|_B!Bt)mC?lllPUyEA(B!B;Ho R$)(!<B!B)7%B!B 9B!B!A^!B!B AB!B!$H!B!B AB!B!$H!B!B AB!B!$H!ġDp9̳<g/`0N7peVuCy7[P~Q+#$mP=wSD"du=<ۡ<v3.pֆ>2iW30/! OKϺzyL Tl۹< }Preǎ5^nlcnhaazJÚ0t ;z-ZPzu4mʮ4/"i hr!OUFXack(E1ۇ},7ZR6 (6Zؘv0O`ۮ]If3͓߫LRo<?Ç2l^ 2d(\f^T!Rea 8@=UEQ7o<7*YeBAb}=Z%Oo>4ਪ* @,d6/&>R')'o<gϟs0, Rٙ {~" g>v{6+-aW/BMD tuZYqݛmH|>g*5~-O�#PeSR*x֢}/~ԟnެ<<۹!w�p\n gxK/t4\t=pnS׃{T]̴M=CaY*|ɸM*T 7LeO&BnysInscUG2۟x&x�G%d"*ԥi='c7nH<33 z?�@'\Q<c'kǓ9CڐxU6ofՔ|{"I޷h*_|͆~u &z`'47O_M䁹$  gƭV 5|=Y? �c75>T oo֍l} I\M{W OۇCjdYrUrkqR8 h8BPPד5?G}y0G> ~o\[&:EIR;?nCh%qPc){TE}#włPFL[/i/.TUR(Jd[ҮXʂn3O= X׿%Gqm<BGX㰑*xjͺVݓnkq< lcs1@+T9^ޞ8û% GkBsu;^;w&>$E9p ݤ 7lHxJj4h>>tуk7n:DVpQV;pDŽ]O}|W/޻g 5Xa*Wᅴ|e 5K>}vxbjNr)"R+se5j4 f-X?kbւ͛S7gO>F,Za^f̠k߾WJWʳcߟ>'NyǎyyѬ];Or-Yt)�Ǐ)YXRŋs5Y !DzHB 5m/<33; tdI"wUwae#$'jSz kLjhҕxR?c;+k1vJ`ϼ)/rm-:]D>s'c@3Ϣnb�ln?,k�lY>* ֮%<o F3xtgygG�88{zj՝ů�}$*x4vuɱ3ضb"~K;&�QjRǷ*G}xt2ƻF~We>a|Ŭ~`l1"+Y_F}? m{zVi9a2X+ l: |n)֍'2pOo ]'ĥ6te̺U3 3*-đ_1xn_*Cp#ֹ vxL4)Rk%GZD&3(wy ʲs Pb<kgxl^"]fu|0r~4˩bw6[ofݏn?S9֎m{er˦T@mHk}<=xy3~r~4⋩ߞ7sdLŖ{f`@GY:ʳe$֞6FnfcЙ}։Ӗr>?gR\|xüv$^=tѩgOecU ۗyKnVbl\ٲѭ_?TU^d$} El]u?8w�0qtN:ٳٲf V =ڴ&ɢY:v,?)`w1obD888A 4םx"8pRŋӵcGmnʻp/^dEڕ%+Wr̻{ @\شj blIVWU9u :1?, #ʈy5+yݸA׾}iT.׮^:|9p <0Gtzv ~)%&K=dիB RYە`P I|9޸1nB|tp}Nƶ)D9T-JQ2p}奬_*qzX2;%R+ok:ЧJҶ QH:4<z + B�k�hjAþXЭL\RP 7`J$^Ϫdu59ÿܠVh{֣^~w -MyVFaM`!7U/c^Ob8,_N{jr1 G 1`CZ!E 0pT{6=ΫvX='5JYb4j[ %߽~$^Hya.T5Gd@nqV½e0ή m)Zpc^nM5S u`!N�P;5>? g«K_5KUH}S!նs|v!}J/YZ]דܜB%kYig؋K_]pb}V-eq_OQׇ5hXi^a](iC2rCdwX)JΔC!m)Z JB&\|*\yt)7[V撮<ˡyok*[BN-I*>F=깄Լ* 4[p7c@/u.EDPo{=pX₟77f^7n$U+Upmϝ{tԪQtnߞ.Z;iٳ)U :0s.뉌/0r0~)n1_?v|j_v튏.. ͛\r%u'h4ف`ii)3x"j֌yrʕdKu>,7'L E\": =QߟpI>)YiUI-(L6m(}L닎k>quetP)/>> (Jϩ( B|B gN6QT<X0܎VJ$)V h,S=K�� �IDAT.lkM5:x!�8i5 :Խoوb_Ό0xL3.cOځg-g/{56E[K5zjӲԥqQKlNm:lq#Q|[I'A@+)Qʵ<iLǝ&,̞nQVDJkoa]IgQHt-ǝ[^CYkmN~X] Oyd"D @^\ʐk/Q~f*`QL\ȕT�@gx /vN(^Ğy~iI˿oW#nm'mKgWn6KۉĢ`qSZRxzr>Ac` -_!:Pش\ZGZҳZvNh,C `kcbk&b (VV-3B9:^ExM.րbel\(U,t.W#{.axzD$$$=[6=<غcn˳u*/o^).]“OgJt8 `}i?//|hݼ9�V͛gj4_+++�r991R>̓'O t:QT)JK111ܽwf՜9tHjx{Ȕ9su;cc0_<nժQߟٲƆ~٥ -?DOQ*AĵkTL#"!>2ɎWsGL; m꽩h@UU\^!HB 'cf.} 7h`CS E?cb0b`p,?bJ�6v(_-7 ͆z@hs$ޖؔC"`0ZڒbR!F6^|52gO:V%+`,}Φ xz~FrWI3kڼ Qj`fSg N'y!g&-[~J`nZMlpǔdK9A }HmY )ßohPP"i EV򹬪A5_9?/wCoANSv0P Zz S;:3Ԡqz 3af(^3'N4XZˎ5<_e`Pe˔aXZZx,.^_~a^uK#{vFOē'OX2kt˸7;&gap+[6EZG4wKׯρ0<H, yQs4<EQP!gĩS<}֐(4kԈ[ϔ)vvv/)SX TdɜfC;^|Id !Dz .Siנ<y+ZbcI^ᙣ Oo \UdQx8ȋs(P9Qup,lV4y}RVBh>yŕ- i e..qG@q.P�ș�9y<($TU�٪ [pIBBYS3T,nùHaMk?Raќ(ԕЉAwZ.Pʴ9r&#-nȏ;<ƋIMD_y}NV}~!=䯶YZ\],ˏq z6^L~el ٻ$=sycikn*\<yfUmq*�46ĩۧkw*p+-"r*$</l=y2qqq5/B…}Yf5ܹr#op<ֿ?K\yGa&J(A/`5DGGi@�GQbcbLuqvFQ.\dJKHΎ<ssmv9(#vvviۜqfΟOΜ9iȲyp\ ~k^UrY<�^^,]ʖ. }*ĕW{p KO;wXf̴+R /&x E NVJ!׮ĄP;hIΟE?fϬQ$P)m ՚ 1Xuql?--nuOZ4a{oĭțLC[wG}j|ӈ58 W%IO=5k9_%g*�msmM 8|-՜_ҙOftYu87*g+L?p}B&nq0Z򾛫$iG1)UHh)j0pdKf]-͕uDͫ3lvν;=y&}4ƅVmIz.ܽG?KD2k Qϰ-Fbi"=mvH>%mFܯДy6y D2aR,m";-[TaΩz`:-*X:?W'c1,*9?k^p&lO\`$$x",k6<Ëm4%Yh3vCllC[&YfP\!uz %K�bI;yȨ(3Ε 29$m;wu>rqPngٳog<rةS ?uSg0M~.:j6}QQl۱Zx2uoΥx3IzeΔ72c\޻Ǚs爸vYW"ErD*PӓWlֱԮ.\`ܺ}c'OҰeK{;‚NN1%+V&w�̃a?_`ܹܼsq%"v(!=Ȁ\0bdKOpcfߦG`f"|>.sɥg2u4>ETqQPؿYi�.T%^+aw5D^0a.孹˻'X~Aa,Y̒cC'R|~$Rfe{fg^褁%#j1en -%!+ǜ `R .q~o ̯OȺJ+S6Sfբ<؛9z`_X2h5r- _./-m pر, )Gߩ앐ֹq tKmgƻ!O_m*$]g+I~!qG)ˆ!sdq/_7\;&C^}ɘHaWEYޓAk(e_f./ygJ Y2x3Ȼ} _<ğפ~}V[Gͳ� KgfRHm;wʊZ~~t=z4|8queAH^hrFOD\ֿ|ь8ν{SŅ^]ʕ̙2168ѭo_K]MMe?m..L=,Y\۶eȑtۗ}oٳd,;͛ɜ)kԠ[NEMWM ʑjU:\]?c,`7ߐ3GZ^&Y@�CGfuhZ|=s$3's)3g:4<s3u8BT)/3~p!"UU1 Đ;W.E:޼Iyͳ0�]6V]=)]sG'fnjy aN[ޤwȣ C_T<nݑn5c3$=>6?;Npgv~HU4coQς{,b (QQЋXNݘb<dWxٙg癥}bl_JKKu&Mkeo{UHՎ|MfZ331BR|7.fcpY 8y݆3u4p A?#p9 ~@e;ViiMсcՄ.n;3|֬[]<2PH.H!)2B`;泹vX[Қ 8&s5|+B{|៭sW^�<C{pswOŁDžU!I<{gّ$I>vkRv׽I$IH0RH$IH0RH$IH0RH$IH0RH$IH0RH$IH0RH$IH0RH^-~/l$I$fS\> �o$OI$I2RH$IH0RH5sk/z= eWLbL�FPƯwBCe}y⪓ P<z<*?G ُ C=4ˏey zwCg#C)}K<4kpC)O C~}+:ן;/9S)d".ܗ %yf~$I'#A![Z z{Vtf͗A9!1=w3?<[>n;]Q./bs璿GV۫1v u\ ~Ǖ's~S'PՏ)ӹü9/J.gut3x{Iƕ]Afl6f2e3}htH$I իدKmZuڇûdh2,C�SGՌd3v(zxK4iؒ|*|1D9'2ѭttnۙʜ}پd1M|[60hun+kR`/~^A'1s'~O;iqRI! ## {I$I?C)v&1y`ι5b}9~2e_mTc,5b4h^6,I(DF_=/O*keZzsb��(/+~7�)iݹa-u:g|nu>zGn@Y=|t=2H$I7y%A1[g=žG_/8ԛX9@q�AU,(.#x'x)~ηi 0$ 1!@ $IBp}/b;|^<2ڟ>�Uo+Dd3-RV4lp`t<(Zu( !,*ʊKh]:[ۼۤqE+Jϭl-ڵb_]"I$I_3RH o/ˇ+Vo[�b ^>ã3>nbā2ҼY]^"i/>λp-/Pc]_l,7,ZCc7p|15Xm?yS=W@@NVa6|8+w/I$g{RH.sw{9gsN* ۝~s3Yۗs~m!{o~řvp7*?M%!,~*Ơap3)ntcԘˡV7\9*e"b-Gnͨ;̞�57)ɑa7$I~ނm5aaH$(.,qoYdrvk4yF ·C%IVѾukbAP~$IҮoG&UYv-陙~l)I$I"H!I$I"{RH}Rג%IJQzJ Iii~uђ$%+)-%#^?#$IOPdgeQPP<%IR"(H!IKHP!I  rsv#$IOPA@ ().f.$K<6mLIq1 4~͈o)IXT6n̶|糾hJv{egeC<#)$IcU \CF!b_]=@F I0 BT%̣B$'.$P!I?_QɌ$I?3Q?A$|)+*. K~|IKO%#=-yZ$ #Q IM$,ee8''xoq$iG]Q~j'IBjj E%$I~ EPQq x`HO#(*.I$I5H!EPIqB"*#=aITRUTTx I***%IR 0RHxHRsZH!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I_(//gaS$)$Ir} N:Ӓ$$H$kDGy 0|p $IRJ I!H04j܄ n ۶$IR 1RH$}@ѬY3 ǐ#vM%IR q$IR@Ѷmz}aCiҤ D"ysITCB y@ ڵg^ 1F3v죔sZH!EP<<yXU;gϞ<p 6z1G8㉧Ǔ*Ij=JKOTJҏ%HG֭]u#ȩˣcrʩ~zpITB4!E%Sd܋/ҵkWͣciԤ1O=$'r 1ydbd%?\$Հ`[A_0 I$ҸQQu%˗[Ӧ[EEBbʓaTB!u!++xγr*ڷnM,#˅$mڵgf=H˦b***(Jҏ/^Au Iv0#qiK$IY*J$I$�#$I$I#$I$I#$I$I#$I$I#$I$I#$I$IIѪ�� �IDAT0{|^4Al4!dg1A-yZ$I#Ag@dT> x� I$I?=zu_T>W'MI$IH!EP]#PT zΒ$I)eW|Β$IH!I$I"H!I$I"H!I$I"H!I$I"H!I$I"H!I$I"!%y@ҮmVy`Vƽۖ$7$IH3RH�<fO^-߇{n;Eޣ8;I{7!$IiF i0AL{sJ~A ҇+9d6h]28tڳ|[SbI\ut;Ɩҗ9K-;^oG'wߏ<b2EOA$IjvQUֹ 8v4l (\&=2IqT[(!AizG^]7б[+f+"+3w`F .)>x K$IR3RH㗳ፇ9kP|5,) 70{<eao^X^Fpi ܅tHPm/ޝ8L[SL8o-I@$Ij=]XagagitCJֿϠ15xv҃M\*ϣU=u %q4M�5ulI$IiF iWu¤B ^γpY<jw>)_r_R";dN3g%{WN}on>$ֳ0dyy!w:i>$I$`.vQ[%8h;Ƥcm_)XL 4ήŞ}5x岍)[=n ‚Kϐe6NJQ%�B$IҎ.ji<$ҏ/:0=yՅ.䠂>zk<uXR:nXFY X={>3;#q!�[Bx91<.;aS>^G7.I$I5/VP;aH"ƍ%O׈c,Yݚ6M^}C.O/K$ +W}b1$I?mk֮%=3?C$I$EB$I$EB$I$EB$I$EB$I$EBpΝ]9K$I#A9Y+zΒ$I)rРF+i9hP$I$}/)v=)o/ 6+(49K$IH!ET|/I$g$I$)$I$)$I$)$I$)$I$)$I$)$I$)$I$)$I$)$I$)R $I^HόR �4JJKf%IZIi)iiׯ$H!ը ʢ yJjdge($IJbjX^n.a"vC$;l/( L$M$gH!ՠ  PR\̦͛]!I*xlڼb6hP!I< XT6n̶|糾OC%+EYYňbF I)V*rGnNa=%.b_]=a$)4 Cb`$UG yH)$$P!I?_F I;F G $I${~$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$II?L~aa$I$EZNffN$I$)$I$)$I$)$I$)$I$)$I$)$I$)$I$)$I$)$I$)$I$)ҏRk򲲘|N[zɭ݋YYlyb$N;K 8m|>F@ã$7+,4#a̱:nnVַ9Q6Sv& (A$BhT;ݛ3_Cb=�WTNnt%E 85HFu}Lq}ﭧסҨQ+nۘAuV6<N,ru@ ;UYYkZtOң{v5)~ Wq Pʀqφnuz ϝaR:p$/NG: �4Ñ'gI4= ߉#!h iUK$U mh+Ƈ it߀ʳiyЯL{2!ϣɆ8n/X;MfӹoZ:A8FIl?oC8g? ?gѶni*߬65ZK)73q݇tEr5_sdd8g&`%nLv%F i'W'Mɟ,9CeV<uSzśikڞ1sa<q{k@\wѡ۞Up<;9})@3�GAjcT*O$IO7υ-X4:7'1�ҪWħ|7m{ R8^7Wjt86݊g3'S࿰> S8;|O>SNaM(5"Erd'_?=_Ϛ#X5csckz&{Y˒+iFU},iWaZv]S |n"?(%}T ?HjR?|wHm .; aR(Qo:WvP8z|17<˜믧x߿(I%! ޛI<FML>1Ș'<R`Gsh/~iG QgĽ/t p A�0?>Z0n͓8n@-P6-ŠV%&x{tK(J i'Tfa</pyFZK6 T. ߶Qv bȯ AvnՎA,.[[VX3[Jz~$IOK+#o�~߆t:F*#E9!"{#�S)ۛ2 3z2^ʰ۶R~�mj׮Edm;CяosG~-ԮSapj];s蟯_]J:WpE#o iNRRrQy#{5/?a) f1 ;'6oߒ-d_$i[[7dծ?]m[,UC$nXj:&_6 o�x:l+ĶR@dΦ0 yRشi[ɊA,'-BHlfR쯎P]97y\vĚT?-ۨ$jW5g/dcQsՋ|zIT.Pv=F i')* 9s%Frh9=�}z7,-ρOxuQ)'Ч[*dz*7yZ$g_?>So/'!EfеgwUjT A0tjцuOO2eSַ!Bxw$߼=3k뼻)Z0esȆ<H}38~lOS>�w!\!$0}<A'.lO^#I|X(=Ǐk=u8'@>�_&`X&<?S?渫/kr 2�F^v,'fUqY7ѠQ4%IOY7!}1s<>^']ok˩w`0x0> ; sTFs0LړNKykU}ֿ";*oMqw';FpOsY pZ1B+ya<r|K';!d O_P*Rѹ[{'vUF i'#GapQ!i9-^msdH\{%;Tcu4ʞίn̾3- >_y^@{BŰđi4,$d/[xֱt>4z8 )}/ryC~ rv\y ~yn4O<7|j/θHRo:8/uq#wT7aw2n\t>2 \:gBҩ~̞Ryil+(ǶOP$ iܨQt/,L$IHLQk֮%=3X,F{Ѩ$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$I#$I$II?̆[$I$)r23v #T׫<$I$I/C$I$EB$I$EB$I$EB$I$EB$I$EB$I$EB$I$EB$I$EB$I$EB$I$EB$I$EBJkiNMWOfԀ;/JS49 S H$I@3m#w_~ BpYpkⶐ[o{rowwWyׇql{t7מ@�Mv9W/,'[p%^)h^yȆE hط/�%${CI$)+|ivr{<0ro.fzir}$I RQ熜=%o3q0wK ~<.*1\-y:jO-?0KQLTF I$)YxՕP]}=m;ťA|ETY֌5!,;_mfn&hQ? TӸ~g$oCa<KJ i'iU W1">|T KЩq7To? doep:li `S~gM@y:}:m!d0q])7uV~>:shۆzԪוs=m ӳ^?pOvv0g^Q-/ˊߡCF ?-|&u8{p$IjN xH9iV~RRRS)/!P{ccVqxi}NkZ4q>>@X>}j k<2V1S(jQmm|=~t/E>чty@ep̙5-إ G =sʽ i17TW2xv9kyN>~|8e2~2=0 W/`3w{q{z&jG3];7bi�_{ϖ΢Ij1hABj^/? ݣ?)kS0J> W?spө?;WRH;I:W)Oe@?/Zw# r]Z<fJbj5lKrgH~31yCülCd M~o[G++3쓳^{b |]*MeS98^@i&bHl*A޴Ǟ??K,* sYߨl$Ibe1ʀ{?H˷s ?�&khP ݺub|rWS>Y>?lftϪq{?by}z>Yxõz:#9E^Opޯ͙: ZE4jۖ9CXg rb-'y1 `ΊmnXn~Kex¢%ּ`ɻ1'N}Io6%p+x +L{ 8d#2$6'FcOxg%_/!x >*KMgҕAx%Ӕ0M*k{ 2v/N"v S/3(]N-cg{g[럼o>UI Kճ-JŬ]RXRbjdCehμ:9*VQ^VYshy$;64s7U,Yeŧޟ/99|>w3�C<u6íyd9'%ر9s'?$IT*7/d΍+Γg7&`ܹ ѐX:}9>KZV,3fh>qְF\pPN10O9v 8.i-&}XUb=sw8a$6ᵌx*ٗxi |p`^z.˖W̜вϙ߉ 0E7/YDV~,Y9ekH[=6AlL/c^�^*3yp&{gt`x/l*C*~z nSknb× *ͯ<2X6zv82!Τ٫SR^+bQgv"`22ucҏ.^Ibewp!P³d°~Y_o~zm ֔g4䤉_ǜݦ5L&;Q}^[7?I8CkzRPY^ѯIIfCRҲrVlLVlMb@VFU/z*l*և!zf0ꩱ6?ս6 $Iwq`۱uĻ<?g g\z=۟DQ㨉{WUz<w/hލ9sߤOC$u4m֌ 1 K@Ɇ tW85�b=2RZNR+I!`Krݫ)�T=QFp+}pW؊˙)GDI#hҫ/Wоo[ӢZ 'tnKz3֍3f�1.Y4j;gؓ Mv*ϱ}4ީK֍,[)=[b Q~5/KMw?OIIeށiׂfR]11Q~[) +Xڦ]=(뤱9a0c'|B^z.2^8>O?e·pQ\%,ZҴ\<u=_>6@_ 18wXOb_5qjw}$IթE:mԾ o~~;>\y|H鑼R9KVod]o�oV'B&Ie@GA@7f{H!}SQ@JZ@,7lmў+lECќu-ƴr =>Va qf_ZBiq1PR\<-Pq%X� +d7.⭇*9C1} : iܥ?@F tPMש)uYvƍo.bɻ㹶CƝ:>1.XxpK L1撋 o(bі]!Mت^ ^%(߼((.<A4l̚0uԆ^:mւ z_$I9[艽 PV<K~ry~<޿9<oy췿弳㽲,C˴- ش~-UaX/hz Xv3POWqV$Ҡ`գYzԯW99K'7t\9춝اv9;ޔmR[%vK�B5iAe§ 5OXy?X-Ԫ]60wm J+~YJ+V߸z,sx%Mlߍ ٿYXR�m_4ߗɟ;%[Oߊ \2ܲp6YD^=Yp3AM!;nc܏FV4&ܾ6cnBJbf )Kضl qB* ˁ:fe|kjE_le118p`/&<9QS�� �IDAT,Q U\r>UW}H$�]?Ki7^]0?rAJ|oVѵ`{OWᡶ6%RD^= S?E@Ҁf~Dv:.Χl4سzx}?}a Cy5c5?_v:X=zqQ/ a�t7&밖;샴VnRF3x0Y#5�~ 7UH xշ=b{Aj;o닯_+/kߒ8Lc駟ӢYSjeM$N@n ݚ@P ]}:y�MLgXg hù"=gwn;0RoP4:NӤ4(;u$OM3,5d0i yy h}Y<c*6nOPûsKeC׍ة;΂�.EN)z MӾ>:p0 I>gpOzIҧ\�+ޞSv+"Q;>;0E8h1OA%ނ9ͫ?u-n9xN<\!mެ_Q�'wL!unY# z�:1@N ުGvmQ̬wO�&T=giU'4sc8Lcp0-%<YmF=xO9O⎿<IZe\ޣ<||n_~rF7| l]H$ {Uu$H#:R M@\.`կSյ ikRB%!!f34|<9{sι%OqiI8y1@+XDdQ#: fwyC0<7)Ixwa\K3䌼|0MbMOL ˬq%ĉ[Mh^۳~xCX3q{IDDDDWuXת:]wSбb}/5ͤ?ͤ8 ʙxwm&uu3G ޻"""""F3)RH! )DDDDDD~TDDDDDDD<B  )DDDDDDD#(BDDDDDDD<B  )DDDDDDD#(BDDDDDDD<B ^0 DDDDDD<Zp@{wB" q/ȯ"""""""RGPH!"""""""A!x"""""""RGPH!"""""""A!x"""""""RGPH!"""""""A!x/\Z.6y)Vb&w Eʁ_g$zF9Lx9xN |u?%vs]rc~6սS@7|H Il]89X8iʪm}vRBw`Bj[xW_eVųLؽK7K#,2[ qA|r. Xqc/-w)�3½^+<zwokRY5V=G.';(,ό ^/2,.L{rӾ=n ԯߚ[yS,]{9oydoeHpKw"1a핿"`wzIY^\hMD~3� )ۋ隹 ܻPl|p0&7e{_W>SI8][m vS?`T|-+<lNWʚ~U_%.n|]\Ugi:a₭lYB-$Im|(^ؐ__ˠFv(STʷ`Ȼx:ٜ=WR߯'4% FVh3iQy;OͰ7ajmt'&-!y5pu6U^ zG_ash#(o<=U޹ / wsMd, 8r>]1\<�,,&NsR(c\<&tg�N o?Ϧ"`gF̌yJ x*3fyd' diHNڵu z=V{D^VݿUDDDDt&Я΃�A:U/'xa5!1~�ԃ86~<<|A1&)eͬOx?/=QɔȬlw>_躇xs0_ǛӰrĂJ|<'cGϛѬ3Ҳ *f |;qi'hk?Yi9`7&=2jX u2n_T7�2Ja09,xvƌ9; ֖X<<[6FneOd: 1 l3eH:ɂ|xc߇`OʕPB ߍhO@|w}Iކ8D $Ќ)#Fr1\C_={t3F6ܚC,^08/ lƓ7 CRdY1\G*G,;~ HЧXz]NpL3(ҽK>2g&b'i2mjEp}JuN]QDϞč <تIqUD-winGm\y?+93YN^,VEؘXsԢ}.c)صXGR|50O[E9bk׭K8۳_uN@ N} pߠ{d^YyWfc�ic gV6tu;|}CIC~ZU^GTD7ć`fl4�{6a|B"aƆ]}z:-2>mxﭵLYU-΂4�"8$y8OԾcPKeq4M Io""""re)F:ֽy[-D7i t WIK_JR|z|8La7^�s?#׋3I||9 ؐ$EyG=>XP;;ޢV"dS]�noZѻ{U8v`b�rgZ|6}=wsKLrgMʎȰHe˨ VR׹_+B ߑ\ƜV}X#~m$,ӨaU/ qcM`+jgw6.""""[,౅əp >ƣܻr`irtm X"oa`A6f;Go,y_G܋*BZ - 8S5deӦE4bBY8zvѢ|/>=x87PfAYI XPZR\ m0 +. 2JwHD. Qr!j 6{$pbNbm~9։=$B"+pX"H,CtjOF8ZZ>`T#""""W72J;NOJ $.[P=:f,Snja1w,(L#X#3_ P;Gjldjb/:LTh(Q  hP/0g#A b֐U6.xǹ{ɹ7ubSvceTiǪXmr6J||*H?PFx? B лA8V,ք[R@ fq{o{:ȍOa>O0cߙKDzukMe4=M23i\xֿܠ\L$?ʇ_¹,.窢 jZ屚}%fuNm݊זDK˙n(T<#mdr)߳~kMw/דk yhV>epbmUc]n(`֣  ܽj]J,9r q%',6-W3|܅U)8z'̞J^^u Kfѯ?w=nI bO >j>̝5750kp. 3k{eEWtZ!G0f}[(x6 -BsŒylOj&5amgﮤ.@pR]MwQw?MnɜY'""""W6 x{NERxj{f wgJԴ,)Ƭ޸J[IM+Y]?q)ͯ4q/4}CNV" xƖdXH P�L>Qv tjd6{.Nar RY1{hnAtҽ`3oG^p#͛/b׻_Xr1M"h60H'9xDX8s>?e@z5}S" y‡qو\A,rQr4v_+P_2)Ix3#.K3䌼|0M=~fR\fǍs/]6k&Nt/rX:]wSбb}/5ͤ?ͤOU)?""""""?SB =CDDDDDDD<B  )DDDDDDD#(BDDDDDDD<B  )DDDDDDD#(BDDDDDDD<B ^0 DDDDDD<Zp@{wB" q/ȯ"""""""RGPH!"""""""A!x"""""""RGPH!"""""""A!x"""""""RGPH!"""""""A!x/\Z.6y)0 m6#vn?.~G{`˽/zyw)s?LZqr,, Lj2MӼJ>M0k."""")%/=jƻw _x{ \wrc~6սS@7|H Il]89X8iʪm}vRw;!d hlP9X?/a H*xז?˫1N9(*=ɱXN0܏|NǏ t9Vqf Sv9y;xiUSf3u=c!.6[źs2teq.`FwkeG ~M*kتve3+ѽc]Z͂75Ļ8nOi߰ 3 { wrY52ˑ*k-{qӾ=n70kS,]p-< 2ҷ2]8K62,/[kܻowo,0~O /B P̀zqo49z2J roS8^A7Uk@!Xy{)؝ ? zEՒ&|;`?՟xӉֿSly3%-ũ)(̦Aɨ iٱ?N3;)c8wmBwZ\7X/-b՚'h\݇;4&C?"9eU9JFyiM~7 reݙ<vBxo["'s""""X:^ *k^^>`U!;['u?WpUY넉 e} ̓$I�xaC>q.١8B*OQ)߂!dsl_I}2Ӕ�YeͤmZFu1hR? OO4M>ܶ0Skh0y;EڔWy$OIɢݎxXLZDWy6\҃6*+dhnno� `Rfnw [pM�𶳰 ^8KYquX>m:a:'p~ӿE<1 2`vh�sۊ~Oh;˪tr7>ZޭMD|?{Ij2SJ?cIh;yp~;R?�SV'{Og/癍'XЧC[#yxF X�lp5m'?Wh3YuIs[Yw}WwDDDDpL_K;sf"ț=ރڀYJo9Lw{&$&6b֓T\%K=cgLGcR{Lvw.u{7Gu9; x+G,x˭4șC{2vY͊9ӈ1HH -�bΝw:}cժ^9`7&=2jX u2n_T7�2Ja09,xvƌ9; ֖X<<[6FneOd: TOgʐ6t375'\Ǣ4+!�ͤݜFf_y hձ+-Wl&:K߇\X1mT+ viEոU6[G6{\uhd;rn+6I>9Vz+sxn x6)AcUͤ>dL\eyde1U1]Rq ;VR˙ ^G<gc\hT5t9p{Sf-|ڐݖFT\)o"""" Ǝ_}7t6.NO[pL3 >ȽǑ=6q;M+f;0o�)v3:F0ê̓*:lUɗ*cSj~;c7#X+IKym7d?cF/EZL"ډ]_ 0VUؚwGq@g*|Ы6q]Iɼ8:lY;Aہo(ᰬg?zf2}k,K6s7_7�Y3㓗+ :<س1m*76 |{:"["&^#Y(˥yfVy\I񁵡u0_(ˢ˫)YpT�0! dy"�B|�/B} 0)sZ؜Ɇp\i6.jLHDUO2PZ0y:b2�/:ll[x(\/-"""r1#AGHxh-uRL:+щ/%)K >yQQ Fl&`�\Pz0Tbɲ羖 8r:ٙbWy>='ഠ$EyG=>XP;;ޢV"dS]�noZѻ{U8v`b�rgZ|6}=wWC8rgMʎȰHe˨ VR׹_+B Iufḿzb[߲;g!{S�"ք¬vv7Hor3YY[\ddzHplm8ފ'fn+i�o?lc?"ب>4} ֭eî]K;!ŸVp9K""""xLy\oQ][94�BXZQwY,s7 h00s `7pY#TY-OFi"C1\IhQg~i2 JJҒR*NXlip~6XqY`Y֯NҜ;>K.΄n]RJ�3VfCY&xGgOSxZ7j��@IDAT#.\%&ܤ]΄׎bsXK+l`G'v,cC-$*YϥٵrOv g_Ӵ8Led྇ƯuiZ Qa5[H72J;NOJ $.-(L3c0u;U ekp,Α|,3_ P;G?nldjb/:LTh(Q  hP/0g#A b֐U6.xǹ{ɹ7ubSvceTi?snr6J||WO?PF~:$\^I!;3,<yM.^Z2} #鮗 p~T+/Uƈibx2#8#Aatc`Zl1OХX:wl7d4£{_W!7v> B H/ {fmzBKp]+c*|Zbͩh W}xxֿ֠\$?b2�{?Vs;Y]UE4o!К_subnko(ќi+Av _ mH ٨<Iвr_pw/gq8j6 o75 mjLC0o \cĂ# D?ë)mו;`U<:] Ҷk(ߜ dÒk][}۷-twE̝ hbahQ1'|ܽtRx6ص=+x^Ine tp}פhV7w`|ڝ{X&3RGhcѳwWRpb3L`B\w$u۲Ӥɨnhإ?_x^k^a 婫i=ͨն/[*tiژijk;b8=sGf)ߢ-Ȁ=3;F%@jZcVo\-Ā X,ĮythCFpteu}W۸s|>EUY5" xƖdXH P�L>Qv tjd6{.^p ct{fr]ߎF7_ Vw&cDоm`O ;sӉ)qt}>~ʀ(:3j"?DDQͳXi"#"ܛ/+$Nf2:ưcu}"""""WIN >apif_@�ibO9ǣ"rѵ7ν$nn*vLX""""r_Xה:]wk \.RSH!r])oWV}^3O`΅N2^^X CCDDDDDyrr_DDDDDDD"SH!"""""""A!x"""""""RGPH!"""""""A!x"""""""RGr/ȅ9\xܽ$"""""тK "YXh{IDDDDDD~-BDDDDDDD<B  )DDDDDDD#(BDDDDDDD<B  )DDDDDDD#(BDDDDDDD<B  )DDDDDDD#(:/p\\YEg֏?"EXhm3k`(V6iQD1zPa.NXty}~[nONit&�N>YN+҄m?Ǎkq8 wsr/o.'/t/jln5g#Fq˙U`c J9mg|[wEq:8bx0#ܻᵲw&5_lՃ~yrR8-`7rӾ=n70kS,]p-_s9ufzS,w<xwY!Yayj_π` {eeYq^+PG,xiy֤8G>ߡ1O^OɚuKpdkѰ;L:מx~Id�%۹;ՠC@  ̀۳r[.ĒBqpD.g{ 넉 e} ̓$I�xaC>q.١8B*OQ)߂!dsl_I}2Ӕ�YeͤmZFu1hR? OO4M>ܶ0Skh0y;EڔWy$OIɢݎxXLZDWy6\҃6*+dhnno� `Rfnw [pM�𶳰 ^8KYquX>m:a:'p-'rl<֧>Rs7r4Kx`A6BmWQQQ|[�L_Fy7p*|M0I\)L_K;>�-3= Ya59h c-p]'xa5!1~�ԃ86~<<|A1&)eͬOx?/=QɔȬlw>_躇xs0_ǛӰrĂJ|<'cGϛѬ3Ҳ *f |;qi'hk?Y"90gb$�xg]f[-صr>.X@F) &ΘQx='sU'>G?s F ,X8f~ iC>#YpSso~,IC PH!\@fn!^V#[EM0K7zEqܝ<?dogW͛9Q`Eت9DDDDqĂp } }㘖ӌ&Q:տ]e iҽQ0ES7 'ٰǺIlLZ;0r_ enǟSiQG:5;'qcFRA\Q]QWa󏸨 FLlt3zֱӫW2 gѦ~-6A>h_D vm4_ 0VQؚu+:8۳_uN@ N} pߠ{d^YyWfc�ic gV6tu;|}CIC~ZU^GTD7ć`fl4�{6a|B"aƆyq~.}*⁼:|!;y󴍯˭R+YXyuY z}.0F8əV3}fX#AGHxh = ll{-:?r#uHa;U9Os=&-NJt"iKIRoOvTg>arA4nP@� X*s|8 xa9w<ˀךq>NRYqꃵ>Y-j.@6%K�noZѻ{U8v`b�rgZ|6}=wWbԏe&e dX ~X2ƇeYpb+^)ܯB!e`x0#ʝ�LFXn-v`m|]:ܑ˧`quA}<9O`ti/&g-z|l޺q-|#Ch:[4:W94�BXZQwY,s7 h00s `7pY#TY-OFi"C1\IhQg~i2 JJҒR**n* 4˪ ˪8w|$"] Zge`XǩgaKkά iqlȠ^^v,SԭN: ɕLDDDD퍌掸5 5Y;9>C9i -L1c:f SnjacYU@Qfǂ)ȧ"RCd 0QDJXp0~T3Ax>V@Ü%4CIZXCV-@c>%^ty^OٍUQb6l-"<OH(vM( @qb +>nB حYrh"CksѣKlf d̾TOhIֶ.khcZRmGd~> s?\axֿ֠\$?� d>M:-^F`%n#E\UAV]0kb Y5W7)nVm͙bl&ǁߺΓY -+ծ 7~'rw fc^p.q]1P֫Ɣ<{�#&`oА%h?�a/ rʚ7ϒlZ8]WFU)t}<z'̞Jۮ|s2 KRx?w=nIo߶યӹ3w7YEŔg%s>bjXӽGRH!r_6,ܝC5٣-�xW yF%A7$7V۾}y#h(+.&mo. {sOԿΆ""""rPo,[Tg||'\<u8-d=I1btJԴ,)Ƭ޸J[IM+Y]?q)ͯ4ÿƝs/*8Y׊0YNc!ck0xPo0CH 3F=5#ЩPTs 6:)@Je-Ƅ7k9hI亾yÍ4oO_~M`!4}#֟w,קSc-ϕ|Q6RufEL+ Ɖg#r, EDFD7_T'OW<HDDDDDLtR89/ .K3䌼|0MD3)D.ƹ.5'DDDDD~uz\ }_XrfRfR'LRB )!A*"""""""A!x"""""""RGPH!"""""""A!x"""""""RGPH!"""""""A!x/\ÅK""""""-8 PH!rՍ^_A=DDDDDDD#(BDDDDDDD<B  )DDDDDDD#(BDDDDDDD<B  )DDDDDDD#(BDDDDDDD<B  )DDDDDDD#( \s����IENDB`�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/docs/fp-crux-full.png������������������������������������������������������������0000664�0000000�0000000�00000167211�15223753015�0020061�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��*�����.()��� pHYs����+��� tEXtlogicalX�441f̦��� tEXtlogicalY�211m���tEXtscreen�HDMI-A-1/ �� �IDATx^y|Tט;d&NL }EdTQZ[Zۺ.ZUd$Q $@IB6gL2s33@$>COsιC2fghӢcGɒ%K,Ydɒ%K,YB!B! �%K,Ydɒ%K,YdɽB!B!h\Z(Ydɒ%K,Ydɒ%KܣY^Q!B!B\Bdɒ%K,Ydɒ%K|dyE\B!BE_dRCsLeq'-/ο|_!B!\B3}v:Qḑ,;-_|vB!B31OY{@ZZ:* S\Ϳ̎&}B!Bn]gtZĝ-NtWW?ߺ;;= �MZiVZiVZiVnm;ӯ\sFښ 4M`0CַR#|vР0imm?.u_uwgԥ.Klԥ~vCݑ~=)5*ԶlCϥH?߼qc<^?.u_uwgԥ.Klԥ~v_w_yW= ΖV4mPhZk[ۖ.soݝ%K,fw%K]dɒnv d3WKרl3)ao.soݝji_WyynvڟJ+J+J3|~/K{K0x⏿߷ݥx2xKh p[xJ5 \~Q3+5dηuE>st M0 m<->YR?[ݑ~y;#2hl'Q~9GE~mt `\H]..uK]Rz~Kj 8JS0N'V�yЩpqOT4A)opcv7Pa۟ ߐ~7uGܵkThZ۝U σK9�/H?߼4 vOW?;Tv/Y供K,fw%_Yku~^o_oyԄ7XG9gt738QQ 4?0:N~>DNr~1){9c8Uvd?c�\_1 s`8#Ԡi<*i43G洽}}bN %T |#*M{/4Z<]|@0Z5 3[Ji|< ^rg.ݙi�A_>og0\v/Y供K,fw%Kv_9ǗB34MMX <8w0i ~lwX  1SihUxs[;] MN%7/z8k |6Gߞ;~Ѭw&My U<}K3}ټt940 .@ЯxtyU< + ,* K9K 6U+g#891#Eas�n9?/}ʎbv45Ƿ5Qr{n7C`{~}*w١>8h׋֪�M#?u8 6)1<>)lޛ崍LYng GPJf"8v~A|r>?J9y԰O>LO2oݝ(,*ֹÍ;OZiVZiVZi־^ Ȫ1Ss0V M=Tdص/5y"C >$Ʃٳ7cX[7V2yxAShA]Fƃ?ط#8J:/oaCzo1My :9Z @FIB&gǡ:^>qѪQBMI3bID.\ͮ0^˷>=Nu#AcL2M˜Xv'3.f 9ټ/m_gj�hͯ㦙vDb(7tU5*ZmOkF4b#тFG)<݅&ȱnЪQ^tq*3#J +!hBkU;h(?϶z?Wّ~y;8?~6~)3z"Mdɒ%K,Yd^y7[50Dbܷؑ T矤Ȣa-Q b}o~5Bc-32y,c@>~T7!:n؅\;i�CП &\' aiZQBq"?�8Zl%$=ЫoZ^(LqGSe`(&edIh<MAy ~MepB&Ay7X>o[#L%Y9~)Wq 7_B3TGM\p>&>[>ŧO*.ǧ>cr׮QFfSAu \YhZ4~W|b:k·~lb?$:7A½3?MbȡFLL`Ͼ&~1"n=CB[Ǐ~f)#Rlh{F>5^~s3cnoG Jp{| g6QJh<v )jW|̊y0Vz J>y{ڂ[xDNk'BpBۑ~y;m@s1'tP%Kw~ɒ%_dɝ~c .@VZy2}X\3f<:#ɣ?u2J SaO(~VFl? É8Ph0_јk[#mvV~ `" (&Z5ZԠ @&�q<8Ɗ_)""!4Wm;`֊j@þ=rgRk~~F4 B>X1Umk.cr׮Qa?S8=WG m{w/?1"m1ml5�@k+`dL)&R(fĜԵ| ӣ#W'&=�md1lDZ~>J>) ظc+f?Dm\Xת3kB֮Lcjr~ucXUC&|cG8g [/jJ+D$aK o~|},mcI۾`깚ݙh=RNimX @?^/vR/ݺNR[wI][VJs @"zqz ފpe�oKe]}|o/(>H)G #bY+◻3iLDzQر`נUsXN߽)4g@)>QHMi~B `$1ڶ45Ccf @a:ƪ6v )n/grׯQ>h_;b.oU2`GDKb\– SY5`=OS"0Q|h٧(~Z#F4RcM"|ʣh,F�FbS((o}Mk %'qw]Ox$M|L };q/5.W_˸C$\M33"B!I)ܶp@vLLn6~s(>QrXNn"Zf49ݿ+Q?^]?tV]~{+uVmo[RwooV]~{+u UX1jQ!Մk?њ2XjJsT(X׸zv&%A0WR)iOSv| hA oÞH`}iBC 4QmU&4-bƱH~¢gvSUbnƻ%|&ʋ`F5MhFcc:5{%Uk[:=t=gr׮Qa ]+&ۨ4p]S!(?1if$C#$Ϙdph4M<!la M7q0dTfE%�4ж= &VWY۶�렎۹c;:~̋noafB8_'2\Xڎ3u#yDM#k^wlg.uz\|ԥwԥ~9G[ihOF�T0O/n(+34#7jǤAq?&s9cY1Jhl/(Y*]WE ALkYy6{ P$Q3#LuZX`5PQTƴpHB<SRVvcxl ?v1M m-ۯiȯ%?k?ȩa*QmoGGؗ}|`pezS5* +FIFHocװK5\lCiLeѴqhfO=FZǤof;eDclt-`  ψDtܙW+|;_r!&^:|v۸ ^וn$Tv/Y供K,fw%_zM5ۗhjS_9=kƴgrp[n1|󂌔LϘ4(܈üY!,?HcL:up8aw65;2*J#A52)7-w>x4li?3D+h�ƠH*,Xw uX3K: Gmؚ[KGPn⪠*?}V}hmqJt Mϐ N.)wn"wnr3]Ǜ_9d]h<Hce7 R|l=Z{԰ V+5 c0fAlQkQoPmNdcEimWcwXnF"B1chMq}l'$�jn. "#&zmXR ?lc 2Aq+_wfg 燣t`h{Wdw%K]dɒnv/Yda~0j[ 0q4 &`n`F="Y2!ב�J+u-0Cq]NjWX h%GxzɷN[G[P2 F%!CǺR࿿[pCqjNM~l}qMynV7~3D0iɛ4 00J/?ngr׮Qu\SK~Wն&q4 kaYhAĥgHd6nI `#Y{#ɓ31MY*C(P{0ߟnJ^"c6HZ},4ZX&fTAܰ8vVЖ}DM/yHZ[`쭟J�˷!Ϻ"b~Eu/$1E#dũB'C8>](P):%.1I0W󭻳#m QWN]I粻~ɒ%_d}7,YŖϴj_H!rw_U5*lgH:Δ8_kոh2hT�?=>޸&҇qc1qggy]7 "qNzZc@ǛEOShU]") r2k3Tr,rco(%ÃN7*Gc[z0躹:IμA<_M{�ǹ'#A-xA`02g/귈SscI#ؚ(aѰfͣUvfo=pt~?q6vm.Zdɒ/dɒnv@;?/ "Gay> ECPF;,n/H O=ݸ*%>X xo#?C}=а}3.\/{jw<=nݶ |Q"ǹ<mlx| w/z-,Yr%Kw~ɒ%[x5*Z[`�z?a€ +Z57뚦Mim=_uW\Ϳ4`m'y_d}7,Yr%KwK _]FLww~>|}Wp<Nz[SU{]ϷΎZ5 CkN\oߟJ+J+J+ں_]Fb \_.iW10_Qf盷3�FkxVZiVZiVZi֑~=);/Z۝j,qC6-f%H?߼v h\]dɒnv/Y供K,fwFv_y]F}  %w=jugvh`0fߥK,fw%K]dɒnv d3WKר@4[ۑmϩ~uwv:SZiVZiVZiVnj]Я\+:4lg{VCs/u盷~<J+J+J+vOk_y]FhMk`0jK9YR?{ݑ~y;g.!B! %epܥkTNtljkjugvtUI%'.{軄B!;:\.]) U|,B!wgrQ!7盷B!B_yN'*<GDo7og!B!=C�{@- MY!B!DЯ\+{B<e!I?ߺ; !B!-Z-Yo7osn2F�kmۏ!7F9zBr0ǛX>}O?j&]V4̪R2%o"B!1OD~g߿ޯl盷>2DaD(S M-c$6VPG0ur(B!}~=)+`{-\s5k|}8G,ݙB j`ҝ\8󞹛 8=ͅ~Fh2VS/HB!ү\e\'S>Ҳ }L?ߺ;_S*7PHTOD]e|w~0wͻ9`-loɏ20 6?/cVCqZo}<6-_0G36wi9q,tNV0eHRW7 r鶣~~F<uD`֐K7Q TƧE^KvA L̐cZi#|wvM̘H1FذtuY+zX'p%?1XB!]_NOsL6|v(\w Bҧ},M%abb8"O秱bքX�((!1h63FGqjՙY2c⺛a623;\L!!H~q(JC!icCQdYƕbIl?ŅsH#gQ; |9Ox+Wxxv?ovw<֚sc>+7pcfO N~�� �IDAT+;wҿtw.g?#@DZpB!@B\|v`/l?NxP*&L!&*Yޗ=d;&Lm׵k4d3wG1V _rn`@T0$rXj8Ν!Wsv,FSh!>[ՙ*WB5axdEh#9Gd>C'RE �H|(A$"�nk FCǓ MCm[H"N!tD0=t*Eic!B!<ӯ<nFܝZ�F ~/e&MEL_CM|ɗ4 v݋Fh9SG*4֡^r hhBjzhK;+T4`ew9F|h+D1!9VBٰ{f{mI?ΠQcOKG S/܏77q|/J�ZƇ^ag 7)DZ!B!N>sr !.~uwNFy C8͛b�؞g7Is-iiC?l6˟ w x}O&16ڮOHP@H` d}6b7ocFF>ޜߵ%'鎧!B!F>s<sL˜_- Zu8�ڂrN/ oc,ʬsq>[|/)R,盷sWQ 2+"c8pcBJ/(8þ>bLý$]ß9SO|76�X&ە'ͨ rvz/V%h$""&F>V_Ac(/a`ꌑ\=c$gvl`)/e-4/e8BGϤ#^bFZm8iZj4 !B!Ĺѯ<^FEnu ˖m"t3Ҙ9o+_<2oC%HN?XT&57x pݵ6e7$׋$%nl ad4Շ I o`�%=œj+T-&uf>@H*{݅Pd;1gq|Qn1gX&*پ_a}4TߕFTnk>F#s,!Cs9^NMhJM$kZ&:# q,0}B!Bs_yʽv :YnG=|9Q!\Ͽ]B& Em/K˕^HF `"DYi{Pjh,4,pbG`5ǹi6RӧQ=ĉ5iZ܎œ`,v r >뷌xLφ# xFE9nȤYIl_~-__㈜rYkiD\8(EƍaC \=,A @=vֱ!B!F>s O=U)i|�ͯ ΧB_j+F?Y26s"?c&Ē_> -L bҼC2�sw1'A!~m4*b,]ܭjej0$k&ZXɨYA +6$k+&ݎZ'5 <ԗ +֠4qSZ$ͧJ '{QxiMYO~}wʫ�p *gޚ8UEW>}EPcJx<ꕹCG]œZSB!awc9d{¨>$Ϙҽͼ2yX0/ fM`!_~䋘bά<�6klb%ٱQSH !)lV@>XBքeNpei>ΘV~~y;˛ l]BcVm;NR!B!:cr\Whidged L8VŗSԷ4"BY9XNoSQB,u T[}9p08Ad} ơC7nbE 4Rfz}WISTo�'m5SQ_B!cr]•f1F�P[,w7}¼hi|ZXTj3b\ET[MU[Pf@AQ*XkXTUm@@sڧŢ߷87_wf!KB!B/Я\e贈;[nj3}h& |$\cxz``TF*eep7DϷB!B!z~}*5*M>Kƶͻt 1"}te ;jO\IA?WPl QTPQkg'i8|vB!B31ODxC/;|5 K ,-04%#56La�$E5�_Qsz[EC bRFb)=N~E3 TA2(#Kqc$ \L\盷B!B_yʽrL`&iԆ<[ 1�ߙ1&e ٙۮYB<<kL2 ῼ25B#7(SaԚ<׷'5-$o˃S5!ǓZ \ͿB!B!z~}*5*64wP/͆�+Y -|G<Vږۀm˳YS?},odBv۩p[:goݝB!BUvz)Br }›H ,.rFN!BaPDtBg!I?߼"}B!Bnʫ_yW= Ζ&|,B!wg=!ޤoݝB!BUvxROc*盷B!B_yN'*<GDo7og!B!=C⢣oݝB!BUkT~uwB!B;3WI=}ڸC}D?߼B!B zSv:Q_<]B3|vB!B31OYQ!.:Y!B!DЯ\eF[wg!B!C>s> m,B!gcӉ OY!B!DЯ<eF[wg!B!C>spOYoϷ_$qʿ+NYt2X!.gʜЯ\e'9Bx~y;_ }a.�~.{y.}=BW]?Ņs;S8_tBg!I?߼Ů==ri.}e+k}:!}^\Δ9mzSkTuu{NPOm+VoNN=O>"9wc|KN~ Pj[wg!B!C>s� /D|`h š0G h&Ш[.\.󭻳B!Bޡ_=~ 4cAAHs5m%Kn{.u,Q drJ (ArN2cBe!B!D_y=~P3ԕR^0Sf?9~B$ӇaLXYɞURF Z4kSL-&abtdG~=W}Z~H-FPhc V< B }qpOjNp9Ψk4yy;uH('*vV9]ǃ )\B!Я<elq|]4BmA%@�QFFsv4q CU~+?.qykO%֯#R` 쏧MuN7?=5_F9XFAӋ_?I_1`m8 ᚫם'}�-̹ͣ:JS9[2;t)+PM ($0[�֓e,93ǁ)|8:<l%an̙{@<d eˠ\ &ql ́U+j} 8FԿ"Uo1ߘGXtjM, l45i>d޷L̃sr:.݊Z~`f.K=Col$7mjh{ n%zXjov\3Ŭ\.|L~eL#iBrn΢<{B/ܷx [öe{Rۀ,YZ)?~}*+@E0QChS>I`z8N(�0 m*MLN4.$,4&e o͘Cqdj!4*q&,]b8r[wްʜZ𧾬Kݻ%gɴ@b\&0=a8{HH/>`?2X)ҏ7a=#*cH ((0T4rj:'B!.M*PWӀ9D\TSjBS}`idOe {Z~(3OϹR}͸KǨِ%Ҁ#݈)_<x]DnK>s{� Q&rB(.?EXS%D&XX `Il|՟Jsj!PU0ƷoJRG+"*e(o]i3|vIy PWSA¡еY}9դ1 t_ ^>SY),$! `&X|uDwqg~ ! Uj0aԠq!fL\m+_,-Eն[qnz9'7/CU^Q YWcr_ 6Pa9B57q)9ԇ b4c )ŧ 0EWT9s-vr$ͽ 9Yn3|v)WLTGghd`6ӛ4+�c? <_d1grB=6s[PM?,-9ƀħ5-< c@>*Ѩj0 nI e, @`(~Oz/l�Kd�JϝP r}I8aX |}Xhc;^N<(l&0*YU>ܶpDl M)bxmU0g/tYje�ɽr>,]C"E,Y2e | X4Beѵ6ZP՚’%&QWkr~3�Oz\Ͽ6S _A%*_ 'y֯9(X7=p˷TܓE�&~ yV@?_BdV+\a>`T\ pvh`ú-X*s[g%0j&`PU;t; -QR ڄZxHj3L+y:yk&0 n�6mŦ^ӓϹ% -P/`9Myby=)ΗxO>wP3XChsc}zBh 6%>(B#FhkbSS[IJ~7Nj`);`FLc]x,[F#F7w� XUUdrcT4Ct{ݙ{CXOTq`X;PI}W,H$^.bXM ~!k幬c $>c Og׺EgL齕Tf2{p  Gis_%ʏ1=9}!P{2rT<ʡ&>Q_šCe528%.�'AO�1_LED /&Y0146A"EΚ�Ih^QD:[ylӧpz{Kn@k_dNpm;ӟlA xKZ`U_TKغJ4TM)ۻ@1DeHVWi䎝FE8mrN%@3&<0gW`IR3PϬ=/{D N[%ğ@?!4bTy|Kٵ}Npv$)—YXY]3viW;qO)t (YٳiUH+ <;1nX(rying祍V|Fv~36`>\qפ{o3?E~ Ԟ|?^9e�O=kc%{;, ;6=5[.9H>s"lBsl8YDϹz!) `$LOl lS 4B9S$$\EzՃ:XS;G@qq _h0G@?yRIn)΍~uw `m*&jR{c`t}U&ʳZ >8²D[9Z?|x<-3 d,²bgfA$pfزXFr8-V}p:]~)63(թoL qy[/(1r3 7@St$07*fƥe >:Qq̤ل ):=9UX*ȦI9Y_9lkWm fi*wQ\Xw5 8%ŏ V@sٕ-;N\H YYZ>ǜK3U9Y^9~NcͤE94j<{U<>Bq,cpVJT/M\df4~!P=\7|8PW]ˢ)SKS 8B楱3 L@�E€*8Zʉڼ S?(n}}bg)܅RŨfߍ@\u-lq > l\BS} F^�8]=;se8ү\et'#L@Xl8sjgQ�p#HJIs*7~. ��!*2F6םa?w^!|@Xt(q, ՟L!lb͸L?߼{`[CL%;3^.io>i3;8AY1�k~ã)g3rFm!F#� 8s~D Bx9粿dء$OFm{C)2i ԌR]PQ[@4B@O7sѤg㣪`dr$@ $ 䢀*Xjkj{jri{ZmjV@ E_# @$!$̞!1L $HGxg2^kǷlNd$X8Ks2a׺->nZRM5DT׷{p}16` tL|ǫ@{wcm, ,cq 4jlK6ED$|<D 1U5kш}'*l۰ֶ6 篋l>yCQ~˲}|KbYm6]/jEY -ޮ7} ~׵sƁг(u ?s-dr>y,d,s\Ls18 *y3s(S O/Ii!/�� �IDATϛ]8\7W�~Q 95;>`v}-]J;{9R2+Hg&nޮ:K% n39.X|2AX ˎБ2/뵯#2|cܕtd㗫�ulvRcfJ Vz}4ަKN#3">phV=E]FNJ&6O-m g;$j3h<NOw0'"25`5`'i(is}a'* Gv+;^Pˬ)5u!x=Ƣ�l:́-_[ v}E]クL8JY+z04=z,XE_Y$<l _8ptEX"lINFNAUu5x(>TG￑}Lv8L;5٭454ssp̛LlZ~Jl7M\Zz;% 퀶Jփ[r>ڠ'O % HKa|m*7"6NΜݪņ^.mS䡸(%%Hf2- HL></G$00jk<SΠm"-830*&۶�Y岰m|}} S|⮛7fe7cS}XFlv9.~%1[m,q?u0}f6ҰmWP\r#$'w7AgCT$tUE3%豃/>}ZtONcmvbr} |sܹrGF;2w3@y8pNH,Nx uX$[3&Ī=|cvZjO<Y}?][߃zbc"k_ "&|wn~he!قDv[җ3}{lkA#_UU[ފ]t+fDpaٷj;"42mgw!Z"mT<x9 DO~C}U5)JONb,�<T7yHKz g1HLn:dɓ oXɜI X)UfSbԑ. i:i<^>N"yR!Ǜ_m2i&s|Sgm+LDD«V[3V uil8mĬ4เ?"ɊwLIr9F mؔ8m$/$`5cIWhOlR_đLF+~ t|v,;6I$ sx;.W$uBz\L.T5A?eH_mFN Iάer9""fp[!ov<<&3|0'k'y8?iWwt:֒_ v6PCpa :ʒRAU|Pk \?66&ra>y:o5xPçD2sTyІer9;%d#2�ԝ%Vl|El:F]UXKT/>qoVO",bӔoYS.`76wVie% f&-KYC%LOԼy7Ps4~<9FŖش�kQe)2ÂCE|H@cS;m46L[*~Оx?>jp!]2Ovwe?]{k&;^C0z;<z-$J>Fh :qk7SM+ueoǷy+iJ FZjiZϼw>sE_1YSTtcZ�|[<~KcmL.Vf=,{'v1` ˗y1zE߽.as/X#߄ͮV#`9'9)wcx<o]H[Fq5dF"ͣo|z~27i3~LOKT|ۯ?#_׋bŢhf�·' Uc"/5͠ /Aoȥ*?L1p[i -y([Q[6c|v"s 8G)\y HcasyD^ÅYl"dP硪kϪ XVr�ь)) j'H\Zw73EbtZ$:I!""""24Y5*aphf tfWHqi o>:Kc""""f=,n839EDDDDDd`X5*cPgf}(sBep2[ > ~xF 's;0`o1`sDDoΡ${>K^ y/1%ìǂe |s@z^n( @/9T&Hga6I/^ y/1%eg˽'l+s:B#6"w2zDDPӘ agԏ`1=W7_q$CM-YDDDDDDYaYl!M2[  oHO}ep2[ > C9!H8-YDDDDDDYT$,""""""ìǂ尬QQ�_A17P.Ӌ3(>ipכ\|!l^o6\fΚg67 -yE,2PPP""""""CYZB.:x uagԏ`1fމ:67?#;S'n]ҺTNx㭀wsn?GҼEF:\K'`~p=Ops3^K7_%o""""""20z,X}k?]Ȏ3Ǵr>IY {k(dKٷMAͧv ?oi0gf=,CIJ44%d}8u$^hԱ};68Cb0[ > FE#;Z݀rZ667'A-YDDDDDDYTB68{;0`DE9"CVX"�vg3�n71H'Xѱ"Ár?=s;0`YkTd D8pDg0sJ"D`ʔD }>ņ#_#:)b%NU42n _oɥo""""""28,P `Rd7]Mkw3K+8߰qӣ陯`{}iv{d?ɮ�X<Zʵݏ;|xDѾ&>]߹PkoK9BEDDDDDdpY췲c^<U²]�l-gfb87QN[|7|{6}EE�怜u:epgf=,k  g,3Ҕ8hgpgf=,[r@Yv [ۿܷh^z-rPff}(k P'Y.9BEDDDDDdpY7#}LEo""""""20z,Xr0[  F\tPPزy$"""""(ݡoMfgrX֨xf93[sL<lKw#4c邘Yl5Z6I䜘-92GM"""""r KLawWظg%ocz,X;QaqfˏsI䜙-YDDDDDDY7H8-YDDDDDDY!`Y$,""""""ìeۓH-YDDDDDDY!]BB-9jmxm1nA' bɿjMê˚ #"c܂h&T0uṘ|EO2 fa| &Pf=,k -y"rft#+cٿ\ʪۡvh:DDDDD-mU4SCsdg˽ٲy$Y̦^-y4pt$YAݴ)حs|E8ÉTK%DxNCLDDDDD(op9,*� I<|uoiv27,P>j̘<IGM-9Q.jd-XV7NfP+֗xb/�Wy3 :X u{}SF ȟ9jlXF Ӫ^;&~tmXmŁy _={IUW r\\`X]/7G])Irx v 6rEDuϜV\о`^)^;)k<`-l9DPO\B"aڢ�h~ye+7A{-G Ȼv<{2-S;3e#~-McnQ擷̅$VTwPs&w7\n5 HɾbYaYbdz$CT\\90[s]7qm6 ]|1wl۫*EU X^-Y%rtw$~C I4p4VY^6{71yT#{/}aO2ooKDO8^Dsٰ1l]�S9^F;5ħDC'1^_YwML~sw?iN}1z~#Kc($Ӱa-&H(LMgnj{+6-~kS [y?̍$}m|oo3OfkvNbvԪ<rw"Dkz<x=|=n9$Z?L- zZU|Y<WG= F\t<P8٬WV\Y@ N35/+n$$QSe y 搜YqD6 +.7k-D\Y3F3-+qӦ`{"`rF$Y<+|jk2<@z}N\e8-ޏ O( ~k GbieVAcAO6 '2h?R[ր�@:+G' 8H1~rDM-$/!%9{io1r&:];en&$cȣ-7`&$Q$sY5*DBoiZZ׶WyCvdZ:<<jRFZNÀg9�Wp\x<8b}w{Iǹ"|q'N\PHa'N敖ގq*Nwf,8`} pD9)kDDDDD Â^Igc-Gʚ6Vm%łߣ@( OǙvZr=P!W/9ANɬ启Q!_x w(12+W:fpt.RSp9s'`9 )AkN*ʒcDFN}C~oC<&d |@tw{oǀM~[$o/@q)n8>O^u.~`EDDDDd,JcI!Knr`3# DD֋�Rcx4<nn g\ivo}"EƬǂej,,Nx w+h.+|5chopcRNn{h>uy3r[" Ể~#E[-?6s7^HeϤN,Ce}plZjSU\tnwzy}.6Py27_;@MS`Za骭`MG{NĽaZviri9z̽iNM\tJbK3t> 3`YkT^[#gIh8W x |7l͇;æm#x}I.}ESo? s:Z ;P}/!##hW$1.mn6l+î=r+i8ui<D_r1:L{IU6S>\m=_chٰ]j[=xjpD8;h |g7hʲ^Kc__KgoA{Mwz/b.8/Q˯w7$8x-EŔnExKNcZrHx4e{prInfrh{-isaʚ;x~ >q1@YkT ^ Xm4'FO Hskn 7,.j?=.^y 9?6addH>}_j<Pn"M]@' rI-ec^A"U^Ư_ڊMD &`d 6h߹$<i� sIΛCsNTt=_op)ڐ?Kʍ%㊙}vpM^"/mbjSk�G$qQmtp@D$"8biGv` `J.w@(f�sN䋯m5ry4<z].Ĥ3HnLg_ozH03b`܉| UFn i08P0f}([~ A\Z`U7sKInn4>6w+FY2%Iw/!D$oԕ$~ X4�7YK^.mx wTܿ })tsgv1--iw^mN Ղ}>.@&;pU)[-~]Ѿe1dD ~-};vZ;5#i683{-eZi]`63.LT 8 Q|yf3. fuQf�7͸bxkgݛ? |} \[  FNȜ} XO667pnl8 rDbzz~¦xs&L^C9壣x{#ּ {$9=^/Y"Pe= =2x 8}'.u8F|86+ϯH�|ݴ~3m='%K{"?k*M| > FyaSy oŸ黈& :e$J2* g+^/ib$SNLw{u+>pfS0zx uhxdKDDDDD>",P() ͥ�7*#yW'-.e蹜8%,~?-vݔu4�@c-'0mlj:?~u-YDDDDDDY~կYęy(>>{40(HZOqn'>3+qAm:U*lϬaeaI[o""""""20z,X9 =n͟v&*n"2Eϓn{O<϶ܧ-�nV6,XY@Tumn檩�� �IDAT n"2)C9BEDDDDDdpY5*QerۯE$F׉V`4֕i7L]P3wQq`e沴ΥlpdW{|f<$?o%yx uag֨8G݋'5ټ};Igoq󻷉'dLKs’œyel~ cN&s�?xgmg<4[s(%NDȥocIΑYZ< fXhvugR,�4l`5$-Bm߳{"""""rcY΃Y"P(_(s(̜5lK>Y!`Y$,""""""ì~ ^c#9EDDDDDd`Xw"p3[  oHO}ep2[ > F\t,""""""ìeQ! s;0`tK6Ddpgf=,[r@\=zG", eag˽9k$r,""""""ìeQ! s;0`DE9""fpgf=,"dPgf}(sBep2[ > F\4,""""""ìǂeG{9"==& fpgf=,[r@Yd̡ezIDDDDD4s<,P @[Co/T9TB?(5@oܢg޳(hG-0`o1MSV  gA|)gf}( QVT > ~xʗpac֨PYDDDDDDYZByef}(k !EDDDDDdpYl5x{mfSfΚg6ˋUn]Ɉ3VN]cMtDss 5nnh<I~4<t8FO�?6dmnr±O޸'6ql�,xf,Xm{�c̨+OWI@]k-/ x0=7=&Z6RD$z,X;Qaqʗr'O6z}I>"6xӲd'I),[s>1i""CN0#/X_-L[x }<td _8cIEd\6.䱈\ F-+s9']{X-<tu /S(iNKcȐ{ ySFLd+7L~4<8/nAkHJ?v > - eK5 QƲ5E؍5Lc q&֭  dGC Ș07~YOT5pu\+>  xvc`|}{bU'k.raqV; lhp6O7ӿ|kOJ >j  8]N gO(!=>TAT<o+8UkqƧ3hV|OnJ=<U侂Yp-V,O?EU&�#X)dLAIgVT~�nωc7L9_f}( tw:‘]!zR4<|O[=[SDW X΋k) ) )2ze匘6 ֭)&j ~B& NZZp,,{J!ەԩYV2rGT>~OpkV5ZUFvppδ™ź f(&A 47S S.9Q³+NIkvt+h9ykrIK!!=<-6/cП""2X|^kT,_/ʭ.9k;U-0ŤYT4+Du4$LJˁ6J\KK] gNTDwP5j"G$L]I=ܼTF\6v^ұ;ē1voXGNz:d)IbƼ t-|YRDL)"N:`hb:sS?WE7M氕ΓNyqvxhJ< fDz<{۝Puڙ?:mui; SӬც,a2$:'UZDD" -�wE,2PPnR|vOŵi(V$nV<|͓kDO 3:GbrxpF8'n\�q|r㜜 MgпϹmOߧߧH8$*)$Θ>v�hXhܞNӝ@'Ox�nw7`{:߼ak,P?etx uY:X;*pם⚛nWHB�,$pIt2�z>IAxw'3T}N_)\p^Np""YFEO'N`ذax^} ړ9/eNc;;p>h:,;Xw3pZcѐ֚NN,#'>\0n;|sZh[ăs3qZ#{yh8dO6n`Wm'׾gl}]ѫ1y h 'ആl M>ӂ3gձvCѩi4p̿ -`mt�huds X8=iWޯƲIH|^PfcyQSWWt*+OoΗ8+Ӟ4qkBIg_?@UCzn&Tyw�X&lN-'I+bci;S9IZL7$'#yzc U;X[-zƓWQ|ѝD'k 9Rq-2)SomhQl+bJ z~<7)uTA]9Sb ~BY_ʮX5&tv>x58E9$%D v1"H'YIl1+c<Z ""YÁ֠+wvvzTVl2[P0)ny"D 7+W@Ϻ䴜983)İqognL)7Җ(6 0bRϼQö{gnFXpLEgRuţ,F\} 4'8/kDO)hKUǹ6ܩydpUظ$D2&MeLz@H-r? vQ v$Gcǹ}q9""",POw\0_+?oc"7<zlټ~l^ɓev+ܧ@:ڧ7OE~Qmxz++Ooa=l߳lV[fs$Do0v #t/,2ED.7f%YrU,""Xܯ5*z^{Gmʗvo߳*)6Yt'fYf Af=,[b޷=*6կM=o 6  #W_n8'gwQP<s)wf $m>72̝_ 斻ou/9~~sh20@*ʁNT\1ߏtN؋wV߶[PWM5Z3+z^;x uagrר]a5>ʹ([NTNvm3S-Q*R'to}e/P> ,""""""ìǂ~Q[L2zh),WĚ(3lHr7SZN�^^vMlz*VIO-֨-yT/yY?Ry*;P5q�?r-NLeGEʨ`d/nÔ[>ۙ/S�|kd-r ; 6;Po%T~q9ȬxB0YQ9gޞ?8{;0`_kTtvvvE|ذa~}/H_fϞcg qq}g3ExfFnEq{uE˙yy*L[v#?DRf>K60 R3!? R"Ձ5[JZ^--̜L_s^ڼėȘs&&r&v &.y ހwѸo%3/ϠAv߈^/u0?Xc59ȘÆE@Pff}(k d' G+ǰa81; �wzTb"ɣ8ɳdFvr0VAڄL:;]' #)h33%3~|Rt5q\웺#?Քy;oذYT„�LH7grTZɊR2ha'-YDDDDDDYZgQnaR B JVatz "xh;H:;;͈cJM1ʽ'INݟIo ::;I,"qy;qtz>3WI|l,o'qN.:;;6\x wacrרy%AO6+>JW{1#8˯$:>~ucgҝx�Jp@Q>楂31L<?<Yuk<x窺{s=-Bmټl�z,X sk|k4 |LoȎ+�{ND憶Z˶F4;NMmt$0{fawR`Am v+Nl/v0xl('?yuxcǞx;[pāoH}$FWdذ'+ e5DDDDDD.)+׿c6]> FEWiǿף˲ 8,/ql|ߦoop҂x %{vmJ$zF X#ML+M`/]ʑ VgygrDx{gn+e+K9F6Ⱦ2~fPgf}(kŦyEE~j^|' c{Dsdz9U=ș+ Iw+rJ l-m;� ڴuddM٣xtδm|8ꜞonV$ H0{UtDf,^(]WU,˨E{#~vvv].x wacr֨Y`f~G1'd`2^`r~{1 u˴Dif̀p3ZPSYçJ"ox-]{ ,zΊ |s`7{v|^/dEzs^ow=~dpgf=,k`f]k<&ŝ4cԿIGh[:{9g<^ >h20@_kTD`*fejnsۤDFL-?*,""""""ì~QỢE-O)_;zz3ۘ_lo""""""20z,X=ŋ=ڔN[  oHO}"S_5_Mx uagrר0M}| oew̦><o4՗@>�O~jfzHn%)$׷+{)3Y0D&mQ~ەD͒MT:G_nHY87z^Z7?y7aVW3qf.%�?4~9¸P1z{7۔cCo3J7!~-kOlK| 9ͯOB Oc[_ç&'0ӷCHSĩ� ,Q�o;/=o|M;톧VRRrY|d&_s-8cp.y>OMo<_-/tRhk3|@Z~ucӒ;ҽM^NP,Gˈww}q=Iu�Ķ~w19@dw[:j["9nã3;3nWnwALzw{8mǟ �qg1v:GqbFO'U8 wf,mmnrQ0@רW}=-y LMؾg4,xc<eݧAZ47Z'I,g$o27lI[y]L+ WK͇N% <$ /ax7#sOS}&J֒M-UGmRNCT~Wm뵯7n'>_yji'ɼқ\Ge7w姯Rukb!>(>s7f <|s[rvƹ-4:'󯓿g㣨Ə~ff @@M@ (** cmժj}|V"*((P(p �!@I !YeKB2Ά ~|̹9g7<^)H&^[\:/>\E槗^wW !03p ޘh j0ͅW]729$e0s1v��Nz'/<).-xL/n�?pO?tEHwޔy:n/ёQMN] 7*VfnFʀ.qAYv]SZRCcj TOU46#>`E_#cY&#"!ّ6b9+ j{K$oɊfeRS4M \LK9BLac`H^GJ\ [Җ G*I"HO8WV23D$&3_;V>*W�E%ud$1=#x0i;^[Kן7uwVpm wY62�qf/f"%OHh1X[8Zf VnMt2Y|wZa޿&}WW䛍P{ox*5nPj50�q;zeTŐ3"42"!}q|q$¬Fa +bzӇI )#$8To:AC+I,)|R"ٳ0VƜ_Ò|zƖ%Dk U2%6 jPo{ elYjNcYSzuZpT\U¸_7~+f\#3;"f4>vI>2#ieO@=+Yo1"n)e} %3wg.I.HYLx@%^؛̴}V�� �IDATG)6ח &S^}≶<D|( ȲG֢*2:1Ofa720:4M^}J 5X4D9wzOikKyiǘ5Ԣ)2e P}"|O"O ˲~>g # <uܵUy%*%EA>-4w)l^eN'aw�T`{Dg߶&K`0(Uw+ `v@RIW U#O~r wve>wyv|,x+Ah`;v%*_?L1?'C<B{ c*>ޖS 0Gjjnmxk7J>ޖSAD["]NYq%w�x7�3 !6eXijg[Yn+ǬYj[S/  yq3e*_n7X%|dqx,3kb28=U59I%WpFe4ߚܵYb%BCP#3, f=_@Qʜh'U<1L Wofie,_ٱ?Iwi(q(*,f2$$vgA׿NsAf̯H2^1d,e;uwYgU֨L?wOdƳ\sY̆c;2;#^glbLL?KC]{x-•9zd3‚fnV@0%ɀ,]pWّ i=uoqoj2Z+?KeH[4uKc@Y lJ biv8)1m;[R=RWV0qdGY襹:/ nڢs7绮Oh_u6=Sاsrap<D̬Sy)2®ct B>B+:mH,W]1ǹ:/:.Ow浌K֨˧WhgfzsDӴ,Brf 3XHNU�H�,||unTxNW qݺ$sW�\f|z5'ptDY/?q_f-u,3~NچIϾ>#G $I?2h `dtje-/ZKpldP#lz7naH#A/WGSJ2FF$-3|BI::4}ҝkZfj(P]rUgdcgi1T=Q]SI/к Ic pe>2MQY;)>s6159Ǩ.9E..ϧ1kgDD(F^2 u[fDLr2?mI/ɦíWkEbv~u>Rta{^Y=+o;4j,,GW…'$`� Sg;G9m3G xJ3a 2 SeX2&NA.^W17͂et}c}0 뜉cCk>$e[3+Ō-j^jjyO$y0 謥זS\E B,Wmqud(qY_kO̮M��LB1 f%M�^|c\rlzD.n2+lIִ1+L;ƂIF`Z&!.T 嬂A/WD(xTZ6q[; AՂP-H _O)[pL6W.-! Xɡ[*w,2܄z2 hUC7?0O14݉HL�8V7tu#T: ^}p\x$Z%$P(*Ȳ -#LuY(* t-;q �nZLC'ϒsNɵX SӮ s=vWSQ[N _X#xܕi$32-/5t_+5ca;+_d;1T7>tGI<y*n9 =(cmNj Ŝ' ͜alZaBrYk(m<btHn_1Ԏ^^=i%*Qld$g( Ƿzc0gltڌgv Nе("z GOk~3yeZP;i%FE- I>W \iHE2e@6)0�#f�C /rBb@ń@흯icz88m O:"{;(|LCxs_2'L&F"oD0{\9-5ngLMtܔQQΟF֙b@!)Ћ{F 8.( w%GY8qN,[3Wʼx˼Kz{(;[vM|Ga]"mt^0kD(&OC5$kFѯ/BBѹdVf͘:�:eQ�K/pqj`C)-it—7ϪݲnhI01^2w/% 02\f\I~z笺eZR{^WE^g3uN*M,Qp"O{r{Y| 8 'i[[7Y:W�Ȭ:D%iJ=Ȫ+ia"D('*hwm1Oy=9tNT #؅t)P]RD /b$#L0�A<s"IIէG@QƧnEՆ{ՀRS9IB;Zc (M7"'i=C)8YOOf|zi J8_Ңs@dOJTm>ɉ%9SAVtNW]weԚvѫk][L2X  ᐍ6TdIhz*,m"QICCq<: xS]foV]f$CÓfZ2":FLc%\uNuɋ ߗPC6YҚzdޢvjԣ�sld'ɪKܖwd˴j\EmQ[]-~�S8Ry�v_YPu.WB]U-d�n!ϋ$k(qPNVI(U,c پ{dڏv|,n젉GLvΗp7=ec1T/Ý)G>PH5?`@.Oy= ȫ1r4'%66oA) };E6d.LÚHlY^}zŒ$黨VgԴDѬT+lH?I<'05!82ơMPctNQ8Mdn>4p|s ^?1P s8QrLR%]|95'),)v2O5OwtU 'weԚvѫkm?/W^MhK@q~%I,"%! ie(eydŚh^jI} 2kUֲ�]İ6KDN&sJenP_nd0&8 k7Ȏ6 ]R*%i*.Di~8y]"[ܶYzdP('9e~kg2Ι4lty^dm[]w v5pVOyA!в-2>+(asA%ug@;>b#qay{QπZIzޖ ڬy�Dz~ O!=8-ڋv<7Ġ7GD<M<R̐~k7~u:lDo2Hڍ߯KmsE{1�S}f%΀ۺ9%x`ͧre(?rq|\H'3 M!18=%Mɋ+OޢkxpJ?AĖXv;灟 I.R& oLHڧÕN>do.٘Po!p0^p9'3I.i2GvOBxX a $\+-aޔᅢ Pxz< &%Ka`C/n\z>s/OcЫM2[]_rNy- ߰iAU?g!}^_ ~>$9 �~L̀ɴwv1`B$7[⾞+-Ňzf!bDZ{|&Q,<³s!Q:s~r (Ƴs$O0r_OtLw~˼ãxHlb֐P"ދ2Ι^yY2mqu<Cb�tf]x?wh.Q>F�uoG܀!)fs: qg𔓵0}E!PH<943m[~߂?h@NVˏ|ٸN!Ԛ2_12/E )ScnxL/;'$zKT4A ?O:a$jˏ/][;VfmFd#IN}~2zP%O=]6`ޒCΪWaB/X[Μî\AAn6" p= ы7+YlKekxt7 _# fn+&ˑXzfA9pzɆ-'H9avWAAil:~~S瘞m晏sA??0afҎϜ͞[֒Gs4[mfS3_ߤnnӮA|X͂ O`MnS)A5v$O}x Fb[AFCjg~jxv<7Qi+"IGr1~HR PMicA<k|/On&YL<{, ⑁3I  7,xL/s@r_.PZ"cm& 6z)mkXM AAv|,n5*NWb%ʍľ!.8eR;$jɏawF#Be sw8VufqB<j4FrMQGɽBw]~NIF[y osnKh[[ǂ   ա9oiAwLJz.;rJ FE /{[yޥ&m)G!u1zrݑ8ݴ~a^tu;K9wK1jKճtm<O<   C;ӋݨЛ#rjJʉR/PQՏQY_ͮ�c"ys,K+`ʯnZnE=.J+ A`oOMejiӱ   >1X[8 ٓg ܱ>$A`#�L�<�ȵs̺nه9qWkeڙzژ=vn�N!vUBUg:nEh?_[Ƃ   ա9m Zj^\�6n?Z}n;~P7RA{l_뿢˴Uw4 9i-]|UbG lOG:AAAYnkT�쯀/mm_Q-<Kv!2B#6F-aA )؛\5͛vMyq6J*xJDӱ   >1b_|2ˉM͈w‡ipv B̠ꦝ˷.ݺAY rkb<^BA NE<mt|mݦ$   8F+etݲVl:Zv}i+w<JX~j!ݴS#=DSDV:̶un.{3n"g-rcAAAn(__tE3gרP3B?7\6z,ۿ1n`?òitʆU$BaWIJ?/jy$ ZT\Eh?ֱ   puhgv]Z׋i!$i4^^){ ]voAAAF5b_Y=[v;¤9Ra}PUUhgXAAAh^|רhov">;U_[Ƃ   ա9osBbA$mkXAAA:3gMFp7Oǂ   BЎf7*icAAA}hcz-ҔX<I:ݪ;$AAA(Y,9!z xu^ZNɭ$\V(yw!O=7,=iuo,ǭõ{^}i jzuXٶ?>FlG<ܔ+ ڻTLbSvAx%2*'i`p5VJ7�@r �`sw.SXz6^} [}uggz rM)rזw2#Ǟ⿏ʬP`ٴ vfivQ~Ϭt:iLv/-hӂm2;2+:pi[*`Iߣsk[ay~iǎA<uߖQcS/v72xh:o˸b''|(POa(_PXG<`jI[�qԘ D7eoBum/_뀗vz<)f.YI]q m,oCd&fei7 eg%E :CĀfȀ,R+$旯A Zm%5Ngbb8~ ׭"aSYeX*۬ܵy5.\+pZ_Ge2^% ߀dmQ͸k)l`MvJ̅ʑ/$USʦB 420gp0f̤鍒:`ގ3:-&£.py{BPM|`1#/#i?[�e iɠ=D)˂&7:`w}#�DSxnQNhwniczXBfhբ8n& 38+I$hAI)EQypBIB1ʫĆ3;*Ȯ) B)*SG%TyqJٿ:p.뫦3ELOlmLNc8�8-QKڲ.<3?<WfpQ] 2)I!Х?gpm}΍b|tS : ZҖ#`*!k .*&qNҵ$ z1gx =)9^ \'6xL/1,q_[7ϋ9waFaK%\7#Cx"_5(et 6:`A9֮tg#vU:+(V?F1@A3lxO<П,O?ӷBpOvª,ŇC0Ǐf 2ȲqĶ[�� �IDATws|JAV;5Us>HaџZ ?xvJ,] }%f?CZ _z|,{QA03We]wT<:K|zp[{zw2× Pz'cۙL0Eh 38+`. /PT NbPT%�C��K pG>Z;] [}ا|ko=#Q^ 2Ο#%WrŅm+E&3s=n@z>BӧܵSLgVOpߖΓS9|6ki/q% x!;iEyY,VKƴֱugȌ2xo`Ґwƅ`; Rx]o,cޗ(eO p$|-ʁ,}M/a2<A;>sK|N^诿i BkBK[[7v|M6o=n^8ϒ5i̞N{FB͟3i< 1(C?1z0O-.(+ xy[Jl2HRQ|/>OIÃev3$7~8VPwgY^ \vjX;^l'2yn%s! N G.{ 23ع 8 yKGs.;㮝;RTxqu-`NجAVAun&(KpbХI>%2q2;BZ+m*n_1WԱ)t5~ԁ߲?iZcjl1X۫M[h`i7um;]�d?!R)fDz9][q,Gy007'׶Kc^ nexdɆ�x/N乴r8֘?&n5*+Sw@((Paцf1|X,X_cO{#|N򗉼;5*)񙳸szsDӴͪJ_U!,_}$#:j{$dA,>Ji|c�{ ];Qk{z/ndρp-+GjH+?dxkUeDkENxvZSłۑEňY6bvrnmZb'$<�>TO-W摲*7v X"<6ϲPU\X]3FvE"w",>hAvM pmYTgKBOԅGT<v},�^^Cec),@H+n`|@=7R2xWX{#r9@sny#Zv֙1$cP}O! 8@F'ؗPTdtU&�vfMrDKJ,<s-=gNήmS1WF^;pgA0c(ʍA?˜v$�/vy`W9,B@v PyAEa01>FutQ|;Iִ1ٍ N 'iU/{tU[IA]X;E:6m_# 1�oS9Veoxn+w5 LF#qFhsG ~LJJ?+SQj0H*@A$:_kk}�`_ߪV3{<uc`8֍X.Y:;Tn9Q&vI.3�3GZmlފez?3?݇&~3r<w#F"KV1g/%t4>X[^)~<7&4�c{ӽ8"S<#w-i @FBZupήmS|8ȸXLSAr|7�qwɀj/<^tcL0pbB)ښv<j A$g-㛝/AdĎdMF>žGyP>$ w7 |zI2ɀ8=ǔwsǰDOQ92M[X3b'O7+l=龾f15p5lZgFHt(M_&`pOI>8~d0]| __ >9S+_77 ]G;V_qPMV:n823~gҙVpd6Ou}צ@Q^~`ѯ@h3ou;Sv�eKE {>]j9rrKT Iп:_pKw&]h#<|sp [ p>'D/Oof x$^WNfޞ¸yOUr,236 KԪ& C|zӽkq/S8,s/m[H+|8+3S0<$A5uՎ+PB"'cޣRW8Ι㉇*߲ǧXʔeS/>A( psZ.^5Yt;ie scB�EQ/lwS[9"̛M2c2;+8j 1*78\TCUQAc, Sy<Lbèh_MD;2뀍9s0P XW^O|jl9+U"νi.ؒk,_[N$ T:@3O;+Yb/T5*U#o�^ >6JJr<¢5lYZՂ|G;>s7ykvĂIFEџTRǮ P?u>Ϧ`:ԓWR/v $8?yn;21ppy};+'g ~,XS#م$K4*൥xw9#1zk9cL!c_1uyo9cU(/@Å&JrdG&<镙%;R԰zG+"+='ת*T^%= Xdڭԕ!T֝k�:`3 7qZAkXO=l:XmϷ3jwo Vm-L^p|6bFen,R>a +8{8ac0̩Xda3.Oge-Gl e9'Вk,ߕ~N|}5udUS~<IsTyO9i$X[NXQb7zQŠcWi=+͂2mf3�FvyQP\̮g1ˈE7_{юfsiY7#O/;CH S9{u{O&V/' O�([ữ stlՑoV=-0xm;~nrj ?i�zSџ.qhm7Rf-{m0%Ps/g5O:`wuݓL)3y [>xD?y`x^F gpxy!$BzlR <?.| f?X:Jk'OU `U2wo)|q~{qك'�<×!л)Zp[_ *nc=VC.fnS:汉<02{lG"Lgke~A~jdTv'ad?BL2X&eݵU?݁s,Cf-9eUڲbИ<-/ bw#'^hKg2Q=@=MTZ9Ǿ�: /|޵ O|Py+B;L4' ^.30buH >=r< try0~.5e9<A}1H>nxL/;'$zJ�^EAh'0aY_[z5Gc}XfZ~DGlunnLskX'i0wQ?YVS"}X[K0`J.  \Zk7Ȃ~\xOsB˵ ;Jغ`5Oa Ҕ-9c Mn@q{ڛެ,f*=_Cvu0ѓwi7 -Tɫ`T,X}<2|t] $N[31\  ׯysGJS,z%~]k$Dh7{v|,n6CwLT3 kZ3.M<{z:"_y\+Rba:tNvÎBf0\q-1NcߓQ%=>}AwGJ<wk7_hv<22 h 76mt,ׂX<δv>/kAAv<K|N6R2Rw ⓚ-;`cPULg3<07A=SUK^JVŭ0eT0X]o_[Ƃp=1�M AAA\񙳸]֨��tCxgC<W&p,yk@|<IdkTdC<?B`ߩ,ic<`ͅ mkXAAA:3g-6i[nBmyA =2z BD@0S$5Ǚ 2"`Vky:AAAڇv<� 2+8ָ0�uqg݅~mi@�z7E<   C;Ӌm #{�6uI4 3�~w;_[Ƃ   ա9osBV{P�ͅ:@AjwQqSH#!J`r](H^i[[ǂ   ա9u � B]y#9LdzPš""(; 8";ƉgjH9N83 k8e ?eDvicAAA}hczqQ1}8 =%+` {o|c=Y+I2AS2@ICxkjXw:/J}~v   v<aSZɾdc<)k AN�&4@mYk˸~v    emMWD;>sֱ   puhgv_B\7Oǂ   BЎf7*icAAA}hcz-ҔX<I:AAAY,֨9ֱ   puhgbFp7Oǂ   BЎbFp7OǂО׋&   O;Ӌ%piXڋז*'{yu?K?f's{Rq7j7nKO.M1 s#уɗx?[ Ò8V|M(,fw"f.=P%O=uop|W\ 7"/d #MSGa;);w0`9Gz[fC4W)0mVߡ$Kk{*W#Ol2m [GޖPˬ$O o'@o~=t< F\l_ ܕ묝6huzרqI,nGkZ3ؘ&:[9gGtf]hzo-gʹL50R~{t.<PnOLM�sxvO:hg�t#Kwnw~2H܏2lVmwL] XsBbA$mk븽ۺMɭon%/B1HڤV?x{\2<le@eI"8Ќ,ݘnk-q^�XV&f=6LŒtMD),XB]̙}'߸N!_e͇+tY.\QO:/ftPvGI#ϖ'&l ;E5-E maP_&;W,yAхKLMl?W6|2NR�#`] "80wrWlmzר48g5 >OC{#D5pV2L3rϵ5KF3qઉW&GSĢoPp;yiqNiwigf]q m,oCd&fei7]0sv,wg Fxav F?E�OU46#>`E_#cY&#"!ّ6b9+ j{K$oo޽GU3I&BH *(i"UWZV>jo[^ڋ}]ݶb+ % א@H`2IB ̄K"(s9$3逐Kc{[X>AkI! ٿMfw.}']C̅pezcM'�2K,T>)3 U~P _,H+4{H!p;Os-3k4.qNu(5s\=xrZ'W]R6`BfZ:syBrc˃)̝8sw#t-ٙYEA 7jI^k S_okUdX0n.QoR=T$2wy%M<�4L1[d�^j}$%PA n$ SOV0 뙷ݧtpX:LʼxCF<?rv[p Ӓ/-žw5o4y/u{ɱv?^\ � }tqn)@:4GO{�֑<5y  =?lsajn%'\ZJrhʬt³O<ރ<^Ip? dj僊 l~�{?z o^R-ܽt!«Cl߾L_Z?NBR]z;B~o4yyǿZ X-oᇯ)T9፧_w%cP`B/u w=ܐmmv,ox<׋a?{�^<^/gn:ibGu;^Qpd<Oiu.<PWy9 >׼:pe@z,rXäL礦~,{]:)&/Qr nԟ$?ډ=U2ÝY2 qnu(53\=x2r_G{nnɶJ8aK^h/�C`[)ʓȞ1ѼY`Xc^LIP5yx}pt7;~o'bKr7p DŽ@r2e g4靏y|ĀN{ڗʦwv3YخƎ7whښ]΋wN`K^~azO,nwYQM?%[/SdXwXJŊd:kqL}Sy$/r< rˣVYqOi南Vsǣpexzy=_c}҉-_^:dLį~5:_|@vBK,+)N^x rIT+fl�� �IDATd(ɝM8e{:̳k$2!o7gx?Z&=:Ͽ]WJ:p̾߯oϯG^N;̂ T|nƟ- u::FR.ӈ::8Pz|cDeC^p׺ ;*cHOW+^{ ya'Ր4S/}Lס`#a<v9{N ,:oX߫i% n+/a9{?Զk|s$ ^/w+rcVn͢j53o]η m{j`y2E2rkD:x5xpI,X#5 .dtg?`ܵt۽ Z2N ro 3<[a`tcKL3:'M^x<μ;ꨕ߼I9{peO([8kp;H1ςe+.$s{iPcpI٩vfN}Nv&2Y!gfξV0b bVbq[xzzB^d2j ;nT専=.#΁ڃü ߿lg˓Yq'h+JbL*Spb鬇+sww&eV'3B|%SY=\ƋpITPr+HbayO Y vo/)F΋•ǯ"!f.\i|4x<=R~ܒ<Q,IL3B~ƀ#`Y,{�Y4n(�{R``.~?Cܙ |fu vݨ,TUä̼>VM̢aӠG+Z [g9Xz7x gAjXvrEAL2gu7:#'9|z}kJƼ7DSsyM:Ef%ћI#L',5g=-Ƚ>*\*3`C{Y~K&uƵnz3f y<vG;`:�nIewΥ=*vKvN6XKN.x;0 >h?>,b&C: ]Nf]-*\ZdF,z 7FDdHYcۿ&��HDZ߸6�jMxphC5@hL�8جaX`O+a+h+p^yŰǰ)腔9;`$mCeN{UU̫=I)d2/أPN.#`�cX~rA˛xxegRދϡK&Tǫ߅/6_V%xKY>_➒fro,nAC٭wT;?o໷ˣ-#6 yZ6n9@J5ر,3Ji2g/d2Q쮏qd!ܾTx^_YZUoYOE7slaaqyG R%sGU+\*3PQ:gK,"czd̓TDf'$dL xO5"a7`ShlQ�<@?") ocN9$s{|95,"+`ƽ [Q$}Tw[tFO3; Y(M<<7/b:~g ?=,jX0-+ntđzQߴ$ ,ڳ|R,L]}ke0؁bua=H?^O2;KX]s{c+”Ȏ{.Syg0ww2;H,?:e|k蛅hnh:7~n ~_vs0 ?B  UؚblB^[ kekuŅaw!7mP?y(7:/Ypu$e^b!+J~ @1!,2Z̟{:O1]7bR9tO|R:C!>#-^.~4XO-x<^፲ u``7='p0y&3sj:ܱ8#p=P%_*<_GQ7󩬬, #iy.~Z 0<U{M ʘ]Ler1#m�Պ=)</0;ʑʏvK*g4.a�ёgr9{ry$888RdO/뻿 7R -x�/Vuh>恎tlsqe{R֐uKemӨ#V\-] pa yR\!M7t럓xz>6tػc}& bRn6Ȉ8}2ibrR6`#ιg{1Ƭ1ς>&$\I6 52{4縋l= gʒ ȞzشzL%Xm;5o`Z<-K2E4WCUM K lQZ;ɁsYSu갧/\{]l9L]U-vI.t Nxכh:.4A#PmyWC5(wAKV҃ZӞ}|&uS4\h .JeYv]Is ԟdZD҉YGKs)vox<mNE~R١8r-tTo:}O> n=-7*[8V_KU /O%zxZC C7&20{^&qV曨8y.ηpAL:n _>͵լurl&r 脺fv{dux2Լ^wQvthklfEà́7}(]:Hl 1' `Ӷ=Iqo SIl@VR$U#hj=Jvv&DogwpcDDFtJPU0oEMObO 5oVEƿ "pK7^?|+ƐOm'^�<AʢJPҬ('V#77)\l<H)eqE YI(~]ô yb PSҭKoĸqpvVsx )%wqg_Y$v-^^z_AQܽ*H SEÒYoq/ 8l)pI9@~q2 2 s9TY2!?)va-o_::eqz*+e1̼>87'kb�_C[1wjCoW'tTϬř`\dwLyǃrɘu3Z?;,=TƷ|+>>[`›MBd̯s.z(;мj<((婽ӫ禒16['4Y쿿eS>;Vnɶ9 N:߸ ''3a\BY \0o^4qM8H9 4eog:`g2yţ< $�L"&g"^ڋ xv�H=\M~4Ԝ\gvP eK`F h0qO0J&Ϡ5ckD.+`%дvd l|fr̋yݍ\URBv="[oYH:V=C_V7DDDd7kg~G{V>&ĜEFK7r<ϼm^|I$F̃̋Ed �u ,L{2GDDB9˹-X%9M7/6|n[Kˮ ma? |LH|ֶ'�0;nz"Ӧ <L5ԭ#̅͂rOC;IjVչع9qW>qfm \("j`ކ;{HyyHP#3/ȹ(/ɥ$PO-;{^(3ςQ,`qڊxFr Clq/(c2>ƼbݼjԍsmH0$5G_16X<Fg!G96FH1߀ť0R2""""""2:pQa3Uuqut -)%yC oB[#Sa)6X/j+.>IB/|e:[Q`8Y~\[b+p,'. ^<-k~3hpC[G~< pR'}]>邵""""""rigr._-u${Nu\`V~/kAnn[Vηh1&[I/ǖ|rI7NTfuTCW|[•f8Yq7\dA]{culkWvpb]y.�0o|k1'\̺W1칀xfLfu]\.g6YDDDDDD. s,Xϴ)_V_ V_;$0IFQ)`25v \OF h&ڎ7=g mNΟKFb 7ϧ٘8t<H fOϠ]`CRN<,¢nmP6g*SnA dz؁+/I\HgX<jsT$.5[aYj Ŗ!m�L>V<M;>`l6ϙ)6p Ea�n !vz)?_2K^l$끸mw7CxeF:0Q"΀kջ)lDuNI4(_�l 6 2;~gn5%No' l6o6*"_ʖnfIaf`o8\Y<sTp]i8oJ�琔Csܝv5kh0557,0?AE <^3έ݆ �7pp|5[r8[W7Cކ;ȥa˃~2sen,i05UӰu;f 6l]I1eа{dzqC#6iޚFn2pTU$Psyc12h$2[ ^Z+o8:؛ Gܰ.ݭdDIfno#/֛n4/ py|olẦL`꒹XYk~FA",byhA_,ʭLM˧jV$ϯ(O+͞3/$ di2cz\V| Vt?p7*a yl͛$ Kmi1o}Fs|rm|~^ pr];ɑˉto^$""""""!c'~x_1!<p7XWJ!?xjv}oÙK&r>Fw s`noÝEDDDDD0ςA |H3""""""2:pQ!C+O˚ta2PYd$pg4`YsTȘcnoÝEDDDDD0ςeQ!cta˃nT#"2ms,\2pg4`YsTȘcnoÝEDDDDD0ςeQ!ctaÎ@a"fno#EDDDDDdtcc@>n,4!'sPNpf4`YsTȘcnoÝEDDDDD0ςAC?|}A[H2cO;j%] Ք&-w/bfcΪ;)mXǤͫEDDDDDF?.L܉3gdno#/!nxCӼpv,\�"#ކ;_,pULX*!xڻ p{͛�YlcBednoÝCjlqhZHh}u3]OʊZ?^Gp͓IQNj!׽I ܾ( s7+7~ZlRt@<{p24 ,g\{;zMhŘR�x�_+tlc|rgTdHu [Ą%ad.L2GGvUoa{'lU݇rWf$UT`Zw =D*?${$wɁNUO7$q= 7%roa*4|EDDDDDF?.k 3mŚ`<6ۼ 1d̄~IEi^<nxܮ㴷{)4]DŽ(_1Y l&? &&3[SvR=;I,(&f:�v+]}s(K@&Xl["%X<Rmpbv3o`�1vx)��e(ˋf8370N/39}Xܜ4^(\Ehny$!"""""2`yTXWJ!3<rW:]m\>m|x &<+x7`7'q+.zo'S6h9x1ݘ0b,|嶙6?G*nKEOUH1ςeQ!ct4xh?7}\a=ɴUx6vE{?>]-ToB{-19 s ]Էp=hs v8䉧>ph!6/aY?!"""""2\pyGƈ4s{|bՋ =E>\vgYOp !XU0qӌTlyS<]c$b\l@ %/J S �+s իz)&%Xx&p~7[DDDDDD΅?.9*ޭs [wRjp6#%$O/].XӨްsR ,^>aaR|(g n<oA,x蜖ܔg@-ـJ`V&z<4s,XcB ^׮dĜXn vwnt`+5km[<ܐx}kONiކ;ȥa˗| lxHʉ'sRXt׭`KCaR"1(/Iȡ1a,dM0`] 䜟T6YDDDDDDF?._9* b!vz)?_2K^l$�74// l3cno#EDDDDDdtc%"X^lyoVnf D% GfD7.e X,"""""",6z�o;x䮹\w} ߔ� )!)?6;eކ;ȥaˣ2G8ޭ;O�� IDAT9-[)L<1k{8hh 0ՠtn< � HgX<*sTAٍ7 l<M %WCbSKbeR7B.6YDDDDDDF?.Ϸy1�K;X:=ĺ2b�M̋.X,"""""","ކ;ȥaˣ2Gȹ0""""""2:pyЍpcDDFta2PYd$pg4`YsTȘcnoÝEDDDDD0ςeQ!cta˚B s{,"""""" 5G96YDDDDDD. s,X2pg4`:hAoϚ\4s{,"""""" 5G6YDDDDDDF?.[?d2KDFJ7yg~G"!YlcB̹fׇ`o8\Y|^sT(+_.YOp3sď "/E"""""""2f zR_i eeeeeeeeeeeeeeeQzBDDDDDDD Q<f1CsT(++++++++++++++'*DDDDDDDd UgM{wnؾ,ގ׏d޴[�wZ,esS &\*?޶/$_kzZSVVVVVVVVVVٲsyoCʟ\؍q'=g{ f �<1I TߑfҲ(3+t=Flz}}Ftcή@1wPskߑfs} :='A/~c#k e\}>\.&fSI:i"n�>v rJgt>wjP6uȜ18sC%"|CYv~oh[?eeeeeeeeee屑5Gi^ݝ?+~G{[ffd^96} lk&`ϙI~D=�Lˌ"o4v6޸ Gf4 _&[0)٠5nCDN+CXXz{LkKb˛{ۏ~q;2#3*pB!!~܊s>l0-/̒bD..M%RsL'2mJȺUf :Z]DDDDDFe>b餲1G�"#UFtG3qIXn`RQǍtcĥg� )6iĴ3JX\^{nSCQIǶ=m$UgO ҍٶ$1GkuUB"ރ55C')8fk.+(a\S3 9)mOظ+H:Kb KaϚ@Lv8A(QIYEäT}ljMOC*rٸM"6*;H4 HNeL~Np5v:̫&=ˡǧuW'I'RvUؽtHGx!8NerI ָt�AGu]'1-3v7H(+9܅0Q8[b8҃>##�|>#ʟҜʇhBﱆ;epVygֻL̉{ iv愳 )߇ϔDƧMdF.'Nq9;)=%DѩY#E`Di`Xm}z41"ICdj=|g& xv{HpՅؓO }<nȌ`=!D[{ putQ<14rR8>I_w$Gu_򔕕G.k eeSΉ,FOv ۶{9ݽvM;xm5Ps6X갛*6f۴�8/b�Vjpϟ QyNSX,�) x}Ly|f ToFK>{L탟%?4#n=}!tqgC,}YQVVVVVVVVVVl8ׂ(+Js$pUQ2﹧l%-% ˸g<0)/{FA`]l842 %4o?="Ly)w#Ng޿?g>6>?Dm)bm9}Ұ{P#`ܸ7fwVߗ=k坵>D7G�X|ʨiͽ=VoVDE0u`OgbپzgD`HrJ"=x'/3iH)5xӏHY,x}>ˋ0u#QT$/kx4M-X�-.a~2b =9sIi)|58k \ >_ ?av{eeeeeeeeeeQϚBYt-6jkjoW#樈N49hn}E,zu^ص \pQ`c4hjĉc4뢻 �>l=l 4$T/*( ldnu:, DqJ wf;5|uwڨk ݿ'4v=(V֞Ϟ|'Zhq� iQ| eQ< Ϙ3noo73)b�cv ȉ}Ofdak+۷�k<ӲcpRC6y#Lz~4y{]5'v|@TR,hEgںؾ{\9Qi_W[OZŦ@۟ɦ}]TT M L\*fR\' yEF5#[[h߾ `YH`b^"}G'_j$Ddu|3:}fBtqg0 rG>{Ǐ>44GzBDDDDDDD Q<f1CsT(++++++++++++++'*DDDDDDDdc& 34GzBDDDDDDD Q<f1CsT(++++++++++++++PPh����IENDB`���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/docs/fp-crux.png�����������������������������������������������������������������0000664�0000000�0000000�00000122202�15223753015�0017110�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR����/���*J��� pHYs����+��� tEXtlogicalX�441f̦��� tEXtlogicalY�210]w���tEXtscreen�HDMI-A-1/ �� �IDATx^{|ײd7;!H$`r "TAZ,zZ=ګ_U[OoV=ТJPT. JD$ $!!&;cNaC4|/gf/!ٝB!B!01?5,Ydɒ%K,Ydɒ%K"<B!B!DFXրNɒ%K,Ydɒ%K,YdoO!B!_rɒ%K,Ydɒ%K,YrY>y B!B~=$K,Ydɒ%K,Ydf.3v !B!�>(.4vR[sceϲAqa-T7B!B5,S9!XE$5ίB!B!3YNC%| e7v !B!9'�}ZeY0NR/ ujmi4"J+J+J{'|<܈bA4, hec+ucQ5ٟGXдvݬ.uvf'uK[7h?K]ݺY@׃ ϧui5|O/K]k3h}͘3U7h?K]ݺY@I]RORgn?~f'c5 ʚǃ DM=YRR7c_^l/Y䑛%K<rYdɒGn6\62y鏌 Qx[K=X= u4<h4۳-N7ceVZiVZiVڳ׺PԯQ??ZԲ'Ͽ%vr,@̨Xu<nw:&]a:{o;x~$Mk䮟\JdֲM ▟|N52yi =k= Foq~ EѼ̀mNo~(]£i9n`둺ԃK]Rԥ.Rޟu@36zRv=7_vh>A~81_XG7<q[L57PL=4 {x|F78䑗Pgykw<_B?pe~ɒ%l/Y䑛%K>2x ,i'w-:Fo{:@`.Mhu'J^un4-pck5-DZ<q0Y&g.4X3{{u7wx}_׿m`|>ouoIx۬•K9_ݒCҥ7etO5Ӥۻ);@w|6l2{q,iP w6,Yf%K٬_s0{ڏ|بغ|o36Y|jݸ<`Ƿ'KjXհcYN~lRg]t< udD"ڲ/unضc|qpLE ?9I sl ,ηx$ݿ}hG&-~M,foGq)]EPu '<{=CbAֿZ=OGc㖏~&OyeL̥_cŜt̥< 73gg'>95 iVZiVZiVڳj@h?\ ZX'41wL@x9O%5:[L&kf'v%÷'3:ifq`.c,PGGp=uVnz Zp#]U{G16?KF~*{k,7Ŷd.;%hIZ/_º{gb<\g\A[,d5VOxahnnan \+inq�aظfvM Խ[7n ACld_C7m/nffwޫ?O &Ydɒ%K,Y!s= c ]eY_JJ->#{jK3 ΧUAa'1-WsJ'Rr\եfy|o�\pQ4Ȥhm T&۾47p2MAVL*!|R&no!/Mas[@;YoXckݏ\sn,z̛[O� ;Y, KsAiq\ǩsA]qR3Oz_oy4\xf ۞e|.nbsy W!(|ϓx\4_�Nt{oQ wx}G:yGu!e @wNc3YA~%nlc vvW.!"9w?Y%m?*k{eLv=r7^Btylމ;~5Yg`RT=|Џ5\٬_d#7K,yf~ɒϕ ZzLo@Oc{8 IM8:\��zthF[: rA-G\wԒD*qT堻8ݮbat{?yOuw= lVV\ѺU8}[13X ./ QgD8?||>l~?mbA|[|g/g=ǻٶn92MķL}˅0vY{m?M-_;X"wk7`ϸA\CB .[)x=ʎ0-ٳx˷'WgpqLí<NLJ*ǣ$6%=Vv>m|s|:-x3sL3=|f'uK[7h?K]ݺY@I]#]vgDktLud+ 4DA]dшzD?}ջ*;hlWU4A4xzO>x;C<mzjz? }^7#,'5wpwܽ-,H/\&WZFbB*>O1 wo1 !fMiT=i,羲Z4GthƿUx J5‹l~Iw|l \?/+*'p՗SJ.1-UǗshPh9eԾMj )#)e8x=ϐ9;pTS(!~2ǫ [׌q~:hgI[t1{ۡ{[RmWݬJ=xz~o+vfVԃ{Xۑة T )uA;lрοbjϼÂC(Kp@4U4>@z|2I}_ځr\yl^vNV֢MrсBws'4:::U|ó0{]Hз4?}ϸ~2˃;lJT@-<NIc!| cռ_04(}߭i\0vF>^DžG̚w;ֶVҕhT4挱y5+cj4lh8hFCBwn\4;1nZzmQ<RKšb)-Tn6߯cu5ίpm0'~^5wFϗVfŕԥ>ARȩ.ZwK2Y4'D#hE#=7])_ ES"phc'&Wυ Rbٕ^~ĚfQ+|4-AW{7e~\JB:U`7cy"bPvVa;5vPv�5G(n/ h zJhg12;`)<{`xgoj=2'% 9ashh?b.[RUa܊{R 'u6:`lD_K 1h=庉O�::H%|VbEB~sq~ uǂ `Nz;xl/Y䑛%K<rYdBF빴@>ǒWO i,ߗ\—jVOdeנilh,ϓ�9 va1IwVcK-늓q) {$1.E'Qv"[x $spǭϏ\ʶ @P)Q p|[W{;.'c=zϸP;?xϰ=I~/~\NbFt2. PU4:4X==ׂsGxerqM!D]h9O8!-sKn>o4\@G~S6Tl ذXc*͇MIk fBCDsx15FYaѭM9f| xq6B{F`Oz<+K,yf~ɒ%l/YM' R4~?M L<yh<,w,?ǧ94%|_݂ƍy{y'Z4m9`!AxѴX,|gXY,5,YK4$Ю{K _: ~Aqzqdw!ylO+E4ͷnxkw:V6sr܋GLk7H T!M? =*ʇdLOT.W"I[p)>REW AqTX)5䃢V.vb3l?fT1c.~9cmPo2Sn ڪr$]Hy1xS xKC{H9 WYd~ɒ%l/Y䑛%K<rY qduE yx<ưe,< R-�ڇN:EӘw^g-}`}lͦ㍷qq˯M|x+gcKO�)VvM{21 / :>KO㭽uD\ pE/\kwIs/ĖpS5FO gbpFƶ3&GBcx1k x3sPd>GO(<M sQVZiϝdɒGn6~Vs][,#=:ϖG~\Nj/n`%S{ {v?7{No~(7~ l=ɮG/E8k Xlus{Rf97WjvWh~e}g5K,yf~ɒ%l/Y䑛 گNw]6{x<`@3uݿ2ʂ(3"Cŏ}<`{SZ<�4M4=V7l2{i=<<@? 0XΌW6,Yf%K٬_d#72OfyP<@_(]kyI1U8By4 KOsBtZ<J+J+J+52yi,8wp $ƊGiYl~F5ٟ~ H+J+J+Ҟk`)px}4Xx4k[W Щd, N#/3ίh-;%K<rYdɒGn6,Yfg3yP<.AESo^|>%K<rYdɒGn6,YfY={Mo{ֳԥng_^o<J+J+J+fȸ~2ˣ: ׈Z -hԥnd_CVZiVZiVZi=Z31,hłǣ/K]A~k_B!\eyP<xYSa:I̷Pf [.1HwlL9%B!98 OfyP<o~8ycw~: !B!θ~2˃`_CB!Bg\?s5 ,D(Pg!B!O< k % uB!BqdG5 fYP2ίPg!B!OfYy q~ u>UK&3?<ϟy/^2f7;-K&۹3fb ֆ$̽DLX>c.~w?qMh?6;\ƲB!"'cXi0޿i[]#q~ u>]93&uulw�]p.9 5B!1+_ф`T]dKm/m6vͷPP{h<_ Kn>>B9ypclTSr@!BO,+`~MYHMIc+LɏO'Jx$aƒk!6cM?Fsˋ%P&q ^zMloHV~cT^Z{{O͝IoHeSG(ycɽvxaA<aec\ jD΢T׽Oc{뗥1~Wiw|XPHt@kx6{/PNڿ@DW_A|\o~:x�o1p5<t?/B!qdbP0!/U!kSlU,X&~c)ǘD녌e-sL%skYpK>֤Zb^2Ņm+Xr"i*޸W2ůH n5~ pD$HO^+rA[ayI {45y"NjZ@={f(Fϵ_܅ooCaO<roec{l*6뢹'|]}=h>B!BSg\?sHy 0ίΡPޤԯ6sԺJn\<ěFdӇVJ6i;|j-5k7%vɭ(IiGzmkǞ;#yF$“G8곾=u"m:}�MGH,LFUrqM>׾4e7}c &PQ#Lp3q2ISt#\wI lNOg)t(w?!B!9ɘC~!NWJm V &@FYJӁ%} 9BQg]**κ6"q &'nމզ`T흸Q}5Ŧ;p6QRR[X.SE$rAJ%L V lkmXT(:Lק?y,B!85Y{q:+LO]e'릕Sk\:eu�Ի`ÓsidN%λh <P7OD)MWh LNuW@x:_v^BvB!BOf`qFU<x9˴S8#o%!Xv6JW`ϸX:PPp@p$/|BP{/IR Nn_˸PbX{PpTp={\jc1ㆀc*((v&PU�n \' TX]Gп#(v쮠qV`܄DM&|B6'k:P]AB!͸~2aAI뷓me Xtl6K8:;;ג8cEM<!Tb;�� �IDAT8Yr|43.V\1$ rpjGx?`L mVu2WKh:%Qn#cҟ*'9u,DWtJ)?:@p^wPs`;qs'j)!,+�K#=un3cbIu^%ia6uy+M!Bq:'c@9Tx /mC:D7n"<X9GqތiE/n;i*l4˥fo!/J9VE޼<NFLuqWx TZrHg#ާJhfR"əGSD:;z߱J覗9/ySLE qj6�떱t<�/1ـ~Beʌy"9׈[̸ȺnsNS?alhB!BSa\?eݣTL\Nj/nP޿p咥Ԟ4|g|kovZ2d"L oO[,ʌfՋNI_X Wy)sRcX%jo9LuvY6-W.%*'l;Lu.tܘ Va;ZJ,vՄ`J{%%14( 1S< gƗ#@}׭/O<5,BCuh[ U1XwlL9%B!9X  cd/\]<zYvuL ;_9øG+@�R#Ȟc}x;́>5V-BI!7Jr_ x+Kf$d;X]|=yDG^܅)8f_ Ȍ< I}D/,B!"8ɘfJܔmMfpwZ9{'0Nb[8ʞvZ'<^ɁEMuBbjh|42O(S)|kj_-v,%NJLlPQ;hݴg̔0x1QԬ'*kB!B'cV@!qgC]Qm %�P TQBnZWRX1�p:�p:UljgPQ.@AQ*\}5XZUUmGo�@I 8ө[l2 !B!θ~2 g5P5,Z۱I*h8Jnyӧ2}E>Mh-- uB!BqdQv+(d&Qڎ=Xs海077K^PZdp`POO(U TT(�cOcz#kB!B'c8y`CmlϢLMYsVH7rr4&` 3-+f>}10SPS$ Y͜iiTNvAӦi gδ4jIy~ҟ.2377ab05Y!B!Dp1=cE"J`ݨpܲp.M"Mz7;v+Õߡ j}1D~fQ˔ZEÿFm.7ٯ˯9ߤV [QK96Kd_9Uθl2 !B!θ~2g[˻zsß^(%�6ֱpn}oz7~QAom.6_bTaO>e]Q O;N縳/ uB!Bqd޲wk&d_C}9! 3B!hBGl=NOd_CxdE@B!Bs_x]?(Яa7P"+Y!B!DpY4e!B8BB!Bg\?_hFܘ%,B!"8ɘNi0f!B8: !B!θ~2fv,B!"8,=İ3ίPg!B!Of9W51m/m6v q~ EB!B1`)pxr]0e_CB!Bg\?@ ; uB!BqdbWB!B'׈d_CB!Bg\?s5 ,D(Pg!B!O,<8BB!Bg\?e̯i0Bq~:Ki?Y@ Ȣ7՜믕B\^/ΜKS,,Fq4f!B8"ʭ?K/?h?o~kB\^/Μٿ2fsL[O瀓,D(P3EcbO'Ʈ�_c:gg pVB1křKS#@s`'c><6<(t{d-mLq(-/X>X5qz+Y!B!DpY43l3:Z|D"|}48BB!Bg\?~σqQ { tVNMآ}\i4e1ίBd r[:alZ:B!BO`)|y�5*ֺPrTڙG .xwU{�Mٷyp֒j/WNu3SV"i\7D%c O36^2j&YYb>љ3; PzP+xx!f;Vrdg+o"|(na淸;a̧xE:2r!'B!ٌ'cV@ rDQc-ߋ}zRS#Hmwfpe<{ P.|$}lyi_MTZ�.l6#o^ 67w|m_3/m,ē4ˌx|` GloO8og﫺y5<NŸWe9;Gpwr ]D xe7;miNοq䩭@K W%;K0n˅ܳ~a'*dG6VVX`VYkM88H1+7{򜓬py&O_ !,;%n_Dpgۖg/l>z)"KӘs-kB/ceMKylK;meO7'Q{-}uʬ+߶4S}K`t G kwAd}L3֯sAi슼9x*`Mp9%M /(h7&= n^3]sÙk:W|Ǽ.3W=%~q'�}Z3a#(/vh<N[T4:Tw9\7M{l >n".;նS}3puላ1&@ 쪓6;kfq%¸)o9yq~:un8TBִ`zVLUX9�Om/"4^.n5!bvm$PPÛX<6^ HCAxJhpNߏ?Y bh@ks;X �T}ζvd_}pe1L#bǒbG r rcM;YPK/cki1tUҎ u`/#_|$^c\?~d;ŝT՝ GD&}\pp]Dj25zJ>"#IJmLf48()`J$LB_ Nk(pyò: X:5i>ʚ(’|sH6ƷphZjo^zU䰵 40B) dN6F5r@!Ĺ yax% g~ <v>ѳ&=VA!f!aF"()-aPOTw I5S� 5Ja# آ7 *;e.H;Rc+1U'KxEG<p�h%װw߇\&_=2LN S2ίgh+Ԅ٩<$_^6t5w/HFElmU=-p/,~rɦy0VRrdh 'Eb9TN[CY?yg52Zs (yILz) JEo~;1f,cUW1en<Dc.Y6-W.%*'l;Lc.dv^Eapۊl64sXYZۡXy1b=,bk&5g-.n w]ܘ Va;ZJ,vՄ`sU,H귳9@l@"TTwc7G|1/mUQp3+m.17)+nܵ`*N <e 6lE=Q}"lzS]mg떝8KH&c"& w<bQ[ōQKLu$bz8+teӗRҦh-7Ef=d 9%02xV+7c|>{9Rj &cl<SWpw5qGo0)V-M|�vmgGInCҘ~^ 9uK1u[}4'ca\C)q~%�6>؜Πe>"5(G,lU&5w U%Lu8A4&@ 'Ìl)ד>#l_� T:ogMis" | e>F|&tw6yaL k >w<;#76 ϛ̌h"=k"DD|D^>cj[2}>v¡̉p[O�ΏNVp3ɊPJҨ$pcrd%X]8Cn X6-"/ $9ɼ̢p\{%ٗ;WY ,*i&*E_jT{.Num\42/bvŐY2_5X4o)O!br{Yp>kU?Tf*oYjoǛ%@y !".DЉ�Z;>pId&Ba Q Xve.yrpc%]>0R/*]-+r ꘟB\(("nV/c|^+ z-ho'ʥ<Y5}~�͏h|;)yrK)Y6/tywah\<Ǣč.2$y\uðKSc{n&RIܕFOgőoK'r]ѣ}y`Q zlr+@v1> rSAr- =@>Ms˸~2ˣ> r�ZHNs*g&)cRDٮWN :1O0NMXlfڱ;CII;U)?!̤Hq+y8L\{MdGwN f2sLJ;lt7sLx'۹}A.S/�%wәs4J;5hkx ,߱jsѕfZ D^f(nw3gaR#uSUSGDFfbej<oJ,~f@pƮ +IRPbɌ L!;\E(i449S:/իu^CgS3gʰ+{s>C$M[XqW1U9QP?9u+*i}w^LZ=v1۠p1%lشg~_M!Dh:GL<.JrL~,krѡB ˫8.鱀zFJkS]nn)` 4R`1N7'td2pΑC9X^ǁ{;@O31Sf |thETzNv|ć84#=t4()@i5jap`ۋ:Y0k XYbyǹg})E]h@xgdf\?UcCI|jzp!׾hѓlX> eB$Ir$'%#vqL%yͰ!2`!~Rc!z6c(8 =t+St"q~ EE1fC x1ȈQn&nMT T }f40W c𣭟VOi omoXmTEܸ|P�T}W=*PQ0&ڙkk�z>XL][C4YiōmO:R7L,ivS{ WZ棾Zsv]{UUQvTS;A#bpZnCd5-DE*ɃF t:)o~?t;MEܶj>E),*;nE_m_D) Nw@&vf:f@dɀ?Xq8"ړi=YK$ٻP"QAQpu "{VW&G':HiE=Qj,d JQTsX׹hԀK(ΖO0 kcr7DÿԯY1+IJ򁛍%l w7| X95So2׌dwn8E |6X!eB% I?M/2F:Z{Vr?_JƔKvr F."#lҐBRJk'[H=rpEMʠNyFdӎ2&֓c융BqnhUAqNX3qPⴂzf'ͷ.xlA40+/YS-ZhZUP>n_Ba(Jý`L ##1{o��ck^|V8i,=?Wngp#ɘG}i0P"+y8V ?-ppVt3n@�\VFu�J7F۟}o|z`Y \@CX,V5 a@zZJK?aX%؉'n'Qm3LJ<Oٛ[Il{<*`WTEx7 JɱJJi=ZJjbchpB%1ڣ &ZuFxac%yLZOsx]sUwa_G+QS"p4/BӧPQ#=@\JcRaVnb"2/3nqc8cSy'nLOdT*JJQN~B\J<~S;{W{3ù{)]1U1،` 7]4QTXq'/l|D%&bUfy/Q6|=i VU(1٠T)*9JII)qjmeW& 'rLƟ[43@<\fF[!S0iy`'l$$! G3rȍ*H֣b=lןVC{Я-U<( [`!rr'd'%~لޏ?|fga2|6Q/JTOR_HγW9s !4᷻Jx˽<NmuAOeӉcMPuL_]imc? 6ȓb-̣d>FffaZ5^A.j bSR30lXha�Nub)'u�� �IDAT6%S&X�/KrO@{^D^ QcX г0?^;l ~\C!XNpgaJJ Da)=aW#gRZE70+B! 4K-/Uk hxŖ&kΰpB't)Ѿ,}.~q4/z,,(cl)L̙O ;0ܮ}N1 )ѢhjN<YPc45lY I<tKCN`w]nM7| Y<F}1p_bJR ^}Ǔ$@L.J(j8Q0P@y~ S $Či)h}h5}M<t,v#]roYӠf!\Im_ȗR ;Sa_w!L@ H ~<#g?,Edax#X3L}̣s<3!$>3w>c(kh&+J6G,03<}m73^ϫXoHkna55MexY�wЍ7Q>dn;�m̪&eݕYD<t-p)Yel*)@ai XB􅦋{uD}Q1eفxṃtǷW3c rӓ, k?b=@:F:M$nC SOB?_X=O.oekNɁj!X8SSRhbQcou~G=v+l[TBIO?[Fإ K~:Dt#_fU(n O/ Yعv+4ʓ$sTgPun:Vbݦcpw~z<`{Ju׮kouuYekFQo/rFzK9g.k@h{,@EA9)nW!wGut"mCv;\]^bm! sYFop˲xhpe3ƛ8C=6uX<vTӝ9c,yEJ?1z϶%''d$|oTέx]�n2}v?yvQ]U5RB,>*XWo?<6v>2 )?yʮϭ'?e7RJ߳~bW<vV:zC!zq=KiSW6UɜSۗn^ߚ6ضc^Q x֔q B!'c/Wg{0tDbv"?G,k\!B!DϤy .}#v|M@Zm]qГ;�Z,B!RS;RoYWRۗB!BeqɩY!B!cj(1 FYWRۗB!BQW/wg!B!'5MiP/w HtCҊ{%=녫IݥԬm CGe!Q{sevZ$zQ-BOդMPOFY1 FP-Wg)}:_<nx"a@+!\/\Mڔ.d-殘;bZ$"V Y!B!D:fypZ$J",B!1`QgYWRۗB!BQ c/Wg!B!'ۮu•,B!1fypc%?)*\Tm` ^njrw];EB!BqIMfZtA5ah,8jo(B!ry .9}: !B!pL?ea 8j \?-w-(j1s0F>|~;9/psf=mƄA2n#^HQ_^>/GPۗ;B!B9OuW$i$~z>Uf3;# c?w_' & vpPMB*s1 !B!pL?70tYȩ #󃍜<T{Gy-ܰJ:N8/Wg!B!',sЀ +�Mfe:NY!B!cj(+{p%}; !B!pL?:AWۤ&�� Y5ZPub/t4�|40{aO_=?~LMcY!B!cjI2灁BhSD0_n#Ka6r,m^ >anwD'1i#5{8)m;+X K64x'Dn4djruB!B2i0=p-p˯�Vv3p36§/數 ;N 3Ktrw TpvSg_m ~)&pr~ jruB!B2vë枦 ]*.`%% 3-_k 4Ml|[{; lL}uJm_B!B!:?1˜'3&# tm % }; !B!pL?Y&8ʢ]fN~ EO۠G͕Y!B!cj(_stGz)Vo0@tھ\B!B8ݰup%}; !B!pL?Y<ھܝB!B8,sKQ{sePvnQB!⒚pT[Qv˜J"! \S!B!.+?TOFs߿[-!}; !B!pL?Y1 j?Z$!}; !B!pL?70tY•,B!1d{,+Y!B!cj(|!Jm_B!B!SOjyiP/wg!B!'5˜SۗB!BQxLQ6W LURۗB!BQƦ&GRU$'ZdHm_SwnGj2&2R|x<KypXP7BqaT˴þvl ҩ wsop!o !8Ouv7jj };_ cW PO:kÇՕB\=ia@uh4uoNBG?Y&8B|EGSr ꠮*B+8|S=^?!<ېǁtր̅B2.@Pۗ@|4NUG >:_rVn8FYn� ba(éx}G2FgqR�@6j ̝IL14?ҪPϤXovpohoZ"W#+`mj ̞~j[b�44BRhtbNpjtx~KE_@LC5֩iB'lUq5 Jjrw+RUP'�uef1mP bYkXzFd0m>XUMnFV 2JIhl4gՓhݽehLJ@S0ԕuZlB!(mf|p=GvZ<C LK`x#NBA?-sjrwb|aSX򨊈35TPZTPapr 3Elj:ijfh(*@G3VL̘x`d�C&3~Na*az0,=4 (sZ! !8kZ0LDD3yTxRZT𜚠7ci`z+RWZ”>m&rr߅B jI2P I! t&~0u·/zacaA2#V}ecw,Nvڛ+@bL@ fRXֶCxP?{ 3oT4>q�NkfW�kֶ>&٦]0ٞpZ} ! 43g0\"T3Mk8;O[i2< !'|yPPo| g7쌊2001 DﮍW Ě 5} 2mjH3㇄뤖_ЍOo�"<M1'̄ςwEœ0e!ZkD<m= TӈkBqS4?4?~E!=2vqTsOdB^Ũg2` �&wlSNju,c~!n>W<nW2}#_M}"iޘ 1›*p*Fӊ J"L;I=>Ort<8\O]u=sBmn �dAY#ФS~vZ}BG̀ԛ&Vꀕ;I8 6Ω>M@r_'34}:B!zG`@� g֫V(/! ^vꁗ?;IW>ݰ:ft4o'YÊUױϷqVO/wQ6d!/'S2R5|)hX1j̚ 'sL  4"MPa?mkv[!f 7;ҽy#ZM k 0jϘ`Oͻ; WQAo%^f:w!=Rsoa訳|5zy[9e^x%w(sz(<p&( ҁO{@i=ھ\f>)KbGn=y,gf@p|0sgJ؜]\$h$p,3&DPm @v%o BfGv- mbB8/b}YL gstf'`&"+=1�:}0߅B\Q<X/8{,N6a7$JWG59o|UHy? >έ{:}:t}ǵ@ŹM� �^\0G'x!ue7DS³?dOgwwc�z3!*TgfDE${kRSӭ|cڕ;st^σB\Q{LӠQƌ95Wq|Q_rﳝ{o{3o|PX Ƒ-J=ھܑ/=PMgkfZ|IћQ̩Ǚ\P�N0ݿGgajBx;rCZ|EýsFB!0SFFq7}bCOѰ[,p Hj얹+ھܝm5Sբ#{sѶpd�ٜ}O"Li!60iHZ,B\tjI0t|4QZp= B𸹔WԢcn԰xwk_}3‰&Z'L4 Э^njfoӕ{:G͕Y\\ɾ&^X0 .B!B\fQ9:q'CxNnf-Kh[2>guqc�^uG ߄wmөY!B!cj(+Tƈj4nZryDrt: n['abTr݄!0v rτo!Bn?BlwJm_B!B!SOj9 \~aq^R7'EţxĝSY!B!cjIͽ6β/Wg!B!'4e!\Im_B!B!SOFY<ھܝB!B8,sKFm_b-jB!BjI0t|4Q]7WfW;ZH!B!.[Eݦy .9}: !B!pL?e@\2jrwB!BR[<Q8ھܝB!B89rrsT-,B!1d50`LfZ$D,B!1deqɨY!B!cjIv71 j•,B!1`QgYWRۗB!BQvBtھ\/[E;Z?x$vˢ{3i<jeI7Vux_84?u:ke;yA.wޟVn?M*&3q7b;u?,k3�s|)+ARעw2}V?`^6?:1_O?~Vۭh_s/`|wG�Yնzlf/CP�Jʚ#do^Fwa҅``h;\]@Umjo: 0:v|Sj3Bv` նLKɖ v+"ѓ 7Mc{mR4&4 rzMx)oXUP @OX6=䡀~|UA7;0Dt58V5[Ō̸G]SOFZMP/wmj=jQG-q<e1p93�Tۭ�}5<DmS!zr,Z..n+Ocn?Vm!x'/ۛH9b2m`>xsS79}q ٛd?HPw{+jC /39pZ!i8캣N/s,|Oo_efTaf#?Tp>xk-l"tBTFNXxd|c.:;MB ph:;n!.30_&̽m5a?OxvA4ɼ4lp_<�:#koONV#8Ouv7jnw"!Λھܝ/Oq̓ nbE:ǪY8Ig~͛B֚lꪨ+bDN(ӦPth527!lOTZ"�~|y "LGs +(wmf׃OBEnwioH B[O.XoQĎPH>S9 `l u.ʱWrY<Ђ !|5kb٤(>e8x$AOԬm CGe!Q{sep_E]~x2qV6 4�)N*_[ >4 wy^90̲Lc__QN�6c1!D$0�GWix?EL'jPk{8bk v?g r|k CZ]l[@]yV]Ǫ~통նYR+do?! }U{7#2|ǵ::!8;eOtx?u^DF5L#_ ]GuvSuOa B\NXǨ9m2&zx%_[y?X+N,詝?d]cod9�$:۟'5|s?lBQ{sUG\SxsAe&<9G<<Z{۶i^Ϭ!APˊ?='uWY Zư;#Im 韙/}Xx9�� �IDAT戀F+>9:3 _Q }Hm3,0A)L&8O-J&>>a:pΎh~ ! w8 |Bc-8xx5 vZ Ǧ yvTF1 I< ]:_}qOB'Qgg[Nbz1^VCuE s&YujYj"?}0çMɉttuЯ cBn"+E#rˏtQ2 6f5څȭA9󾜏|+dh 9odgE睻ayl;gsdc:挬t%K} 3#Ɠh1E� ܌fmC}ח [n6N3@f�_ DtGZqJhLωT zQL2 ʒj#:&pLl3ӀѤ:Ύa !)V`t6|zNDf5k!|fͅK=m~YH_FFq1ElR?/H;w8MܾUo::/Tm^Ń} xc۲}5bO(Uw2mgm]X}Emª;M}NcO+1g&y yMl⒰Ϭ̍� w,DW0ym0"&tm xw !>0 tjm_<.ER\K||Fׁ{;wrԟnt\ YrOW+ }4V7cs|ܔ ɉG`:̼}7� DOu΋z3m*Mۊ'GƃnNg<�O<{~z͠O"dL4-o+v_qȨW[hj7?KX>;j{[B0[st Is;-m X>^ mNVi-$X۶:/~|o @bF{G 'FHYDMr4_Ϙ15aF^|4?IB\Lvbidn�<p8QXfz'i_b?)boNjI`8A䞐EL 4h$_+ayIF˲xĨvYw^i<ucxJz-pB]w ,) 4nK1!U ߽}` Vh�ܴf'OHmV@`a}X]ʘR Q煊& IӇW 3pvX�[ɧ/է:}Rثpd1U'px_]J!gE祟',6ߐ%&hS�{;WSOF7pNGK䞔E(ҟ:LOMHHv=ݩVʼjA ëwd=h}WUo'j1k 1}H �*˫N_Qݦݹ?˪7ᡝ-xΎՑr+mYqI;㓵80fM'ċǐV5̪"I? 4oOڿ%̂8;y#lc0"̝Q3uߜ.`[ M@qmvV,l:TE4@ ԝ=Ttv>O6.[-!fLKzr XTCcmf߳Oқ�1DŽSPau(E׶3AÛy} f ]j(}٦:F\䞔E4֖QPՄ nf dӱZKXy9tfr9wMy54i"<&AiNXP]H-;}d|ALXUBZU9 ؆f8ڟch}_7;h,WB\6]9|]y2e٤ھ!KQN ML0$e]N46:MU6bl>g=:Gv3=_7R7UdmMb_h}`i/zζ3ɪ7:ƦCe~泥:_D4(A"_G/AY޿@Uy\5ZwX{%DmH۾)&n= v=q/ēYxNɒ{R'Sٺ ?^@I<8> ?<F: A|^CxdFYӱѾx~60H<w_ fkiIcQo⇍LNGud߮� 'l3_#~xc�4'A erU]Ď*6<lZ%,KƲ�,N%vШi吺mGF2{?^ʙ˳xoxpV,snOpۥ_9dzvθNg}| ?{i-� z2慴vxkHmvˏ|FN䅴QW+&<Ʉpǰ@^ȱ]5N S磠ZO̎7<6tF?,a_6<0&ߘOb?�c9a=ZKxpZ]ih{�<axh^nw'5z϶i,JÓFf'�<m뜏];0wj9oÉx͏?_ߥzB![2ᚩjqx]�n2ҝ:f [ YrOӞ dWX^b?2b!z !BcCF./qmgF.ě8~J-p Q{f:J|R=Eu#zB!Wc{ԇcZ$:pԟf)@䞖B!B8dRV,e!B!'0 YrOB!B!SOFs OV.ąJw\B!BtQcyiPsW q!n,B!1ny +Y!B!cj(k`<(s]EY!B!cj(wy΃ ի---S~vJm_B!B!:?1ל�A,ܑھܝ/-["!B!15ahQa^$KR6⨽2­UB!jQ'4eh@~ھ\B!B8r<!dβJm_B!B!:?1wk΃O[ZZXjU;luKy#}; !B!pL?[s8>cjQ/O^zzs/<[X{/AGyc|"?<ջ O_qz`V:?Yڋ4*>-sQ{seB!B2i0ʎn\_ᱷp@1SNCwk VcBuq1Q-VE[Ǘc{m_WY!B!cj(w{'w䨾+),Թ8-$.sQji93~Ekg]Eu*}# !B!蜣Tܭ9uũE<y;vT뿼i-{Q~<`v7n_1 /a:SΩG"?|̕燋܆/o&d]K^%kHLALc}z ֭nߢo ;? x_19 ?�kNG| u:^ya4`S,y fqCھܝB!B8ܭ9>YV?Q~w'{g^ |~s  &\ضK/5$hOHaof3#^Q/+JrOfĐ?miE r 5N!=H]o߶՟g#y e5)o;`SD`ZL;_zy#֬#;Wn. Cؾ˛lbil,-~C'#ڛ+B!BQ֜~AMzW_?;wVade{ѫ",KD GuiJ2 e'  1³B?) eoZZl777sBR̷ooQ| }v:lDaͳii^tbBQ/Źx A`§&4ToI/W׫Ejy; <8֓>MʝJ$i,ܧ1t;GLn,'.w+Y9 P|u :^|o Trm}߻ n4K�ļ- 7GѹcTY>mu- VЏ!mFW/Vjv?>֏|+u;0K~ܷ!p�%VX6ƌƆ2%`Sjg]9_ǩ+5g an무Krl`a٬hF޾Ύ[xehWP/&.zۺ?oK+fYkKqݰOlxOuI9 _F/O݈ۜb&̠+׉ӻ*}r;�|U.9d5ځ;-Ͷq|P GUq o�D:dzd܎W),$ ٳξ/6^jm ޾^�xzRft1ЫA7:^4ZekD^477M nAS'ھܑ/ÇEddE0vGLjfT�k/r w)=՚z ׬Pp#1\_C\V~9H<J܂X#x3{SٶaV81Mn\p<>0`h!,t7`>puˮgͫP >~vV3x_G &-[Oe]थ'28ν׹r_ݟ\Oy*aa٭'ĥfx+.kh/ Š#u}8=s?8h*=T9:~2Qw-}}z>Rr ESe3�,h`OYЩ7! R?o bPr̃Yrxzcl<Vu\c}|OKkv~u/w%:kwN]uB`x ^]mS!z::mϞgphQURWYD%&3;gTDQCUg̓J\|=: W0F֥5:U@]^ n[X":,<h{s'Y1čP3: ?%lR=FgNWW^gI^ CTh׃QqVW $x|j,?/rd.1\np\*jI.@)|ug/Ϟs--@ & A4PrƂ^u3`2NѢ봴^dhԤ$^B-{cAO.OfB63x=)~/LP_݈޽[EK۶W/'Z9jojxz~jO^^p-hx,<1̴Esi%#uXxdLӮwԙU˿8‰1cvd*4_~ߵaԞ̶;, ٶ5KÏ(&?u�ڼ0Rݧ̨NӫqC">.ů(-OpxԀkIJt-iF[l8;~ڬcVc6>[2 V_ΣbeؔX薣<:-/pv3 .7bR{ L}vC€狀*V34]8K9cTıJ)sQ>aN dYWQ8m5ag>F)ࡁk膢FkYA&2n<2.O 2~x&1pjj(k`<(Cg [xg;,5 >Є12Ql<ęo> "hnC:=(Z`�ō-| y'5lޯ3 7 Ҽ"YC}@"tۓ/ԂWX$O|XE=FfteT2<ȂwX<-569zTjru�OAߑ�=5om4+ҫ ?b/X^%f󓺫(fDU|Ċ_Tjӵa|fſSAɬQIBYݙBa~FKYr]8+zXt֙R{Mf/,wI;͏PT$A|T Qp 3g"43~?ŜSB+E8:%m/-`m�UA4fl̫'t_<sG3t0w{geqgcn wٙ-ypd qKi/BU@c]v�ng'&ZĂYC9{mONtNd^=-kF0AKՄl5+VT=wW!Lg@ٵυ8Ya%R<}9y:e1޹ůS\&~ƪq]̀|!<+9mlݰuL[u(wg؂Q}WL>[ZBh|ȇEzqhLM6n"ݻii}2"(&|D---��Z?!1$4cYHK#zpCE]_֋yN4 #h շ8߸9sQ |FsnGs`"5i]?y`Dm_8/b$r}G6Vki"<QjqMgS1AD`f_JRJ#(L `/lן2~Ƿggl[F/f`o!I ꏟ_8474}9SK-z?;1$n7BD'`o[ۻoLf0!! .@@ZТ.*jWm뱶sNi=}z{u}vۧ=jJ=TPpO� saC&3 &w2oo{Z_`5,oD}ϖ42z=x[[cof!x<fghB?~dx.-�ḫBuz_x&^NѴ("~޾ݽ|ϯ屜񜙟 1mqޠ";�}6<"ڜٴ57beX'ok(>YYW^:5pfrS)-K}yJSA}ݶxC__p�H#ȣ&²Pp yb1>t _AKex#< vfK#͖ �� �IDAT S=6> XZL$l KzX:9Fgx`Ʒm^kJ�x@WS2yr(:L.aք18<3l^2Z894p8-:?�_v7@h]Կ~f�G1xzF[~~qx~=I]"Wm'_<ja8 zYw/~߿{z˿U̻gqicl_$عIÞ0oa/]oFlqtGOI=~ U%y/I[`\I&>ߒ*HLζ6궼ճ;njgmϾז//Ƒ3T䢲gD?Q 3e!mi՟]-Pۿ"'ýP2Ofۀ4DvDxgĈ99.w] ~ge-pǏmdd BEzܼYk0 GN91O׊{ǻ`XpM^sa!wT+܀ z^ ADBsE-weˣ~բ xdQ>^4ncЯ@:"z6쀧$ϏeWp?¢0$|(y ]|~9?6='[<Rtڏk^H]ʵY^շ/ ~⣮zD2}!r%U wNٙ%#po ~f<H�߹ssZ)n[)vµK%,K/JvoRa⑹csG޼i7l ]_dNbA@= T ?" {l vm7$aYT84XCzk#Y.XO%|-gc>pC^g;lwb:IϹoN\66pX˂F}p`vl'}_8ƪmLa[l@3"4I~�Z|оg(H&d]1 -~\jz(wAÊDye6SfNב^Ot1 N\;z><ˀ^{co)pޮ^E)gމZLXpX '綟zgPc+aau4ݧ'_[XSo *[1KM5-sxNf5ýw^A68r,;@16dNn{.6Ԇ''y<2ȧqs-3 w.7bE^b򍙇ókn!`y\c>Ić _X ^-;̴‘saH/i'v/`Y^U&*9v <tG6`A0iv9+^|;N9Jx5DN"b 1k4\ikv�|<d\`fvzl:>wx=c3\ua%4]UN;dycԐO[C=~eaS$=m# dv>k߫mw55,Vg9'޷pns2JEzJ.XȎ>`0j`x-D=? n6:�?~u*>Ggd8kqs'g0q5$1[O+G_!han?+c�` {Y kɥGlj�wpb]pQ1}\z.g6Ͳ>^XGys�rZ$ p8]\iNYwU_Ux٢lXܷǺoS:ڱsI~kWsC-|#K(྅1ozق#c&�'Z?~;~=};c#ȡ+tol<&S/`g%,ȧpa9:f"nsKJ|+gxݎnYK 3ɼۯY</KMY}`ߧpz-Me'x1<#ˏW3I_&�rW\yWݯME)KT*7#~ǂibŊ0cƜO<?7o~Kof˼ޒS'N_=6wrgxU\=u*ŅWWqEDDDDD"*^\|N~qYTdz΃`0d?X+=6԰\<z^r\,rY{̌ s WW6gfͳI߼NmS/\ϸ? @sd^_Cb}ћg?""""rěՇ"k<QOHO& rthBXj֛#Pf̶A{";χ9'V[2[DDDDDDb3OzPs]ta]AL'4dfum =f$y} uHlAy rk[DDDDDDb3Of@Hgkd2dfu Ŀ!^$y}%EDDDDD$6s5\45-""""""'ma`H2PxU" sd B0D~5!V X[2BͽfHDDDDDc?ky y}%EDDDDD$6se΃KS?z1&⫏ށḑRr3n?yOn :\%W()!z0zNc󔘫 g^_n?kĿ!^FO&FNY3lni\/=Jxll~ήg^_n?_`ņ`#cV /m1em2+]l|D>Zg>m1 i~y&qkr2h9X9�v4t0.ϟɶwcFxk7YF=[9ɢgn\Pf̶Aȯ&di?@Viyx~~�6)9bAU, rzKfHl)^ۜ�~HY2W}']6<\+-""""""xuۂy?OvgW6͏vfᷥ߿#Ft c~R9x{謯0'##Ky} uHla�`_{�[lm ZNQq̚EY%4SHo�:renJK(7{Zsf?SG1a| 5Rf^_C""""""9~2{X<�8v i$-?͂m&/z\0~xO l-W5/ƺ#~mc]^&/|+\0{/ջG--""""""x=,sl8O>Npa16}o?gs1/l; ۞1eƼ""""""9~:H$ٶ0i0[$kB/NK4sK/1FO5W'S tCH2WBmi6c_Ý_~7FLDDDDDcu Ŀ!^$y}%/ļJTR{$N\vSm! D}5ld2d(�I�x_wW:RûE6qEdM_kr5tSi\wp^zn5cmcg2jxyBSi]4#sK8d/?^Ux}L+ێue5qnWŋ'."""""WXȎ0ld2 ^x- C&OpQr';;8Am|uq_d{>6C>^|_7.Toxg7q\Zf=Vk:m -N�C|SˏfC-OXDDDDDhlajB*dv2xgM3]dne0.CʙS8kpӃye8Hix;2I}]tv(۝C`!.znkϠBOVDDDDDX)^ = Z$+ٝ /miw19ݎqg/d?34�v=zo)7_4-(|b.!"""""C?ky y} E'/tmᮥ8 탃xqˢ /~.^_ yr&7O^;=j5Ee58 瘛(x*5\45=X[f܅q!_m utϬ>ā/G'Cީ렽nsr/=6~桁Э섮{"k}{qi\E: """""W,sd<ضݨ9egu%/T ?K7<r-/[~OfP~b?ao)w,A&d7$̮ ğ*MWnhyJ򽟬M'O/][DDDDD4)^ &0utV+�ˍ"g ҥR{vhD^=YcȕW~8qYm =f$y} uHlly y} uHll-LSNL.wI&JvHl)^khk[DDDDDDb3Ofkhk[DDDDDDb3Ofk+-""""""x=,s> }y8-'O[ʕȼ""""""9~ך@.ٚ@.6ՄX=/y3ry2*f�‡'XuJ7wkwwN-omΒ8r"/X[2[DDDDDDb3OzX<H /Y_s޽|6 v\Ϸng;7crNqtW[DDDDDDb3OyJ2Iy9,vpdc Ubg%jk ?. &La\.$xvRf^_C""""""9~2= ftHVSϾܩaƴdWL�xnGPti�g^_C""""""9~2y ,_\xo^]y;v�&gY|Bp�R3;K.Wdfyp)amᚊ||X h�WɸFUoGr3dfyP#j7nȸpSOnVs hh>A'�;r4OæOP[@CPf9J0*zV+vQ ޸\9Yp㭳!kS)Ϯ2  +̇ːy} uHla =~iqM]g.ྉ.X.3dv_9s?a@$JvHl)^Gݶ`H2P4ҥ@S=,sb^_C5E-b"@Hgkd2/ZVjZV_Zm-:/'{�3֋o`„4 /ujZVjȅq4[$KVjZV՗fG}x``H2חZVjZV/֜rљחZVjZV/֜2l4ZVjZV_91/ZVjZV_=G?{,c8NΊ5Kof6s\4\t5=+k>o+~N4Di j ݲ775]9񇢏-6:b7{G[Wׇ\kZT[mX(cLkk`OVjZV{� qz[$Cm[6ڏ皹lŮuTedBj�X9Rp ri{�\9u*T'l1QmOvjZVjwԨ  D:Ȯٽ-zr<tQ2\nƎsr4_x9|jf ,>MZslgl6?sjβ: =?ZVjZ}}s|st'ʨuu/On6/uԅ3EjlLZpBxxa]N fS @6m'=I|}̛aSg.5[ @'@7@3UN;5'97Vd[]̜SNjNysok{#dpUuz {ͧix)3lݶ3CsجE7\}˲~Z}%ui=plz[0LFq6pne(I'ז6.+4wG[1ŤWsԖOGm=yy`wG=~˲+ȁ{=b| z38ptZNSfxt>jMC&(9'qiFq}$f|I&Vv|;8, gY$]Ӟθ FsBTc)f4GWm-LMx\>].>QcUc  ZcRȿj{)<I=bi4Gqb~tb\[g$8";=C]Aoefi&Ξ(:4_D0L3ynMV1(RbjZVWz�qiP?Ν ̙?"o?@πܞx�F;-†7SFn}_`ޜr&JuP<6dBO^r.Ɩq)�Δ i,ˁ#Ձ/A c=@ <@qa&'nt?�}yذY|洨h΃Tp䑝j1kV%6rRspQT>wss@5s1~l'l=> ;ZVjZ}wJ Z1o0or>9Tnzni �`+Gǂv^[Xö5:cZi)dz,r0}EOI 9XןTH-(fæVj?B Wpx< pX`&6t[`K#hɫv=L {O9; 5" /X <ZVjZ}vԄ!WRdX0w 7l2Jn0bDgoguYj,Xgn�lgdۇꘔ݅k4z-N:5X/S7/z#?e9!lh*k"{g^V?8}w09;k<FO1z��IDAT^VjZr;:>j i ` tX֙h[,wݸ A',r:wutQ2ܼ<2<�E gV "Jb c= $ɼY͝C#9-2N~`k}`YϯsadvNzeZ?:IwOkfY�))WjZVՉ;{OZqne4þ6p1g �@H7ͽlp+#;x0ƃ@G{8VFgpZz-ڛh<Iþ&Vܴ7}��N_|/#<h톷Gw@{g/`8%gˉ6Z8}*?@| �NsoރQg ¯6<0dgXTiǖ۫jZV#@yiJgCC5̤Sb>xm GۺlY] Z8ՓɆ-@jR!r`Ŋ7پ=3#;7ż]Φ 9m$YoxlBss΃�>zM"gPUת羵z f ];i,krE51\pϧͮLWo\_sZ0u5ms}~Ņnvv_kWAyKKy{g/Vũ;1 R0lsFjZVWnADМjZVjZVy """"""" iZVjZV [<4ZVjZVꄭoHB@VjZVju7DDDDDDD$: ����IENDB`����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/docs/fp-getting-started.png������������������������������������������������������0000664�0000000�0000000�00000111145�15223753015�0021240�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��+�����<*;��� pHYs����+��� tEXtlogicalX�427/_��� tEXtlogicalY�183v ���tEXtscreen�HDMI-A-1/ �� �IDATx^wxTJ*UHP,( \)*Q& RR"MzC !6sX dAD}w-3cdɟDDDDDDDD$x<LJVHd+JVHd+JVHd+JVHd+JVHd+6~A`?kr0!"c=Y bhP.`-Z"""""""kf,7ƛ)Y!""""""kox7SBDDDDDDD%+DDDDDDD$]QBDDDDDDDҕNVdgk關 ͅ<YZ|�lU<@VD:ź㧰x3DDDDDDDD*Ydk}l Vhw@06#Pf5dl*Bq+ѧNq)B1aO S;!C*l`Yd~َB�/*/¿jOHS.)SW;O0r Zy9]m'4Aς$/"j zпOKx6ItɁϓ^W'%D~GH'C(_v�V9{sPI.G zV꧌{m8vzDȽd:S^=m%~ @N/xMUJ?֚$l=zٳ-m'o6+HN _30{/5�gҹK+K3wb٘ 'G*Y;'�c70~UJ[ (Y!w̕d?Ql=pٗv3t2jyqgߛaG~2]T-`&� +Wfx8&Ǘoh`Ox """"ob�/T n$ێ�ڗtn xi>ϜQOhՠ/3}/'9B\}(`5ӫK0sS/|58ꝸe Du` >W)0{dwlsGصM^L`<m=�آ(;]8r uRn]n+Q[K<qBOM0Kو>NYD^DZGgrg% &قе<|<i1A9Q_~2Ƕ$!m æc ~-DS�_4 ;Mh w!)^ ,y�{+s$"Cwr0步p7?nv7 9i#XEO�`vٵcGѼzf5s.t+ŽWOF?Qs9v}t,~f3,R[a ݇h7- g,=sևQde(ˏdɰ9]qKpj":kT9x MYpTgY-k9+s0d`M L%�н~a3SЭh|r$܊\Gm fc+MO Fܔo>NJWP <ΌkPͩT ܠ`(_ńNK0 =ȟ\@Pn�Zů {8p�$JS_ժ1Ü CXx=�jV†l[8Y4=)UKV9k8wz/[<R.�G(YgR‹9KiA+w�ѻy%- R�(R cfL{5}f-i;UEkXs"4xiAN˝.'㺕 .Lf_o?E_Eڃ`wұDroxE%, ܃->uy̹KG|pFlr8(_: X<V2 H]�bX=$. +?nIPf#{kaՔsr0&+6 {a]բ/9v4XрC5ojuƈү~Z F�j{ÕfOI?Is=ԪjѤCoBF?ǴWhB )33˴מ`\ F^-jũyc?U>ɦAmj J}=`YpUvzfp ˳ҩu[ S&^vPJi0U*fWlNwxc�oN5'T2ykQQd0eQ! #k9 DL̊_vġO9xr3g^-_'$%^>#a2**ԉw>[·Cc<50nHDDDD�25)R_v﹀ﶝeYMz;k['r}Y V`TfϱF>\C=,Q}FẰ ~tadE {gOA�O\xg=Z@&n%sM.8ߤ>y\B^2$jӒo9(u<Zs+Â7*e K^x~9-G6#қ0"�36M1 кl5iOE ^ƽUR݈3 .;J~t{ (`c+`+I/aO,rn2O?-u.;|(_ >%)g5kY\�K1.8cFJ6#q9p^|„HXOf>5xW$`&%.S0[kNϳvl)d@X?6`q^>>ؚcO؞L9ص3(U 0'?y_bm$-I0,"K0Nė[0w@^me`8K\<a?Osba2\Be 929CN1fK6VNϾxk:7& K^~eg܏Tf۾r3"V(֤.S?ɽ8r<KnF0(\Ӕ.^E`_`YI "r(\�eʞ;y4m>kמ™bDžݞLV6 W*5eUD`l_ ~xO3,eaڸ3gc\9#;B_v4`hݖi&WOƀw^�r=L_,K.w?E,\? ?G$ d6XOr L ALdº޳${`bHso f.'$\fdhpI=rbv<~W&.�MOb< m:/؎Xj+HP )DJG}Km24�S@o/p W÷@jr2i>]ĦÁ$z c1f>uL|bgru@y|i͊[<w80x% m`c i07[Fc}4*2~ n*yoiZyg-J~`3$y6XI`̊&?73z1�9"qjg"KF^;``OLŽ%f ;(/V�X8゙2Ӷ-uװdZ,R"3!p$�$L)Rl|*ce!+庭x؊7s~(auǍ+S�3}䲂_"ew 8lϝ0m{#B Y#}6i7ɚON_Vl.bS> c3(Wa ΀P N? km筗j(϶߶"-BA|^~d"""""\6 8D&Y>f瞏' n~$J^ رs@-fx#!q:^<LD8lX{g懣 ^/&ZY6z68ΐ, Ǜ~h<zm\6?>YwSpLܺ͑|D }{dşcŒ( -=J!Ȑ99||�>\$J 6?bul ɔ9k0A}q6{}FfJKYaXrtM-smfDyp)./9ڹ5ذ(J`+YL`heo^b�r[;w^*X=7۬ZLlݽC=Be Z{y+ϷykL`eݔҕ�Ln} 0;_n*s΋xjU\Jq⻓0 }ҭc/"v0ӶOiOQL8T}ڼdǟa@ ] \NaaE/ o$lE38>xOiHvp{5z$JU:R|qBbrr|g� ĚF~#|Ij $_s(2 h-zmr<ۜ%HYy!%~ƾ0KPl: ʘ/rbŧgcO0c|H9ZW'{�2(9IYH$z7W&xI߇bC @ 28k7K &D n\2|Иĉi^wg^mj_<Cq] `pjkZ3|"I5C?Xp�ϴEdW2wouE `گ6v6<׋OF>vBW bDӠDuoʩnϔ IW ;u $&& S jb x1S``�>6kX y7ϺpF`3r%Xx1r. ԭW 8m!guL``x{ Ưs7[<h6{ln̥u?Pf_&Sp H+A߷:r"K#&-Bc88-]_^wi; /[:áT+儀T:~Ǫaٙ.39 ?XONH8q%�8c/Of|νם7 vk<\BTQQQ\zK ѦR.NIqQ2j?Zfx0oUlS Y #}GĂiи؊zߒ9{IBT"Up"""""w˚-3)W~ey> k,X3G�,2ùse)X}/A_gM8u'#Zj÷l]ϰTNGZ=Zuս 6EEi6ΝGÊ,Mܩ(aA?wκ&AgDe-pVE:tl(!%rlx~5y6!nxa3 ;Vm ^�?mi2g .''!W"&k((R�I?%!>0IʾnT�:ʮXqrlU ۰IϮհdUn8HHN|$X[@BF%!1So}+ȋ PlQf-b'q_)XNgjPJKӲ%#IЧvVzER Y4/jY{zҶHʔj.˿ۀbKNDyr!:  K8qm S+4TχuV||KL<% m_Hw « lGnr1Sod85xY6J{\rE9r�FP L@X eGlak\pA(U0oehLW@(S&xhH"xeƳ.|su_ g4=,=3΋1ز-9stgL"Lv7󲉍v^98Y!{ nwB:P`Ĉ*>L-7s!u=֤K)/R۹\Fzv[ >%ݏRv_~36 `�^Og6æ,suVbܛM^d[,l}G<~w ]k;q(:1a� Vmj[]2P'z\x];Vҩv Kس}/(eĺcldp[Av' #8rZig»ps;>|);֯˅7__ȡ^9g5? oLfҴPXgJ9l]_.Rߧҷw)t Qoxq/~p.֤y1*v,Dϩ!?, ]G~cg}\KBL$76;iv!e9W/HZ8İv\p<Y ]ɩ%27J榯1kXw_.p\ c`^w.qspI+f'o?CFݻ.+M׍LuÝdЫuX.cBٌx>T6f!<&a2׼j FoKOo'кNxg$jvb�bb۲WZ|3Z ޞk`GJD"cy@oZW{ `Oƚ-l~\=H&bNҩC=FYhӦ2{J h_=7ƉӶew"887MJ"vu;v@$:%8GQ* vπye%[Gw+Z w/W)m?W,C=ii[Ό1Z;d{_|~FǤ3N{QcZ\\YC &uHW`'jCqiFg'w@6kA֟c7-OGw ,eVNB=x0 ?If|drF0+"n 2^;@)9_x%,"q3C.}T \aoC89{ldG/N2!5,]7kcn,9oI:e3O3d.vxq1o$"""""Q³YY<s"X \П,us1!t-k>`RBܮ <y86> Z]=NG�W!!46 S'zb"enhͿ"D7zljm🏟<7 KtԘ䕙hf_Id4LF,)6OyUsRYq0SG4P7?՞Eeվ0o!ջ{}KV$/gջ(}h?Ov~1E'6\gӎ&v\HVieSdi̞$mbOד$.bqc$Mڶ�l0d )&} z?z ཯`Z EI9uwΣ6Xaּ8]ga.>uyN,<i%,-`TSJv;&0p":^W."""""ws'Ɋbo++fдq_IVܷe @1;X0WH&$".&aIJfof|{%S8q7,0l<D.6}6kT51'xu$~ rŞghhm 50nDm 9*Y3V'% �� �IDATm!Dُ=%L]O/r}~|Ņ}zuK pWq] {=ɡm_դ~>r~ǀvObFsk\'dj{F {fV< z 3LDDDDDDҹ9�2IWzbS)\{ŃoYqcJI.o8 C<>o@DDDDDDDD %+DDDDDDD$]Y!"""""" sϊߴgfVZƓ fJVڄE8x3= DDDDDDD֖'z`6-anB{VHe """""""(Y!"""""""?k1<T9۴,{EE""""""hY!"""""""6tE3+DDDDDDD$]QBDDDDDDD%+DDDDDDD$]QBDDDDDDD%+DDDDDDD$]QBDDDDDDD%+DDDDDDD$]lƳLDDDDDDD IWxӳPDDDDDDDa IWtE IWtE IWtE IWtE IWtE IWtE IWtE IWtYpL,Cax >9rw 4=) {J T|%C`=R Á/,V+Պv)Tw2JL ~8$&&bOJ"Sx=i$''c:.$q$$&t:S7;n&.]_j?-n'n'k֬K|L$)1oo2yV=p56{r2~~w=ֻ 6/0{ kqq}ψ3*2~c;NVؓ''%n9NLS  cPӉ.d=%) .^6{4M\Q!"""""".nNQ4M=C;P4q9h)ḫ&+3{~~\.!"""""�l6\.gd?Lﻛ1p7w:6SBDDDDDDD%+DDDDDDD$]QBDDDDDDD%+DDDDDDD$]yɊL*5CqX# UJӺI=6m*EFu'yԳxg<u?Ǯ݀$j hK.jZzVeIŅXpyVߵE1&Ձ͘+%Ds"ɞMDDDDDDD/y<&ഃ6'Q3OBy;zVe~\.?Y�#gef̀$gyyg5�ϥutH x.$/cu<b/6�:͘FC={0v %I9 1t9j'rA/\2{Zi٬!ߎʤcNywCIIW%Ьݓ$`'OVh،;`ܑvj1{BZ@-xKK0"""""""P@Vj2siI|ʼn _Ӫ/9mw{0ݏu8}Id΃HNR`ɖm 0\eEM[st3N>0<ٰ(u ǽCŌq<ds䢰Au䨖0d%f-b%k5q�� #Wf`SDs? 7w'""""""Pkϔ܀Gr4.xL61Œ;;CUϾ]pؑ̕!Yϗ8$ǹ<[c7uW<12p~m\֒wG3sO-WZ`W7M'~ <W$Y 3`w?ɓĉUx<M"""""""v%YP?*Ͼ?M u} >o -G/Bz8#lvU HXv un۰y�8uV3U_ |Ԙ9E6aUb Fr2`p<Jd\ 0UKʄ_srϜ0/dLm)""""""ro<kv, 6nuG?r&&b*f&ߊqd5XԭUScn0ܿ[ng3ɻ>;}8l%<~(tBakjO В�+q0=$�r i!+6DbeKb@58f߲V<*b Ȏe˞ `?HM,W4kfcmuDE 7B6(Jl=nuqE2X(DDDDDDDD~CytuУFU{k>>¹,u$Ãr6 s;p`:@G3ͫ/fÚﱛNզ??j—GB.f*0pa� f%./6R ̆XW{q=ÁR/h:2r9Dp,:+>""""""" \J3 beO~$Ďm<+m$FLjgU66 .�7:IuAOnʥT1xNj?7ּݶd~&<M^+caN|9M`xl<,*˾c a|Ɣ!&^DDDDDDD~* d [qNxeH: >`.ɥhrȁb0{+׿I ̑óZDDDDDD.㽇 A8G!W-_}qm+U / YWZ*܈!'񻸗?*"""""""gVxݪf[AU"*Nhu:cS,٨=xk2o ]7,%UÒg<�s.o7e4`7EaYvnw 0fdZ&wr}ܩ|B$=2vυ$l 1w+xſa?U?\>\F78a1X{6y`2yYwHY??_L)'+U˔el<EDDDDw㗁G+λH YDiqh +Sm;\1;,=2Ds1qI[IWLXb=oPBsWLY!qW7,&�˭ lHA3W{̘]!"""""rJV<`Nػb%7_�PϪ6I0S| xCqvSK c6F2Ş.mڳBܼf?vxW)Y|\Q %ؼD)i3�Kg"X49OhRb#\3H )3Xjd�8cU"]}jjWMzo xY1hgUc4MG�0~~;g~'-\;QwJ4,""""r{Z"�M+O 'óJ&yÈ6XkK4/uairAD%{8#V)kڀz8Z:ŵ-ШM5eO8 ^1Ȗ53mp&0Ʉmy<G .߮9Op$\$EقԠ銑8Gd .d5D9qԩP;4%��$!aE_{q]ӛ#p'4:Y,sbj`ÙD]-p֔k^bԩ9SO]ep l ˩\ʼ֚gd\ "W,cD>=.2RL7~[g[콘!dN#JF 3P`V/O4?OUa3N`Ih \ Nق9h[ ;wƚgߵ."3{J. 'HtlU⛧g:b-l#s]I# xjiK`AϦblٸqb$FJY3P`.U+O6- _tu[j `RS_Z|ŇR9m:v&>,Ogq)hj;QBIV, eVGümP`nxLc~Igc]9o松t'ƕXXCw?&z7`ޘr烋q2>2ys>~~65ˑUfwYL%[j̟o¥4s?Gqtn͔n؛F$++qljjÄ+)# n4�LbĨDlL{kN&4"W"Syԛ� ޞL<.8u.bC|8u:?B7o47m&d;h`CX"2M2۝RLxkx#Yvr[cL~%%巖H]3aೡ8b¸9�±WXq;ԓI͢]0|^Na<9w5si_8~]++w8O&bSylZp'-"""^i).[>[^ TlTf @oü>LMW_#f<RE$p_yV&=!zό4|/~5c{Ixs8 n~?, OO c/q\q$^klPA#<gPyr[gDlD'Xr<g^MܾpɄf'/ߒ׾?I<Ӱ]'gǴi73/:37f WLfXI8?[Ju FggqĄ8i;d?[_Y'yC^�Q⷟gg-u0wP[^ |ofV=wγH~0S[ِq. ^ebel8R6'\i9;>ow%gNƌYu ˄�Nӄg<oaB tgm]u/2.Y}Wѣ<8SV`-Y}ـpԒ\WRˏ;!/d(XOW.~kPz;{\|T,~U�w+9<=0[ "#9r*M@ I&;xҳ^tҬRx&ln2DDLYǷUc9~xsAo_־6Kߞ |?La»"R}8y;L䷮]#]@g1V \""""]%+ ,Y$rϜQ m2+д^N*GDMR$/M'u.%H9>mfAE]6g|X)+7[3#d^*M%kVms@Mpe˱^39*Ms.XWbШR.VG- kCr|L׵4q>[�(\i&DFDR'._tG~Z4&^J\#I`&ïsO9f&W N9a0gJֈd) i.ޠO8n Sud�y-4[*͡\9 e&^uɋ'Ǐjc\=qlZW)n~_ƙ<}u]SG`@*y(R!Ѯ֦I@ę,7[�ؔ!_?ƛ}QV\vf;ו X̚mZ6Nl.o讒"笾le7:rZu?{Eq;TBBJ `.(` DUD)Rא@fg?lK)+>s$ޙLvg8eՐr"QӁ*h揝]#v"~75p+1+G(R[>xX}G8 xy<%<J0[,Y{*kXH2喔k2y#>~y Xi޶,8fmN¹eSf)iM yx^WpOްxHxߚNϽmmX"ZX5(~+~}nY5�!tV/峮m0&E880AqBJ-k4G=Kwp"Ȁ7OSO!|C=y>JFO'Afd��;wB`('݇7¶xe˰oh@8:[h§t n�:eg`fieQaM fMM,;e-"""Vg0n>LG6)j|e-:\)<a. ӦPB>ܵs)!u�/+NB'}QG9:[~&JS} v%~]'R&̥`ǴYI{{ ]abf|-=? +Loʵ}SJG?*mþ=AA?nm '؄=Wa7Z%C=#2 "Ԩ˞ _wm`LpG)ҳml˷!a>e�`u?@tF~" xGT ~VnpށPf_T�+2`xsuk5CxUQ-YȀoHer`mc<@g@xnJ2j>R W]<ߧubV5 [po/ȀmiҧS s}*"N NIa&puE *oYoڔ5>!o\`u<ZpTX}MӺ)yC u_|Za8""q IIP]Ƨ ̄ dg@LT'Zc! f|R� 5Kϩug؀zH3DA,së/Kez:Uvk�(>aQSqņǿ? uX&E>2[~ȂkRoYXiK7иC30|& �Vi5p^݄q&U7B 0|G VƩc7Dpo@B<MΊ!�ELٴ;A@YiYpwR&mr{TWcㆈW 6pVSv#(G<5>8c9mp8}lq r`.i�N`7g,`ټa"+= rxJ=pBrh1/V1槨u�jլ5իsWV<ddKAN ~=BQ"+ صk/X| L�ϵ|>eժ̰a> R7o6/y4Z]7v sO*b@ha‸EDDD.6"?m3kOyk2MݐVl`ɔԹ1<<#>ʗg@H1 T .|#}n;l!S>utg{2Cݮ枅w+ 'ˆ_I+ѥMsvyy I f 8v CSK3 NI]#O�� �IDAT`=N H9B, ݐk f#)8%| [DDDQX!rqÚi{GMx tr 0sz:n`By:<�u .wc}v4 d"y1&mJFaz qWͳ?<.},f֚^3ZCG2$5I zp`=r\dg+wk!qyν Z~A?udo Po %p_Ki,gx'3E)V@HGr\9ʹ ,[Gju@DE xzMygЬl!ZvRkR(\#n߬cפǶ<1&ue▌LڇǞc%ȥN*Eux־  $8XIS_ 68Ng ˼ x>a$!zD' cQx7ԧ-"""B&MYmU! LÍ  F܇.ꕭV`-^qG�ߎɃ} . HS :׈słXt s.aع>l{cm |.X+@dd!L bbؐ,Xbb1b!rwL{`̻(ڰkSmMO-"""rD8gY93abx:j%b,nUM&1.4$ @YmOyжE) ,rw.ik]4 *bmVG0g@FISw[ȟm }L !1 e3ƵwTDAK׺sV5!t\,Y Q_|}\(/. 3qѿM9VfOR, /e>?7NANww|A }7Xҧ,}zyͥ~Voْ-[ҸeK{ Vx3Ď>)Ʌ!s(H/`ty>e&$U�8S)Pum6v?25͆)Q�5 8/I G2`0_ҳɿ'g#o @ayp5eX6+Ooҕ8o6ÆiS+Pp^{.[98= v|QN]g쟼zX) | x%{B 0|{=,?`z]&;'}r\y`EIJuNnٸ};S'|"'cyk7\5+fیdo)頛yyFW @B׸agNžQM A~`Y['|\pP.-{ip ]O l%s͡_gYp(T[v2W9hFads% uYK?Y`UMGuWjt'SIʆ`ۻuO*`mGXb 9)[`�=EP{ -%a屏n#Ykg{Zc;c]OHdlV,^_tzY"ka`~8 1P+|η\zOȕӴ9qX'iS{/ Kд] :ޚV;{ݶ\DRFSRfʢl}qS<4z;P0LmRpWܘ>E!e,ܸoGi`?[DDD.hXgƎ\j?x]e،}QEc`ͧ<Ԁ#ʧDBFQ`/ul6ru㭊2wdB~`~ݳ g 9ҿ8p[}5<$OHo~{Τ`6AS)޲ʶ<1Aiݓz_ }'m&AflN tWGv>eïu8*ׄ4+|E~'8jo_z2TNVEu/rml~>[[v26C86g3BŀEDDD.2 $("l>;YR߆_'* 6gqP(ϣJl8u57P5?fTMv'j@㟚p/?ԿH؊3};b{׽5`seC2RS * Sn2}'qy'jĚ0w]e|CP*S/z*a Xg/wvpCσ噲-"""r\j mH4fѨ`7 ݆a?nsoӽc|8n:66fdhYCoaѐ@6|z|1݇]Eηi{-2/ }*AE|Sp(\1Ϳe!29YG7aթv4ә#/9Px_CFa9DV<4]GLېeޙ?z{m{"*7_`7>L`Mi'!>ݔ 8)/6sC1#/dxj*2Zůpf(041M!v<ظa@EDDD.2 LuAKrU}~܇kf]|?o'-O= 7߮>J8B+u&!s>Ovi+.M㖗1D ;cvRrФa:RIm&O ˦LFG�'@Hya#f̱l߰$-L󚕸Ukٹ`%0*F8j\QVrEo~Bm=Er?NB*@&uh֩33)ÄaLn ;vhƢ3~,">,ŢBTkT͈._5Evg5߳|,Rn% *U+ܥ=|eUj$&al^Cq"16+'su5iֺ-wc]ŏM2rhX#wm JT4q9]; z}|K6£®׷gWa6eg^J$&W--OVe lnFҷzz09`Ë䱄\~ǫYbMw}]`A͘?q]vˑ�s.1M8ygl住22Hh޽q�ςfno]AݙR{vNIreɻCc@rٱn,ۇ8o{69v܈}LawjrQ ~mݑ^#9r�i bi<uwM27zM /&"""""""׉Wq@LsblIhS,� Ң8q+y+phF>#" #pE|8XbD= """"""".jXƷ5%##ƻ0Y (۬!æeq�&ĖTlpdc]dIEٴe8{i })"""""""뢇�7 &N䍔0GH a=^KԪxf8[�P 7ݩkܻ8ȡ{DJy&>rx'ڹ FvA"r*zȥ> $ FVQX!"""""""Ea"""""""PVH@QX!"""""""Ea"""""""P8 D1DDDDDD 0 ˲jE ˲q:76�O1$4L*s"#3P""""""rfa@xXrsDWn.WPaDFEq8%p03:DcYdfd}id\k)gƳJHh(Q8L4VșXgJHhh(73 h """""" ,l|:161&cy5 ߲łfTi ge y3&u+FPv>u <0R_纁S[a߱T`!gR 'Ng (sCa?w~?)Üť'"""""{LN( e#%x*4/Œ_ɶ0l5"""""rBDN�nCseW[?m_'aibwjF0r%1(5JӪM'p`a>̮ cm)\�0xuoK32�ʲysV,MQRʒtFh�Sddn\B3'딧эkfoTܺu⧬ycDlOAgBߧg\ eM%m~,,w9_0s5~yVh˧_6Ęe\3y>+BY׀E.0m.^:{wgunt˂իzU<ݭ7cȯNc *&26 oLbw"D[g="/XKUywwWo;#FjA-Y!rIVv(� ][Kf`Rd:u P;Dq3!bTq`ҰA1~1rw35.W_ܘ1GjRl~!Wl&QH3>5(ekyepO96hF(}!{]Du*�4fBDDDDDl(@l ''«:mQ͝m[$Ц53b 7uW3$,4ػ pnh` r%cg~U(V[UCݻxH:$e['0i8⓽As,"""""r6V\ Z7&~C%_1Nv,h(ZUk2K^3aX>4 L ?eڼ޾6]˵Cc 2 p (DDDDDPBS*c9E+W'6Xq $&:Adl]� _NY@Wr=]%` `<XEIc/fLQ.Kόl/cQ*{DZk%ەml9EiiM'4B<9mrΈջY8c*_^_3"EfE eYi%I`\NTLIά͍UO#: ]2dL˕-+haets<ى 5g.K_RMq̘=jEte 5Sȩ�Zƛ -Y1-XYsgR9"ɻr"kp`rJ |*WGq-ͻ h]ly \mf+kUL"Xyx$] 7 F!^7c7RA0koH#@NƤ/;P2;0`a^{}jĚT)Wօ79#FZzFl%϶m,"+#xj9Khx8ibq4BW/UFVFV\<wd""""""""Ea"""""""PVH@QX!"""""""Ea"""""""PVH@QX!"""""""Ea"""""""PVH@QX!"""""""Ea"""""""PVH@QX!"""""""Ea"""""""P DYc-ƶmj 0 œ!,\I PF?oYA#XœDDDDDD.0te7=1JՈ /4-+ '9 *DDDDD$@@3bDM slю;(_%"""""0FDbюU sl{~0*E =mEBte / 8aP2] s̶mQ!""""" >LQX!"""""""Ea"""""""PVH@QX!"""""""Ea"""""""PVH@QX!"""""""Ea"""""""PVH@QX!"""""""Ea"y7ǽuOTwr}88bǷ^pyNg|݇<7[{WOܛ}߇""""r~keYUDZ,c.ͿVQ6%d44pY.@P< 3zepm{0"/i1i߶fDDDD<aL7񔁅eYL7mP8*ʿB$�]znyM6;}m`Ņeہ7:|q�]j'->aЦc U""""rFJNfۦ-L3eYL3mPt2׷m䒠["�֏塱mex݆&s!e[�8p×d!l^L8PE.2߼׿p?GH sc&?|+fң]$5cfsW?7b ^FOf^Ͼm˧AV5qsw0c}t_} &s4)W;pat{o S㸌Y0Y3h*OaDT" xgfx#h[UE1 Xf$<܁?,<sw^o~j7ggCػv. xw[wpsvrlY1X#kcD\w?S%΢pMkݏ670f^;Ѹt]~cѴOɽK' <CGv}ѳtnĖEcN߻Pc׉?g&:Ĕ1پeSƌU0M8f l߲}.5W%r uWlf,iqw�b}{O8WE^u/\:I=po}- k�_ɐ7P{, ~pKByy>:'e쁜{?|2`0w'm೷оK~^':l/T0a/E?>+Xq_^no feڰ$o91g,Cz>rC"&|'w1d/L9®otKc/zEzu(KAS{6=x}}u3kՀL]KA83?FL*Wɩ8C>S9KyE²,,' Э0e�w׉x>"R׿ 8�L\BwP+`wqX &N7ɾ;< (!jhͪ7`$SȀZgÏhͤ ]K¬3'h,8xx3~w:u{"tmG7al`)'Mxd͘I ),r/3ߞCLjwd UWzrW:nǛoV�� �IDATk@20F;6m~ dv;{dBeLăIŝO`:Wx'لϞra90n֬jAf*B̪~7<냬yqw<zk=B*7,0՝LC`Dβ}ټ}J?6^憞@0-ەeX6ȧ"o]&ukJ- Z_A( h傠ѭm3`w^"`Y6Rn1bri6-"pGY:=mX`:n`Ӧ,ܛ;ϻ\W"p88kwgoal%Vλ]PP`vszu,eo�ȵ޴dlk�ANώ@Fh9bHp0.7`p߾{kzzWզME1QXk~5ssc.,6(o"-m(c� LL rfp0?i&<<;BnsO^DDDDΎilƻ>@V4T/[N`8~F6XCO 7sמ'X,9v^wWtм�o *�G-}k7�/hyz˲l 3m Ȍ`2o{.2۪gYx!.\O3~ &3~uu$V0 0 K?7!4 +;,jgBhiB8s� \5uCetjZbW2s[џ $(&ISx"%'Rh"cܣ?ӽvGhiJLd7xlpz҉(ڊO$.&bBؼm?97 Xmϥӝ;Ve캪7O�dKv76!(" "k.h*kwC[%""""eYL=fr$)-ۘ:v rQX!/th]OWsV>Ӧ͕(Gemm3ۗh]<Ӗz'?}:9\ϢcҐ/Me7w #zsN G9Z׊bYC>g ]�pzV%d\ݞW>ʆY{7;^yPk-_ŗ"6s]|p'c st5#`5=^˜;ٲ88AL=<vD Ь=oa>U)= =>}<歔,Lvmhٮ %ضyIkz)4*#FtrQ'ـ+ xBwZ\@|z+Jc]m嶶mX3#P:G1b_=. ԫDOp-{ Þgd=<ERʦW� O0aP G.O}{L[x_~.!  -_XBӝ˘=~5xh]N?ťUɦcW1g<K 4О%Jq'ڳ%?<P1Eպ9( lyAʼnѦc;Akz1ӏ*rm˲ !>޿v,%/ylAOprg`&^DDDDrrlPQQص}I]+lϩ={iFl'Ͼ"`nMes>?WY"""""F'LQQICMv$Jfm̘0ſ%cED.Z︃\ PLjEpzG)UiOj:jߖ)c'~Կi i """"""'i """"""""BDDDDDDD  ( +DDDDDDD$(BDDDDDDD  ( +DDDDDDD$(BDDDDDDD  ( +DDDDDDD$(B3 ۿPDDDDD$�x0Fa9 !ӕ_,"""""p2]Y9C/:"XE9_,"""""pdQpQNa9V3"9\ ΥfRENayШt5R3ؖ Wְ`,#5;F7 A"ņC,ڱitecۊ,DDDDD2 0g%  yVG5*R """""4 DDDDDDDD  ( +DDDDDDD$(BDDDDDDD  ( +DDDDDDD$(BDDDDDDD  ( +DDDDDDD$(BDDDDDDD  ( +DDDDDDD$?s$#ÿHDDDDD$E]TY!"""""""Ea"""""""PVH@QX!"""""""Ea"""""""PVH@QX!"""""""Ea"""""""PVH@QX!rȁG޺R8FDpxxG`}XJVOEl>� (; GD](ʉq_Ǻwy-B=U%و\J -A|T!Z_~�^\K4m,�>:%>"cssm2׎5-_:vةKm 'P%c sgJ*1DEDPHanxkFz6I -B,Qyۈ[ȅa9P%.`en tŁrcb4ȸiY|+a1- �; XoU ?1L}:;;�!8{EDDD.ey t'0f2EŎ{WUC)~V,p&uAXgg} ׆dF7ѩM~K!9N*w5i6Fdo0u~a =�OgːV5f`N׷o%'eӡv 3-|Iw~#"I\CQimZ[Ə!6.Cnor=M +xaS5{Y$^}%r=yt޻!߽ $Р+tg-1<r>[(en_E^kh@w;70hF;G1:17A4b=^+ |$Jd-ǑwufИ`®ȻϼµYud-OرX_!R^]&'=,3Oy3Aj<G~N"Q&r\8z:Ƙ9Do@͖-Ȼ4mqnuj,@ʡ8.kł9Ļςn&G=2xya޿?oO֟+lUaP2O4Y�oNY@rr9\jzv241jt`PԀkojA;u rDػW%JW4 Y'~; sH2 {dR||LPP!vY!rTʵ){Ӎr,-Rf0ql<-@ɀgȑ4 ,bɛe2%u YW^[ZS"""" n Ӏ'҃b��5p{BdFNacGzqɞh6Xi1 69v(m | @େ˻e>bmb&T5^*<}n{+bch-p߅ȿFV\$6n쌊L?=Gѱmv 4B1IKIJ=L!˲4  Qt}(BK]h:uͭ7Mz>#�FCZ!ә}8G(T _h:twF*&9fmz8 2б#xowE(w#M nx7Ždiӈ2,(vE#Xz6&ݸqlr+"^ +D.LȮґ7ݩ6yԪYWP9&MZ&iԪℰwZ7La0_-"""tmW^z{~v߿X'lr;므 TJ.˾S%ȦPt&ux MIA5(8j_jxIBw94RlEoã?L: ޻(.Ůk^XZE]uݟ*,*X�Q"(�I&sD]ׂ:<8s8s?7Ar!ͨplNiû6%N!R"JaHh{+7Dz/ *6} 7<{&JiCLgpOhY qqh泒Ϗ]'<J8ym 7>�hf�<9c+S|% ׫&=/lS$1z /wIƾ}R+&9(4>˱5<, +q{Q+xsy LxtDV™_.=) 9!?獆ek#n{~f^1^:W֝at !xgǝHfyfӪM3Y]a+jtcԊ<}NV5iUTw_±ydrvf\{]duc2q><+Ќxa63(qLf[{a$I-S.?'xS~@t<ʫLKkxd3T ͹ |r#O>7Y9 u_׷j@s/[Gɥ�ek,*wӳU{: v<6 x{)|}-kD}`6 말v9Šqߠ0 l۲;զ-[$I$)ege%6T+W"#+H$By>*$I$IIŰB$I$% I$IT +$I$IRR1$I$IIŰB$I$% I$IT +$I$IRR1$I$IIŰB$I$% I$IT +$I$IRRIIlӬ-ؐ$I$II-;++WeX!d5$6I$I~�H$IbX!I$Ia$I$IJ*$I$)VH$IbX!I$Ia$I$IJ*$I$)VH$IbX!I$Ia$I$IJ*$I$)$6Hy-C_'\9ՠ}4J#5i"%I][Pĭ3_q=sI1;=SJ۞cE;9@gt>* 8d3c mp޽B7 WR oDz$v//rHt7THi8D$IQKM _'yzyLy w ?D7g%2'umDVڨ_Msc[|4INz;_eNqر ܘ%I$}gg0i@Ε}P[x 8q29>.yL(OYCdPF6 rs˿jȅhfПUM$WVHH� &!l ၙ?i4 <;…][~xpU& x-/ٙҦG쵌~s4,Y AP)$IE͝WȞՖ(kծsBɧ޸?҄8 W椣ҚLz=kb11Ԋls&/(Gu9G̅ Vppiii/>;fxp[?3&Rt=űcqZ=O=Χ]FO /H/3󁻹DxQ21t #s:1x[/}ET..V?H�L,(^gɂJƀ]!5p_d;%GP�L;1y]�\Y!JޝZl+*ǁgmdr6ycJt"{(%n 6 y釉|Bz-•gݧU$I8y&@r6nKr?{-=sW[5mڴdG �buV,Cn\–P|1ssL<>ۇ Ł_EV33(nu^I#օpȏh?7Ͼak'l%If.ZVa駟Ϊ/?%\}r4ױ!ܚdna{O~1&dQ��,crɅqﲚʓnm!7>*Ff e^%z�>/xNt;Ɯ}N3f0|:RPү&�nIV<0aI&=lx K(3b2:g,wnA( ӑ0n#qq) ry}b+_$IR_T x,hG$R-yEKʶ)ϦiۇN9u_ȀƛZn-Hmr$�uB.Gg~-uoXm+ym]jGOz]'OB%Ԭӗe@L2k|oÚsBşӹqH<m%do-Scpm#1h= A,tkf@C0df*ze.؅`އGK6sۇx̡oBy;h 3 \ֻ-wrN>Q)D HK!]@_Q�N:L\@XZyߢYAڴ9oTi¢ +)ݸ 2 XT %+& 9qLM7Y$IH$JYyW3";4Z7z"tˆ!0stn|0_i5eh@q(ZVͫ�I wHVz ۷@R>]g~*z]L ׷߲uS'lHxgEmiG޼ձ̥i֥ }S[w&vWp9U(YR !�.j]<pi2锭|f5y XgԌW[B�DPf4(Rᆭ W�'֊2Lx1YlD (k_Rtv7Gt ReGߚVm$Im�U7ǨQiUv Jg-eyL�^/kY!D �aHT!eǃ4 RPsOe<:ՙ<&MΧ}1Nf@q۶AEۊ+(-M8D¯ v,BrO[q]�2ٞ7B4&scq@{J7~FhN9b!i r7[tlْ/q4ʏ$IҮu,fG̚Gn1X3g6C{K%%0L)iB႙4HX_9ukV}lnG z.W} jX#x5r RzuVNթ мicx -MrafL8.Cjivqr<M{{G/$,SlN|zTq\f@qYYKir5v$tWeX!%UZ d "~{J1b&��IDAT?t?>t_HkBHZ6JB> 'p)r`R Cg1͑lOg%I;m ZkoqDŽy,{~Bg4L[\žsثC yH\tY*F;p[KٸrJxͅm.Py }i*Gc+OR;O=akn4\1#y|0 �4˫_RJM-Xp m aٺ,-((ZUP�-L2c\|`ݙ2U^~u+,Ek6EmIڔTfBZ{{5V啗_!='3,X9Ņ^:HI k>|�P#~&NjuЎ) `Ҙe,]bu%j<W&aƊN;c}ߟ$Iv}{.?冮'8{+y� O}. 4sgJj }9tnۜq/@ﭟ{qc9F^b߶]|EGSq 7NF݆1W~�ۛ!K[dҷ}d_Tsє.-R & tkKfur6Zs0 .oۃ{ީljQyp!qkq@?G ǿ^Ҷ\:A33q ?M+ yЙu@uLj?gO[M. FڅaH<gۖ-y6lRJ$I<q;+%~nY?ϊVZEFVH૚|ŕ/u%6bM$Iҷ5߷v{z:ԹR\Y݂++$I$%#WV|;  +$I$KU]$I$I +$I$IRR1$I$IIŰB$I$% I$IT +$I$IRR1$I$IIŰB$I$% I$IT +$I$IRRIIlӬ-ؐ$I$II-;++WeX!dJl$I$�n$I$IIŰB$I$% I$IT +$I$IRR1$I$IIŰB$I$% I$IT +$I$IRR1$I$IIŰB$I$% I$IT +$I$IRR1$I$IIŰB$I$% I$IT +$I$IRR1$I$IIŰB$I$% I$IT +$I$IRR1$I$IIŰB$I$% I$IT +$I$IRR1$I$IIŰB$I$% I$IT +$I$IRR1$I$IIŰB$I$% I$IT +$I$IRR1$I$IIŰB �D"b^I$I% 6 RTT%I$IFwP[nMl$I$LlJʊ뇍vaAD"6lܘ-I$I6lH݋BaE$%b I$Imظb"))?86oUqaH<#$==$I QTTT#Bd*w 鿫X/--$I$GD"DQjǏ *�|Ny0$�H %I$IOAe?P-W!_%I$I?`džVh d`!I$I?O 'VH_3$I$I?]Ζxc1]? ο[GE+�4]?o +-F,. 4έ_ [B5nIE[$IR1n% }}?7ǠAW?ȴT}d0ɏBd? `?^xs8]RjY->݉To Ա.: =c؅ClZbx=$I$ DqX8uIn'�QjՆU)1~ ]rrH2e4:doUa[$IgXJ40—뷖m{$W^DP%y1|o9n�b89N `Tз}=ztAV X Fǐu5WS v�>2Q ĩܡ3P ^k ׵f4)]y#<)#+XD9cèeqzio>:'4›;lDWv&IĈ2t8.bxYHi|Ts4،pSZ2K~뺍gqv<FL`1-s9أ>~=ׯgdu#[p)7_| _̡QՀ@BsJkvj/& Ӫ}AV$I]@[@c33q|[PiаI]c8;IkNw1LǧQo <8+1aߨl /oJ1C|kBhn<_֟g]' /(hR?]fqoQڝ\.ʫy-?$ˏ񯿵Z?]L^1r[f$e8y{e\G�=<G3܎t>.:eqb `sqӲU<4e3^+oƍ.x⡷aoV5Z\rRx=b?)bȘ:9/tp<$Ivmn%�C*W1;YjWΑ!@Z^рԌt"F3eu8DM#bثx]~| 0OjVZ�уφKy]>IOJ} ,9X9|p̾i0 J~5$N<6i-F|> e݃V u4 ⫿*]eH^|-:t#ZbVYVLzjhj@4bGMZnѭsͥdtϼڔHݳ7'L0c}K <ti5v E8C r:P ۮ'>zPE$IҮ̰B(лY8㍩oN1 7 X\|+@&/+ԩLJfϑdCl)4M 8+VǩYCJ5#"))<55 =NRVy[Jj*m+  #3sBTү_9y[ 7=K۶3ж Ҫ%-_�\5gmw/'®6kPt;oI4ұPEF�AZP"55Xc$I~ +[YWyԫMMNoÄ{o۲P*CZ9c!u�և0w[2_y65 C-@�"ɱn:sw`GٴeθtCojr&OCՆ^qġ*� E:ðx'aB$I&kVh2s qsl�#b;Wv^yiyyG^9Ur c8ϟGQ+ GX_|Aqkkh S]{.|9 dB3AFQqaQoFa57b˨Scתx$I$ V:U ҋ>!3+>Ky萷h&L dl)XF:Pgo~l2Kg5 y~: +@<7Qo|!bBX #4gߠx"m,W߄ RV3x,<׮f%d.!Z5 ++`e</"imǸٛY8s]GR*);٫5/eYSg_Oҽw3/+I$m ڭdp){1y$Ȉ{|ڸBG֩wpk2`]tp ݕFĸdk\<hT,Y+ދ_͸<Jۚ=�'p<F^591whϦh~y~ p^Y8"}Y>~3sx;2| >n8q%tQ/P?]&ȆMT'ujPzf~K9kJxg(|o4¥t 1$I~[zsI$Im $I$)VH$IbX!I$Ia$I$IJ*$I$)VH$IbX!I$Ia$I$IJ*$I$)VH$IbX!I$Ia$I$IJ*$I$)VH$IbX!I$Ia$I$IJ*$I$)VH$IbX!I$Ia$I$IJ*$I$)VH$Ipa1U؂����IENDB`���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/docs/fp-message-admin-plain.png��������������������������������������������������0000664�0000000�0000000�00000152665�15223753015�0021762�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��)����� @$��� pHYs����+��� tEXtlogicalX�427/_��� tEXtlogicalY�183v ���tEXtscreen�HDMI-A-1/ �� �IDATx^yM׹>ƾgV.)iAi셤M!d)Hط؇c3Xw9?n2|<~{ϙ{c~pa """""""r7(I!"""""""""""""")(I!"""""""""""""")(I!"""""""""""""")(I!"""""""""""""")(I!"""""""""""""")<DDDDDDDm3079-47`|| %yIֻ'""""""9߳bKBB=DDDDDD_g`nϦ{AI ׶x\AI $LAI 2m@^,=WzbN"6"k .7Bv+czaۯgylNg�m fu(;\DDDDDDD$:KxWt|s,E'K.r{XіYKK�xB@hV<B,@NV߾xX{̠~AlD1"{WR^7dzM]ˋB!wBV3, #%)qcG>O#h}7CǾPt}Y9ȿM=Ϧnu23g\`l?Џ;UN`~92\h:7+O*Fo3fR{f^ngbX9 p:?Dw\2Y<u8=_s̉$/- }i9g 8<p CV!{g�X^Z![pl sW}g=g;n~svEDDDDv B튅].K¦)ٍf<~?>ٜ@ A+r"~XKfy <\S o@Tj�3Vh:Ӎu#7osgHF\�?D9ӡ/$`K4^≒^|V{`M,T}"8&'.r`S~81 f|n?췊rڍQ I o*%x6籭qmCc#wDDDDD GrRn$ xv m>%80�s*lןQ'/>[_6LvZfL=rлcMJԊQ?keG6 ]}wIg,lDW_w{5g޿a8g5�_ rbKb#"vJ#x|/N@XAfѸ7_wOg¿t;} ;'60{#i}Ȱv9{[Q&`b]5l@[ܷlPp&';q<f|(6`crF!XMsYyh ׼:0X �=[L$rVd⏫(޸7w$u0nΕ8GN>+s_\ΡUnb+޻аKjic�u9| o|#ەx_>W ط #RZeQL@d6mO+GfDxi,�vneᇣ8<~cۗ&b_.V9mזNFod壔d} gm Z>i0�0zř2-&ODSV`3w"Y�x.�m0ut'﷫ 0jr_LLˮad) v~[1gujL5�:9 ;<w1I4y] ̷uIDDDDr$j+ {bX+6[� ߂m]�wgcW8}jTl#Qyq\;~J�ol:̚cGpN.JzZs-I=tйbװҽ+ ߇8#T o(@-;ՊdJ?�XӍ_`Ə |"o}a>k*oM3xHx,,GO`W C,>nR=: C7&jQ,g�WbR=.[�Yyo* YvaF1j({1lT GJ M�WIoPoU5!n=@ű`'RϷBZY؋>%_;0}pc6C2&/6C#�Bӧi{^zQi/۵-W{^3ٚھ[<MN#xouBs*7{a2!A%/Xtxsi0l2θH6OPjx=Tϫp©[Px)UKxq:!lÝ �zC}6k/yGG^%ػM*WV� (`%ܯ$I߀7<0rG}@T;iRWzbOS8v Y Q,dx*a~;W^HDDDDd�Z_z.`ڼR{TbPPHޟ֞ŀ ]RhL# 9ǜp.0,i!̉3ڽXs1Ih@ZD,$|s7`@Ѵ9$< &<Y0 ,fZk̄@۽X|Ώcva�cw@Mzg) LgQj4tNNdD,t&j]^@@`l<Ѕx`C{30 ^+x @ o.E㘷2'{~wcKj<6 E&kgFhECq @A1~pRO!䣾ձh~;(39_?_L mK [9## T V" r_!>ϑеqAdc _#n4x(7cg߮LZT@ tk_U!=7dy%+]Ф,f#S)/C%{Tv #~Ͳ u ~SW?lHKTqox$[pV(ٸ<- kN ¥)bsz>T?Jʮ0ҍ�Ŏ >L:;~ =&))vL-\Ԅӂ cQ|jT4??"""""x,7EbwX+>gWJ9Rtï=bSb}'Р;-(r:/"}�[g%۔`~ L/K] y ˣ)b1>,'sl۲:RMX$w3=%0M|7n3K &ٍxl013jRWҵ`ς'⑷.qjdi�`F`l}RԭHV,yis]Mþs4?$Ǚ$a`RXO xX_�!2FeY[дAA6}\ؑFAy+CRNj:|>#MK]>#W^f~ct`wQ-^z%S ֞^cy p]�il(LG<�I&DF(@g[%;K.f�F.WS?9j53^-�/dLLb,}{? I~`.>~ V_5+X*.,{E f{a)xy7B fJRZ|WXͽ"_ʞc~+ti{"VAb#^~ޛUaxg'ۂ->vLM u'\@n[[ .?Ub9< Uc]$8OyvOB|l03;mŖma!0IdmHX<Jsۧ4J~o =kª*:l޺pT:Z€ 6 41c/""""rd+e#85�8yF /!G5׏YV 㷁{&<OC$gpIc^|4I8+<ȩ'Ip;<Q҇ȇfkQ؁D9%ܲ ZgO}`rIӘ<x6}At+N0W|M%)2 0?=3 [z{.&e$ &]/5&[V �>&$D= qE*&&pB�||}]pL]%[8MRT.e/ Vż,`yz$;/c~<Y ?44jſ�Ԍ6>=͸r^`%ISG#Հ p+Z2~*�GÊo'T]]x7Ov\G<ԚhTO֮Šh?ֆp/pO].p9q,K)V~4MGۙ�:킈Tk czS[Ws,3- 6G´vHB 'OQb@#ReʓXU^] ~#*V(MreyݎX%_ߓbna9`MkwIDDDDv3,Ks|W�]rՠ1V`V%!<q!Z: rp>$ ~l oD҄ tZ6cK{..0vu4[?ztІ^#rq8=un>T[B0SI#+;{ I+~++.Xh-n͔7Y J_nMa� b` *d 2xY ^-�k>ěc|~d #mryg{b`vM\{w x]Q6x7&}g$c`'�ޞ.2q2&-vNcu2% \;y}=B>#TmdZ@E_@Պ~#SYƞX>[\qx~~tB#*]}I,3xƓOx\Qn�8`p4<%99pb�>ޘ)v�싥FXrq8yoMqt^1yC-jDlxJdϔͩh'u,\Gʾ{ZF!""""w5wvqWT fyr`=Gr78Φ?0pNNkG9= 8i]яB poQ,3mTk bp2 sΠf>LgK%g bIj3]܂=B'ryY|. <Z BG^kvrlqhr+|K7qOon29HpI =Lp%aZүXؽ:PǤb/wpaGK. fw@׃q$Eb*$ o:ɀ:A&nwT /-}5@ozn\Q?>zZd'qOĠM+ɩзV. ?}٘U\|}Fdɘ=fzZb<ut[j:#.8"x[{;d39bŽ$$`y4H̊/O?!g\<g˜ppXM5׉{ѴYxCV`mbOS)ܫXvqcrGhS6X;6uyef9\W%&3)\#Xw*ơֹ?͈zf',ĶX2r GDDDDVsƜǖ'$|yq\y> k�׉ǝ3qr?^8SrA9mx> "}`/Ta&<W|[fCWX0cv(?d iO;σ3Fz!xX7$ф0pF�r6~0(h*? Xh7 b:)ñMO,w ϿA|l%O`8x GtʮCN@:؊<ڵ) SzrIT *Ua6`\).i{ \�Z泒s\yZ6g1CAYIxzg/m,2Ÿ8u:yYХdZ&b|x->Ǥ7s4/8SzgB(ʡyq&:}KYDM7׷;h3'u/1k bjb t |9ƚ3SHJ :c¡mv:9=m�}7zY$ F|<l0ٛtgƌP̸�pi^J$w-q= ێN`eTMYgowwM\W2ɗ ww^i0C^[%h[V}?_ cL ~׈ȳR +ߝB|;<;+A(Y &߃ J+OriRva?8,?W7mP뒒5w nZvl}Lڟ3g \9“ Pj8~$'*zQQr,@2)ܠ[EӽR /g�g`Ԛes9 )?Oĸ`uN.FH=[*w9 ד yW#>hޞ<)9|j`[7At@ƟuK'ħv@p Xۯez.i+?�ߵCQ{845?wC!/v]tͤdkS8bQB5 ;SvN uy&dsfȆj2&VVLeidJ(լ3/̿yrf - kv$úK@j4j\` ׋.^k´7m꺐e(a ?uë@N;a5 [̎%7G,KV&Lf)ɇѪ|.>gS0/]""""""&[lFVO�bim&p|.sN^t,9;v!ms�앂P ۢ w?m|@7]I�$/!86 [=a_'LHZCAd sW]-^5淏T:l$l>Db}j1*-pI0fWm^GQ+éx!�bVxDc,_ŌM-WmOj{pU>2O]0a$IY(1OO/C^^AҍRWR@@Jk{Iq [ɴZ5MSM&7`Nʏ_GyN/]Ca.N~'}rjcd?Zm̭ԟ2όT?#{6ܫ'Lϒ{Ƚ!'ٜ&vmklxη��o+~3~$q>>JW9؆7~ ȭLlN ?_ &lOLfD13dl1:~fߖ'{>XȹcHd-.߀Ux3_Х9Ye0B2eҗqE*}v) DƧ=L7̳׮& ]8ħpZ>y0$|[Mtdڨݽ=�� �IDAT"/Mk&Gv篞a^b'CJ R> f<.h:hx&R4?+vcƮRDDDDDD<x[!Xvoְ�)yumAIexǽ)?5'/*se.""""""7�Gݰ@rqKplƍ.v!""""""_`Fqn{^e?$d """"""r﹝5)2BM X׍x/\#(I!""""""rc<9k=CDDDDDD~Kg`nrZinkש&d !"""""""""""""")[u׶gQ?$"""""򟠕""""""")pd ZI!"""""""""""""")(I!"""""""""""""")(I!"""""""""""""")(I!"""""""-_۶m""""""""wVRH`%$""""""""wVRH$d JRH$d JRH$d JRH$d JRH$d JRH$d JRH$d JRH$d 6φ4M&egSYDDDDD܊y?NRɥxRIOAL __ޒf8N'?ͳXXVV+6?N9$`t/(r ))deώL$55+)))$&%t:GJq Zn&gϞ_ϰMKNI!5%\rfIrR>d -p1.T|2<P[<0 %(R|m qy""""""W֠ |ݫ38p"%9???ϐ-GJrroܛp:1N%(DDDDDDAAN' �P n5f#nlLg 3p9P:CI 4 n#@Mp-K""""""w.#CMRdd[vs.KOl6.˳6I!rk)I! afJRH$d JRH$d w4I1I}i\ 3œiRǺP<÷Ĩ i֙m_u="""""""rhⲳ.v*H&C3DggIo^ڐJ|b,cL<DDDDDDDDnͳN0]0O]n3-qy;gf�7ι ț0xvpWVR HXrs=�;mPy{5ǽ%1|1Rڸ0`U<n^ y4-e 46 26%Uk#rn\mz jVhڀC_ÌN>jnb:4m8>hg4~a�4>{(8�zhw<4׳-k:ݕ$Ee/(Ҵ%/L fR;{[|hswFRk7kqDZ%w6'з'g1%rN88-%H)ZX3vퟬ%ot㻀VeưNnLB칔?-LFx)†-8ïNDDDDDD?$)|ϗ^q".w潏G17h(';Z )k8R3m&j$8N-L6''kAiþ0se-Ö]x4Qu~lx ^k:?5?.!'὆|7v2/|-̚w�Rܫ9Vyjw1axUaq'$I7]IR�fJgcYNJ/%^lXI5>[qluzJٰq�'LN<W_+00σe|0Uds Fj*`8 U ,%we/pq0/rTLL o]LRX^ b-֎CqFJ-?o2rg}k X Lf[[bL6-XN@Z+ -/9f[ ?xʩf+t+vC�W1Nw S5'DDDDDDD2%)�f]atkD�p I1+6@K0bqzkJZYϧX"E2|}G4!'$�z{NaqLT|-y/+fk9-ɦ#)bvq ּ{""""""""qWAzV= ȥ#q x~ w!f<Á?"T0t80zfgWy[W҆cW#ߘLȋ}V{…)@.P 6:؝ /'kL^cO_ jƪ`=q:OLS8_DDDDDDDﮮ�o]bxLk{<gOjJl#؊X )`R+raPV2UûûrPNP� _,>ǭqhV%J2q;ɣ>и3sҍo>j&)we:L{e:~ x/"""""""g%$e4q\DEG+gN–)T ؇W;C7eÿ.9KyX,ȭr>NNL$_޼a]q'tBa%*c{/<QЊ#<]r׷{nŬеks\.~1;yniT."""""""w= H<gHDDp'4 ݣ,~0q&di0B͒t{?xvOR-/Oeob-gL_/`{y?k<C"i@)D*7 0fPmth+Wqfѧ(eaNM  "nI`Sƌ9geL dA'-Y.A1$zb.? fnVq R$]0aIp8{nhy-p9w8Գd,Ӟ f| \."""""w ,ylgL`s[<C"f<C]8O, 'TAkOWI5)D}8"wtΚ)x-I! Iq-&GF{^|׹UiZ9׳&JR%`I!J֒tV5IڪY3zgsp|xyY մ$4}3$""""w{Ev8]kb0yD2,X&p k<EDDDD y6�p StWn>[W{i,\dXYs^b9)7;5ʗ}ڔ,Y<M l:% ٷ{ g"p%_"rPme�k9 neٿg#1ICyY #C�o9vbn%tΤ8Y@.jUz-Sᦀ8o2}j6\á8bM2ؼ6UZ?[[k  LjGުXsOepf}N^S=dUl\Gz"мzY^|-oy5١cb祵=lȋ,/m=K%eErtE/sVi"Nőp|A^<R0עJ+?@*P KIIti:-^5D?/'AK@݊%yC3 TmGF""""UJRAؘT {yo+)>󟖟q=' аNf}U8aз!,!ft8쎈awD Sor_ް+2]E$;c8k5<|x;£ZNJ\�l#&<D]L"16cKVs=Wޚ ߣp#VBlCl9ɗsWҳ5 "q[1v[8ls;y!t;oRZ0k/ېf�-ӹS�IP+NS6}4/2�ѿ)S;md,ugᘋW~ X<x,;e1=g1a`[I98�q> {X7+/,3TZ:sCۙb;,_�""""{A&cNt uU4fδ<Ԩ OtL=9L></tDbطa;BN}8s5 O.`Qx^řClqs}b\N2dƬ?E=_. tΨnl5 O&Zwt<3 ct8\<eסY7~4_?uք3! 4_ǚޕ ,Nv=&ݱGoFߧ&}?]?.~z']D7ޙ˰2k8bC8M<K?9?0ṩaz5]Ef71KrsӞM" :5٤ER a�sBh *)l[+y-`ӯy}LxeL'?'җm:bh 4F�a;_㌽vBk5J=9b{zCX>.~=�|,m$&K8HFʁ~�Nf~贾fIltl8o2eH̤}W0][>܌g\$nY6(Zۀ3gr9tkyKlK1|3t W+eT 'o<ں8ܳإ14~G%y'pPguu+�XxEDDDxvd&[f~MdfwLǩk/Ji\\Z UI^9ðtI>U"8oe0b}sF׫6mJ&eFY >]Ͼů ᗜ=mO~\W>^sž(ۣ|;o/f|HZj6 #>B:/fasdoUtWzW"/O8kwScJ7Vq5bIϪ1= 9{:>98&R3^0Qƺ,Šc)XQɾ,r}Vȍr LٞII"uUYl/:l-w9؏ ՠYx'}Xa/lL{oFo&$OjD&P.V@4o{&8U.*7O[ VOJu`Sٸc+Pp>Wa+$xE%Pl 6i]z[{x%I8iMk+d6b[ikŒoV`:k()Ln¬18|cW8.c�kRP01g2{M†\:-[Quhs|.ܟAـ]Q~OQC;jb$ b\p(d;i5}%)~/Ʌ>q3eGZPIP'`C^cZ2>?{urywM9s+?}\1_V\_9-K {Ep7i@HPCo -;H"( "h@DQPEbA%JB=Fݙ%R=C8ld{uҠ/@[;z7xm [ٵ=/%#Y4x;zRGdw/O͉yo?{^1-x_H=2^ߧa7`8c{ X8yr" (y�>/涗T}$5W!B!E !tiitjYhTPjW l о*mHC;|4n9�_/T/;H:xX=G[noU1݁_tr  /ٟPzR5-; `u^{;83u*+`Ğ`lb[âz%a8S0h'FGPtdlrn>g}+} &<6H沑SS=lfdjځwD/\H9K`}~u�L'1 S٨;3csQ�#~*8@nr',vX(�ݸ3UIb`_/H]�dMQVF bpEqB!"OQZjm z;F`hj8 v�\5b8N бuIDjvUlk;eXIPk\|`S:Q*8{w|Pd׀/X�š0`:[ AVp) ٯ�;+IEfh��pU`\�X+bEZTߓCN'LF98z<b @Bn.fbLyװ.<XY[cS6#ohYy=A5A2{m#"mpA)hE|e/Zl[Dsax:rIMՀ=,lEmA]4�$�RRc !BIB(M 3Pm3J T>:ZEhڝ5b6,L=ޛ8!Bơ,/eSpELbbD^^vH,SC)Vf�jUJ5&΁rqZwlPwP�cLPi6l&UnZԬZ5^uӀl ȡ]D\>G82oYTi D^Ub:t^V$߹~�c=m/on|&cc25ԫ}~\~kb`["$ϳQ'ke< ޲B!H!SyhvoAwdĆ^cylʴL pZwsӀwq-CڑрHl|o ZAo t6FJܤ{wP.2(i,#tGcR9b؆^BlӐ}zH=s܎bNhT@͛X)Jփ"y;VpuE*6˙ꑭ=x6iEdY>;\}YyM6w,bĝB!x>IB(]-# hT�LGQXUٍ(СMEn[ӀאUӕf[%4>Đx{_22}M ヶǓQ\*x`Ʉ[h;gs\9qF܈z&fKƐAI=M�� �IDAT?{=Ge@3X.�P(yxT@pp[Gt ?>(wO<o୳방d*R� w?G|B!"Oi�iz5bV'n!^CXwbj6 LS=4 ::){`|m0o&8h1IWcF >Yw<kؕ3 e5!Ad^?^Wdƀۙ2ځs@q&Aw@y˭0^(D%l* xwO�S!H{h~L7?O<<]9W4o{KF8lQ�{;[׉xPB!x>HB(M-4MC:5,@Ki{y[9sʙ쎱tEW`kkn:Ʈ69[?ʻ2% jѫ8ƾÇٽk/ig^\L]o’iKE"i|4ӏۣqL4v#vcM矪sϲ\leEJB;(Jz7Prvmp6opvu%kc<ͱGÃs 5quo3+7DP#`W PЭ�֋~L'B!B</%>!242rm_Q;Uu 7Wmj3힡w7׷(=Q*,b-P<?ovkƜ#9q1þ^޽6j9;1XsC>~A}¶-! bc,6adhY94rPߢ@(t@E|e#ZأzZZm%ObTZhAYmNj.=uڝB!xnIB-~.@@j*ײW(ܢ-?)@ݚn/c?kz5 �ΦâCsFvJv̷/v�á\zݪ4  Jbm@Sy{M u6QvljnP"}rv#Dwg(8ݽХxZ @5"JӸ;dd3p}զɻy7#SaP jmPl+XhkC׮37T rk'AjB!?)Ruέu0ur;r@:P}8w$xШ 1?ggoÝ]< kCxDt"[Z{mm{W£ns%".]f}I91[[^`F֕0X&gXĭb޳E,];r*Ҁ A0m<B6ǣ쵈o8q⁷S'NrzPIhL?)VnDd�>Z=$ۃ!|9DB!ϵ:{Vhʼnyyj-vJtM&yEߥ~>l֎%+^Im뀒ţ*ovԜm /8M-]߼).+Kc݆i* Y4vɇK$n!g2RA,aTiރ[Fcof~Z1j'Зc {x6Ԝ[A>@tWi~_X:/~,7+ofd}N_K㯐}ݼMM6ˑSwS3W{c̦}=TjD\F>8G-L߹ygD7x]ϫM-b o^GtؒrcZ:Nql:EΥcxWhDD-ێsG< HB!9T٪(Qs뷒``?hӶ&sy5{vXxTu@ &h@XLaE;Vac;c]ֆ{gЀ=Uڿ6cBr1#N6Gi}.4roN觡�LN~b?]f�SG6}=۱D g)2MwӀ=lg"� Næأz\ǺGdYGZ+�5̱Qu]XX -e9~[{:?"cgi^?)B!sW@lB"kxESy9&'XąT}1#sF֦|)<*|6h3wDŽ(%-4nHƘqNa۵W-3k^5 9H{(>b�k3�ؗjh4zbG4vQ6e$_N+< F ( Zqu-U!_f.i@о4P�`篡+P~pv+ȓSB!ϫ'=h@ȉdں^7wUI@%Ojy't˄MO|FNw2PIaQ)L՗El{s¦M?ǷFWLK Kul}^PlXF;MNblnr$:&�_6MJߗQ7_GU\UM5%NC=%'{56*Y0U)~]3z6y/|(@=/;zW$Tw[~b(_AkdWgwл4ǭxzA*8 dg/xYՙ1?Įp;)Lm֩{z\ATHhkuRp" lڐ܋ԈܸpgOaW{=nzYVB!~t)zz;H츰ȤBJ�9W^/jC灯1.:J|կI16Xі>{6ZWY$Ju:g}#6 |=sɧp+bgSS\F9"Sm.a+0WU|IQNd|φ\:- fSb o?; p΢EI/6X pPRqwb4 k,ۄ{u(uU mdV|-p1d$lD!7*S:j Y0=/cHXsQn&DCV)Iں1%0�4ߙd#{ڥvBW$;4J^L8ę@0[JֹVʙ �oV+@c6vl\ Ч'R͙5zdT6p~ll:cp!"�k8oЪ;m2Y >оWA_xυf˧3gVvl\Aąe&Q3?jU^qȲPkMdM !B盒4MCUUbbc鿥hES5x%{t0ҏ{#75z~`z4[OE&eӼπt*rxSz m׬z1C"2icOB�:ʄ iyu<. )ФvY_9>7e@X/x+Fi%2/�`3M�hcqR<#Y6lt(ʽSS)m' csL,y(FՁB!sbbcqpt|h�66:41 VTgRX(zӕCa1l<bا),t^ `W1:}GOPpn+FwaI?69âCG +@}C2oUqQ :AfVÜ+Q-LCҏl9ll xh=ItuوKo*ê)Z(]gB!)�tLH:rC)ș50�>3utQ1rgwFv@UTL:̂_ӨRi:V(#z0dC"'ClV~NG_2?48ʸ!]y?E;LW7tX(RUYOtC㏿bE*4-aڇ%,~];ԴSpۄ6B!L�Y@pHV;cTȈpli|v:3T-4ϰrz/'pȵ.lalܲFԾz3Nٱc;jZ<}"qU+)FC�(d/lx) ✽H?0ua2aB<k0vfVqցshSm=Zͧ –U1޾L$tm=y?DB!yfE 5*bߑMOv"X4Ç&r+Dܽ%=Wfqv1WpA)ށ5 b(^Ώ]744&ettz IJbv*έ“TzԲѻEu>V ! *_{:xy(^\ :7�bTz2sulN0Nva?*ۨ <jO*k&=r+M:e{h謹;;!B_L*9p86$?@+٦_$cόjFor';Orf49{3owe۽saxs'ݠ_{t!'I9 M̂,HH6*6� QXFÇ ch7$+?F"7@k �;Yп9Ys:ϱUR {Txhc@t^2B!BSycW4�#�_'2H l,1CY0qn> ܫQMK0|4N !B!û{</:LƉkFv-{g !E|la{bD;D\| 6xBIԬB(X1B!)#N_fhB6{X#ӎ_e}/Btf�`B!B<R Xu-U B!B!3~B!B!Ϙ)B!B'HB!B!y)B!B'HB!B!y)B!B'HB!B!y)B!B'HB!B!y)B!B'HB!B!yuANdⱉ !B!B<fY@%8*4=Q~ƥ j~Я:MPFѳ0\N=0t*S&e1 ]'iTy{Nu4ojT=Y5:-B!ȃH!NiV d;ޅ Opn/cL;x=ip#ƸqX{$-E\!BIB'|<^5^!L CM:`i`*s=[tTHs!r*CG(| !B[kR!? υq<度0u\E '>b �}4,ĥ3;IcX@Iw z/�v$ {[Pcrf/0u׿;̲?C->=йTƗrH(䵪ѥCQ�c9h-(jΨehE tZyjmʇ=ْ^ Vpy<mY.xq< Żkm@j>"@_Xc۠*\en6&%3n z70!8)3<yggHamRIWh\؉6ƭts (t*A܈9o -4=qόg@ ~/ĺzqx¤ٺe[{vERB!x+ˇ|;m?s?E:3kJ0^%IwuV֌|G16T @HX4j9bZ3z *>$&x%UC;|U&Y~ }* ]x8aS>1+vxZectcK( }4EOײNߗXɉʐ~ >Eǒm4xsaXG=`cqeǟۓC؟,ԐF~〉,]0o\~mc> |1{Z1~RY;wnhbc t'fF+/v"MS0/fˆ^5瀖l~B!BWHB^lmIDFUtb-ی ]i٠'oݎ$IDOBeW֛qc_>�z`l/jtOa4jٸ|`;Ptm^(C]Y{-4cTNoeD&-Zv<߫ N`;@iؐvۭ}xUF=b`i= ObsH~FhLxBQjuKP$( 4q0p|MŽY7BܑC(C6(NnE•[֛rH$ȵP)[&ݙܻ jtTJ듨\<<<Cu{ TW:TT"E]=Q+bA aFTɢ^Vvν6�njpfN>PReҤ];"3ZYsB!{B$]23/h(`gw`bThJqtj^ 4Xv5q(X+iH>;m 0F/)5+7xg/WIsz!=sc7lŅg#*8!,C]s{[Bǥx 轋6W<Q^\7MլĚ+k#Q/(nU:C%{Ǚ#3cyL 7`&3n )_ѨJeUG:eaX&Uh[U#sv,K5jFZX X{�l@\ͤhuL+ nwD!B)R\4qQ-1 =)X*G8T4i|UWy'1~;_UzYQ) :rҲoʖ4o~YW n0`8Yn4}:WȦ\mH'i�FrBܙ0Bbc%4-֨jtw渋& d6>?3&jwJ|{ۯTg[~!1pfD__e|+a:a pNEASWEU1]>q{@_P*B!U!MųR5nj /^Ge Tņ, ,�g{)yA+2`W `0nY25PL8}-bJ,+dTO W@_%j7 @oFZVR:.fz&Řcj"BܞYI8dʮ3p|; �9#?�Jyp) D{xP/7 'Qe؄gنFY3<ΥufbFP !#|?/^MVj�|A3ޯB:tDKL?GpV]R,=)Aa<GQ!B")R$fՄУ_<Q=ѹY73{ /"K,lS7s"cα3:IWORi0yA]K^DJ*Se^(ZL_Ȩl_KVѯ\2zڔpqXqgC_Cd &3`0�qX-FFjۯgppFR>+ֵN=2;M͒\pYJ״n EtĔjĄr^]_5 G%50u*._DZDΝ>IY680aN^D!%}7y:ږr8S EK=BfGur|{̎rZFZ6PA}F\ء̚%Q/@!B�!~5Nz:>bMh bLj[ 7Qȫj{wuۙ' n�� �IDATZ zTT*BNNZSVNkʢ蒖0;m3_LX6UKХҭ }cW/ yJ!25#9e?h)E |ѯS$1R3 F`L鿥C1=ӡ!NSL/g ـWه6/Î2yU%.1䛃xmMIag}l(w[6˃(K˳RүQU,=Z()2(c hU/xA+`\׫|_B!zJrJGfkRGhONTt4t(T y{[3hW.},h�&%ƌT_l,B!ĿTLl,=ՑTکy`[œ}H +K\R90:voCfN tl\:H2\&Jwԥ)."lc_C_Ã;!B!j"ۆHu6/pi+kWƊQ3mwZxfct</v|U=/"ZuFqܼ!B!gRqgQp8܍:-EMжuJ!Ba)s-=*(-8i9uOϦ8k͗9c`pnj T͎%[a)pj*@Ͼw B!B!L Shܻ-ˎؑzb`v 93Z>ǍJ/ 60FJL5MCΜnzUq8ޞCE !B!"y&E \V,Eix[;%Bu"Jt-:أV֞Fi;t,Njm)]؋qf Z_!B!ySYnݫ2o|em\ %Fs)oFYu x.CTԒ�ws{T̄H>\p FdexٽP!B!B<gw㪰cM½6s\v8 M!�.:^η9;4B!B!DL{d}zqP]PQ!@Q_ xnhx"E:zʝI!ťhˋ]Q\B!B7="@Q=4݂Ԃ�R-0'$C+LH`cMQHhRGQVRYc~ M=ih-S!B!y3/R�t(e[dC{qSgʸO(pro ox�*BVMf]<AO&P[|6 c?#iS%@΃ !B!"ORSR^!MPUXXxl)NCQr<驩N !B!xbbcqpt|h/OB!B!"B!B!)R!B!"O"B!B!)R!B!"O"B!B!)R!B!"O"B!B!)R!B!"O!Ĥf`4Ѭ"P�^=nB!BDB<Y.+@Zzqxya/L!BN{'b`K~')P<'lmmℽ-qi!B!S E !Ĥ S9^!1uJ!BK v!&%5''xs'%%7WB!I[E wYPN<9Q)֡h)9[[FuX!Bt!3AΣB!O)B!B'HB!B!y)B!B'HB!B!y)B!B'HB'3^pbu.+9{n[B!)R4{/D'wgȟ-+�;9 dZw`Ȣp׎Иs&uӻ4e ءI4vEa,N싩7]PWYhВT- ̘Qk֨<'*ZܪdSY!x^B@"_7 F#G3ǎ\-aɢE�t<UXsw|zuK@.Zٛ7q$Bɯ6Y)`h 5+h~Lȑts?o΍FGI"y kVaꖚr }h?:p^ˇGo+R#k\ zetJmWxLlLwf3dN2e}<#䚊sԛǭrV`EO?֌c3gbBoB92?BoUX1mm9n '-3Ιcq*"j%KпI:5#ʁpyoyJhƚ0c  77ff/N!!aIB<LQ !+-`stM#|.i82MBXU;yW0 ' :>sF`(Jg}B?^:[IootM(Ys+TEbsŋRl,)TGz4G5aak҄N?V]`h۶T?EݭZ=FU.Z< "(ojaƬC3m!)t%իp\xȡ5pɈg}_>}{8>v;f#+8Ջ;1(Y|&/{KO <R9 O\̮_cH8GRj\_|_cƻ38U ƻKwVsa8i83ey~5ij1~p[:?Jf@ʥgP{�uw4˧3�5¢yq#=ĀՀa`׀yWRmbOҪ#?,I9]{wi·|iҹ(0s'3uINQ݆qמ+33"-J6ȉ%>рGoq寯N}lauEm7JwR=\/NB1j.uHWݶvbL熸in; !߅C4ӄ_5{ϻx(Z?=!WKإK=w^CH##\qur V۶d LY0MiU*4Jl?u ҅VU'-'Nڵ\MH۷9xn~ %)%%KqϞ>4X-'NW^.ؿA;'q5!)yHH+L׏sѬ c9oTU\Ɋ}prpOÆm|>&-+fUaWPӴi#Ԣ-l0mDE}T�NFD0v}9pjTUG&M|~%J/)wVGqۆMw"6d%jmlnlEjhJasۓYн׷5PC#u[yh}ܛ&gxq Ud24Hٳ[7.3+:L05ZyGѨo6E2ptA߷qlGK ׏տoA&otZj.ϑz˿ ԥα%njrF^}m4m[]إ8?�Er9fC ]1P-^ϛu^㏚ok|2{G׈i> g#~ ·zQPoO$�~4lL X<¨?lv+dO]HmΝ4bT/\U 0߅ Yjj"3 +la"/ŲkqM Fc6q\X3?w(GW+݌f]327ioV,.3UahK !ĿU5__DEa0IXx8+U"tiݙU6li`gέطʱp+ H2E^NټX>+FS@�#r\�KeFp0vƂ#(Ȱ_5amGΙÅkט4x0##d}_ǃɰ_ F&M=v\CBZ)c6,ERÃ6ժ6, -melǓiΟ ^sz Ep(W,3_?t:Lax{{)Á)SX(lɦO>|^={nN)0xb6^ׇɨwط{0 y -!g1GHd1g^ܓ2CGC>S.AFpj{HQcٴrmnժ h9?oO'[Î_g_qiK''^Vͧ}+3}$&'GXF h0c=:#+-qm}Esg|k9{_;{B'=dM'�² )E۞|}F_SUYx5W&25*!=.Ӗl:t־Q\*K/.> c(?\z%HJ`~ ]Q M@I[@ $I xxxٹv3trk"\UOWfPz^Cղܴs0%|Lgмu*\ WyJ8ne דPKE>wd<.#G>zlb WCFI)n*;gnEdfP*oXtjB^lEWQL4ïæY`>^a`9+;b||ajOoHAQRRXmTiժA5klV+�}|)λiShAղeS'ٝvq8t[2eҡO0�dlڕ65kR)&gg[j*ep&ߟz ԪX#a,Iǩ꛹jy :jUHڵܶq{s҅tL.]$+Vй^=�:֩Á,mV?fnh׎ rYr<׿kê4\tZr nӆUOfZ Zzba1 |ls|z=]8)ⴳuǿ_q[*v+aIݛ#г9KuK)q 4Dp`,~A5"+ׄy_c?/6 cs*Yӕ+ˋxu9ѷw=F~Y,mՊ{u'N/:tϘY\:ZlHNh{-O^|b&>2t ih B닠p*L28VZ ?r�,"0 �_m+Yug>`Y'�>rp޴&fm&L?S^ JMM ~�7ut)K /͇"IfJ `YtqBIZ?&{b9hDH^8ؼGE0hWkS{qZF��# uYUh_\(qU%{Ɓl'Y)TLLh!րؼm L�|mVEDFDP##Yk{i^=Yժ7clJI={zlyj!~{!hU:=^y5kҪzuz5nFnAxu$^m\.{өwlZ B!ԉaÊ>y�Ubc ,/}{tGoخ۽tk*ODP*Wf4RBԍ/j�v8@Jw0pzYr�Ob99Zg�"VŲf~I_sqY_('қES ݉oID0(̼Ⲧ�nD{>n) f$U sg ?/?ǯn#f0}_ٓ~멯i\2=HGnȤ?pH o ׫8�[VwNױ)M|/t@^7al^] ZD.FpL\@ޑt Ä<+!6Ɏ!pZFjG42v jUYe2I9gX`uVn]O. UZ%o-,@Bߘ~@n~!.s.,&oz\ܫӻGrzO@LDOLdmr2eH{LJc&+VZ}۽Y3}:{ogG'6*8ÇKAeغ0< SZ}:Gߙ֎ѷy18ra^00�SNO(.w]سwPl 0C*鈴]MwƱKZySٻaF6]Uݵx<_z\)<ͻkGϛ (; $䙌Kg_xV5b>':dk?~!7d調T >i:5o琼z!f딣~'E,T=n\I9/x_:ph괁kpmIBħ?UEԠ̞# *vE0s1e5ʱ<ZkٞIu+2wd?Q>e < +,{ +~/'ƾŴ6kx~KLlr/I7xUaTfΆܽk6JIdeq3jj{A\&utnqh_\0&N,nV<وOr }c$42 00ÇEDEsiy=h p7Yr9't#>6-L[&Ͽ)Vİo!DzW59̠^Z|&_ ~T*/ _wrrgXwquxnrLFQDZI)];,7a${ROIf5^ED %&2f|v8@FRA$&.^ea+`l;otlI ұ#yYV1eKy =7.&F0{&tؒB:xo޽O/!:qp:GJ]ԼS2M~ZtkEE |-~[kS6"))4I:6c7N^yxy<1XFFAF6FPG<0gx^^[ɴ_gnC/0v{YMᙑؓǺJ )ܫcxꮎ,t6⇑CN{W-GJQ8f fJrMxo̟T98><}h0X[e#L͞UsI&Dƈ`Mpg&;=%CApj%pHPaϤY[zUi؈'߳8/}ǝo`w`8\:h??8~<jYS ʗ[ ^m94L\8E2olVݕ]ր{fe+ypt{e9=6a -޸8@j>8|.cۖ+pm֊;&ѣESZF;hz�Xq�7mAD:xKp~s 7JbLWc6f&: h}j2U3QPx)9_3ĀS柭 _`ρ|e?} ț �� �IDATYXD[\мfo'D* 9-4yrG~jiJ̦=p"(Y?ؼnyyJjYLmPMss9#giԢpl ngٞä@Qexl*wUټo_GO7ofoFgiLW&NǥKI׵k9W&[;v_eIOgҥt~y2ss=j:uيQQ]guwq^3}a1~Sש^= )S8}pa`kw3v9v<dzg_dҏof%^'^|yZVe�U+>EnAϘAq ghْ_׭c2wP·@VSד_ RY5y<kY Wk1- &.+'uo, 汧-h1~Tq|Q ZkW&V2Ê/_w>~fР%vhܙY] hNR\wiȞ&KKNB15iR)!CQ$ҍ.S i䃸h@+jcH"!ؗ.ڰ8-ǶEEf@Wk ^rھ0y-vYYL{~1W=>i),g.<ۗ7̀6Coᝯ6ƍVP+^4S7cu'>ںhoG^M~/57ex{ iL?ȂDtd!,WTh}3o.ĵm!O)$N'$/X@DzS;&0m]MM\V'Kēm lcÙ&rtDְD_v^Bo\c˺P aIѦ/޶VӨZ< &\jb/ş1|qwϠs+7BS%ɭú9",@pz^~c1X7[ESm0q+_~xsc>H;۳RRٲGq %$H?aٹ3_ΛǨ=OM<ѧg͢K/Ɣ)<һwgoтaݺ1zLΗu^x+ė)M F_ ï88U}vF ¢Mh<w',8~"~qc,`c/YL]Dzf˙~= jݚNu2KyԊ*l>y2m~IKr)cgvذg <FVN)Gbj*[\s/̀I`uXo8N[noױBk qxsAXKR=q:tdS0#ϑjFX8Zb1>};޺ |/ ݄'_#I O6J�V~4H^|nU& >}ZԬ] W:'==o&8ǿUGb˼tow`5 x1�-O){SRb0D:z[|e}DE_gIͿը XhB;biZJ{|2.{zoMD@=Գ x}s>f֣3Ipl-g•Ɨ Q<""""OMpkş!-©y(M+G#!r F{zeҽ7FP66a3k㹥Q 5osakeNbsr&2uCic^Ek3o{]rO82 yCE.<` &$ΟG' l>3?Ƴ3{c,Vª\wj5MDDDDD =ꖍi[ę<+[&&:hBBxl‘Mi[{YaA!kWb]8w5NL,iNMޔ0gove뀋G_E!/Rgf2y4cǿ_G=:~7U�N|?#\>/|?#g\$ǍЫV�Vtl31eXrZo&.FX nYsI7 G "``&,.b-̮ӑN˒W V2p u!4_L[cMH?aYrM?u%Ckߖ*z=xIϬsvU9+-"ܕtw &2H,ӊ3`=֞Y""""rA p/صO#4+~^r�~#^|4H `<O4 5{@oӲZ$ u o<p!Go_ cf76d"9 !ZV/K= &~WĔ_ʢiR �Xv}, dE?I|0=Ϣ""ϰx pni',y™Mps gz DA  g%C#)DDDDDDD+(H!"""""""^AA  RWPBDDDDDDD!ry&E(ߏy&'%VLW(H!rDEx&E(8 3IDDDDDa!"""""""^AA  g5#-=3IDDDDDDD8 ETdgy7%3IDDDDDD.!!"""""""^AA  RWPBDDDDDDD""""""" x)DDDDDDD+(H!"""""""^AA  RWy&s$73IDDDDDīx&+.Hp督q,D'qߗd{ 0K䉈ȥ)DDDDDDDDJRdhd+פؚcsH^=3ue`?$�V94oX@>״Inq!<7)^cWxs6wR'&7O]Cbxf4lȃ{kCWܓRÌG_pt=UNݺW9@^Z:uI4C GhZLˁCV+ֽYuZ}z]%D"""""""⽼.He@x% 5kצa:4i {voemZ> YM 8 ^DDDDDDD.hOb� .bNp9Z{1V¢ҷ=r]bLW*#f5H)N]\M8w: -LBiNMޔ0goNtlRD"&:h"  \DDDDDDD<A Vڡ99º_/eOfcX9 [6`ں,3װ1%a`atl FL=]fOϼ?S^\\. pgh&Z?=uM\^}ke;"1ehC!7%z0LG5>ti@Bz~Wr8P_U6k4Y99%`&.+[3[ٛBlL 0<q~n.11Ց\Ϥ'Y9o.O^^!! T?*8 3ڟ= :CD �_v?Ϭv?}+(:k !2@+6L` <AHh=BK0iC&)KJ1_Ou>3+nzujo?-nРr|3}yGMQ@/S Qܮ{~8�N"""""r=D 򋈊 L>0𷓖Ipgqc<JcgQ Gu;Wxf6L#&e0~մE[a:>G^\:#4-V={gggƃ�1L.U\{5`_hw~7 xj? l4XDDDDD/)D.!ffrdx{tee""d Q`?03k5k 8&7p +}!6Mgݻ71.”y~G,]egۄ$=p;`3.s緌^?/bCHY]u}"N5}rLIYNXd.ߙ_YYJ9+\{lMة:gs'h:~u7p7�͂!E>;w{y[>n0vb2q yPc6`Z ׹-?esol=j8پM?ODDDDD֤\0J&&,L\Bר=X_fɑ&0nu/Ç+qe,A<5n*+CsSjcv+�HPynRu:5+@!�[l-q^$w!7' ÅBWJͪUYR;vS\<\'9՘xOO߫b3c�AVNs`|/�CWT`/n&_ ~w3!_?ᡏf{/0aUcm̳SnN?~P2pɤ|mt|;qS\<^DA<ϔO@~3 Rf AD[C1 yP+j,z9 AE<qmK |ٳ`E?OLF~RȨwgQ8NJ�uigɔ_0ܮuFN7iM K4Iׯ7KIGk'P|2O=X*FR}k^R*fn5pDz>o-i8ф/&ZHl,-1;k_QW/cށe{7p:=fb~ u$c(Jˈw; ɻ0"ϥr}nbd{r&}<+зW%V<ߘz@g1L`Һ|X78- Lh8G}CG{֗�keڇSG|4} dMJa0r^`/ɓ2 ݋[�w3뻟s!څyhϣΝ sr_1XY99:N222b 9\.DDD`Oir%6&3:T$3+_r+$4$<ΫX,xX{F#) n'7/@l-7/?f%4$3=}K)�9t~~~x3*r8%<<3?fl X1?bgm0 0 Cﯩ\.r%84:K), >@hXSPTt"g|| jvnQ*=nc]sSTa`k""""""rA 80M 7&A M8 ءTB΅""""""鬃A x)DDDDDDD+(H!"""""""^o/)"%gz&x�Ϥ"$""""""g@=DDDDDDD+(H!"""""""^AA  RWPBDDDDDDD""""""" x)DDDDDDD+(H!"""""""^ "<Fˤ 3OH f_b@Tdh,8YXe~~u% 3]>>ΔLwu>dܴy< M}+UY}&r)+Ll^WȷtϬ" 8S\<; \޽#r*rZ*_@2N`\>v=o!y[޲9u XCA}c~O_le,=ϛ&٫WЪi<X</z  Ǡ݆5ȥ�z 7N*^ okxӅ9m4ÚPlg1 !6 CiM*TkxnrN.TBRB+/$*236[?i^ S'=s؄ô]XGޤ&feҶvȅaGo+[VM (;bWYweWV. 8o�o7z[}?XN}]~%XN]tY7V\LۙC3xp]"uy&ۖkiԲ+Xْoޜ?ٲyQpcrkl%pl?”93):Ne[;gS}<",T'}Và0/3f;6 R+&O?[Sܵ*פMS` b>s_F\ݿ-r'B6J^n`0-g"3uU myutNf0~WkU,X8 gN*mc}e|#kBöl^*~y<ٱ61;ab<͘qx;-0JWp?1vve`c~,32U걷W/5o2~ ^#>#w:82q4Oyqc gЍ9ٲalyפ 5wßfyMuπqZ}$6t_Μˁk`2y5uÏxl]+UDTNԖd 5vKv<<+~YLᣫw]XkK0(?]U *iF b`(zt3N[|<U ya;ܾ]w#,X-Q#""_b1j1uˆ׳u`N܎kb66_m)qF0BJu. X. {ͫ3|*>tr3[oNhw;:x#r H3ike,gЁp}Hڟ8l<5s-0<p냼91\,<څ& �ס2U-ǵ+t09c57Ж72jz̜�B>v>qV.ozkLq~ çm|M/űwvxJ?>t7I]o孟X^} OE cw< :``e*f0! fÒ|?Z|}]6+;DG\>ߘz`ⴙJ?/-lDޞ]8[(-8 1,#fm]oL=?}\J;kc,<=l0с_}fUweh}x^}O-!sLXF= m:}/uwPZF.}yXW)#&oCR8Rs &ޝGzgx~Ido눽rWiMky@�� �IDATa109-'0bi:vĸ:r-qU$cZ9=tr MpT Q?kLK>m xBk]e=fj\\CF2܇TEy&[Vѻ}}|Q7B6͙ c 8k30>*,Eb1svA5n?k . ϐ:@U+ԬW_` J(_Wl~BQҰ�,`Z^Çl)Lnӷ Zpߦ_JM *K2\NeՒH4WXHє@?ʰ/?2m6lV-1kYFMYr {GΎRvȦ]{rs+fn]E'*Yoi%?eX5fm,w*N利E-ZKVmB*Nx,Y|vn b N%ש 5Wy85"BlB]l6;_wza sVrP wLӓ04BDD8.`ؒCt>Çip.'7oFF^F%jULp!&™�| YXpQgZlz+M3 'kP0xu~E 9XCŠdžZXZY [loo+oҲ Yu$鯏)N`WπuE6^q>;p&<L,e-&Ol.t*5Iujҭu}rB>ˣf7VfqL("Ƞ=b \!0l!gn^ޑ_<#+ǰj#5ɢoSH8ڹmLZG?pjVr]ɹ3B`q?eBCHdŖKXH0C;y85W0,/[MXsI.fs}�,ZBDD Npjt wKmr Lg*Ā7 ޞy:9 }brmӕEߤ % rr6.3r3; _kP4 ,�BN ?⿏g�a>\ͷ �Ki.x6V9xUj@2~B`{W֥Ҕ1<?~"D,6$ZفMߊ8LA`9n xLnG'(ᛝ2'>f62l`yfV`3 k@R }<&"pe !L I"/ jZyXB~zYjޙ0 ?d[<FN,@g@ Yq`JN{ +,qMxvF]A 妟wCxϢtg\@ !V/)Ms;P)* ,ڙGu߽"vv1;kBEE. R*+1Y~#BWìy+p>\:l@q|mqE| Ys+؇D6fVeyl:lr\G6{L(ŅAZOSqfla/.$yOBB}qY0]Jq<ԩgd⩸n&WVcڕ8\Ck]<G7X^3}g1]Ӽ`di{�J{+<\Դ)Z+mX\Unn2`i`'&33?&/IvBPj^iDŽ|99\.gGӺUX2_CؑdŪ5@i9_8Q}\>gs /0 iLwt�#8X0iW>28 -%Ê)d`(<﹥s!7`߬ &qT<]*{H KNn~~~ج N}twUa/)Sc )SJ0 r}GQ5׶N|Ksc9v93)a$5C|mmJ=^c`sX1.n%xLw<t{ Gq:|aY 7-) ;@sɞ^yd,2gKECM*a+2Qn2kFV �D12?ע =*8~УgM}(jF` ds Ϗג6>,XR,�5*W$ k*�41?wG7ʀgYy8,\Wd}$}`9ʫjVXOisy_{? !�o^j�E.d6US(_ p95*Ou_t]>x:5x ڮo㝏iS. 3V%ٳ ܯO+ХNEd4p/.:ȓsVfx ,QonhÍ2pg~=2Bcb8|)y9pǦCS|2CmFZTN퓴cuSRոՍXY997D$LrKḻ7B(`/pk%0ȣrr(*tbp{/MG_A j]q;CsN'Ag-}pB'`u _X_H2ց^9sqўITX,S"ge~c|~v8|gx?^oo?gSUy^Xby~qܘ~] g%\U,eιKlFDDDbrI"'s1w�䴠1_VuRl͕:czPB. R['"""""""r)H!"""""""^AA  RWPBDDDDDDD""""""" x)DDDDDDD+<D/pz&PB< L3""""""" x)DDDDDDD+(H!"""""""^AA  RWPBDDDDDDD""""""" xg'zf}bY=DDDDDD4Bs8dgaZ?À<gr?n#w7Y""""r zi7^} =+[w|u̶B"`@(bx;N<<*z6tPU DJ'$ݙ@ n3;c<4B4<OhW E>>?13ʄ]_}gٶ/DM=4[WNG 'GqN+ >νtpb3[V~-ݻ39[DDDDNj|k>(w .%7 xhD yom%1=` &0ĻLWM. a빦3QhI!i|lbτd_O(Nk҄8g+rlv| ϏUH!"""R I4x8?P2�<Z&UW&ջZsq5 }8V%{>kP 6|hWp)3 <,_VUK>\˿+}F *زq U>j[�G%~ی +4 3/N$ y6ܼ)7{>yz!N=۾]<<vi=#v..advzϝ` xo]f*|W@g؜ܞ-V$=}3a[*V%l\6ݮP>uF^Cbcr\:v/{+":ɕ __Y̊9qӓ8p+z}ocү/fl2mM,]:wWM~o{ _zJɃ0sÝ6I+w5mxvV,Iw/6]~\ඖ\`G2􅹴7x[5:NE4!Ul~" pmA,�fGq-#_ހ7sC~ 0ln08Ltps/X_ {u3b^ '/uAC<=xDm:όG7"rF �O}rH.U3ȶmdD[aԒ�G]BJ.]F`ƾ;uw0.N^Mlj:hWP 6Hf4#0(JԷgX<nw+#&FR>r+> YCٍO7'/>$SX6o2vd]D@Qr̛'e~c9ŕz{Ap7�[-1:F9^3\ƒ sgX<]e3Cf|9lC)m[m1+>Pӭ)o"""r Y:Nc=mסcC:`>D4τnU72>R@*EpRǿ%+5;HiͧӠG ]g8SH!r3�>E^vw6ϒ[YS"0 8eVx<qNUTӂ, @ǿ~Lȑ??$O6=aP$VƷſe==E5,˷}=u5hs,]*mKMZpUmDިT퀬, ywy}ǛVr-'?aS-U]n 3�ЬmK"\1tGL\}ODt-:'kþLv6߭XÝW!2%-ԉ%?債?dJWڶ.)pN]<)8H9N#GgienT4rѮM "teÃ(>N(pz}Rǿ-K,Sֺֆ+Er`Lgѕ m}t6rW�mnnRt9g g2?e{7 &7.E6g,NJp$_\\w"810C-ژ`Jðn=H_DF) Wi˥ D%113 =*`nD\O4Gq>m36'�lkh%Qڶ-+u."""r `B$Z/r&$$&^Uq ԍGy.~"^IJ7/6Pk\TQxaz P )D4<XC!,3j<L&Z:c&_b2 ,HvqC; fZ6`ƧA~!ZrZA hq+m m;->&d/yoL,9ʮ�$eaF DEE3&Ĵ]‰~#J}l8i'"""r%PKA>|n� R"Z]ſ̽ gv$fcK㍓76xg͕3RU *Lߞ��w߄L"HEh֠5`N<Wr7/hH߾] SV-eM^Wg} {lDiZS=*\ErmgeA,`ޘ 9M<Q1?w v́¢c-WӴiֶ9.ځ/s6o>?٦xeQ˄1[MmLhȉ<WDDDDNjoքݎNkkR@r/K0觢/OO]S߃UN1kI!rED/t~Z|>""N; w+,=j].`Pŀ'e +$>6J~WO3h0q 1BA$:]ӧZ=:FKˌY<u",vhs�纡9-s(�N\Żߜop�:$M]i`RfK1q�Ov³Wp p]3]F +'qsx>\//^gi9</yu\W:$kd廎BԹ;E߃rDی)r9{]ţ0ntOe\Ƨ~@rIBjMny"o W2 Je q.Uק9-{�:FPwukԄv-o<{]j˫؈H$ ٶeYxRWVVc9p�Atԑ/PYfmaLlR׿fJ_m5Su �t3>}(9"""""gب U{iFcwͤ9͜N11x}~gvpWX@6rdhѣm#ij 0YiZbu!m㡋UG^hNt0}N=:IDDDDD3)N3)|,%d}1nLW.8*͏A:LZ""""".3)RYA!H%(}""""""""B  )DDDDDDD$,(BDDDDDDD‚B  )DDDDDDD$,(BDDDDDDD‚3ADN&?BExM""""""R:CDDDDDDD‚B  )DDDDDDD$,(BDDDDDDD‚B  )DDDDDDD$,(BDDDDDDD‚B  9'*p2 @hfRfN/i@RL�Nj1nuZMϵ++;YͲytBDDDDHg8/{ S -ہ *Gecv]67i%7@v|z篼s5�yD:ܡeHNN Y3Wcb.+I8]}zi=هFjoS0D{S<w{i%w~G'7jda~o "iҦJ<75V㎀+tRۙB!i|l"<Tŀ7JLuN(RW)\};cP8Occؗ1;$Ҥǐ+EߓP5k!Jdt{RTĉ )R%XL][(vage4piB=ll`bJmZGra+QW}IrC*-;]N:<zl64J瓍6M H+.#_墫n#&ts4ƀp2`/Ƣ޵nUtՍWeǦ42wk7q }Mc-Iiԝɨ׿:6�-/}ka@b ORGK_vɬ7*Y PqbWwFrҝ)/܁ |mdqUnUb�L/ٻc lvjLֽh{tcᤉώ mNJ,a%}hWsgE I/dq\=~&ΙGhmposBB?%X[`3~r6fwCΗߜNa$dL q0xvEq��IDAT[;/fb/M ㉨/h}]@QW. fcHFtvLa ?\Xbt 2-ޜ}M<u.IPQ91 X㴃]︜o 皛+a0 e2a2;˙4uo\X(elQFχÍWN>dž3~dtnc'e27cUsEvdZ<wacSW1Cr^y}iʶܱ;G016kfHdڦ]FTb8EYja¥y|}>>S d :zm>2g; a0o|?ocѡo ץ{hkS︔G~ {kulX-a.8-=vgg5/ۄuk/vgˆᬪԝo*?KVʻ8sLq` L|pMv lo7SOrڬA vXYn +|2t�7xcGf6`߂yu,IRv]ɼobޣÏ[;״Je\"4aO[Lsq0�fx*mp%ĵOG쏵&/M^w1ۉ|/};o]r""">2h倉"%x~\;LE߆`uou2-J9^QH!r^݈v]4c!;>Lv[iܾ*IP/I-;&$nAEs̙D-X+s�׷'\7+*\ e}2^ucԐ:7:T.N7m@X9%k2xvPW7p֨)X@x <:믺Gd ZD$6bOFN_C4i3εcemRDUc zCnnq$ToKuz ٝ;D-t+\ù]tqy~[XfH'Q싮Uv�87!boߺDy6UHmp▋)Z7펥y <h'}KhRFb7oKފFe�&x  kp̀L.Qj�]?"<h9'Z^x 6^kh.=ug<8De0ե:i␲rAÃylQֺֆ+!r?/";}3a.mx 򈏏,SF'`c}J5 ۲)񘆁؎.S[|={yɷ r[m8܌_`> r?yh ,5mUay>,J@r|I.^h4Qtc&`a`c^Bu߹L^d1?3hU5rӒS l) O\*f6no�tFdlDhC'8em^Zަs6H6U^fTnb_lH3Ki9| G\w.u"R96'A/c؟YOјxc.ǫ=S+ )D g<jmxo$ ?UX?g.gVZvLlxrFtsg|@R`炑@ؗC( YeZ~&O_ҊB3ISyRպU4$ +/]F!OplΜNjp%w(nobBl&f2}]ڐЁ "rwmOvǓyx(-\\ۮZhS9N3zU"ccĽgRkr1\ [xgͳ3ZN(`f=36mR Hmܐ)$ n&VعNliY&,9X7�ÀA/vdy5eO_ hʆoaY^Z5(WHpq /*YWm?ivcl;k7eY Ĕx[ZYVk;Z2'йI5fl"8kSw0ݩZF"::eP9LQ\#|�;xuAޜ+wcDDD$<gfIz`OEQ3oMẎ[űͤ9<n x<8焁MG7uC viX:,K6wHbLVof2HrܖWx釽 ȘEootL |3jֺUJ.8ͩ4I ޜfo#ֈYjsrbq}j!`/^2(xS#d]O ;vӏyv[В]ыG>GqԎyz8w*Ql}[2~nc^xBkW}!vq"s21xfx� x8\Hת$6悺<Ӎ5Mw੟8V .5ꗨ M\Ș>'cjFXަ.fE%5)vLq[^wVqem<-;_߀[H-+ ;>Ub&*ϞM|AJ[?Fu?x˫؈H$ ٶeYx󩚒]vT r;: A"<N_ADl2W>ZBEDDD(UTvCDTib~ͳL , qRhO.pWX@k&?#G>*#CDDDDh&i&laZ:]#@fRT] h%""""gү'"""""""r)BDDDDDDD‚B  )DDDDDDD$,(BDDDDDDD‚B  )DDDDDDD$,8CDx}&)"njM""""""R:CDDDDDDD‚B  )DDDDDDD$,(BDDDDDDD‚B  )DDDDDDD$,(BDDDDDDD‚B  )DDDDDDD$,(BDDDDDDD‚B  )DDDDDDD$,(BDDDDDDD‚B  )DDDDDDD$,(9y[=ء""""""3ADNނ|Ly}6-NͭWK7�"""""";ͤ``ҸOjo4G3nZZ&2YN3)D*#Ԣa}҂s.�4~Uym:?Ç+2÷03~UsMQ Xm1^u}ve{j]p6nl2Il^Adt'U?>iɿoQU?ثXVx_ W(HϧoEU4A=Hhq`pSD3)D*X:MO mX>&+4lZT>ˏ_FO3m ˌ!ƽ"}*m?^[uQ>q26=?fګ'yUXQw5G^; x}— #_~=A0 L{c._P'c|<a=""""""B Sot]|ƨZ6.-mk܇.>ܻԍ_Ӻ_/$.Mt`=+ixUq\*/cǷKFNH횆Z#ܑ)AG�Ll}}Yٵ:>8fSE{"EHy7xGxZV3"]9ƓG+#*(Ӿ65ސNˤ�I�ʕ} H\ wOX +Cš""""""B %ʕ4\LX>>IM`2ظh_RyEel +6lϡal& )dd:#??1cъň+ٗ釚uDžx헞ޱI,9~$"',4xmwX<lM+IJñ@L^bv28k|lמ53>fo^|m\Nfko L]MʚLA@x-˼. myzT. ?m؁9U4B\%Ԉ6~qK"Z\Zzya<;5b>Ѧ;;"QZ{y8^Nk 71oO$8wŬv\ڕq¸TWb v='ké`M1b4BDDDDDN#'/I"@mcY|v){"0M0B>\DDDDDDD4RH!"""""""aA!"""""""RHXPH!"""""""aA!"""""""RHXPH!"""""""aA!"""""""RHXPH!"""""""aA!"""""""RHXPH!"""""""aA!"""""""RHXPH!"""""""aA! �4M@H*@�,F!5 t8|]""""""r|>L(a6)_PL)[aadvH0͢c1ͤ9`Ha:~""""""PvN>,sHa١"TmcYmcؖETd$Z.""""""|ŧxN'Y )DT",,`""""""rLt8S<P�c9_¶1�41L[y0 臢eBJ8{8q""""""rb 'RH!g?""""""'DBP )DST""""""rbDve:����IENDB`���������������������������������������������������������������������������flask-peewee-4.0.1/docs/fp-message-admin.png��������������������������������������������������������0000664�0000000�0000000�00000152207�15223753015�0020651�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��n�����Jkt��� pHYs����+��� tEXtlogicalX�610��� tEXtlogicalY�249P���tEXtscreen�HDMI-A-1/ �� �IDATx^wxUB {M EDۃ׆JU:!{'�!;.Ȣr]wLfw6:wΙ3FBbx-gADDDDDDSpr n""""""^NMDDDDD)x97/Y ңDDDDDD 0<Kהp8p:DDDDDD䯳vv;>>׎eWaYiiiXN'yNEDDDDD$%'t:HG˲HINϏy6up>!Դ4r\$sMMDDDDDʟ/~~Htb9 m""""""a98eͲ,K#O` ә[߳IDDDDDDnL#w 4M)"""""74M2Cp)݉#Lr """"""/lvوx7/&"""""DDDDDDSpr n""""""^NMDDDDD)x97/&"""""DDDDDDSpr n""""""^NMDDDDD)x97/&%9\(UL͚,ٔ`_д<޳\G>i T&1yex6]<6;y/wg3}`Klqq;Ķw 2a!:;C]<=_L[aMDDDD:mɸΝD&\]s#B$9V怸+M rH䪉ay̳H\77f'eR,;g#'=`Y&(�u>:Y=Gz6,=γI$ҁYyij 5 gϦ>ЯOeo\O7k SÀݳM/+ٳI$֧Bp4rkp*?џk}&i|ȏEa۪2{<�xv냛;?U=JnY$o4IL_3&ҳ�fDGg?^t]Gz6 S%3p8pi&0{iM"vX8&79IY!rĭxa'B`_@*Opi1&łmX3[8cB._;IN8M'eyӭ5Z[n.0}"`uĝ:r�;eиzE؂n{nS ,_<{p>Fz2X-U(Z繹sN|?K#gN<39v*Ujӣ=w=7~_̊D؎# EѸjiwoM^}yq]?3�Jt<K.X]jdm_-x~ Ӥt_i"VFN'|Q&,Mk0P&Y;Z}:y243ˉ?u�X�5Ƀ!Oٶv'2y!"Ng)ϗFUK`V4|B]ҀZ/,$isd~|�BrB?=ߖX̤شj1Q_t ֭ģux{*"""o}&k@Դ9x/ثwdAId^LڀmBuiuN;3oXIGi=Y5a;/X[L:%%99w+`Bs^7o$j<:̩GXG0 H|tnYu1ţrL3On ɐV_ԨQ |,"5d?deڽ<<e2'ڿ W\gX +\5Q͇=wK d<b“4yn#4sω|<0U* <~`¬2Xo+ 8}g~ͮio‹cgrl)^ƯCXWdY~g6~D̵{:3|]Uq/ڸm,6?obM|,Z<v """/S%K[TԚr':ec`mq ۠^vCp( zNg_<9,e9< I~l yp(q[~,y2Yя]<R%:8yԓYWbyӤ֖<1zG"/ mR,xq^xX{'p^(3|<˾xxu<Yq,_Lg�ځеNyeu"N$V;pSǬJSts.ƹϿ&\vM}-yړd1)3GxIgsqZ0z9"Y?a?<7q:mtl""""F^R,n\|F8ad}q6΋++u.bê++`c=-.2>gϰ.rնۯ~vy1lO;j?0cfjFV ShsN8wyU- rdu `*9,{#nXiyXus~|lSmʜ5a%G7Wճ2vϫD ⢏l̲+ygegq9O\5Xf3 ׳IDDD_+[RmeލDN�No_@աIf]rh/;n=ⳃQ@ `/(^BIZ3Lx5{Dg\O'}mKMvOp�~}'n}Gٽn%֮aҼYY[H]?I`w(oά3֘)UE{cƌ v<5U˔fpo {r�}<IX`\>92 Nbnrw䃽L[Nj/?U>q }Vbw Tlv~;AsouYd�Uܧ-Æ ˽Sڥ,{"wylgأ}yɧQȉ"ϲȿW㖜jQ֖J.ٰ ׅ|Dɋ;[ Yx+}Vvbc/X)zNX YS� 3vAU bgǫ~-0m?o? c6o=fk?B�Z>6A|ϟjCϒ?d^;uPÌ%b۲>Gפ|!мx yALV:mɖt;7߃|55ҿ``PK;R7nO8va V$ÁZ`'RKd5 yڭv<Aq¦ynܮе㊴y2#,hxawt3ris.AE? hW\lOVgI63|%8>?I[>'7Sˀ!vn9;Q$g1V7*zg  f!.I*靖ȿWYXJ�@ EҸP2 L:?S뺗[ IE8 +g6mIPdh O7c@DwةXJ`f-8]?k+f$Y`_@@4kcw@l0fTpq V%4ñ/+9,:MN[1d]Õ)E3؀VcقGH~yNwOhJۑA681q",ɂy;lE\,8o^_W0;ڜއOzn�oL}�M[mU|[h5 Y|-x`ѽ zNu,ˊbg:-=KLȿW T^nX89NcNVzt. >IJ.bSVG vEN3IkO庤e M8w/j[,U(ND } #Z#\ɮ(P$wd6؍[b Z �[� ٯ!x*%:,(� 2~zRR2`h0hgPλ `_}<a-<8sc[SY;>?Сc]~fƽ0}S*}O.V/pZM{t�B`c!rb�Ay.}^/Y"`e=򔫐p\Fޤ$ ѵ@dmJH�$&o?SDDD;iAZ2Iv,]#gOu>~f(,.׶PKNrr:?uY۔w q8P :K&/̚ϛ`]JHJMjӠnCիC'_֎ tт|3ijѠN=ׯKͳ,`Mt#"ٲi%Q& XWY@IJ2&},wYa+pF?3J9-k`t68c&j, sM :eonnkq&s>vCӲ'=[mDDDD-3Y`$cCva,1V2 cѢrckգ>3d|7 8{wYNZܒ, 91cDOQ; ^x7`e^prtf~[(lWNe�ƞqt d `$N[ Ӗb7v<ҒC`+Of/'R neVܭ[7<386߭VeMt|-g:Jp >2[EDDD-+5bԤ/.M\Kᛘ{1 \p[j`/@r-xI+fƈ/]ex7'ƽ ip䂓go9y<5\}`[y?Xivӂ'|OhEGFO>>IǓ( 4|\n܈[)@xF0O6I?S3;xj\|g7�c`Yo7%gL 1UV]V36ye|n u/AN$- 9af|jxk&/"|d⏬sL10㉱?_!-Y{?"vf/Wz]ѩX/OxO`%΂ߛO~epWz7T' Mı鉐 ˧9.7<$Yرtc׹ծϣAA/}giWc'Ϗx' nXS gDJd,uKKfX0}d\cv@~.`m6z_Q%tG:X7ldͬZ{\2b7&}ꇔo,0ir?.='Xq#6nbU8/ 'Y>*m+I>RF~Fjy@Z׿=y  w" `֍>W3c̳K<1?lF؀!\X9 gooޕ#DDDD[ݜakHJZƿm>y&8o@׮uj^.g>@r0geMW@tg;~5 &ӰjL$ "m3k@OyЮFqF<ؓ韽t:{.ɪ-ҳph`p`Ж6t˲+~[-)ނEsVprS&ZdAٝIC?Doe][W7'6[W-%#ݹߠXk\@!`V_O�3{�oBWNZLn\_ m 0SZ I, ygfѲ[/~ZuƂQI�e >%HGI\Y<W,b`]yY@%V_lq`d_1S+O!HX5?(kŠ9@"�u`Vus [DjL 1 7rȭ{M,` ktM ݃#_&0r97R]LS7K^M \Z=`!b|8(%9\=/9zk?G:֙xL0̪b`Vb-ҏltF3ŭSM_aj) vqk>#{xKޚ~Ǧ]\0}i5n68}Dqկ];vP+dӗc]%lb[_xuQάN;agqPZURDDDrsBXnLBAtUs _ef<1a7y +DgR310j?>7LBb2T 4/f\pkX9=\?�T {YzgJX;1ϙ[<R2kw[ 'R,ޙ >!g@UaJ0B|h4tǟX9O&[Z.Lp˒u4�uL#Bے,:=#ۮxVĦ2o>o^Lsz'LXjbïN[ZN7!<"�,N09t!=:Qfή,[)G ڊD_—n܁x(bn�tڀql\ Bm9[/5og OR8~0&Lcm%4OSz ﯙq>c$$8S/fcо@0@ۧ#?`f<s~q_N' )XCQ0El]Ϗ enqG2,Ne�dru/J* y):@bݰp[<gemKc净ڕ@+q~т᫹3F(ú?tŏv¼|n�=c/f�Zcwg3argl@v^WXx/wY�Isp^3 >2N'wփ$:I8chd{0  xQ =sΜM%Q`?VV+`dy L8ݭl@ӶM<n+i] A;MƌxQl\IyC r-*nuJvt_ vk FA ;L{#GO\k.`DoSn>R *�o4+_}_!&=ߌ~o'Wc 2iܛh &X! \uOvW s0va8m�oW >_ Ox6z]x>WiA&mjWSȀm[}ui 9ugpyم >\ZCƧHDDDD$-3U2uR1vm7 6۫0/LK#ؿ{ c'Q(mZѳ#+!lpX(fĝ8#56 a lۄF{@@Q�yoUKqpVǝd b0ש[SI��� �IDAT0<wR,`ٜ<Q`(KP󽼵-=O3ʵS&[=k ӿߗ|4؆=,%CҡA%6R݁5pkL>9y{8D s�Wc: eo- z÷31�LӔ%,_0[KtX>:5P7!{DDDDn-FBb β,L$%)Ed'NWLy$F s*&<ylFl : ;(4s}"%n5?*T.ϟ)Rpl9_H' :ķ߹l%~J|HQ}əlПRw:t#xev3gx#r6a؊\{EDDDD/xu'fOʉL|pa6:<;u%P M:6k= ;hbχb+6UH6u |0={p%uZ+ø_\d�vܥXhQ6{>i Rlq4I(X5ZERDDDDʮ8�7/q঩""""""^NMDDDDD)x97/&"""""DDDDDDSpr n""""""^NMDDDDD)x97/&"""""nZpKNGQsPZosh\ ճvĄp䧀$#8<ݳoa%<|U{ <2ͳ2-j>%>f&9b c?yf7-ez^ώ^oO%Ϯrɪ=i4 ܂tϦYN&0gYCnu.7=Aa+QԢٽOID,fzϮ,˂K6MӦVԳ9GEm?_!lDc&lߴ񂏂\gf2j̺ٵM9c|�KVL8NAڧ#yK� ^`BYNqdnX=0�MÉkhZڑ|G #|;? [ e�vX|8s ۶DyS{߉Pt>7R7M+{p s Mrt=_ه)y,U4Pdј܆P֭NuT2�DĘT;uJWl<5H}q'kfGa<էI>Z9?BbAzGkB*ǁ725|:Nv~Vr o|`ˎ$r2bӰ -f6yeYxI'[5܁-EDDDDrw7*opqŜUgIX=͸W_eg^7Lj[蜲ཱྀym[�L@UfwΌ:u/ w1bs_)?@O@9'CK2g`g}:g,,y/=_䥵&q~'3mrZ΋,SZ&<} {=g�gK& X5%wcj|ENG ]HMZ({3-W8 MLss]7`8/o_11,e#-y{+LNƁu2V_~ޏ󱒶q9?-} $Mޅ3v9dv/:g̯9茩Nq8W|τs/2>'VEDDDD./)ijA?)UjGՂآ.;ºMIgҺl>JHJE.K7֢0IbiՊ8 @aFjH |qz9{|w3IKx6,YnBoo~3v=l0~`Kz"![1M8|8VӢ/VZswr<P$;ş`Uiج,=( hblܸHgblCÊ9\}ǚ۵GDb[[fhL,'$(Ԥl)VB�&ԨVꡡ}[=u{�(hQ=,MʰϿQ$Ṛ4kyuc+mNسdoVZҦX(wDľX{].""""O7I4 b�v֮ HLj;Ӱ,6پ'͡h]&&`sS/\t|1g^/)y4{NS+4e]_G %s9ˑLZi ->tڤo"]>?7[T9'Zr'݂|NTgi4뵏9Qi=H_n9J甓 iht`�iLe`[u}1j֠[6i[ .Ձ>LM͍tQ-a}~DLӇpZt,&1&8Q^�D'hA?t`^8="""""h^:㔪CƟ>66|1\fvǝ{f@My~sv0}PL'[|<  !??nr^0fZ& X ]Gcl* Yٟm5ݳ=6^:uiZt>s7+6i@b]|u8XHS/:H=VI[x\>$_De_ U2)Kf3)&0,ox;WTj"nmy%m%z][,^ R-؞ ?B^i\ � 3=c_�OSʈV0E}؞3})2-RLj%qˆCHJOsT>PSZxM1&Į^O浀@\iyj7{`2Z4 dPZR:4ҡ `p>Z|l?>GWЧfIB2yY| ևӥ\^Fuo淣I= ХyUo@`92ޯ6+X2%-t`~1-DP/nΦñ3l:ˋ[Y7y ;a iL^BBCe9Y]G<yp _:ϯӦ}j+l'BHrk37Zf:Inb6NVn}|;۔Hc(լ?z7'?׭1uRRL*/ ϫ[sҤWkٔk~@e8~{ q|+m f}u3?!є>mqgٷ{'%c`#f9>m(jƞ?Ra: Yx(ty΍+3zVΖdf3�hZ4gD1m3 /> S%{w>%nФx~ӀJ;v[ͥ~~'k̪U0/Q%Б駿PȖēKвC%޶+dz xhflSxr!y)|@cޟƸ/Rvuл`΂ym}Ƀ5֪ JQ{Zx} بY˸j5Q h~U<JH=n |y6Sʀ16in>!AilEJ?n~S\�Vu ?ΞNZJ kB~:Ru<м ToC\Ia2J�o|'#&R(t_]!1HSIa1t.U~v�[qϗ """"c$$&fYi$%QH&J`th}t�{oʒ{Mj?YDDDDTL y`0nڈ[C=Kj;G,УuEr ѣ`_Fg<л- |Alǿbkw"""""qp /5.c|xgK5'&EDDDD4&"""""%n""""""ru n""""""^NMDDDDD)x97/&"""""DDDDDDSpr n""""""^NMDDDDD)x97/&"""""DDDDDDSpr n""""""^dzp3?ObR*N˳QvR g 75;=} ((�_ߛz8 SR:KuDDDDDn:U2Y|v!_pĞ>,"""""7M ngc{6- 0ly&nZpKLJUhY7ө鑷8__NgYDDDDDܴz?Σȍwӂ䎂Spr n""""""^NMDDDDD)R1s1ٳ2;=K.z6N'jY(/fn3@ r~s�ON:gp?m:O+RE 2o?bdn{b,;%#y&x|;f7&80{6_5CCݾ JºDDnGPcPϜqN' G`z€/I�\ޭ=~}Ƨfy11:11M7ŏw= g/^a…M9j8b6y]˛<0}:EaøwXm?3石n٭K89w&f,y>w[GLf }k4E[ ("YEa jbȓ#Wcy&̈́t`,LS/0<pGLHE|D_J˶G]Gƚ}\5ӲEݲeߦ u.}JCY:n͛,7z6]wQqq0 2nIn.| _EDxn)؈S�\�M_:a#^d`+ic.尡`yE=؁b5V]|&Ч#+3>Vno:'0oq?˶غ ]_6l�)*[]os+">v;Kt nkTh(Ĵ2x(&T+͚Q&,̵צ cbwguI�wJrT6% u}8M!7'>[Q8Z.3lf੹؊?ҋ9z5}ش*iQͦc NOrVX^cG~j;J1jm4z=0 2yOL&Ԗm/_{QY8Ѳ|>>ٗrc]C`og)x"b7K)L<J2y`~&~g.Vo>ѕC>�פB[�|#X5q>y) uo&-I9E;!f&t(dž -X lzˑ$2䘝t*՞3<?gwٻY*0^iV6'ϚN]4*ۚPVwO;ʓr#{9(ƾ#sV9`ب,Hp?X8nj9%0ŧäN[Ǘ+xj"Δ&.j RVOF8BY8GѺX/jIH813<;?cw&D/<G3`yx""(ʕcCٷ{7竈vGGST)=J . @#ykWR>6 ȘJ٩NF$#v"48zS:;lQ:4!ݻӡV-WU>2D-}\Bj}/$'޴i,ޱaоV-^ݛi]u\mێI8Gҥ){c#߯N`ƍ +^4M>1ik-[f:Եk2<tլIbjg�>5#3n9s<ҡjբ,}-Bss8w}�;|9+yyu& 6mXcʔtS2#�dMJ13�K.sn2Lͺ_^~6hF%< x>=a]r +<T'E²1 Ssѽq!}3wX/S۟8wN}mS^_)j1<d\4?7;94h\-Źn�1#˚صԭ_ a<vVdT�TnX>_涝7{A݄m^0Da\<Q$ߞ{r`oϵs2񠃮iԽ57%u|�vǏǨG<&SKh\$ ]ؒ~};Lj&o*n?[ڃ3r<˘9[yʶ 0}MZ8d7$BB PB5tETX�׮W,׊x "R"]zz'BBJzٝ%",<<s$9s!}GRg|ֽ_{^ ¤EOr0$&z'j`ʈأ1c8=?\mEDnTbby9l9t5jШR%~քnْx_?Wݴ5khO?MX^8܂Wxꫯys -19Wۘ1pXWo`qj;ٛħ<˜q0N|r8v,!!|3p i-[\=g?o~=գ szZd SW޽:~|WD^{n'Zd$}Pܠnx_?, 6uOlD6գxC2pz={xz-uqC<z%Ͽ-sZE3?- B;�/gKsmC;u?NK@1%߲m>L^&#G/z,lMwPv!9oƽr7 grt}!%o}m+0#Y_dX:gmZHp”S<̔0vr U>a8CwЁqHzN݆d'?0U3(C(Yrda}\,\m Paƍ5NxVDhh}`d rk;}*r2>Ǐ% v3z:[I2<ۺ #۰FxY#{۩PkI.yx:F@& ~<7?$̀'{6b5}eͤ7 `JGfLlnpyJuSJ2^]QY|E@H+ :޶ؼk`ߊȍ~L y:zuQ: Je,60⼬V|m6�|{{nk֌Z 6"G;u"37?p8֥|2<Ծ=~;�`<ѵ+mj֤bXy'qۚ.vr2+w;^ Ԋ>}H>yrnLN~>#ZѴ]ڶ-j{w]D.<~km tWur4sO\o[5Zd$y9+/QJ<ѥ U##MŞju-gmu0۱^^s|zƠ]iR uqC 6o7E =0+Ћ`"JDLgo/]YIIUm�� �IDATUki6:m[bP)U'V:X]ZlDNh{w-O<ܛL�Ӊ cB̂}t녭r/M`@L�n&iҸ}ݻWlXFFYJқN`AB6y{Sx.{~ˇh5�b X6lOl#8,8J&E{.Z!~6(zSxySppirQ}~IjY_J,ұ=Yy:-{_U-k߀j]fWY�^ fuyv˵suhKx$S Qc*p&|5 ""͠y �`o=""R%JU4[pZͫΈeԜ9dQmɋ u k\ W疷ޢm͚^M`";/Tޙ>wɵpZgG2]0X,W|yK`J ˖}\/\؟TS/%&r 9N-U+Ub4\BS|y2VаbEP:"#y]<^+sti۫ fNC2<9�)AAKu,@pҼ@܊L+.ïf,ۿDzI,[&,]̷3;S?_x/OQ(h7Ӈ P7養A?,=]u>xt `<cv(5Dʇذ*Oh?b{;~hإ~O'+qޝGNV: SЄ B9 ,;%/N>hJL8N(cfXR5u{~f <Q% ƽ 8dr*<P[X{Psq ;7Lw.Npb>hVQ%'քv9CE|qjLӤvtRWʘؖȲl<FΞwO>!yO]؇|9epᶿ݋n r:ro gԋ3H|mWYɎ#Gxwo �/rwÅz8˳(KQONhǂ+hF=)(Y4 Ti bl:ͧK׮x7Ddңԛa}*΢k8͆~Mټ>`x'؜hmgH?7ii+zU+yaxWbB -NlxWE tmM]I͈z=?ڄpZJr2$<0>3`nB8*]00'2r!WStNQaO3g|1Y:yfRl{(zv Vh*k{0N]ڛCB ,O�,@RL9ԫQo|d4rŻ\5zo98G#N㹫̣ Do%-0#(tp̄ Fk>/]DFP'){ àI*L[j]nrl&._Nrxsg~|Yrsy3~v;<~B�tAѰ t،gԩ8MqU @J _\w8M_6l.]\KS} !'/۷mQf,~bBC9/Kyxyo% g#gD{J4$f.Ѩ1|l':4#מggRvu|B팟~kCbK`_Bp+j]K |/'~|'R�K3 Znޅϵ/TCg[ѶZ۲A�jUл w%[Tniь-:Qږw#ZHu e&Q,1aQiQaS~r�g+"/3f}|\%>R=Ǹ d(+.{RM5˱z9 18y$%9!'g 7ulփϦe?-=-7HTߘV 4Ņ)2i4wӸE+ LJuO>^DJ_{Zd$Xv'%p>g [{7Gݫ/i5m?]toJFNkˇ;tŋqj=x8 ]ڼ<iy/LH҉X quW0x 2rr؝+Wz&._ք�r t\33|XZgi;>գhY:3׭Vr"";/s[lrZdmZ|~ݺuPߟ1|n߸Ց_~{`7gԶSK1+нF ߰>|&2k)u"}yD?8rV/~Q/ 62m^ %Z؆90нrϖ#97&|tC#!mn4ehG!zl{EVlYH5P }3C:hjUW,mC-x>}EV֕<Ү2/6K8耄y x7&0k[]Vat]̾ tVs'Z[!.9o\r a`�ΞeR-V5ZV(Ym2րO=m[PU):i­�gg~TOCg`5yS�mC?R˓X1 ^AwiP^55� m6#s1m"y[#o`t.m@ֵywJ?sxX U""]qf3>0xsg3>Gy̒F5x3o/OD`˵;[ '?1sɓX,osA~~gdxo_ޘ2>0X.,%|q}C2i߯XAՈƲ\|jEGiK%y-֭/؛f[GB8[0q"kݚ<4z4~v;77lHbk++wɻ?k',6rM7 3rzar$7;J9DH?62ڽmB+qW~~,ʅz$ {lȪk{ze}5PkjvOM;EL7)ˍ+Ʉ,e\rj<^DDD#KNrpb]y]%9}/iքwToj:h>.'Aщ{o$)o0OpoF`||5աvhDt!,ܔE<~|{c_:v컡/R~8'ɣy}GmܫEDDDDCi =iݫΑi%.rhȕs+w( p0VOϢ""""""NMDDDDD)x87&"""""DDDDDD<Spp n""""""˽ju΁$bRLpREr s/+LC%EDDDDD<Spp n""""""NMDDDDD)x87&"""""DDDDDD<Spp n""""""NMDDDDD)x87^p-$3+LJn~m96TӇvip+(tzώϽ5mh4lOX&W5*zo}zYݫEDDDDD|^|U]v*#fv(9<W5 nYm""""""={܋k 4<RDDDDD9EW5 n=RDDDDDϹfMDDDDDD7&"""""DDDDDD<r/t&LYr @/:Uq`wor�NO鹗qor$'*sކ%9 rb|`m?deKd-дJ}|?tffӁMvV-π>cו ZLԑ<5^F{ެC0O/m-E{t|H[=,ADDDDG>6c<<zxj2\W- VoO/[IxD9:Ԯ@{e& Δ5% W:D@phiV> ԭڞKXʜS.""""r=_1 [6϶Dޞ6]GrO2床3u5Tji0�{%'}#y5]=itWv}@ =SO;H2v9 ݴ!R$'̾L+ RqNhWNhZ<;-!8wLQϰ� dݲPz_wl�Lز*6u-,W 8Zfsi؎rM5ޭ/24a! [h]HPB`ʺdVMH}T qwϦm p.L=;'&Kr=Lf;RDiJy!.zEDDDOhDYxp0陙e~ysjߞl>x&OpZ�QK\ϞUJnA1u*23w.wlٳbkf`nDp8̜]۫] gc{옫zp]Etl7}ݶ AJQ!6q)wp2/ >ϼĴc1lSL3/V"y<{G^y5>/c\  ^<'ǺaD3?˨tl/=}ɕXh0O@!MPS|0LnB7e @�3L|&689W_x ĉW|Ci2j&*kC^dfRy~n ;dW_h;_X[=ħ_Ǒ0 ;מ`|-8H1aإT=1Cv�.z1]_DDDDwlؿ0xcGƒ8x+(n֌Aݺ1bT~,a|cwxhZ v:wn <2f s7m~L <�׬2m>zAbqo֌94~mv}z Q!p$DzC-ǝm\/tш=YzW HJ02# ම4XXRH{G~8F#?q7X5d^T7),N:7wlu'hK[0 E!o ;WӲ@Lpu/׼KIMNI(6lNr�0 uSA 9--/`p-(ftf]z%xU# 86ǹn.GDDDD8N5:pwV ֍僙3rl+&7#Gxo8BV^ gŽ2i�kݚ۷�HNJD5ʕc_r2�oOβ''|9zzs]7�+оJc_zg̼;6'h0 G`P4c%gdDI~#9'|0}#X(XË@ V6� E4 ۆQHQ:7@aA!k0ƻW٤Wq{Ec: }81,kN8VHy6]ɗkuej֮Muk!FV˯HiPm7�[)d�mЖ/(NaRIRrq:kcxylf!3ͣejM71~`5GP.$a={LdX*]md]wQ/&>>ؼyH-@JRٲ\ԹpƋ'g;~]^W-=$p"0T.erFآkWiqd5Ngj؜]ӵ�3(1 RSp%+<|Sl+rE/=g-餪 ƱaHN5D# 8Nb:MnE<ӷ7aL{cOB.xcp;lO3gTP>j g ¸m&F(gat<FPѽ""""%&, ؟d,ݱICpwV�:y2?gԌ V>8l͉,wN\l9m/,,Uv]9{o 9S(>cP7Ba>Vg$JXh(k}idL 0l`gv>Qe8q찫l]ef@aQw 4kVe{KjWN(mB˖hAh ,_` 5}%Դ*EDa,[ӱ_gꕷqͭx)'6,&ig[V'*`!?~3pJხ,�̢N/vwhȇR4M<b!;/'P idJxp0_+'�\:T:6mh]9e׻*5*iӴĎU8=Y<gUkoVpx磩?Uf AȁdyiMpfA�hi!J~㉛x(z| Xݛ_$D6%szU,СIl1m"p*/Á`r0kif7<)]�$IN}+-:_R1 e˜xg=:0 hj!Js~#{װzaV8Tg)13m扭�9Zo3f@a2N`4V M˗S&0w￟+mҶfMfo� p_۶n֌ҥ٤ s_z ??:En~>vDhkӆ;7u၂,^Lۚ5ukʅЧysr iMk>(S b_<`B׌˃wEJOo yyOY2VK(o)÷'zgsE Xh˩ <i$Jr[V 8`@&LE@8ow1sOz[Jyҥa*tb:2f-~4Fǰo]||2GrƽNtGoOބv4.~Mv:wheN' jńoN\IH,2.|甓_}(kP%KhtS%X%D7o?PDDDDoRR ڕŁ-mҊl<ڹ3/cx8]43oaXϞtoؐ{0jԯN/^q;f7dn уǏW_-1zΛq:+˕VLtMٰIr/R0:) ِKĿ6JӽHm~^tEKNR4ﮫ7zNqڗM?:\DDDDDF nr^% ֫!?O9ʱ)Ihtn)"""""?79/!>@jnDDDDDDnP n""""""NMDDDDD]v0kܼq:܋EDDDDD<^t\V߇ܼ|bԸJ8&U""""""fӇv/jYpD7��� �IDAT &7 kIW5}�Ȳ!$3+LF""""""׀F*UiO,WV2MInv6eŠٱd|X,ٹPI47&"""""DDDDDD<Spp n""""""NMDDDDD)x87&"""""DDDDDD<Spp n""""""˽jv/h~~EWzDDDDDD<Spp n""""""NMDDDDD)x87&"""""DDDDDD<r/$r-prxkeu!xlp+,tpt6BJWdrtA91yq<< F)6y/R w FIVpռ%޳[I1ccTj ?CZ0Se>Nq90qWHztZFx-M:#`/SfI_]ƞ=rfҹbvnO:�Jtgr{p: |�8~.e<zN=\7]=1`uU3` WjA`Sɛo͐riPnr'v-_|=u|GQx)8c�6Al/Vi.` ՝&c[SSm0U;fT"Cpb1 fed0: 0n&}FvNb@77UqF6<}.pOH[;1¢B H Lz%kvןjS."" n9yyWL}N^^~nW^'㻥$-䖚 c?<FX�@RBk~*ę2Р">,N߶OmC�7%Y&/|92ٛ^<jLض/' o 5yY}ղ$x0~'1q�ON-ENlQef.?? IZ,JT,K+'LY@؞U;GDK߶$4k5Š_L! `TRcM/�ڄzۄNfon&/ -́ϛ *`m{4v=x{6M8M'7'Hc` w7 V$\Eh_է:�P ED[pў3,iwvCD 3혖pB*foDNT ]J@pa lSkVͅ.dK✩`p8o7}z t\8TARQux3m=FGqӫY6c$VJg{ L`e2cꭆVg7-mmv8'ǻb7(AUQ}cNf(*7L=mv}Keлk;0]DD h>cTn7[hѭ3Yx-?];~k0yI|hf_m4svΞ\|vZ.GMxGGP;ꓲ;rO@*k$\y<U=;}OJƭxzUpb۞"�4k<#τ͇NBq(qNs( '*Bȭ=@_ L8JQH՚Uo@CT7O@(R0sb[K+/fL8?<IUgL&>| yv Y.$5# YP%w11p[! +7"ΞC[oVeVFw}$l6:0`=m""(]> ,Iĕn-֎00~{*l_@ MVkQ(M׮o^\&xP)il%207 >gPX|<WyP++w_ڶy@ϺԹ�2بſpS̺ Iߦ:1 :�g{1&ʖ\�!zV{ / �&f~.fMU}^12m6 6_ThW^ 2$NUonN -ZƳ#&֨N@ч֬hp/*c.*"+k0{xSf7\Ӏ+yٔcjijs*g%q@;d(o9k12\u֥@yݚgp[EQנax[ U ؃z#_F͖wrǿn煙[nﱾL9[ N`SuYl?G&2!s&J_O>""MuWL˱ E3&vb8OcÇ;<"lCV8Xh%~0mU'zwPkapovC*G%Ѵr�`�L7$}wxcR=:# p�Kw<Lrngé8RSw%ETn;$joxf<ܩ3q6@_%d6PH9y$ϏѮZfUY*k`\H>δ4* uB8B;9SɊM;<\[q+֬ [8DbTש ؉cxyZ:d}ih6n9D)apu�ccK  36qg6@3;Tky9v)1mjpi+pwҼm/9H(۶CIH&_ ]݈!V:3ظ}7- ޴ E!x Vv|ƅU۹s[<:})!x;~cIM{h`wZpâYG 4gg>*ZV&|l`Eb)t;&^M{Gl)sΥSvF<Y&c;�U :P""f&;';8M<> 0OolY> ՄR;M|3~~�wne+MI&J]K'2ޢq^X^Vm1|FҮ%u3AA a@>%jv㋹ٽ@FXG:w\mE x[}F\΃usv�Zԉ%?+j{u~ڽ*:GdpXKFo 0c4*Sma o}ven;ao)m;mCV|�l:y+ =Rjl8<)w3.d[ɶe\?wtj&"r\it:ΦlOp92/>|}ܫ]srɿ"�ǒb`7//+A呚vʽ&"""""74 nPʃEDDDDD<Ս9 DMDDDDD)x87&"""""DDDDDD<Spp n""""""NMDDDDD)x8/%5{G s/*Yp[݋DDDDDD<4TRDDDDD)x87&"""""DDDDDD<Spp n""""""NMDDDDD)x8/Oei^bm1(tW<En^!BJ]ŀܼB.:Kxȕ aGqt{ iNb!NMݩcJf Nx+fwUCNrRLj Nǽ)W|mWO>!*'#?: nNo^uݎJ/cˎ!x^Yݽ5r_䆓 <3bw?0mڧĽ19?bT<W]Q˓5 jk(�Flzs.~/wDLL W w.wk>knwok)K\8 h{`N(ſ0fmJέp8fK& b*0�9�,:ZH{&&&=VfC]u.̓yPͼѪ8Q�_ɭ΢7QRdUI#P-gK}ࠫ4'<*Dy{C2q9o֧Ӿp3yۮ/qmGl&",0"¨Fg\mgwдѳJUF.ωN(s#4a[fjW(y|kȍ/6u;F8G8ڽ9>>d8H!0aqN&nJ.9g֟Èn[OIܵ Q'L]}U nyeKZpJOa a[ yNҦrJ, VE.\ N;ȭkY1`7k>t.Ŀ9s2/hhܿ5|<miNa`{8>`Dݵs*?1qTxs1}& d+<{iޛ Gx82].dv$N~0_�otNd׾h1jOHp৾婐lq/e+;[j.$'85Y�fjpvP�m:`9p$gNgz__]gw "I?K"&0og}$vQO[�xoC_ח:feT0\뀢|5辩ܗ@/U@=YM-x7挋=mȔXc.)O=q)>M>|֪Qav~yC3 s@wX3w0X7=G^7wKm)BV اQyoDwQTǿ3@{J"MH* HG"{DzI'$RwwG$$k/|s`;sgggsɕ$'yݷNې1:x �K� yu _0FVI?rL^9ϸx'~,_v؀t?Up3ٌY4�M:fߖ>s#ɶwp M$Tj~q9MH|w9%oAW.=x}]u=rM>'w~Z+k#A{eq,CW]h(eH7-!_ :pVJ<yߥ:zdeCM XZM>X oR? u8R8/_4Ӗkt =d%�#ѧPix^/]X~+CWr^G�fm 3J5# t#e怙-wcv,~>iQ�V =ᷱ?B'+?}^Onque�ږf{,)S b?|�Qx| ѥZaL4ozE*>oыE}tC[)P*cX^^NuRs(BݮȗqrvW)L1Tޜ\ E @U  ?Ճ0ܟS@ ^4[<X,-ݰ=Zq#.~NEQj'+7<N\h@3T?P90e>х]_3Od|lPcPMo^5Υ[~6Ε|l<7G1:%Kn-gRI#xum[ƥ8:\n, 9ÐҥѣP9[#&Jq6ݬ87@m5X1cK?sGsuI܎ 6v+0 /ٗ+7q_�"upxxdWwccZ?¾w:QާVP ‚,<<<IОk|0})Dq|�z4R0 UŠ ([`4 Iݼ6l޾+@>\t{p2]"YA6*S{=8ZZJ[r B~%JLM)oJefMv^rm;е@r"n"t{oS nCG~36mmg~4kضkhy 0[udi}>:Ox!yp/u7ѣnL,Ce]0Cq,9'Ugk`,#Bg#µW뽃)}ܵ!K}n31|,&CI'seJ%L9GY~<8fdb&U~՛p쵃6"u_rdKPH_�87G/B,8,wYt̾~=5&7Y>h8XVju&ؾK '>LSWYÍp5Fe n[J (I5-%Ytym ?Ω(#cN2A[rn_|5φn\{NqfrpwK4+`Se�V9u*_[C7h9~2ؼinPpn7g͊]2=S܇<ՠg+s7G5sLggz~V|'ı ,BAF5F#Ke(g)Y `<{0/ FGLIJ{C\ݲ�I)<�Ȭ'ςuKQ3#3;O0ꍴi p*vH! n\[k⤀+)r GJ|{vt#EjVt-cOɓQҽ7> �buv>N"gQ\s@Z,i@ iS|+n.6`tړBe֠Srm?zD6=!RXG�90L# &6Sty˫ ӯu]'qd̎%I@,saz1@BX% W=3M%K<)(@<\17LF~-|2TumKS 7LjyH$pKtkԮV+ղQ3q:FZ)cJfRS {oX( ZᑯnF#*p: =`#35QR N-YJ� PTQlm3뭯⨰m9{՞zMxW Cng1Xxb3q^ ^]9%>E ݵ̅mRqC>QEjՏ,v.TkPy! ;\9@OA90nߩ@n.q5Tbak|Z.9 ޞkj LGSM(5jr/\7q�z31S]wu)NYPO5ͺ!5k"v5ޛn%]p6kr,"gvqp]/ yv� !պG7=9G T7 [w4IvĜ @Fr耍}^7_ :{0f+Gl\5l ژZ֡xѸXfC㷟  H>r.qo1 X(ꛆ # **JY~-ZsWuWsk,  IKodDŽq3`b=Uvѧ Bl_Q�� �IDAT %7%+�5j1}ri]ڎjC5µ"xe :u f«{YThߴwmMKp2^a2;Y??044rar|=\:Shչv6p9gL>TU]X8uCA0<yTAhԛ<z'`dn нNu0Rxq<ƓH.<ŽSy=&=m `6kgfrH""F'+12%LP&y2e $ C^*L_D؋WL˔isKZluW\yˮkDE=?-,mfСć^畮+>�Z5>b,3J9p>ے??.%[$&$:)XBU:;&i~ݨQ MxC`N/}]U"wϟDUHF ):JᕨVGڠ\Aw}m.SY*=;m^k_@yԖgT@H {ǁ1'Ε]6x1dOHKJT릅WJ7?~AA/9jstϫ@ nxxf#g,${Sh;G'z4Ϥ`P1ooJ]~t]7~4`D5 ƴ9ib]2J{kF| 0uGL%Ҳ ^EƎ#KT'xtz$t@7Y<u|<VWdȓ|KZ Ă*'$^z3m'aU'L= cvg5jk^ُK|3ZHi0%9Urh�<<%:K ޔK)vY"+wřfPuR׻q>~S}JVP}mNPyRn/vZܴ]LΤ^YAYm%IEŃ%l3,<6]uM'm% ܒ#ZTm—kD<9-:NX^HlƗ(o+Kdl$= } AOJ\mhjG=ڃ=y0s5.%晁:�y?d͌`zu!9m$dC?-+ŊA鶺$րA+RrW_[G펇ojD\p�-\o�x`VWlLmIYgI\ pu;b@XQU̩m>G^x7 hϴ,w*R.C3CTC<=l@PscM͕-$ՌrrmM\]߉փѪ EȼavEgE7i:3MaP-2Ӥ\|gQfY[7+`̺(٪ଂ'xbZp|䙬?cRU&;Y%1r Uie20;fl.E[H_O,'-*IH`8 11sqlo1U3C9[x�@u}㉧Ա?{٨RYc~x U=`}&*ױ� ,Fzcbk%9H啙PGFI<`Ew*<[o;#F;hdU`ݑT[ŭ<^v;9E1aؼE|=Iҁc(lѵ./h#?Hz[[aͨ%'O]B7G ~>FSTrPW}G/?fghXTc2@"Y=AcMeàE&Imdo|=nyh K\@{u:%3 Fm!̦k`6q!8;b"[&,L愩~*Mߚ lxX ~_6l&RҬcd";ј$4$ !>(tV|oaYf-K1s3OH6^iQCu֫M@8jUjř fŘ#cDK]WRMKm4Uآ™hЕӨס>5] Ԕ_&.ՀHn ą%U{G5wSCĴqKXgM&Fp"u6_xJuhwM CC!蕅cŒi� vvE`1Ea@E\d)Twyc ˺1qTτg aRasoQήQz4)cw. %/Dwa59juS ^"d*qn؏?s-3@v) NS<jSʭnPL`f\g>9@c=:^$u\e"oh|O1rn! #gihǙT{.[~e;~֛wӉ3~J[K*oZgŵx&7WRt-*)1K8:mf݇*p@ER -/\_= "9PF^bēZ[ 7k,¥}?AewIw9|6:lxiiͨ2lfgoKTt fKTE#*:;|]MK28`9,Mɪ(LhT]6i:/M_r)ڨ z\o^H: SS^[LL3wJ?BuSUA0mIR_Wy Nj #~eXۦ$_Mʨ X`ՙi n)+}ķScbK@loW|Nf`ͿJ\g;gJ +Xjw}t01-)[-Rie֩B\ �46qR9mYkҲ/B"RTӦ^0X 0LV6S+* 8ٍ̘wЏ*sypƭt<U92/7p%53jGUd``.ΈE|գud<U=}_*N50}WAx'haއNPwpyd3\U+aa-h߾ ]6cY'{+?'sL>|LC>|•s)h͋J/+/Wh|=��cM2ey>ɠ> 6ڟ_Z<|7E_.KB5R>}2m?�YX|6 sy\7D_%ms#X8=?@Xܪ idm63 V!ZB2M*tX8VDSȧ8GTѾؖJÿ>c�s×Ϟz|= jNo* \L7P}/, 7쉧nѢܙ1*go�5cgrϡz'x\Րo p uJf {vH,� -y|'f&w6!m4@REwO.jތJy&뺎iFGקhG`Ho{h0gրOעc0[3bN\6P~a9}N'~##q<yh)|#5J`/8!BWv7c航(ʛN ;Nn3bt۾֋2FY/ONo?͒yIgS|᳔b]fWˮ)9*#B񷒡[UfK坽1Y!olS,\ J'_U1{Ֆ8B!P*)B!T r!B! $pB!B N7!B!$pB!B N7!B!$pB!B N7!B!$pB!B N7!B! Wb,֋B!B-pssu^$B!"2UR!B!28 ܄B!"M!B!28 ܄B!"M!B!28 ܄B!"M!B!28 ܄B!"M!B!28 ܄B!"3Z/Hf q['%`$B!vlU nΩ~^lX!DfhVu"ڣoB!~0kW`oLkaƴ~?߅ cck:);;;ll ƥ>*'2̴*޻?'M?q ^' 㠀d-ݮp)DЭEV@ujӝXʽ7<A 6�h5v7^yJӍ)mˡJ\ WB^DK~^ ðyL_Ӓҁ.H͞xe~aonDLK^Z?1۶y?>j%2_{n{nRxSY{Q:4efͫw $tj¨r9 )]k[89%~>tuҡҫ,R_w7+rĺD)-[[fϭh өq&={dfFi,Ϗ T,NΉ?>E `ndw䣪~DjJQ}z%udf޳0cL0,LssIҨT=F0Y<qׅOB :o#n89:`4FC)3Mf(X/NFnfGktсU"v&A\6NәYO0#>;=ѱOxlÃc UN1',cyɦ;Gebq@G%?N\ob=gcݤW3yA>K涙wS tysy65hsyO ?{_LPxN{OEz|<f/|cIh3ɖO9v-%nƥ:R~[ {?6|ĝs>޺͙p"G>v!WI9Uы? nQ1{S׆hTz?Gg2`>N˓yc΍T[,@X@0{;ܹc[m2[t2 0{w]K(j4&qr$MudRi~k0 ,D; ^$f|j~HO e,-Bh2k6 1~7q%ZcԘ0vsx׏`yx[~3<eN=uu:_D`,ObRH<=rѶtnNPF3 鲉cC МH]1#|wC ڭgeOw yrv %)ÕZ{0h "N.~Q0-}COОpNγqL.wlN!{n*:Ee zkmẌ́x.C>lLBb{9NΤ0?݋N^4t9Eɹy]@H'p ~_ 趕+_)C <Ԩ^Z?/_HܞTwitaCb1s|i>iCޖ9Ӗ 4p*F8~rm*muH}{\ߏ1f*nܭOs %?U1\3`JV۶9L/}صߑd+cd6]Y*Ε9o7oСMYl]Jzw6`h,Q S30[MjD 혀_cm{_Ѓ wX ًOOO=<1)yM2b.7C6-'q[f%7Լd:m0 r۩'Euh{:-�6%!.(bs鍧'n` Jv{lW]sd}2ſ T5* =^i6:hZXc \4=]GغbI *d5н'a&'1d$9@JcJZ9u!.|y]h)M̌Bt2_y{9<=⫛H]gض_ uG3 7 zűbD? 9xLd~K<|r1Gc_nĩrb&X7 {ͬfvЦ2ˣ;h_roE2qsQGoQqkq ʏ;N|"8H=Qd[ߛG'GnKq`|O4CX҉?�9>u uzC!i27;tOԡ%-1t0z[`J(N;n⟯Mv;87 bϜtݪk듷hw\@䖤7= oXȞ%�Ȭ!Au I*6[.oa)6C9Z!7j$r8)FJ_ zVmL ZթУ=fDŽ,LY7ѐ!]qۧxrhbkЂ0;g3Aq# LiL5>"2qY^^u]%%q2scY6:L\Â0zz gGvOBtBX_wJ`>XtBѺRln .{.=]b 0T(ymaW t4Az*1AM/ЊŵhsPIItXũR~\Ʌ%Wagߘ̍W_]M^jfΔT]ʓfoƫ).3#-` 4V#*9\ ےEZq28Ou=O{ԢUu7B!(W;,/Łsɞ%X&[b͊㱴ZCq`@K_~r'M߯#_`h;ŮBK-]Fr脫Z}~4E@X޷^-]ƖH3/ å7V!,HsTp;ήĤq.։\6 ׄcHdݶ膝KI͂ڢ?ww=5iqo8i_*um}&oPm-B3e 3ڠ`A9ɚBkX,fSQ.g.%}V^ O}CSq=V?%쩲 -]n%P�-& \J5oJ6Z`ސeL=Y9O5b5WsXa$!(4( ʭ}Ԙû|6.#yuuK0oʳs x*ySa /No-]d?6%>[@ysUUx`a|jBeۣ[wt ӥ-odžЪX=L6Sߣ1ϥ=OQiX*EQk7W8' J&acK^?NF1ڡŲ큉(UvLt*2=ly3 �20vN~<ޚee^!:w/a�"H5d0qYq0x,f4Jt"êѪ-] GUHWTAE1&*)*h b5#2m*M^ T&Cǿ �� �IDATlTϑ7b s֠Ǐ$D˅Sh ny!B\sc J i?TFL ^է3�h ԷSi?m J.Phzl]`0ioF40[cl[3`]7tE4# 0ތOӦL6k;[mS; l8ų[bIobX{_<+!KUa䣣^%E뷞%Տ%DOщ'afuG7}G[}xNMxӽ,h3Ұ]<IG k)Ԙfȯy?~]>LydWgb~HODoi3=PaSAS Fj XrD(T6 >)s@am4hӼErϡ�Rɛs_\?/I6L`̄s12m_.MLWtQ>`p]ӁiKz{K^{tqx]H,JZᑌ u{r*<n#YK5BZ5z랿9I)t3Fdm֊bsÖ >MEUU̦S�u}OK={MD/YޤteN+RݠxHWvN1<~<gQݽ #ir˪RΕ]B:9 U=^~o/xߖ1@ׅ7)3Eq@Vl=|Dv, ^N(N 5l0`Ư.FCT�K(hφ6{gmugRm9\|QËpXQPQP gb|c %~oPr}0 ]G@Y> Sy/,~/*<r*50boh X9* >I%r(ˀ_mO8ܟB]0>P,+$0/ @¨{XA4{~ݳ 9U@G,qr0�hr vxEcfbB}At�rY'JN܍cniÇ3MPN{my3_IT0q#%7�>})W{#M<W{Oc ؤ3=^>8u^]jy9jbEh;_\i&l+$FîcA<;DZ'q `"BcT yc6,3 :v=1GtJ>u1'rZ1i%bm#0^gts�Hn wk}aXg&L'w#&ڟe烉;Hh@Vn|!-ޫᵸ=7MAjfh\?gl[3 jEW53p2g/Xs?)|Rzd fڴ-Lh|,K朠^k[gOU[x[S)/4.nZC™͵pk{P˓ s>cW; X1LX'Wlp+فƕx^ċKyYXUK&G'u*`,q.{GUKpyB|R \unr(5QaE 3�Y3 {tZiDzߞ ֨э&<嫮#Ԝ ~E 'ip=qjc$E,K<ܤF緯sMOOC_vʉ}\p7V> h˗4Ky3 ْv٢}ԉdCOO]f(x(0U~xYZ_}3rWj2u))3}%N;h|37=˜ 7^90rn9E,@R6ZҲYN-ϡx(?_Zc�&(Ϯ;|ݴ >ك#*,![ᕷ6x1ݙ݂@de._+撻�p:➾_AS׋``S"VawXaM"ϓ7&\I ߎ◣8WF$_@Iު!] oq OLO<<m^xv!5P7'_LE*iL׽~.ʡXUA Fo[ o mXn[|zp(kU .iC9+4"esRl>[5[gMU1#Z6㕳< gLkh<m}zdX>5K}ȑ=kˏ=5!?^0.WR {zᰢGɒ0׎8*ٝ1.T4l^nӬ+q{IkSk9[WrvD _Gy:%"B3iu49=|9ؽKîh�ٚji8x{I[Q0fcl7{7Y6g&.Aq.;y]giXcg/xxt$o΀ :7cԚ4L}LGW�y˕v;*ͨQQahFlt4^nk/SÞ^րOעc0[Ȕ1fm t3Sa[e*^¢}2jߙWm \ǡjd!B/z;#(o:y23nFLYXmF^Ν<zǘ.c[~%:uwݫ@=:;c8=%B!ɰ#nBXСD˖ 'sA dDqM0_ N!B5&B!BWa_N"B!"nB!BI&B!nB!BI&B!nB!BI&B!nB!BI&B!nB!B< ^$B!ZfGGEozB!BTI!B!$pB!B N7!B!$pB!B N7!B!$pB!B N7!B!$pB!B N7!B!$pB!B h #14xDvب f:I!B!2숛`$6ΌsU83F>yOc9`yd$ai:m|:)C|ĘEt:oWk ;IB!sg?И72~ 6p3i:6쬓րIӭ2@>Xs_V~h4i�Pr3=֠tۥ<Z>Y'ם9oim: J|euߖh8[{=}hOYgv/|O˦ 6hHUJaVh!G}5ǩz�?_{wSquuf,00f{vNDDe/Q!RM}M,($EJR$Y`3~]1f\!u{?9\׹|997ҁO\ѳyCkpݖ,w;D鰲tU˟R�(U:*/+ns{ˌJ&nJvڨoڳge6?n>֢eߩJa{AȈnG3+sNNZMOxh)CC_%a`]5p&SVp8O |7Wᡡ+A̶o[fɹ`U(և;J,F"*6jP�HF:F:Q.$OFq?)›F⡒`j4ͪ<!gv\E:c&8p�]ݸ 0|W"-"_kt:,_!~?U;Jս0mJKMp`ɿaq)6_{G 2`D  | 0Ob”m)\ɷ]O{s. Lߵm,};jrD$N#.7szW,̽\//{l2s[ޒ|]=^܁1SdoxsEuT763aޯI<7̗1Keq(X7>9& {NSeN=ΖY|-~´yq>/; Zcr{<l2Az}ZF0NdTw$੗710u~ZƆex F_0빅(bxe~"&;ϣy`\?+/rf=E橞�dׯde_JKu1_�~Y87mS;s2y ~2}"9U=,0g g!l]&+?g&IT){Z Ų)B&]k66['b`k f12bhjU}x$ iT,?۩)VnΑ:,SC?voNۓسC8f4OD� /ߙēĩ >ld_h3y6}&mJ<DqYt5s?oZE3h f1 P0"B#֪ _x}&VwqݴY;⸳-]n*pfKy\t)݁Q%u"By?Xrp<rw4FR,x֕=�H#WS*jDY~2u(U*ՌOmzJG%>X~EA EJc@J4zA湦~w/ʇGDm"b0f>\]@%}Jjn,�R㈕GԤ]RY3p%Fr�۟ĝmPdY:Y{6JN^.uf4S.Zwi\ _vp8BC !4$ECҲҍq]�Ps$k=ҁb)_2<X</l}S$ѯz;/VpD #Tz5ȅ'NĺZ$b.Jp? 7cHwolK)?}c7y cKa|fѦx6+=&7BNu9^a|mNvz៿ Úpvݿ9;iw"#L&J{6vQ|w#9'\=t;V+ QiN< 8yfS Ԩɛ̈¢<3zOdn:\\@`~d`]SÊaB�6-/[Ňyn̒]r-e7[1.JTAAAP&GFq_};ߋ:t p1'͂Q(Cn8_ץC}ؓFُGR <Lib3ML<kz:s&RbXtsg (eңljG۷;KN蹓= 7Qݲ NO]LL~͉ިOO "__X3:IۓqنC,Q ;W 23w1ÞĪϯKwNV|:=qg,0ϞbYڌxbŕ$gq v.uG<9bSӼi~=G~C] sŢǞ?ۋOu6}yVcw6K9 #Kr�O=@=#8u vՃu8γ8q2xQ">˾/惜͸ OpnO;o깒2g.|D;yuj4ˮ/py$c4ej30>~6]GJ=>,0+퇙|1&1Eon`ix Lw}7:漴2~Lǜ3ﰠq~9#U&~ÈQp7WW oyqNA#~y4sNW1?7nƕ/XP!NGGq::78MpP+<y+W`Ov|b l&sG1=;8r>S럽wؙg!Ed^T)vF>~uquEEMƮ|@K�~̀ԝSI]\^d\@P 󪑢El\L.|B` uX8?.("�`.]Ų5Kܙ8r~�n9JbP<uBr<}o vo_` 7:Sj bϤየ$\[VRI}NZ�w‰}tfܝ]sfOs'v`iԫ`R8  {hx\v� .n-zB_]DhX3j+{@;_]͡tv} { |.N}>iɬ}'=\P\r;ǹ�l^FA2jn$9gn�j?5SȀi+ᙒXt? 4ôfůkP~/d7uӓ(P�ֺw6ia #Hy?rGj?TR͞^IU(`vaZ*x^h^bBs_W+.O0j,V LEW5{Su;:U!cQ* 3櫟Uu|M_ZTZe\�-7_)Z $p\O|$l^N^Μ8)C`DߪhO>4`/Ve4B!<4mW;}P_W|BhY7uqʮb pބRiKNN v3Iێ"?(8v9xSB4[=y&nJv*7>4lUS|:W||:w.atӢv5[5O{�7.FW_Ei�yA/F޷n�G3`LlybAyIx|n96vB&�x ɋ̸!w[^!Wehu<whζ.lܽTOK`k14`E:ƉNF˔Lr80\ Jat8[wٔ%%Eb_$+ 8w6WXR 6;`/B?xypm"Ot{xn*~M/U T^0 r _XʫOY{wm K.h^>/EQ<Vq3^{7gqo-o]YtyK'`Ԣqx ús-Yk, E4y?2OQ'T +͕m0k?υ}@v/>qw"r-"#i/gq?+1sկs;&YxA+='4I*uc ٓ*ivhxy>Ȱ3$ĞeX8R, $ (]{FX`9rݐaX.Spsg&v/|X07Ç~q?W-h,m)#s{03.`�{}QWbZWp)'q. Kí c`ؼĕr,Ƶu0M ȱ~{"% 2 O\;@42;ro? ,+6;Q`TA';Q5{A`<߀~3̒m`Ȕ=tDE( h߾,gI2Fhpeɛ#qoF| s��IDAT@+?X5{ͲW<X^VZ=4v�WL{6`_frn~{FFo`EJv#VgCs,˅n ^(<}U[өZ�E+pPa֥Z Hްh+A=/( p;@)|-xoi9-g.xY-o+! 42Sʰd^y�:zieL#$$Y,fbh|۾Os 6`F1t[]מx�J;Fˇ!}EX<9+<5^KW1iOiؽv0>UeߗiUb{Y<Fs/dSR~<iq:#0k-|ù%�IL\OgTOʼ")9 |2kp-r~Cr넅nab$B> Xp�~$h?ϪPm&.X~Ww[J11BZo\/Fcv@bmQIG+KYt4Er6b:ElC0 ݏoc> \…9bh/:.Gn,mُuk[Y2c .]!۲wҮ9Y2H-}z2P{9pϓeyn`Lە <0?o`j@9w8;/: s ?8W+ x=O9dϕ"t).PBaF&>"9OMjRNó(L̹x26y0o_Czֶ/Cj >r�΀of-ds/u7�NfM9uRYTz/YrWGӳiƽ|uV$Gů}�x8-/bNnKD#1_ >kJmlCk}xS݆3s_Dt`seuj;tZ};s t/Pܽ,*zX+^t Ѿ~{DsS_ d$RgG.;ò6 |YVt+58_NOK0808r15K67ẑ R1LHHX pjBhVO8``]qot\i_padR X{Zޡ̕%/i1]9b8^*=/ϸS?V'Ȋi8\W3W{ ؍Ka%c@J٠BvXGCƹq1}_.|Eq:qHt/?z +=]20]\6O�8A>%{ "-0uir2b54o uflliƮ q:/`e"v-:Hwyj{Q�ԩ oo*ƹ&q)#%3i靘%~Y^p6";VmJt瓕T(lE9xƍԲ_1D9C;}<bs!\~c1u^|s,Ȍe7y ]I9-e-ߚ\W/33 GDZƵ/Rȷ&*jAVB/QbqCUb7爸%~e*햜<sӧ9~45Fmey}dBGsMۉә_s{./Vѵ^.Ev>O/[W9Mp]9k[yYjjR.떵cG||IJNt79/13yÏ-3p:mJAC�# d|6{5EL q7CF7=5~q Fwf3ߓQ1kS_ 0d$#$$re0 w\Ջ hsdH|L(fX̧ܦ665x ݒc@hiOq/7&e x멦xew_G8&w3*<rt9⒘%˧?8ƕ=ӯ=ۆq4j_ȗc<?>W2�j^P}ܛKg70b 1o6tcz7 ޹ȟU:|:ziX` 0 {0iOӫ^ Z5_'x hfE�ƶV�GЦJ^NwE[ݭ7'̥pkԬ~{MUë0XWhBA{*O4/Oۑ1r8o}7 \7)gP]/ u�/wAǟ`|tfKgr, gqdqyTn;mifc_fz;ӽ^(]&NfcsEyL8h[-bxf|[1'RKXGS'=͟)^.2qcDŽia&]w}[ǹ=UK2c_ΠcuyNOC>Iؼ"%+5�l }lɄ_<JW+|֕7dJ<C޼i2ceY\.R)|_\L\6;im&KRr N|}8(6=ǽYDDDoU,(~ ͓4s=cGN>v2\bܛzeEgY Dلtyk6f#$"""o 2Û>=1YAIsm̀~_W&͟ /&"n/8wd?CDDDDDD<Spp n""""""NMDDDDD)x87&"""""DDDDDD<}Kj}?Js$""""""7K%EDDDDD<Spp n""""""NMDDDDD)x87&"""""DDDDDD<Spp n""""""NMDDDDD)x87&"""""DDDDDD<Spp n!x\X `7Ice\>|uEXӞ{ȿ?6O_jywV<{inl^B).vBF1lawS9a{dxXzb} <#O'xo:L}MhXxT*/'ďT*bҷ{S VȚh^&J! 'u懌Ƽ7{'^|Xi@fnk2k]HJ^ofTW\DDDDD/򏍸@u' L]^ (|5S8 ;I}2f 6X8.YL ] Yc=x?)R,>x{9k3wk>is: x?+*3f'X�v|Ψ)̜7[p8p}EDDDDDBXp2e{*}yͯkkouKjWN[S/߆~^n݀= vŜ$T={JӤC8mٲ?>(۪3^<P-9;E9;7'?MBDL|4۹wehB^&:UK% 닣,ӽ,$%0i ,|J�d.EqR5f �@…HKuW- ٓ0 P„'U.fBq/Kc-*]Tn,B||рK>x%7 4||oQt{L_Yw|?3>H|o+W.őhkp叕|#t(r1[JG8Ϣi2)ÿNbAi0wOv%190nZvvVnu9~98^6}3"I;|*&g|JeJ�0*}'Ǿ:qt'&frHǿ?N ,G>DDDDDD*؈[M?ЍȥKH^<琢o.ѵ7Kٹ' K^m7}x,^p'Ő`/Ձtڃ #y3T(lgp&!!:wE x&L}cH΋w�kT.[L.`>0jMDDDDDFbRR ^erHMNhpp:p<y0Møn~Mx7&"""""DDDDDD<Spp n""""""NMDDDDD)x87&"""""DDDDDD<Spp n""""""NMDDDDD)x87&"""""DDDDDD<SppaMÑIDDDDDDF̌hY,oF HKKsoIZZ7n�i>YDDDDDD&))Ffaa$$&7_,!143팸e7n'-=]MDDDDDoHZz:~f$&%Y-r,\E??|||""""""8Ҳ/4v̬o7[xstf]DDDDDD441m6vyBMϲu, 2M ӺadFipֵ9Y![[,)9ucDŽ����IENDB`�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/docs/fp-message-fk-btn.png�������������������������������������������������������0000664�0000000�0000000�00000130666�15223753015�0020747�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��l��A���:)6 ��� pHYs����+��� tEXtlogicalX�608Reh��� tEXtlogicalY�252)_���tEXtscreen�HDMI-A-1/ �� �IDATx^wt ${&vU د^zm?(*({  !;c& ~^9yfy#-=BDDDDDD|ͻ """"""AMDDDDDG)(6]JDDDDDDaޥB.+9N'\9ݎnnW8,rrrNJXDDDDDDddft: y3.u6˲$0 Raa""""""rIK#;'`wh#y#k k""""""Raaf7_/䢁tb9 k""""""°N ``, 5k""""""Q"8IJK6@&b:l�ij5H!???L.1%RDDDDDDaSXDDDDDD䏧&"""""DDDDDD|R`Q l"""""">JMDDDDDG)(6&"""""DDDDDD|R`Q l"""""">JMDDDDDG)(6&"""""D|LjU7v?5n̲=\iCZЦ] >~f̔uDDDD7.QFan/O`vwY?g2`nL$wy79!_ijrC FFX4M8Df=F&""""r#l[bcp>O+-+ݻI8aǜa `EʼnYQSVP@욳]ỎMEyD]Nzɲ`ά `n[(aQw l""""refr<H0kI VZ&bf΃MX98{7-4V7_FIw-Ȁa7Յzo3װ]N[CZ�vf,XL&b[ 1д͹ΦùwD.)nR�60'f/{f NYdtHme<]vs�f}{//ԀGׁ{7Ug>}f3$RlWyʻx'f{EDDDD aXS`& bӸ\h ,=@P'sזdL_e9o;i')zT:6Rzo ѫ;g;CYg S|8mfhN41ޛ{Ĥg٢YǙSG1r3)HJQtnQ|>@N;aڲ,Ů9y4J۩U1.-pTl޼,&HܷGz2h[*v4 f2�ـ` ޫu.)K<Wloҹ'뇜qv =…^g-$߆iE2}#6jޤ0?k-`'0ʹ'dnXFIԾ1wy%wwo3dZ48S(OUs`Z~�9@1 Ș3#ٯw Qx'-mC2K2_ٸr>'`=Kղ!to^n@Ŷ7PTDDDʧ[j~Ǿ_� i<r7zv>o~IN"m@n|pѹ<'KX=I:Zm?W\sG<3e³qj󏅖?tq6狙T#^yi$-=�[~O_zcyL&d7i.#:#/>Tg~ZL㓕߯q"<JNw(k)<< |6#i5_[bj&wf7LўOy~1W8\ $3mf�qŒ`&MD/8F Q,gxwXrO<_l`le9?X3�nM%͂}'W3+`w8KeR{f"{<;RScp$9H\kv3j/<a-W*݂Sg܄- Vw؛t1`#3N} FȪt`sЉcgL~L`X9qZ95$P 90dl4s߿PH`gw3;Gq*Ba͛ ̈O&i+.N`Ԭ#|ȝd?ѿ, [vG?Lim9Sy{;[(y˲GxX)˼֥CH*$| K?|Wdy.) ^D{ف=ѿYMzw4I_3ˣVgȇ= }N9\s忏c&vL}#yەaSx5k>|AqZކ`x7_6wb޾#y;c_mWk;e1o%m8脭1 p?6̋+?a5U`䅜#1f<XyV6yήt׶+~3y dI [^-= w &_V  R Ci:W]oK ^{y"%Xw:Ѷϼӣ^ 0MOv5Õdv_g?޳Tދ:)&,,xOmn*$۴r.}n#`9 YfsTxI~nlN`ޣ yN ۻIDDDoç[FŠj7+bڬ`1ܭ;ѶCzU lNqhK{'�*7%{l`Y vL| ,wtե]ٽz.Vfut|cy^8do'럷c[ѧmi ?kWgj~ʽƀm|9u�77+g@@/FeݬXp1?BH!}<$fb~^ZR6[$aO0.}\pL`cX=a֝�O`+n3egRk;ӎj{^r{7p# ٥Pc�JySwd$n2 ηWJ >L.C11&މcBﲈ߆O_ÖmQݖM~YC qbof-8]b!,w(|,Gh@6>|,! $`۫>~s-׽rFmٴ9T~ `L : V3u۶H_"y'`428Am= X1_LP'Mػn;˵sn5f~wס}o .An՗yM[s-׬$ʝL=Lx*t}>g#$͑`_<WrN8{GX�o80s"r@NV:? jM,y wmw(KGkzy # {?~~zzny>'m{<� Q`2{t/K_4wxNzޟ߁O,Y\ӻ>hD6͋mQn MK)to܏}\w)+fP6̀7Gu&<Y;p܁IS'La5mKfFޣ)Av0\7OމՇSvNV牾)_5(Qu|84hWse;jpl %c\z�޽.>C x,/^<~M/?<$wtvӳyU�Du$eX0oZ](�K\>*PǓsˣ:r[q]/?u kz?AXS<VOO]�kpI`f5 @l�w]_펙? x1ʰ""""e>2,0_k-z`f-<Jћ!5�s;q_ܷ:5$#*4m l닺=f6 )pzn6\" E=,E9:FP燺c)<T27wO.�Pڀ燵\J~PWsr�O[\uAo /HhxiW8D6�=>5@͙89L׵1ۏVi/ݹZJx`b�!%CY\)R`ڢJԨ@\F݌ ѥ@R ky*-ri�sv`3-ɤB ߃%k"o,ɳchb;ֱC~�;O/ػ/Pۘ CG|up;x.aǏ'u=˱vXGr-n}+.sjޚ6-QQK Q%;15,y7qLz< }6jւ-SfSs* XAX6 R:uA,U7É׺ [BoqQ-7{V{=w `@@&Evyb1Լ6 z~Ov?wב,8 ceQM3[PjDDDD|;Y`eeb5="Yf[k uҩ;3R _m /5f'XűPgۙ?ib_ 5[p謓C 6M@P;C5gC)| <# <ǡc(8ilu M˗~T}6xl3W6~ ށz;*zԊ8cz\1vh#:d6٭'Lgk;x`[Μ9bYy&lYXٙ@pv8hp~Z$:=9G=߽5�{ �2AǛdeJ8M? w7L38RP-Y'6T/ c6ry,E;(icl&0wB{_{YwE):{'Q).s(lQx[qǡٳ7ỵ ~z֣`$NMsk l�GR"�#ػ?j~`tM 7ˀ.YN1'MÜ-5352lS~@ոDѓI=U[9>Oȿ\;|Hg\;osIͅWb].eb %9eŐsyС2]Hj i08Pl+]R~P+2xε8<sGb❰y<Z5c�x_Wkq"Ӂ-+5�\%'^̮% 0?}�hQ+6d�J,=Ps'_DPoۛWi[56rj2O"oapŅlHc7r\h�W 87vve݆ ܰ5+q;Jןa v3sDSQ0ݽ iؗ`W q-(Y4('< Zqb:ػ|ٜZ=meK`8Sп Ec3)+;9a esN؛?@o6*}5jTM1q_Q-Uq}yqϟl[ dX;o#+y+i*2k~_,Y4ޣ>~lwp2Vn,�] Z=# Z?J8xK`Z 9n~6:U*gݞa/|)CDDDD|O6"w�[iw-˕ܿ 4Ы?o'оU8k{w;!?Y5c�OB>wN:I܏7o0;SN FB#p<ʣ3Oy~ 2|p_gJG$ɩWn`^$ ,|U;мi%EzWdZ+-q4}kiLX>+Hy=? };aziH]AyMDDD~`rMlݼˀH l=.iH ;AMSp_x9=ىz# {#%b^yίY'8~Do;up^gO`P9c%/k"a~RO=7')uo}cQ˲`g[8} L`|t<_kEǡ8, zI6$lvǎm(=?S2ũXg] u{r�xUC?k+)"""+hL`1S@D#UnF\wL2C9 a'-]KǞ Pg-J`%X9Qcizt &c_bM)<TIY'|:V9 YWgp@Dygw&>4ʤb` hūnw(Рq}lةW'pn %?#rޑ2~v/Ls˗>p3;> hlɰ 쾊 ̼u{8iyѻyҫ05a^Wpͺ{ԊRس o1Ei&"|p ^ߟ>=ˢ ]HHg޷ ߃ l"""">O؂~[1ru1(m�ޣHT>]FPpl8͆I�ׂ'Ι0-4y~Gt\*d/)e8ϷgPct3&n;w^ 4%(ٴ,,g048F~6nl85yi Y,^ő8]8尘`',:h\#&9qs(m@ v!з}(sJJ_䮟`U2(È,~8;?s̵zv_&"""">O7%+N<]0y-n|˹G,gǸCuq[=d8,NNÙ}n36|pwVɝope;I;ZdXkb(psaY<MQ8F&/nauQq'= VVzJx/kiV=( ^y"&0js!A /EDDDWgVP"m}@g0;^Jv ;6Ru%mc~v~x񫉄 ?jP.A{K|e  ?{_w4)O^t7gۅ1ϱr׽ E$ރ8y<ެ$O Vf&}HW8\';1(ٮGbЪ{g .6"q,n }><]AviN?-?ݔHpMد |WzaG+jLj~:o=+e8RO͠l�T@MzMoFQ'6feי>͟έ8u4JۨV> jqMv={p׆լ\27sQͤt jWc ە:c0e>Xv<M2%Ш:uq[p;L�� �IDAT%]?f{%Mr,ÿatAѼ}?۟l޷{V KҫUy [ źGvy^p!w9qQ3-0Ju_ 9Mrֻ̜{u MB1e%afrRF6m:_b�;\t o3 YidedP>*ʻY䊬ʅrgeڌɟ"""""W'*Q9%R|LXm x.gbZrFDDDDD.7[p/s0(3+ZٳUAݸ5]"""""g&IϽǤo|z b]N y�Gl=#E]kEDDDDj7y{UGgNJDo:F<;a`^=o]SDDDDJS"7Y0nR-(�:xQitMDDDDB-Rf!{{h.u-Z FƄ?d{T3-/W&sld$HL֪1CLhUH [_MDDDDD>l"""""">NMDDDDDG)(6&"""""DDDDDD|R`Q l"""""">JMDDDDDG)(6&""""" tFFx(}'{sl ˁwӻ c?q ڻFǂwErScyWB&Z4~#&|$XL>cx'|`nˉ>j/Av J7�'`wOf6;իIYoHax`X-?f<=K`k6,NveaλH0g& ̊KʍU9ի2y7_в ]wy"λYDDDD�5EҢRy^ք<;s0SywӲ,Z)YU;i߾4{7 eߦm<l֍qT*}%~7`[E-?"YPf:/n3E؊\M;[3[$#c{-ciGU1goM*�5g-ޘ]˨í3^e&|>{WӾ fou4~:eyۍB#K$gYnz�>gѳ8x}m L;H޿㣗nbQVK^aKgrLںm)nȊ0z޴z}^ 'Lۄfol5lCE[Mρ7=#N?{+V$$7Ս䡛`/ݐ,uǙ5gZ!gv%VO|#9}|7MKxq@Kj/-=ɔIPytH"X^zŋ~%(׏7 Z/e~mwX~vlRce{2oZ; 6w>w?j4Aks_@(sޭDa_0hHW%vnQo'38gгb0\ߋj85Ӿ]/`+Pgᫌ{A?Mv<dFfEDDDS3?@MX*rILLZBڒ/ᶦLxYW0<15Yz<%= '�&`o\_&M ;-;b4ߤboJNZO3>FG*3kg`a]. ,yOuw5&L^۔&<3a4de]J!}o2zc+7ӱNm/ n¼9],#~Ds~nI 01y~U Ac꽝yg݌�i<bfo@Y})j^k_`el#&w;31 Mށ3iLF4#DN'ĊS8weqLj߀~lXm [űEd|4wRĜ#1Z4f2OH#Hkv3\SL-]lGcK@G}5|v]=4Rkqɧ L?c`vѪn34 6ˊӹ8ҾiZO)"""">g[< yuzPLizwj3e%jAFJ ]Q|mՉa7X#�vNhZU@.]؝ c�3`ԫՖjVd凕M\[Qr3T`-2qg(ΤuԲ;3`DWlǁGț2ww-;\G UD+u5i.gWnu`n[sZaf NHHֵqF'ر{oC Nu^ˢDL+ci0^1*[QHI-{*ԣaD jAwYe |Vʥ#]56q,t f.F7ΥCi^O jl[�8akPjL  s~= ĭBvo#,{&t 5Hޔm6NL zk믣^Ś<ݾ6!M[eӡM4X~<m+ȵ5*PywM':ˏKv2E: ad9ԌfdoC ⲪLg}4:rhn20u~JAO cYC` T@^=˚uu8ISgeRl?[ktmИ-T#M� ?pF VgQOd.MOb/Wޢ Uq8J(XL(㾞ÑXLrrMyuIGUuيOw`5t'ׂ0.2stY u鐱ƃ]f7*븓9ij40  93Ӹ}5ҐoMƍЬvnWMoDߨ!;�[ "O0I=r`fb9a# ZD�I8zIcר[E0b[&ouw%YiVjD�M6bi4|^I\Ss�&7!T [D^lU@ |gqIڱ8Y(\'iuh]^XY~&^lmw?+}Bn>@N)nX?N UDƨEǩ[ノ2Q pzԬ4ja=|}|w4Ʒx8LWff (xk=,Eb*ow:C!70N_o^j0fqe'b]2&b4n( n lIڵ]6mQ!4-zBm7F,ޝ;I`҃-Xs;æ`9|X?~Qm!�GO͠ jPɰdx{{끀̥Z;VmU.kiiq d8lkb�~vp)}][DT}/ TIJf%sgPԉbƔIWSp""""î,5LghȆ9cRbs0ʵ`k6|5{5rvsoL{(b `yr,0s]y,* le"[ޏ8Or7};n$3[c '+7[s"0Sk%0!i:vl{7K�(Ѵo[ҩuc Df9TMjDU#"(A0R,>\C˹qe>]n)8{r[2fӯFI^؅'*}h-'ӯj4`2`9\WyFcgBu0]y#J $ U#R5" DQg-jYEV(np2[Rac0u&Z;T-W}Ir- JyDS</W#q2)eC&20@QDTW6vTiP5jzVDDDD|\8|*G?ɾRҀ&n9͖] 'D \g)$dRoBx Iٳo 1{z4441Bq]yv僟xd+1|?e:ajK66e]źC3{#f[D[ Sg,!;KYl>Žc&-ά!A{b �}%Zp]%kva߿u'e NF3O[Ss ~ [Ngv*f/NG㧮bۦYH9Ū-7Nb/NPfgE,8p7ʈ#'A oۺ%+~&ޙ 3y-�mV{-'9cwoy xURT Fh J0aGfmRQ#*QQ4e6ݖuM%>qf{rnb�B~mqv#%7W%`x8 K#˜ $J-<)>;T!&rWl@eôF""""|fJ9xw X 7N˾?b~shY==ڲre s9ԋSy݉e`Jt": cON޺e?(Iw&|8(9F5ƵC4ח7s3~ xGٸ<9]zt梨 ^օ7~H/|Hpk=k. ^].ETĨ jkx7SŀO[:a*ҺkfOo?|( 73x̽73Zى'\hrGzҰɓx{xp}ZVcGxm >S׸{/c}f-V-x8eA4&Ɯ piǿdܾM jPȟ9%W+Ed@"} AHm\ {d F/Ǔu �3i3` w-k֥s.Wt_TT].HKO/4/˲,L$+#QQI`Ѳ} |K濄\� r闾c-&AM|Bb:UEDDDD|'*Qak4jwom{yB ܵwX =9kZVk{gWE_y.yo#Nx{vV1zW cM66|fH&"""""DDDDDD|R`Q l"""""">JMDDDDDG)(6&"""""DDDDDD|R`Q l"""""">JMDDDDDG)(6&""""" "WCJ3q:XލR,` )HxR""""7&WUv)!!A+[:&h" )""")rU%L!0ȟߏI:,""""q lrդf7 n(8( %w)U;  $=#ۻ,""""a lr8NMt:""""&WV3{Q`Q l"""""">JMDDDDDG)(6 +swiӢLnl8)kϟښEϱd3H_ı# ^Oa/ptLI0wNWfޕ턲ߢlH;\cNǻ{)ReOr/hVFѨQ۟B""""K8Â{0J,^t 8� xog&B1bJ1~99]ߐZ7g3q/AOX]NrMu<u ~Mzozd0˄v߼~ͼEDDD#lyۘq$f&zY= ( mvG, 6 {xVR'<#zcgXkNX 3nѝ Wu{8=uc6]NÛ\=T FTQ\Kxw]YVqqK)o㻴f߰:6L`FigznJw}9Ƭl\?2iRۮ\&+gqUK3^ _dhL`;ԥkV3 $3m#5x`# /LcT1}]’4 Yy13Z)؏mܯ= qT `#֌F# ��;ݎitkV1(c'FH;ٻ訪 יI/ԐPC/{/P@T_EXwTw {K$ZBB̜ÁH]2Y ){1Tqa<R@1}LKwW9)ԡdQSJہ 3󻸎li|Ch序#DŽl 'Tyf~yK_m/P۟(Gucv` ӿ4ϯ??}Ȉut5Q_*,_T# &M^5sI=F2<2k$3eK2o<kI8bzD4|,""""ꦚa+1P A�y`5Y#fAνi?fB)w`za,(c&$.U/2W3>q,d 60~@oӗ9w< \y}ӆSyu )ߖ9̃VOݪjv"u�x~Kb=:X%_ {yVMB!y7@~\qڧWQr#rA'B>LcT\6_=OEƌ 8WvLD<lUGq+/8CxluxFpkv76RVM&m7 }Durh6<?m.aKMk U?W ^lS1fMϛd'D�`Ct�_{! p00pĄ^#֒hzv~y@v Q&w=kЮ{ d=5,\Сj*AU�L>\j֨ ˄c6nSh5Z 홼LšcqLʟAwקN{1=J4�"ҷr=pe>КbrөIKz7b%o6O]�Ouv"VU#ݱ6O/RO7p0$syݳpԄz/YׇqwQy м8vK<eT`5M뒴*SmMrkY捠yɼyY<k*%ٹ+/_.Ę9<M\[1iH z?/dS/GAݺH)Φu['מ`Z6F9zU CfE.HOտ?g xhdвC;>cq7˨֪3fmk9I. Zw`$H#{RD] w� ئK%4W}8}pbfREDDDnu7Ւ2XruJgʪC<X8#mFSgH0� U= 'ynEPA Ѧb9ԯ?0YSMVQ\ >! �� �IDATV ʝßaɊoI8y7n\$#)Rsy� +LH4I<cv�k֍T7q}L$ÚQ;'uƉ3as O=_N#�� g;f3V c)tSV>>hslc&и[tIU rEskKɛ>y3N fta&nbۤ|3MúM#X9{UıVw0{LL%eNx6) 80*y]NGkcNgg \�>ymn*:b/lT 2H_QK'|,MȅƵ*0q8|q|Z- mn6M]{[Zp N/<Y} _ EХ:M ~E[ɦm|7K~ـ2ynQȟExd/�0oH&?[ m Ԛ8�|NR` @X|2Vxbf1˓qn7m9Q4~w `kqL0.ۿVŝ<;,֫߉5`p6e5sV{GsA&$\y߃<�x5C6աl� |*E4J]O~aaDF98aŢ]vΣmܱ9=i~jx4urҷa|uc$)l޹{n#h0HL1� Aνuy�fXA\p8h"F0Bs`n� Dudk]?-e9N�3pgir*I1pRhuգnzTWGLp;1|Kz 3~=&p&!sK;ԿVJ`ck:hsG5#:U*pPAm'h6-GҢQ5bc2j^Ml t}s1 6<M8\(d'i7$F!`~.v񪈈ȭ l5 W,\Π1rMxi2vlXL^o߿O˴c=v,dDZް>'q!ཅ>ib3{Qm@>ǯXyv_&ځrQ j⍹l0Q|1j $Yo;B0'KFX4 |omq(S0NC�P(ˎ38CV%l\*WĹvǛ>C`B>a[zMM/2c֬rd)/H {{ernS_ v{:OTwNx 'Pn1LGa" *0ď-}1rxN�gL8p,iXp%0ɪ2?Z6gv,8.0fGX>o:T 2tb[ɲ|2r>Bbc.r1ٱc)""""$ZA|v52qakF +`wkD7Cp$ڗK{˶a 2㩟?6QN 8PE! jUNC?Ϧltפ2c M &7/ȫ y` ;Qni8y|həL`^\#Z8ɫe8g;[o^<=3]k\`͈,'9hҘEx'<A`_Ъ]M~[qG~;89 n4`ٯ(kalZ%�4סi܇VP,GEQ$zncD`bZ~~9-48ӡ է� C>MJh0 OHw9I2R&/pw9eO))RDDD#.!ubixHJL$o.~aLx[f/F_^ e>/v(m~ D% /͞"&Z8LXޜdc(^|CMo[wA`M{[DDDD2@tL AAN]xtn4?2C[Ys,UpJEMTN2o&1~EF5xz~9~u#Xܐ;sE }ZlpG4�v:NDOh%m"Zy:B)]y +uݴ$2yÒH|Dޔܪ b/ dBX%""""""^JMDDDDDK)x)6/&"""""DDDDDDR`R l""""""^^8l/I6o/I ό(^)<ݨ 4(^Dx)6/&"""""DDDDDDR`R l""""""^JMDDDDDK)x)6/&"""""DDDDDDR`R l""""""^JMDDDDDK)x)6/&"""""DDDDDD�T{y>E*V6!u}HZmdGR Xz+=.MHX'kW!"""""⥼*-< L<L9!yTX5s.VKf\i5>&EqxN.�|l )8870en $MH#gd^N0oBf<eK"ݸ<~{JjJu1-jح9wFr[NV:5e3xnPb5ULJN\TQyjuM&=?Of)_`0IᾑG(R:x ;}}5*a -DVs~ 33$y̴5x'8{zkvW/JרC X8p |Q4OS:Jg='MMO(QjT9h7iIhۢ.3zRҞc?I4{ѐέOoQQXJUDDDDf5m ˦0yoS>!~锴1{?2 IGp_ߍkc?#|+Ŝ]q<pN-xk>^/^ %~/R\|4{ ʬ_^%5vIm=½Pjpe.7v$ڃkr֥į^F oPz 1n:Ę9H&9s AQ4 FHD^ܳCdVĐ ~qӠR^Uyx0dNɓga."mu$=CH�x}8ë,]M|yY q&ĞI=c.~x;Kx5UDDDDf&̍L\A\kDp&̟x�Flvsz ;L nϦixpN{c7f-`1iH!,2 kjq�V/_N_U0tNqk2lV,J߈1.#OU:E+Ok &^$\۷Paj5x�MhW'OPm&=kfR/$Nk0ƏeW1Xq._Fo(Ə#wኟ!e7o7_F?SBwvG}37pGϧK?xqÿܝ(\]kw4 p1f9J}~&ax\[~\&R;ї+VP?J"""""7{!+s0$ %W`uj5If/ݩ!rPyW0|[/YH&\qż\ŇN >ٍy$y 'O%y ۣ,;*^@A*én\ijli4'@W6kbd$:8!R vʼn[Y(|RS+S j3۩ׁXuN4 L&Nkf͛kkf0i0_&3y~/8  \lM41lXњ0biN~*uf=1^�>7o%_P!&_igww8㆓')? F�pyظ!Lg`B+tRFڕ_6|ʷN"""""7l{H^; ä^Ӽ~|+(aO%w$NL9? ☋I>~1=FY!/$|i2MNÒ(X2fBI$q[*Ø ;9*+:, %g,pv�;cB34l݈sY8s>hDK͙3m8qLMv]3./?`x}la)`HT-*ʞAtF>6/Y{_y34l!w4x>A t4L""ry晋'""""r3&<4^O�fN]νw8Kp+!SB_9-]=/=D̏CB >l˽�#}5X(Sbi҂|Lc1OSF 4&aNY9b~BP [ s:lƧ,?i?=dZG̩Z*ym1m1ūw2er5ofu8/=AGJrnޓ3xJ;^kYe=lݰn Ӆat8.`$̘TC٘3c< G1Q.Sas>CPNyL#oƧ@2kOynpRvqQ#jP&U"1 ;<Z+}<nMrߚ]M8 s`hI7~` L;aW߂)WK9<-CzpN|ZUwY MH8N?B݆,|zu\z*c(jGæ0r,Pr9Lß&q_$c^0O_kՑ""""r3ɻݸM'0YVusk =2e Qr]vw6/}|OPciyۜWs>P\^V:/Ym`rnNDSLkv}\kUӸXBߘ©3ND:Go$/LüS5$q4j0)SӀ&0afrqFgv0coz$`g)ZIӦ!N˩: ["pYIP959 Xnp4m[pMPG=?'.x EBI;t],:7U:oHJHv|s"""""E"̍&N 4 yGOF ;ӉT` 5]U_b\y;>}jc4N{LQWcB�3 :6iس>CJ9?Cyd˓U"|WK<=HJUƵB ҠK +i_?G4 75?^�ҿ}us>]8#3] =y~$_}G.,?d,QӲ? I6W>HJN1w/T`&|<܏7{Gn㊯Uajj�X?cw9� 'u#.~O:F\BL񐔘H{[$CUis5s˻ ד<[op?L.Y�J޿)""""C@PP/[׬xDILRI' wV,e\@Wq<{Sh n K dX5%hT >ؖZ'n V8YPUk""""眛aS`l =q݁o-\`MGD$#X+3o >=[)dKQ` nDuk(ȭNM$[ xj#g@j-@M$[8umV[f <Tz""""776̱6ӷo9[9)x$±6nĭ z""""76+�qFa!"""rSQ`RKZ1~�""""76&`ݏUk \0kcodk>a{I&7= TDDD$*^tKvV 5&cpp;!P+]WDDD$ђHLu +vjXG$d? l"f xHXt /GӷEDDDH[sag{CL,v""""^JM$øfrU�^2[ODDDĻ(d/eoD`X xh F~�a=}[DDD q `&DGD"({1 ]3l�kX.qA[cb R`>�ۋD1 (ٲB`)XᶺHS`nnryLfb;~z@22Њ\uٌu({c@HvI>Z~];{DDDD2ֹMGD�a0k X>'�q `N l"-KXgM:XgŎ6&9h뉈d,6kl/f!'֎oi/e !#  c/ȥXdg X2{El6c�J{ӷVp/.MIDDD$iMMfڋ7Xaf7OX;Lzl�EDDf&rULE{i5n7v T m"""Ѵ$R�ۋ] ˥U͙Ô5ki^p"MnC7+m#ݬ'ֹ|HF; 򅽐b-Vw(~ n/ai[2Yiӄ{e0 yKkgfdwoEh[dX]c]}<ܴiiNc8k\FO+e-EDDDja(=jm6g%""F;>iՇB6'~EDDDe3/Byʚ5۠,Zv�m�S֜7$ڋ""""WMM~'vk$wlZ RSl%3UE䬧 ;pxQiނE10CVd`}ȕhM W +@,aE+R` Zv: kY0t7V ^,6r (b/Jsbʹ�V�bhR`Bg/ W 8 �ڧog_BRZpn|q@''0u@-HneBhn8\FM~͗6i؇^]{o�.{& ܇uoQ%7K%ey`N[ ^4nG2;7 {F_&T/mv܀Zooy0`p2`("""rQf`3M{E怽2~[#~�� �IDATS%# @H:t6;p]e�PǺ-3}o/\T9-4mzU8hO;q|+'}GC_r<ҋxqi*۟l_E"{t&\Zp*b5t:9 f"�.Kp �`W |0ykV$8T*}ww?eE1Q0~x@ j.4i'POLR?Ns򢰎 Á< w;Lye�̄qw 2׶9jB7fP~L ^q4̬AOTh}l ㇽJVoo;SI{!S4y}?C~ƮmK@/T(^?/L=r=cT6 xb�eaV;ϕ:mh??Zt}g'st/,~ zG @ۃ?03)`("""rl3ö?Cq0uZt^.\0sM9qhC)`O3iLZ4/(Fx{:e/d*NT|~6O<ް-p&q.gD5Khk=uP,.7I.FNF:vz|;?)꓄'�'M{^Z H:&#uӼlZ5lm[C@~6IaK?ﶍsz'IkG<_ E.+^N.1lN{DW֟ȟ6o^zms-5:C�LIœp2sm;Ԅ;H| \?x3l k3VÀd"""</nk3q<n|N�3SK,#Cꫯp;=i�aoZI*et`Q\` TGՖ/\?݇W6[g8ri5i^r3g0Q޾?��EDDD..ˀ u)öd0FxpCl ZU3>NgtQ;=DKHEF?2|6[6u/2/z<NKx_R~aaDF9~3ˍu8)^ mP~L;֮lA& """"dy`Vw_d/+͓GS8Dzr`Eeւ-D/ zٺW6?C>!EBpn6sh3c6|$d?sZY;H,ׄF.cǶylM|roLTbDm 7y= Gӟ;rLlNN^l<cxNn`rt*ӧMt#ًf=\DDD2J/[ޏ/?ϒˈc�y{}Kotb>_s;!Mb:'.z'B?SxipFr.Nn<;pi=fao^3GMrx#[wkD7Cp$ڗK{ڃ#g "{w勱;JayJppw$)۔N1ӛ˶2yK4`m<x=J/m8p%i(?FpxZOameo\H:F\BkL񐔘H{[j/^'7eR3ϰOe|k/^ %ûG[B{!$im/\'X """^LM2# 6ڋT ȥ(\T]{!TE6u.HVQ`@Az mdf l"""ry l"e�oq8g&"""&rIw c{Q){: """"(\R32K?.0 L7"L0 {9 """%ً𛽘NBXg,v*d/gui/&rYL�𝽘mx,Ŵ^^@T^IGMJL0^fs[rewL 4kfoeiu*f/&rE7"(.Z{!=Ĥիy~pޭ{2M5wLZ!eB^ILjKHix<ao܂>3Aa 3)kְ-*J kCr ѶzLYkyP{:-%i,:& 6w'0^$>d@A26c %"W[{!Ke`!֒I:#ذP56Vm/fo@~ &%ӽg/dzDI3x?�y x$b^� """"=l"T�Y(yUv i/^`Z)"""r6h rx\@ (aFA\Pd|Xš\ 6 0 4o, 4jcݛk'eu3ȳE)g /V.&(IJ8Pkv.+߇y<w `/nDidUDDDD l,xBX=r&Zx(};DDDD.IdX;8ʥ}5c5 ws�򑹳sghv<};am6{EDDHlBK. {rc;8g}vys`>97FX jGZw&"""BM$T -s޸ <n/\P_E Vz l"^`(V l"9{QnY)d73^*tD$Sumkw*N'@jdu2a{CDDDc�34޾e)dEtUHuXp@p08BV"""Wp&9 Goz$Rp`Cuv; |EDDNAr$}KR` `?d8oͬ][Ɠ,^k_tQ`X;InºP8݈sN'@*>K tB|Q`RP댮RqY25U wh"""tj/rD0??e5[Dx\cgXK'=nnY/Bd6 hw:mFn#@/'"""rD%;{=:9 =߫f$cz�#"""GM)IzQX*c-<�`%�XDDDFQ`e r/< ` xfp$}On= ( TZ;^VWvΟ8ШL^Hƽ�_ppUֻX{7`]Tbv]^V$>[gV᳙L$^z3ߥGxpTpۇ\g秐| keoB€KXlŚ%ke<L]y&NF)ZͱwO#xs{yy4fOӽ`\f�U^ t1@4pkI0wem^NgٳBX�n7v/!ysз[=BvO"8ad>-_ϴN_L86z' 嫩pb Zg;}XU>hcx^SQ [/~ȉ [؏wHOix8~?z;F>{ۿBg<�W/צ}?E+q*m뉈ܚ<]DyC)R Gxnn:<;Xoc9YK!2`anf`� ڄEOac%ߘܙ>L!6NHdy?LƧtoښŸ>v&=i~o Q#!|$f6tx1mCٴh~|:EDDDD& #/OΈm$}yǃK7:=``3Sô,_:]a.pw7�'rO#1qzA颥y:l+ۃ]nwEШ۫T+].=۰=< wAA~N$"""""+˗DJuaE ҷB*Td qխ$`jtM) %ϹOSA*.U%"""""/[AO8. XqDt0p8HxL0M<2n(y眛l4'td,_c8SL%Y1ß2ez6Y1RlYL*ub)IH+D@0N Х(SrǠgbɬܹgAyCH' G>mIw2ڻ?cwxGºg Br|g _m{Ӌ~Q9Bcu:REDDDDDK6!0gY�v"x~ �C >~>݌]c] ;^<x]q䩞7xoxgE>v߯t&!?U!ރt}vGguH3>ooCt лTM:+"*b]Qo{]B" UJ!@ۖy^too~>3f3;kd4z-"g6\RR3m($8@@P5fDDDDDDX l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""bQ l""""""&"""""v>uQR`Kp݌10(_oE """""ry^FAxD .Ras2rHcԹ3o:Y.J l"""""rʕ+ӡcszCPߡ%)"""""DqX^M5O?}(iM  @qXQ:M5Ͽ _?9r:BMN'0ȅ8ծ]&M2a$\qaaa1An]&bq!6^/FA4nҘ/I~(W<Fd-FvN.!_tD,.LBoygԯ_K/m/h};&3+oy9'LKtToe.);laZ.Nv:0lJI%8(8v/D;&;'˥ Aw#4v6Hh*R`(6R`(6R`(6R`(6R`(6R`(6R`(6r6uede픋8NB-}FTcfDDKM<r{8rFpp�v{y<^ I!2<NwI.>m͈١["ES$8(�]o[9n#8(�'Svj֌Tl~~N.c9;lddevjOjFDD6'ϷYm>!՘i͈٣&bq.Km\.Rə֌=8=O33+.Ձ5)XE)XXjZϿl{1". ""/(`djZҿuKJZk7ln:D9l.+;z0�X+J*1y-c;.yh ݯ{ vҩ^,N wZ /߽-c]k7\? \~ oTWo�.#kg`^>Y| Nv4;zR,p6ɛ5}sIt�O B�A' \qo?yC[^M~cWd;jx.K抷!%VY&rs*\gT]4nЀ믾ǬfƞB>zc$.Ꭱ``~˧PtiY;{DK5pOcF)[7=i3t $݄WƮf޸elgpxl5*k2OO-TZ2=q7ZG!p88.<׆}t/""y{-'~ʯ&1l7Mު}+l'c$>z<-&Il0Ptru*/fmpoesPF>Ҕ/*Ctœq۴i%<m=^CPp4]%�K#UKO3/J|~5W#/ǵy俾=/}0ʸq<?>N?�cw{x&1Ss0r(E~>_z?}5]SIӦӵj:6oli32FNgI<e]!<pOÞ绺Sr/ KN>/|OKL_} zo$U�� �IDATx7!wO xhıx⽯Vؑx3- MϚAq-+ϞIѿ^DD.T lQfM֫Ň',n;f�BԈM|zg/>~3g" \ʃԻ.q3++gD!:2 ͣӕ(J�楛Tc]{r6w?WG-S=:O^ی]q,K5a<A>S'*ColKJkٴx ^'&q@Dŋwg/_,ΰ<\*#q?9yyM%3+˷~ |h qUrgD3ׂ7)43>5*ڒШ*]|k6vFS^+ޜuI_lԣ�X`%wsӸϭ]ǼKpm_2t@P'5WVjR'^ۓ:w<`b"ccnpo*e9[]DD.,'?8m^.Iijx57P|uqNwOfЫ5t?+q) ~LMxbjL&͸9xt&۔iTk lɃޘF}iժ#3kDΞD/xvof[# bMw7s"и_b^y)\^w Jy;vQd&,jdǎ`n/xmPc],�I0sM=<ث�E'@p-ɠC@-Dz޹igY mەGЃ"^PVU춃{7+xw,Y`a8J�@~o{M(T"g#|od+݈{ڋvdqσ0{iA`�{j10+@R25^P# ,nKEDsοv"@ơCQHR3o/ W8i?"?V*5ٽ4r>/__xz.zqFT5o&v?Փ<C`n2m z~ OaO=^n/O>́R!08  "'3�wISxz` ~/l977B>KP?Oh 00\Rv{!hU 8nͦ`?l:שt)Y~u7[$v{)ī.aG3G0B,w< ֥iƾ't=- f�%Av2 MHDy}M}ocBpvN_+xk!zNWlTup,@(!zcY ˄Xƣ "hp4c[N+q6xJCABCRcY7?\ڛ?J�fl&^ȕè\X,y)7څ}0uk Ɖ_</VYڼH/U3q`H~^&O ènEp֬s5ų}-Av80 ð31Co#MhԓWd\ "*oѕbǾ7-ˡCωDLO&ʵ̅bCޢR|̓^zd5'݄>^Ơ)TNq谇MYaO]W? <\jw-xK{=HߡQTE<8=!{禛{%Fg|W7{= ǮUT=l/S]+)۷ݽ<T:||\JĴL!7d/-qLﰕWaȅ23losvh$.g#p$ΗZp֪Ϟc߫Ǔg?"xut6 'Ivf< p僧�aCv]  ͼx`;r1X0} &l0{>(۾T_170c6o>`>+m~Wy(sFS<.~}?f _!C_#/ #s1Fhu\ltl}.+_O4QR}'e[/z)nZ_�?;o7?7n%'3_hQu|<q{1~ xG:y �O݅nZ_'/AzN9{VfkϚEDBbvkM^ <Y_&`z'`\k3U`1�SzSA�϶{wI//}ە`,}Yl)kʐL r )ѳv{b-nQ.u&͟؁2dRtJrs(lpb9&<Z}{x#pc/>L'O0U5C`x䩐c›=cBBɳy!+B yxOaS/3z8 iŦ8m1WP1.dj[N?=a䐹eWvgPP^.s2huL : l<Huݰf  xOunzᠼ0JE�֛_?ȡdnA;O2-ߠFJ%89+�θ\G|E7 o졵k.a'4X|5 $QIN EAn*{:Kn597l`VyU>भDVJe> G"L]OO\kVaz>}+FQzAIOx>=[IϨ3|(wxj>&Z=101p!l"J]jU dyF4M*7 lݲx(~ˊl~+79O"fw/x~-|[ygdzm MCZ 7G]_/3׈?_ yy%˝XI*U8DZӳ73aJNZ""r;ˀhP?I[X(mKMógb$L|[7fhw՗6HrsO"6y"/'Ȁ*q|5?G㲵.,(@6.]Ea^n' ~G6>5{_)"gI:js`OY/?AХ4Y2nnI/ݿ5آZ9ܟO Qc4?6aW;ioNXIƱփ㿵=pE6kxoHvxoRRSIIM%3-' n ) 3Mcۊ~7|;1ʴݥNv6dcٷ{×"ytlI/Ng�?'I9l+9FRJ#'?eW9Xbců\4T) 3I8[~ḑa^Q="F\lT(ODJhDxkjvĶ3n;Zvry ;"mli6],<)_x(c z[ ( % H/ovJ$})g}JLz3j]�~8jG^}Sƻ`F*r]CkOҵ0^zO~CHoZAyq>{ rv3By)5n|t#?AE\OπŔKkAIť3őu<W8ʳ<dLh?~7\ /w WSM}cN?&0far=0 =Ԛ?|F]V.FNsOw$)t+z,^yeqw=I\P>okN+6p` w0}%فW(8&-"!`7u=N %mK̛8:(ߴTBj'G`~qֻwFľ/о7'z߈ȅ9 4z-"gYKRs=-{-̷_woi ,^|Raa<p-RR3m>.+՘;gR3""|�AA l"Vi'[5&pf5#""{ŁHMDDDDDĢDDDDDD,JMDDDDDĢDDDDDD,JMKKOIݜXpDDIMN'׷Y</NӷTcr5#""gŅ_P,rB6jLδfDDQ`2!x^ ]]"(,tq{ -uB?9{Dw[</9终 /}J[3""rv8|Dz;&;'˅;H.ZEC  4͒..F͈١&r -ۖJ5&""b-%RDDDDDĢDDDDDD,JMDDDDDĢDDDDDD,JMDDDDDĢDDDDDD,JMDDDDDĢDDDDDD,JMDDDDDĢDDDDDD,JMDDDDDĢDDDDDD,JMDDDDDĢDDDDDD,JMDDDDDĢDDDDDD,JMDDDDDĢDDDDDD,JMDDDDDĢ gM""""""�6]Ty`ȉHR`(6R`(6R`(6R`(6R`(6R`(6R`(6r6Kwm/,:oqi|v]oưeN\.7`vEtPF<w2ȷ󴨮?/⯕kٷ?Ӽ8aTYtη[DDadn&^\|uKl/<�??>6Zժu\[ora``ZR\NnZ59.C)|=f<Qo})Ub1 w4MvNd$8ĐA;LDD伕|�AAָ%B k�嗾'7RrZQ\.O~=f<͛6믦Zո&A [q|4oڈnj"""rA8a.V, m>ߌ{D r7c|:=QtַӥC["=oy۶6]PN߷eN Vi20زmo1TW=\K֗6_ڷVm9\kNߧAș01S]N۟L|XV|XOm96T˙;91bM>vi^TY;0.'dEMDDDDDĢDDDDDD,JMDDDDDĢDDDDDD,JMDDDDDĢc<&.'(*3=|VfΚ|_ eeJ@Xegyr+́Cp:ɟvxC67ﱏNQ譥|/:1~н5 c\?~3wy߬@"[&˝p9oKu,7;wӹa,{v;rOML䒁C9?DDD5姡x}+H56av^N=^x .(66aw֒{&u*ع/]Lpߵ }N7m;m>yz, x}ݹ,\3}b[i0 `g:I8mYv&N[gHz|s輼%27?Ylc=L;bo'M11۴eб[x#EDN^nc=!~X'Ӻm,+.".6/^fol*rIk]͊t/wŽK3"""Vs^ΰL0<B*9IE'fݶ% =^RR`Z~8^.l/x 7?/OŖke`~n^}k<ŻqNy~ ʅf6�v(ŷ؀5жGB+buT:˥ӣ$<g0b]MB4T=YL<ڋ"A$v+_| oCyيҮZbo?fЊi0; ]=H`)yX5e1{}2 L߇t }ͪ\"u\uU'jdgu)- ꪷQy4jjG<%tB^ŶT7\I9G$pmy5Cn @ M2;'O a vCr!U/x7�o w9 iOaC~mn<ݫgDea;}v"f31y666 l[DҴ[1,ِAYTY !Yhz FH3ڽo|0|vnK&m9m980I*0<sW/đFP_g%US^nuAξ4ppõ&S-#qR\V/W ٖ3ٿaل ')r^ΰ%0s ^hP?H:m߹ xތoLϷF'xd9m^E;@Չ+;xOk%#y{Pѝ|I3aµ\_~o#Vs=1 9F?^xc[' B ד5&e#AmS/۝[ZVe|<>7]Ra�76+CDpn^C&0`@3@)XK#=>sHhX;pkhͮa S,7r 6C"5K ԇ_cI=1*R\a МΗ3YWԪ[h}x{O>ڕY�*9h} ]iֻq-[4ՆM;]T'bXJ8x⪰k.�囤.]ƒ+ө͔T ^كaxژklǯz]�*ڠ|ڬYal]A`^vm^h<k~ΐo0udĒ<>Kg㈭xצhwx&vN@œe+ꋶ5}.!Z0l"vO!뱇YԚyޢƦvY﹝X:m餘?2'nFm0#%&3Y,-<8[^7߭{`q}"e`:>}-L#I/H^C/^~&N);FҚߩABYj-/ J4CP,\�3k ,^=[o5*/ |6<5Cq.>�EAYegزp"3R Ik CicךM4hvm6A#vv{7,`TfM]I;5(#m|H6`FKm}@,6/ʮd_Gc?Fx4Uݢ1dךlI:B!/;/NAzܛNںV.au`V`,'mg溽$.NhM0/\şl,Q|Tf N]G٘h0ضS6cӢ)$d;)Q %נmWVaͺ(G,5"mp6M3y&?}'+&~E.^z`�w?#]+��IDAT�8ޘgblYG5�'#lPb3-YWpY`tt/ǯԻ*~F-ZTc͛Bbr/܂{۱A ܘn/ ]`ZcVL9;:U;PResv'= UmiX9ڱ7byr;sEDUOp&t#)",} uҩ.HFRL+[)""rH(:v{&c?%'3y|/=76L^ԃ*# } /3frcߝ|X!XX3V1X=?Axr[\wdT- fHv߿FF^BiЗ2QU1 'v?; Ytȴ:4p$%b湄x N;Kjٙ$NƎBlK(>sf' L){J^<[긳~@'"G j 2s (H9p0Iy<&';Q,(0,vaۨ`3 w:lMip`WJʢ@2d\wSjRb aZ멂&L3^lCWXIwivYu 7R1ذd]ـ)GohOS3"=nI樺:_8v<:sސ`HSzfArFk;Q<Tta<nvFs1ֿUr{Ɍ ^DDD8/[AJش/0][bbL ڤٻ_>s̼CL]j>,vNÎt-Ay1l< ;~Eɞ bﰕ3f\ v󷵸m$1i8uRΓów.`]I]\5m[-3oFdMXgܒm+lvad"#[9]\܀RNƃIީ koŨUl? 3/=bm�G`}&xLx pq]+^xؼ5m¦H`bX㷦bUT,k0){6Y/ Dnڴ 6{Ŷo%2RY* úue3 f%z !LL:\U@X9?0R1;es7еf.5tqe]P m5ΑNfq [&`3MnmNd)c�Bm;l"""Dz}gS|yO!u5z�f#.): ;6 +©&X;|Xj y${bbʳ'ŞF~uN}w vw~ 22]8p:Y-iٷf9;;d}f7%~[6f>sMrREr(5CiYX4P,,\Hƞ`389P`BHJ?VUYx T xCҨnX0#+LNeb ,i;L+% ѡJsq(5Cidf):ߔ䥆{':dVpyez $J3mfζU kFن%m ;# $pxo)�i]=QI߰0-[W^4MRr˔nj4rI)LI!:P}볲z$}Qσ^3 ^tlG@xFaSoʑ<\e(MNZraN"+^e 9j-"""R ldd5lHU>+2ofDIZtvmIԩZ_!.lC6Ll4$LȪ ͏ $n=9wVf\­ uլ+14E+:4:-Q72cʍ4*e꒷z7w@͖WY!rӣC0BJ\@ )itDպmFe ^ q =Hc%:V&( t\ k`I'[!e_pdC.-웨ӭ+NP{iGΕts)ΐXqҬs 5pſoOtXW`]nعjUIܴnG!Bw'i{uk 6؅Z-[X;eպ <<5;Ub036XL`,.)\GρTz1yT~Kdn:Y/ {V֗O bY'Z;՜lX4}KsJLU[f/Kv{zfʩpyS?([0}RRob;Ì8{ChӶwI9xIowU"""yzKd 7˺P!-Ʌvݴ/| ]L΀&0[mi̜3mVXcy%!s?YH7_Xk72L[M3ڋs+ۄ'mg1Ա!r-wNd8GћLۭY q6 &[ױEJs _[l>Ǐ^Wj?<ى\WWԎyp#)yiͼ +ww'ݼ w(�2Mb~}a;Y9o uZ-90z:7]!9}{@ف4'\UO"1εlL5z4z"2n =@~ǖt޳(߾>\^ M.8bQ+w~0Nz0� ikS|˧j]/ѫozsi.˞y?mpO mi ^`i;1;'l1s!w7DAqqˆ5?OHcg3+Na19~rg % +r7Q˫ r~I6oSZYY"""bd{wu;ݵ2>/c)K\⋃1J!z9dZBB-16ICMҒK0D"`ea${jdJ~a{{3jb۶i&66tHAҾxL)v̫6N;qN�OVֲx|n��86�����:J`��( ��N-aY,MǮ햛Xmۦ7�7{^ޠATO|u|]ʕ/ʗrRY岴N,O36mN,/[Wi=}d>RY>>RN:Y`y`{V`WΟ/[=~5SI~VΞ)[[WA7yցfu<ce �ޞ$yܹ}|\YOe'oMĠ٧Wa'7W:P״m/~x+Y>dy� [·mirkc#KG]k˹Y`GgZYΫ}>|%~;v_tbL+/1?|׿__VUU]S'/en6���l ��V��@G l���%��t��Q��@G l���%��t��Q��@G l���%��t��Q��@G l���%��t��Q$u]g4]���vh4J]ڶ-za!l��Kaꅅq&+w:7oe���v͛fZaTue��Tu=b[apsSh��E3L lmyD۶i&Mۦ6M?H:^W��FwAֽ^ni-)B[$Mc���v w kI2uεlm*I[שRy���LQU+6ybj`KzJ]P|��`g& j3I6��.(f���=o��ޚ6w /\3+g__~5~$|\x_&y[$߼z;/Ŵcٚ;l k-6'[>Ovl?{}� )):����IENDB`��������������������������������������������������������������������������flask-peewee-4.0.1/docs/fp-message-fk-modal.png�����������������������������������������������������0000664�0000000�0000000�00000142461�15223753015�0021254�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��(�����3��� pHYs����+��� tEXtlogicalX�429��� tEXtlogicalY�184w~���tEXtscreen�HDMI-A-1/ �� �IDATx^w|Tם׽3Q* ! ѻ`p/IqI6l:n/f˦90ؘf{ {Ѵ{ 4Kx;wF9{1II6""""""""Y """""""r)@!""""""""""""""r)@!""""""""""""""r)@!""""""""""""""r)@!""""""""""""""r)@!"""""""3@DDDDDDjQt3-*Xں-6="Y PUf;>kz R\[!&nL,\(DDDDDDt-85pRb)@!""""""""""""""r}.#adUj,'#:\p06Xl|i["A& 'h ə 7M^Uo.,OmoۅeXu)Gv|`B. nN̄޲`HZ<CF2rp^}u8rpf1, ֺxf!14փ`Jf~lf,l(ohcU�B]<Eoւ$/7Exk"[\wé0a$*rgf:C'p H4ȝ5\}ذaQ쎲*mr\ L({9XŃEA3UFvfBn-=t 0kBfT]Y �xc_'[_#]3xf`Z, ֯G6tV3xp!{Sjj΢WV<ÔA&i.j"Z6 ?+CY}Ij[d�7i6'dҝ7� a-meÊJ[ˀ>vnY% \Y�y�t7|c]j!sV]#+,54󠧖s>+e#s TW_BM�IǍVC {.9\&Đ?n*A3 3UgN[ 4Y}QibQelٷ0�`w"Àdzɼ? lZח Xs#bsg^`-i.6Mg8V |pwr(:ǞVw=Cd)doqk6h><2!>Mmv~!u<v45~fmtQ0}R1#'Ng`U37tik`{Bކ�߈ |jV&>qcא30& |i+-;1`A?\z 7QBk6^J6f[0ϾD'dQ<i,X>:ѰdLcı-b{v|6[va;2 8;M-l}w%�`卦-f}I5_/nqY7N'=o4v ٱj-$ {`~ ߞWyL#gL &-uQa3Ԝ<i&r: v# r55؝pㆦ;l4DP:q4Ϡbۀə&qna;Lf2e{Tos.i.0AE 7uڳͽfM wȾ{FG֓>d8>#Cu+o6\bL;}5];h2�`Z\p 񃣩AnKprÙ0dpjDs6 Eg@\]<X}b<vqL=aC%xhfEBzg4.crSxY$e=i <<3qs9Q/"{x<`R^  !}o7&`2W QferCwb 6R~4|#72f]ħpIq18>r;Q#궱Z 7s#�XƺY~=v>}+OŽ[?BrV1X\ Nw$s}n\!0ښIIKq̸΃˸p/X 5}/NgĂ g< 3v5I7qm=؄b~c3|ymx7f{l_,w a؂rp}/O/aKdAV33=~ csxw~y].7vxI{3+ ݆ΚgL 7դ˝E{M g`>43XW9iTHO#4(TMT �2 ZMS^W1*QB)ա�n[70gbcY {֯fL| c?ȵ�1=0l`U-U!Y+' RFz *Dwݐː)M,JP0Oe8&=>'< l4"ʀyI#74UV{kD9a̞k13 e0G'5,`vmYɸ$SoXWSfNI.z'ƀ^e6`A;c{{H2}0BF&2Pc�h y:b<ǸmzI22dǔT)LI;fJv֊]%ˆJeX3F-ضzSp3#?iwp&qpB3%^+LH!?+fXG.A&8fc;wG`8Nl`1?/ سS1Sއ;1Z*h%H`:қzVUbtL=i 9jw6&`YiV1Qغ-e.z i_u':9�,MV8!ضj x+pcXe[^Y yYlŃ&sӨrcwD6'Հ|l..ܚޔ\ZZm4c$ZG0}Z2SuEZڎXpR.BÛx>! 0 ,- zػ N d?Cnȥ֑;و\l1yqN,m~<J69DϞ pi?}`%(Q` M ~D4ƛ`wj\t'=#~Q:FB1 [lOi]t.`ܨLoXwv#(70QcsȎ2:<θ꺂S73Y@a->v%u=9s2:Ή}ǭ`4Y뽝؆twŁwW 7awװ&݃chqF\t PXƊXu8�%w?Ͼ�RIނD&I2#QCWN�ּ=Cr0 +Hj]pz #Uغ5;8� r5<alH*n==@꘏_b΂hcX+9[Qo¶@�BDC%'qsg&&Ͼ2popOWy:~201 :`Æ][8ITszJm %`ӄ, A8Gن3! / Y 0 Pg3 1D9 z3(B�p0+�gr u@Ξ\|Tuٌ!5g(F^܃rD8bm\: 8qu46Ct[#qydML5=zGIi&=@KpP&>y T$8v& ɎݘƦ͆bN\>.:5뚱+_"([n5?.)7@>'eb, 1 /j</i4pԛn\4[lMhRߡ/Qi:PY)ccp, hﱡGj3~Xdê;il XGL/aX{P]8c &vSyRcp90'{z6#>QMO1�h'�>jp`+9i&2`?|4 �3!ja3+1cƐS8Õ@ ;"i##(onƒ? seeXҝ`dж {'5aY r?wt`0q>6o`[pꇁa5 4x ||jV& Ho3Bˆ ݃謩Li j=ا.$741A$ɅYzH8ęG;kƐL8zh+pm]^n8:̳'�3DDD3ߖ #EB:.N[um }EDoܳB^|n� v0zo#Au/ <ϕ&لqŬ>vS?m ߊ=3bG>[~s<YC(Z- [ދ&�H<0Pq8%/]4)\T_~ e2� 7v8>wapZPLΣm<>iQY0i723y/ {#Spz~_i~ޗ LQG!!ټ\n`r 儂icظ%el+9#u0oY=8gsPF4mV6[n+* �f9i&e;y& 1)ߵ׊pO!BZzM, k)ف1z4]/� @3.*'wGC!ýEP3mlh Mfm)G Kv@Vq(S0fvrc۲ fwcWFr)8PR²/O?MC}=Fxj5͈&21b0zN_~aXDCɌ. Q;`D"6aԝ�,Ljr` 3 )&iE Dz#Fegtv'҃qZ|h<3H=XO-`�nCLT|[k6fOO3G}w1` $T�`9w1q&hb: #͵o26�`;:m˜rHp;HIN"1`J Mɳ걻J�]mLCdRU̝6 #`F^, ́uV3yE߶y&̸ewwR8sA~vڅ7RnΟƒR$SжQ$ 1fCC<1kh,Zm3RP ~š,h-`!MPưT'ѣƱqm9hl&PsxS}];EE6BoEdY0" )8" .3:/`'I6'r"""Wq?n_W'W_UByvwf _Ǫa{A0c 7ߚ1a#Btpۮ {W}̛"ANo,rdAlp OG%ͬYX},p8|>? NEPD ƈ.$�cfE3.#рĜlewA5|2!+EM~@s3?k x&p(]@8Ȱ(7!P߷# lNbNw�ylߜX Yoh<݇NFSLR ޱ 0x6<t?e[!M5k l^8.ci ^_zd!>#}ml]V3ovl3MNguY kTW0g,ݴ,/ІW/{!U<;*f,l*-Sn&pw@}59[>nG][~m`Ci'M,1n> ~v_8jڨ<aֶZhl#6m)eXN `9MǃG}+ZmR _~>u"""rq\PBy&b&;f'1qFaW'HQXB{pg;0RA=s Ttt5y4]e:B|R`t5"L{0bto4;'ot�B>z6=nL,F&p: hn6aAK'ol`҈av2(zG.=u{z}(L9>nLN <v6`³M<28W.gb'`-/#ׄSfp0iY0o!(3' g.6p3({`ď'?od$/H#mDz(]Ivz:0F(nCpdP7c$ _c~Pѳ6_<'L>hJpdAM%p[=$\AOF[<_x<h? #ggS?.l-@yM ' [~ԂrU/ {۝P[CEVw9/J-?J,eX޲U�}|)@ŔtڔR eFOd{sG=p2O-γm)DҜSEC{f_uO 'g?)_OcCÉ;c"W-Rũ;쵯ǻmXY!#t<�=?g .lO;ĶJbgFVfWz!M#UQ əC$,Iz�߲7=KRq9ItC>;MGcGǮ͇ 5)@~dk,<G6;aˆC꘴w=)dRɮshv1vtb>s<`DE);|ffFG{uXl[Gxhz͵ܟw ̟[=`8*uKV3xC V)>jXiY-ӆ-ڲYV>v\.n6 eriٶ'}T:DDD2.O<(?{h\ߝ~soEފ3TbÄ'@  soY6t?Or[q![[^x8 ot.R9m|Odž  l7ˬ<3�M5e Tc̝1,/aKt6bY~ZA[E햷�$3>lzBN:!֗6%)lKh$(i噷gkc*/Aec*r/lA׼}u YtwӆWh*!8y[yHo,aBc1ǁa]@(I3bpb�L'OW+ҽf"rX5UUA!""r  yD.ƥE]P1C㉺a*F ]!<J/v_ٻ\(Z!"r>:o\?K<⻠K<DDDDDDDD·"""""""r]K<l]]맑U"""""""r *yx^ PUiYt͹^ �Kqmx=PBDDDDDDZj-BL"""""""rURBDDDDDDD.;-92H."fPe2`/""""""fPd�� �IDATe�\v Pe"rBkt)eeC!?g?))]{復'>y>OGV%�\|>a˖>KC_IyW�xHOKh!""rvկHIM4=ڲ,^zE:::x"MD g N</z6.?HOo|,-͑"""甚JüXYDpj+"rUXn�S&MdfdMsͯ|Çٯmph`0HDD遇R^x3),矧Bx&""W,gȑe""L,:/m:×Yӧ/~@0ȟ}WxZ=}:O|dg;/-/nlq򓸜Nfr m|Q�6. V.Ͼ"JJlCEp8{-]upݽu7̛_M>zm,[e\.O|yg]ǤsO䭷رg?_N=i|Gx9R^ ?GywG(^Hy9}>؂}XBD OgϾ}ص?O|$%&g?>탡{8L/[6LVff>Hw_ +~kvï?5|8 MM9@QAn98~k N'~C<ȿ~[=S?)_Öٲ};_v]N;P�0ԉ-Ha6=,G++/hpBDRr>padYt^>On8/+os;3s&Έ_ٰe G?bĉ9z/}TTV߿?ToYO~{x^ƌ|drwY~=֮?99Ϩ#$/{�1iO~ >232"z\{GO?,�Wyc# y~'yrĄd$&$;8g_$ raJ9ΘA{#"A.'E_~k>Oc;_w< +}Oe|SbɘIСۈZwș]<z7ppw2w,�G<n5K</~Ѽ[1>ޥ3C�p8g?˿|ӗL ^S}_n>u""r~L䡇IQYQAAaN\JZ!"Wh/O}+W䭷شm55|[ɯ}G?QZZŋy{ժctwwIGgg2S Çp\5/~c,<e iˋҥ.-dg3ivŗ-ΟϜә9}zo u>%Źrl�\uxp"\J䓔>gs睴-<g_=>I0]Ǔ&'%_45M~˖t83kC x#~hO/,_f rsrt]N PȅgYVoB̢aðm2^|G4BDJ PQ~?| Ǘ!�O|s~vKС?яX0o^y.,^ Y8>�mm%@_*mMXt)kʪ*x]Y$""ȉDO&,/+;mw>D玎ŋyybV]Yy2j6YY#sS�E1#/)-ogEy``;X{ﲎSQv_~/vV7o? gy|'�TTVRVQ1"""GdpD pя}=3l-"r%SBDxY̟;7<K465w�ߏ~@q0M-`e Xq&?qx {O=EuM mjZ~?aRSSH:%hw~<Y<seY}<2N$_磩?=B y9WbwbB€\xPxU/|K_@I )S} ɯ7;vfמ=g?~ L x|7SM?t ?w..X�Lrsr_?7$+33;z4S'Of>0Nipn.a{?@|].@휙3y|YdgPS[ }w{.""r)/y&N)N2^yezf""W$ܹs-PDBx<v̓ IMMe̙|f)9N'~;11477Ett47Lw ޶~9:>e S&Mp,x#mm )糏=7UL;}Ivv6?1v80 n?n&z~F|{Inv6sf̈k54^G{O>ɮ}hkogޜ9=0uRhjmP(Ĉ_gzB!~?�p73DDlܸlz3'N0MQFQSSemk[ow<璈dO}ȇO"EDD*|b WKD N N Y_vdH?W/ٶJ"rNj� ~ P(ZN F(˲l۲4Ȃ`d\E ?XD00L00[ѯ�EȲrv#ZeY 8{>l, ˅#*y<ݑE"""r!>..XD˲B,p lÁ`N>44q8zzz.ٔA8 X\.""""""i\.bccq@`csN,�p:5BN~߸ubxMDDDDDD.ۍ  hw�M0rEֈ\.+"灰, ,K Kvebt�Κ/i=M8m""""""N@< "E}߭pDֈEp8-3_w blL K4M~' kEDDDDDDBL ADDDDDD.N N 윑~ͺk"o -xmĴ㷏̞ٵ<6kcr\5o̴&?]m#M%|"""""""׼K:ذsfgfd Bn|`#k wp#o`OY$"""""%akYwp!WM4V>pFV_ czpGVY%EqIAdn)�wad*;ClߺR\A̘1cqyUd+icx/0;+=ֿ>|8r8di ?AkRmeLBgSqfqyi>l[:X ?ãm4*<Chl-otV|L5S^D71&}t՗ fŝ50"_uMal Ϡzv Ч!+IkNr7u=l]\|-¦�y`9VU�־äI,�[l|gVc# R &eCY#W3xd1 8 ƌLjs|X]aڷ0;HL-e4yg۲1qIwZO=uΠpSgα�3{>Q6EHVauV,_uRӵ靵揤E}m1!zj4!~HJX]eLL1~m]<@*�Mi '1jM̎ikV)ȃ6 *&/XDbǛow7b0[G1x}xya5l㉈\.i g$j6ж`KvBUb-ؖl B qsęEu1b;k)H71@簁. ;H~Nq9&GHa-x7lB!#�Z`iBtN.`dg\6-ݭPDG�(1B6>9DDDDDDDt9L<?V޺2w6l:̝3Yx]{D8c%v+y)`&9)<0ΜacmCN{Lf-w## <@)c+5Rl0xX2v7VARR |"_$%aNuC N !qd"*!C ـ}OH6LN ĨlHuq)]DDDDDDD,. vs$w91 %�G"i^pZが!1Tء LļcjT#Elo.x54bbɱ4Q=Ew%G`5 ?1.Kf1{dGȺ}8ƎJgD"""""""qYfP�0a0p02`܍ gQ]NY`�lb %tu7O%..P+Ad0+My4W0 #f0A'0۝B{;s|(1o#MC} Q^RH[�G"""""""rv??S&؀mtuuY}Un ՄE/-مi;4Л"ex0 8w+Z4bJ|_'333XD_q\]%[%s'2rbP`\DDDDDDD.k6@b 7S*AFMCTNds� LʍcRU"""""""rf"˒`dG>:#ibd9->Cʧo{lجSDDDDDJrv[6meZ?`"DDDDDD P\B e`GV/KHPCDDDDDj%"ء&)m)#PՑ-o_OP() pv펬)@!r5YR^F 8;PUVq|כPȢӃ0ǗH@ OHЄizKe`FV嬸VuvzpGHLSpBDD,\.' q]tvz"EDh P\[,>lPE7k";tU~vc: =*+nC\ qXh̴)mG e`zv,?|Z8XNUe9- }\Er| C2SOj0"ᷡiՆ4H!7#QydzEG9DQ_D P\&{X-<[ɜFFǕukO.0vWf}qdž;j(ݶm}|ԷuSGy fLާ ڃZO^>u=k퇎R7M%&k|v+ iY�\NB7:DDtZ!r $ (SJ,3lБn]T�g.t'"Y6k+ 4fgKniH6p ]xɇ ""r}Pdgggdp8"9@ edeN#2ViCmYyEvfػNiyf~5?;8Ft@NA#9`J%QgeOruuZ|%{m_[%{zWkE9p39hts43hI03ϫS{Xh4~aUx/K&_:/�(~*_s,FP(LM^~kj5?r%$=OPjˬ :6 D9rN%{UNId;wTx0s~=^ 3|m74Ĵ| :'X[5*|-ܝXhlpc<# ^fM^igʫ`. Tu|."""""N4Cd"&)FR01g_=: :RK6`Sy)w4]mL]rϳgnſdnyYeԄ)Ff >p00� S`w.5KDDDDDۚFPȇ AR/Wk*G^>ns&vuPlUNhN?۹săÀGbKpphO>?\RD'!;P(L[;{#ڃ]DDDDDޛ ufr9G�36Zg}`U1q{ PYLBa[gЪ5 m*i ,9D(LLM II^ ˪"gzC$6JA!H�3.@~�>" d B^y1}CoLZ09<օ57bne!M4 dɻm6 d$ `4C,^7V[ąIu yܿ>17IKa^69n&%sX׺ (DA!CU7 F+ wP{xt 2 }S2|aڻ1rljGBt4w=@BUQ[T? DDDDDDhLuP nM0E1khŀL0R;‹xרX+X'7'aInDn F>?* , """"""nPXpa[iZ4Y颳kS+AJilz VgX9@C|k~8S VF/d©7!>;c|w${x`C+c t ! ߄^&'V̶`$Ŧw֎�NqGdǵ?vGrl{)sAGa  p4MK]M ?񏙛?o#o;l0" bBEcuN?E, (/#K@$#(,@JJv[0cIp- 7Anr164r NsC& l4h4ʟv(�?v]EDDDDBdܑ+؁nt8ۡvk5nk>M~n"F(^NWw hMjg5 k&N�4*? M+5KS <Jȝ9P8YV.̼G(2y|*mUy {J1HȮ`^Y 2Rg!3/\Ku0�8 -ͭ:>pGޙe~ʄB!~;!33k}-#eE__Ƹgl\YnZx<Ip*6]䓠 \%�� �IDAT,n7<pE57f0o&yM=b &LB$69~-$;"G2ݽܺy~r G*V&4 ̪%�)cmz75RSR�/žFC62˝dV}CEg @yy.7`V \Ejǡ|;[fU-�F|aF;Mh9FQ\|v)<go㗮b\ AK tUmdet:?_gO}"""""rX&_r,I*3XH Ɔ<(*s޷?W^ȪLעm�[>�,<$F!)5 ,1ć{sIȬ[U_/I^/posͷa)EDDDDD 6:ǃKdz�Ź\0ٚ<8m+qz3Gyc J"22Y24/psy+o$G89H;eawu9y,6/p apoz!&<9% +sٔ[FH<7oB(vZZ!fn=; (./$3|p^:ZʙdNv`wi ⎅{->V!Νztwn'z7n+'lCxСUX-� Y /rz.# clMwgm;xs fylKϜ a[YyR3Y"GkXNgyBm%gٗz~"ɣ;+83M <򭌶A-t؋~s*iK20BZC3WnnpM! ;_{�eY\nJhlO︓8^/psN'F !e87U8ӊۮ!=/?B[zڙƿ0K4n5H$FUqpBDDDDDDf]e jOQ39{,@y}2K@~x*\= 1;7,Mm �$9 f '#c(ZnˆX5᧍L!D;sM*qiS@f[;YJ4gs\/oY-9Z 2<>]j˷pÿ1nO`ou.{s[Z/IDDDDDCY� ma92NV&ΌD1_n8^!sX-._!Fe 0tN�LS]|`}YLN22 � -eņb`A` ޕF&gx 2~{PŀQÊawbj�m CS ɤgӍx1ᭀ�L N/2w{QML|EiTfw u-1}H_0yL>UIOy.5Sj~9a2fhT$A[64wco`1x|D&Va ,("""""""knx:gٜDUYm.̥U}|&x=N斢KɴΊ|lY4Ov.PSaIa{f"G85W .$caҞF"`]$cMJ^Y,�3(E{~ 9ڬ{@о`ƙCU .QQ$w u[f5(̰Lr=$001 iFV83e{2%&Q?y$q8Z,`o8=ȁRꥺ D�Z}&^擞QLŧ+sزU_ͺNe΄]e, q/D_jE ?AhiN6ʮu ;~h§ʪd"d6ZM78\UKtb(BN6rI͌ ƆILZ36㹦aVYBJgh?@l_z񽧟~{:@,20MO.^oDZ "Q؄x4;-GyM ,ڗ`G&z8 qeg?a|}v;6$S/Ba|%+++,"&El5=m{ۀ/oϣbW2).J*0!<]Dցic)z*@_gϑqM>J;Em ڥCd#$:!Af$z)"wѶJ+$"u' th]Bp"ro"r_Z-xX Y\ Dȃ�V+M#'D侤BD+Ny|iLp (DDDDDDDd) BDDDDDDD6 p (DDDDDDDd) BDDDDDDD6 p %B|IDDDDDD0k (DErc e$jMdwI.%5gք\٣U!| ۍ%zUzy~(DJ) FJ|;R@!ۛfv7h7<{.M^ ͪ;=-|\VHqz8VE~.u.b㻊[4BcVm繶&Fq3Mo;fpRõؓ Z7Zk '70�LN\`az|#u%8RK0 An4_4iNv`Ûmv&Ȏ$j6CB�Q3;=B5́4+jNmK [HSg(tY#"""""Ah,�enq]Ì'Uq 9ɛ{[~WiL@o=Lh B|.H<<LB_]ž9;D{ pN]icW4qh'22塬a֚/)=uVb|jj""""""FP|�Vp Î'}7WlBiAc]<OLhitI4`ز&e1̭ L]큨6`U.<ҁѪj:MP<\ܓ_& 4CJBܥ`uPSk#'`{jeIaxsHJ7C8"""""" Y pZ9ݽALil@U&~<D2(ߔMY3Pn`?0ca=0*ke7f`( ۻkl4ZHtC/^n`~n!"QhS?hacowY+"(8Or {|4ԶZl.. ? lI;H \ ny"6!0bݹ=v0z nCĚȏF+W1jp""""""֠@XM1\9Yj289p xu d{^_VM4o=#@p$k@L.DH21n=BnLJ$92eg!0ÚH0#Ttą!"""""a(-E`gda{jā2Fbv ql'fiiN\h.MiyyK&&XˀEhfjzmTe`ϤcK/^_-A ONQ#Afe"wwpL'qHhhL GDޗQΟ>bu\64^_*٫lrF^@rt<7Ü;ׄ+KaVf;I7i?k=E歀<hx&nc}9TWlvTm ]'"[<D .˫/$p|K!o68r `J?VDDDDD3wNS_aiHzE>2 x< øcuƭp(ou0>>ΟeOwKVVV|YDdM|$lkz[?u.pL'f;ՇM~ɾG1w%r_/=о+_yGP5%o~IAKydo"f 1ȓG_=߼ϟ{Wpql�~cu~$߈oZEDDDDDHfc?$"&45a&'VDQ^ijbiymm+^jlbߴklq.uu1%kZ]DDDDAnT9t0|w2qhWrrS]K4p@d1t!4+gyh:*'OLL9: .ٽ>ζՃyHlh`WY z{yP[@brnZ &pgۜYŋ] ]/IdˣfľBrw<˽~9PޣGtUz3{YR#^vÛ7ĶmmkwᵖR\.#a.vvw4M^jl-[8e /~EDDDDTP�Te$`2UmQc[ͤa>FKBVa2ktw*I)'㦲@љUFrsOOX}=/56b7" Byl)*"W8y9T]͋׮wyp LNEDDDDdP؁͛s]d͇ǝʭE4+-J· < < 48R|wllX}lq܇jkXXZOϪ>o0MVT`q2.|jO�8VW7oX^^dC;KKIv(Ƞ<;mS8r=X۽<=�wBJe ׻1}}+}=60W ɑmy}G:Cca."CCMLpTo N66rxf Mq񹹕>lj"#)�WVp͕>HW9eJX}Z]DDDDAیb�n 3A lt&៞f`iz$`.s& G0E>uk_(m##|3f2s4yeib##&9''bCm v旖Ο˿�5M‘7ٜEDDDDtP�$P\WBכC�H--mzwFr!v^[XY d13@{D)E\iф3v.p䭺ˍ|qcDC ?p55܌o;=Ɇ~0 ~7MM]s}`< 3ݜll@UOq&ٜEDDDDtP�TZ. @ld7=rd';ٱKr)�VH.-\Uv,#w1{i1p&fi2v 1w\MDWd&%jWYɆpjk)\3w  edL%?=>qWԎy?v_ٺr4kš]DDDDA.׀'6ѭɕQ WjwJ�UA#+5, ~N^Ɩ=<e go=h|rs)k_ٶ- Vcuulhep:߲~~ظM.,/f񽧟&y>$7Y#30Q?[P,`||?"""r~ȚI.#(DD>}O?_D9ėDDDDD8 (D䞧xO>K|ADDDDDDDd) BDDDDDDD6 p (DDDDDDDd) BDDDDDDD6 p (DDDDDDDd) _R0$"""""""YS@JtėD>2 %yhl8"""""""PȆS@!"""""""N|"_^|/2,"""""""wQSƗEDDDDcmFED4ddėEDDDDcB~:C"_$1oG|^~45)e 4y;;q&$p'q� >4yyffF9Gķ蟚4;_ԍ7 p}جVp+xpU(⏿%JV#"""""܃d#r 5<V@UO:4ݿ;6?ww\G@py ?=7wxg[aچo|?yu~qra+S#- /."""""i=(9Ѡ}NUR B0J.j|(eWZZX /} fwbW:o?b�t�*7]Wpsp]u-쯬KW'NJ=cafd"F(wLӖT Ì w.=K̢͐ &hZ,%ؓ �V|ڢO 'A\,}턖sYy2OV`0okmdOʘomN4rbeg_ @(b&�'&(t%X+'$XxΕn'z)ĕv;KwȇEd%M"�̙0><B&7 12Zr9_ 7aա�XçbYkb$ gu5SwRTC4c gSʑD6mT fp(b<ѡf>WÑ\[wҀ >P$wzɟCV vG """""uA`©3�x T䥑_]VO W?,i]ޕ \_uv#8a2{Um}/rF*TvcMMg!ek.f/M\c=;P!q4 ~'N,0\<XvL(p ^k=e؛k.^`sݩ9 9{k<"0;c^IfgCHq�1ҡ03]D8Y%oDDDDD~.-; I.Ce]o'a<9ۏτSotq${ڱ> {{W$ sy ZI[S07Atjd2;�t@r(l\0+ r�+bfd9'=Dsa. ,%JB4 f.sa//D;;>bXS!-͇n^{Ec_?x·}'O[ǎ1:7dz/`KDDDDD}P@�^F*uc%koy|yCK"&pbRIV,IF(H4n�5W%SiBߔ 4s0mn>Wh'&9?>ɕ|f[!JN-ʯm3^[]2P{੧'8β2y8/755M6׿<s99.+ZwwDDDDN�� �IDATDnE<zL@�l07iގoOBڒ,2+�G3?1X<'zZ8}N@q?sUSD:P E2=TUaIf xjS 2?K=Ďyx\ofn$Ky}-=6$ 4<,#[jʐƍ/] CcaSmxCU'pҒMĬG!mjp//VF" +MԺ(:åbϟco.Kё.*˲)f[a6И@3eOL+| �6R 0??MJ DMbM40G`u5W~ȑ ;ZoZ,VۺǶn]Uzj/nX]ݪ|pP�,-E v;avڌiҎdh1 7xшpϪ㦣p|d=+$]ar8ęs& Vj\0YfßF"R{d/Xӈ=}$PٙAؖQq`QM=.!dR8p Zn&-K@ ߉Ϛl9KJ|wyZ) |: oP1h(7UHԕ١gZ۽%D]YXDBپ9) Z^ĆMh[f/4.vNaF7e@Z^.z9$žl2 {=%>oC k,t,S`RX,iTx`h3cCg)* :cᝅx% NMENF�5`5XqcLc]l_5�/PW4 zBAy},NIč8VfMx.Dd-v, Kb)@y]1S=3%]ŃT&!//xN-yfM=#TjT7:GSF[ K5QٶV.F9LNV^VlCNe-Ŀxk-<F4fR('J<r~@ �DDDDD>-07[(Ymۅia^rLĄ' f�=nAõ|#]&3d-k>ɷׁHCԛ|9,ܚ`oB Q\@QE 5w,rsߌkXb߉ 7^,ۓ-.& թ+=^=\ yb2sPiA)xzToo�پoK|�96bxdCg2:A]j˻܉u (�vv/8aKE &TZ۾ؘ� Rp, Mn#wm{9<ciwa�Jbl| nnf_=AW(ky9fޑb|^;ۻxd{=Vrc$:׍=. �ۍp>%yXln�"k=55DfVj!,Irk;@{�19oAg}ε2hX}m""8VtgPZj菈?:βq*-ϧ4ť\/Wch$:ΤaR:ޓhkq310ީV^( `cr6ma׳Awv)כ(oMFql{vV tLa ~ËbD;U>B3%籤j�e೵P=DDDDDDڐb5ygH9c_-mD%Lyn )eTu4l?OaF"{ 0<psCl)'[.7"v0KkWףф tV0<u$-6HIA" 8ڽE;xOiL7Gd(/^6,Y[ x< 㭵A>BáM_|deeŗEDķHͶu[BDDDDDDD( akPHL>+,""""""@ p (DDDDDDDd) BDDDDDDD6 pC#2;/ 0ǗDDD>2cwO$O|i(K/{r@,9".4CDDDDDDD6 pk_ ƗDDDDDDDD>2k (\Gf~a9$""""""M BDDDDDDD6 pkZBDØ/BD>v%U4CDDDDDDD6 p (DDDDDDDd) BDDDDDDD6 p (DDDDDDDdíK@1瞿Ltʪ ϽH<X%y7ȀŒ/=-!Cpfl/4�F&MIS[EfEQ:GYf$L qp)" """""""r/gFPͣ-Zjݗpe`0\;Bsdփ\߸r(i~vڋ.ZȽA ~Sx3qcź}3$L{dsº=`ICE:Kaad 95`xV[dڇ;,⻭re?=K6|});⻬ (\@QE 5w,rs`~~q.1!�b{fP<a0XC#X=yK@a�fꕦb@}f`|W"|Pj!o>r� ,D6Z[3τnN/9κ<-,`&%5ȂEGdO*FY^yM-Ufp{<,  [*�a{g) @og?LZm=~ (K&tu!RˁJZ x똁9SQNZ^_& GD#4_%!8dv?|pr0ɑ]U$-O#`~ ן\"2߶T_ -[?B&RT*""Oܧ>ـzmbaa95SǒZA:Ygra NJXsi܂ony?.u2&XT%K<؁0ٳt/,v5_^DE"c(-WnBt}7FxSMw_P $<R$ʛ _y2>HwëDS ɫNF QN3321Y7ȹKW_?nA]J_`|=I"rZMc/Wo|d47ÃصQhfOwSc+rlc_-mD%Lyn )e[1wy!4DӠ{^@w'T,vMI2LX%βc<2Og%5ws"Jx/~=[n0:ݔPh'?wHj=x'^ ל|O"+&§?HJ ?0՟Aާvc$04Eta N2abt"R[csKnWaw c &IJ,u||nS}=U~=um[-Ks@1g09N}b6H UZﵺpX4L7$=%�K*Xڰ.jԤIr�Reڅ1|cʘrip,ifNMPgrCsg0̼P8{SP:sa  !ܳla'�$3! QT^L N3})TKCɐ,\0x-�Z4j8w6\FY$C_Q9WwlZ?O7I7$=b-}!kMă LB2(?T2箆v]۳}w^xdCB.\9yKKHP_G[I^6ቫv1GBp<x,$)ÏJzPHH:R!{u> i$ `822a�vd yf, 'ޖEDAA^ek 6cr}A)Y:PT$I>g\^)= :C|,AgdHB+i¾3A!3�tt%!F{WZ ˜˗Q7}&aF_I2e" \}zP"52wJM`=}YzTℱ1$Iq4udNB7:Z'+ifE֋[:O{[?C1OVP;+A {{8COP�aE\<+wShb(dS4Jixv>\lbz1D&LcjbrW'I$I '!̂YcS [Xҗ-"S 0LE=89ƒ^&Q6 *L_=Y{r/o-cIN$(MׁE@u}09: IcW&I$IO~p0 룼,Zz`zz{)--[<ө%%/gx37[$I'bUImS6%}9}sƏ6#/ft o~aΧ-wVI4SYYxL&3Zol8|K/fFΜ@@n$= ($=Vx\%PUYO'IsdӘvA| \s%I2V,]s% z̀BcǀBc' C2 mpI'pdo ;S9~EX`Hs.{AfNw�(H$_痿}fPQ^Ƈ[0uJ=+ZBii ]]sN�~t._ǾCG`TU208CG8{_@XrfseZVܶ*.*;Ļnz3n >)oZO<g9r]$=̛sCz(ݏ0 FtGAPYQik-O$9v9f`z#~`Q<_ByY #ߙ6u2]^CG/ޤx oL3kWqZ _~Ŏ=ٴ~ %E$I.=V^NPo_c$qV-]p:7IR6 I;0rHӹUJbz`ߴ?w?.9zh3 f7g&G7p2M4LB*̘>iS8s:n3+Wqe2 MgÌiM?'ISTXHaAW^odn3I#RiV.[[u~SdYf9}|Ғx,hhydYREUҗ\|%JKXb)\4A0�g]`E?LZ>ݹE(.*w쨊޾~JǔΖYd!"=qʋOIz aȖy훛9ҘCar)ݸ{ݺ$=P#ϵ "nK_FiR`\�6ظn ϥzCCMgJK DnF" t^0v"/>n;rKq]]:r׭&}=E".Z@6/Y[םv-w׀"�"i|*I(X‘opy,Z@k{}}4LBQa!N6f9wO-^;. @|R_Ǖk-lFuU%l@Ww/ӦNZK+55Lĉ> 6N>!^vJL: 5գew뇖.^@:?ۯG?MJg(/+z{lvt}k@02#+ $ 'gN!7QXP@[G';v?ssfO-Yl ϕ?J �k__d2|6֬\KN:=!I0 ٺ}7hٝ /l6ˎ=F.]J_?'N5vrJJ9p-[G[W?} !``4p"d JQZR[q-B~7sh?z۹Eq(I_OK}'{֑ruBJ$ILPFS$I$=(_:4VWMjDO@n$Iz (:G*KsÀBz@s{! Ie^HI$If@!Ϸ~c!I~ẀB^qaX�c!IʛGOߐ1ԒE#xT.c!IʋGOߐ%pQxԒEBDd!e@!0Ջ,Iׂ}$=N$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3e2"I4 ($=Thkr%I#5hn$=D"ѣGs%I#ѣ$bIz( ($=Tڹ!$=b2 v0J  IU<'L/?yn$IT2I<ϭ€BCWVV#G?#)$Id2GPVV[-IMW?I[(=.B Cҩ%%g ֬]ˢETW狷$Id2\ѣGٵs'dpBO,'IzXHRl۲OmƏ6n-x$h4J"B Iy`@!i\q>bEE<^$I;($I$IRPH$I3$I$Iy;(7!_s=7ao~W0 v\S$.9A_y0Ug>a3+!έ$Iׄ$k+:?@yhY>8yp`sm� r{h޿%}Cy1D&VK$+p$k;kWZ09Ɣ) *)c ,Pk@%wI$=A! ?!}q^X39(ix).KQU3'lӐKY?.εW+(^z&F$WpH �VVEXp+\r 'dU{=ћa߉Sv]*a Z r~ta %WߺjI$}ގ ~]"l>4[^]3cuN?02e`U~g(ܭ;e|et]0EI&VAA7G[}?^9k6s3j|^m$aޣ(V0kZ޾aAI]Y8楔L[9fݒ$IjA!*2k!AIUqE9Rr OSUsίYˉw `zoZEsW-=vIԮ^f=IM8Od̑d)n9˺ 3J.ΝǩW�*Gw _`~Bde t /4H,F!0$Iz (qlr_O]OpӧtlP)�� �IDATz6t_ۀ�dB Þ~ DO�XRUՋ6ȑ+},vduҖ8 @ [WE[_xǶ]}q�2`dߘV$I҃f@!= #sd �c.\,_<ϯgݼ!ϽAhDPo-0Jݬzb޷}WȆχȄec@P`/#!hÍUI$3ǧJH!PP^N[0}mi B"9K˱]̮ʅ+̣a+ JҊ JK y9$97w$vrLyIA qf. )ISQ\LEq1%@06[ QUVL[m\9YH$2(Ԣlضh™N 3Ǩn|0ێsħtvquí*BjR8mïvao MJمo\r:{9rYe4&4K�kjޭY�'r2DӉtsGQv1 b]aN2A:�@k7]"j/fGhI$Μ!=@k'F[ܵ_E!IT|U)3%^[5Č $onY$2;h/g z[T+y/P Y2KCR൥Sv2_%9żb-A17ܳ \'߶x+'R5cN4~ȥ6fe(a8z KˈNtO n(x~H$ON#!!To|o˹ź$Iz {)$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$i|xI'$i\L(+jggnnjg'r%Ikq1#/6\bIǚ$i\,9ξ>;[[8wξ>Ϝ[%IXH|s2>p==,6&Oxξ>lYn$IcπB4n* ,[0ٓ'PVz^Z4V$`@!Iwgt $I$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$IʻXn$Ip2I2&VI$=DD"Jwa@!I7lH A$ QM$Iy0$ΐLPR\D$5p$i EIcD '$Ic*$1b(պ IҸN& "Ѩ]$Iz2DHp2[*Q4.4X4X$EI&ӹź  IҸdN$IOHbd@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRr $}5WC>ʵG{h)bӪFVb&(I$Iݒ�]Nfm-V)o s:J$Iƅc<<KLճh'(H$I)BkH@ь"`i$.5B�3tOPfݼz}bULÖ{ O3*7^X͕|D8pCSVԬf`yGټk #ïKCLL$ye\J={437oLt` I$I[tӦMOnf$=c{Y3-IQBn\c 9j +K܋/Plcb>fΧ=fgyaf,]Q /a~<V,éTEOLdڳoxiI6nr[xfH}'[pgt&Nhݿ*Y1w=1~~҃74$7$IOT:CaýJRDQ #PB$FswzSx~#SyjJ5 y5n1kb5S-za'X #X,F:p%652}sTWT),L3�/egeshL$F<ň�x$I$= >ʒ(@4J6ͭںX[Bv|ML$luX,J&_wOC}OG3E"f&d]U$IƓ@iݧ$ˍC׆)rp�0o ymQ%UK^Ԓ�(IDt$IGw.R8qn/]!"DJ{�ɖ6[TFPU3ZvUTGeyʊ *+*(.)'VT\$I ($�6.p1[M\=):bv19v]ȵnoB�H$]IXm8Z8t5w*Ht .]#3ؓ[-I$IS<hjzm/bw1cB)y!hH˯md]|oSHz}]�WfwWn%o'2tM&dik]m,pzS;([*~fT$Ix '?ޥGDaH:$Z8飸 X$708LeyinX<gF%I$IңB$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$IX6رc V ($I$Iz,�0Vw-$I$I_N<pϟ[p$I$I@8p2f̘[m;0$I$+N0={0w< qߜ!I$IWp3=0|JKK 0$I$}I 'e~c#%%<xL:B4.Y Hpb„ٻw/S\\Xt)hh[Q$D"F:-$Iz$a}HaQ!de LH$|0$D0ds$I9'N`ZLillÇԲe sGto_'c+d$LRVKglH A$  &$Il6Kԍl6K$0$$qDk~b8Ap8IҸDJN&I&d$I蟢%E ($I Ö$IB$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iyg@!I$I΀B$I$$I$I; I$Iw$I$) ($I$IRPH$I3$I$Iy-$aN&I&d*=ᢑDD" {r<sFq͆ DADOlJgH&()."bؓ竞3xHM XD<FGF$HcbQssUIׇ$i\ 'hԮGF"dny=پ9#Iz$d2M,-(LssL_$}PHE&uȽH|\z鋞3 I$Iw$I$) ($I$IRPH$I3$Ie`pn=0 ٺc.\ȭ$I/I\LIR\km%9T* ׯ3qJK$݋dvB�  5<feWw]oCq&1j}d 8er.ka)0Bz ƹ# ;UȘOY,B8t2w1 6oBdZn�\LS_Xݗ!-/plVW+9T^lo/ |zӇvN]id¼@QB!N*!k1{nb}{zLcK?p 7>x5\jDWOv >rlΰk.z[gXOʧ!(\_]~$E hj+7!R<%gM% ns.5<!~;^ʹ DF~pvL,f$.~G!WȶbQMde*fXKbɘudqÿϟFo$=9 (lEM/ AOO˷'N[+ W1qO ]+T-z os[-}-'g{f` ƳoT0%>?{c+GIup;DjGo.4_⻳K Sw7y ;/ 'GLY@gۼxl?nǥ7u5+8xv!<*;۲{L\= ?|̢+ݴ:u{ԩp~]km55U_[mY/;G^dooDWi>VoZOX!(]]eOt< 7r9vo? k@0NѽLR5K|6{KJY Bpm1x{1HL5yo,5Jz4K\sj+f^0U?r H6 "TWV2mb5Z9ڍeg 46YKaUUTj<NO%}PZd1cl g# A&*f֛8u%-4,_Cuy5q mO#|�Ο<φ9gBE%O?5E]HH%ę.^gΪ TULd _ŋȪlze- Q\5f?n'Nݗܢڮf[BEe=US` g[!DkIMxz5hTɬ8!{:=)5yIv`d\ mhGdҜ pUVMR7g-Ӫ*Ya1\?7~Fu5l|~%M = a%e: ٶ1˞,ubL$ !+ xDɆCt{Z \g?SL_[AL. Fg~2�X6&grI2<΋P8c-f2go/BoӞx).KQU3'lӐSaa!zZ%7jD崐܀ps%}{V!p�&>=. tuv:P@au }L"ɭ!W^ؼIepszV"bYO-IVO+�bё]HA|3Ki0iDJKF9܏3}ut)'(96cd[^FuœFDbA@{Iu1˧ůwI^?ւyy]m!g+~t"?s!{'83&!x}K,!1H&D�PLrV4L:tNo]$ c@!=di`h�#, =SDw?%rVMŠj:/SDO ;~b^];|_/5޹_gf4xME&G)f#dXz!L6!NԚ'yiDn}ízChk>K 9H'SQn@,c8I>YK�sV1:8Օ gu0 e寥if,A ׻B2mlii,ݸc ѣ5H%S$b@p90B6I}I�%!BE6N !1vJDe5NxR5B|zz9=98ؽ΃uM. H4%(S#IW)=80"]?Jf1G^cvU/P?3 ˱)sܴ@39xךH ~+KKts{>k*w{ M26>M}u /CkbڛOq=bqҩ qj׾:VQURʢSivDb1"@< y4y+f-'鑧oR^< n+Ͱ#R4 5Q:{Hh sssF~ o/WKr s,3|2Kc')Җ"q<obrNo}Olhs9>9O^(S_eILlS#Zwb)[=Fykj!,[}-EչYX�lUDݯwӿ;2G~gs7 ;]bp3grg24̝YH^QtEW &ͅLfz$IOGPHض ȆP)Y^,]M5twfYtX|mQI-?[}mdeҐ[;\Ow_ @&aptl{i By{gYMl>x ?r77#n[ΰ4<̴//?c]կtF3<zyW<ɏ~NgAp5Ӝ쾞Z"0ˬx߻M۝5'erVrRe3~&<@ِ%^xn!f4Nvt=3lSNod|$c@!=`k",~UD$"Q+=54]mTί $ouQzK)}[ Ch<z~v (N// MKS$ p�� �IDAT)z)kr% L@<Q@2avn5JS)[#nJoke _DyOl8DwYDsSA< K gR¡[g<q Q' LM$~T_ȡ>%P6KߟS!ݧa0ć?g�2ِlS?}?f#w<),)�L0`V~ˁWoeE*L~^y^ z’r0 s9D!|$IO;_!IRՕe~h4 Gff�2cYFn3ڳNŜrgVVis5l ^na8%�R)F+# +("6edHqkCQ@PUMS,H1:m7Sik,&RuQB�9Kt*`䧭Cd;!2;۩-9`^bW)5Zws3ُ*(ntyڪ{ Z/CqOPx/|\Tƹ<\JFP^Ohobae&&yr;~L[{|}c3ђڻi1Gp,ϕfh/~6bo]1R#RV{SQ`ZX^KP6k$=ދHz"@mm;4r{l?Eh,щ^.Վv>̤#̙ϝf%tupz'uMkj JJ**~rr+A&s|߂D@G52=, HM_[AZ{3?A=v8I�3Ne~f7K挶;; cmƝ#%MW;�"ry3J96P;d۱kT^?̄snxp Wl}Mk&,   66'1m-ã dv1sіSt\=Ωݜ޽ ę[V9;};Ysj!(;?>bQb#Cͤƾã7.l;9 TSQ^Nyޝ6qn,$�H-$ٖms=[ܤ*yI,/$ usJnR̽37s=c˖-jIQ 4: j-%>UKt?(cW[q=Uϭ`c.\&SAyH8LM$T5am/՝\JbeTo,NLPųykؙOv0 DDDBEg7|F)X@P%M{'?>>:{\Ll_Se'Cl,/϶s?^z匐DŽ1/OPs Es`5=(}3=~x`w�ܣ x~fsPpڿz4|c!CG?/~J5dǀW"p}rB>qӆ?Xhgvo[L�x _'@﹟R~'ٖE% b{$~Qtx tN%=w73ܿgO܁Ss y5yԋL:.39Ӄj}">uW].^[/>:x|W*ju@2aW r)y-󄂺B#RId@7O+=Hxo1<@ ^w2;?_\j9s~,7L)wjL*ejFDD{t׋1qFPȡ6#+^O."""""""Rq (DDDDDDDPH)S@!"""""""BDDDDDDD*N|/lˢ"Tt]lkekFDDPpʛEPp<Ϥ9XP]X%5S-}gRnߦfDD`Q@!""ߛ`B!/h(|(R>n͈1p"",CM(@6#+u[f[>[_W>n͈BDDw~O'R~4CDDDDDDD*NT 8"""""""Rq (DDDDDDDPH)S@!"""""""BDDDDDDD*NT 8"""""""Rq (DDDDDDDPH)S@!"""""""BDDDDDDD*NT 8Oy|;dIDDDDDh8T$eP"#"""""iT 8"""""""Rq (DDDDDDDPH)S@!"""""""BDDDDDDD*NT 8"""""""Rq (DDDDDDDPH)S@!""""""")o?߯Yܤ8] m^W/Μ)ڗKWLPt[--뢜=9Z޹/?gX^^#J{H1C!Z[*9T̯> K!' wr |&yl>MG}}y7mƹtE :j²mΞ|oz]|p-B�]F#勼-I2=N P]k+Nz1`;h+�7/7?ӥ7p}:rpKWo=uhkmfıCN�F#8F[k3W*94P"‰=_sudT�E]_z?;G($ pvKDDPP@!,nn7Qb J&"a^W;ktu7Z],/7 (D^7uĞ?ݸP^fOuMRrZdzF#B (DI~i<e3CJT 8"""""""Rq (DDDDDDDPHyD7p3B_(˕wp<jk`=LsW@˃8._h)gfyK{8_!z.~� ݇NȆfZq3yI.=�PkU֕.eM~v3L^b|8sl*N.s<5o3$# Q@!RAYWYijL6Ն`oqF1�1NMܥbH&p͖&\~oo&}ܝ8Qos{UCfq+Onv H5'Ł].s/B(9"kt:|59TP@K[3 ,.LO%MF]L|7N@mk#SKbwISl$YMw 4"B^ͻ16HL,ٝ+ V|SF| rOsqB0]u5~O1D"""#"[$X}tR0p|u7[xkxvv\/׶917KI)�>jq[d#T4)ɝEWm�"UU69�m9ǯf W麟zM6gIxy7q9?7PG~Y255Zy{:"taWenYfw>U3Ln_#A`siH#Զ q}` _8Cz٩;PHw`+yS7 Go'5V)Iy԰=M81MCGYSb;f1@oAz6wܺƚ w)p6h?nqn>kr*`"*�..pu>qs9i `)\/;- k%UZ$`6p=Hk0_ x0xG].\-k8 '7U1k[.\.֐!E+sXZ#~ 6'7pou#{kHajz^7KocAq9f%.`q|ƾIDDDO#(D*hۅ3|TP $2X3(>ů-c<5ToX@gS698v4X2g),\㧣-POٞTΎ skht>yP}X^vJCO5v68S8ꮋkHS`a aclw/oǹW28vH0'?->"'NBU Pdj3/afhtO'֘ηo j^f M|-/2Pw h—7ؙIjN,ܼB}Sv5ح\M5wUav2\|-Nh„:H5ILMZ'J]cXF$b B8VpYX0='Xr.-p=+lb5Pcյmpwl]y`t?3z-V'/sCU0`iBK/ܺ+b.i2sW/qSUn8B 6�\LS=}kNfn7  rӬۭ,Lv�n,~OL@{E`wOc5{$"""/CH[W_ogG7x � ǵ&'"3M*Y]Yf M̭yF|ٛ\Qtji|pjOs �ibsfYO^%47Z`7'J6n&>K" 8&T0YW^!&ak ,Mp$R)f֨1vCm-ܘMXOl;6C>Uv3[,%wY[$ej`vM%IMS h rV&؎H8}ݳd&8=v6Z6ؘM*fr>N&byooF16FX]T.hf&+w,O^fwNp F㽞w!F]c`4lU7Y['j[WM>M SwȤ[O]OcKhknmmn(nΔ .8Ep](:#|(],Ñ$0| &~:Hl(n210:@p.)Ͱr/24N0Hk$@p?bٹ8 4t  9Uv{Sy9!Ra.pc3ˍ/oR=ʼn&UO/D119nbFF[ &ip1]eH5X,z]Cq4}h{el>~l<D.nEN3el~h!(`al (/b&+ESO~5^B`|�<el ˿PQ<c`wϭXC!h ~r.4!i˃m`Ip+ǯ TSܞ{V,m9؛PZ`Co(/n{-?U қqjky3{mc~p=u5V xAwaji4}7sX_#$\y.�q v]հNȺ2@MM*οcoy3*eo*UbVi]Y>6Hnܢqug�c?ZǶR㺤.5& }agGIOr5Ǭ})dCJѪ," U6ypvXqXL!ȩLִә7.r0 �ɹXnW1/Js] 8&1{G'7@rPW_Mv]81f!€5KW&^*7t�yk9NM(lX:٧O# p+n#Ap/N<󸸥}hS\[ ~3ӏ)7>umpy>Cz{[pq)Pי%Taé%m&ͭ Ɗ5~ L2M-̱p3㽼Yฉ6jaue+K,ݼ B||n׭}dU6I xbVSƅu86XyTE ٫>'k쟦xTP[/鬃M,aW2|xqayy3T52@ʅB&MM"[ [ Jkg4g:XS"sd~d]\j鼋7Tdvdvdvfsޑ0٭ep<oyR7 !鋲6/͇'Hw `JS} <uƔʸM(yvɮ N&CuOfKall4t&@\t,ΓFG-N\6ex^xc0 v6jdw4t֕ 3;\] U}K7 IoUb x(`JVY!VfJA�V2.rvR6@5@5~īP@!RA.~v#DCaj81<Lw{]h,f8NK482}dLncp]`!~'wV.N5PG0XC[m>Vwq7d:hnÄ,< bF u%^Ez"XXkNǗ\%I{]>lcGVRK+ wִPe[ւ|Q�һ)J4e@ua=O٠ˮKqs!imy7|0?Htꂜ(v �"xxj$7@C}UMS5+mv@4^"턂A"D{XYSp/<ѰlfVr4;k 7XSn"qX^3ؐ'܏0v#Bh5j`{rIRmc<5M_m+A57`+-VnOPt2D۹3Nj]nM`,|tv3U-2$s ~9E!vDDDd4Cv\5ǽT:I976\~Sݜo13xټKnc{ڧnw1P2{TuƮoy\bjuw fb)߼ -adf3di$1f0E.Hiz뤗gus3ttɩ%ȭ=.p~{""~]L?<.GX_IɖZn!0nI,ihc%Ǝ~T*Ԕpǎ`!)L'׮3<0kd| '�(c uŭsz>+%cXR"V߿ n{,ZVw߆\Wky뗧8[C86֒lLEno±7yhy7w(&p:3fqglb:{\!腣M:T'eOu��PIDATi v@83"55:Խ;F:>gb<~yyBC -oz)w(oyGMOQ]s|_aDDD$t׋1/""""""""1"""""""Rq (DDDDDDDPH)S@!"Ћ+Rn?5e`DZ3Xg""" WcMo?˶ �a<u'ʛxbp(T,""r(7ٗ7~_}]p˛E}X3ϧz]61X|h-,T,""r((yE~q̾F</Μ)o'Gl[B.`6gOw}2ǷT*ÃC<T.CA+ӧ߸cg:{rgaRTmsHY߳^=*nNnNʩ"""뢔\u] <`;q77)8Nykc۴k7t:EKIu}]Y&?gX^^#J{H1C!Z[4rBDDHt׋1慗PR\@)"""""""Rq (DDDDDDDPH)S@!"""""""BDDDDDDD*NT 8"""""""Rq (DDDDDDDPH)S@!"""""""BDDDDDDD*NT 8"""""""Rq (fo b>E)흛= yJ8]""""""qc̾ P@!1|>_,""""""ߑ|>h~(71/1d^yŲSbBx{S<eQp""""""ߡl6Kq0RS<< "o_ ˶qE2 ^۶,t""""""b8`K�rHxŰ,\%_(q]EEDDDDD%{&+_9?�|f����IENDB`���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/docs/fp-note-admin-2.png���������������������������������������������������������0000664�0000000�0000000�00000137776�15223753015�0020347�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��g�����5!��� pHYs����+��� tEXtlogicalX�258,9��� tEXtlogicalY�99"���tEXtscreen�HDMI-A-1/ �� �IDATx^gxU{v74@@7A&UE`AE[PAj @io@$*ﺢxf9g|ŋHx7ȍpFDDDDDDD$)E gDDDDDDDDr\pFDDDDDDD$)E gDDDDDDDDr\pFDDDDDDD$ټDDDDDDDߡ0 fo=ǻt]IM0/nOزfh4IDDDDDD_hpPAገȿm*ӕ  gDDDDDDDDr\pFDDDDDDD$]S8S -~ȭ&:�[7l'sV{ܑVZawȿU3,وgSF+|ðYRPT*CuR{S[ApH {ޜ)|�`.&0kfŻ  ,Žoćh:v}U:[>m�l}݊Z:ek厢Ƽ;kjn9\Ƿ~0|9f2}2HI yֈ6ޛd~ˮ)�4zDĦnzD:Y�@څٖZ챚$;~j6>6EDDDDDM^ZzSM1ҎL[5ܤɾ,vfL�`\T&dҐ�CH\Ype?WD`69o .P O?TBȱ8t8YknKoYg3 Lӻ9m[ש+`l"j&: """""mP<|ۉ<ھG/asD1}1留Q<y;ۜɣs<y �.nW>8Bjh;Տ.$0bg`hd༃:EUq;eE<ɖm{yq*tie{X&:X.JEX9}cu8RweO+و?bbg~o]}:" { &?ў=˿"v.6odWV%ڣ\e<GXno_r&&^2] Gv1uapfxcbx`)@^^ &g3QrJyrWs7 8͜r }Ƕy^T/Orr:vEd{(C9ܿ_߾|~aݶ}4{#Xu[mgWH(m &rr.VnѠ)` <Ӫ—XZ  Qu{>#v ظ%WCnjiK M} KN�зyiiSq#RHv#� V%2j*X"�QʋS^kc>x'Mc1T�:"9>F=@>6�vxg>8ޟ폌( """""#w'oRԻ+W@֥l]Ԫ_\2XZƷBYhL[ME>EI{ gM"vw/{{`7gr 2'Biѧ XKyr\~|ۏo %3]-J�+3o(s'naقx3O~>gojё4Qj(9cS&?4y|~Kq4!Gy4k1tL@h_&O]%5hFTןECy5Kpڍ&,@Z;p[`(؂�T/nR'apQ ?ف!o~MZ`˰lPu\s~XTc嫗Z]n{]zjD 2`8#ĀO_júChe^vIWƾpt|b&aՏPdmb#5M`F6<`#㺃ۺ ecwnڎ| ,kiSx|I�uɚ]1Fd]O-Xv+|sKcd�Zƣ_g箔:>5gUΙH: ԩB8m.�oZ|0=(*/8e-K|T$*#(T50W�* eWl~̄l 0`hZ-xϼsE1Կ10S6lH9B !TOg!]rKt W26].ѣ'#_Dav ys)2GDuR4=b%c~ui8`y0<!ypg&K! ^!4.ؽa'’^Ȼr$P{"޹!8�xve:7g棍<쐶X6$^_I6Yփ>G<nl 6AP�LKtR`4^Ăk!_Ax Y >ӖZOٟΰv|0ؕͦUv|/Rg{AO7"RL K0h؋|;E̔T 4r?U<�,01}%O>5sp_w)_> [6n"lacB Tkr`f%! {7n؎)e n×/vgoKH?O=`Sw1Og\ƣX>{6Oʄh1~ؙ]eo?e';ITT`jo[xC0,о�uaʰW8o ϜRߞv2c('NbիGM"rJ|qWk~ ;+H_⯃s&ߴz}0P f q2V(צ)S%?ysP?4J%rQ*Lo#*En&_cP|vM�w\p2'bmI&۾gבƕÑʠQ kΜˈ#0 k{U)rޚ^7?oJ~2%,&l JMkq=Ƞ (qAO_w:}!X {SBӌ_ <Tf%�Ǒ 3|q# �;IIbv@ibqn[ f@@p0w#2u*w5�G]8uJOABPN!9~.N&r)2ؓq@gxy,kGa:ƴ#!ݨ^)om% ރP3E#Auĺ2d,ʮGfۿ֧<%4lLJcA<@~ 4hVïD6&T#Wfk{{ek 1@$^eVi{cbM zǘT#_Ҷ %ZpoC 'Mǎ72X?VW0 ZF+ؼ~N�Uh k�GڼQQvXR?~lN5I߱"hӻXŒ_�@xzLk܊y-�?GjLlgSmr"E,17|:[fݕՖbO,\ 3Iʇd̔$u�`:<튢LcYQ {Y `: [ʜZeDDKr1,}nn`{~N [T>9O 8s6+'L`{?UpkV fmx&bxwE9 -b Nz)^bq_gRpG Ĭ܋ ˗lGXv;H^",boXf/FPo\,ˋ \sܳ$FaBF?ʩq5}0^}p`5г^be?5p4 >LT'1oDdw?92�bd[%׆~$oB׶Ui{ս6䩇I&s7gl{O^dgr9Id+Ļc^!Н %̵H0a] M :'y!nj� /qnRwĿV=&u Vo/~L\g܃Gó~F>=3q}V%+|4\@}JeyStC歔ņDYjY1b/eYX B|#RZ1 |׿,<ziy8-^Ђi`-sB+WY`aLk9mOA4+WYEQ% .*3q+U}r-<&'ֿ 9>X (A9:wkDQ\n.U_!p1.LJH: -XxK>͌Fhݢݛ4c1;<w`'-pc10 0,<SӇ'~Cm&qƳaCYLęo DoVz<8w� $| g¬vH`o:9SI?DTeo2]eqeώf 4ZFEg8b31_AƮ < DDDDD86+e1Io6sb C?%٬KW!=MrpPPW㶜d $D $MCZ::h7 63'Vdc]0 =mE1K=3%{Lxn�p۰2|W6'cձ2k3zrRKW6~t̟5u0Z .'.Կ=X}.3p:L-*cDn05V=3i*X]|]keo#: 6X 쾾Y_`kNHh0``�v5[aaˆn\7a3jٸ 0f6ҷ/ 4mO8~``}}a}s|g}V59b15l&2u&\`rMtkyxu徇kO3D}~@8tc<DJ.,| P?P-’cٳ3x 0jź !W(x Os]0!rvfPlre�L6 xk"ĝ'iN>ͅ 1$. sTCRv#M;ѱ1;{;4".&߭b̌9>UZ.6ςʗNĹ(b|p!N&iN&py^."""""f|b3  ,?_>I^8y2-YӔVg ??mڒs73h0N}V?\/:zE00BBhf`k҉?]CԎcKϢ{d[xozEk8S #^}BMٓMN ^_x,I{^GL|i"W~T 1n  -IC~ɀuGVDW%X;Xț//`6=&Tܩ@ +Q%~JL<T$⯄(ڞJ`'߲+n�zemJ"Wnp_],!u=�NRtzc]c,QMcsw<4#t4ZOJ[;qO,1yԪӁ:ԥk 𵓖O6ϐc)Y T=)C]QV>3*0G=|:үWaO3廳tN>hz[=_z)8/t)L^hQ&[~)SRy_eXʴNoZ§ޥ ۙDQ -¡[* k[plPc LJl?Qܐs'%*!rq0?% (X#RLp>-NI50(^,>y @WmCykmޛ5rH8`~2 \pWk\uF[BV\r3W\s+8K<i RÊp20zJXs;i?%]V[xD0/\ Od#wŬ$<\�5%վv:ٽx2,Ҍ*X?^}ƾJgc^:& [,Eyt ;lC_y=A0<* acJ G 3}/@ l%fm�t\9 D|z{>p[`<l۰tWabA'VbQ g4U$[M;<oٓ!U Y)x=d@B-qrz7g6\·| ޏgY<Mj<>3`DZ0.3`S`ݼp*CyY6d'{~.uԂ�7+M?,c 祟2OWc_3҅=s'旘uy>/g*lڵwǎ5ۓLR#71Ή+fww0Xb:% 3ѳ87γum;NqǹHtX[Q۔f|Kz.M }/gMJټhs}y 1%y>\ 78&=0 ߆ #x6f$ Ⱥ|kAr�H>obu:@@ BAT'b)� _;g HZ ld>^O)&l]ovt٣SR(y|](W4'p^/LC{n'x-jO;6& -DtQ<q?Z70BM+hu5/'?1[ GkTOSy( Ч�:ؖ2sDlM6yO;ԥl`3flr9nkqƬ<'.&ɭ svf/'v:U7ɻ=V۞0-o煽lx%/[EθL&~ĭ_XBmLv;hּъwMʊ|=c&!wq_o�;w, O8MO7aiaVBgWp~t<NG4%}|b$b0zwW4`Vڌ,!O6N{t0/u?!Ir|&""""""<+x7N])tHw?rS <P 0 #7>< 0 & I[*t_9y Sm3svŸlAd8XTYG\x|Q7װ 26eMoy)|U @U2j?_#k� ݬ2̋Tcлw[JhE#f׸�n/@Z>d3`IZĕb/e us0gn{U,~5eDu2i<׽/󫉞1[8",L\2 KlK3eȉ-31mqLKL=0�8̏!Vr73Z /~2[Fx'g\&]F&꓾6Xj֢}8}c ؁mk&.,t~ c9%+sN^nĆ |/g{nj_yU.""""""|9 g3E B#2){Z™`د�� �IDATb $l9o봦d߇Ƕpx"}__@*!*s mtЦ8Βd<>u)uއU5"5 �>9QG'L|e`Ҳx>}#Wv3IMg&3wYAdvHH|2~N{Fd鄤-�_λql[ b Itîf2ź?;ٻ~>q\Hq}kv'fg_Ws""""""rsBw{b7a#UVwl.߸ij3%y{#g oB7�Kꤝp xF(3ťIg""""""""x8V:IDDDDDDDD\tS9#""""""ow9Or393"""""""B{#пppFDDDDDD_齤3M975$""""""45ANK:uuZsFDDDDDDD$iZH.R8#"""""""[$ŻIS{7FΈ"-,"""""""4rFDDDDDDD$)E gDDDDDDDDr\pFDDDDDDD$)E gDDDDDDDDrP.m""""""""rh䌈H.2MF14rFDDDDDDD$)E gDDDDDDDDr\pFDDDDDDD$)E gDDDDDDDDr\pFDDDDDDD$)E gDDDDDDDDr\pFDDDDDDD$)E gDDDDDDDDr\dniz7\Wax7#]k gLbR4s&`Gr_ ӉۗjbbZٮ>j-2N'$a@5TZd8HK#4o^|ng&.kӉ %5˅U *0s</4MΞ=ݎ-rC9;ϟnke&i}} r!1Gz:~9~fS0 3v0 .&%kdQ0#""""""93"ϬW8qFVN R0#""""""9rZ9g�7t?cnL3"""""""W#˕A9gL[}iN'""""""Wnv:sܚp&';-vV&j6 |E9 gDnFg#""""""7<[*{T8#"""""""Έ"3""""""""HገH.ܳ&Z>I9(N nw7mL 7J4{ \77'ӴlHɑd:놏-﮿,> RNw:\IWm~IOb&;NRJ< qgLDDDDDDDD$Gl 7 =˂ɔ{"`.fXh囄&o~�^msտ <`.ɑ\9c3 bwc[ 7#A-xޤD/$(n�<<[e-u$={A�F~xlG:۸9sͧyXD-5?f&t1˃&Z'c<,dwRLxkY4m|-`l3\ 83Qq3fןOGyw.̩]"""""""rɵphۑ 6}:l3g?OXݏzy&|vX QNHܱtLnF*MWKlZcD% 3i)΁N�fsγ#qE-(ٔ ˢX IRҾ=7^7'_OŪ}1AwֳgS0H ŷ` Ob;+݉M$?{bmEd:[^&x_}#bhS.bQqcn99}m&6lJyG/mәr{x> ^~&sVd4{ bTGZiq/#s~;4kiz8<w 2e' 4 |uODDDDDDDn�4Pgɴ/WE+;aj /I7tn ɦl}r۰jx� jѴNAUSH }[FxOKpFYu\GPڱME7Ӟ1�/�cbfhAaU3VNEMIbg`G-'IXtojW1Ϙ[VW4MkDV%矖+/:_[hl_x} *x! Q GYEԚ2"""""""re�Tvz4 `<k�lqNRVIrUg@9eǒ(g͠X&x (Qǯq x֋ٵw<m]*|`&K瘩 % [6&9pA<e7rUڙ <׿'.҅-|iͦp܈��7zj87Ӽ k.u.s6|>z3'@k b̒8? O 0XXh2p; ;k%v,kzYFxܗ8U�{mpVH\9Pk[.p ^Fzx-6±Di{0iςO0hڸXK\ePrN9Mp� &yhHZr`fj%oN;4GL?m`tR fT J`bTu7[H.b&nSqq WxA(| $ = {t~ݜf/{˿x cX0 ϺBK=BpnT\~5ק5]0xիt-b%N""""""""7?bZ߭kt+Vo:<ҬO9x07ϭs.\uSI(VjWjUI_wir;MPV]:ϯ3ww\b?7f"[{p 潃"[^]u(,XJY{nh藤\Z'.zoBw֐07�3=B(}EDDDD4-ഛu:[rM\�|&ylm7XfʶlMذz?EDDDD3"`NF=c]8OJX٦紨Qgޥ8.`w13vywUVyѻa�AwAv<+{ȵR8#n럂w\'.ZLwn`/0VywTh_x~z eӚ3"p&0q[ AL[+gwY$^Y?zCEE\C|wmL@ޥ"""""rΈ wø0Z{w_�, ]YRMXh3w= "7j t+`gݬ-0/X '\gӕbxtȵ 9W k?/e6Ο9SxaZԭΝZ\6_=t i szLv3;_ 乼 'X263Ǣv,6 ^2tiu5Z>aޛ%^}neVjcOdiOޥKCx$ل99ݾ : qO&4~/P{ఋq]W­Y4+vo]C©#S)U0T=ځs>YdyBʹqQX~:6A{Q?8fpr!ckV/~d ,I Y5}Vʊ#)|=c0)@êsg ʷ :3""2L>gv�[Y�3ƿBZ:_!}"! y!p:UgFa :uaeKtg} }v%' }?c9~^ ڬ@ᤔڝt�|MGwO?cwl;mG9wGD O]qs9ls"='wz2q$F} 楑B])8~zR43&ȰiY5e8fl8jsW6d-FDDDDÙ'Oz7 __h!)ܞo`Wyb=&sy SLn }烌2"g؍L<[gӊsKѷj9kLΚ$[H! mՌŋ51uy838㏮H>0>9^Cpx,t 8ɀ7h|eY'9Űϻ7ׄ<T,&<8K<Mg7@ÙӦy7yy7 ä󏐼e"ԉnxu|rFՇ$N1l2$GL&A/0.*1.ܼ3;07.U{wIԍ[[},R i7ǺahQw(mL)rq$u@7p1#nCLVVc�AWiGaeawxwg]u8#"7N)+<lO޹GLGdVx7f#o5:uj@!l܊4;V8Ucti\j+4&ObV}Y+,!�`?n`S]3`AVuWVb-|n/g"WU1d;Sn;0 \uŸ`Ӓ oV5 nƚ 9- |2@+5kq7L3#[4(@f-0CJy6Xz"[*d7hݤepǒ5$Lw)�| 5LxJaɯ{9oUz7d9ZmfYEŠuJlF-/#OwϘdkNx>5>3"p*gp =?z_t`q_5[{SLӧ>�'̈|1%iG"| ߍg͞ôٰdkߚ+?܉YmС_.Yß`?n5t9kjƷ.2dn:v,@X-uY5ϻ9j1:z `mn5=~j&f(OR.?jY%bo2ϥ`8K.wU;IzˠC環l8VYV۵*g7.o32žj,y7d:LE;\Q""""rk 6.ѿ6N:M  8}FcU4:6+lr oHژjr%x?Լ-\ǖfk+hquڃ p l%־+_s�, [`uiDL췴&Ʉ @!<%m-94[0е;�Kl9w+A{q=�KU6` e�AW ӱڮ=m'3<ܶ0cã6g7@${U",]P@"bEEGA) { !@Zz;!Kv�$ޟ"93;ΝsX˸NͳGN_FDDDDFpF:ЮAr97[3a,cǑƊo<*C)mKwm]0]l`HtiTB@Ff.vmM+1 6[UlZq.T0k3pwٖ}.w /ZlҞ'0ЇX�_*W Kt{pS\h4J 4!'-ͥ0I-` +LjEDDDDJ" ̲_#e՛M9cOV3o@vO[ (: ZI5]~< r&ه4?StE~\ #{.e \ڂ-씦<֥YV=̌sSe;"c1]GXѕW忼.aQIW�۵^XD+<>޹Wm',is�I'[(a.mـ`R0O6q_Tr$:x pPCHM3Lp&mJuN�NiӾzI_mŒ^Vq=y)� b5HpF:Pz<ft;ߙGiUy:<we<>g<9Yِ;Iʤd\Dryaӥy$Ouw�vY`kӁY.&ttpj>;}.ɶ3 ?"""""" gD#Gv1It2\~f,ucg:.ȥX3/>Rk:X3ua4~P^6p s!fۉH!R8#riSܠ~~8ԙ Zu`q$2UJ`?m<ݯ`)^jt0SKWL(M�`)C~i&$&QG""""""P$A+a�/v X'~wy rXʸ-q_Ȇ_7*6K @H_~q-W#bz'984P+wxlۺ8Jٵ3"""""EPy+<9'w-RFY٥-̈́i?{K;F?.?e= hа*]9�kx ץ}UɂO';B0Op/]e!̬܅kzGL[y՞KN�H~]p& lz6 Uۣ1W u_{CَWߘq/5@F1:t%e=F|:=*�K`g'gijཁzo'dF; C] [gu>Ab~J֭[e+>M_!h%<3q!�e-PEs/K=8_e2^ȍ֜[`pjQdLu/м澹cɽ|Ag 1SV:8/6nIwj?Y鮁Հݥ=$Fp.hH5ᎷjXJT:Yԛ*GY0ӜO9Mԛۍ&mZQLU<X0,őYNOoZֹ}Afl!g낿S�~!Akג+<t09<&+?o'DŽ3u{/鈽X9V; 0;4IDDDD(*p3y}8ol#E`-2I~ ;Y0)�� �IDAT<^9&yy;'�VK~KZ8MqwR`)[T[<xzz\@kkdy<g{~9&|(5y_gmz,Фm3җ�Z33s=˄Y7AP ;mֺ8?â箲uiOkq2?Cѩ[狮[Q€W[Dl@VoIJ`mR~Blds:{Q܀Qʳb@6# ;EnB@r=qwDP^(%^h^7TeO7oLaM*>k Z}^sӫ .Ăf;ܧ6Mߖ}&% r  W?.}/ْ?O_Ȑ,WJ]Q˃oM|P[,eʋIV^B66 "ã<8m'O gE 'ڽtQ% 4>=qso1xc$~ψ@B?ROqy/- fԗ|x6[F͛L[#qKtnM\ f趭 gsRUE0]1e?~} )W'{3h~v?o[ 8kPU3z-Jd_/>ΌoޖSl;,-Punm�&#k~=ܿȍ_E+}]xsiֲdoݱqF'UʇҺ~MzځRU[s06 g뱧$RF24mZ,kĔ¸3T~K`MLN'QBi^*ujMX <. f-Iv?ZkF1Xʲnl5sW}=D'6W55 {'7gϓرaiIA2Ѿ MO$u6ؿBьHdNMu4q8MHq+r{7ar_%8B|GGͤuNٛF~K8S+>ͷm>. 7xG0+i Yi6ry�BCBX,F#.T|FZ!!eK:%[ u S&[sg<:  x?(IA73�2\hkف7%RZu@r;դx*'nP&"=G<G&Sʡd%&HӘgܻBg�v >\hs6-^k킩ݕRک{u`Ͳ%@6)&Ծ Ka¶1m !"0D0ިHP$f.uk,9mHړ_Iv\UWV?1]iw};<(~GC³ǘw`pDDDDDDDDk բEDDDDD(Έ"3""""""""HገH!R8#"""""""RΈ"3""""""""HገH!R8#"""""""RΈ"3""""""""HገH!R8#"""""""RΈ"KYM"".>޽IDDDDDD亣3""""""""HH!!Rs >3^ ~dW,2 & 3սA{8D}Ş{@i#qt/c~qg17 s\C gD^0sXo<Mp$w6۾�ý|/fefagΈDP=4GV罽7H(jL� ,[B=%깗/dx3n6eBs ȿ[6cP+=is~]DXxDֿ ɘ)z3~][0�19 l^ yK-6`q;?Chl( 0؞a֯+ټq9Cѫ{ p�$d3[G-gW-w$/l/]w_5Wײc,Ӊ_ L'Mؿb {,M`}(=An�{ [82Ǚ<xv(z7߆|?ΜJƱݴ-Ë=QBs.gDFΈA@x >s0xÇ1%4i'Ýefov/udf-|}4ǻ3v8]fxjøAO-~32v`c?fL~}w™0O&^l&ap[x~ĵS)zԽ8n:k#*>{YdR*j7JТkWZrre#zaިGcg|l|.ap0v7< gD ͭ% |N4AjT^9IҒiQJˆ=*Թ"t܇je*pG8� PNWa`QvA?ܧR.{tŰ[CE Я9]!qw ojāCqC^M%]W:FPF{ږ/ݷk^X:f{@0^q/IzA˱5xz`XmxZӓ4,xMN۩^:f67[DDDDDb4I2,m�6J|ۓ٘@7i Aj5rs4%svr V v #0]ʢqzP+z''!!'xnonI'+ANcogX�J3 N;NpFxX!7"<8r M1] {3>p58k;dxg3�q8}$Nb~ l;+ɕΈAiDa폟3o "*|x)@ `T4f⶝I>n{܅{s34iv $۫&n�;� 1VکϪ}K_9f5΄_?ìY~u�6a4 v+iZH4ێ4];^ݗDSDVoV`d%Y߰?Fh:0ϸ|&7v$&((PcOq7uP!9V~6ի&ٹB* LBgc __JzE M;{;Wfjf47+*ԣuW�[P0Ǐ%Q>ЏAA t�ݻ\" ՄCّpq0vW xX0(W3mY?0io?O,=C(SsӋ.7feM]JgxWmDɋ8~ʯ:5!JX`2 `dW e7?vrlҲ`#w9`YPߠ~[II;7"Rk}tp;RޢomcoM<̇3pg81hZH j%}xaUZ} ,A|. 嬫i~ފČ#T8x|<-@KUyTvAl@ ]Aҡ dʔ>!oŷM#Ē G(A^ 9 q_PZtj0SnݎڋB{Tee.lGM|7b-7ؽt,Fse[0#a :^+з~n'sxr#>ߦ:y- jr{""""""cNM|4q8MH CL8h<=d#-vos{R b`W%g>#-U`P[OP\OZmkuGyFΈ7mX&'X$νtIt<""""""ynp&B]:1Ȇ3{SM&CP<M0:Xe�6%ڙlXJ hSj]ng/61%k _l%-"y4>JgwsfǃŽt)̨Sa#eߐwI݇s]1G_% ErL*Dt?!j'{R<&dž34u]5-og˪wh4�m+xPKo[DDDDDDD()L4`W3jQ^4ñ{ٚ_O}&'Brq �('"""""""t X,8L+xMajb�w/yVl?0 :tz  s< m""""""""E5_s;t;cd,ٿ,'8eUaX)kK؏վ3.v`B)oB$"""""""]p5gض퇘$WLVxzm$nag|Ƿ#a}�{6`HȖÉd.fEGDDDDDDDL,㭂ny/~Fʤw3ysEZ|e( <x1qƕCh~RYg0QʖAzDtV)ө\i8&$V{YPb0 ?3FhH{YDDDDDD䒎&${k>IDDDDDDDDQ8#"""""""RΈ"3""""""""HገH!R8#"""""""RΈ"3""""""""ӽAQDDDDDDn͆p\{/ 8)""""""r=po0&-=??5 $<EjZ&v]#.XV|(U","""""R]v8É'qE\599QdIu+3;cǓX u%sH$6KODDDDD#5 rGA�N8AJj85p8HIM pLOFb~ f̓qx{YDDDDDH@0X,؀% ))lnc)Lr<&D  gOb5r/";;䓧4IDDDDDr8y{{cZC 0-s3�iy7EjjJWDDDDDD+ g\@c&P8#L^s#Mgtlvf"o+ۍƸoէTDDDDD'+qw#8.jM""""""""r))D gDDDDDDDD BpFDDDDDDD)lO!fx^v1}SƁ^Au.N@59~|޵$8m/='šLw Id \k?Lťsˣӻ =Y@xa^v�YGc#ν {1:%w;Sc 5 b/9ƠANJr6?0n#'Oo5.~͜|HHƠAHHp/ r믻7B!| ?ls֯wovzON^M^#zn={8k~ ~MoS8#r07d7i$IRy?dq/_-Y0<Sa-F}˲_g~zzD6⛥1<Sy?ec# ,N3;דbnTY/<Ǭ^` /0hx`_tqI{YDDĩzrxllqm!=+w;XDD�poV>uZf&5 b޽ף8 0MYֹDFLDv@uFRܻ9|<w{\E gDn '1O]^~O;O$kDF5fΊZ6[=AY�VxS0w[$ٛE-7h_vE(k%2$Ȑ?V!S\>Jppfݔ b;}8ξOH 53:�j҄ K;n}[b_BQﻏΝIhz]v7 "r}2�ʽ &9R'5WGơZټ)lLXԛm3#4<uo`S&̟;]NP@l*~ۛ�[E֐p#' |ZvglХfdU;t`[蚺 ÿ!~w0/L!=a}I+]eO1yqP'AZz<sQՊ_r G{`V|4?G Ѓ4"VWm:UyxdV~w3@1د4=m$cߝ[L›=.cjt~Yzv:?dGVپ4^jYj)~3*n0]45tÇWv(lMe^^VaJ8?=3t�P72u;_{7}6sq05ʕcKL % <ٹ399>ȝԡvm4M_۷TCwCo֭|0{6)]iW|`'SS˽{_dgyctm݊0h[Cwg=9&'s(1Zq>;#=ܙ':wvo.Tl:x7ew|<֭cHٲκ3j~ռysM[qs搞M5It{3g�<ѮV-;ůJPξ;�l%KX6z4pp=dj­[UwsWz{ AX{{DІ?ފsD'ȒhTq~_L?4.CۇU ? kv|`q 4YĒ<q9�7gCԯ1G[fki`aZeikۨ5� _5d+.`n_OU$n@ԦSL~3Qm?%/|9lS"~|;=ȪVp8w#numhkTsyVaO~zGYEO6#ȉ⽙Ǻm{,G>Tzf�zZұ;=e3oLQt~ �lz9<Cɀ'ߗRT~~n�:?c&~{@3a@oս#zIdc/a-qS'2qqge9&իSbEV]cCiLݼ9�}1}:kWqT?L(ODFv;ĠiSF8Ymʕ|4g/ e_8GwCG#0Gq0Lq,|僂f�mՊ7;?D<yzB?{:S>(Nu0{:|w3mJ'?Lge9bcy٤ _?$UX/0o`׮ٷ/5c0kW.NQe˲fp1r$Pg=v<ӭJ]o?pFrW9O_)^~-0;kYWb9ɏWdoş1i{�� �IDATnQ2-'r2uQaVq7aIĄo3vڷeÜI)&f~za2'&yf!/>\K{`)\YRwQRL`Ύ4;MQ?&::prXEWz䭕1%䅞M!Tۺ,[#QJŪ`O\"dÒ LӖ}X C[VfwX+o@C_GmO`91MpP;�d,NQg쳼PيxEKgYl7绔R*w@p 5w "<v2DZwȠ0^hIP;nBٍ<*W O@|<=Xm گ{#""׏dfg+>XCCi g:DݳSZffsz4n̝͚U,uHJFO?t89v;kצBo׎zb�|<٥ jঐ^Ӈ} 8|mOݟ]էu""Y<#z&I,۴,^j/OZu|q?/'֯S:�Ӭݗ6IKr6t_aageҥԯX';wJXjE(g=? s,| z^ ҅+SdIgq==gS,'krwϟV=F$:miЮ1O�k܉9cD 6o%&`GB֠sϜ61||q~p3s8EF6-F_~κ OΜ<M}. N|6^bW@ ҟ>ɛp"&!V&xry{A#610<yld!nT|<Sly?+$1ԇ TfYkF` ^4YYW`tTk0;2& }{bx7 +C.9I'::b@_tdv-򆬣@(6-QDDR9&II4G&QQ|<w.i슏ghn[kiҠreZTF7ߤuV6ÃLby_xg 6IID)lT_a`X7&B{)]jRh(~g r+I|Q=ˁ:Vߟ+2k:TDVNqԮPbqo�M79pjX�W<SW"A1Ia``XνP;K^`XLxfۼ|%�VvK}AOҹ9^ay&' cK@bn@XxaWeoLdݦ`J`.`}4C2¦3؝XUӁ s _L)pdEa9܅ �j9%4u""ruԍdC쌋v@o+Wb&ʗwYQƲdv&̟χsO;G:ݛn'AŊpK\{s?K .+._ +'yWgmg[8 o+s=<S9wgɶ7 %Ȁ9尲~ M, jP}q�l ^ ;VwsJt҅RM| RL[iN$; Ǿ?wrkh*c(e;8y"Mp_k-g?ӇʹC6t(?JX!Bs�{{<W*m#{bկDJp (D ?ͰIu2񶔡Q5VPreY0<wY ٵh*0!g= 0!#вl>f j#DfWh.DDD:gÙ=G0hX2WjXXT Ұݒ;t)5ʕN:t(ߴ _//ʔ,ǝXF@F`w8ؓJB1Ǐi8L"9p9sS'4mzYsС4d陙};6JwUdpcyUӹ\(F؀jXzCMI[_2uI<'T:= ~>u`آStlЊ]d|`ϝCxTŞِ�ٻs{0(}/>}O|/B>¬9 6l{M"q^޹RH䷣8lgM?f:j|l2N0+>+~'oΥ-Ԙo]Jƙl>zݲ(pA~s@+$3o/իWSh`#>8nPb˿IdbڂCt^}]Ӷ[W9Grn?)ʿfr((WıimT(NUho䣼!cgˊ` ?w'1blIYݻޣGFIsSDE%/$ow^$iXdܺ3+C=ܾ='SWpR^MW_TZ۞ [>(j1rdƲ3.&q ,q(h0 ޛ93>r/w?.eC�ddgy$%q>ݯ;!z5iBpWƬkE Z-11efܹd[s6f[GFVnuwt5c=z(yy'f4eJ$t(,LbXn6|cد~,7z:Y#7>̌ao`Yt G1mX]5UBmX:u˰@3#Xl5 L:9t)ʂ- W=$ f7wAnuN0 fƍ#zܔ)/ze|sG�=MxS|03۩SMOEzQޙ3K>jqQ-jW5R>@*)ψ�4J5h<*[�<+pi]Gr|T:(e3;]+}xy^( (oÌ5s'Eޤ 7ߵ#5{7e\o&Oޢu""\3 ;u'.97]r^zd<В%y۝ݧY3ҳ?o2BC}=|˾ 070P6vp>ߟW&Oe˨R,XwL],j/O3LZQQgg\,ޖ-/:*v-u## 8yכofIddзeKⓓ'zyqkzBT\9^Ӈw~WLqT7^ڴY+> \`NMF;\LpFhH{:{_WF6,jj\+2mSMOsĤSD;ܸ@9y0ݻ xbXΛ5UH+a }'lJϟ+Ok-m7c?r^عg M�x+ OӚD.@Ӛl'*U4t(eO/ߕд&) .wZȿ�.��\ȍJӚDDDDDDDD BpFDDDDDDD))D gDDDDDDDD BpFDDDDDDD))D "rmx7?Ł#""""""."˕qo* gD YHP)&7Y$"""""""RΈ"3""""""""HገH!R8#"""""""RΈ"3""""""""HገH!R8#"""""""RΈ"3""""""""HገH!R8#"""""""RΈ"3""""""""ýAD3iiM""""""r uo*9#"""""""RΈ"3""""""""HገH!R8#"""""""RΈ"3""""""""HገH!R8#"""""""RΈ")zrrgf^ۆVq gD;NIP`{ NN%".=3OKNyLyUL p˷9K[x,tkxfzv}gi\ൗQR`wQȤK�,?ag޳4.SPb ϾzF=s7xngIr__=9M2 h[Vc|7a,8]{Kll6RܑJ  ҵ]O�< p?OF]0Xn<r_8q 9jg-�/te0ػ(ߙ$HKޛ4Ҕ& (RT(&"wz/lݙ@HA 9'>3};߱[ ٟʉ`N;R<1W!x8#S.՜늙TEDTt.ζhA7c,Qv% -,M@9G�9߭~U8w'N#ࢱu+Z1�V`ht5[tV<9C):o5w:T,D<O\&d6ckw{QL̾TPBv'L\ ڗ/U,+N]U;Bj%H7dWH~m)uCrӊ5"0 NRX+n jf_tZv؟R�Iʳ-q7 S^?@V !x8#ȑMՑS'OQH+R0%MIęmé0u]0ɶt%ckPcOR10ޣ<1Wa|bF^~xHҁGip&=t&bO:&,?szQ tXT̩+HO<Fk BXeGocmP@ Ŏͳq5<R ΰp< u( 9 B)6} MjhҤm3,_dXؕh%<g$b�zR-͓᭹zQ>vT13^!xR䗉"G8Pm'%H8{Ve;->8Y竝rYWROJŀA�Th�.ajZlȨrP~@l ÂԛqqP`SP6$i`W*u"JƕҌP gTPc,{B [V4 , Oxb*fu:_K$>ƌ[Is;�KA)bHNy gq ,U0#N  (+)!Og9Ru E];xpm8'uNX=Yi0e`ntÝqک5^)ܗk1wdav+ 0l N % `BCŜFt{[ahQS@ACN�*}e{ 9LЅB̬IsY{{I+ԟ Pݎm[96]J.4/K7*%p6TWG(fmBDHqFTZ|f^J#+hN/OqIz3O{i鸦tU;w*ƍrx:ZUcé,߱7W:vN[')eԙg8V{zQ(7v$ Z*|ҽBJsdَĖ(f]VHOM&Q{̙65J? !3'~3@xʼndI'%zRt)6 P]keMncmMi@9tSB{ Bda!POǻB L"ZTl=6<GV`ȮPONTpgb@˵xkEf_ܴ 4VU-N]j1~2rZ)Χw[f(K4FNF>@ 0B r]Wrб#DiZ{|xa�úCs d03Yn_N btv>넝"HNTqcB!!Z9;tf=p5cI:4� Uz)/5Gy%sn$9MMP Ae]q;xIKw*±(Z!A($|h Z46-S',Ԝޕ] _q"v>zl'`IzBЦ-ܭO7R)_1T!x8L_[SbͩiYI6σ�ukK0Wxs:hVML/cb?Pؐ'߱-"}Fuo'_zc bW'"I s8](5B!4)s0ّbdr@Ur~ͩ8[2³�ɶN-Z5g7~V~G-63U[@j+YՅUg*L T SlI։;D ߀۳ɱO UjJ2;l G1?H@~'^hHFɘktߗP)#E3BSx.,٘'qSbqO펒m8wM/&yy+ |؟XJ{om'"r<=Ã1엛řqZn ހ3{&BPⓒ.h99_*!9j$qr3))i:c4DR!B!*,<rdO=р3)DE6k0#B!&) 0 py7 !B!xۚB!B!gB!B!gB!B!gB!B!gB!B!gB!B!gB!B!gB!B!gB!B!gB!B!vWTt&!B!\l7 )LMB!B!C&!B!B<$!B!B<$!B!B<$!B!B<$!B!B<$!B!B<$!B!B<$!B!B<$!B!B<$!B!B<d x F5TsmS&=vjmB!B3B<#T n S- Oz^N v~~mB!)4ܹmS+s~}Ogxʥk:vlqpp@6=š-/ԩ}4.vd^ε_bۜQ` hqlcIB'C<D٪)S(Z6OF(Zp1@8R*^|S/?2s_MlRa)l* /OJ\(z7B- tb g+/Z<i)W EZ*� :fXgefˣGn$3njz7̶h ^{*(W(W'wwzeBװ�� �IDATb* Mx4Pz�5(i}|2rwpWu҅ mK6!+h}3b9dW5W�+D{9GJOi9m*]?Δos 6o7Ρ%v!?jNv}#Qq J߷FE eP(l}2�#=O�ɶ9Gϣ%cgVҶ=<T^!xt`ܚH I+!=s06:_҆+ת 8UrovˍQ='p8Gn$T3mj|E]m6 _^izuQ?Q3D,o9"`{}+GƏeׂJ86\ɫ_c`wecd^ՠkE4z{g*ۤ2B[u`hoKȀy'7E ʙyNZAY/oxxvy*Ebw1T} �8f+H'Pvq\v~(v !~*yk6ο5>] *ϵՏtS/x • 3н z5wy ~a;9g٨�]Q�dn{qd~( ;Ӡ(zEDGq2rw| a`pHBʙ}4#Hб8YbP�ڴ@W< +|4gNORtj/3fEƏ/#%%V'uC)^c4ٴǩ[TǣDCQXp6vp^޺ {b9vѮL4>ž:qA<I_B4mښR!) v=_K@w@痫UF^bJНTTޛVp}8/zݦQ(.^~ʂ߭4 q>Cqmj{G'")J]Sڥ 3c-21"fn}Q(wFsAߊ|830V-C)t\Gd`FKw<DWm٦u d\˽h\%.IXȼٺjLZ8?U-!'Jf7: UP3ƶxMs 92q:F5!iήlU3W)xܴŒxr;R1-G;+cV1C:701!7Ү{?P\; SYڋzGc_쎱2.s?s^B0V[f">K!-o.0^F13dt\Om`̀|<M~Ѫ_Ⱥ |x X39"od]ʻ#\Wx>JWb(1qkЏ/~9tm:meI[og/{x+<g͐>X]gs4H!3 xz_B<-o_N�#:pp, P>"1xࢀLJh:꼷c�\Jܸػ10mUϬ]qGM:L2쉞-vGe| z1j8DG㭀nA /Я/8nW@F)U-{iQ;\jCaGC1@y83{ ,Sx2͚FB5nzjVɛ7$R@o5}NJ&q&ʏ!_3DSo߂QG1 nd[ 05{QE9i.5*S<|7+RB<2ग़%pp)JMW;TRDƑ�F(Nr\,M,ז|ei͙ qVѱqOgAj6݉7d \Tq祮18{2ߎόkRF8^6?A^Qb 46 Wk2/D3'gr0EB0]UΩ4k\ͧ`f'OsѼa;uWzק`xuB[L`l=u5>fkBzpV�%}U+*dُUہ]>۳Z2xU o@\r<ƧR!wM,f' jQ| мc-|e2cJx*ۼ,ù�8(t݊9^?$L>$&B`۶`yzo}Kf١#b ZLJS9}>a/п/e)hJJ?@ҚRzqۚ(N\ߏev > ,w19RŽM3n+E {U|73qn]?lA/U9:Fp3ܮ\NB;8]Ǟ~kk{I$:IÇ$ nuS9WgBA-! nY,=@h�]W:&뺆xoꙨ+so}ƒ耖fn02`L -Mkh5'cR`P ]bRh`W? vqK//sP e9i r[җT{L="*\X3]̤dgipifʌ&vLĎ8uQrj{?̸_v~r;vdnwp(vɆ)uQ\(?OS;?&VpHI͍=wtU`؋)j*F}4p>Q1wqj^mlge-!a!=6kB^KgOz MNǛ].L|WӲP [2(΍[COP�w';^畁/z4�R4Bs⬭h( ZC@{pVkb<;/ )`L@˿:>!x$Tŀ=�>*A ^ CJx8^e=fg X;?|R 9*UЇ2ޡd%]Ȩr~@? Cv7z3H+NQ(>@FknѫZJ<:ɭ=:h!P r V*Oɸi}7hfSާ frJ3u6ly� hV,~m{rp{J IS#%8A7:^ r<zq\i 4tC_a5-⮂љhsaBJxBMҁWS(gG0߽1ռj!bS!B"0f,q7MXnрYYwXCp1;:isr V7㈾r<ӻt0HLJB419 'F&r:7DK8Ϻ(t Gp4h8;;aTе<: ѥٲ(ZZS4v=D *ޗAseГmw#=ϟܠEcf[lƟ_-je񟱔s94'?\{I?>\>'3qհsJ|͏Н3JOeiZwTFq~|6!p-Ug4o j�cp}0.hЃU&bt[z&;1($�Ѩ~:dHu6D?1Ln:  7(dǗ XNƶ\N9ğ^Ff囥glXcuNo zl߁|'n^\~\[ \X,!|(PGooq[QNT3Vkƒs۲z}wzPܣ̡rFɞ0rZ8Aɞ ݮa⦦2(mȭ.l�ޮIm7xtY[e,sѸP>*H|KF"˽(R<YQKհd޷Q['&]f+}TvcsU$dSa?r*۔eDJ*UJ#߯75"6nAP*J!XHhЗt=§q>=y`țe>}lO_'ĔÁ�ԳoNaDXHqc! ]y3t40fN=;Jm&cJCt(n~{<-#g}\1&ƢEФ c��q62Vq> 0g@ &FΦR)ӼL~&/ֆamд$F~&M"jzm 9Zѭe^xwG-Vp}r FqmŢ(遙Trjw wx gdn+¾xVfĶQ{E6EĐyt1�{]nYj\*=]y9e".Qr2)?~V(II4&Ŀh99_OJhDl#T vPJJN!=͊ŚB!B!V'%,<(_(3B<,V &#NTtms&c+̴:vxl0vB!%!09<5C/B! B!B!≑B!B!DB!B!DB!B!DB!B!DB!B!DB!B!DB!B!DB!B!DB!B!DB!B!D2nB2Zm7 !B!yvB!BI!B!"IqF!B!"IqF!B!"IqF!B!"IqF!B!"IqF!B!"IqF!B!"IqF!B!"IqF!B!"IqF!B!"m7!>sjfsmS&=FI!B!SLVX$&(럢@bb 6cuVm&M:@u&d?W!B![G`lT~'3?$HqF95 ;{M888`goꚇu&~N 2 ~-?L=ٶ9Gϓ9{l>I'2<<T^!ĿKOFwDЁ)x>~,WK6Eŏ@ʽe3J6`=-V27|V'Ӻ@ >ysyv3@˖'xcTlC!O/^_#_`AxΖ-?+y- Ib̕t륹mQlJ7'C#1;邙j۫0erW DVpuv IltX4-Ndd=ik^>%ڷޏ!!UfN5zmx63/Y䓙`}0Pu&L;hD&oNmqίoj3h1mYR)g6]g'0RHOK')S0C0�E&Aqm ?|{<x|\yl=B*}AONpb~;}@FA]7N)cz~jG~\%8 M bFp?|5mS$k_l21l?%[yvߗ碩מba;ơ922goL8 �{'y;"3ϑ՝Bڀ➙Cz}M+qJb.^Ks^Y;aa\k�k&!!&ʐi,nY ._;s:dG:Ԭ>?{KCВoqwLOLLy<w0l?! Ƕp%xz)2SNmh6/Vy`(}C <&Sq/m?~q17uaYOqF9#FP3&1@T%sZưJ,s%R74"L#W" 'n/WאkՊдug0Eƴ5k͎瑍8[bxtjR*@fn>ɠm8[S֋n;aq tnහ�AcO_jw ,sq۴s%yx}}L})bN53>c{Z`&-W_c_g`@E_:vL/W_9^hg`&و9.Z2Nr!ݕK歆T Gֆͺ_ =E| o5D\L<(n@}1:|29Щ-= 5*F4ĥ\\0ЭOMlXips+5^ kmr1zzGx(~/^{qK`a! -}ĤQ\[:ػ yX3%Qjw6NǴ#*3|i5ؗ!㜶yw$+t ȤY-ڄzl_OKB<;F6xu?W٦ <Si>s zZtOJB7Wᳺ=CiJ2�kb*D"|JHPWC0*sΡSkNn=jM8ѻ3nZ!)zV{<[~K*xAU=-?2)WԝȊ +i>&;{߼|P0Ph9//x K=:rn0:xnn&Ǹ tW$ߢwEj<b3rf/9H X׿ƼQʼn Fj`Ws@6N#&xC8[ϥ[7gZC[Vu;:.sÊqZ@ \W-YxzaM@߅Zٳr Zˤ Gu+Rp^/nϻF}4j?[.4>8 6R)oNd#`E%$O5Z�f5a*ӅEM|gqL7{qLo!fiŚCf{<Bs<'>4;r`]:,0}ZtJv_X9_[ сbh\  �(KDXtn `>c;sW]aMH>m -< >dÄ“Г#nӱ.Ma=s+"Q@b{KA~` +=Qd):MPpKcO)3_X'(kcVrʶj q#%FC| l[ŀ 9j⬀'9()b leGx9}TlֈoW,DRZ6k[#!L/mE9KmȜ$`5nΕ-HpJaW83ncBl8 1sq$O*ҧ&xcmΧgWqP(۱d-(@Y#)6-< ,3.i͙b-cb)e5.SjwϡPI%rE:*У; cŢ'R: q280rT4-W?Nj}odFz?�Z*Ю+^0|rҲ&cBP3gc F7͐ðҮ|4ji۱_&phG>j߲Ŕz+zxɃ�.q|PF~bX:ޫ՚}̈a{yk~71_gǴrgiq~,[_ jAU`dns̐[ =+)D��*IDATrghF.(�|Fs)sGsM6_R;?:Z=_%_Q*PA387@Y^i˂9&zTPҡ(VxtƧH#26:}ȃB M 3a&LYҬ\<} UNvԨZ X(@g#SͬNcTic>zVOj^==jJnkBci:Y`FS}}a{s2=KZa]({TƇW8=o=+PT,4C֩UM׈O/3w )螟D rlN"qtp~}�M..:`$ 2WQ1텺,ߡ3kOTrNfHJx޿3'9{ᘘ@3# kBlt|?2X !ް2pV#@h�]7kFýg/F2p0Ft|>Fk7KniQ_uCM4حi`DK mvGP rCz]e9u' Ѭ:wWvVDl/ꭢ(i(i1⫣{s|ܞY/r"C{}y)=7yh̸5[I?zwna?u=uCqxul|ғ"5 lPE <nYc'`JN=M1jQTG& .DDq4lWt`u "qY/kBqOgOY8ޯ_@Lm;U7LNƚXj=ƺx_N۞c@q A9h4?VUHY--pwGD\2H!96r㮀3k[#_mۃwT48mPgm Ldvꤩ J~ ]~x(`BBe 9YZ=)k :>!]Axq^t 30{R NSnUo>\7ţ 1.Kح2n5(oT Y7@ `z= a99v* &=~©V�Un0PC1x%CihChi:wnx٫x:>Ag넭YOc0U|ЗRjeRRFLFЍ&Y mwRF.P~9^ý<Bg N.$Eb  P(l۔+w1 !=k?Ύ^^:?Y�.fe 9+Y}V<zL!x.o =vou- z<K\*NZIRQHt}(h[şoϻui'f“QP3cMAO/B ɑI5:Źr<PDƛZӨ !XSnٞK$\ owrZ4٣5}yr\mPZEIji":n@0W/ϊxR/F//Vgt,}4-2Z4߿5Gb([" !.%>yo~F[*| 7M%2ןEèEfAFmOјYgմjvow:Asgh#r{۠nU 1$-9Msm+dL�a]P vai:)6[}JG0Jvn.* h3AK `"8͑Ic4+ 9E}7r"FĦM߿ 22R~ 8 ʗBg%+׉ԹK>s>|aNXx*YA>P%ؐV}[- L`!>(0HHHDӬ}V!r&=I)888<uFjj*&ӱ[TcۼpWS^"u:[]�_ϛY i9{-v8ZҪSgPey)0MUev!d][4^Kxr]�P&U xwlW yiꋴjiiVȅWWTՊ&FDΠ+#|fħ/%B�lO#BKy}b7LI睆e0n!<9`l1mO/RW<O#BX__֟i{�K�˪7wj }G fv*W cs*;SU~voKC;XycTGQg>S0V?dՓPxР0\:0g]/Zqŝ9{ʥϿ֨X#iQʅz�|Uwg41�X( WK16b%1/`a(nϱ5Tc,-jOa&V{Ԧŀ:[K)m DOyi7.ڎ/MB5yAs^VE#Z2Qc_F3#Zem)MV\e5aRV|p/GB~͜}3+[rgکTvgn lkcD&J�Y^פW^b5yȅOCs}V(II4&Ŀh99_T>n .&X,VS7tzWRr iVsh|?B!'!,<(_(3B<F9bNM#*:ζ9d 3u&L$C94u&!B!_3BiZ9#B!xZVB!B!gB!B!gB!B!gB_{wUy(`=3@DD bQ-uk]k}*ZT\P@T* IsD2,b|<yr3$I"d$I$IqF$I$)BI$Ig$I$I"d$I$IqF$I$)BI;Wʒ!I$INP'??s()bmv+$I$I$I$)BI$Ig$I$I"d$I$IqF$I$)BI$Ig$I$I"d$I$IqF$I$)BI$Ig$I$I"d$I$IqF$I$)BI$Ig$I$I"d$I$IqF$I$)BI$Ig$I$I"dCBysÒ$IS"s@5,/PZ~u7?T֙S%I$Iy ~LI<xEsp.ۋύRw0s@$I;gm zݗX^Kʃnfd āLrRb/^ܬ}]cc6?n_OAz%'ܖAhE<JOcC~|schz>_,a䙭Y<?0%ӟd)ֵ̒1o>yINЅvN ӷ'I$I9#Eh8 w@I=;kN*Vpb+~yLXTȜᖡo0)gG[Lq_O9mf|!wE9 G|Dz+�z2aPt6v!2[YYRI#1yon徧KI-|~ӕ$I$�㌴xy @^ s [ũ߾$ryc|~u ?O,3W,b;9 ~FǺqN>?ELYN{YҐf;oiHvB9f@GrC9~0#bTYA6y\~ěWE&I$IҎs[ H#/O? 8JVpx걞y!2j/%^>PxzOHJ^^II5ͩӨ%Jx̺4^ jCkS *tagN$I$}x䓵lw'.GQ)[:flE)X_{.c V%ia.b8!M%xjS^=J* nYū``{Aql<NfN$I$mۚ==ţh;V%neܴ5_L"x|Ziح&$~s֥i$>y{g3e}W:dXStDZx4?&T.aY%,1f-p?gwKv.Da:O$I"&'ǽMP<s��@,A1s~ͣґÚ[mz? j?֞ӗK!3i3pI#\p!Ědwcxn-4nv4 ଡŬ<eWp/:H$IWP~}MH" C4ee4k4$I$I'[~&nk$I$IqF$I$)BI$Ig$I$I"d$I$IqF$I$)BI$Ig$I$I"d$I$IqF$I$)BI$Ig$I$I"d$I$IqF$I$)BI$Ig$I$I"d$I$IqF$I$)BI$Ig$I$I"d$I$IqF$I$)Bi+ � L&3J$I}dX*ls[36A@,"$I$IUQQA,0iX 2%I$Iڮ s,'(bA,FIiiaI$I ;gߦ8K$4H$IWIi)3Aa栤*aNI!d0&?/DtI$IOP2z+S, i7qFhiHIRU$I$b1b8|釄�_Ϟ C qb]S$IT{cTMQiTт(OI$IOۦC&|h$I$߉13ƛP$IGiK$I$E8#mGxaV W gwW ;ʙ�| GԻ;a*yh;X?^ /3e!\̸ 2K$IҏqFڎg$y鮿qL5\s9+Z։1 ,q{Xg Vryw5:s]RoO�Զ6]? bM3oZdE-٭Pr2fK$IҏϜ! Elu )C3 ` u{t?|F݀t4φGd[04f$I-㌴ Ȋ,ՐW@缀/>rHǸaRFl<cHr-po( f4d!Q_xjθ)y'\s8帟`߁@I̝$%tI  4fd{ShrRvw0ύ~5 Ӿ~=뀥>d7p)H^{ z6b_. LEL;ާYFՁNG)!_st>>`h{֭Ll=?=ՋfҼVݛGMVl~#?e(ہgȲYo8lKcAv!Vs.[8΅Y~QfW^$I&i@ߞxu$~o mFdoY=7�.݀oS4VB>uk^K\ìph8PL*aws >&Oro /g΄Xg$G6.?垉xK(n{,<<*?M&[\uI0yu%g=9Ixgd.|% mů?Eoq- uiϛC{Ҁ)Ԣrnt8rFN\IGz=!9|Vrttiz<I>zn: . hW^Ƨ=ys$I$E;g$Fg^N;}~K :֘! FNVXVR0ZQo#er$ڷ1{Paisay=I/=X2m[Hb{bK0^ {<ĚpDxJ.=U}ӭO!?Eа�px8p"Zҧ>x5h ^U 9%tԜ6 , hu 9[T@^�z�YƭAϡ`i7;~4wsM%Oſ_KApq\! Xث^(I$I0HcFYs,ܗޟó/L櫿!WkXRRY�(6Ht r>vV/&M썕Z%_xl-fl:@,;Zylzov" M�Y٤RI2?ͩsL=<0o}:ugHԩ /η~~yghJ͆t{6%3em Z^![�$vc$I%㌴ e!,[Wےy1ўu_jC n 6_S媳lF_8zN<0kmv=|ɧ<<76.9`:6sV= ŇùE׫YU7O^˜UA, ;4C Ӑz|$I]ϜaUn/f??ͷ  ۺO jR+`}fV,i4m҄&MPAn^!,5_C6= Ȧ2œuXdJ C4;O?ǞػLqSk@9oC/VRԸE$PBXݵ5@ݚ2gI�ί [|7Y$IvaiZa>=F%M Ęi.{FGf8K;g)e+.f޽o f(ˋ1y[ K߭ڜ�6m˟cG/<5)6&?'ܸ h {ie_ŪLzajT2 `r6~5Y[\o7tU M x>{e>GAjK$7-k@u} SϪgL;>]CݫJ$IҮl! x%Lxy"'2iq8XC!晎Yк!} Y~;kcħG_OfpOk6 =zY} 7xV9OW~A4$#[2jݩ\xSԏf=YPw,=<1qVO\ԆG ķ|}%QGO?Fֆt~x :fXc!50xz3T ]c$I$!I$I$5I$I$E8#I$I!$I$IR3$I$I2H$I$E8#I$I!$I$IR3$I$I2H$I$E8#I$I!$I$IR3$I$I2H$I$E8#I$I!$I$IR3$I$I2H$I$E8#I$I!$I$IR3$I$I2H$I$E8#I$I!$I$IR3$I$I2H$I$E8#I$I!$I$IRD$mc����IENDB`��flask-peewee-4.0.1/docs/fp-note-admin.png�����������������������������������������������������������0000664�0000000�0000000�00000113451�15223753015�0020170�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��g�����5!��� pHYs����+��� tEXtlogicalX�258,9��� tEXtlogicalY�99"���tEXtscreen�HDMI-A-1/ �� �IDATx^gxU{v74 @w#IDA@D Mt DiAJ%J @MvwkY[@$ ﺢ?gfΓs9 6,a.ȭpFDDDDDDD$ )B gDDDDDDDD,pFDDDDDDD$ )B gDDDDDDDD,pFDDDDDDD$ ټ """""""?A ^1n'şgqRwm!fp>m!bK;!Ѵ&AK;Aገ6  gDDDDDDDD,pFDDDDDDD$ P8 >L6Cl۴~\ [ n ? jb;b"#Yy$k]DDDDDDDD3; 6`<=|E470JH/ErWTW ,y7.CLd$G0\N&�w2_:z7aֿTsw-F>ץ]SP`dhT)40r`es+ADDDDD溗='ĠˑdӖ{'2腶XD$7wQ8aT28ڍᯟޛȟ?p*h-`&`jU|$Ee$n*2{19b÷{n:8x1A<qO)5;[A#/3E$X Pa'|XKg|p{W�C:`]f(J=8ڼ]w8?|w pVx" g$SN^JБ#ɆqaoGu<?ǻa?9oJɿfb8�zuّ�}u^[ZGDDDDDf�OF1ӍNO6a>}#c" ;x&=֏_&o( 3y K.uW%==4\ػ f:55 CV[U�>nKL.z9SD3c\3"غ}?oLGP\{+mJyGʱGX<cJ{:rn<ξc{p=RF̑!?2G9m%bܵo} 2|ٲ-!\#SJcpxRN;ybاXCbHuuzց �mc��xs̛H-8oWP?׺s\yh\Fa֛8g<̻߮^49 ~4gn`wa~�Khv;0]32ӕٯ%jZ6l?@>KvE:lضNCgDJal73w*<}&%LZ|p Ɉ%R sٷ}#{&yk }_iZ\[}; Xx{X  Ѐgꘗ2y2=ƞ,vk=`޽(NK~�ƤV:`3 Sh le�@{CP'/&@^ZǏM枧cxɔ[=) GbXn@թȬM.máv=[.Pa,8 XuK?1r 8$/DEDOԡ`&ps1xK/RR +uz~WÙճ<2B hNƷs>^'y {JԼ\m+iw_;U�sX#4xj>}7NzC-N?_:UDH!0r,:]L o)m1dyxJ %Nerx3ޟ-Fl:y< P|Nݰ:A`� [ l ?h Xa{mlUk=(7ytSePH[z=+t*N0V{)Gk'ѽy}Z]^cG!|fK6O= ,#&pՃ{~:㟼Sᤅm*J}Z>Пя1gAu Xhl0!t0{$V#�#'KZyr$- FX7#z BkrO׹U ٨)<ev;JWEÛ\<X5./c�!gf/9r1ZK/2e H> \*l*a�eJegwT.؈ 0`@js/ SH<A36˄&Tߩ\\!!+ XW^p>_7nρx@"""""d�[ZݯtY 'N!-8dsj-Ϟ%mT˾N ŧP0g- F6 [H6._v�)iCrw6 Eߕp&քWPN?S^[@v^ KzD;hҲ=2i N*K˺9 ,W-9[bVU{7/|c3.C?c�4oٚU< 5x`-E0Ai0v! |ƿxJ TA’&SW‹9] e^ߡp5pSed\�r[RûUnؿy+NFE#q|}^{HʩU䰘 ]ܳJ fr"~~80>y7C{tĮl>q3fpW+Ov,]ٽYۏ{[Z>cC*yi<ۗ0imq+S\Q<.{oo7<w$﯏aC6!#؁u| 3Bv|᜛ f>s? ۾\gm L:]=]f/Y:a;i+IY?M8}0+P Ɲ!wwJXTFL^p;qY\GP{OPhJ.A)px 9+V¥Kg,37ϝ8s|7돞a︰{vn\ܘ8Tp=̜x,Ρ^U|@λsSt0O3V}Q= 躅F/`4``2(z[/?- 1[|}|진&1{K)D1ߟ\ Gadħ=;ijv@ir)Nl_f2@@p0{4y25ʯG�ZTfY̔&'$?KZRtau&Hb�Dz~0GSMV^L9 Z҉Vy<S4"D@G}Mɍ6| SzHǧ1 %><@. m\ïH6&$b"Ve}*u (Mua3V|W -bQCwL`R'}9@}}[Z1HS{S@*š2&>ѺY~~Q-wd*`+^F˰|Md$+ǖ$)`ۂ%K.}l(f<�¢e/ NiL'x 0q$%v_ؒ*\? K X,t~` VWpi7x&I`xd||�dL(�lB`e~+ ͆mg7R9|qt>ܥ`X`|uTL䳂Xs*=5M5gFve l~nĿB jFo#6ou~dT(t/ ]'�&VlwkA| jH~:T fQ `ŠExz,:ݻwqN6o?σP7?Qf/FPoK6ӣZە\-sg<@`B?Y|٫`*j@ޗs9Du aow{8I>L$'2"tDgR>92�bdElXtAߪ3U w^ujtFɬMQb3WؕxkWP?4!,=WZbz.RJÙkŻ)rЮdQ0*g7�;k$YڌmH˚ o~L\g܃Gų~FF43ncz{9+|:Gk.(82I)θ!r6JqQbZ$C172m},`!|ZB`ɅXlIxpZ8Ӟ ۶ڹ^"aZKaGuq|]>+$V6KŌFE-_ 0'za�VOҾ:wk7Re]f'p1L@.}? ,M�xK,?ǴiѴ662$;'=w`'-pkc10 0, =?W1lhzoiLqFl3y`8jt҄džz n�X,gZY8Σ&rvx/%4`3xRiN~]pul?}e<Pbcؒb+Az*`^m"""""@6e)/+I,9IӬ%Ǘ`"y[K\8^ !0A+.=b#H'$-HP8X 6&Vd`]$0q.z`Hr& &={#@=KVu5iVƑ81'Zk웠w@~Y9ގԹ P~\УTN;tܸ۬]3iBq7_Gt=�K0c5Yl>_;!ك۬VOk>l:u*wW*K IscUmаQ|V l ? d/�~ /s7|=j6NEYۂ +RfPgj?Àp,gs&ưo<d5"~~(]GN}GUjU qݵ da.3%� ޢ\x�< Os]6!bd%olzGp&$y }.s8w/_toBd~:VDZbHܷnʞEv u4M}T%1rlNz-Jͳ򵼣. Xs>ws爽|\Wa͝ԨxV sX3g�Xs8gΤR:]?Mz%xC {~??MWԩkwNqYZw7݁7]L+ ~q|6bo24yTs"/|ݝeQNj<]Ze[/;HRvޛ0q?0y޶6rLh"_yab GLp'a=^!H -RE|� II P_-R7}*yi{pi&yfnkwa`UD^pZXBjq {7m$HD-7Ssw,PhV,/O_pK,x:Tі֢`INQ-הz% R~Nv~׳?h$`ttxųWc1i:$~OSxm^o`ҏS9v'и[OVúc3e[0 lK6w׿6'?8�Gl叒N8Jk%_<^F\Kq8敽D!v.+AS`v$K:TÏP%B ]4yܵLPlYsڍ}Oz!+X< :KEDDDDopŖ'<X 0pWlz^r-Eo}Zq9rAEt'@\Q(\4iV )0gH5 xŁ-2gw'Mokaż|rVmʶU`vΟGÙz^.'{Nĕ|\Qe�[#x}[r6`Y4|l k Y797yGf\)e30qzZj(k�Vy;0Sc�5 VmN*@`e\޽'H`/޷ݩ9�z'7�3:lAXyI5\syVm)&7MAϐvy!Axvv|{n̞b>ZͫVɜe$ݟ}`РOb3ߣJIL*yB.6yO<` TzOsQ/yrI{p2Τףy226/H):7 _}93Jj63-;k~q6YV @M%iWw=vě$E9ډ+2ܻ9 46?oz<W_ƌl'ڍBv�n`γrFs1";Sn7q)yG;t4|tڧྚYuԅޥ ݈s4/dgDȊ/"""""rL wkM(}?˗Au~]a !fRHdbe=B@B=ݙ+?9SIR.>Av V5wI{Mضa7ք5;Q<w.R͉H9pu)l>T/YiQ_~3t:�6".>NCXjT+g}d([O ռAAƔqpu12YoDVX6lUg ŠS~�Уb/3}xlK0焞]+բd`3dT< Œ\u#n&>]' ZC7raz7NlrB6G׆0-h/;HЬ?J9.[YλLNܶxy^J{gw{9R=m:!WvHҔnϹĒQ~_ǧ8M/ϳi/d1+w+9]Og:lpㄏlF'?Г� d-u u#XB8`2I>rᇘp<o>(!2}&"""""">x~#g)+9�b58N\Qٞ닑'0n>&9! F'سA;۠3.g $!6 P}Huj_C*B2r41q_Q+װ 2%ew yϿZDrj"՟cˡ(.XEuI{+AOg3޽E4ʈ|l\ F=qa/?,f(W`z&_Ƹ_qVxpioIc%j秱_Zщ23-`ق&m;1>~3,nbqu0Ѿd֏MƑ�4a0AT{AG)&[pY)T 'cU$ˤ5iA]_=kqCG±u 6O=MHFCnfĆ |z =]DDDDDD2-gk_>B%pf~ gkiM @15NnL!TO3U�&B,X ZuHBHHuM^k<yi!}f݇#BU?gG �� �IDATߨN H<KTvNOƷ5im _݃SIIn9JApPbN‘,AӇ'Iٳ [7&k/ql_]qĹafz3i굥>oJ4SY{0?˝Ìz]DDDDDDlV7+ֻ<S7Ϗ#9[Mp#gn'׎yDxw'G@FyֳI>KpxF*wș늈Y*\\=ԻI&s gDDDDDDDD挈?̿ɝFΈŸvu'\#(O(ws'\#mM"""""""I�PxvQki,iM""""""""YHገH&I۱wInszDDDDDD63""""""""YH d!B gDDDDDDDD,pFDDDDDDD$ )B gDDDDDDDD,d۱wMDDDDDDDDnBF\B][C#gDDDDDDDD,pFDDDDDDD$ )B gDDDDDDDD,pFDDDDDDD$ )B gDDDDDDDD,pFDDDDDDD$ )B gDDDDDDDD,pFDDDDDDD$ )B60Mӻ$rS]Wн/"""""rgϫ7Θɕx8RS!LϏlAA7N˅/Պjjb]r[:\? 8ȍHu:IJJ‘L9i`\coNDDDDDDn?NAbR. __T`%$dz^i\p_?ݻYHv8Hq8ȕ+u74M,""""""r\3̚Ӧ2a f$K`\|I1`FDDDDDD2#$8gE&Y+q$'$rHN~.˥`FDDDDDD2-$8™ɵJ3�8RSo:"fÑ]L3"""""""#˕AgL[_}iN'""""""nv:3ܚp&3;*vV&n6 ]] gDDd#""""""w<[*ɌzT8#"""""""Έd!3""""""""YHገH̬ &՚@F fY'5=mlƍӲ7}!- 4j['�EDDDDDDD2喇3i.)+׻oIsDWwukRًѪ!/Cly0S7wV1Y't7]nX}aq˻o3bo ټdJlW{0/n`͙T)tI|w.xPlY� Z] [1_3>}^`Ý u+�&Ӧ5k+Ouˈՠ Q/ҡ(j5oOVz䳘q{xCf&4o [eвDZue$||u.m6s$bqVY:_\iSDDDDDDDΓeLu(Ҫ+/1 ̤ {Rᥗ?iWُm_>ސ}N۹Lmه$6(1F:=(jRC?�8×ڷQccոרOZ%} tn%V?_Q/`; JvLX_<ӞR #ȗ<EXw*~NDDDDDDD Y=\3GS/" nx㡪|4Ux=^2�K6l9" j;A�;3K;)o3[ޗ5/<癟x/)~em0{0u^ye *nkY6Dh؃`+Dyxgeqv \d|3fpxFXa0a` $ɰ?sdY8$>ɾTMmEP ~IODƸN}K 8h\3ӯ*;va[�LQ<_?'((OV"h5cCAJ `#G:~ 6^`PKu32�B�> 4')ZPXDDDDDDN׾�b+jEzO&>}5qe7ڀM6(�k>WZ~:vTOƧw&w?d0~=H=ȘZSFDDDDDDD~_3�}un8ܘ.0�#]"TE0sPA|ٹh >Y"E6e{48�R�z1⎡[T#A~?I59)fkD8̀Ɇ#wR"kX MDDDDDDDD,|vxN6Vz+@| B|u 'tN\g64t:1&usѧΔ-4)eZkwc�k' ^{#) F.Pk ΃�Ih?q&q│>КoͦeU8ŮqNѭSWI#g�Y0|K Ucƣܗ/ 1 N& rZ�k;F�v/ro˾N*%݀ Rl4xl'9q 4 ’.LOQ-{vR'/b\̰ 0en4ٳ0bl >H#.!/D1Mhrz7'l>Z>|T>%}SY: yw 11 b`un{>91aa"""""""lt4~ܚӚn.;E}Nv-_J@EDDDDDDDnŴZ1+w ?<ո /7kxwe3>@yQswH#FΈ[ PX1b~ͻkr6)^mi/;ƻ\;bȿW}2Css>4CnHz,]ru(74~[6h> N{@_r~W16+#˲S8ߴȿؼsn6L|Hnli7rm0$M¦jwX2f +&lZOGȿӄNwӿ S(T^9MT1λ뿎 fn&bܰzJ0x71 (n"(ge/Q gD"RLx pn$/݄2fj;c+OTQϠ~\?9#/g'f(SNytw9ݺs+ֹ w_;l�3)(PwWN gD.aGx9F78EwS$.“K;F*jn n}>M7O3?-3])"xtȍ ÿ?͂Wy5spv.?) Sp>֪}[\n_wy 7�sźLAc; vm7�6IfrNO \ΓKбTiv/zo]Uj-, ΟI{{TQ'H 3FdL@b)rByyuCt~o||sOz/|b;29={8$ ]eP{B+%;wbJ3dqQP.իBׇNqL;fX!u[z8.L u_>ŭX+ `Df}FJPb1zהͻ{CDDDDvpF?@ɧc`+|]O2m6 ӱ=Gxy l_ R)CX20c4fJt8'9q='i]t"o MhG.|jp_JYH,֟ր� [r *ȶ+&Ͻ:S?J@eX89؟gq&9{~gqx{2't,{Oo%%T|x, NXy ՑB\Y6:7s~󷻒d63q&\)[X=̔ڏslnf-[,Cu3Ϝ.d o_{ nσ |;߿K.р OMʦIg&%ٱqLO&OȥmiE9|16ʍ^eL7,p$j5oL…彪Mm OxiB<ٕƕGe3%`:qA3|*?:@Ӥ{x&]L2, B؊>|.mfZfws^[vE^jDDDDNrL)SK"YbN>ޥN:>L [Ǔ@熷?͖a^H͊dӤ fҘcy7ȉw邞T0sόb%)ws?Lڜ,*icaD$oLg ~i$?ƕ2d{b?^Zǝ& λ6Ǜ GvӄOxÄ3C0Bnm]w8#"N1+<rW>|'LGDz}qC5:rn5q6hNJ`A<U1g0:0z*0M^Yʼ[y%I+ e{`?n`\X7`A5Y&Q ~ܰkLI9d<5:"]hiZ6*a@YҦ%W:o͚yLP7Ѹ)fH6敫0Ngw Z4DXuh]ւ @n֍Vg|X~.XX"͓_h1hQ=?ū6&5gؿn9+c@>e丷=OMDDDDpF_gy?0_?�ύv)W}1"W~P4`#i`i3@1k:M?_o S~6�? m)ꓯ^3|0MvL<<1y''< nOZGy<ᨋԽ4YFF ЦInֿscCz\\}N0g[ xi~GŞCpZ̵Yr[ė *۝sF|U2|3dOzgA~]3"Cqn`+8vJ >#[ƳY:Lط{uDȝ- "@`ձP?4:fP3pnj6*i4`Tz0V|m_oHڜdrEx?g֜\'gWW `<Y[3w۰9T`<,{#bZ`׆0&0 iڵxⳫZ[6d@`"v8,923ݳ&Aeqf]KU6`ce~W/_M:M3npPV`Tni xV85D4"""""3"Ͳ4_xAwȺC.1X@ǻV"C<5T6o0)R {r[(�|| mN=g ّǖ,3)7ثXf`\ L`dQki&;ʺ:v Q=ʟȆ Z̺l+ljf9rY \?#稨eC~::\o]CޭJbsiC^wy,ߙ\U PR<LMOwi; t)$WaVro&-~"""""׊sߥHcFv bGI]:S`N0Lh еMauǵJ|�u=n4ɿ_u ܝ2!~>ܧ x+ ʌu @BbZ^@d치2',pi @3SYo*Dz7bf .Tp'9bqmbDUj>iKn@G%] sn3"JDDDDZub)­؈y뮟19wۇ >HI>~B` ui+A@X—"3b7=Kn~YL*˜.�tҔC91 ;|9DŽYs3`{ ί ,…¯)bB56f {z�̼<v?ЦD.vuvg|>g=<Y97Id�d^Dr9a~$wuw�vY`+39.&| pj>;u6ɱ3 ?"""""" gD!~r5Id*g䜏~e,9ucg>;ηXE3fqǩe%qf"Ņ9i5P^6p{!֕fۉHR8#ri[Ҡː}v 8R\ [uhD8eIqgk%Ͻݨz6gTt/]1X6{1ifzfCWO+�J`) XgtR)#( 0;R3_].pbF×|;r k& z s1A(;sq9wD˕4usй^N/?; *<ĊVG4۶ΝRvi􌈈HpFT G^*TH+270U`qiNa?m�K;umOQ`2Y$0FO>r93bfov/mh`-\<&`$Sgw{*(%%#yDDDDDuÙ,驎 \/Rʧoo."P̓Ȼ}i :B&LV2>v 8G{T؍H{X)Sq{puӧM),mm wCv�۹}{=;ܻjΝ/}-ĭ[ Xe+>_h%Wfo�T@V-qߖz1_9.3c֮W"""""r(5gV=ۇrn5xbCt4=?EkFq۰^>/o{scԕM_ڃz:a})W @j[+` h#84ph1,QlzCUi#zs1'&Nm(])}uKHO�Lƭ͠'W`}afm%w낿sR~>4lߚe+<r49p6 +2?k'ׄs4l {wcri^HqT$ ddL0GHZ0y@~8uWCG{\Fl䚰`qZ+WF'F.p+2uq$qiߛ`e2 vxXZ ـdg{A&|n]5~9lمzJYY�� �IDAT�[3 3k=ۄ9s7` W̶k]B Kfl]mZsFDDDDxӚ oOğtV6V,9UoFSj{,|ݦ,c_}`[-6lIo6J0E%V_oɨA#i~h<)Rq=`)^ 9Ƌ_(ܽLsov[KfaIV#Ιt1} >zֈ{K"~(]W}[Om-9* x:i2KyM-^^%""""";.~/ْ ?aQٔэ;ŻQ#<27x3vXʷ㡥y9fo_Bo7$#<0}'S~er|E 'ʽtA 2(Ϡh<)?362%`\ڏ~s?G>Z2=5(njC(Ma#iKti\ jvm gsf+^0~Dt~ o C/&LR_DCgDDDDDsLگ#ǛV1Z=+kӂKؿgs1+4-۱rdegc #ǎ='( Ի7/ضEɧ3xrtޭ܀ܽbe=ϲ{-M_2}Z.;6r")r znC[:RM\,  >g99{=$J٨V>kurV4C{+XtvnDRFN:e<B5M6p|NxRppi3U`pi/Ԧޫsvק\`X?֯g;WK4Gԏ(ѱ]$D` \g+͈OƩ_7MDz^,7Xǡy`O6=J9xqgiO/Ș⡑yb"{h3n*OsO˂ ^z2j`ځ3ClVZ|_8\~4`, Q˕=NHp{YDDDDDD䢎$&{"90Ix$0Ϭᶂ0;sOʰ@i w;ӗ6@DDDDDDDj!EvI=6:&N3){*ʕ!` 0O:`IɴxBlRqII$>uڽH+p`&R' mnæ?J jDu#l�/wފY|)CjII{n(OɲYokH} F{fFw*"""""""R pӃįIVv`cZ)_Z{2Ѵ@xĒ#)vfsOtSw&"""""""RL\E-,""""""٥.\lFΈ/R8#"""""""RΈ!3""""""""EHገHR8#"""""""RΈ!3""""""""EHገHR8#"""""""RΈ!3""""""""EHገHR8#"""""""R<.f嫯7&kFΈ!3"ElȆljN!ChPE- )]/[.uAOf{hb,~pIIx{"Rҁ#i8t/z~π㘳oG\E gDv^0{D,ͻЕY}p$w36TܾFM�ý|/cf�7MI#|%""""")) *E`nPwpz/ 1+s.&|}*#`n^>/ 903vEDDDDDe/,">тclrbϛ#*e᥮7}+`ciqR*xd0(:n-\6YBeSֵ.5Zx0Dr:n Rol4yl޸rzݣ'w�s8s.1fURrɈˡ;Xܿ&kٱnG3+/ Xc^>/ X _BE׽*`sv]a 㑗8YOۘOw?yt7*|ܒK#"""""3"Ő7V>rq iic?l~t)'LxjF:eΜawsGٛݿ}M:2r{^J۳v8[fh!O-#o52wh£R'a6??ޝ!=[a̝<̓Ɂ>ͣ{X] iٔCLz7teXN{[!J^V'> zM�/֍7b?Խ\6d^6}zޫc1|ˢo>J0iS25:GDDDDD.b�=mgpK>yNX@z7n ))/IXHUU fT^xUj<ރV:vK򕹽]-R{b<�V๖_B3w+~ͬIuL? h ۆzt=}{͎؏&oI{j 974@l<M^NT &ĭYK©]*[;5X/:u{P0aIV̟y¥^rt >V$ gQm*ĠY7[DDDDDB4I2lm�6|ۓSı\Y9:T@v ?e mFuzce{xr U vGAAf@(ɻؙM]cX!VDnbewJ̤_ۂAvܦ6XM7 J?F0GxX!/"4 8r nG9]G >`5m:k;z`g3�8u8O`~ ;iM gDt 6`)͇rYgLWw yS4mm'~P&ۑ/.o޼-ŀ w?[-N}`rb`;^znex^d+z0I&)fJ;`5M& %=�J|&"""""R8Mk)fc۱jaNjrZ-Cl�dVR%{drir?Kۑe9cl`wO! %g}bW`u3Ӹe4Vd`=kp/Ӊp8p~~114vGU%vƏYQ$^@B]ylA;L�?*R)0r%Ka.]DDDDDΈi&&bG1Ư{`HJ0;ƚKXt q-LHvN.6hI1CGvP2'bQ/g]xua6nÌq]v]5[C,lSp(~ %ݴy kpc*`9y9%)*D7EI=}9Xܻ\[Axh.g*t7r gG\|-7JCIG=Z~kC )gLDDDDD$R ,΂^OA2>Ӹ7{,u}N>ݼ:?jCRa[~>;|C%GkҲ}l]ЮQ×f=zW5ݘgf 2^ez`gu{oFΞϟ㹷N٭r*m5i9vJM˷gaF5w /ߑM3ߍX+u/]6 0IYX@H  58$>x7OWkWGtO@OM\ODDDDDBSiiO`&#V8whXL-x4|پ=5nKT!hBX,ƕ~LO'$mX)&D)[!"""""ݑD}}/zݪ3"E!M{tSh^z ;|}8K>="""""Rpfoɋݼ)E>%)Όrd2dr{v'v$cfMb4kF>Kh7{)zrt>ӷk(̚&ʎ Pj3cF>D{G0aQ)˿"K݇rS%G%rLLT?k'zQ2"&hi;VAQÚַe[lq v=ߵXB\-"""""""Rp&Ѐ6]1UԉMunobP^&e;o8 `q�,vpرZJؼe+ng %.0&A<F egHqvל)gG cvg{\R xq0`̿JD&16*ERA%DpP-Y"țDDDDDDDDTBd|4ۖ|˂/СJ7n;żp,n ;9}e 4bg#fOĘl9s` |DDDDDDDD><&'Ny ?^7V^O<Ȍs=[|hZ-K`;3usL4 '8ߥHeJKs]<Lpp$1 "E">!`, atB"""""""u$1o_ߋ^^iM""""""""r"pFDDDDDDD))B gDDDDDDDD"pFDDDDDDD))BΘ "EHߏ""""""r=p0 �l6[Us8xlOk{Å7E `&Iҳt jEҥ""""""%3�>>?~///luS+&'7tʔ)^ferX 76]\22K8JPxk%Mk3aPT)N?NjZ8Up8HMK(U=y=8z,/o%K)l6Jc)eb풯 b`J.Mff&dp}\Kqf摗7Jj`Xp&I,Vo/\&o/rrrI9qRSDDDDDq h o710 ˙2K0{M>^eR{EDDDDDxp4ib3r1t&�ݮLWnwo)ű]Oa;ȵo3 g%$""""""""W"pFDDDDDDD))B gDDDDDDDDL`TbfO�e31m<% gDq9@Rʯ$omڝSS)gʀ#eg2.�d[|.x:D+.8Sdy|7?)> t;R tF-e%I|8n88�cqX^C|2?&?DDDt Pr-n'z&/u=:kָ 3{{w 1Cp 1ѽT$&{T EK=b֯wovzON3W+5l7={@o)N22x}ṳd<\湗/ɖl{<Uy|T_( CNahWbxS~䕛)$ oؐG6mt8s=yϸ\)&e3y9<{Ʒ u@Yp0OEDDjUgۦ2Y{al~x8�iC3geQ{-^Σ߰4n{銋KJbԔ)tҽ;ʖutor)p.<yiif=ylxL(>w]̛y+3g|l d t#[0OLr?l0oo6sߨ5f{ ">%˝^E7t6Zaa.ݻȚ}p?1,GD�лY3*+缍Ȝuצ ٝz}0�wB:FEʰ;x7ȵ�L9dg/RT.gĬJ>i <bz搻`I`z�[v)>|q VM'4Oalr&,W:NɶaBr6QnkYlU�Xð�:5i݃Ls1+x",Y5kԑyo[6 @t;mKzhcu䵩 ߽ې .;ǿCm`'/ ÷ v=<{&'oQnnBhn؜u˼6NÜtW__u/_?Ӭ(_';xxIXe7\v]Q {-ZנqǾ`cu"9auKhEf=]v~>[lYWcĂ8N?Oǧ:c DDD�h_ܽ͛8t+%&~~Dz(vBVn.f�=uWdz:C&M ,Q=zб^=dVޟ;ؤ$*2[7׭_wbNQ/<xa}Ogdڌ,ٺaЮn]ի/xosL N%6)*~>?#=v]7$6<;!91BgpYX ?oolٲL_摑C:uHr;gŋ;t(ڷ}ݺ{,3>^o 8&/]c vaøM~ۺ+ֽ:y9g8G[<w=v8 )A_-|'?݃Z^vZ=89D)IRz 7@꿈0GZc+/y`azSik&�J݀5d!2ܾj1܏5~IںMO<|>Hvٻ+ þKk0Xq인=Z2!|Ȯ?~|v(&}+&?xfU<`'7~�t>md5<bU*B0'BN=`A,ͼ2&)ӵ``cW릲?gGNL>~ AT|ߒnͅ3yP7F"@jck/`qS?"ddg9&ֵj] ά569ZW^`#0_?gmƪU4Ci)SVA2i7oΌ#Ͱ/Ѽj?\ɇ|ϞL:R s稞.wؗ_a>ya&<;b̴i<Ž͠?R` _ =mڰxfc'҅p/s׭fX\>s׭,|L_{Cs8^{z5kƗR#4ÂwaXX3nusYkƍfXuѣ_|+;ݝmZ{ 3"ב;+{eLb+oyY˩L} s~[+~ǨܟKRh0۞ ըώꭌ K">{*{ӿ(ߗa&N sʂxX* K+Ј`v؉_d=<tz,Z̓sc�� �IDATO[S]B#y42Z$_:(%jF ry =` ǽC)Q{$Kw3f [J o]ݡmؿy}Mj8Xm?sư6AV~EG2 ~O?MCV l͘ö3xkE,eF. PAl<Y;�φ7ۚ]NߐM""0E۹PvW"+/�O,V6==ވȵADY99JH`}(AFF:Ù-483 OO�m6l6ggӦѢ*hNfftcȵT˕c@Ы�Eص+mj`^ۗ}8tHݟ_v1o_ꇇSR%FCX,Ga[iټzԩTurM7x4}q~=CTGOb?LYڶ{t45BCӷʔeˈR]P=4{۴id^ju s,| {] ڕժQLgq-ĵgS$u{y-#pd6JZ4je)kڙ8c 6o%\n&hGb<O21T||q~pS8yF7/Au_?&>q\7x^xm*JlІ$ڄUțbQcIxs,QAf# v;'eˋٹ&I!>`PΡbtnjȎrtKmq`6*Mv y#c"ЯW&*R~29L(⋊(Ϯ%ސ}VJ?alPr2ͫYd$͟OzVޣ- WWLUiTj֤sSڴY[7Ã,⒒xcLޚ5yd"˗w]0X,DnU2<.vGR5$3a9E|qǁD:VߟFU0g:UJvn.))ԫ\y �=Jnp~ y!̿bkP�<={kuܳ%"Bn#aC?˯`00 A.ya�0q}Y+aKίm[}_ `@!My9^W’&iTn:ƦŰ;۴v00(,l10 `52VȿO(mA죅T6mT\]B3f:MjV޿ 3� 웗|S ԉȕ "쌏g@@ޔoW4MVv+f2Gۙp!̛wO>0O](A.mpk{/Y :ޮ-@(_tqζ\V z]-u.p%!"*;Oc'Jkqaeo+tV2I_0IZ/\ȡjbJʎ}ti_]T9 Nbp}Tւi+t&RAwX5n Icܴ0uv 8!/ί6˖ⳟbL>',q!9f=;sp=)oU|#^9|8lT R` %˰Yue4񶔧I52VPZ5aO yokɏmxaBz:? #�ߐ l>f* C#τ3{ٙ3aиZ5f\Iмqa;v0e2jWȣ;efp&|(_ soH@yS\ `Obq9qqQrgwH.i ^s0lYY};6 e˞S*"(uﹼ*ϵ\D.I x! #[lc6^}Gݬ22x4@/i&v~ǟcp4vdĒtjԆ]3k>{q͡W<e[͹RKpg߾ٷ/H%ؿk\֍x"w؄ 6ӣ;wL&uH�UǏَ:5.YǙvNrnh?/#A6aHvKi]e8t 9Bw&#ozpJuVjU=Yy*̽xp9fq`G3&%|J& W=g)vAo'=Ss6)G Mshר>FI·{Y{ qz�(͖ߋ}ʽ=r;;uYd$vn}>kܽE9Lg`$֭p P|r%z5_~nG*o@խSxFNDZyϣu_0xglNgda~/3e2' clѢݯ9!iz7k|LͰ0Z֬ɜkU+7ĐY`A;Zmۘn,ٺչѕPϏM|JD̗i=Gýζ#=̜„Qϱl\*1 *Xn|y(sFod}Ǹ7܂/_~4,gPH|5Nkf7eWq$,R)vL`}l/08'v2W�[TkI ة6yYC-|X7N$3ӦUZ!2!jw7OOo~X]4R<WGxk N,% ƴ_}իPf'�h~Ukc'xT.p ]yVjmGؒyZX#yALgx,o|y;" <^Ɇ큇5g:'KTi&t"Yw.Z{n ?k?{ khGn"""N*T˹LEY뇇du̧J|J رRUzb…:2exۜݷE 2`6BB{ݔ%ic`w2?~<aб^=Vq}8`�/M˗SBFFv^q 2S)O3e2FFRߟLY{Zਤnڵ4 ԹSλx##L!53~[€?ˋ[6$+R߾ϼ<mM##@r߶-| L^*uWzTZڿ5Ie&tBWԁZN;h~wCyi]kΒ缩8)$.n'/;s!zyx�."""""EHb"޾X,siM"rE=\Jăa;{g>*`FDDDDDZpFDL~5q>^{O1c^>F6e랦55s&؎'Ui&P֞_xˡiM"""""R\&\$x?땦5!3""""""""EHገHR8#"""""""RΈ!3""""""""EHገHR8#"""""""R<DroNjqݛEDDDDD\DT,T$ΈMuo)4IDDDDDDD))B gDDDDDDDD"pFDDDDDDD))B gDDDDDDDD"pFDDDDDDD))B gDDDDDDDD"pFDDDDDDD))B gDDDDDDDD{\]ݛDDDDDD*(T$4rFDDDDDDD))B gDDDDDDDD"pFDDDDDDD))B gDDDDDDDD"pFDDDDDDD))B "R"+3ǽ //<<%)ΈsvNJǓRe�329y*R%Ј\c4Ioo/>>dde.I dBI7Yf@.�{ҡK3X%˕v]0&>9~~y 'g9%Y6<!\4rF̹|Ǜ䓔s=MRuw9HOps fM L=DN0g`k:,4sXLtEVկF�%E{~) `t3R-3`ls/lxms&iwo~ǠC`S)=lr,X*�yt�,S]Vyy| gD伪y@ZV/Z0Y3U[ �kyfd7VnĠu6IpOaI(t9"""}GYUs̽3aU" bckLAc{'1!j4E{o+" H30{~̅AZ߳Ykfq??I&ߜ?Sj\l QҶ �PBX҆eوe%k47 YY`QWH$I!@`IM:k)Ρ>ѲUK"BʗQ WEyXŔWTPVQM,I$I'3�.>7Ag2 l3u><ȻSj~8 (_M$I$Ijۚ$рB8qzPQC-v9=1qGߥ{m:(HԟC6>W<Nf!�mB_lGsD^$I$}H\*]@eU5t0?%_.!.Z'VGyP? z<9ocD\xٴlVC6eኛ^^G~穆3$I~"$5\.Gue%;u^UojJ&B�TVUSUUKI$+I$IkUqq~i||ńaH/3RL&(i݂.*WH$I҆pF�$ Z%i"D$Iݚ$I$Ibd8#I$I#I$IH$I$pF$I$)F3$I$I12$I$I$I$IR g$I$Ibd8#I$Id~ApQY~I$I*./pFY:/I$I~@$I$I#I$IH$I$pF$I$)F3$I$I12$I$I$I$IR g$I$Ibd8#I$I#I$I% d"I].6A*]HAf$I$I͘+gf.HR]! }&TdH&\%I$}9 jV.k\f.QP J5R?^C]."":c|8Mth~$I�7)4O'FtXʮ#0OA&1w}-?M[gO,'Nh ԱcmNm__,yc*?,$,?A2Zڷ+/"IpQT"xEW0i߻3-m$IbWlSJN_J9`9k@>v/ء۴%6Y. J0sg=,WTO-f]lTR`8#)�F-'Dm So$I $€cnF?5iaT ɞMs#b碛RNOa!Bк\ D�!Ghx&%n~|J=ЮNӬ;pSU9?.n?V魟sNߵoYIi!L%I$5sY`11>nF0/rݩ -pI{7WБzZ�ڳI].up/qߙ'Q\dɍkS-0A|P7pF$I L8%qhbb&?s|Tڙ6wQ|-2M>(.DGgeإ}3D ٬wZfF׬m7m$I$I&ڶ|u,*())a]oiBƬ9NE-e% j񐈊ʞz -Zkӛ&b]?$I$ImBr8@&EgVѯp.v[fY+' .gӦ龙mn($I$ID�6Q_{k.Qg,3VB L&YlW K29n ~>ۮb<Q)^{(ɕYn~z"e7vM}T' X^QA.[c•3R3JRQYE*"h:OdsԐJB?%I$mxV9kj=C9{3zps?BJ:u請TdF4'/AoϲcXZ%ClߚKvFw�lcٓO=o{:Iz ~56ɾV9{l-lӱMn(uIQ娮sNԼ//5L$PPE?PW6K:$K$It1N}>>b0$bd3SIr 7H Y0<}%I$Iҷ`8#m�2 ND(Kff2$I,$I$I3$I$I$I$IR g$I$Ibd8#I$I#I$IH$I$pF$I$)F3$I$I12$I$I$I$IRIWuM6$I$I1b־]I~I$I&I$IH$I$pF$I$)F3$I$I12$I$I$I$IR g$I$Ibd8#I$I#I$IH$I$(_d2YkjjNNL&$I$I͘+gf.ɲ|yA�ە4'`*2l$I~q'~?ԬeZKFw3R3W]SKAaT*?Hx 5L#D\> >řrU)'Q/U$IzV 57HQ{hS.%r~{%p{zo$2&>t)A dhRNiKzn3Pen^~C<AXipFj檫ki߮$d"$Y\Eel߇3U9M㐲̣v{'3 h$I,�؎?9? �pˡ=BDw2?]N[mÙNȓN,ז/W=UQ <s#V`8#i~z,],A`РA~q-$I@" +s2pфwٴd-؄�fH{q(^;%s ȣO1u�!M&8_'DχCa_YTbغ~0==rWu?n<Mv9geW魟sNߵoYI^8-/2cC{!ѩq$If% \zNG7gvG=o.281pÏ;3[`&lu~I]"ޭAv ޫK4˓EɥwGF5wLIr+P6dޫ Wۛ?gsf8#IYl }8so$I$pˋv ;\?\2>e6y 'mߍoq[ƖF]X\h��aIDATp5/]QjaHBU2ETSC3ؽmiRɖ9KS3F׬m7m$i"|\v[$I$$�nر[Ŋ3g�&e!]6mZwJ8mʟ,l5ZŢZ*桋nne E(_C}kӛ&b]?ጤUDt￸(s~$IfMuŭX@:&`NE@&E*ټp6[SZVQ 9 ָyZj�(mtߌ|]mMV1~^-/u;܃o8hI$I?t]y?|mQ /?,HlW r\8ޥ2wݗ$,cRE\F׮�Nlrr{7t*RDyj&t0Y'ރOsH!SH$IZV97zp/Eӡ(M.}uR~{iN[0qm۾kdӺ dp6\3b� H]N:z_.|Q={=9~M_–_ͱ]:ho=m\vd"(Xј=E\J:wnߡhYee~L&U&hQ**Ҳe$IVuI!AWH\2e"kjY,A:]΂a瞛_j//I$IWHќVH$IeLXH$I$;g8#I$I#I$IH$I$pF$I$)F3$I$I12$I$I$I$IR g$I$Ibd8#I$Id~ApQY~I$I*./pFY]K$I5I$I$pF$I$)F3$I$I12$I$I$I$IR g$I$Ibd8#I$I#I$IH$I$pF$I$)F3$I$I12$I$I$I$IR g$I$Ibd8#I$I#I$IH$I$pF$I$)F3$I$I12V"'N*%I$Id~A52=ͬњe?{s AQVI$I+gUW>W)a~xz ߾EI$Iw3RfOvo/¢+.Cwқ �cPNYL/؊2?p[iSo8XM" 7=/C"ة d^]A7!wtˑ|Ipg|4Og[ʘ^`yiy70,x/>|nEgK?_$I$i-rFQ$6@YK>M 75#|F<0 nKO\^Lg,Yj9On˱8:nև/ruzg:~W}ܼX\TΘGóx}2Y`S8%nBy7<XNv֣+߮$I$i-HD0|䷰F J7i^ze??A߁w&̩͂dh#$8: I욚H߽ ٚlgck9JmvOa.#·}jۦN@Hɐ3.]^EϧZ2I$I֞ۚf \Ŵ|jFP(XaPK,OmX<EE9R>ٱw1{R"@_Ӫ}[SwXFmFu6Qb9v*I$I3R"Qu:s8淬"�Zn{wfg�BE4f.жj:ml% @ВZ`ŴܒzBnњyy#P pMێgfWpť7rE{H8&]$Inkb'̹jN;m[v^$0tX~%bG<2y ?zj cO"W Ӗgǩ|>vܼ* 2:M@a۱r%[٧'C\gr,.D>*RZLK~)I$IrF r�o߽QQ!vVX {dן 8mߍDz#y( 9~tD:%u$y~f퓜~.]C #z0fA<2R:$)tn|Br> k8ǛQ0ƓH$IVP^Q IDQD.Ν:K$I>?tq1a nk$I$I$I$IR g$I$Ibd8#I$I#I$IH$I$pF$I$)F3$I$I12$I$I$I$IR g$I$Ibd8#I$I#I$IH$I$pF$I$)F3$I$I12$I$I$I$IR g$I$Ibd8#I$I#I$IH$I$pFZ �ÐL&7*I$IҚe2°>vY)3R L$$I$ijjj fpFZ /K$IFUU_:k%�A@aHYyy$I$IUV^N)]9#V3a2IMm$I$kSS[KLu8WTDEI("ˑ"r Q.GqQTd2.I$Id24le I1 goQ@A.G.X$I!a"_ne& F3QD�DaHHF暒$I׍APԬ2B7Z}ʬ[$Iö" 37f@#I$I?lMpF7$I$ͷҖ$I$Iጴ9)e3fN>Luq E�8gnp8_7orpKo!qzQooz7Qe$I$m g5xhf'.sɡ ұD){>}^8ԫN?Uk�iɖ{aUg?G*=tǐ HuK$I҆3g&d6=:c۟a�r9ssПwQott-?/W(g$[$I Ԅ�H,f u``Qo~s | ;>1h_ ɗ[SFeTdb%rľvA[Gl!mOۭF d{b+!QF7\H.|`6^.#hs}Y<2 zMK?|G <ge>0!/aV#'hY;o–Go/uy~Dɾ< a'oѹwތ_:򳈎wyUƻ5glue<>%'ѵECwۜ>>SN_'pOHu<|M7 *wX=0(5pϙcb{Ϛ.w쾤zx'/I$Iq[Ԅ׎Rf\U}A:>=SXڽ7�ܵ-G2J sĐ/#1/,`cWsas3vMot2?|5=/"j=2<)o>#S $h7fػǜ:\;a^'Nܣ,9n}j?lt ~ahK#s(n{fuSocjn!FvEkucb]KWyP$>sNؑ~<wXR͟/;w^F02bě\c[WC%99uΜ #/}/D%I$Iqq匴;w )=y.su{ݘ=?$ )BR!aAO0Ӿf�ց~gIr>8_sFѪS7 Nrף;-w`+悽yΘ s3{ aG~{n yCW ݳ zܒЮ�Gzٳ ΙF~ ^\ l9+]z1K@ YPEl 7+#>gtب= fF[V#珀''35<PԏNÏ≿_o@]IXj]2g 7mWQ$Ia8#}-/~շc_?�Ń[QSν#:PPeɖ l �-ۤ*&rUK#Ga]-DØ_Ѣs:lܓ$VeE~00Eq"V[ ȑQWR�4�PPH6!ݜ {7]W/fq ꃗ~D--xtI11yS!WC&Kvү.jB;{>t ݫ޷w$7o.lRC ]�$ r2 5I$IԄZƥ5$Jө(64yiPeD #~{P^4CWԇ6c㼓ƿBƝ1'@l߶__o|·<8;Qzhfwn_ӇnD+λY €0whF@ I$IϜ8?L}t +o*) ՚ڦV^|D[TLvgt؎N;ұcGJZ!HZ`֔xmz�A!5D5�tI,oݙsbUJg9^{6)]]pިXh&=<Pkz{E 鰐Cv!H&g]os$n=:1mn�՟4ԧϨ stY$I1 Ş;pK1F>tΚǽwBi 򃃢d@e>r\&rlx;cܿ?\FTzkStS/gO)3e>$gw> :l QŻY_j㞛cт|>DmUŗ@Ny_|fq/$,\y�sp+,sϧ2۶W$I?Bjdx ,|t Te?v /{/gȯwW\3~q Zop~mulT<9W?b8yܲ}?8 3Kz7g}١m_ǽŒgmÇϾ'UG1 2-{+6K> j_Pho<G8?KT ?߶/z:-J$IRsWTij'B$I$Ink$I$I$I$IR g$I$Ibd8#I$I#I$IH$I$pF$I$)F3$I$I12$I$I$I$IR g$I$Ibd8#I$I#I$IH$I$pF$I$)F3$I$I12$I$I$I$IR g$I$Ibd8#I$I#I$IH$I$pF$I$)F3$I$I12$I$I$I$IR g$I$Ib����IENDB`�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/docs/fp-notes-panel.png����������������������������������������������������������0000664�0000000�0000000�00000243254�15223753015�0020367�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������PNG  ��� IHDR��*�����;��� pHYs����+��� tEXtlogicalX�427/_��� tEXtlogicalY�184w~���tEXtscreen�HDMI-A-1/ �� �IDATx^y;lQ}_$D~iADBYR"2(Kƾ}0{?.\L~>#{'s9_#C&""""""""= """""""P!""""""" """""""jP!""""""" """""""jP!""""""" """""""jP!""""""" """""""jP!"""""""= """"""O'hw s#v&ĜgY\{_> Wh%_X""""""{_pשP!""""""h_TTC I5TT jKdX؟~v?/DLdX=> ւM[Vvoʶ!|6?O+7RNng�kdĶL_[7:B<8 zKڿ3%&|=X85c}�O}ezUEBV y"I7kH [݈ 0Baro~_Tۃ[!M3G!-pT xIA+ފbGW1i;I \Ry< """""<m';SA)8{Xg㑽6=ӷdrFС~ mA@ǼFIc`^.qrIV P[̻bt^ps gϗ#/VLI9k=b܂?9WҖH^+΋7hhx ]g:[Z`*rSZ5>MSӽZi77ož}#^.o3̋(ƠKU&g6=Kfy٭;Be'L_) 3 |wۭ{_X> ~4/⍱_#Xy~IN^JѣΦ=v[Jpof`PTeI*TxO-Ȇ 8oS}ADDDD�^y&#Ut!Ζx|Խ� h֦2xӷh^؋r#9h@NUYUicbhߚb;qv(\e{A,BXCg�QƅƠG۵C? ٜ9!4o-j%@FD1qjjAЄ;!!` <sԦNO>80|"-�.~9aGFGpRn<o0GG=l€IxlPp'%ǟȘ ?iflʼn ;J0ǗY}0]h W1X|&o+C15I>�-:E5{j4 0Ci=Yh:gmbOޚK}z7)@9t^b7yezԾla0 oG 'k!<v;̫ca) ,;d2Z!lB8L/c+ߵ唃(T)/(i*mFFL%GcU|z~|)'ӱxeߦ0zN# �c0U y  }.ШӇi�$?ֳT1~̚&k rz{Ødo[$""""| Yɶn2qO=v>\3h'C`bw!v{ծݳ?ӷ(4d떨+**epPUX]p(NZ`sS*s|H N|6MJ>1&|3}L$ǓIG'gm5迂SI/"o|_M`漯(Ӹ'isד 0hڧW1EY-:^~ɑƋu3aXwwR5AЂik"Y ;|Ѡ44\$)t `!~FM6jFqdw'VjۣtEg 4_G8�cW(?|2 CR:^3X 3aS#T>wtȗ`d�'\"z`ӧq:녎g=pن9:5c@0|8 �L9&Tl֋i]0z#x”{&ZWcHÔ1E43m>ǀg}9l o̾L)<|8u+ �WA\A<ʼnmA7@mǨAy2r)-Q}d( (Y2?</Z0x2PBؗ__z-́MHla<ۮ+7ƉokoM⺱5Lu(KXoG lGxMW0nHDDDD_�ɇtk=xN`3޼ʦ1~~H1`brT2&MСNN~Np#0fF&pp$2^{ȅ U.@&MR|=Qi>Wk@.U1kg\%2h Loo`7 . Rع ՝ZK隑q]z ,C3shѻ0Oۯ=Fatr&rZ~5"?Ki٠acvfQS_\o] ';cYzn}>bA: CcbӀdg,XL˷>3!) #i]23�XcRrfw`XLk6ɜ=4!ԯ ,RvŚ`㍉ 1tlюc9z&NI`lJ΀49sbwGck8Fz3oJc9_B<d^\p$owb}՟cVK@~oƗ}p|sFl uBs8/ydVdvSN$dxF1zO[Kϯ]�l p< u-x[8}PNU&/9K9t,γB/Ǟ#šyd lA bCBiu*ftH~�L8v3! ŽqEđ$LG-\*]3gcT(e?"""""dH>"dR/\@2i;#3L#ԞX xx!W$%3<sIZM] l~ XD|T#XAW0;dr=G׀͊1I4?ބ;Oqbz0]jebӖրLW7b0ҹ>Tx_GE+|ٻ6P;E;~o,:oQ<^5Zd9~Xm9a�j,Xy�繭|^m-^JQ,Њ%s189<GЩ vGvSdk-qF10)gFx5_NTILu3�!1BiRf6 /Hn]�MbbeDp_v{'(黟}O6䩁荍3/sMk śaب^0={H.>6OoJ|YL{ �q&gi:m%=/a f"�/՗y7** qDF\ei,= q>`N9'9kJaXl ]yp3\@B|< $`M0bs 1;]ش=V(P=>A1<i>I@6++@%Λ܏?8yV \J8ޔ\^rY'DZӊ-.BA!d.TR6vۊsu\JdWr1ky0#S{5Kkؕw{f]\ݼWysX뙝> b!?=fB"""""K6>aq֚Lu2y*~1I; !qN{ҕՀVrvYF`ƾ~dqv8K|z!-IwÃּO!7SM#p)3||! Ia�pP{&I(jؘFVL{ʙ w u8#H9pGn4R!]D� 0R.Sq˗ɆD,D_LLҥhxy{q&tx!l6܆gf|`PQ÷8&0'IyX Bv Xq=J0v^ƽiYsZ"n7; OSl ޽Y4`P7ͣOՀ칲s+8=ɱDZ`z0݆svWG{~1Rcj(O*xƟdחp_p7\1\haa?|2c�]~*̚0CY׻8<wM@MĞha8!,x+k6]OqzZnbhЯ.N@M87E_$XߏGy'f7(Al~'6.`J,Bx\rc?;`wCAҞx`^rDDDDD6HӠJھ@O<<jjn8$F i/r=.Bb&%͈M, Lq&Tn[AK`Fnt+,shWyܦN[띳epN;9%#EW*c䪟zJ~]Km*7>2M&;>wL�7#�Y ?H`%�`u_c7FR8ͧ }5 ז~oB\T:o0�Y l}nf�^^>G"/{ڡ&{6rv< ?  R>Pk+-̤E+h#?Aֳ2' Wڟ*cIH8s!G) R r|8DqGRʳr8C}})ǎRH \qF,o-[Dgo]p檉ߕ3X3Hxzyb&$w$FߔC?H"a.k<c R jX6IJ|v~ټFjeA)mNG8jR@V\ """"Xӓ~&ga͜k` Nz8sc DY;/&Nm?WAsruBoFp |+Ht3r[lj82n<:E,@OY~<M7cLzp'}+ -iىULh׹!Sxc%3ori󤭬[qOiW)+ 3X>#�W&fU.q&80x+,,pw!0't8Xh.  vǷJx- `0<p}ܛ=R<ȟ79 :-INh2b7γ ;N]6zxyVDY9Fɾ0"IWkN;yTU-=OՀ//_.aV6^Zsԕ.8O-h0^Ҋc 3iӦ/^GLbo~_5>x{'Â@+ 9&�C誵tmR/o y[ YO8@p$tfٽ+:u [d0`|Sd)4.Q.6$Ob9穳g%]:̏c=*b[,;^ȃ8-s� xqYY#*kf�ɔ]4pmՊ#!^tMᶁ̃bƞx7({?,ӢgHH;[˦y|l\UhB⥫U(p|̟/"wzKZĚu,Nz#c^A+,4`eCI3I ņlYC_1�??k*Y- Ui&;0`�c<9 hZ \t�|")S(KV`0ŵkk&,ߗC{hJ/qs w`},׭s5|CW+M~ׯ$]o#Ƕ,oY9u&Y8бa#j:~~ɽpǵ5n0S ڑC;y&]^̫iزl],׺@~~e0#dv,*Y4i#`f77Dz:{vl3{]:gmq88=-�n̊pW 6u2{`�Bpe>N8*C$E!d10o]t &\:F2o ?<btpTP>VUI[L_m$Mw y:~4X3)DDDD1_yϴ0ldIZDݺ ϴ<P5�^2m "SC̓wZ+J;$"TxOk󒐈5lw0]78w.sxK.?@^)I؈}l9pq =<^"?nƀ&_- }U,С^Q۹>do^/Gbbe!;;3da}ѽOCAL6WrM;H:W͎g͒V.WJ1EN0�: H~MP%9}ȂiI{ekpp}3 z\5k H?w|#h]!/>8In1&1) :hˮX.N.deFL-b# Dv/Qx6p_8䀬>\S$IծSɱISnW;Yi40F^%A'%l\%]w2v7[r<% H/;AeS&5ɱo|=Nv} Wn4Iy.KrlO:dg_,:7s '}*X, fK<,P`Uo54"j~_- =KDpgbN%{@yÄ3#֓d\2 ݏ Abǥݐe$NFRB~py7ن{6wY㏊5Y5`f790DTX9u,{[s_@ |ҥ P=G;DL׾e0Jᄉc~&N:E1:5?ZA d{_؟&Pd\ߖ ɱl<VL2l53 N&mIA'M ~2 MΆOsZ5\+\wn2h ȥ)7 s(lVvƄcٶ,}xX [, āFDDDDDaN,w+V�+pz?;0zMFn&֝ CgSbB~~ ]&nn܅f8Scx;kҏ}I_mL,ʱa-8/׀y'"cl=ыm_ fb|nqC"uv4$2j )eRHfȩu$_|L" Ҩ$\϶ESn{fk>O\|x՛ñ];r$'!$щvΜ�3p'뿂O=ρ I(`D�� �IDAT$~;-cFޥBq>ZVv¹gdȝt[Y/gҐHRܷpDDDDDDhK�WJN](I$Ώ_} OR.ޖPS,׹~P~*DDDDDDD$OQ!"""""">s俲GfT?ZwL/\u*T?ڄ5^~?ڲh�$5̍tڙs> GZ!""""""" """""""j#Y3<�g.tghFLSDDDDDDDR ͨTC I5TTC I5TTC I5TTÖY3c"""""""jWAA3*DDDDDDD$PBDDDDDDDR *DDDDDDD$PBDDDDDDDR *DDDDDDD$PBDDDDDDDR *DDDDDDD$PBDDDDDDDR *DDDDDDD$PBDDDDDDDR *DDDDDDD$PBDDDDDDDR *DDDDDDD$PBDDDDDDDR *DDDDDDD$PBDDDDDDDR {^KaREDDDDDσs4MĐOBRa xyxMWvÁڗ?ՊjjbsBEΥ(0 ||} ϓGB|<ҧL$11//~n'!!ظ8}]u7M .具{Z'$@L|?L$>./OOEDDDDDMBb">>4ֻ4/0T +11}3)Ty~c.T$y |||H;""""""@ڀ�L= xW Gxl$$%(4q^ۓBDDDDDD _]0}W 4uwy AMiK""""""N{YێDs:#dp:;Bȿ,ȟ1 poyxflB*THB*THH /ٓ:U+siFi7U+}LʃQPJ/nMq=@z;ˎ@{ZDDDDDDD#-T\w _OY S[d<F#\48blaIa*HLl$QLt?DDDDDDDD=(v-DV&M UEh `x\,9,�#{OeF̀x/fż= 3I0 ZQf hKlRV j*8Rk34lѓZ@6�ӠH*ԬGךj\pd掋46rӰ^M3z8Ԫݏ7(z-'bMJٚ_l;Q؁Rr5Й='Pfm]3EDDDDDDDS׈ gN3.E~o~kF%\Ĥ?nTawm'[c#*K`6&w)3ŀN:�W|͂$ʘ:?ZV\U='Syx.^IGA]4$ l̜O0w;R+㗄ttA>|>x߀^X7`Y;(W, k^36*~IcY-̜1L mힰG=0q7[v]ǨE墨ѩ\US~\k͸)ﳯg΂aF5̗ĉQ'w4E"""""""ePP=/$NΈ\^/_ZpDHL3ޥ͖gvP K 7N�8f<Uf"xmfb Voj=DLJnw'G8~b6HW`P2^q81a�id3#=IڌSDDDDDDV cpIέ2h/cB 4kF KUfyMVauRRfOnsr ;nKR&q;ӇNO[fwd0p=]'LMA!""""""r['p#́3:<W5Y '9RÓ]KSȚDJUp{ȓ'3NÛ;" ( @իk={OcqFҦB *6?I&`x峁5OABpydwQ k<ۓ^g�MrpeJ?3΀v;Pl(=q+ ٰxsɚ=luB_tE/@3ti"aW�L;} ,>Ymf%x1VB} _@ۡAd)vvM"U8^DDDDDDDΨ�faxJ=B4[6|p|J5&4 ? T`xelTyntz.mvJ$P"`pšÛBu,t):L'/b&^Lѿ\'!. {w;�)ڋȝW& it:9A[%Po?Kj]g*+WǷG1I,YX,ko8>6YEDDDDD!:]ҏG6lPdq9>ؽ<F}Ö :5냏s~'U+;_Y"""""""gTx�Lg>pO:fwIY٭< ׻m2hķ[; W]%3MsѤoΐ!9ր7Z'loU_Gܽ[DDDn "9*wmb <4s7l#pn''+BA Gf9^)YHƗ92L"4Qk-{shY'q˸^KqlErf.l[so ۓc ᷽ٝ juHFٳSpF""""""B#Lp| 0|}y`5ڙSq< 3j{qB#ꀝWyc}uv_B=PeZ=rۀv/r7gI4apiyĖu`߿}z\gْ=:,KFm+d�o揝]4� WٷIѧp_3P,gg䜈ܠB#d~Z~�GSDzT.6qp1{BPCTcޭBo 0~nf#j7 N`+T9"DEDDDDn"$8p�V-)!J2d"gˆ)E\DDDDD\q#xGSA)burYYW ɱQNl\JZUnj_1f6^ĩ{H"O`<[W5u'!&iɱy,xQS|�-^ 'Ii]ڵHSpXs<s`8w6rgSx||DDU.y+x`d$5OǾ{Lr>NlG!;s}J"NštVOr-�c`k΋u1N/EMy&u@\7~ 1QڜLKbhY"%k=b$~iWv4K4Ȝ֏ysP|I7ogph8aoYCԅS&P<oW-K6mf(~؟Z{*fc\<G\4TZ7;dz'?,uzp7W.E'{4<]8JæXz[1N8zp·c$Œ)EfV4k:ffǍ�407 F΢I̜6Vr54/ep0bdx.PB/ γ1+йfNΦp-KNXt=Mk^#]r1/_fL$El`(;sl` R4 9 A.a!,^ݔ3vzB_̄mhmcm|v5~6 ._კY9-=| 3ov&w\B_FtSZb?2%9n77�gȰ- )rWT$NE͊-4)0zP cNxov1�3x\v a|>2<M;Os=m xzLGdr<Xr!X` MWY dސq7 eϰ]Η5HAiYca 悗8rG^b]|:jΓϿbכE:aw;iP⾷̙q]|b>n_݇Gܙ@t~˜^lZp[DDD$5Gp~2\@ZըW�n 2L`̋&d¾8>y+IpD]w*Ѥ'kq=Gt~}$;f(RJ䳾Cxu"V钢X. ݿ _v^BШ7mn2;=Wړ6W3'~;q|s{ҥ}gNm";X|*^]En`Bc7n)Rι$1v=B~nL{;Ef&y=Bwɼ>N1`ww$Τ-OE8Ű_3eQpNnf48_?[X#_~�9le{G{ۙA[j{~ofT>s=$xy>ˢWpFK͂GԵXS&܆XKڪ w)n=u >p OoaþSu SĐ=q�fLYE:{*aKp^Ju@쁽)~mޟƝ30p~y) "s?3>E{~9'^ƹ&ERiB GwO睼6sJt{fIN"9Ik<,$wq_qBY!OvHvǷ]</F7~P8e& {Y'j=HjtOyDw7'2a༜ue�ԨI\_o² Xr$w IG>Mo5_ ًVd+~ǥӌb�٨V~يrΪ أn)ŀ([vl<rkVb&Kn'£+T\k1U:KW#Ɩ5Nst*LB}d "P' ,R*M?N82~IK@ߦOPm<L,C$l$0ZaIe�0$,h/ H0m<~ 7Λd´yu-Fǻ3jU-M| `ن}\:;7fM9%޺ŝCjձǎS1jΘ0n~^6Ř6}U6|昃mSy5u@ٚD:Gߵ&E!Ƅ3wq7)3*YmՑO7# ʌ1q^QLv왛<œwf3pGImP!"gEKyO׬ xbϾ/ \khw"Na<,.ゞsF@sw{ˣ7wVw?a+ZQޟ8ks:E㼔rՀOjgՈpUz΢ޭyXq g#wY'm39> LwW{gtrP'gã*�nz!$^# #H"EA@EQ�*v`WPDAHc{O!@B{ǤR,r繐n6̹3x�a;!'hy۴@Be }[v|�>J!#2U!䛞6 1c ؾaIٛiwV Ct�jХrA v~6s$m8׻qBs_ZUf{жLb !]V}Bnpt;lۼc�d|?V`h ʃPƤ)d&>}&a7a1cw/~,?G-12BM�! 4ey;g30uB/RÍ09i\?B!*e:0gEF4Ri珗23T3,GU`_%{]ԱYOɨ]!BR 3k;c=gf(l>ho�hW̗v$~zOJ{ D&jvp"Ÿ@ ҏO $v%/epE|ѱ^s[HMM \5{5vgk@nj%F6]!f=.Kn�]E0'隁Np]ݦ îzhfe o5 R�w6/u@*apL!i̧o)�ua;3Mgoo#.O2\\CY˂KwυY!сbhfhJ"&}M(g~Ԩ?u54RYc9i0M1;{>oo!BG$ !rY[.'RsģZ-4k᣿(]r{s̱�{M[ nFr͠7+w ̞8!E o"l[Ҧ L!f=�t4ǝT( "w]�ty zl<'k;vl�jzQo oW8j/>;KSJ.PYopu1�)6DD7]54_к? <b\Y#G(^OgALФCs|l5hӹ)㖅lepޔJ&*=8Ff|'5Su]B!pD"-<g%uoֲu@j֐k'fe8{)fMP8W T@xxuvplӖ[4QH/g�Qp0;۴.ba(R�_pfnZéIJet=- jUtbęd-Ё?^fPԮUURzu܃p/+Zsq@}O(aXg*t 22b;u m�u.bӖ] .^ #)+PqQS' nr X"kV.D;KXS1g뫀nB!O"YKNaiog½F36˚Y)Y:XUDmfP+e 5Ȧ-zn@O0_�j[ #E'nL77} $OI1`ݑY�i4 kh֡ &[U'&0ڮЁ+ޒHn7k&ro@|l<}<a jtoM}~ !B T[%dTp ~1XjӮԋɫ\Zcxy�� �IDAT9SV?srj7 Wr*< Um5-JsVo!g nݨ_@cwyoH V|`VBq>4yGz{p@+_l�i ]KMoo  5M=0|O"_nAyQo!B8 4%l}74Fgx5V puqN(Kj#\s,ǰ/Y aj;|8=>4h^ʋ';<M񰚸zcќx㯣D.~˛gb𗘹IL̞ S.b?'eK.ɬ(d^ֶ4ɌKzKk>`\>x쬶lL> m%ZUjΊD mػ%B!t" Y;څki hޘ�? D`3[VTڛgV.##AjLK`6OFbf _˛W7f.+tnR3.5bJ_6:];Xuvoư$،?fWs^kpmӗ_.'fC�oo/Lha.\7}s| 2>fY?v`A飕# g#B!y!g !%"W,߮z>Z@MҊ͸0qd"yamڝ/N�cn3ݺ?fWAnO ^]YX2c_byݷ'J)6|`ӿ/ jvIH=dV%JƎHVى {o|~ !BkKܭW^\e|'Ĭ^DުaNhٌ9a= ؊ׁq͹C�q4U6j]O'xTX1LZԦ-z} ׀fɖ4xI<$M| s>>hV;ȕ>9x""˕1q xf�nKBOhk"ae3urBjV q}Y,%Tjzi8E11d4X OfIgr7B!e"\V,ġƹMqn[wm Xx+h\![!vOddE[ٖ[$Fi0`>xe6}.p6W 4Ďpav ^%bo׵g0?gEp9Μ;ljsX<ou =oF2r5]Iڴ2ᙯ <5\*4iI4+,J} \?ϡ h$�<⤁.lڟWf2!vE̽r[!"/N: shHL-l-lj_?\ ?)k.ĭ[<nfTs sa2�sa*EMh'XkMn)@ ~!璜Yv׃W}t:\и+{دHЀ+{R(5 Pͽ F̶D^v#o%|Lh Y3{FqT xy-aUg�_nѿ7{}wʠKFvOP ^+ڴ6,`m.{*K{ϥ ,� ң|ƵZ 跀sQf3eѶSٲm]5;P2 VȾRbY+x^(LK>oȽl[!< Td8m1ܶ" TݱS.7"W6شiаqu|lohܤ=&}W%(JW4̼۲ 'C>N3�,٫þ]рΥ\0pS>24rar$Xv3) 0Tem"CU-8=tٓ`MMK `.Φ=/s6ͱQC+/Y9z5@v|&ôMg`6{^ {2Ne_�-01e幰0zk4lwp!o!B[?4/(͛/v旅)\݃٧MhYr5\4iNZZpʑfH3`C`= @%phL>l݈^WGqF?"}ؑw ~N-ׇx#3υ5[uSIN.HKig`*dӗ4 L^9_Ssɮ6no=+P/Oz+ 4zf4ۄKbc?;y~ !B<ԨKeH;%=ɀQ \×pz/#O̮d,=d0t ^{>ӛſør P[Inڛ=.l*-|6rͪ?¸z t4{˷ˤ%Sח1+�?LBw}Xɧ3o/LKtnJz j"a'LRQ mi:ˑ+=˹2`\ 7f\/WҫPY r=vр\9+)~ZigxW<4v۽bw<u_{H\mވIc`˲|w*0m!+k1W6l�gn aft7w9nv>yOZ `MYf}Esy ùKdzVBwo!B[? rx*k늁͔{*+e1茅䥧{fK?IORB`ԍ^@_䔵IEzct�^1sW<`wNayt-ơd_bFS!\4o:$.wNQD! P8aΜ3c5+U#{,#uMh&<Ҵ xQ?i݋RB/ Yɛ&~kX|6% Z ܚ+-uVhY˝2ԬF&X1p~CmPg@&,j˪9up; 2ST4K]XNIM8??Gz@G 7l{s`Ǧ՜9yKqqiRaj2 ȏ (ȟ/Tfq9L7{6 > $P�Z֫B,n`Ҟ#T⍖ә1-/Ա$ŝǙ4B=REOa-g4J5V5)3ٹyqӓ(X&5R چ9cٳs"* `D;B!D.'%rFas!*¡w ]'{0ܫ8JLO~3 8G˟TFYA[pi ~|ׁ+<[)S:p'fGe4FwNjJ\ p V`Ь49=>¢+x Ne;0SToo@eLO�0~*)?o:ko\ܖHB1Lh'"w#uLHp}B!B\t!* 7ۚˊ K\=I]ӛѵ^qN0TODA}Y .!͠ѓe>3*QFe<4�L4/?oɠ!3Ti+=LZ/.DY u@EZ4NE&'@SW*EMgZ[ZOHGsͼB!B!nS*�tC'<kcƟ/O-QL**:o4!d,�_w3fTɗw16?졓:O Cjʁ9?-G9yZ#fУV$Đ9gkPQӍ#=nPEK9Ͽ'B!B!n-uK?ͤ~X5m%8؈X DpP>>xt*,=Ƈ'Y$$qv<w y_/Zs /X(zC%QKJB& ,3B̜w%*qSB!B!˷@@fCTMаY%d˴D_82t<) \fѤ)DX _͗񍳸s={tB͜1yFN>Ƹe{]; KFL\)[i!6 gÌ`�Ha1vhF򟆀~B!B!ɗMP^m|c]7޾ .oŴSI\#|LtkR m 7ciz"e +/BRw/fpu1zʸUyzFċ]4/L AX�5Z6꾵_!ЩoҐX4<TWӣ.O0t2RgSlA?LeB!Bq{b5p2d}g i`qϤB!B79tՏE?o#mdK^ !B!"H&|5hپfFrauNc4/B!B! Wčzow:w !B!"k!B!B$P!B!B! !B!B8 T!B!aHB!B!CB!B!pB!B!Ð@B!B!*B!B0$P!B!Bdp+1 MB!B!9>MB䘈$&! mqf �|@ 2P "B!@ߥM?J_0s1Q'ԟ^MjPJSuxZGdF=l\s F ͂7p*Φ//@_:C=Lgӏ4 *Q( UײB!"IB\vi'ԛK7f慿0.zl JVمg`^!B!$"@ɠT+*Q~EK޷ n1S DjÝ ;B�`p9 !B!\"h@J޼6*wS~]b oWg? /G,ԓU@c:]OlA� <~_unBR `ġ̜\:Nײ~ &r�L1ff^IAQ(ϴVEQi6g!gN절s -CVh34UOdsl!YR'&t"x]r~B}I֡&ss+hqm)Pm !B u GJ lT4::o?ҥ2@}\M5,x9:w{8jc~}Z0yRУ�\x?/f`\&ʀ'oՆo|wEX870ؖXoщ>îsVWJ;}8RZci[ҧ35zbkƷ��L/?A {[P[CB, & !B!r"j3)Rр{R(7 ʞ0ù]8 +@2<bqM;0 *l h0#y >|&.k~= U!f]EС5n#̅P8l[~'/nt`s&wo@fCWTNG:�Kya;|Ns[y W,Ӱ�ml6#[1j"kB!B TGR 5W?g4Ǖ/V^a˶Ir4C5)f6Mk}6G?̓+WӺd޷VEsfPgv4*Gc*_-bX" 5xѸDۇaJj[xgFƯ:c0w2k]*i{0{ӏπ*ۋB![yAJX1wϜ+T_"Ml-d e>`݁;pQ2gmvE4 w~g# |M\yd.`v4 Mh,VMXlF"P[^mx(.B!Ŀ/,pX:0iOՒPBU c'NLEoBDJF�E)zWjgry�@z/C(Ea+H'%s&ʶ :v]I1HKkT.di4@]`  Rܩ+2'b!Bq'dE$. ĔCٺl1c[_/?0ƣ~l 4\a.,i.p xf.ռtnWCb,*hiibrGi<:>A#I3Q˘kS9Z�Vn¿rA~OEּd`b5TWپ~9%vrucjv*tzp Ur*Zp Ɂ+ U2s!B!HB\q ÇYN:ՠl3.'JYt>V^nR'_Ԝ`J iEΐfʚZ ^ ӥR.'~4/ {6_Ieϳ6%ҷJq>*ht#a)nڰ d(n/oS.1l7pZp~h>±4}c^M_nP+p`'I0?/EKҏ Z@%*ׅG~!B .'%ra΅( w c""# d2i9[A uLH\oA&_,}2EUČ*Zߢ"PEB!\{y.I}>}3ri=wlRo_ځre6]8vr@ IdyDZgP CwP[Fs8~< <4aՎB!iyȰ,BU(+gwnC0?վ[|]<`5j肁GSsE@s牨j's8N֫UQ:�B!/_NL]tklD lh-xYTBȌc?9 4D%VPoRe*81-`W/*p E!B8<ThSq:f̧kU@+`?$>ɮƟr/tlW|"c,Vs#^dÅkNc 3.CǮq kBbnd$Y$یp\QZ r[c'c0`6�.Ӛ]P+ZʢTE|jpB!D@@IG;?xx<<*=gӯ[uy?uD>m҂ տg�ꈁ Fc^3wmNZp7\r9#'ipAp.m5-`1*8ap4 �ܱ\=�|Q9"GVYd854ߥ*k@FZ"A !BG/ x*̍]at*WNXĊ z j= x]Osl2? g7W4L:09r 'VchbV}hlAf}TNB/8�j3ZVK<hAaGj+Py.g ~ʢ6 +ia&B!C*�4tRz˧Aw3“ $DPt)2viX GgS޸!" 5&~SojeiV ⁖ H,'lP 5YoPީRe$~,7O?F^B!y'_u|5i S #vut nTz0d0ln\ 8b}!�&�� �IDATݨrpċ|PW+rKB�GjkV`%5g u(q ۅB!Dn@ 8a'bbJ@>E=q:`"ހ'(R4{Ⱥ䩑5�f -%9s"%3?v}jx(\!k39 Uc^/q*-B!r^+b&Z J5oğK8s.119/O/&Qcw'd;'GAYN&2zI4M"*<7d1.oBx %+HaFr t!A GZs؅ `D~G`*PQ+/q[B!)_WTdhUʅt?*zҫi}z +\̗o6\1�*8CѼ#5_>2U/ gcL ܥZپ]ExrJTB~J\x HCX6rm{)#x`3B!B9rR-3 ]׹EPn!rLDd$!L&4-gxgS *81 x0z80VlE%j 8ej1B!"Å(<<nk+*ʂZ9*@^+TD&2�(tF[Pۑr]Z�m18ֶ!B*7q膺jWȪ8b- ҏ U)T@l1i> >B^B!OB;}#;r/*8Q$rOQ!BKQ}ixQ9@*Q !B܊?Wr'YK[: VG28Z=Cmq tA.Zv !BL⁷ 5yITR0VM4_*Юl!Զ@B!–*x`o�;r@ f K&ȮQ<) "b3B!A%5xl x|$ RTn^qNΛ2H̪B!D@dT @hN*x _SUQ]߽:J&v !B<@dy0r#ÿ ~A)U=`0Xkި-!P]~' Q%M�UI XyOB=F$P!D.1 xzZ1HAM~#K0Vd4F8a+ă7%]߽Fm9 ak3B_ /OO}OBH=vHB\p-5QQ膁;^^^CrJ8kחB<$Tp{r*j,*X (l3B?,.'&D`\]&j' !pTt$G90 GELoo*耪$Al{$H!čy{,jGNyɉ89;s>**O_{BGIwBB䠌ajߝ ` hSP%+F6Bр U{͈{crtV\]/rüOBqɫ;uGa&!D6a{NNLnf71hN� w!nx qoQ8|lFNbR78oߓBܯ=NQ"0@�'"2ɾtڵ\BmB oT ;ju7*  St}s$!yt'd90\ʤ~U!TœRKBܡ.ful5`>P J)F ͽ$!5t$P!Dɝ;}<*^N EUY>ҍ;\d%+X� GnܧB>Gy@ �FJ`?>P5qB- ,AIPB!MB8@3T+v}jTC! LEUhcwCF !BIB xh  Jv}BRk3l}׾GCf !B8. Tﮡ7C]M)ρ3!'借Q^R< 8b'B8$P!D*'X/"�On!}$ H^C HB!"_ GڣPQ81ɾW|aTk>:o;[B.*1xaAi \qk?E i]�,\j RaCb컅B;"SWQInO?L)ľT@�jE[5Vg9@ǧ*c a?D0P6)US$co-dʕ:{Ŋxfݷ%6.sбm[B!+*3q@ $Has"l9Lt 3:f1;컅 pxӾ.LVYHu`Zr%˒+n[Ll,ock-6IB<q&Ӂ!qDx;P .'JߋXTފz$B웄B!ĿE BEWƏ,F>�blX9=e9)J|޲5ۿNlM7:}3P kz.1rGh~с>q 'j UKjTh"h2T&ʡK\9OqWի@P-s"7<,>A6_ q}86oNll,!4W/Gڻɔ,Qg;t]Vc~5q&QjUשӉcڵL7o3zxVΨ5SaCvo@l|<LC~=zPH�nͥ�[o// `ʕL1OL%xkW֫y;!y8K Yqei4-aeB˰[2K:̹{5z+ #?:6}yXD~9 RmF۷L>qVs~D~(F⫷0,Q8ily.vo퐟4|`<È9{ WR)U,^T�|},sz'5͉G.iCW<nehO7R/$ܭٺ?jH9 | lc_VnD?@<׳'psu%$8H&M5k<f ~~~�lؼw'55�GWGDW5{cݙkڍKpc|X\ILˋ" S(8^xUq2 *X8\?73ih-JXٲDpi�J(+fzaH&NU?CCBHvwcnzu?B!s٫ |`?ۇ,4Ö>s+E|#=[vJ}\0+݂&'O؇~`:+lFl+WCf}4sYgwJaL%(/n$.im)6/hW5~z9cfgX6{OF+PE-'N"桪+w2%s!n3@P̚Ŝɓ{8<ݹp"3ғN&&%1p0RSSiӲ%/fq&XjтG3?oТiS&Cjj_j՘<f ?,�Sg"*:??NY6s&E!))Q?Ȱ3<f $\̔x7}̞M֭}ܸ B|<fB �f  Tˬ4CkU;Bo\Z+9c9 oqʠ~\MUՏŅ=<bw 2=i;ͼM<A/4 c灷Y܏Eҳi0�fC_G�-b;Vd6>9M)X3W.E}͘ })7Aރgq/:Hs TQ+Z\NLח�.Y/ &.ŋj:ݺ1gB""#Yau(gtG} /|N89; /uk\x8O:�ŋl6/S>, P !@= (!#!XB.B)tjR-ϰ+i 8 -'I.̾XEC�='t~֑leFӰB0;)2q vK5سbWtmvO2:y%gq Dhj[J0ek Ze6ֲ|g}WĜN /tkshoDNKsAi@3ԫֆ4/70|y 5ZM@̒ ?x uÜ dԩ%.<} *,HcUX@=*=p Ӵi%-ǽQl*<ڈZjСNup}B �l)T/`p|9d,X}iڨj֤#`�XV^yӶMF·m=<<5HnݝM֝;%-HBJسo @G~Zԩ]}R!o<šǏi!zRۇZq V=bMwhL;ʉyi[ me(̶9-.§'hŬq@]^>aQ|ԿiU^`-ɻH6`ݔ^gww?el4 ?;6QF<# "|{g ~5|=gި`9m?T8a@־B]~ X ^&2Rٌf@d4 | @SW~2x{9Fa_UI$}A0L<AEI!h ŊKq'K@Rh񢥸{{|wd!I6Sr̝;Džs0a( (FL6s^}؅Q֭kǀBB/+?ƻ0&7*z2%K2yheebZuLuY~i'Ϟj:DlfZ>>݇\r۴a-(BUi٤ ^0 l۱!cRn]K#E8ƩMki^fǡ5|` pԽ{}^T>%-ݹy(xm*P,US9dv,urd�귪ʲA.( +)[-3{6J1'%]pH~ؤ n]х _+r2n=U*2Un<6*ov"a �Vhf)uYB.iK/^&˹IF X;$%W!PCAyӐPCI(X'5ŵ,k[["PUȊ3EFb&@W,wɫ9v[ӻ2V?#8HmTDhT%L@DBeog X[[G?}aӿ+Q͍+׮q1vũg7e I&ŻJț;7 >%s!6s-"8$xl!Spӎ'Oӧsg<ɡG;t[wn2B}B #Pz| tGܾ™Ga:ʹNӁ9f*pڑ% r T+u*l޾x -f$ <%p[uec :Q:(Q$3CCP!J/Ccbc<5:W^%D$˫FOƓbN"J6QGnEQgȝߙS8|^GW$�p)P#ɟs^]@9݊ݗt4ڏe7} Xr~ k%:Uύk檌_)#?qq{oN^/0h}!'&'9r�`08ᅯ)Y2Z�d̐;[[8˅^fժϛ\9sҴaCvʱ'ٽw/U'xtUn޾mA<}J4iL0w V#׮_DѢ"@xxQbcw RufIi۵+7o͛.B_no.C4d0JdOmxPR *5sZ1tha5b0U�wtOik SFwed s`(&𺼡<4.pC8z%7M8ZQ@n=jD,kJtkE*Om gFln`Y_\&l3pP Ԩ^,`o(v<RkbbF W<l!ni9| ;5C+`G,]ufC^= E$B)�Κ܇>;6suu`?t^Čyw�||L<usgxGƖ}իT@t6} JNqd>�${=͛7ydh<=xNmز};cr6�^@Hh(N_eZ }]!H›Y?akZ:_2kMҧ%S(ƪrlpT^'ˋDqpBDG"&Y3XߐX4:x=D2*d$,Ǎ8 St1*=ٷy*_c&)Қ"sip�a7S*iݎe\-' tή ]+q{`Aҭt*2)`eڂ\+!zb۸pMaamCdE5P(5d&|Yw]foKePt(TD=?S !v` c۫;Ʈ Ngo s>ݿO}^76ݻ[7wcǨ\6靜aa$qp0:eJ3p._J-1 X1Cw}�(Q0l[TۛϏCGpm׫zzE�ҥMK  b 0mSti<ٵw/]%c�3;ԪQtiӚ#]W⟙tI[E}W)GNؔ9k_NyY۸POeMK'o=Y)]H΁746b*ނ^,s> |8$‍l9+Vi.>N򦋊BTX$n㿻sJ;YfH؆w8C`M~N3{\r[9R27 ]l RtƆRuJQ30dl ya kT eL ?F̙eJ(@bI5gy5m&ܺGf`zfXzs*HhR�Á勞P`(gl߆ z"1}zH@ܷ/Sƌ6Fc…Tޞ;AALooV-XCOOϙ;)AUɔ1#X)SCUAR4Ct�.Q'Rﰷё ^44`ܰa˛[2gʄ0avJyy))T�g{ ?B)/cm~*{uӷd᣷;~r5Nԝ?5z2Z"YVտq?jxk�٢M驳cؿnOP>ojDSUNN=�� �IDAT?SFu~wz0UkqVR>Fj52MQ0]͵uym4FʄsN?ѳ!`+w}Mӕ`Y=gˤz`_>SX&5Dty9/ D>Hl e~YwI.1PQ㰐ҿ>4vU� \iRk{86( �㴑ca6~- G;Gzܻ|:iRzPB!>1)ʽ{=t\E "fGae9LeO1+T< ՚¼B/�m+!Hx Ǎ; T&yR( !9IQSv֝u(@B2�5xq);B!7)TAk#s !>1!!~T`$cB!"f_|~lԬڰHziqd+(q6Ú6�(Z!'-*m0Bul؍C=xc1)<ZF!P!D<|~!j!Y`s)H? UNMN!*Y5m01BoMJˀ$n @B!" !cp㍱K\m"cJrHB!D"$ !̶ cGBoT>`PA/o`*ҺB!HܤP!6jO'_Gm"F�A!B$"R,z#ݛ#ҚB8Y#ـ&ぉڠB! )TaCCm0]1YBĪ(M`6(BDJBm s7(HBDX,�ir Mo6Y1I!D\1\*T<z\"` Z�̞EBDj &4z&u?\ٵ!!"/uL2W iR;jCB|2wbQKBAa9 Xəcp T,B|d !\PYB,Vkf(&BB u$ڠBhjO�m O`6!Bo*v6os7!l߁ڄBB!ķH Bj6'6("F<G0 TMN!_;)TG<ǦB5MiB!R"FKW` iB!b#^q s !"B c( !0-@kf �kB! IBZ\cP! ,fP:xw !B|eP!;t(m0!8�&p W !B|EP!;V�WA!%7pqcˊڄB!R"=0Z@B|F6a@Y! */̿ W !dl1YS0e-2tڄB!/Z8;Aw|^i=t辔Oh9! @,!)s�FoE6(B*HT`6"6(il8,؅D!_oPal!-4` ;{B!>ƖoDA!B$PV@Bp%Xeʝo'xD P#=p~2؇ѰwoOLYۋGEG}j18HB/YirB!Hh\f\73wCl]1WS~?jK}#'z ~@,>dj38bPB|1%``�6!B&*G)=)}GiݺFv|IYa7#]xLr:/�fE H9X'}!bfn6 ⋫ /P&B$BE<d?;}W JG$~Fԩ ]:uޟyB�XYJ",XsRy$akSf9Ӹ`ЦϞ:U@}9ZZƉ)|) PC�FiS J\pff}@M !G6@u6!b1vdqhp *={3^OR6eǦ?ІigSysm,aaaA)Q=yx3Q!E  `aA>^ z,--QE<v�Ξ?p=G涩@AfN+a:l0F J`1v0 L|K3~|{Y@I]ě/I-m|6PփkgX)$2~EpFO 'z{@RpQo9z&Mb\~acjBX}ѫ`H[A}'}=إsF–qzu*ҷu2˾װ_)}Z(8%{J:''99"ɓ@_@ 7!mP;f$À$6m~H|`M�ЁmA$K~ӭ'TUE |}ɖ563 lں۶ E Ǐ?s^kB}BEKS,wd[p^Ώ遍l9+Vi.>N()* >g o;:k4~΅RQƭ#:%6SZME1:Ԭ=Axӽ`3ܪܷ"7vMbߙƇ[pT.>x3:T|\`zGw:ތKTX=:!OU0h;[kqͧwFRUN= Z MaDߺ5gLwНJ( * TэZ:Kr.eC_Q._|yuq+t<WaȚӔrnoX3�iVOiJK)Q? 6 לltswKX*鸖?u3zK)QmPaȺiO77FtGص� ;I괜4|y o?ϵ1B$ _aڠA̙Øɓ 5ʱ'hSY39Ih׭iSՕϞ"A//ؾݴL ӦѤmh1Yb﹋SV-JT@ˎr)t>zUeUܴٳ׼9=)[xÇSrexy1`0^zeZ'J>}Գ'�Jb5KhԲ%hТEqVuLǶQ=NAWW;skܺ5c&M2t*j6x33KɊi۵k;<2^^Uq 56b8<kÇJYiv1ݿϫ`kϛ^ύ7ZR!bE @G'4]O2l"2zc7@F ر2'l4~9F x>Z�Mк,K0drVNFg^9fB̟4|tl&iJfldOr? Dݖ^&r0{2hb<uC >eچؿ c|x ."* qOVIЍ@ѮDnQoaO 3MSgxϧgK6 '<=mE~ڍIY;}f-gꍂԗdķzAT !r3p4]3 aL5�<,^~%( -u =]ntT"0m/wzɕݘס�KV,At o!o֕S|2/=amz҅Ӣm�\z+/Hw3P)VGJh/>>?Rb|Q_F{l!j$`6(bгsgBCCٕkh׭WgxWƏzt]]9q:1 =xKW+ij?`%45K*eJwѲS'RLɚ%K׭3͋V9ya…dΐqSpUOܩS9w"G44jS^wk8g 5йm[ϛ(<ٔ{[lȗӧ>{9v$ʔ`o1c\ME8::c VDFԙ3̜8SO?elONFiQ,P@(BB�H4BBpP{6ЦL PZO:U* 5�Txj27+0=Z\ub[,3" PNN8mIrzu,Ǚ^{N;#=V!oعXU)NM- GiN+| �KgZ䀝+xt_24йjvvP`) C~a3u{M޿:Kwz\vXt[O+{,W&'p}G NŰc`_t5[2gJwvI�K&!/I-`E(g!@o'JRi.~ݼ l`m,8W X2C6|{(ӯv(Xbog=E1l\* 6HоGVG;&[4j}}݌]H4'<=1] ё;3bxj׬I嗬\IE774j@&McvIzt=w" TbϾ}ԮQcǏ]po7v:霜p-Y g=2l�,--qΞuiVW @<yhow @|�6kׯQlmmX*ƙ¾oЀ SW҈m-[Օ#ǏӶE <Hҥ9\v 98ᅩ6 _,vP<� ӓ/:uj'V9{v�wD`M[Ӧo_?wEyswTN! B$,g`,j-OsD$ܠR^ `o@~ZZּ}rnmeAv;$-Ɍ' `ccKb#Ol�lmx_ -k:${sdmv._P~ܕЫ �X[rvR-.�!Xˈ9׎Qݕ"u+CRq`R@0uae8sik Nǥ*_&kBD, c"\>92GG6_]ڤc0}X$GnXRm{Xl.DQ X2u@3FZ||XiƏg)r/]ҕ+0")T�vvv/R#'N$IttjV8z$]?Xחm;wR^=<ݩ pE?yB)OO:3ڡU+z Kp/[^^ԬV-2qI<vvЭ"}*Ҁ�tz=OI$ {GUUCB(BHHaԩZI n߽ǏQU-Zr@Xx8Otݻq/Wŋ�XXƷ"1BHM͓( ~U0j?c$XaG <cZJQ{rdM<)f6o@2Bp0Tڪ/6oZ*`2[R.`{^eߑ͡`f@7T`2[]ݤ(UH*>d>R+ 7-�G}6u"ᨈq:T}W H$.0_?6oֿz'Wvm~hIPL9(x/sNc'NpI7nm=seʘkp>L(\3'NDÔѣcm1Խ\9vo7kFclI1bZ&�.T Eqa쉽֭#ŋΎ]0KkI'O( k/*gϨSm}mK2nm`T!0*D"w[EC^+ Q+]F]АpC̞Di<~t.8Sgµ?xx" J(!ysfb!3NnaWx) Km*,[{-ogfz7fy^݆U7UU8w ?T`MH ƓqTx&7#"v8eO"EvwN\-#` 8bE}> x3ڻva6PqLm9x2Yd1łCBH[D9WWf͟ϫ`ڽjQݝKAM-i$blg_ɚ93˔|2֬I&Mz:rd Ht!VN9s[U]*p{ bB|ŵoĵdIf-X@,YpJr4jָ+dH7omZ?8$gGUU<|mL,_|ȗ;7&U 9Ifwr"yd9w|e_%ٳQ qy/F6IgY8gN`Ύ9uKp Zs-o~ZvW6΢%GQ_Ps�fuk!x_@S4찯̬SyawRk['%~ ;te=@o,:9(-Ђqfs\ `Tm^Y3lsN_ŦcgyL""ݿeВ3K Y\Q^6 /r߫J\XwwlÍi}q!\'qB$LM`;A];t0]Fi٬ϞeiܸyϏ@\HK(S$�8teJ* +l޶WӴi 42t9~lߵ {{{ҧKGʕI"= ŋ\z={2s޼ k++= x WoБ#̑C(�)^@ؽo<d۾O9WW9BcO$Ob q1ʽum,Y@6nL__xAL^2nj?LF.]LGuڱ#2d`+;3(Ԩ 8~$gϟg̙TPTBsH b0s*Ζ0h3GfijsfX)r1`<N'*Pa dW֓ӫ~nQQa>̚<yƒ&`n 0o7fh<x9I"fQHFƻwE(/Q6gJG5@IS# 3A'XF ht x {A0թ2*<a&X16{vᆵG%ىG߈0W&y Q&#z]<>dX.D5cb7n.i$ޝ>by9iSgbդM4v׾\<y4Pd"EHHҥMh-Kg̤IXYYQ+:vD{@̬ɓI$ �Mc4mxz~01&ѤM,..=HVÃ^уzkkU\5G �\y<o&~ 9aٳ3fPS׎2~Tz Hxx8ŊaСX[Y1qH5oΊիiܠ+׮%Yd�СgO e2l@| BNyk[qUU1 ܻLߍSHt鰰fZQ㰐 g; TzׯwE!ppDE~`H}709r|Bsܻ;C~D, 6 a ,Rk8x !B|fR%̙fA!_׍Go�� �IDATNtǀVo6!B|>f*̹c|%m ߉B a AByY;bkm wa0}=y\>@ k !Xa-mP!I 0^8M Ibkg�H!vX D,^-xߴB!*T�8BNM Q"u:BCBpצ>3s i!_4AmD!¬B((B2GG=}ʫ`">`Up0Ϟ>%s<b !~0 ج !GQ,,,S ,,Ǐ)C b)0k>O6TڀBo/XMĢ-P!|*Tb١_~P׭(|6ڀBo< حM))KbB!م xSPU B(Q/#-*!ߔy@ M!W޽b„Sm RBo[F`9 5<RڄB!>R Z S@Am@!7  &b0TB!0k!=NM N!׫ P]u6(B$ Hb*"P@m"ˀڠB!>*D"uBA m@!7-5"u^iB!@9 Ġ6 cq  !IB$RhB!@Im031.BHB$RSB(X 1F=0AB!BHk1H $X{#H¶צr\n qw}7MM̹n`MO$�.wZ=t0-"˜z5Cu6}o7^ǫxxrcUG zެ5/iIGj6 hXɓ)PlѦ�عgJpm*Q6{6~Zi&mVFp)P{צ̲!j5jDrV[KBE " bxff'uoA*Y(6`9~o`ԴɂX?`]-V*`ob-fĦ%P^A$0Ey6ƭ[D~m8F y7!}K%-[F=+W !D!m +6( 'z %/>F%Eʤ(XȗhU0ܻCPȃUUEU!#82X$.X�3b8qd&zY2gȉ1Û)\>{5K-kVeͪ ܱ4SӽS'�rɟ;w?ۥfi!]`&5*.@I[)^e1C]oi|WgjVqcܞ`\SjvbnUh[&1~MLn oC?8I<Z*>s.0;foƥJC*W,Ϟi*T5@}jڧCY C֝ŵN{ʸ1C=®m YݴH(;K[mv\-Φg*zp$�#g*Tw-ǦnDߺ5gtwZEo/w @0Pvu�c.UQ6!2l6j{4wnnMTG|R/^ "{LqqHFUg:QDB)pҀJX95ꫳI}J54}"ū5ã<+7G >g՜`xL_>>={[d-{6{ W,8\�\RˆB}q0<ī yҼN%έ 6? JOС+ͱ5ʻcИ.xfdxW 8# $ko ^pMS}w~wOjB\!kNS~\ʹѾa>X+p5[AP__gxg ûۉ[n60#yMzb˶msrwEݿO^(AպuYjUŋT%*Teǎ\v͔۽w/7͍ڍsS.,,Q'V*%*Tuܾsǔ1whTeU(U{tY~=}})Y"mv7]c{(/]@RpBʕM9Y(E*U:k)nnժz::uD TU9 k̤IÇ)g�cl;q?;5#Q޸A//f͟#csU-V o^. !P!7'3Kj_+d;5MS0+`#{th_'2[ߓA3sj)6]Wcsx\ m tiWaV?gxHn$`�vΈ5?$ wMڠ{s:κ;_ԃ=]|9G2Hq eyA�\ғ!zxvض[w잕سp{LTٸh4ͣ�z@6OOiVѕCE>jx:GQTĚM5%0? ߋ߮KN%}�Sچrwσ7glF@AiQc&\`]^j3^vG*|'vr;Z3//8҈\}mc>׊齹y*}xD8S>=q$C&IJR1(tnw etoP3\8``g[9\mnEv||>UXm2vߍz?UiM. (joM)zKHZMH_z{0rB2xҨx?w_p;'a-5'e_:aC[V!m1J*# 9Nd儖0g2=ڴ Oꅇ[;Tlܲ_oot7儅ѲS'RLɚ%K׭33]Ho,YAXd R}ʝwֿ?aÊԪ^\u 'r Ne˰С4jweԩ>?v0�3e`,Z#?`͕c{P o^;7m2Ξ?/X<g۵cŜ8={>]:.Y޽t)V򮮜8u X|߽?KW+ʔ*k5uFY|9ժc^ݻgz<ҮK*TS6�T(_OhE &y-'BasB|Cnj1Ȧ |1f=yWXS!upu7ANq[:(Iߜ<X]3Rس-ŝsRol ߾ \|Vșj6裟Ei nȓ-|,._f'WTilO7w=7p*`䣀˖=j磒DAI9i['Ce߁kT}ѶFOQgv^Ά!hGVծ(Kv?װz- "uOzxxN8e˃g$DT�}&GH]o߿}k\\Y59k5񇶿esj7|o_yD~r>TqnޘFP# X(RkXKyqmv~A+=9 VZlTkߑ-{U;@)khY$Ιm+'Y؟TL,;8SeU=OJ> ɑ5 fu\~K;Tl5Y0Fa dm[|Xvv`a[ƹ~2[w !i:gu%9ЧyUZAg7hCQ=4۔yK=? Qѽd&2<ې)=uJq^Wx=~~6-]fޡ? F '̐ c}_I wz^Kz{={ e؀8gώ a׮_'%K3[6uӦst:U*U"[֬iޜ{NZh҄ӦQ _>f pYtz=w{�ǵD \_c㣮?%{REA@qM:[muԽGXwuZ*A ***w?N"|72^VߟK.%5 ±GŸѣ2p gt̞;3f{+%I!׌ 0?pÆO>;c*oQ^^΂?fQ \w]v;:~lh[RUUŴ陙m=<ߟ0g'OW_e 7sN~o?f p� 'zCSO_YYGwC ᴓNw? S)Nթ5)%庖._Tq=ObVҌN/Ttb7ڐ ?ʋ%B:tov S#JDf#v�TTU;mg.NYz+p8mWR)1;sn_3:Λ1i|8c4U1k滼`9wt+>i>_Y3-]A~Xy O^q)ەϗpKItގW2<oJ#:&sg:;V�J۱Wna#]UUQM 8E|Wc<�fxnWTlp)|PɌyL&�R0"N^'aCKx 7[>UUf~tM8VuS`a%'a5ّu10df@{G Ϫ"Q8o䵫;nI =�R >d�HkGUuڥ[1UƋ'OgQME+uզH< `Ky?+c̮Kn5'?"\V>@UQQ:]0vh!1z[lA>}\xg X;PUUU1>/;l=ߞC�b l-{31n=]v�у&Mɓ/N2TU1% nQNo/w-[Ƽ>.+ɫS)͟ώcyqv "ʖ/_EEEs|G:atޔ"l3%%%TUV#ʪ*f;3g2r+V*_ }ygA~^ݳVJ&ҫ_ib$ʢB9hADh4Yrx\zٔSR|oH@h)tM l|dM�vy :fsK`~ ;ܳ73c|LhөRG /`?^v*H,zM8oۙ /[>W/tb÷Dg-- NW>n˖u8篓ri /}0hXp^}omaKh7& ٽ ̭jTUBm/|6D]M"o[PJU9"b$ _G"$/oϦӐJ2V y_cK"82_cXy=ja7y]ɖSYv0q997G읰O\z5@AAyo><Ҕ)<KtMꢋ(((.c˵+_{-wLDus/._߾_"s%N;Dtղn]{ߍ#d{sqUWq%0r-›ݨQ8e DG3d zi"}7|j㥥5^\\#Fpyq 7*+:v2/*W>ߝz\WǏAI-</dF~K|u fʋtzn;&Xy f@> ߟӭkwř]7+3I;2/].c pS;/d@ ߟө[Wc:&f'.e2[-z.N� ;z7m L}f<Wo;4^tw}9TͥW_}|ݺKWT?z|5fGt 2%i`/1y={ՆD=q>1ϐWՏy/�ͫ˯_<ޚʽa*a}CA5okk, _~۴=!YIJ4_ڔۦ鳖0 >z{i͝aɜ]=v8s)//gÛ0t`>;Ν;|{In,n^2ѣFqͤɓyl&wsmqvx /2#H|ٲ8`�DiSU2ӣ޽z|\k׮{ߡpCC̞;Kݻss_¨#Û6[os1vh�o=nl:|8P~A̘5;39~{\tY|8w.|f}:iӧ^Zd <x[IR<kw5&IqgT f/ ~W\<vٟH/!]0dݹi|C|l7?K'IT�W=> ݢ�6>r9̙?y?ҋ2'lQOca⼟1u$wЍ'է\ʇ>I2tHv;շuHt~y,s>‹s>撳dbDZ.ݷYX)c=@.5wI)<|)|4mzu6?x |9ߘ6#inP=*ncorsyy3#z{!<6QCi}<>|_r??91ΝDG><`kx,>.z]u9䭿>k}K<rd5>䟯LSb ekQqmW 7?>e&;}&t ~z\O2Ouа.?/=vۍ?N@Qwg|ܹ3>$Ϙ p92xiڷoO=IӜ{%<,c<K2h@�.w{/=^z))$zɸ1c8k曜JGvy'< ,b}ŋPNxW;$pW2x{ aCRR\̻3g2j�q^2Q#GzkM/g·򫯲ׁAO=7TS>3uk.JfϝMw3so JR\.P8fHy?3z@S%tK4S:G^IikJS[?.1x~MO>p9?q /.vEb̚qc=v<uqO$lx6: /~;%8s%qQһ2~FlS]!vYs[3f V# qgλ~5՟2qAsYP /<XgG˗dH~˿#'s8wlumv4E]ƅ^W%tKp)hJps_8)=6'lX�nYw!%Kgq}'ya�� �IDATX}vB}߫dD&Qл[kէo\x n>bcvؐu ${pF%KIxM%oXgǨej]6@ey9% `5TprŸncX9_?/^DR@Ǹ6cK|^\)Y>;ǟRw5 2?̾m؃[{=&]~9\r gk׎w؁v�s US(++c!\}%0v8wڿ9^={r]NOg~K/<n?qɜr}Ӈ]'LiH~3}kn?_pCNSǎw觇N=?pNY/ 7[諯jʡ7یΝ:ߖ}2.ˮ;wwϨ#qo}8Ӹ;xc1G\yᅜwz]Ջ< o*IJ,.+ksťNIR/[F{S›E 1U+c'V#]'ЫouFEKj='\z!$:7EiǸ$DNRg݋9Jw [\s?epA_/Y'q>Gaa<P24d2VKjIm~OpgS9iO>X oײmcl}]gm7s[BWxf xs9gW$:~/IMaEݴ:*)Zzr]4g0HSm1l `^8&p '0| {dBzvi'K IjC,*bue$ ;y1\skv>~a??_aݱ約I88g9Mm= L`p a&/; 񛕧H~('{GMj1Ql%)7̪ԢxU?ji>'I)Vj)ճ\lMaapuJZXT(=΢BTC0$I 堸3*ETu̱[ $)`QdQ!IjL0]a IAq67 # |$iAa~a(IVaQD޺̑$[a@$¢BdQa1'P!Ia{A0$I߰"Nzߌ* $u& $I7,*.$!aljg$IŢB9(nQѲ?}懧fdq?F�8}J%?q7~~ElA;;N1@)1Sl8^DHev?}J%?}N۵lOn9 ^6F۝=wë7ҋW~HI^_Vc#ՌXg?̖qcP,6c<<b >O>Hռ$M}0Wa(IhWbR[TKpϱI<xo9؅'B+�,Ks�½wc'@z)̩?Y;,{obnw7ɗNjaOqp7p+~ɱC^//Q5Yg^o⽹a,L~^\??&v_L7x'PXKOI\$eà$IWRZX/`F(d]=8zo43E(,Ky饰ev6NrC([oNʩ# oőc6xP% ِCY:k&;ǎc3~!yOy(̭?͐{1fh~s۱о0"Iо}KRaFx CIrE N~̱tWG']y3b} e[fʔ0lh s+PpK<u#w܍}vOkHj2H�_EtꐄD� @B*}Uj{I>Kc ϛCᆛՌ蘠rf̝˖~n(,IRȢBj)q7⡏J'0c�TUi<~ot^~3ozjol)t4H$Hķb�{QHv;0$)YTHдr1cYiP6HSg|ɀIϔ7>aB /v]Xtyǚ*+j݅)|50lpTb[5o.I :HIjj큉a~M%IU1_A}]X�7.<fYSo${�R%wm,Mn}u./O}&t$~k[Gߩ8qUԶĚX g]<L:&;Ỳw<9οyS9sw2t@ A$ӥT|9?|ʁPRvA{(W\Z5GCEy=T[duS )Y:ߏχD)L"UOwNhc.~>I}kϻ݆usOv\ǝ9 $:WĭqgA�`|yx-zp vh ŭPX\V8^Zt:M*|yD8\1°N+c'nTOUÒVd017IH$7Yc$Ij/XzL&I$fv'~JQqqϗ1qgT4Ţ$)Wu- $IY1 B0$6=nX{IֹGr̲0) ZGGX�x 2X+V8Z3*cA0$i @ =kl(iIB+**h_l#ErL%a Iw\"pHeee,*s,*$Im0"e;NXjY!IҲ2ҩ;v ZErLܢ8 $IZC;+\k,HH$ѽ;+Y.$޽9hRq/,*$I r8P`% $ՋKt>[s)*Ijni2{бCIɤEr* B0$i-D`!#X#+ ,ءtk]ofQ,*s E$1 ʋt:M,*$I5Dk[ErLܥa IZV^ZVHRjDȢB9& IRcJ�j*0 8h4m"U,*cWj$5GaQ 8xEmya(IRNP[TFuu%KKPRRDAAL*+jˋshh 0x>ks;p5$) -_ ,Y¢:v(VPO%dɲpP`QS Y-/_A2/S%I}Q!ɼWC1M0#a IRNPiEŊJK Ij<RPG`00$)'XT(]ѲEEuu=$*(ȧ:n]= 0$)YT(Ľl٢=$u[;,<$e8ϒRiE$)|/ #$e=  IRksDx$e5 嘸ua IR#% "PfQcQ!Ij F�0sa IRVP$I`lFx; $IjR,*$IM00: %IZR,*$IMm2'zH,*Zy$%M0³a IRֲPq IRkiDx4 $IZ10$ SPdQ!Ibv"Xx, %IJq%I$�ۆa$IYɢB$E}? "<$IYǢB$EO$IYǢB$Em $IYǢB$E%}0?0$)XTH$aa!RJU,*$IZkFx& $I*$I-.f$IYŢB$U{0$)XTH$ A IRv$IjA0$)kXTH$ �%aX4?$IN$IB IET+JZB#JQ!I^1 IZB$IYâB9f0~H Aa IRְP$fA@aQ30 " I0:uJ,*cAa IR3Za(IRVPwAH Ja0$)+XT(_$IdTD$e NaaqHL $IYB90 "T$Id`DpgIRvP / "|P6ϢB9&N`Q!Ij9=0 0$ͳPqF$K}00$ͳP[T,鴒@6ϢB9&Tڕ II0( $Ij,*c a0$tQ!I>A ka IR3> I< a0$-*Q!I>AAa IR3> I< 堸~$IͤgDX$yAEa, $Ij&} 0$ͳP*$Iͤ_D( $Ij,*zAa(IR3$°%a(IRfQTD)@fP@b}VHԦYT(G wǜ0$MP[TLIɀ0 IRvP[T$5 $)XT(GmIFaB],*FA.IRs[TP6ˢB9j]SFx7 $IjR $Yq,�6 s@fО{*C=,*s@fҐ$e Aa0$ _$ImErX?II0uHfYT($IͤsD* $Ij,*zAa IR3[T8B=,*úA@yJ  IRP o$I IRP+�6 $I ~HErܖa0$8B{,*Ψ$0, $Ij,*oa(IRIErpmY LCI$IR#P+$SVAH$IEaaNH$IEĐ0nH$IE0IEa?$I-nQ%$){&)P�$IM(a IReQ!5䏙a IRa IReQ!Yq IPܢ"@I ǜ0$ -*@6ˢB``D$50 IR�"_$IZ[UaaQ!7 LHDΨp3MIR�Xn I3*$IǢB2x{a{0$ 8B{,*A20$ -*څ$ImETcGGFx! $IjaS?$IâBL /$IM IRVwDBGIT IRV3* ", CIE$)XTH l\!IjjcQ!}ǶaBԖA0$Ͳ#nQZH%a IReQ!}aa4 %IjDea8 $Ij,*XxJo$I( IR#< #$5EE]Ba}*$IMɥcQ!j0VHԈΨ$e VqgT"W$IM01 $Ij,*Z #WE}ʀPFID$YR AaafHH@6ˢB~Dx/ $Ij$Ψ$ )0aHʁ/0E$){XTHA IRSXP6ˢBnDX$5Ea{HԦYTHAGIq$iRa0$ĝbQ!E_$Iki~DhRIRv"0$i-ݬ9s$ImETAa0$i- q$Ij,*:Ž{, $IZKqg I4 N @UJF0$MCDOJRaX?JB@0`HArNm|f�a(I[T I< ^Ay0$i 6I< ^;�a0$)acQ!ի- #<$5ЫWacQ!04#$IZSOA@0$ͳbqV$i<va(IRgQ! #<$Ŵx1 #$e )= sa(IR aXgIԶXTHGP9- %I RlaIG >$IˢB-L $Ixx7 #XTHE {AWea(IRva(IRְd ? #\$!Q;Ea(IRְI",&sGqO$mlTD CIj%- $I*R0 wvIRnOD $e a@Z $IYǢBj00= $IEܥۄ$IYǢBZ#;AwTJ `NF2 $I:� Z,$ITa-Ja(IRֱH!^FpCMIR]g4CIEƆA@UUUqw՗_Ck00, $IJ> " CIRRUUŭ7L"K.ZHa'NIԶYTHkaP@FR)nfu~G:Zy  IEۅa$ HRr-՛qsydfk0PE$)WXTHke0jJZ%E~~\w͵t)Zx. "�$IYɢBZ+A IR+2d0u\˞{IIRP5q$e- i#T{OðV>'I-geI1trK:gz-ʊF=P IE~*ɔˣ*%IMleI1l06b zk/v-7̡B^~yyyᛮ †@0$)kYTHkP_@>*,*`y0$5T*ŭ&0Cup-pO~_,b2 7_/Aa IRVZ 00( h_TH:mY!I`7fȭ[݋;~8,'$IE7gHs0$)%5qR+NIR/[F=F.R0k6n`0K,# .(o"IjDU2NS]UEXsJK;PRҞ[_$$eU!Ij>SI&$~W>R�1yyI:w.ey ʩVQ_A]3)�_0�{a(IRV+*^:/*l cIR0# #+u%Ig>!qt.:$e= l ZT5IRvyx1 #� CIEha@ :$ Q=B߀GJRy$ " CIrEԨƇA4tSMIR[q(CIrEԨ�J0a IjבL3C@aQ!5ba>2 %IY)6z$I9#? $ =aXρ'*6xc*~,-#G[t:N1bx8,I:q7$)9Bjta?xc:۵�� �IDAT*! KSaIR' BptJS,*F?3$ṙ' G$I5PbQ!5-&!Kb7$ .$ɢBj}0CaЪ{Di$5L>I`0$)XTHM" $$m{:a(IRαLܢb!0$eE0a IRNhcFgUHR6P IrEd x*@$I0)04 %IIR{L)a IjӦoa$I9ˢBjR0#0$YqgS�$0Ԙ?jU8iHIE"#̓^=/$%U�waza(IRrFzasaX 8yp']rq6WmIǨ撤f8EF8< $IiΨ\pedʊO 鑄D>ϹT|=?7=h,_`n\ً,?[V{Gco<cso:Ϫs3=_^~HAb`0$)9Bj? :\N*>ߚ A^1_ᦇݧQ c~;W<'zU'~#(7fF G;`rJR9jyt<'w'pɣp»$E̾Cq tCIrE,9z.;V�>4ϟSgF@Yi.)>!*ӕL] >!Qήdx]l([o#5ۧX6{WZ1/~RNP /$I $I9ϥRH��oY^^1j}+>{=l^(fQ^G*6˦!>)Ǎ |a0$)YTHfw`Gp dv/ �^$]vޕ's{ƉwӰ \v[,-M3P |wpڷ@3.K3j_8/_\%I1VIgG$8*°WS7Ŗ^%z.ؐSR D{Hӫo=d7ep i,l ߞ^{o1jmHK~} x%)W-N  a(IpF6"LF]ޫ'=λn!=tQgfQ NŬ'x2Q͡<G}6=}v�|ߘklG�|IwĽăYn3,dGLg$EƑY!IBeePKӤR)ʗ-WϞpXyfϦo>*[jN>}jjjsa$I9"EfÁ71h4d2I"5IRvO)*. :T�PԪ%EW`0$I߰ZvaXG@Ԫu8%IEBd{ӷ P* /P$¢Bj1a IR2?'M!IR,*0Ǔa IjQ7aB0$I Em�#y%D̒.aɜ$IbQ!kP D: [V:$e_W$R ]-mozZˊr"_:pDܟ!@0$IZ\8ed8`"F- 3 ]: %0qFKR d}H8@RK!:pEM2bDho̩$qAm녡$I 88, q[_,KTa!̑$). H�WqcN-+$y\u8$R�n��a0$IZ.4|߉ 7$5ˁ0K<CZ10ˁ$Q|JP$`Q!Z'�Ga �CIZ;(GP$`Q!Z 2G6(&I{) ##SK5aQ!jkZV| , $Ik@UF8$)& [YV_8P=/IR P$5E&$#zLχu8$,*FF sp.d6, $Iu{x2 #ҐcB͢Bj$DFKX//s$VUðGðV+**h_X|!I2,*FH$(-))g.�1vVcL߅a2JKJ,)$IE:wH:bi)-$2A$�ga~MyiYT;C$ Q% =wgEy9 l 1 H#UF߱"P^Nk3$I@ҚK$$I ӫ,a%|bMs):ѥXYqp`0&I-aXcS4=JKJءy$dҢBZ$鴲^:&JQlz KӤi18( HRß6!33$ ̢$O>Xρ?Jjt$iGfߊocq= 3p $e `96:szG}V^CYTHM$mb2p T%;[aKRV;Ѹ�ƅa,&$Iϥ ͽ 4@'^KR6 82 $IR-S?e�X\__v{_HRkwptXRH4,*x5_Qp@K #e"$)XTHYo;U`p�Ԇ= Tu 7$XTH9, oѬݾZEÖw=IԈ,*Q� tY}(/ly>ڪ̀@=.!N$5% )FT1Uv> $R,�8EJ&`Q!-d6)p@Zedf-n>JM$5 )}F[1}FfK1Ijmv 3!F)dID,*םG pp/]!YYcS2:$ YTHړ)gwIRKyؘ/SBw:$IjbV@<A毐$1=lGfFECtz$XTH !SVl4wqU_9L #jșl/˖m-o_;6̖[q2G-nQAyS|<ns yo.5ǵ4@}ׂT797Gwm�†]jgb- <.'\O+X0 """ߧ,"7| @KL8Fh (p-0F` *Dš͵p�]IEȩ ϵ4] |("""灂 9 aX!�\jgj9p3Px/]9cIi ] """r(d��ˀ. <5|KMDt<=Kt|DDD<QP!"gֶ}_�\jgc�lvXSI.ӵx\YD΂K79""Jcm|6X[(HeSW"rF F. `ܿtYD.Rۀ[K.3q)V """ )-a�<\jg+xh&z +lLtXS"\ """R(2< trEM@C@鲈 a+<נ eHyQP!"e0 Yld{a=X;zȅ00 +]>+mqhg )p5bϸB=kXbFDΟBc1!_|nc#""""lN>EK/�Kj[SH@` B}}92~ ţDTe ΍5ga|M/A~4̓rx%(~�_R~7+ l{"<ʆugԷtL$Á(:KʬkJF Ae!k=o\N~/KxG;6}iM=%7<KxW&gӄq.MEᄇצML_<3sMI'ϗ>=/8l'  ඎ8yN98j6hOxz5o PI kT '0qzR�Lw(Z~''AVaw$V^?*�p烩 Ysw5`X54^^>}KD>]Xl[J7""Ra;ͥv.ObTB~;7>-%o]U^ԺN6~T; 7Ͷ;e}2/>:_E]\ӧ3Vgpl]/M y6fLa.i7̬eUJMA1o2ܹ_\:w0an %>D6(9Oؘ}( OO@ʔE!GI ?UF^=Qɹܱ _+[4�6xc۳y[G; 2} / 簜Bu#kC Tt KJC[ >vEpR9B^=s_< #›x<5~{`Km&h Gq땼tjaAAyAܱm_r)ēvIjr,û(O#Q 87^:W^ϧ7N'�V{!{[iy gK^"ɡ|F?[9O5r',8J)ip+W^ܭ}za׋Ip|U9Ovu _u_%zsFɫ#GUQ4-].s�5$<B\E)kkX#RI3Yt5v3X\F|Q#G#1/'X2{.a~7R+48r9^05]d>l^9pikfsQ#ʵ @]a(X36hrX�3f~@gB.dQ!rD&M g&<_�qG0pX5)6qabfgq6U%sY#߯u=j|͉V(`pѱwokͱX_@n"rG6}5+ty�U\j""Rw7ˆɯ�nƏ681L @pM+\8άL` *ip4֭(UU� ,y 6 J {Mf<6Ṁ)|3||4<ܟ0S\04B<;nrձ?^S~ u Aْ0m&6gq3~vʓe9y�77v,$+;ln�xkX#[0k+FXZ|=qs>+B 9S-l< j6<#貒L Yهfl1mϏ㦁sbAcp!3?#Y&83Kd0W ֯yqC`hO O< d"pbZB0zlc>oM]MF!\d}x+d $'d@sLHkcRH@BP b>= fnDZ9xwn~'qM63|Z+1@_**55e<54SDNe(-X/ ?j\9mB ^xnnv|h@pgŀՌ77fײ5 d<09h’sj'uKN~%޼⳴]d'ow?698. f3(6wzdl.HQS\04C<q&v'ͮbr ߬n|5 vVuAOL"ҹ'vJd $8&pGvb㒃&>7l�hi0X�Ưa3v=#4 XkJt`-9+_ہv#܈_KZ'bkG딈HY'v _ǫ�ƺևnݟ>#&l2rp `}5 BH?ŧH妷G=t%`&&=ͤk߳F&-2j7zở^h )9Ѭ_W]}ܛJfi_s |Fjo=Fp8y~;v~˹M,O>&>8򈓕o}S~m b*Ƅw*N < <L>N,Z~am:k@WN"X7s-xp;DDY kh1/?œ S cj,fhz<=c�x~c[pς{Òs{Aby7y'`0q;^ЩA \N?u & > .ΫwG-Bfdeg}+/d&Nljw-Ǐ6IHZo:V+^ڽ'ץVOam)|>CROތKMK͆az<rQPPofiEr5Z JVWr`A1xϥVV`Q@!""RTT0 b U �E{šޑR+ 6;pГʱ GAHSPqfc2!po@KE* {wZYn!䯷B)kdů, txc5=>c,1`!  \FDDD*"LAN8'Pq@H^egH~Ś6U^zZ.""" BH`K Xs;R1B �&m~kDDD2QP!RT?sS*/wUj4B`>0)].S~p Х&""" BSK"�]vBhu'/"Vt[J˅ ka.5TT0rvX+cH)U8@˓VXwEZ ]j+2 """�"LA;pּ=cmh D!|a'bjt\ybCN.5(` *l9FZ|uqxtZ[t|O$R` T6?  =""")psmbp)?�9Uu  y{IO X#%J+ԥX;x\DDDDʎ s⁵hOeL`~˾�±F_am'fBBĚN؄5j"ݝt\5bGDDD))c32]Ҥx+ XTtd`9Oi%G$n$!hTƙ:Ƣ`ɝ*'aUzm7+gBAH tmV ֚�Xk _8qذFdT;騊wǚ"VF]!+؈k2w!S-2JEDDD*_�� �IDAT  t,:^b;0~'] `.:`M= 3|v;G1_OX;n,(6JUmJ:vvĺ}u+RtT=,:z`Ms(:܋>'#kEEʢ knXۊF.E~h 5Ծ-X߀'):.B@_?VH-kEDDrSP!"Ri]F[Dh+VQr:��?H奠BD2v׈ĺڶr9KvPZk""""""/NLyk1-X[\n):Eb̀X&&VDDD-T\lXwC`gё+VŅĆms -D5CDDDTkU-:ZXZ kϬ>]@acXp-:b&@S[EDDD. *DD.:Ш85cWc7vg'h5u""""" *DDoفEǥ.5Ff ,R=5*# <]"֔h ("#qBDDΒ?,6b+Fqb- CN>U[ehD) %DDDDN F/p<Z>۔_gN ||cO@V޵9Fz3O:�9@>VP_t`&EGqp(0=ִg/`<!=` u~N&gXKb-ז:Q7&79r &1 ;WPȜ/_=={pRrj *DΣ&7'uk.ؖ3ws"rl@@QtIDD_dl׮7n˦|ٝ[}Cvw*L8N`L;l2}:]]񻺃WÒ6OAg7(F>3�]˕Z|3 `]` Xn+6r1 &Ups#גǯl,eH5a}:m8R]e@j!`vZL2N=3Q!rԶkn|8e=q6HZ{GKr| 3V*Czw3)Lx,]HTy0mÛlJ ^nĎ|xo^'/0;<jw1KHy߄mqGvSgks"ۈ3ڦ>/ ߒ_DDDDʎ ap n{Na ̖H0 lL^L)/^ڕT%e 8'`M|}UM;gB!' KD ~bѦظX|јf�;᭹f!A#ҰWMG>q7Pý8qӜt<;[s4{0[_-^o/xxmьXMʄwۙ}߼GxVގ_~5g`~�,(`ܺj nV+PÛ/粦yٔSuRy/y~�`ш76)or"в~ ظ0ik>ʹ_(g/|%w3#Wg1oWHGDȌNB}5˸Im-َ<8c3˖L&-.iLoǁ2)kٜ4{6yfpynfwaQld-V/""""ӆ_�`�`Enޢ},8yk)4А1wQpZ?0z@< 8Yr;X>+^hCaGd7 l-rKcX|0d $̜u2I먷w_օQ,>F11$mO3Nسy3 qތHJɢUlu]!#93<ԥflY2,GZ{y0~f`ٌ`"g˶Ca Cyq/L U{v3ږ15ۍpsЄ۸PB Ј N,[Zҭ1C-TL^@%QNn☭ wMȜMSw*kϐГoZB'[;qO/ u}<0sa}8?޵c0}jױmkH6~j?~wowBGY15�0oٷ >=oS%BJ""""R@6JlXB.J9!%9°قgŬ(L36clJ� )@!@o}vß`֣RU<<nqf2˻1UX̐aamB-`En.i[իSGhoوop;bXt?G-�Ksb;㟧o,/&kخթnxԳoYg҇4| 8hnv`.5U^բS\5@`{|[>m�%;^n`s/i(9Or6x׍g?zhS5F_�ϖG0|)9unjUMӤh]7 Z<mL͘qɯ}M:\Q.i Ut2f&`d81\Z͆{p�ޞ}&OH?5Ҏڊ89{v; ?&r#{+L,.sPZ^hoGœsGFR<`n ;P'<HzA%ӂ v>|<(Za:lNs . pYx& nk&UWk�+6}HxI!u 4xյb}�0/&c}Ks ~=Fx*lˠ'M #}?ԲR6SM/$+"g%τZ5Dz?<`j܎ӱQ$U9y DӴ^nePm�> Ia2ڲK70dޒB>|qc &'|jfl ?󟵿r!<vv?GnZsu0Mj`xN&nՠEDDD_d"D͂]omyu̵)�$a_aޝ,ڝ&S$n). OQ?NӤ;gHpW|if@fX֧,g{J-Eqf0KEPw#4 6߄\0!/7ϵ\-K0l&6NWfѢ3\~Hy+ G!]yQRh`?NDx  ix`m..,<FfP ^Y-K|0<0݇Ɔ뙼Ls-җQ= X#ݳFvn]3_9a؃[0<" j-,T 4�i*DW�ç\""""Rv >'--nb6}BH_ѝw>ws?K bޚD-O#~JO=i6%%0b'YDLHp0!`"zu!{WG@I!Yp{mӖ;'ƚ#HGW^6n&a_6Q#xJr g=f6WphDy'669ҎJ7�X~yk #kH.!ٕKؾ0^jascچ,$A$;"0m':FMj*_gorA+V%ogaht']; Y[b3vS}�=x􇈈7aB]^y?N~23`ݘx!glnJӴy{lUN4ᓘ,K sӢ9ZEN_ r7xZٗĮMո|(;%%<mW!O}PXO]3lY<\ku0 ^}ΟK޵fZ {6w <ЛǽY3g&_F^ܹ &ΤUр'+0m"Zu槣ȫ1rC'܌FgqY/~gƴxJbed]ԌoU. ߀XޓBq],ցg{~)vC?;w˿ otu]Xj>Q/Н5ZDl>og3~:\^ãIYg-wݼ5W-f_ kYle~\c6& hK3clBu'!FBDDD<'rOp[;qaM8{ -th@Bz̝ ]r6R<~5W~Hm*mdTIau<7q"= -s xKx;~pkUa@`  !UҺ؁vq?Z7kG'%m5mxwYm"*R|5MzSjL7�5 M" ԛ&ң'զS)^􉴳e z.z >17"4q:?NDxpEп\T&f{'֟}Aa{yqړ=9>3ҤXjZ^>>l6 k~҈ 橧\*_z楐b,kPvF=w-i3)eK/6Bzz6~B\RVߊrQЈ0qm8ѦFC;$42ȹш?SP!""""""2*""""""" 4THBDDDDDDD* """""""Ri(JCAT *DDDDDDDPP!""""""" 4\Dtm}|\"e,$8еIDDDDDDN~HBDDDDDDD* """""""Ri(JCAT *DDDDDDDPP!""""""" 4THBDDDDDDD* """""""Ri(J͵ADV' �3u/ Y@sA.P("""" K:cF<Njr"v{uv~N&gXKrK䨉雇g]zI`wr9_3T{>z'T'FcZ>-SMF9=[y7[.""""/5f774i4f}cOBY]93qd^` wvkn^ K< ԫ<oF1Z>r>dΜE`fDDDDD&ZIۂg4'X0{38v>䬥>y׶c~FMɮ]2f?BCKP{v-Wi6]p&b3f3�Ƙ9tغ~]1aLR%B=CK{q7~i*ώc 8糵I9m mS] S�Jv[677| 0J?3޿35ݛɋiT3S69X2j$ x}UM;gB!' KD ~bѦظX|јf�;᭹f!A#ҰWMG>q7Pý8qӜt<;[s4{0[ХO_.o/xxmьXMʄwۙ}߼GxVގ_~5g`~�,(`ܺj nV+PÛ/粦yٔSuRy/y~�`ш76K*?9O.-HşofRu'BrL ۡԏ eq_ĦE_AB`B75˫g3aT(x41~[tVـ^R�+!uk -0oA:Ґ8; �O-O= Geuv,9y,/!#{]91>2`Zf:u;/ow(OOM#N'ټei8o $d*O[ LRif3,B^#<^f?|3 }Flx0sYk3e[!0ɗ_8�GL͘k[Үf_הn7>^}ZBnB )@Ayc�w6'wj6' ;hj90!:>lLXtl!apg 13yo&^{F( VPEDDD ?3{?m/PVzۜL0l`:Svy;clJ|n=}Jicpq5x]}c.?$.lCHhݏFݾ He!'UX̐Q+ ]jҵk7ab/NjX~ؤMRjƓe#1ْ�>m)ulmiO^^GMÈt1N#FCIoN=c=m&}XI})ۡ [mbֺ\̂|rz0z7Pԏn_`8^vn1pð|M9pC| ,܊Ys�|TYim +y Rn\?! ^�Ҏ< EYDDDD.,yo;y,iΡD5ގ')y =؝T8�r yҠ^P4dwzO7xA!nӜl)HBZ�L"x׬M,_j"�Vlj-ޓBl)�^!ko5wu-fu_7 k˭I=X=wugkăFx*lˠ'M #}?ԲR6SM/$ *D#{0/%l`Xf/?/S^6pbuw,"""bO970l0ԵY+�$a_aޝ,ڝ&S$n). OQ?NӤ;gH9 l43 f,S=%͢8P3%"g v Pbwk |ss<r)XoE'Yh_\:Frg]W=N'Eq``c!dm H+A=0&`:eRMЬE\] Ljȅ̸V~9/S-k9qϸc}q= I48ʡ4ǚf/nPR!vRU >Hdp06/ W7ҩw5~1q R W:v=mso9By|%n^_iM7 #0Plo 'rU}'T<"@�81w .eЄ$#>]<CßE&<t؂|#! poqOyũ\f9yj}xC~ No]SR@4m޸Ԗ=#Cɏi4PEseYH+` w#`ѭU me׺+?RcY';MWȉmVub6fdu|[o4lo]j ^}nI] {cOFFɑǙefL_wg,MIb!6�� �IDAT+0m"Rw?^1rC=1q,`΃̘6ت4s,N2izu./4Cp 羕 zѶ#⼃f!e7 l ؄{nr.;h^c<Зj7f٬ٿꞻOB:vx\Ldo[g'.X ͵x{g(XA5r5(U 4 q=N.9yCSF+?J$6k?:_uxOxxE9]u%`wS80_wb*ui] @P Cy5X퀁Ē6x,6pmy)o|Mge~O{ӦM`x {_Qjө%~>vս_e\_@;Yg7Fb&Nlj/uRQV^'{ߏ(o>3ҤXjZ^>>l65FTT6O=Tak_:[+BY7>ׯS;^(T[4B. Q!"""""FT (({)Ю"""""""Ri(JCAT *DDDDDDDPP!""""""" 4THBDDDDDDD* """""""Ri(J͵ADL&JǵQP!RB]DDDDDD4iꇈT *DDDDDDDPP!""""""" 4THBDDDDDDD* """""""Ri(JCAT *DDDDDDDPP!""""""" 4\D|mu  (?�6ZETaHfToБ ߞMbXgպvGomcy%F�]̜|1r<{x4-Ua~a,F[""""gN_3qR(7߳gks297U\juS^'GMdN<<Z5HB�k Έ "у=/.v!)7n4`vg2ww*|/'ks2%d+Ӿg{3[+$;(G2 0`>2dz�3/ӵ,""""ao^w oih4ƭ3ǨwMssg(ɼdy`;Wy~c!ߌb3-޵\w1?^qw5&:U!;9�oޮ]*T & _~K~Aeq�VO30e ,}%MXׇT'a_ɠdկpv2f?wkBaǻe@AH%`@ڤqX| ?'X?m+_S䰃Om U}:>.8ӘU+ov/}2/C&tgLR%B=CK{r}^>ECZM\E@x!_ty"GSi o c&<t/.JA:Sl G)^~'-Faw wwQU ?NzIBH# J#E@,؅G\WW}dW˲bokCpWT&H$�iC`f~sM+|9&sM550\&x+!�ï^ E\6nĜRvfȾYQɋ 'I�.' @M%,]: B%ڡ"NQĂoM|vv_5O hGt0Fn5<d+[y;6!fԫ+n1É Hwf|^z0ѕYF˥xXL^Nx7]x/>OJ_mΥAu#ۄsu0|�X^V; ?'?g M+Cjxntztbj&6/frPv| I3dh<aFN 4�,݇Ȑ�,ßw3oc+vvV7Y|/j' Mx|?E|Rv1ͽ Ok٨E]Y'pۘGv:N@Zɮ�j7 k.*/Ot2{*j"xdff,�69`/SoQs/?-rK|$61U{3_Nl᜙a]lVrK{h[Y$8�ĉ+pl'ql.O>^Wd71^ESs0ޝ dc ձnsĪ Vyd?~^-f'$[ V.8{7Jd ~ a; +>½' �לV2{,dsHW?z])`w0aD^*``Uw07qxjW fiхcYtso{XSGr"S`/wp�NWȲtVB<7=qſ{7H43$O ѐ^a˱LpQ*6lC;W(8O VL'y4Jk{Uf)+A_SI6Ly]vU]LNa0^V5c;Ek -TRk ޾ *:qq4-Q8P3n 3s׭22dnNLzvrzǗqčź'yYYN4ChhgGm=Ķzp#pP dlSFڜz:Ԑ] qпM^= lgѳ&.-[yCjd"D鞝'o?vjۋ-ZM|TzzuP;C7>әK8!l}; tAU]70Xo g?Mks=>[/ܡI i�<ԯ ]76 |+(8,v2xW뀚BJ-[ffuǕ4:Y9@lit.GX&PSSwuD/hԢ`=›=^D �^`R9'5Maܵ�2!%9ujCp$WGШaT9~d2�/fljRXv(\7-"""r1TfãC@{I#ۈn0I Idf}Nj�TytQQ Gl&`�\Pu0mZ5vzqfNvSSB�8-hu8Q^hQ]uE\wlM;0] rG[Yl?4#�62# /]q2—U&T/#0Q.f@ gi^)rBȀ#;s | ,,o"-, ,bMh'̆gw61ÁueK-{6 <7 :Mp6b�F7X|o܇c lڳ kw0,޹3b/)&ӽHDDDW[|Im3νy>:H>/.>-wY,*v:0h00sI6f;GO,zۛja iIvzr͡,=$lmYmAue%XPUY^] o0ogeq1L+*pMTkWXŖ!霘ѪGP\fҵS"cݼ`28t %5X'g` p?CY3? coG)p}Ox 77.B.ZdW21%Sc94{/fڄ6a&L{`mM9k`Hi gZ֙n@oTq6\M&*$BCB ӏj;;Ji] t6 m} ܻٹgsRZ2bg׫?3ND !>NV g&Bl?Nx? fT 6,Keܱ ӿwg2fg< gC[&&WgόH\G0r: 10}XYabg&#+>^èE!42n$�ڻ 6 &[_F q?Et0gQ]/O/S"+"""rq,(qma40}L툟fI^ WgӡSOgg [VBge᪶4܉Wc7QѸWʝ@<@zJoHh8>I;uб0[Y{hcM"z_-w4CHiѐ7pAifUkr-wTZPpՕy,;ϖ x0]6ci|儹 V+'ٴ,cx$_~E2W|<sWm-ɵS_Cn˗'{BkM.v_-E{=Rw:g`Ù)v3efPGHwM/V.*`,Gg`B]wlvmCqӺ`?R <?ngeԬ\G`oƤi@9/XĤ0 e9_- DDDD~,y;s人pC9{OT eT FmڮK>~ܫ9}׾ݜCv1dE׵܇}̧_TPߵ#܀o '�bma׀@jɻ[еA؀D;![$s_�2bLxeL/^\- vz/Lx%Ͼ�ieu b[s<Ątt;~%L}iQ>5<GSwecei~=8Q^~~snD.#er<}pG7羦50{nJiOclt<3M(.)/ �416\t&Nt/7dݯɓ}.""""S^uc \.{)(._O54q.:M9;о[h*h釈@Ax """""""1TPP!"""""""CAx """""""1TPP!"""""""˽@D.E""""""-( B" v/IK?DDDDDDDc(BDDDDDDD<  *DDDDDDDc(BDDDDDDD<  *DDDDDDDc(BDDDDDDD<  *D. Nr,DEK_>۟)g_#ªRMhH$Ø=q8TՎ-[NЮ8C#.99owsQ|v¢o+~eoz? UY3ܫ�8~ fpW_&pOmzy|"βUx/=NN72m v:L\R'3NqYNww\8,Ͳݳpfzl\~m| 5jVΟw:^T 8-`Wr?Ř诸n J0{Ó|Za 6y|k'Y߭SlAvvFt c&_Fgaڽٯ1AvKʲ, +PG,xnU.kg8YLF>߽ IO^Z,/&CWw!uÇo>f׍L}xFPiDDDDcvH{ZՕyyo48wk>-�5unl`KB,+sW['1ԟY"/` mgW45O%\N*JXt KCE4םN#Z˃d\CKjЎajx~V2,wm CͨWW0bz݇ 70^/t `*f+O8 K]#|㙴/o|e_ ?|$ڜK2F aFw~N~zW2:9ӇP]Ll^䚡Tfxºrq=*D< ,])> ʶYEy,]bu?lZ|M0K\.L`PG;=>�l(3fXLCSPdqו]'ta؋%))%O��`"?I<2z*U~<͟}Q̩w>Xxu(\ǫs3*sĂgmU|ُWKY=o:1F d斂UA ͺqy'HlX| +>½' �לV2{,dsHW?z])`w0aD^*``Uw07qxjW fi�Y`;x7Ft!mX܁*o?iԑ\.!(H. /Ay[ֳ7XyE58yt1>wd֭ٔO&avw|Ǘqč|^ОNuWb ǻ o.^ee;) Ob+ʣ 6mᱞvڥӥi8MۧظHu=x45 W=xSCR ٞH\e,<׫;N,VKM\5YԢ[b(ݳXOj|C0CO[O z{1{7{wZEI5i}&M"okn}3u)]}ߡ : G~X&Oѧr+\?nc|\3h�<ԯ 8?o6/olxaR-V'5Maܵ�2!%9ujCp$>oae1|6#=|$gvbnħQnEDDD2T.}rf<)�iecdz1mFz~0<--t6vL҂`jtY?U<DdTgLaڴjF �`.>^YZNvSSB@~l\5N'5ʋ8(P; ^irѲk?trG[Yl?4#�62# /]2—U&T/#0Q.f@ gi^)rBy>4yqL5N pe�&a},ڸM{va|;wX\d0d�0n:$ˡ_mL\oquu~kwo7mYVD0~A6٬>:H>/.>-wY,*v:0h00sI6f;GO,zۻja iIvzr͡,=$lmYmAue%XPUY^]Oۄ iapeneՕ79w$"] p,=;sj*v`XiaaodϚyg;vOdGv6-B[n(ii2NJ-��IDAT: rZ&""""Js3$ 5 5hl ߤk8m7i`ڄ L0}5 dkp#%*߼w t !vJQSŅs5^~BB !4(L?ЪE<(uf$$=$35kok1sgrKij^؋U]vV(,'<OpvJL `5qb +s?)vB ڻ=[ͽ h,E4"\HVM�yx':(~a$ژړ}kr_<:9G ;ûO;^VH3))9i=|r{pK/Lye[OgI^ WgӡSOgg [VBge᪶4܉Wc7QѸWʝ@<@zJoHh8>I;uб0[Y{hcM"z_-w4CHiѐ7pAifUkr-X0ܻ(*-(8r ʼ`g{UU]{q.X_r+IŠlZ1[pk/"+>[H~~|Y+fک/!`KDEĽRP!ro59un(`PƌB@|�EYi5+*؛1i20xa@<4ɚ K/u#o\L@˫l*""""! x}^)9Μ*x;>wࠋMf9wG?_ سJ`ef.U`6jS.؀vX^ !;>is׼OCNֵ xLp2߫p, v !�۸][{ HKc|E?\N ,ƄWu`ѩ亁W컛a 0V6X 5CLhNAG<1j0o[ԗfScq?u~|!Q6VK6ѓ?7F2bY.ӧwN}Dl<@;H]jA?L3KJ 4M ܁fT\b&Nt/$O^$""""~qrzɺ_h_rKA3*WA3*DDDDDiFRP! *DDDDDD'z<x """""""1TPP!"""""""CAx """""""1TPP!"""""""CAx """""""1 D.;^$"""""т܋~1 *D.M݋DDDDDDG *DDDDDDDc(BDDDDDDD< S2f8�����IENDB`����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/docs/getting-started.rst���������������������������������������������������������0000664�0000000�0000000�00000024601�15223753015�0020661�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.. _getting-started: Getting Started =============== The goal of this document is to help get you up and running quickly. So without further ado, let's get started. .. note:: Hopefully you have some familiarity with the `flask framework <https://flask.palletsprojects.com/>`_ and the `peewee orm <https://docs.peewee-orm.com/>`_, but if not those links should help you get started. .. note:: For a complete example project, check the `example app <https://github.com/coleifer/flask-peewee/tree/master/example>`_ that ships with flask-peewee. Creating a flask app -------------------- First, be sure you have :ref:`installed flask-peewee and its dependencies <installation>`. You can verify by running the test suite: ``python runtests.py``. After ensuring things are installed, open a new file called "app.py" and enter the following code: .. code-block:: python from flask import Flask app = Flask(__name__) app.config.from_object(__name__) if __name__ == '__main__': app.run() This isn't very exciting, but we can check out our project by running the app: .. code-block:: console $ python app.py * Serving Flask app 'app' * Debug mode: off * Running on http://127.0.0.1:5000/ Press CTRL+C to quit Navigating to the url listed will show a simple 404 page, because we haven't configured any templates or views yet. Creating a simple model ----------------------- Let's add a simple model. Before we can do that, though, it is necessary to initialize the peewee database wrapper and configure the database: .. code-block:: python from flask import Flask # flask-peewee bindings from flask_peewee.db import Database # configure our database DATABASE = { 'name': 'example.db', 'engine': 'peewee.SqliteDatabase', } DEBUG = True SECRET_KEY = 'ssshhhh' app = Flask(__name__) app.config.from_object(__name__) # instantiate the db wrapper db = Database(app) if __name__ == '__main__': app.run() What this does is provides us with request handlers which connect to the database on each request and close it when the request is finished. It also provides a base model class which is configured to work with the database specified in the configuration. Now we can create a model: .. code-block:: python import datetime from peewee import * class Note(db.Model): message = TextField() created = DateTimeField(default=datetime.datetime.now) .. note:: The model we created, ``Note``, subclasses ``db.Model``, which in turn is a subclass of ``peewee.Model`` that is pre-configured to talk to our database. Setting up a simple base template --------------------------------- We'll need a simple template to serve as the base template for our app, so create a folder named ``templates``. In the ``templates`` folder create a file ``base.html`` and add the following: .. code-block:: html <!doctype html> <html> <title>Test site

{% block content_title %}{% endblock %}

{% block content %}{% endblock %} Adding users to the site ------------------------ Before we can edit these ``Note`` models in the admin, we'll need to have some way of authenticating users on the site. This is where :py:class:`Auth` comes in. :py:class:`Auth` provides a ``User`` model and views for logging in and logging out, among other things, and is required by the :py:class:`Admin`. .. code-block:: python from flask_peewee.auth import Auth # create an Auth object for use with our flask app and database wrapper auth = Auth(app, db) Let's also modify the code that runs our app to ensure our tables get created if need be: .. code-block:: python if __name__ == '__main__': # Use the underlying Peewee database to create tables at startup # if they do not exist. with db.database: db.database.create_tables([auth.User, Note]) app.run() After cleaning up the imports and declarations, we have something like the following: .. code-block:: python import datetime from flask import Flask from peewee import * from flask_peewee.auth import Auth from flask_peewee.db import Database # configure our database DATABASE = { 'name': 'example.db', 'engine': 'peewee.SqliteDatabase', } DEBUG = True SECRET_KEY = 'ssshhhh' app = Flask(__name__) app.config.from_object(__name__) # instantiate the db wrapper db = Database(app) class Note(db.Model): message = TextField() created = DateTimeField(default=datetime.datetime.now) # create an Auth object for use with our flask app and database wrapper auth = Auth(app, db) if __name__ == '__main__': # Use the underlying Peewee database to create tables at startup # if they do not exist. with db.database: db.database.create_tables([auth.User, Note]) app.run() Managing content using the admin area ------------------------------------- **Now** we're ready to add the admin. Place the following lines of code after the initialization of the ``Auth`` class: .. code-block:: python from flask_peewee.admin import Admin admin = Admin(app, auth) admin.register(Note) admin.setup() We now have a functioning admin site! Of course, we'll need a user log in with, so open up an interactive python shell in the directory alongside the app and run the following: .. code-block:: python from app import auth auth.User.create_table() # Make sure table created. admin = auth.User(username='admin', email='', admin=True, active=True) admin.set_password('admin') admin.save() It should now be possible to: 1. navigate to http://127.0.0.1:5000/admin/ 2. enter in the username and password ("admin", "admin") 3. be redirected to the admin dashboard .. image:: fp-getting-started.png The dashboard is pretty empty right now. Go ahead and add a few notes (http://127.0.0.1:5000/admin/note/). If you navigate now to the note modeladmin you will see something like this: .. image:: fp-note-admin.png This is pretty lousy so let's clean it up to display the message and when it was published. We can do that by customizing the columns displayed. Edit the app with the following changes: .. code-block:: python from flask_peewee.admin import Admin, ModelAdmin class NoteAdmin(ModelAdmin): columns = ('message', 'created',) admin = Admin(app, auth) admin.register(Note, NoteAdmin) admin.setup() Now our modeladmin should look more like this: .. image:: fp-note-admin-2.png Let's go ahead and add the ``auth.User`` model to the admin as well: .. code-block:: python admin.register(Note, NoteAdmin) auth.register_admin(admin) admin.setup() The admin supports themes. Here is how to use the *crux* theme, for example: .. code-block:: python admin = Admin(app, auth, theme='crux') .. image:: fp-crux.png Exposing content using a REST API --------------------------------- Adding a REST API is very similar to how we added the :py:class:`Admin` interface. We will create a :py:class:`RestAPI` object, and then register our project's models with it. If we want to customize things, we can subclass :py:class:`RestResource`. The first step, then, is to create the :py:class:`RestAPI` object: .. code-block:: python from flask_peewee.rest import RestAPI # create a RestAPI container. api = RestAPI(app) api.setup() This doesn't do anything yet, we need to register models with it first. Let's register the ``Note`` model from earlier: .. code-block:: python # create a RestAPI container. api = RestAPI(app) api.register(Note) api.setup() Assuming your project is still running, try executing the following command (or just browse to the url listed): .. code-block:: console $ curl http://127.0.0.1:5000/api/note/ You should see something like the following: .. code-block:: javascript { "meta": { "model": "note", "page": 1, "page_count": 1, "object_count": 2, "previous": "", "next": "" }, "objects": [ { "id": 1, "message": "This is a test note.", "created": "2026-07-07T13:35:04" }, { "id": 2, "message": "This is another test note.", "created": "2026-07-07T13:35:18" } ] } Suppose we want it to also be possible for registered users to be able to POST messages using the API. If you try and make a POST right now, you will get a ``401`` response: .. code-block:: console $ curl -i -d '' http://127.0.0.1:5000/api/note/ HTTP/1.1 401 Unauthorized Server: Werkzeug/3.2.0.dev0 Python/3.13.5 Date: Tue, 07 Jul 2026 18:41:49 GMT WWW-Authenticate: Basic realm="Login Required" Content-Type: text/html; charset=utf-8 Content-Length: 21 Vary: Cookie Connection: close This is because we have not configured any :py:class:`Authentication` method for our :py:class:`RestAPI`. .. note:: The default authentication mechanism for the API only accepts GET requests. In order to handle POST/PUT/DELETE you will need to use a subclass of the :py:class:`Authentication` class. In order to allow users of the site to post notes, we will use the :py:class:`UserAuthentication` subclass, which requires that API requests be made with HTTP Basic auth and that the auth credentials match those of one of the ``auth.User`` models. .. code-block:: python from flask_peewee.rest import RestAPI, UserAuthentication # instantiate the user auth user_auth = UserAuthentication(auth) # create a RestAPI container api = RestAPI(app, default_auth=user_auth) Now we can post new notes using a command-line tool like curl: .. code-block:: console $ curl -u admin:admin -d data='{"message": "hello api"}' http://127.0.0.1:5000/api/note/ { "id": 3, "message": "hello api", "created": "2026-07-07T13:43:02.200138" } You can see that it returns a serialized copy of the new ``Note`` object. .. note:: This is just a small example of what you can do with the Rest API -- refer to the :ref:`Rest API docs ` for more detailed information, including * limiting access on a per-model basis * customizing which fields are returned by the API * filtering and querying using GET parameters flask-peewee-4.0.1/docs/index.rst000066400000000000000000000013001522375301500166520ustar00rootroot00000000000000.. flask-peewee documentation master file, created by sphinx-quickstart on Tue Sep 20 13:19:30 2026. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. flask-peewee ============ provides a layer of integration between the `flask `_ web framework and the `peewee orm `_. Contents: .. toctree:: :maxdepth: 2 :glob: installation getting-started database admin auth rest-api utils API in depth: .. toctree:: :maxdepth: 2 :glob: api/ Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` flask-peewee-4.0.1/docs/installation.rst000066400000000000000000000013111522375301500202460ustar00rootroot00000000000000.. _installation: Installing ========== flask-peewee can be installed using ``pip`` or any other packaging tool: .. code-block:: shell pip install flask-peewee If you do not have the dependencies installed already, pip will install them for you, but for reference they are: * `flask `_ * `peewee `_ * `wtforms `_ * `wtf-peewee `_ * python 3.8+ Using git --------- .. code-block:: shell git clone https://github.com/coleifer/flask-peewee.git cd flask-peewee pip install . You can run the tests using the test-runner:: python runtests.py flask-peewee-4.0.1/docs/rest-api.rst000066400000000000000000000543261522375301500173070ustar00rootroot00000000000000.. _rest-api: REST API ======== flask-peewee comes with some tools for exposing your project's models via a REST API. There are several components to the ``rest`` module, but the basic setup is to create an instance of :py:class:`RestAPI` and then register your project's models with subclasses of :py:class:`RestResource`. Each :py:class:`RestResource` you expose via the API will support, by default, the following: * ``/api//`` -- GET and POST requests * ``/api///`` -- GET, PUT and DELETE requests Also, you can filter results by columns on the model using django-style syntax, for example: * ``/api/blog/?name=Some%20Blog`` * ``/api/blog/?author__username=some_blogger`` Full operations: * ``__eq``: equals * ``__lt``: less-than * ``__lte``: less-than or equal to * ``__gt``: greater-than * ``__gte``: greater-than or equal to * ``__ne``: not equal to * ``__in``: in set * ``__is``: is, ``?field__is=None`` or ``?-field__is=None`` for NOT NULL * ``__is_not``: is not , ``?field__is_not=None`` * ``__like``: wild-card matching, case-sensitive * ``__ilike``: wild-card matching, case-insensitive * ``__regexp``: regular-expression matching (database-specific) To negate an operation, prefix it with the ``-`` character, e.g. the following are equivalent: * ``/api/user/?admin=true`` * ``/api/user/?admin__eq=true`` * ``/api/user/?-admin=false`` * ``/api/user/?admin__ne=false`` Special Python constants are supported when used as querystring parameters: * ``?value=none`` translates the value to ``None`` * ``?value=true`` translates the value to ``True`` * ``?value=false`` translates the value to ``False`` Getting started with the API ---------------------------- In this documentation we'll start with a very simple API and build it out. The complete version of this API is included in the `example app `_, so feel free to refer there. The project will be a simple 'twitter-like' app where users can post short messages and "follow" other users. .. note:: If you're using apache with mod_wsgi and would like to use any of the auth backends that use basic auth, you will need to add the following directive: ``WSGIPassAuthorization On`` Project models ^^^^^^^^^^^^^^ There are three main models - ``User``, ``Relationship`` and ``Message`` - which we will expose via the API. Here is a truncated version of what they look like: .. code-block:: python from flask_peewee.auth import BaseUser class User(db.Model, BaseUser): username = CharField() password = CharField() email = CharField() join_date = DateTimeField(default=datetime.datetime.now) active = BooleanField(default=True) admin = BooleanField(default=False) class Relationship(db.Model): from_user = ForeignKeyField(User, backref='relationships') to_user = ForeignKeyField(User, backref='related_to') class Message(db.Model): user = ForeignKeyField(User) content = TextField() pub_date = DateTimeField(default=datetime.datetime.now) Creating a RestAPI ------------------ The :py:class:`RestAPI` acts as a container for the various :py:class:`RestResource` objects we will expose. By default it binds all resources to ``/api//``. Here we'll create a simple api and register our models: .. code-block:: python from flask_peewee.rest import RestAPI from app import app # our project's Flask app # instantiate our api wrapper api = RestAPI(app) # register our models so they are exposed via /api// api.register(User) api.register(Relationship) api.register(Message) # configure the urls api.setup() Now if we hit our project at ``/api/message/`` we should get something like the following: .. code-block:: javascript { "meta": { "model": "message", "next": "", "page_count": 1, "page": 1, "previous": "" }, "objects": [ { "content": "flask and peewee, together at last!", "pub_date": "2026-09-16T18:36:15", "user": 1, "id": 1 }, { "content": "Hey, I'm just some user", "pub_date": "2026-09-16T18:46:59", "user": 2, "id": 2 } ] } Say we're interested in the first message, we can hit ``/api/message/1/`` to view just the details on that object: .. code-block:: javascript { "content": "flask and peewee, together at last!", "pub_date": "2026-09-16T18:36:15", "user": 1, "id": 1 } Customizing what is returned ---------------------------- If you access the ``User`` API endpoint, we quickly notice a problem: .. code-block:: console $ curl http://127.0.0.1:5000/api/user/ { "meta": { "model": "user", "next": "", "page": 1, "page_count": 1, "previous": "" }, "objects": [ { "username": "admin", "admin": true, "email": "", "join_date": "2026-09-16T18:34:49", "active": true, "password": "d033e22ae348aeb5660fc2140aec35850c4da997", "id": 1 }, { "username": "coleifer", "admin": false, "email": "coleifer@gmail.com", "join_date": "2026-09-16T18:35:56", "active": true, "password": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", "id": 2 } ] } Passwords and email addresses are being exposed. In order to exclude these fields from serialization, subclass :py:class:`RestResource`: .. code-block:: python from flask_peewee.rest import RestAPI, RestResource from app import app # our project's Flask app # instantiate our api wrapper api = RestAPI(app) # create a special resource for users that excludes email and password class UserResource(RestResource): exclude = ('password', 'email',) # register our models so they are exposed via /api// api.register(User, UserResource) # specify the UserResource api.register(Relationship) api.register(Message) Now emails and passwords are no longer returned by the API. ``exclude`` is a blacklist; its positive counterpart is ``fields``, a whitelist of the *only* fields to serialize. The resource above could instead expose just the username and id: .. code-block:: python class UserResource(RestResource): fields = ('username', 'id') Reach for whichever is more convenient -- ``fields`` when you want to expose a small, fixed set of columns, ``exclude`` when you want everything but a few. Nested resources ---------------- By default a foreign key is serialized as the related row's primary key -- notice the ``"user": 1`` in the message output above. To embed the *full* related object instead, point ``include_resources`` at the resource that should render it: .. code-block:: python class UserResource(RestResource): exclude = ('password', 'email',) class MessageResource(RestResource): include_resources = {'user': UserResource} api.register(User, UserResource) api.register(Message, MessageResource) Now each message embeds its author, serialized through ``UserResource`` (so the password and email are still excluded): .. code-block:: javascript { "content": "flask and peewee, together at last!", "pub_date": "2026-09-16T18:36:15", "user": { "username": "admin", "admin": true, "active": true, "join_date": "2026-09-16T18:34:49", "id": 1 }, "id": 1 } ``include_resources`` can be nested arbitrarily deep -- an included resource may itself include resources -- and one model can be embedded through more than one foreign key. For example, a ``Relationship`` resource can expand both endpoints: .. code-block:: python class RelationshipResource(RestResource): include_resources = { 'from_user': UserResource, 'to_user': UserResource, } The whole nested tree is loaded in a single query -- one ``JOIN`` per included foreign key -- so embedding related objects does *not* incur the N+1 queries you would get from following each row's relations lazily. Nested writes ^^^^^^^^^^^^^ Included resources also work on the way *in*: a ``POST`` or ``PUT`` whose body carries a nested object (instead of a bare id) creates or updates the related row as part of the same request. Two rules keep that safe: * A resource's ``readonly_fields`` are stripped at **every** level of the payload, so a nested object cannot smuggle in a field the resource protects (e.g. slipping ``"admin": true`` into a nested user). * Each nested write must pass the child resource's own ``check_post`` / ``check_put``, exactly as a direct write to that resource would -- so nesting can never be used to sidestep a resource's authorization. The entire object graph is saved in a single transaction, so if any nested write is rejected the whole request rolls back. To disable nested writes for a resource -- silently ignoring any nested object in the payload -- set ``nested_writes = False``; the foreign key can still be assigned with a bare id. Allowing users to post objects ------------------------------ What if we want to create new messages via the Api? Or modify/delete existing messages? .. code-block:: console $ curl -i -d '' http://127.0.0.1:5000/api/message/ HTTP/1.1 401 UNAUTHORIZED WWW-Authenticate: Basic realm="Login Required" Content-Type: text/html; charset=utf-8 Authentication failed The authentication failed because the default authentication mechanism only allows read-only access. In order to allow users to create messages via the API, we need to use a subclass of :py:class:`Authentication` that allows ``POST`` requests. We also want to ensure that the requesting user is a member of the site. For this we will use the :py:class:`UserAuthentication` class as the default auth mechanism. .. code-block:: python from auth import auth # import the Auth object used by our project from flask_peewee.rest import RestAPI, RestResource, UserAuthentication # create an instance of UserAuthentication user_auth = UserAuthentication(auth) # instantiate our api wrapper, specifying user_auth as the default api = RestAPI(app, default_auth=user_auth) # create a special resource for users that excludes email and password class UserResource(RestResource): exclude = ('password', 'email',) # register our models so they are exposed via /api// api.register(User, UserResource) # specify the UserResource api.register(Relationship) api.register(Message) # configure the urls api.setup() Now we should be able to POST new messages. .. code-block:: python import requests # authenticate with HTTP basic auth resp = requests.post( 'http://localhost:5000/api/message/', json={'user': 1, 'content': 'hello api'}, auth=('admin', 'admin'), ) response = resp.json() The response object will look something like this: .. code-block:: javascript { 'content': 'hello api', 'user': 1, 'pub_date': '2026-09-22T11:25:02', 'id': 3 } There is a problem with this, however. Notice how the ``user`` was passed in with the POST data? This effectively will let a user post a message as another user. It also means a user can use PUT requests to modify another user's message: .. code-block:: python # continued from above -- edit another user's message (id=2) resp = requests.put( 'http://127.0.0.1:5000/api/message/2/', json={'content': 'haxed you, bro'}, auth=('admin', 'admin'), ) response = resp.json() The response will look like this: .. code-block:: javascript { 'content': 'haxed you, bro', 'pub_date': '2026-09-16T18:36:15', 'user': 2, 'id': 2 } This is a problem -- we need a way of ensuring that users can only edit their own messages. Furthermore, when they create messages we need to make sure the message is assigned to them. Restricting API access on a per-model basis ------------------------------------------- flask-peewee comes with a special subclass of :py:class:`RestResource` that restricts POST/PUT/DELETE requests to prevent users from modifying another user's content. .. code-block:: python from flask_peewee.rest import RestrictOwnerResource class MessageResource(RestrictOwnerResource): owner_field = 'user' api.register(Message, MessageResource) Now, if we try and modify the message, we get a 403 Forbidden: .. code-block:: python resp = requests.put( 'http://127.0.0.1:5000/api/message/2/', json={'content': 'haxed you, bro'}, auth=('admin', 'admin'), ) print(resp.status_code) # 403 It is fine to modify our own message, though (message with id=1): .. code-block:: python resp = requests.put( 'http://127.0.0.1:5000/api/message/1/', json={'content': 'haxed you, bro'}, auth=('admin', 'admin'), ) print(resp.status_code) # 200 Under-the-hood, the `implementation `_ of the :py:class:`RestrictOwnerResource` is pretty simple. * PUT / DELETE -- verify the authenticated user is the owner of the object * POST -- assign the authenticated user as the owner of the new object Locking down a resource ----------------------- Suppose we want to restrict normal users from modifying ``User`` resources. For this we can use a special subclass of :py:class:`UserAuthentication` that restricts access to administrators: .. code-block:: python from flask_peewee.rest import AdminAuthentication # instantiate our user-based auth user_auth = UserAuthentication(auth) # instantiate admin-only auth admin_auth = AdminAuthentication(auth) # instantiate our api wrapper, specifying user_auth as the default api = RestAPI(app, default_auth=user_auth) # register the UserResource with admin auth api.register(User, UserResource, auth=admin_auth) Token-based authentication -------------------------- :py:class:`UserAuthentication` and :py:class:`AdminAuthentication` use HTTP Basic auth, which is handy for humans but awkward for programmatic clients. For API clients, flask-peewee ships token-based authentication classes. Like all authentication classes they only guard the ``protected_methods`` (``POST``, ``PUT`` and ``DELETE`` by default -- ``GET`` is open). To require auth on reads too, pass ``protected_methods=ALL_METHODS`` (a convenience constant equal to ``('GET', 'POST', 'PUT', 'DELETE')``) or your own list. API keys ^^^^^^^^ :py:class:`APIKeyAuthentication` authenticates against a model with ``key`` and ``secret`` fields, supplied as query-string, header, or form parameters. The matched row is stored on ``g.api_key``: .. code-block:: python from flask_peewee.rest import APIKeyAuthentication class APIKey(db.Model): key = CharField() secret = CharField() api_key_auth = APIKeyAuthentication(APIKey) api.register(SecretModel, auth=api_key_auth) # curl "http://127.0.0.1:5000/api/secretmodel/?key=abc&secret=xyz" .. warning:: Because the key and secret can travel in the query string, they may end up in access logs. Prefer bearer tokens (below) for anything sensitive. Bearer tokens ^^^^^^^^^^^^^ :py:class:`BearerAuthentication` reads a token from the standard ``Authorization: Bearer `` header -- so the credential stays out of the query string and logs -- and looks it up in a model with a ``token`` field. The matched row is stored on ``g.api_key``: .. code-block:: python from flask_peewee.rest import BearerAuthentication class ApiToken(db.Model): token = CharField() bearer_auth = BearerAuthentication(ApiToken) api.register(SecretModel, auth=bearer_auth) # curl -H "Authorization: Bearer " http://127.0.0.1:5000/api/secretmodel/ Override ``token_field`` to use a differently-named column, and store high-entropy tokens (override ``get_key`` to keep them hashed at rest). Bearer tokens as users ^^^^^^^^^^^^^^^^^^^^^^^ :py:class:`UserBearerAuthentication` resolves the token to a *user* and sets ``g.user`` (rather than ``g.api_key``), so bearer tokens work with :py:class:`RestrictOwnerResource` and anything else keyed off the authenticated user. The token model carries a foreign key to the user: .. code-block:: python from flask_peewee.rest import UserBearerAuthentication class ApiToken(db.Model): token = CharField() user = ForeignKeyField(User) user_bearer_auth = UserBearerAuthentication(ApiToken) class MessageResource(RestrictOwnerResource): owner_field = 'user' api.register(Message, MessageResource, auth=user_bearer_auth) A request carrying a valid token is now treated as that token's user: new objects are assigned to them, and they may only modify their own. Set ``user_field = None`` if the token lives directly on the user model instead of a separate token table. Filtering records and querying ------------------------------ A REST Api is not very useful if it cannot be queried in a meaningful fashion. To this end, the flask-peewee :py:class:`RestResource` objects support "django-style" filtering: .. code-block:: console $ curl http://127.0.0.1:5000/api/message/?user=2 This call will return only messages by the ``User`` with id=2: .. code-block:: javascript { "meta": { "model": "message", "next": "", "page": 1, "page_count": 1, "previous": "" }, "objects": [ { "content": "haxed you, bro", "pub_date": "2026-09-16T18:36:15", "user": 2, "id": 2 } ] } Joins can be traversed using the django double-underscore notation: .. code-block:: console $ curl http://127.0.0.1:5000/api/message/?user__username=admin .. code-block:: javascript { "meta": { "model": "message", "next": "", "page": 1, "page_count": 1, "previous": "" }, "objects": [ { "content": "flask and peewee, together at last!", "pub_date": "2026-09-16T18:36:15", "user": 1, "id": 1 }, { "content": "hello api", "pub_date": "2026-09-22T11:25:02", "user": 1, "id": 3 } ] } It is also supported to use different comparison operators with the same double-underscore notation: .. code-block:: console $ curl http://127.0.0.1:5000/api/user/?id__lt=2 .. code-block:: javascript { "meta": { "model": "user", "next": "", "page": 1, "page_count": 1, "previous": "" }, "objects": [{ "username": "admin", "admin": true, "email": "admin@admin", "active": true, "password": "214de$25", "id": 1 }] } Valid Comparison Operators are: 'eq', 'lt', 'lte', 'gt', 'gte', 'ne', 'in', 'is', 'is_not', 'like', 'ilike', 'regexp' The ``in`` operator accepts a comma-separated list and/or repeated parameters, so ``?id__in=1,2`` and ``?id__in=1&id__in=2`` are equivalent. .. note:: Unrecognized filter parameters -- a misspelled field, or a field not exposed for filtering -- are **ignored** rather than rejected, so a typo such as ``?usernam=x`` silently returns every row. This is intentional: it keeps stray query-string parameters (cache-busters, tracking params, etc.) from breaking a request. Double-check your filter names if a query returns more than you expect. An unknown ``ordering`` column is likewise ignored. Restricting what can be filtered ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ By default every field on the model is filterable and joins may be traversed into related models. Since filters come straight off the query string, you will often want to lock this down -- especially for sensitive columns. Three :py:class:`RestResource` attributes control it: * ``filter_fields`` -- a whitelist; only these fields may be filtered on. * ``filter_exclude`` -- a blacklist of fields that may never be filtered on (use ``__`` notation for related columns, e.g. ``user__password``). * ``filter_recursive`` -- set to ``False`` to forbid filtering across foreign keys entirely (no ``user__...`` lookups at all). .. code-block:: python class MessageResource(RestResource): # the only fields a client may filter on (with any operator) filter_fields = ('id', 'content', 'user__username') class UserResource(RestResource): exclude = ('password',) # don't serialize the hash... filter_exclude = ('password',) # ...and don't let it be filtered on either Because an unrecognized filter is ignored rather than rejected (see the note above), tightening this list can never break an otherwise-valid request -- a now-disallowed filter simply stops narrowing the results. Sorting results --------------- Results can be sorted by specifying an ``ordering`` as a GET argument. The ordering must be a column on the model. `/api/message/?ordering=pub_date` If you would like to order objects "descending", place a "-" (hyphen character) before the column name: `/api/message/?ordering=-pub_date` Limiting results and pagination ------------------------------- By default, resources are paginated 20 per-page (the ``paginate_by`` attribute). Specify a ``limit`` in the querystring to request a different page size -- larger or smaller: `/api/message/?limit=2` ``paginate_by`` is only the default page size, not a maximum -- a client may request a larger page. To cap how large a page can be requested, set ``max_paginate_by`` on the resource (it defaults to ``None``, meaning no ceiling). Setting ``paginate_by = None`` disables pagination and returns every matching object on a single page (still wrapped in the standard ``meta``/``objects`` envelope). In the "meta" section of the response, URIs for the "next" and "previous" sets of results are available, along with the total number of pages: .. code-block:: javascript "meta": { "model": "message", "next": "/api/message/?limit=1&page=3", "page": 2, "page_count": 5, "previous": "/api/message/?limit=1&page=1" } flask-peewee-4.0.1/docs/utils.rst000066400000000000000000000067541522375301500167250ustar00rootroot00000000000000.. _utils: Utilities ========= flask-peewee ships with several useful utilities. If you're coming from the django world, some of these functions may look familiar to you. Getting objects --------------- :py:func:`get_object_or_404` Provides a handy way of getting an object or 404ing if not found, useful for urls that match based on ID. .. code-block:: python @app.route('/blog//') def blog_detail(title): blog = get_object_or_404(Blog.select().where(Blog.active==True), Blog.title==title) return render_template('blog/detail.html', blog=blog) :py:func:`object_list` Wraps the given query and handles pagination automatically. Pagination defaults to ``20`` but can be changed by passing in ``paginate_by=XX``. .. code-block:: python @app.route('/blog/') def blog_list(): active = Blog.select().where(Blog.active==True) return object_list('blog/index.html', active) .. code-block:: html+jinja <!-- template --> {% for blog in object_list %} {# render the blog here #} {% endfor %} {% if page > 1 %} <a href="./?page={{ page - 1 }}">Prev</a> {% endif %} {% if page < pagination.get_pages() %} <a href="./?page={{ page + 1 }}">Next</a> {% endif %} :py:class:`PaginatedQuery` A wrapper around a query (or model class) that handles pagination. Example: .. code-block:: python query = Blog.select().where(Blog.active==True) pq = PaginatedQuery(query, 20) # 20 items per page # assume url was /?page=3 obj_list = pq.get_list() # returns 3rd page of results pq.get_page() # returns "3" pq.get_pages() # returns total objects / objects-per-page pq.get_count() # total number of matching rows # a windowed list of page numbers for pagination controls; None marks a # gap to render as an ellipsis. On page 10 of 20 it returns: pq.get_page_range() # [1, None, 7, 8, 9, 10, 11, 12, 13, None, 20] ``get_page_range(window=N)`` controls how many pages are shown on either side of the current page (the default is 3). Misc ---- .. py:function:: slugify(string) :no-index: Convert a string into something suitable for use as part of a URL, e.g. "This is a url" becomes "this-is-a-url" .. code-block:: python from flask_peewee.utils import slugify class Blog(db.Model): title = CharField() slug = CharField() def save(self, *args, **kwargs): self.slug = slugify(self.title) super(Blog, self).save(*args, **kwargs) .. py:function:: make_password(raw_password) Create a salted hash for the given plain-text password .. py:function:: check_password(raw_password, enc_password) Compare a plain-text password against a salted/hashed password .. py:data:: PASSWORD_HASH_METHOD The hashing method :py:func:`make_password` hands to werkzeug's ``generate_password_hash`` -- ``'scrypt'`` by default. Override it before hashing to change the algorithm or work factor, for instance to pick a cheaper method that speeds up your test suite: .. code-block:: python import flask_peewee.utils flask_peewee.utils.PASSWORD_HASH_METHOD = 'pbkdf2:sha256:1' See ``werkzeug.security.generate_password_hash`` for the accepted values. ��������������������flask-peewee-4.0.1/example/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�15223753015�0015522�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/__init__.py��������������������������������������������������������������0000664�0000000�0000000�00000000000�15223753015�0017621�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/admin.py�����������������������������������������������������������������0000664�0000000�0000000�00000004123�15223753015�0017164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import datetime from flask import request, redirect from flask_peewee.admin import Admin, ModelAdmin, AdminPanel from flask_peewee.filters import QueryFilter from app import app, db from auth import auth from models import User, Message, Note, Relationship class NotePanel(AdminPanel): template_name = 'admin/notes.html' def get_urls(self): return ( ('/create/', self.create), ) def create(self): if request.method == 'POST': if request.form.get('message'): Note.create( user=auth.get_logged_in_user(), message=request.form['message']) next = request.form.get('next') or self.dashboard_url() return redirect(next) def get_context(self): # Get the 3 latest notes. notes = Note.select().order_by(Note.created_date.desc()).paginate(1, 3) return {'note_list': notes} class UserStatsPanel(AdminPanel): template_name = 'admin/user_stats.html' def get_context(self): last_week = datetime.datetime.now() - datetime.timedelta(days=7) signups_this_week = User.select().where(User.join_date > last_week).count() messages_this_week = Message.select().where(Message.pub_date > last_week).count() return { 'signups': signups_this_week, 'messages': messages_this_week, } admin = Admin(app, auth, branding='Example Site')#, theme='crux') class MessageAdmin(ModelAdmin): columns = ('user', 'content', 'pub_date',) foreign_key_lookups = {'user': 'username'} filter_fields = ('user', 'content', 'pub_date', 'user__username') search_fields = ('content', 'user__username') class NoteAdmin(ModelAdmin): columns = ('user', 'message', 'created_date',) exclude = ('created_date',) class UserAdmin(ModelAdmin): search_fields = ('username', 'email') auth.register_admin(admin, UserAdmin) admin.register(Relationship) admin.register(Message, MessageAdmin) admin.register(Note, NoteAdmin) admin.register_panel('Notes', NotePanel) admin.register_panel('User stats', UserStatsPanel) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/api.py�������������������������������������������������������������������0000664�0000000�0000000�00000002420�15223753015�0016643�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from flask_peewee.rest import RestAPI, RestResource, UserAuthentication, AdminAuthentication, RestrictOwnerResource from app import app from auth import auth from models import User, Message, Note, Relationship user_auth = UserAuthentication(auth) admin_auth = AdminAuthentication(auth) # instantiate our api wrapper api = RestAPI(app, default_auth=user_auth) class UserResource(RestResource): exclude = ('password', 'email',) readonly_fields = ('admin', 'active',) class MessageResource(RestrictOwnerResource): owner_field = 'user' include_resources = {'user': UserResource} class RelationshipResource(RestrictOwnerResource): owner_field = 'from_user' include_resources = { 'from_user': UserResource, 'to_user': UserResource, } paginate_by = None class NoteResource(RestrictOwnerResource): owner_field = 'user' include_resources = { 'user': UserResource, } def get_query(self): query = super(NoteResource, self).get_query() return query.where(Note.status == 1) # register our models so they are exposed via /api/<model>/ api.register(User, UserResource, auth=admin_auth) api.register(Relationship, RelationshipResource) api.register(Message, MessageResource) api.register(Note, NoteResource) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/app.py�������������������������������������������������������������������0000664�0000000�0000000�00000000653�15223753015�0016660�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from flask import Flask # flask-peewee bindings from flask_peewee.db import Database app = Flask(__name__) app.config.from_object('config.Configuration') db = Database(app) def create_tables(): User.create_table() Relationship.create_table() Message.create_table() Note.create_table() @app.template_filter('is_following') def is_following(from_user, to_user): return from_user.is_following(to_user) �������������������������������������������������������������������������������������flask-peewee-4.0.1/example/auth.py������������������������������������������������������������������0000664�0000000�0000000�00000000174�15223753015�0017037�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from flask_peewee.auth import Auth from app import app, db from models import User auth = Auth(app, db, user_model=User) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/config.py����������������������������������������������������������������0000664�0000000�0000000�00000000325�15223753015�0017341�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# config class Configuration(object): DATABASE = { 'name': 'example.db', 'engine': 'peewee.SqliteDatabase', 'check_same_thread': False, } DEBUG = True SECRET_KEY = 'shhhh' �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/example.db���������������������������������������������������������������0000664�0000000�0000000�00000042000�15223753015�0017460�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������SQLite format 3���@ ���C�������������� �������������������������������������������������C�.������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ���R�|vpjd^XR����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������      ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ���A�A���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������?KA�I'm an admin on this crazy site2011-09-16 18:47:17.0458847;A�Hey, I'm just some user2011-09-16 18:46:59.670759CSA�flask and peewee, together at last!2011-09-16 18:36:15.668596 ������.�����������������������������������������������������������������������������������������������������������������������������������������������������������������uMtableuseruserCREATE TABLE user (username VARCHAR(255) NOT NULL, admin SMALLINT NOT NULL, id INTEGER NOT NULL PRIMARY KEY, join_date DATETIME NOT NULL, active SMALLINT NOT NULL, password VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL)>[indexuser_iduserCREATE UNIQUE INDEX user_id ON user(id)F%%OtablerelationshiprelationshipCREATE TABLE relationship (from_user_id INTEGER NOT NULL REFERENCES user (id), to_user_id INTEGER NOT NULL REFERENCES user (id), id INTEGER NOT NULL PRIMARY KEY)v?%indexrelationship_from_user_idrelationshipCREATE INDEX relationship_from_user_id ON relationship(from_user_id)p;% indexrelationship_to_user_idrelationshipCREATE INDEX relationship_to_user_id ON relationship(to_user_id)^+%{indexrelationship_idrelationshipCREATE UNIQUE INDEX relationship_id ON relationship(id) ���_�_ix�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������3=tablemessagemessageCREATE TABLE message (content TEXT NOT NULL, pub_date DATETIME NOT NULL, user_id INTEGER NOT NULL REFERENCES user (id), id INTEGER NOT NULL PRIMARY KEY)R+mindexmessage_user_idmessage CREATE INDEX message_user_id ON message(user_id)J !gindexmessage_idmessage CREATE UNIQUE INDEX message_id ON message(id)@ ctablenotenote CREATE TABLE note (message TEXT NOT NULL, user_id INTEGER NOT NULL REFERENCES user (id), id INTEGER NOT NULL PRIMARY KEY, created_date DATETIME NOT NULL, "status" INTEGER)F %aindexnote_user_idnoteCREATE INDEX note_user_id ON note(user_id)> [indexnote_idnoteCREATE UNIQUE INDEX note_id ON note(id) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ��q���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Z}�Ahey everyone, keep an eye on "coleifer", may be spam bot2011-09-16 18:35:36.06774433�AHere's another note2011-10-29 17:48:11.911884���Z�������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ��� �C�k?c7 ������������������������������������������������������������������������������R �3Q)user�2011-09-16 18:46:49scrypt:32768:8:1$tscqAulbOnt9oc5x$4f195f847e23c2dbe59c70e446ff9d64e59409a515f3641]�3i)user�2011-09-16 18:46:495f845$e9c9154027aecd8c37ef02e966b653188177d07duser@user.userE �3Q admin2011-09-16 18:34:49scrypt:32768:8:1$1LQc8Ibq0Yncc8kN$c9c82d5b1c115a7ee27c899c424b6eb5dadbd2ffc92e3131435a7a81a596f38c081ad966a3bdade77216ab2b56f602d552c38451c282b9788f419f5b8fe9e6b6* �A IIIIII�2012-03-13 02:49:31.977035* �A HHHHHH�2012-03-13 02:49:31.972886* �A GGGGGG�2012-03-13 02:49:31.970255* �A FFFFFF�2012-03-13 02:49:31.967091*�A EEEEEE�2012-03-13 02:49:31.963988*�A DDDDDD�2012-03-13 02:49:31.961231*�A CCCCCC�2012-03-13 02:49:31.958624*�A BBBBBB�2012-03-13 02:49:31.955460*�A AAAAAA�2012-03-13 02:49:31.950733�e�3i1coleifer�2011-09-16 18:35:56e1ef7$dd4949985c4b168136b45a84d5d9770da8951243coleifer@gmail.com� ����l@|P$tH������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������*�A OOOOOO�2012-03-13 02:49:31.992156*�A NNNNNN�2012-03-13 02:49:31.990125*�A MMMMMM�2012-03-13 02:49:31.987221*�A LLLLLL�2012-03-13 02:49:31.984260*�A KKKKKK�2012-03-13 02:49:31.981245* �A JJJJJJ�2012-03-13 02:49:31.979428*�A ZZZZZZ�2012-03-13 02:49:32.030799*�A YYYYYY�2012-03-13 02:49:32.027586*�A XXXXXX�2012-03-13 02:49:32.024213*�A WWWWWW�2012-03-13 02:49:32.021126*�A VVVVVV�2012-03-13 02:49:32.015616*�A UUUUUU�2012-03-13 02:49:32.013264*�A TTTTTT�2012-03-13 02:49:32.010231*�A SSSSSS�2012-03-13 02:49:32.007132*�A RRRRRR�2012-03-13 02:49:32.004115*�A QQQQQQ�2012-03-13 02:49:32.001454*�A PPPPPP�2012-03-13 02:49:31.998571flask-peewee-4.0.1/example/main.py������������������������������������������������������������������0000664�0000000�0000000�00000000307�15223753015�0017020�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from app import app, db from auth import * from admin import admin from api import api from models import * from views import * admin.setup() api.setup() if __name__ == '__main__': app.run() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/models.py����������������������������������������������������������������0000664�0000000�0000000�00000003513�15223753015�0017361�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from hashlib import md5 import datetime from flask_peewee.auth import BaseUser from peewee import * from app import db class User(db.Model, BaseUser): username = CharField() password = CharField() email = CharField() join_date = DateTimeField(default=datetime.datetime.now) active = BooleanField(default=True) admin = BooleanField(default=False) def __str__(self): return self.username def following(self): return User.select().join( Relationship, on=Relationship.to_user ).where(Relationship.from_user==self).order_by(User.username) def followers(self): return User.select().join( Relationship, on=Relationship.from_user ).where(Relationship.to_user==self).order_by(User.username) def is_following(self, user): return Relationship.select().where( Relationship.from_user==self, Relationship.to_user==user ).exists() def gravatar_url(self, size=80): return 'http://www.gravatar.com/avatar/%s?d=identicon&s=%d' % \ (md5(self.email.strip().lower().encode('utf-8')).hexdigest(), size) class Relationship(db.Model): from_user = ForeignKeyField(User, related_name='relationships') to_user = ForeignKeyField(User, related_name='related_to') def __str__(self): return 'Relationship from %s to %s' % (self.from_user, self.to_user) class Message(db.Model): user = ForeignKeyField(User) content = TextField() pub_date = DateTimeField(default=datetime.datetime.now) def __str__(self): return '%s: %s' % (self.user, self.content) class Note(db.Model): user = ForeignKeyField(User) message = TextField() status = IntegerField(choices=((1, 'live'), (2, 'deleted')), null=True) created_date = DateTimeField(default=datetime.datetime.now) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/requirements.txt���������������������������������������������������������0000664�0000000�0000000�00000000060�15223753015�0021002�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask werkzeug jinja2 peewee wtforms wtf-peewee ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/run_example.py�����������������������������������������������������������0000775�0000000�0000000�00000000127�15223753015�0020416�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env python import sys sys.path.insert(0, '..') import main main.app.run() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/static/������������������������������������������������������������������0000775�0000000�0000000�00000000000�15223753015�0017011�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/static/style.css���������������������������������������������������������0000664�0000000�0000000�00000001521�15223753015�0020662�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������body { font-family: sans-serif; background: #eee; } a, h1, h2 { color: #377BA8; } h1, h2 { font-family: 'Georgia', serif; margin: 0; } h1 { border-bottom: 2px solid #eee; } h2 { font-size: 1.2em; } .page { margin: 2em auto; width: 35em; border: 5px solid #ccc; padding: 0.8em; background: white; } .page ul { list-style-type: none; } .page li { clear: both; } .metanav { text-align: right; font-size: 0.8em; padding: 0.3em; margin-bottom: 1em; background: #fafafa; } .flash { background: #CEE5F5; padding: 0.5em; border: 1px solid #AACBE2; } .avatar { display: block; float: left; margin: 0 10px 0 0; } .message-content { min-height: 80px; } .message-edit { float: right; font-size: 0.6em; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/templates/���������������������������������������������������������������0000775�0000000�0000000�00000000000�15223753015�0017520�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/templates/admin/���������������������������������������������������������0000775�0000000�0000000�00000000000�15223753015�0020610�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/templates/admin/notes.html�����������������������������������������������0000664�0000000�0000000�00000000723�15223753015�0022630�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������{% extends "admin/panels/default.html" %} {% block panel_content %} {% for note in note_list %} <p>{{ note.user.username }}: {{ note.message }}</p> {% endfor %} <form method="post" action="{{ url_for(panel.get_url_name('create')) }}"> <input type="hidden" value="{{ request.url }}" /> <p><textarea name="message" class="form-control"></textarea></p> <button type="submit" class="btn btn-secondary btn-sm">Save</button> </form> {% endblock %} ���������������������������������������������flask-peewee-4.0.1/example/templates/admin/user_stats.html������������������������������������������0000664�0000000�0000000�00000000254�15223753015�0023673�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������{% extends "admin/panels/default.html" %} {% block panel_content %} <p>New users this week: {{ signups }}</p> <p>Messages this week: {{ messages }}</p> {% endblock %} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������flask-peewee-4.0.1/example/templates/base.html������������������������������������������������������0000664�0000000�0000000�00000001370�15223753015�0021321�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype html> <title>Tweepee

Tweepee

{% if not session.logged_in %} log in join {% else %} public timeline create log out {% endif %}
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %}

{% block content_title %}{% endblock %}

{% block content %}{% endblock %}
flask-peewee-4.0.1/example/templates/create.html000066400000000000000000000005021522375301500216460ustar00rootroot00000000000000{% extends "base.html" %} {% block content_title %}Create{% endblock %} {% block content %}
Message:
{% endblock %} flask-peewee-4.0.1/example/templates/edit.html000066400000000000000000000005601522375301500213340ustar00rootroot00000000000000{% extends "base.html" %} {% block content_title %}Edit message{% endblock %} {% block content %}
Message:
{% endblock %} flask-peewee-4.0.1/example/templates/homepage.html000066400000000000000000000002111522375301500221650ustar00rootroot00000000000000{% extends "base.html" %} {% block content_title %}Home{% endblock %} {% block content %}

Welcome to the site!

{% endblock %} flask-peewee-4.0.1/example/templates/includes/000077500000000000000000000000001522375301500213265ustar00rootroot00000000000000flask-peewee-4.0.1/example/templates/includes/message.html000066400000000000000000000005141522375301500236400ustar00rootroot00000000000000{% if user and message.user == user %}edit{% endif %}

{{ message.content|urlize }}

flask-peewee-4.0.1/example/templates/includes/pagination.html000066400000000000000000000003131522375301500243420ustar00rootroot00000000000000{% if page > 1 %} {% endif %} {% if pagination.get_pages() > page %} {% endif %} flask-peewee-4.0.1/example/templates/join.html000066400000000000000000000010061522375301500213420ustar00rootroot00000000000000{% extends "base.html" %} {% block content_title %}Join{% endblock %} {% block content %}
Username:
Password:
Email:

(used for gravatar)

{% endblock %} flask-peewee-4.0.1/example/templates/private_messages.html000066400000000000000000000004351522375301500237510ustar00rootroot00000000000000{% extends "base.html" %} {% block content_title %}Private Timeline{% endblock %} {% block content %}
    {% for message in message_list %}
  • {% include "includes/message.html" %}
  • {% endfor %}
{% include "includes/pagination.html" %} {% endblock %} flask-peewee-4.0.1/example/templates/public_messages.html000066400000000000000000000004341522375301500235540ustar00rootroot00000000000000{% extends "base.html" %} {% block content_title %}Public Timeline{% endblock %} {% block content %}
    {% for message in message_list %}
  • {% include "includes/message.html" %}
  • {% endfor %}
{% include "includes/pagination.html" %} {% endblock %} flask-peewee-4.0.1/example/templates/user_detail.html000066400000000000000000000016021522375301500227050ustar00rootroot00000000000000{% extends "base.html" %} {% block content_title %}Message from {{ person.username }}{% endblock %} {% block content %} {% if user %} {% if person.username != user.username %} {% if user|is_following(person) %}
{% else %}
{% endif %} {% endif %} {% else %}

Log-in to follow

{% endif %}
    {% for message in message_list %}
  • {% include "includes/message.html" %}
  • {% endfor %}
{% include "includes/pagination.html" %} {% endblock %} flask-peewee-4.0.1/example/templates/user_followers.html000066400000000000000000000005161522375301500234620ustar00rootroot00000000000000{% extends "base.html" %} {% block content_title %}Followers{% endblock %} {% block content %} {% include "includes/pagination.html" %} {% endblock %} flask-peewee-4.0.1/example/templates/user_following.html000066400000000000000000000005161522375301500234460ustar00rootroot00000000000000{% extends "base.html" %} {% block content_title %}Following{% endblock %} {% block content %} {% include "includes/pagination.html" %} {% endblock %} flask-peewee-4.0.1/example/templates/user_list.html000066400000000000000000000005031522375301500224150ustar00rootroot00000000000000{% extends "base.html" %} {% block content_title %}Users{% endblock %} {% block content %} {% include "includes/pagination.html" %} {% endblock %} flask-peewee-4.0.1/example/views.py000066400000000000000000000101161522375301500172300ustar00rootroot00000000000000import datetime from flask import request, redirect, url_for, render_template, flash from flask_peewee.utils import get_object_or_404, object_list from app import app from auth import auth from models import User, Message, Relationship @app.route('/') def homepage(): if auth.get_logged_in_user(): return private_timeline() else: return public_timeline() @app.route('/private/') @auth.login_required def private_timeline(): user = auth.get_logged_in_user() messages = Message.select().where( Message.user << user.following() ).order_by(Message.pub_date.desc()) return object_list('private_messages.html', messages, 'message_list') @app.route('/public/') def public_timeline(): messages = Message.select().order_by(Message.pub_date.desc()) return object_list('public_messages.html', messages, 'message_list') @app.route('/join/', methods=['GET', 'POST']) def join(): if request.method == 'POST' and request.form['username']: try: user = User.select().where(User.username==request.form['username']).get() flash('That username is already taken') except User.DoesNotExist: user = User( username=request.form['username'], email=request.form['email'], join_date=datetime.datetime.now() ) user.set_password(request.form['password']) user.save() auth.login_user(user) return redirect(url_for('homepage')) return render_template('join.html') @app.route('/following/') @auth.login_required def following(): user = auth.get_logged_in_user() return object_list('user_following.html', user.following(), 'user_list') @app.route('/followers/') @auth.login_required def followers(): user = auth.get_logged_in_user() return object_list('user_followers.html', user.followers(), 'user_list') @app.route('/users/') def user_list(): users = User.select().order_by(User.username) return object_list('user_list.html', users, 'user_list') @app.route('/users//') def user_detail(username): user = get_object_or_404(User, User.username==username) messages = user.message_set.order_by(Message.pub_date.desc()) return object_list('user_detail.html', messages, 'message_list', person=user) @app.route('/users//follow/', methods=['POST']) @auth.login_required def user_follow(username): user = get_object_or_404(User, User.username==username) Relationship.get_or_create( from_user=auth.get_logged_in_user(), to_user=user, ) flash('You are now following %s' % user.username) return redirect(url_for('user_detail', username=user.username)) @app.route('/users//unfollow/', methods=['POST']) @auth.login_required def user_unfollow(username): user = get_object_or_404(User, User.username==username) Relationship.delete().where( Relationship.from_user==auth.get_logged_in_user(), Relationship.to_user==user, ).execute() flash('You are no longer following %s' % user.username) return redirect(url_for('user_detail', username=user.username)) @app.route('/create/', methods=['GET', 'POST']) @auth.login_required def create(): user = auth.get_logged_in_user() if request.method == 'POST' and request.form['content']: message = Message.create( user=user, content=request.form['content'], ) flash('Your message has been created') return redirect(url_for('user_detail', username=user.username)) return render_template('create.html') @app.route('/edit//', methods=['GET', 'POST']) @auth.login_required def edit(message_id): user = auth.get_logged_in_user() message = get_object_or_404(Message, Message.user==user, Message.id==message_id) if request.method == 'POST' and request.form['content']: message.content = request.form['content'] message.save() flash('Your changes were saved') return redirect(url_for('user_detail', username=user.username)) return render_template('edit.html', message=message) flask-peewee-4.0.1/flask_peewee/000077500000000000000000000000001522375301500165215ustar00rootroot00000000000000flask-peewee-4.0.1/flask_peewee/__init__.py000066400000000000000000000000261522375301500206300ustar00rootroot00000000000000__version__ = '4.0.1' flask-peewee-4.0.1/flask_peewee/admin.py000066400000000000000000000706541522375301500201770ustar00rootroot00000000000000import functools import json import operator import os import re from flask import Blueprint from flask import Response from flask import abort from flask import flash from flask import redirect from flask import render_template from flask import request from flask import session from flask import url_for from flask_peewee.filters import FilterForm from flask_peewee.filters import FilterMapping from flask_peewee.filters import FilterModelConverter from flask_peewee.forms import BaseModelConverter from flask_peewee.forms import AjaxSelectWidget from flask_peewee.forms import LimitedModelSelectField from flask_peewee.serializer import Serializer from flask_peewee.utils import PaginatedQuery from flask_peewee.utils import get_next from flask_peewee.utils import path_to_models from flask_peewee.utils import slugify from peewee import BooleanField from peewee import DateField from peewee import DateTimeField from peewee import ForeignKeyField from peewee import TextField from werkzeug.datastructures import CombinedMultiDict from werkzeug.datastructures import Headers from wtforms import fields from wtforms import widgets from wtfpeewee.fields import ModelHiddenField from wtfpeewee.fields import ModelSelectField from wtfpeewee.fields import ModelSelectMultipleField from wtfpeewee.orm import model_form current_dir = os.path.dirname(__file__) class AdminModelConverter(BaseModelConverter): def __init__(self, model_admin, additional=None): super(AdminModelConverter, self).__init__(additional) self.model_admin = model_admin def handle_foreign_key(self, model, field, **kwargs): if field.null: kwargs['allow_blank'] = True if field.name in (self.model_admin.foreign_key_lookups or ()): form_field = ModelHiddenField(model=field.rel_model, **kwargs) else: form_field = ModelSelectField(model=field.rel_model, **kwargs) return field.name, form_field class AdminFilterModelConverter(FilterModelConverter): def __init__(self, model_admin, additional=None): super(AdminFilterModelConverter, self).__init__(additional) self.model_admin = model_admin def handle_foreign_key(self, model, field, **kwargs): if field.name in (self.model_admin.foreign_key_lookups or ()): data_source = url_for(self.model_admin.get_url_name('ajax_list')) kwargs['widget'] = AjaxSelectWidget(data_source, field.name) form_field = LimitedModelSelectField(model=field.rel_model, **kwargs) return field.name, form_field class Action(object): def __init__(self, name=None, description=None): self.name = name or (type(self).__name__.replace('Action', '')) self.description = description or re.sub(r'[\-_]', ' ', self.name).title() def callback(self, id_list): """ Perform an action on the list of IDs specified. If the return value is a Response object, then that will be returned to the user. Otherwise, the return value is ignored and the user is redirected to the index. """ raise NotImplementedError class ModelAdmin(object): """ ModelAdmin provides create/edit/delete functionality for a peewee Model. """ paginate_by = 20 filter_paginate_by = 15 # columns to display in the list index - can be field names or callables on # a model instance, though in the latter case they will not be sortable columns = None # exclude certian fields from being exposed as filters -- for related fields # use "__" notation, e.g. user__password filter_exclude = None filter_fields = None # char/text field names for the quick-search box. supports "__" traversal # into related models, e.g. 'user__username'. empty -> no search box. search_fields = None # form parameters, lists of fields exclude = None fields = None form_converter = AdminModelConverter # User-defined bulk actions. List or tuple of Action instances. actions = None # foreign_key_field --> related field to search on, e.g. {'user': 'username'} foreign_key_lookups = None # delete behavior delete_collect_objects = True delete_recursive = True # restrict which fields may be exported. export_fields is a whitelist of # field names; export_exclude a blacklist. Related models are restricted # by their own registered ModelAdmin's settings. export_fields = None export_exclude = None filter_mapping = FilterMapping filter_converter = AdminFilterModelConverter # templates, to override see get_template_overrides() base_templates = { 'index': 'admin/models/index.html', 'add': 'admin/models/add.html', 'edit': 'admin/models/edit.html', 'delete': 'admin/models/delete.html', 'export': 'admin/models/export.html', } def __init__(self, admin, model): self.admin = admin self.model = model self.db = model._meta.database self.pk = self.model._meta.primary_key self.templates = dict(self.base_templates) self.templates.update(self.get_template_overrides()) self.action_map = dict((action.name, action) for action in (self.actions or ())) def get_template_overrides(self): return {} def get_url_name(self, name): return '%s.%s_%s' % ( self.admin.blueprint.name, self.get_admin_name(), name, ) def get_filter_form(self): return FilterForm( self.model, self.filter_converter(self), self.filter_mapping(), self.filter_fields, self.filter_exclude, ) def process_filters(self, query): filter_form = self.get_filter_form() form, query, cleaned = filter_form.process_request(query) return form, query, cleaned, filter_form._field_tree def get_form(self, adding=False): allow_pk = adding and not self.model._meta.auto_increment return model_form(self.model, allow_pk=allow_pk, only=self.fields, exclude=self.exclude, converter=self.form_converter(self), ) def get_add_form(self): return self.get_form(adding=True) def get_edit_form(self, instance): return self.get_form() def get_query(self): return self.model.select() def get_object(self, pk): return self.get_query().where(self.pk==pk).get() def get_urls(self): return ( ('/', self.index), ('/add/', self.add), ('/delete/', self.delete), ('/export/', self.export), ('//', self.edit), ('/_ajax/', self.ajax_list), ) def get_columns(self): return self.model._meta.sorted_field_names def column_is_sortable(self, col): return col in self.model._meta.fields def get_display_name(self): return self.model.__name__ def get_admin_name(self): return slugify(self.model.__name__) def save_model(self, instance, form, adding=False): form.populate_obj(instance) instance.save(force_insert=adding) return instance def apply_ordering(self, query, ordering): if ordering: desc, column = ordering.startswith('-'), ordering.lstrip('-') if self.column_is_sortable(column): field = self.model._meta.fields[column] query = query.order_by(field.asc() if not desc else field.desc()) return query def get_extra_context(self): return {} def get_search_fields(self): return self.search_fields or [] def _resolve_search_field(self, name): # resolve a possibly-dotted search field to its Field object plus the # foreign keys that must be joined to reach it. model = self.model joins = [] parts = name.split('__') for attr in parts[:-1]: fk = model._meta.fields[attr] joins.append((fk, fk.rel_model)) model = fk.rel_model return model._meta.fields[parts[-1]], joins def apply_search(self, query, term): term = (term or '').strip() search_fields = self.get_search_fields() if not term or not search_fields: return query clauses = [] for name in search_fields: field, joins = self._resolve_search_field(name) query = query.switch(self.model) for fk, rel_model in joins: query = query.ensure_join(fk.model, rel_model, fk) # ** is peewee's ILIKE operator (case-insensitive contains). clauses.append(field.contains(term)) return query.switch(self.model).where(functools.reduce(operator.or_, clauses)) def get_form_data(self): # combine files with form data so file-upload fields (e.g. blobs) # receive their uploads. if request.files: return CombinedMultiDict((request.files, request.form)) return request.form def index(self): if request.method == 'POST': id_list = request.form.getlist('id') action = request.form['action'] if action == 'delete': return redirect(url_for(self.get_url_name('delete'), id=id_list)) elif action == 'export': return redirect(url_for(self.get_url_name('export'), id=id_list)) elif action in self.action_map: id_list = request.form.getlist('id') if not id_list: flash('Please select one or more rows.', 'warning') else: action_obj = self.action_map[action] maybe_response = action_obj.callback(id_list) if isinstance(maybe_response, Response): return maybe_response else: flash('Unknown action: "%s".' % action, 'danger') return self._index_redirect() session['%s.index' % self.get_admin_name()] = request.url query = self.get_query() ordering = request.args.get('ordering') or '' query = self.apply_ordering(query, ordering) # process the filters from the request filter_form, query, cleaned, field_tree = self.process_filters(query) # apply the quick-search term, if any search_query = request.args.get('q') or '' query = self.apply_search(query, search_query) # create a paginated query out of our filtered results pq = PaginatedQuery(query, self.paginate_by) return render_template(self.templates['index'], admin=self.admin, model_admin=self, query=pq, ordering=ordering, search_query=search_query, filter_form=filter_form, field_tree=field_tree, active_filters=cleaned, **self.get_extra_context() ) def _index_redirect(self): url = (session.get('%s.index' % self.get_admin_name()) or url_for(self.get_url_name('index'))) return redirect(url) def dispatch_save_redirect(self, instance): if 'save' in request.form: return self._index_redirect() elif 'save_add' in request.form: return redirect(url_for(self.get_url_name('add'))) else: return redirect( url_for(self.get_url_name('edit'), pk=instance._pk) ) def add(self): Form = self.get_add_form() instance = self.model() if request.method == 'POST': form = Form(self.get_form_data()) if form.validate(): instance = self.save_model(instance, form, True) flash('New %s saved successfully' % self.get_display_name(), 'success') return self.dispatch_save_redirect(instance) else: form = Form() return render_template(self.templates['add'], admin=self.admin, model_admin=self, form=form, instance=instance, **self.get_extra_context() ) def edit(self, pk): try: instance = self.get_object(pk) except self.model.DoesNotExist: abort(404) Form = self.get_edit_form(instance) if request.method == 'POST': form = Form(self.get_form_data(), obj=instance) if form.validate(): self.save_model(instance, form, False) flash('Changes to %s saved successfully' % self.get_display_name(), 'success') return self.dispatch_save_redirect(instance) else: form = Form(obj=instance) return render_template(self.templates['edit'], admin=self.admin, model_admin=self, instance=instance, form=form, **self.get_extra_context() ) def collect_objects(self, obj): deps = obj.dependencies() objects = [] for query, fk in obj.dependencies(): if not fk.null: sq = fk.model.select().where(query) collected = [rel_obj for rel_obj in sq.execute().iterator()] if collected: objects.append((0, fk.model, collected)) return sorted(objects, key=lambda i: (i[0], i[1].__name__)) def delete(self): if request.method == 'GET': id_list = request.args.getlist('id') else: id_list = request.form.getlist('id') query = self.model.select().where(self.pk << id_list) if request.method == 'GET': collected = {} if self.delete_collect_objects: for obj in query: collected[obj._pk] = self.collect_objects(obj) elif request.method == 'POST': count = query.count() for obj in query: obj.delete_instance(recursive=self.delete_recursive) flash('Successfully deleted %s %ss' % (count, self.get_display_name()), 'success') return self._index_redirect() return render_template(self.templates['delete'], **dict( admin=self.admin, model_admin=self, query=query, collected=collected, **self.get_extra_context() )) def get_export_fields(self, model=None): # the set of field names that may be exported for `model` -- the base # model uses this admin's settings, related models defer to their own # registered ModelAdmin (falling back to all fields when unregistered). model = model or self.model if model is self.model: include, exclude = self.export_fields, self.export_exclude else: rel_admin = self.admin.get_admin_for(model) if rel_admin is not None: include, exclude = rel_admin.export_fields, rel_admin.export_exclude else: include, exclude = None, None names = list(include) if include else list(model._meta.sorted_field_names) exclude = set(exclude or ()) return [name for name in names if name not in exclude] def get_export_field_objects(self, model=None): model = model or self.model allowed = self.get_export_fields(model) return [model._meta.fields[name] for name in allowed] def collect_related_fields(self, model, accum, path, seen=None): seen = seen or set() path_str = '__'.join(path) for field in model._meta.sorted_fields: if isinstance(field, ForeignKeyField) and field not in seen: seen.add(field) self.collect_related_fields(field.rel_model, accum, path + [field.name], seen) elif model != self.model and field.name in self.get_export_fields(model): accum.setdefault((model, path_str), []) accum[(model, path_str)].append(field) return accum def get_exportable_lookups(self, related): # every field lookup ("content", "user__username") the current # configuration permits -- used to reject anything else on POST. allowed = set(self.get_export_fields(self.model)) for (model, path), fields in related.items(): for field in fields: allowed.add('%s__%s' % (path, field.name)) return allowed def export(self): query = self.get_query() ordering = request.args.get('ordering') or '' query = self.apply_ordering(query, ordering) # process the filters from the request filter_form, query, cleaned, field_tree = self.process_filters(query) related = self.collect_related_fields(self.model, {}, []) # check for raw id id_list = request.args.getlist('id') if id_list: query = query.where(self.pk << id_list) if request.method == 'POST': # enforce the export allowlist server-side so restricted fields # cannot be dumped by posting field names directly. allowed = self.get_exportable_lookups(related) raw_fields = [f for f in request.form.getlist('fields') if f in allowed] export = Export(query, related, raw_fields) return export.json_response('export-%s.json' % self.get_admin_name()) return render_template(self.templates['export'], admin=self.admin, model_admin=self, model=query.model, query=query, filter_form=filter_form, field_tree=field_tree, active_filters=cleaned, export_fields=self.get_export_field_objects(), related_fields=related, sql=query.sql(), **self.get_extra_context() ) def ajax_list(self): field_name = request.args.get('field') prev_page = 0 next_page = 0 try: models = path_to_models(self.model, field_name) except AttributeError: data = [] else: field = self.model._meta.fields[field_name] rel_model = models.pop() rel_field = rel_model._meta.fields[self.foreign_key_lookups[field_name]] query = rel_model.select().order_by(rel_field) query_string = request.args.get('query') if query_string: query = query.where(rel_field.contains(query_string)) pq = PaginatedQuery(query, self.filter_paginate_by) current_page = pq.get_page() if current_page > 1: prev_page = current_page - 1 if current_page < pq.get_pages(): next_page = current_page + 1 data = [] # if the field is nullable, include the "None" option at the top of the list if field.null: data.append({'id': '__None', 'repr': 'None'}) data.extend([{'id': obj._pk, 'repr': str(obj)} for obj in pq.get_list()]) json_data = json.dumps({'prev_page': prev_page, 'next_page': next_page, 'object_list': data}) return Response(json_data, mimetype='application/json') class AdminPanel(object): template_name = 'admin/panels/default.html' def __init__(self, admin, title): self.admin = admin self.title = title self.slug = slugify(self.title) def dashboard_url(self): return url_for('%s.index' % (self.admin.blueprint.name)) def get_urls(self): return () def get_url_name(self, name): return '%s.panel_%s_%s' % ( self.admin.blueprint.name, self.slug, name, ) def get_template_name(self): return self.template_name def get_context(self): return {} def render(self): return render_template(self.get_template_name(), panel=self, **self.get_context()) class Admin(object): def __init__(self, app, auth, prefix='/admin', name='admin', branding='flask-peewee', theme=None): self.app = app self.auth = auth self._admin_models = {} self._registry = {} self._panels = {} self.blueprint = self.get_blueprint(name) self.url_prefix = prefix self.branding = branding self.theme = theme self.prepare_template_environment() def get_url_name(self, name): return '%s.%s' % (self.blueprint.name, name) def auth_required(self, func): @functools.wraps(func) def inner(*args, **kwargs): user = self.auth.get_logged_in_user() if not user: login_url = url_for('%s.login' % self.auth.blueprint.name, next=get_next()) return redirect(login_url) if not self.check_user_permission(user): abort(403) return func(*args, **kwargs) return inner def check_user_permission(self, user): return user.admin def get_urls(self): return ( ('/', self.auth_required(self.index)), ) def __contains__(self, item): return item in self._registry def __getitem__(self, item): return self._registry[item] def register(self, model, admin_class=ModelAdmin): model_admin = admin_class(self, model) admin_name = model_admin.get_admin_name() self._registry[model] = model_admin def unregister(self, model): del(self._registry[model]) def register_panel(self, title, panel, *args, **kwargs): panel_instance = panel(self, title, *args, **kwargs) self._panels[title] = panel_instance def unregister_panel(self, title): del(self._panels[title]) def get_admin_for(self, model): return self._registry.get(model) def get_model_admins(self): return sorted(self._registry.values(), key=lambda o: o.get_admin_name()) def get_panels(self): return sorted(self._panels.values(), key=lambda o: o.slug) def index(self): return render_template('admin/index.html', admin=self, model_admins=self.get_model_admins(), panels=self.get_panels()) def get_blueprint(self, blueprint_name): return Blueprint( blueprint_name, __name__, static_folder=os.path.join(current_dir, 'static'), template_folder=os.path.join(current_dir, 'templates'), ) def register_blueprint(self, **kwargs): self.app.register_blueprint( self.blueprint, url_prefix=self.url_prefix, **kwargs ) def configure_routes(self): for url, callback in self.get_urls(): self.blueprint.route(url, methods=['GET', 'POST'])(callback) for model_admin in self._registry.values(): admin_name = model_admin.get_admin_name() for url, callback in model_admin.get_urls(): full_url = '/%s%s' % (admin_name, url) self.blueprint.add_url_rule( full_url, '%s_%s' % (admin_name, callback.__name__), self.auth_required(callback), methods=['GET', 'POST'], ) for panel in self._panels.values(): for url, callback in panel.get_urls(): full_url = '/%s%s' % (panel.slug, url) self.blueprint.add_url_rule( full_url, 'panel_%s_%s' % (panel.slug, callback.__name__), self.auth_required(callback), methods=['GET', 'POST'], ) def setup(self): self.configure_routes() self.register_blueprint() def get_model_field(self, model, field): try: attr = getattr(model, field) except AttributeError: model_admin = self[type(model)] try: attr = getattr(model_admin, field) except AttributeError: raise AttributeError('Could not find attribute or method ' 'named "%s".' % field) else: return attr(model) else: if callable(attr): attr = attr() return attr def get_form_field(self, form, field_name): return getattr(form, field_name) def fix_underscores(self, s): return s.replace('_', ' ').title() def update_querystring(self, querystring, key, val): if not querystring: return '%s=%s' % (key, val) else: querystring = re.sub(r'%s(?:[^&]+)?&?' % key, '', querystring.decode('utf8')).rstrip('&') return ('%s&%s=%s' % (querystring, key, val)).lstrip('&') def get_verbose_name(self, model, column_name): try: field = model._meta.fields[column_name] except KeyError: return self.fix_underscores(column_name) else: return field.verbose_name or self.fix_underscores(field.name) def get_admin_url(self, obj): model_admin = self.get_admin_for(type(obj)) if model_admin: return url_for(model_admin.get_url_name('edit'), pk=obj._pk) def get_logout_url(self): return url_for('%s.logout' % self.auth.blueprint.name) def get_model_name(self, model_class): model_admin = self.get_admin_for(model_class) if model_admin: return model_admin.get_display_name() return model_class.__name__ def apply_prefix(self, field_name, prefix_accum, field_prefix, rel_prefix='fr_', rel_sep='-'): accum = [] for prefix in prefix_accum: accum.append('%s%s' % (rel_prefix, prefix)) accum.append('%s%s' % (field_prefix, field_name)) return rel_sep.join(accum) def prepare_template_environment(self): self.app.jinja_env.filters['apply_prefix'] = self.apply_prefix class Export(object): def __init__(self, query, related, fields): self.query = query self.related = related self.fields = fields self.alias_to_model = dict([(k[1], k[0]) for k in self.related.keys()]) def prepare_query(self): clone = self.query.clone() select = [] joined = set() def ensure_join(query, m, p): if m not in joined: if '__' not in p: next_model = query.model else: next, _ = p.rsplit('__', 1) next_model = self.alias_to_model[next] query = ensure_join(query, next_model, next) joined.add(m) return query.switch(next_model).join(m) else: return query extra_pks = [] for lookup in self.fields: # lookup may be something like "content" or "user__user_name" if '__' in lookup: path, column = lookup.rsplit('__', 1) model = self.alias_to_model[path] clone = ensure_join(clone, model, path) # the related model's primary key must be selected for the # instance to be reconstructed and traversed when serializing. pk = model._meta.primary_key if not any(f is pk for f in extra_pks): extra_pks.append(pk) else: model = self.query.model column = lookup field = model._meta.fields[column] select.append(field) if select: columns = select + [pk for pk in extra_pks if not any(f is pk for f in select)] clone = clone.columns(*columns) return clone, select def json_response(self, filename='export.json'): serializer = Serializer() prepared_query, selected = self.prepare_query() field_dict = {} for field in selected: field_dict.setdefault(field.model, []) field_dict[field.model].append(field.name) def generate(): i = prepared_query.count() yield b'[\n' for obj in prepared_query: i -= 1 obj_data = serializer.serialize_object(obj, field_dict) yield json.dumps(obj_data).encode('utf-8') if i > 0: yield b',\n' yield b'\n]' headers = Headers() headers.add('Content-Type', 'application/javascript') headers.add('Content-Disposition', 'attachment; filename=%s' % filename) return Response(generate(), mimetype='text/javascript', headers=headers, direct_passthrough=True) flask-peewee-4.0.1/flask_peewee/auth.py000066400000000000000000000166751522375301500200530ustar00rootroot00000000000000import functools import os from flask import Blueprint from flask import abort from flask import flash from flask import g from flask import redirect from flask import render_template from flask import request from flask import session from flask import url_for from peewee import * from wtforms import Form from wtforms import PasswordField from wtforms.fields import StringField from flask_peewee.utils import check_password from flask_peewee.utils import get_next from flask_peewee.utils import is_legacy_password from flask_peewee.utils import is_safe_url from flask_peewee.utils import make_password from wtforms.validators import DataRequired current_dir = os.path.dirname(__file__) class LoginForm(Form): username = StringField('Username', validators=[DataRequired()]) password = PasswordField('Password', validators=[DataRequired()]) class BaseUser(object): def set_password(self, password): self.password = make_password(password) def check_password(self, password): return check_password(password, self.password) class Auth(object): def __init__(self, app, db, user_model=None, prefix='/accounts', name='auth', clear_session=False, default_next_url='/', db_table='user'): self.app = app self.db = db self.db_table = db_table self.User = user_model or self.get_user_model() self.blueprint = self.get_blueprint(name) self.url_prefix = prefix self.clear_session = clear_session self.default_next_url = default_next_url self.setup() def get_context_user(self): return {'user': self.get_logged_in_user()} def get_user_model(self): class User(self.db.Model, BaseUser): username = CharField(unique=True) password = CharField() email = CharField(unique=True) active = BooleanField() admin = BooleanField(default=False) def __str__(self): return self.username class Meta: table_name = self.db_table return User def get_model_admin(self, model_admin=None): if model_admin is None: from flask_peewee.admin import ModelAdmin model_admin = ModelAdmin class UserAdmin(model_admin): columns = getattr(model_admin, 'columns') or ( ['username', 'email', 'active', 'admin']) # never expose the password hash through data export. export_exclude = ('password',) def save_model(self, instance, form, adding=False): orig_password = instance.password user = super(UserAdmin, self).save_model(instance, form, adding) if orig_password != form.password.data: user.set_password(form.password.data) user.save() return user return UserAdmin def register_admin(self, admin_site, model_admin=None): admin_site.register(self.User, self.get_model_admin(model_admin)) def get_blueprint(self, blueprint_name): return Blueprint( blueprint_name, __name__, static_folder=os.path.join(current_dir, 'static'), template_folder=os.path.join(current_dir, 'templates'), ) def get_urls(self): return ( ('/logout/', self.logout), ('/login/', self.login), ) def get_login_form(self): return LoginForm def test_user(self, test_fn): def decorator(fn): @functools.wraps(fn) def inner(*args, **kwargs): user = self.get_logged_in_user() if not user or not test_fn(user): login_url = url_for('%s.login' % self.blueprint.name, next=get_next()) return redirect(login_url) return fn(*args, **kwargs) return inner return decorator def login_required(self, func): return self.test_user(lambda u: True)(func) def admin_required(self, func): return self.test_user(lambda u: u.admin)(func) def authenticate(self, username, password): active = self.User.select().where(self.User.active==True) try: user = active.where(self.User.username==username).get() except self.User.DoesNotExist: return False else: if not user.check_password(password): return False # transparently upgrade legacy password hashes on successful login. if is_legacy_password(user.password): user.set_password(password) user.save() return user def login_user(self, user): session['logged_in'] = True session['user_pk'] = user._pk session.permanent = True g.user = user flash('You are logged in as %s' % user, 'success') def logout_user(self): if self.clear_session: session.clear() else: session.pop('logged_in', None) g.user = None flash('You are now logged out', 'success') def get_logged_in_user(self): if session.get('logged_in'): if getattr(g, 'user', None): return g.user try: return self.User.select().where( self.User.active==True, self.User._meta.primary_key==session.get('user_pk') ).get() except self.User.DoesNotExist: pass def login(self): error = None Form = self.get_login_form() if request.method == 'POST': form = Form(request.form) next_url = request.form.get('next') if not is_safe_url(next_url): next_url = self.default_next_url if form.validate(): authenticated_user = self.authenticate( form.username.data, form.password.data, ) if authenticated_user: self.login_user(authenticated_user) return redirect(next_url) else: flash('Incorrect username or password', 'danger') else: form = Form() next_url = request.args.get('next') return render_template( 'auth/login.html', error=error, form=form, login_url=url_for('%s.login' % self.blueprint.name), next=next_url) def logout(self): self.logout_user() next_url = request.args.get('next') if not is_safe_url(next_url): next_url = self.default_next_url return redirect(next_url) def configure_routes(self): for url, callback in self.get_urls(): self.blueprint.route(url, methods=['GET', 'POST'])(callback) def register_blueprint(self, **kwargs): self.app.register_blueprint(self.blueprint, url_prefix=self.url_prefix, **kwargs) def load_user(self): g.user = self.get_logged_in_user() def register_handlers(self): self.app.before_request_funcs.setdefault(None, []) self.app.before_request_funcs[None].append(self.load_user) def register_context_processors(self): self.app.template_context_processors[None].append(self.get_context_user) def setup(self): self.configure_routes() self.register_blueprint() self.register_handlers() self.register_context_processors() flask-peewee-4.0.1/flask_peewee/db.py000066400000000000000000000045701522375301500174660ustar00rootroot00000000000000import peewee from peewee import * from flask_peewee.exceptions import ImproperlyConfigured from flask_peewee.utils import load_class class Database(object): def __init__(self, app=None, database=None): self.database = None self.init_app(app, database) def init_app(self, app, database=None): if app is None: self.database = database or Proxy() self.Model = self.get_model_class() return if isinstance(self.database, Proxy): # We deferred initialization, now initialize the proxy. self.database.initialize(database or self.load_database(app)) elif self.database is None: self.database = database or self.load_database(app) self.Model = self.get_model_class() elif database: raise ImproperlyConfigured('Database plugin has already been initialized.') self.register_handlers(app) def load_database(self, app): self.database_config = dict(app.config['DATABASE']) try: self.database_name = self.database_config.pop('name') self.database_engine = self.database_config.pop('engine') except KeyError: raise ImproperlyConfigured('Please specify a "name" and "engine" for your database') try: self.database_class = load_class(self.database_engine) assert issubclass(self.database_class, peewee.Database) except ImportError: raise ImproperlyConfigured('Unable to import: "%s"' % self.database_engine) except AttributeError: raise ImproperlyConfigured('Database engine not found: "%s"' % self.database_engine) except AssertionError: raise ImproperlyConfigured('Database engine not a subclass of peewee.Database: "%s"' % self.database_engine) return self.database_class(self.database_name, **self.database_config) def get_model_class(self): class BaseModel(Model): class Meta: database = self.database return BaseModel def connect_db(self): if self.database.is_closed(): self.database.connect() def close_db(self, exc): if not self.database.is_closed(): self.database.close() def register_handlers(self, app): app.before_request(self.connect_db) app.teardown_request(self.close_db) flask-peewee-4.0.1/flask_peewee/exceptions.py000066400000000000000000000000601522375301500212500ustar00rootroot00000000000000class ImproperlyConfigured(Exception): pass flask-peewee-4.0.1/flask_peewee/filters.py000066400000000000000000000454451522375301500205570ustar00rootroot00000000000000import datetime import operator from flask import request from peewee import * from werkzeug.datastructures import MultiDict from wtforms import fields from wtforms import form from wtforms import validators from wtforms import widgets from flask_peewee.forms import BaseModelConverter from functools import reduce class QueryFilter(object): """ Basic class representing a named field (with or without a list of options) and an operation against a given value """ # stable name identifying this operation in query-strings. key = None # override the value input's HTML type for this operation, e.g. 'number' # for operations that take a count or year rather than a date. input_type = None def __init__(self, field, name, options=None): self.field = field self.name = name self.options = options def clean(self, value): return self.field.db_value(value) def query(self, value): raise NotImplementedError def operation(self): raise NotImplementedError def get_options(self): return self.options class EqualQueryFilter(QueryFilter): key = 'eq' def query(self, value): return self.field == value def operation(self): return 'equal to' class NotEqualQueryFilter(QueryFilter): key = 'ne' def query(self, value): return self.field != value def operation(self): return 'not equal to' class LessThanQueryFilter(QueryFilter): key = 'lt' def query(self, value): return self.field < value def operation(self): return 'less than' class LessThanEqualToQueryFilter(QueryFilter): key = 'lte' def query(self, value): return self.field <= value def operation(self): return 'less than or equal to' class GreaterThanQueryFilter(QueryFilter): key = 'gt' def query(self, value): return self.field > value def operation(self): return 'greater than' class GreaterThanEqualToQueryFilter(QueryFilter): key = 'gte' def query(self, value): return self.field >= value def operation(self): return 'greater than or equal to' class StartsWithQueryFilter(QueryFilter): key = 'startswith' def clean(self, value): return value def query(self, value): return fn.Lower(fn.Substr(self.field, 1, len(value))) == value.lower() def operation(self): return 'starts with' class ContainsQueryFilter(QueryFilter): key = 'contains' def clean(self, value): return value def query(self, value): return self.field.contains(value) def operation(self): return 'contains' class YearFilter(QueryFilter): key = 'year' input_type = 'number' def clean(self, value): return int(value) def query(self, value): return self.field.year == value def operation(self): return 'year equals' class MonthFilter(QueryFilter): key = 'month' input_type = 'number' def clean(self, value): return int(value) def query(self, value): return self.field.month == value def operation(self): return 'month equals' class WithinDaysAgoFilter(QueryFilter): key = 'within_days' input_type = 'number' def clean(self, value): return int(value) def query(self, value): return self.field >= ( datetime.date.today() - datetime.timedelta(days=value)) def operation(self): return 'within X days ago' class OlderThanDaysAgoFilter(QueryFilter): key = 'older_days' input_type = 'number' def clean(self, value): return int(value) def query(self, value): return self.field < ( datetime.date.today() - datetime.timedelta(days=value)) def operation(self): return 'older than X days ago' class TimestampMixin(object): """Clean a datetime-picker value for a :class:`peewee.TimestampField`. A ``TimestampField`` stores an integer, and its ``db_value()`` cannot parse the raw string the filter form submits -- it raises ``TypeError``, which ``process_request`` silently swallows, so the filter is dropped entirely. Parse the value into a ``datetime`` and hand *that* to the query: peewee converts it to the stored integer via ``db_value()`` exactly once when building the WHERE clause, which stays correct even for sub-second ``resolution`` (returning a pre-scaled integer would be re-scaled). """ input_formats = ('%Y-%m-%dT%H:%M:%S', '%Y-%m-%dT%H:%M', '%Y-%m-%d') def clean(self, value): if isinstance(value, datetime.datetime): return value for fmt in self.input_formats: try: return datetime.datetime.strptime(value, fmt) except (TypeError, ValueError): continue raise ValueError('invalid timestamp value: %r' % (value,)) class TimestampEqualFilter(TimestampMixin, EqualQueryFilter): pass class TimestampNotEqualFilter(TimestampMixin, NotEqualQueryFilter): pass class TimestampLessThanFilter(TimestampMixin, LessThanQueryFilter): pass class TimestampLessThanEqualToFilter(TimestampMixin, LessThanEqualToQueryFilter): pass class TimestampGreaterThanFilter(TimestampMixin, GreaterThanQueryFilter): pass class TimestampGreaterThanEqualToFilter(TimestampMixin, GreaterThanEqualToQueryFilter): pass class BooleanEqualQueryFilter(EqualQueryFilter): def clean(self, value): if isinstance(value, str) and value.lower() in ('0', 'false', 'f', ''): return False return True class BooleanNotEqualQueryFilter(BooleanEqualQueryFilter): key = 'ne' def query(self, value): return self.field != value def operation(self): return 'not equal to' class FilterMapping(object): """ Map a peewee field to a list of valid query filters for that field """ string = ( EqualQueryFilter, NotEqualQueryFilter, StartsWithQueryFilter, ContainsQueryFilter) numeric = ( EqualQueryFilter, NotEqualQueryFilter, LessThanQueryFilter, GreaterThanQueryFilter, LessThanEqualToQueryFilter, GreaterThanEqualToQueryFilter) datetime_date = (numeric + ( WithinDaysAgoFilter, OlderThanDaysAgoFilter, YearFilter, MonthFilter)) # TimestampField stores an integer but represents a datetime -- same # operations as datetime_date, but the comparisons parse the picker value # into a datetime (see TimestampMixin) so peewee converts it correctly. timestamp = ( TimestampEqualFilter, TimestampNotEqualFilter, TimestampLessThanFilter, TimestampGreaterThanFilter, TimestampLessThanEqualToFilter, TimestampGreaterThanEqualToFilter, WithinDaysAgoFilter, OlderThanDaysAgoFilter, YearFilter, MonthFilter) foreign_key = (EqualQueryFilter, NotEqualQueryFilter) boolean = (BooleanEqualQueryFilter, BooleanNotEqualQueryFilter) def get_field_types(self): return { CharField: 'string', TextField: 'string', DateTimeField: 'datetime_date', DateField: 'datetime_date', TimestampField: 'timestamp', TimeField: 'numeric', IntegerField: 'numeric', BigIntegerField: 'numeric', FloatField: 'numeric', DoubleField: 'numeric', DecimalField: 'numeric', BooleanField: 'boolean', AutoField: 'numeric', ForeignKeyField: 'foreign_key', } def convert(self, field): mapping = self.get_field_types() for klass in type(field).__mro__: if klass in mapping: mapping_fn = getattr(self, 'convert_%s' % mapping[klass]) return mapping_fn(field) # fall back to numeric return self.convert_numeric(field) def convert_string(self, field): return [f(field, field.verbose_name, field.choices) for f in self.string] def convert_numeric(self, field): return [f(field, field.verbose_name, field.choices) for f in self.numeric] def convert_datetime_date(self, field): return [f(field, field.verbose_name, field.choices) for f in self.datetime_date] def convert_timestamp(self, field): return [f(field, field.verbose_name, field.choices) for f in self.timestamp] def convert_boolean(self, field): boolean_choices = [('True', '1', 'False', '')] return [f(field, field.verbose_name, boolean_choices) for f in self.boolean] def convert_foreign_key(self, field): return [f(field, field.verbose_name, field.choices) for f in self.foreign_key] class FieldTreeNode(object): def __init__(self, model, fields, children=None): self.model = model self.fields = fields self.children = children or {} def make_field_tree(model, fields, exclude, force_recursion=False, seen=None): no_explicit_fields = fields is None # assume we want all of them if no_explicit_fields: fields = model._meta.sorted_field_names exclude = exclude or [] seen = seen or set() model_fields = [] children = {} for field_obj in model._meta.sorted_fields: if field_obj.name in exclude or field_obj in seen: continue # binary fields have no meaningful filter operation. if field_obj.name in fields and not isinstance(field_obj, BlobField): model_fields.append(field_obj) if isinstance(field_obj, ForeignKeyField): seen.add(field_obj) if no_explicit_fields: rel_fields = None else: rel_fields = [ rf.replace('%s__' % field_obj.name, '') \ for rf in fields if rf.startswith('%s__' % field_obj.name) ] if not rel_fields and force_recursion: rel_fields = None rel_exclude = [ rx.replace('%s__' % field_obj.name, '') \ for rx in exclude if rx.startswith('%s__' % field_obj.name) ] children[field_obj.name] = make_field_tree(field_obj.rel_model, rel_fields, rel_exclude, force_recursion, seen) return FieldTreeNode(model, model_fields, children) class SmallSelectWidget(widgets.Select): def __call__(self, field, **kwargs): kwargs['class'] = 'form-select form-select-sm w-auto' return super(SmallSelectWidget, self).__call__(field, **kwargs) class FilterForm(object): base_class = form.Form separator = '-' field_operation_prefix = 'fo_' field_value_prefix = 'fv_' field_relation_prefix = 'fr_' def __init__(self, model, model_converter, filter_mapping, fields=None, exclude=None): self.model = model self.model_converter = model_converter self.filter_mapping = filter_mapping # convert fields and exclude into a tree self._field_tree = make_field_tree(model, fields, exclude) self._query_filters = self.load_query_filters() self._filter_lookup = dict( (field, dict((qf.key, qf) for qf in query_filters)) for field, query_filters in self._query_filters.items()) def load_query_filters(self): query_filters = {} queue = [self._field_tree] while queue: curr = queue.pop(0) for field in curr.fields: query_filters[field] = self.filter_mapping.convert(field) queue.extend(curr.children.values()) return query_filters def get_operation_field(self, field): choices = [] for query_filter in self._query_filters[field]: if query_filter.input_type: choices.append((query_filter.key, query_filter.operation(), {'data-input-type': query_filter.input_type})) else: choices.append((query_filter.key, query_filter.operation())) return fields.SelectField(choices=choices, validators=[validators.Optional()], widget=SmallSelectWidget()) def get_query_filter(self, field, filter_key): try: return self._filter_lookup[field][filter_key] except KeyError: pass # fall back to the old positional protocol, e.g. fo_username=2. if filter_key.isdigit(): query_filters = self._query_filters[field] idx = int(filter_key) if idx < len(query_filters): return query_filters[idx] def get_field_default(self, field): if isinstance(field, (DateTimeField, TimestampField)): return datetime.datetime.now() elif isinstance(field, DateField): return datetime.date.today() elif isinstance(field, TimeField): return datetime.time(0, 0) return field.default def get_value_field(self, field): field_name, form_field = self.model_converter.convert(field.model, field, None) form_field.kwargs['default'] = self.get_field_default(field) form_field.kwargs['validators'] = [validators.Optional()] return form_field def get_field_dict(self, node=None, prefix=None): field_dict = {} node = node or self._field_tree for field in node.fields: op_field = self.get_operation_field(field) val_field = self.get_value_field(field) field_dict['%s%s' % (self.field_operation_prefix, field.name)] = op_field field_dict['%s%s' % (self.field_value_prefix, field.name)] = val_field for prefix, node in node.children.items(): child_fd = self.get_field_dict(node, prefix) field_dict['%s%s' % (self.field_relation_prefix, prefix)] = fields.FormField( self.get_form(child_fd), separator=self.separator, ) return field_dict def get_form(self, field_dict): return type( self.model.__name__ + 'FilterForm', (self.base_class, ), field_dict, ) def parse_query_filters(self): # reconstruct the "select" and "value" fields we are searching for in the # arguments from the request by depth-first searching the field tree -- # basically what we should have at the end is the field we're querying, # the type of query (QueryFilter), the value requested, and the path we # took to get there (joins) accum = {} def _dfs(node, prefix, models, join_columns, path_names): for field in node.fields: qf_select = self.field_operation_prefix.join((prefix, field.name)) qf_value = self.field_value_prefix.join((prefix, field.name)) if qf_select in request.args and qf_value in request.args: accum.setdefault(field, []) accum[field].append(( request.args.getlist(qf_select), request.args.getlist(qf_value), models, join_columns, qf_select, qf_value, ' / '.join(path_names + [field.name]), )) for child_prefix, child in node.children.items(): new_prefix = prefix + self.field_relation_prefix + child_prefix + self.separator model_copy = list(models) + [child.model] join_copy = list(join_columns) + [node.model._meta.fields[child_prefix]] _dfs(child, new_prefix, model_copy, join_copy, path_names + [child_prefix]) _dfs(self._field_tree, '', [], [], []) return accum def resolve_form_field(self, form, name): # fr_user-fo_username -> form['fr_user'].form['fo_username'] parts = name.split(self.separator) obj = form for part in parts[:-1]: obj = obj[part].form return obj[parts[-1]] def process_request(self, query): field_dict = self.get_field_dict() FormClass = self.get_form(field_dict) form = FormClass(request.args) query_filters = self.parse_query_filters() cleaned = [] for field, filters in query_filters.items(): for (filter_key_list, filter_value_list, path, join_path, qf_s, qf_v, label) in filters: query = query.switch(self.model) for join, model in zip(join_path, path): query = query.ensure_join(join.model, model, join) op_groups = {} for filter_key, filter_value in zip(filter_key_list, filter_value_list): query_filter = self.get_query_filter(field, filter_key) if query_filter is None: continue try: value = query_filter.clean(filter_value) except (TypeError, ValueError): continue op_groups.setdefault(query_filter.key, []).append( query_filter.query(value)) # `form` only binds the first occurrence of each # parameter, so give each row its own form bound to just # that row's operation and value. row_form = FormClass(MultiDict([ (qf_s, query_filter.key), (qf_v, filter_value)])) cleaned.append({ 'label': label, 'key': query_filter.key, 'value': filter_value, 'input_type': query_filter.input_type, 'op_field': self.resolve_form_field(row_form, qf_s), 'value_field': self.resolve_form_field(row_form, qf_v), }) # repeated uses of one operation are OR'd together, e.g. # eq a, eq b -> "a or b" -- while distinct operations are # AND'd, e.g. gt 8, lt 12 -> a range. for exprs in op_groups.values(): query = query.where(reduce(operator.or_, exprs)) return form, query, cleaned class DateTimeLocalField(fields.DateTimeLocalField): # wtforms' default format list renders with a space separator, which is # not a valid value for . def __init__(self, *args, **kwargs): kwargs.setdefault('format', ['%Y-%m-%dT%H:%M:%S', '%Y-%m-%dT%H:%M']) super(DateTimeLocalField, self).__init__(*args, **kwargs) class FilterModelConverter(BaseModelConverter): def __init__(self, *args, **kwargs): super(FilterModelConverter, self).__init__(*args, **kwargs) self.defaults = dict(self.defaults) self.defaults[TextField] = fields.StringField self.defaults[DateTimeField] = DateTimeLocalField # TimestampField represents a datetime; give it the same picker input. self.defaults[TimestampField] = DateTimeLocalField flask-peewee-4.0.1/flask_peewee/forms.py000066400000000000000000000035151522375301500202250ustar00rootroot00000000000000from peewee import BooleanField from wtforms import widgets from wtfpeewee.fields import BooleanSelectField from wtfpeewee.fields import ModelSelectField from wtfpeewee.fields import wtf_choice from wtfpeewee.orm import ModelConverter class BaseModelConverter(ModelConverter): def __init__(self, *args, **kwargs): super(BaseModelConverter, self).__init__(*args, **kwargs) self.converters[BooleanField] = self.handle_boolean def handle_boolean(self, model, field, **kwargs): return field.name, BooleanSelectField(**kwargs) class AjaxSelectWidget(widgets.Select): """ Select whose options are (re)populated from the model admin's ajax_list endpoint by a search input -- see Admin.ajaxSelect in admin.js. """ def __init__(self, data_source, data_param, *args, **kwargs): self.data_source = data_source self.data_param = data_param super(AjaxSelectWidget, self).__init__(*args, **kwargs) def __call__(self, field, **kwargs): kwargs['data-role'] = 'ajax-select' kwargs['data-source'] = self.data_source kwargs['data-param'] = self.data_param return super(AjaxSelectWidget, self).__call__(field, **kwargs) #: Backwards-compatible alias from the chosen.js era. ChosenAjaxSelectWidget = AjaxSelectWidget class LimitedModelSelectField(ModelSelectField): limit = 20 def iter_choices(self): found = False for obj in self.query.limit(self.limit): if obj == self.data: found = True yield wtf_choice(obj._pk, self.get_label(obj), obj == self.data) # ensure the selected object is present even when it falls outside # the first `limit` rows. if isinstance(self.data, self.model) and not found: yield wtf_choice(self.data._pk, self.get_label(self.data), True) flask-peewee-4.0.1/flask_peewee/rest.py000066400000000000000000000637051522375301500200630ustar00rootroot00000000000000import functools import json import operator from flask import Blueprint from flask import Response from flask import abort from flask import g from flask import redirect from flask import request from flask import session from flask import url_for from peewee import * from peewee import DJANGO_MAP from flask_peewee.filters import make_field_tree from flask_peewee.serializer import Deserializer from flask_peewee.serializer import Serializer from flask_peewee.utils import PaginatedQuery from flask_peewee.utils import convert_boolean from flask_peewee.utils import get_object_or_404 from flask_peewee.utils import slugify from functools import reduce # every HTTP method the REST API handles. Pass as protected_methods to require # authentication on reads as well as writes, e.g. # BearerAuthentication(Token, ALL_METHODS). ALL_METHODS = ('GET', 'POST', 'PUT', 'DELETE') class RestForbidden(Exception): # raised when a nested write fails the child resource's check_*; caught in # create/edit and turned into a 403 (and rolls back the enclosing atomic). pass class Authentication(object): def __init__(self, protected_methods=None): if protected_methods is None: protected_methods = ['POST', 'PUT', 'DELETE'] self.protected_methods = protected_methods def authorize(self): if request.method in self.protected_methods: return False return True class APIKeyAuthentication(Authentication): """ Requires a model that has at least two fields, "key" and "secret", which will be searched for when authing a request. """ key_field = 'key' secret_field = 'secret' def __init__(self, model, protected_methods=None): super(APIKeyAuthentication, self).__init__(protected_methods) self.model = model self._key_field = model._meta.fields[self.key_field] self._secret_field = model._meta.fields[self.secret_field] def get_query(self): return self.model.select() def get_key(self, k, s): try: return self.get_query().where( self._key_field==k, self._secret_field==s ).get() except self.model.DoesNotExist: pass def get_key_secret(self): for search in [request.args, request.headers, request.form]: if 'key' in search and 'secret' in search: return search['key'], search['secret'] return None, None def authorize(self): g.api_key = None if request.method not in self.protected_methods: return True key, secret = self.get_key_secret() if key or secret: g.api_key = self.get_key(key, secret) return g.api_key class BearerAuthentication(Authentication): """ Token auth via the ``Authorization: Bearer `` header. Requires a model with a token field (default "token"), which is looked up to authorize the request. Unlike APIKeyAuthentication the credential rides in a header rather than the query-string, so it does not leak into access logs. Store high-entropy tokens; to keep them hashed at rest, override get_key. """ token_field = 'token' def __init__(self, model, protected_methods=None): super(BearerAuthentication, self).__init__(protected_methods) self.model = model self._token_field = model._meta.fields[self.token_field] def get_query(self): return self.model.select() def get_token(self): scheme, _, token = request.headers.get( 'Authorization', '').partition(' ') if scheme.lower() == 'bearer' and token.strip(): return token.strip() def get_key(self, token): try: return self.get_query().where(self._token_field == token).get() except self.model.DoesNotExist: pass def authorize(self): g.api_key = None if request.method not in self.protected_methods: return True token = self.get_token() if token: g.api_key = self.get_key(token) return g.api_key class UserBearerAuthentication(BearerAuthentication): """ Bearer-token auth that resolves the token to a *user* and sets g.user, so it drives RestrictOwnerResource and the rest of the user-auth stack. The token model has a foreign key to the user (default "user"); set user_field=None if the token lives directly on the user model. """ user_field = 'user' def authorize(self): g.user = None if request.method not in self.protected_methods: return True token = self.get_token() if token: key = self.get_key(token) if key is not None: g.user = key if self.user_field is None \ else getattr(key, self.user_field) return g.user class UserAuthentication(Authentication): def __init__(self, auth, protected_methods=None): super(UserAuthentication, self).__init__(protected_methods) self.auth = auth def authorize(self): g.user = None if request.method not in self.protected_methods: return True basic_auth = request.authorization if not basic_auth: return False g.user = self.auth.authenticate(basic_auth.username, basic_auth.password) return g.user class AdminAuthentication(UserAuthentication): def verify_user(self, user): return user.admin def authorize(self): res = super(AdminAuthentication, self).authorize() if res and g.user: return self.verify_user(g.user) return res class RestResource(object): # default page size when the client does not request a "limit". paginate_by = 20 # upper bound on a client-requested "limit"; None means no ceiling. This # lets clients ask for pages larger than paginate_by (up to the cap) -- # paginate_by alone is only the default, never a maximum. max_paginate_by = None value_transforms = {'False': False, 'false': False, 'True': True, 'true': True, 'None': None, 'none': None} # serializing: dictionary of model -> field names to restrict output fields = None exclude = None # field names that clients may never write, even when they appear in an # incoming POST/PUT body -- protects against mass assignment. readonly_fields = None # exclude certian fields from being exposed as filters -- for related fields # use "__" notation, e.g. user__password filter_exclude = None filter_fields = None filter_recursive = True # mapping of field name to resource class include_resources = None # whether related objects may be created/updated through a nested {...} in # this resource's payload. When False, a nested object is ignored (the FK # can still be set by scalar id). nested_writes = True # delete behavior delete_recursive = True def __init__(self, rest_api, model, authentication, allowed_methods=None): self.api = rest_api self.model = model self.pk = model._meta.primary_key self.authentication = authentication self.allowed_methods = allowed_methods or list(ALL_METHODS) self._fields = {self.model: self.fields or self.model._meta.sorted_field_names} if self.exclude: self._exclude = {self.model: self.exclude} else: self._exclude = {} self._filter_fields = self.filter_fields or list(self.model._meta.sorted_field_names) self._filter_exclude = self.filter_exclude or [] self._resources = {} # recurse into nested resources if self.include_resources: for field_name, resource in self.include_resources.items(): field_obj = self.model._meta.fields[field_name] resource_obj = resource(self.api, field_obj.rel_model, self.authentication, self.allowed_methods) self._resources[field_name] = resource_obj self._fields.update(resource_obj._fields) self._exclude.update(resource_obj._exclude) self._filter_fields.extend(['%s__%s' % (field_name, ff) for ff in resource_obj._filter_fields]) self._filter_exclude.extend(['%s__%s' % (field_name, ff) for ff in resource_obj._filter_exclude]) self._include_foreign_keys = False else: self._include_foreign_keys = True self._field_tree = make_field_tree(self.model, self._filter_fields, self._filter_exclude, self.filter_recursive) def authorize(self): return self.authentication.authorize() def get_api_name(self): return slugify(self.model.__name__) def get_url_name(self, name): return '%s.%s_%s' % ( self.api.blueprint.name, self.get_api_name(), name, ) def get_query(self): return self.model.select() def process_query(self, query): raw_filters = {} # clean and normalize the request parameters for key in request.args: if key in ('ordering', 'page', 'limit'): continue orig_key = key if key.startswith('-'): negated = True key = key[1:] else: negated = False if '__' in key: expr, op = key.rsplit('__', 1) if op not in DJANGO_MAP: expr = key op = 'eq' else: expr = key op = 'eq' raw_filters.setdefault(expr, []) raw_filters[expr].append((op, request.args.getlist(orig_key), negated)) if not raw_filters: return query # do a breadth first search across the field tree created by filter_fields, # searching for matching keys in the request parameters -- when found, # filter the query accordingly queue = [(self._field_tree, '')] while queue: node, prefix = queue.pop(0) for field in node.fields: filter_expr = '%s%s' % (prefix, field.name) if filter_expr in raw_filters: for op, arg_list, negated in raw_filters.pop(filter_expr): clean_args = self.clean_arg_list(arg_list) query = self.apply_filter(query, field, filter_expr, op, clean_args, negated) for child_prefix, child_node in node.children.items(): queue.append((child_node, prefix + child_prefix + '__')) return query def clean_arg_list(self, arg_list): return [self.value_transforms.get(arg, arg) for arg in arg_list] def apply_filter(self, query, field, expr, op, arg_list, negated): query_expr = '%s__%s' % (expr, op) constructor = lambda kwargs: ~DQ(**kwargs) if negated else DQ(**kwargs) if isinstance(field, BooleanField): arg_list = [convert_boolean(arg) for arg in arg_list] if op == 'in': # `in` values may be given comma-separated and/or as repeated # params, e.g. ?id__in=1,2&id__in=3 -> [1, 2, 3]. values = [] for arg in arg_list: values.extend(v.strip() for v in str(arg).split(',')) return query.filter(constructor({query_expr: values})) elif len(arg_list) == 1: return query.filter(constructor({query_expr: arg_list[0]})) else: query_clauses = [ constructor({query_expr: val}) for val in arg_list] return query.filter(reduce(operator.or_, query_clauses)) def get_serializer(self): return Serializer() def get_deserializer(self): return Deserializer() def prepare_data(self, obj, data): """ Hook for modifying outgoing data """ return data def serialize_object(self, obj): s = self.get_serializer() return self.prepare_data( obj, s.serialize_object(obj, self._fields, self._exclude) ) def serialize_query(self, query): s = self.get_serializer() return [ self.prepare_data(obj, s.serialize_object(obj, self._fields, self._exclude)) \ for obj in query ] def get_readonly_fields(self): # the primary key is always read-only: it is addressed via the URL, # never rewritten from the request body. readonly = set(self.readonly_fields or ()) readonly.add(self.pk.name) return readonly def scrub_readonly_fields(self, data): # Strip read-only fields at *every* level of a (possibly nested) # payload. A top-level-only strip is not enough: the deserializer # recurses into nested foreign-key dicts and would write read-only # fields (e.g. "admin") straight onto the related instance, defeating # the guard and allowing privilege escalation via a nested write. # Recurse through the declared child resources so each applies its own # read-only policy. if not isinstance(data, dict): return data readonly = self.get_readonly_fields() cleaned = {} for key, value in data.items(): if key in readonly: continue if key in self._resources and isinstance(value, dict): if not self.nested_writes: # nested writes disabled: ignore the nested object. continue value = self._resources[key].scrub_readonly_fields(value) cleaned[key] = value return cleaned def deserialize_object(self, data, instance): data = self.scrub_readonly_fields(data) d = self.get_deserializer() return d.deserialize_object(instance, data) def response_error(self, message, status): return Response(json.dumps({'error': message}), status=status, mimetype='application/json') def response_forbidden(self): return self.response_error('Forbidden', 403) def response_bad_method(self): return self.response_error('Unsupported method "%s"' % request.method, 405) def response_bad_request(self, message='Bad request'): return self.response_error(message, 400) def response(self, data): return Response(json.dumps(data), mimetype='application/json') def require_method(self, func, methods): @functools.wraps(func) def inner(*args, **kwargs): if request.method not in methods: return self.response_bad_method() return func(*args, **kwargs) return inner def get_urls(self): return ( ('/', self.require_method(self.api_list, ['GET', 'POST'])), ('//', self.require_method(self.api_detail, ['GET', 'POST', 'PUT', 'DELETE'])), ('//delete/', self.require_method(self.post_delete, ['POST', 'DELETE'])), ) def check_get(self, obj=None): return True def check_post(self, obj=None): return True def check_put(self, obj): return True def check_delete(self, obj): return True def save_object(self, instance, raw_data): instance.save() return instance def api_list(self): if not getattr(self, 'check_%s' % request.method.lower())(): return self.response_forbidden() if request.method == 'GET': return self.object_list() elif request.method == 'POST': return self.create() def api_detail(self, pk, method=None): obj = get_object_or_404(self.get_query(), self.pk==pk) method = method or request.method if not getattr(self, 'check_%s' % method.lower())(obj): return self.response_forbidden() if method == 'GET': return self.object_detail(obj) elif method in ('PUT', 'POST'): return self.edit(obj) elif method == 'DELETE': return self.delete(obj) def post_delete(self, pk): return self.api_detail(pk, 'DELETE') def apply_ordering(self, query): ordering = request.args.get('ordering') or '' if ordering: desc, column = ordering.startswith('-'), ordering.lstrip('-') if column in self.model._meta.fields: field = self.model._meta.fields[column] query = query.order_by(field.asc() if not desc else field.desc()) return query def get_request_metadata(self, paginated_query): var = paginated_query.page_var # to_dict(flat=False) keeps repeated params (e.g. ?user=1&user=2) so # they survive into the next/previous links. request_arguments = request.args.to_dict(flat=False) current_page = paginated_query.get_page() next = previous = '' if current_page > 1: request_arguments[var] = current_page - 1 previous = url_for(self.get_url_name('api_list'), **request_arguments) if current_page < paginated_query.get_pages(): request_arguments[var] = current_page + 1 next = url_for(self.get_url_name('api_list'), **request_arguments) return { 'model': self.get_api_name(), 'page': current_page, 'page_count': paginated_query.get_pages(), 'object_count': paginated_query.get_count(), 'previous': previous, 'next': next, } def get_paginate_by(self): # an explicit "limit" wins (capped at max_paginate_by if set), # otherwise fall back to the resource default. paginate_by is the # default page size, not a maximum -- clients may request more. if 'limit' in request.args: try: limit = int(request.args['limit']) except (TypeError, ValueError): limit = 0 if limit > 0: if self.max_paginate_by: return min(limit, self.max_paginate_by) return limit return self.paginate_by def paginated_object_list(self, filtered_query): paginate_by = self.get_paginate_by() if not paginate_by: # pagination disabled and no limit requested: put everything on a # single page so the response still uses the {meta, objects} # envelope rather than a bare list. paginate_by = filtered_query.count() or 1 pq = PaginatedQuery(filtered_query, paginate_by) meta_data = self.get_request_metadata(pq) query_dict = self.serialize_query(pq.get_list()) return self.response({ 'meta': meta_data, 'objects': query_dict, }) def apply_related_joins(self, query): # Eager-load the include_resources tree in a single query so nested # serialization does not issue a lookup per row (the N+1 you would get # from lazily following each foreign key). Each related model is LEFT # OUTER joined -- nullable FKs stay None -- and aliased, so the same # model may be nested more than once (e.g. from_user / to_user). return self._join_related(query, self.model, self) def _join_related(self, query, src, resource): for field_name, child in resource._resources.items(): dest = child.model.alias() fk = getattr(src, field_name) pk = getattr(dest, child.model._meta.primary_key.name) query = query.select_extend(dest).join_from( src, dest, JOIN.LEFT_OUTER, on=(fk == pk), attr=field_name) query = self._join_related(query, dest, child) return query def object_list(self): query = self.get_query() query = self.apply_ordering(query) # process any filters query = self.process_query(query) # eager-load nested relations (avoids N+1 during serialization). This # runs after process_query so it composes with the DQ-based filter # joins -- the related models are aliased, so they never collide. query = self.apply_related_joins(query) # always return the paginated envelope so the response shape is # consistent regardless of the resource's paginate_by setting. return self.paginated_object_list(query) def object_detail(self, obj): return self.response(self.serialize_object(obj)) def save_related_objects(self, instance, data): if not self.nested_writes: return for k, v in data.items(): if k in self._resources and isinstance(v, dict): rel_resource = self._resources[k] existing = getattr(instance, k) rel_obj, rel_models = rel_resource.deserialize_object(v, existing) # a nested write must satisfy the child resource's own # per-object authorization, exactly as a direct write to that # resource would -- editing an existing related row runs # check_put, creating a new one runs check_post. if existing is not None and existing.get_id() is not None: allowed = rel_resource.check_put(rel_obj) else: allowed = rel_resource.check_post(rel_obj) if not allowed: raise RestForbidden() rel_resource.save_related_objects(rel_obj, v) setattr(instance, k, rel_resource.save_object(rel_obj, v)) def read_request_data(self): if request.data: return json.loads(request.data.decode('utf-8')) elif request.form.get('data'): return json.loads(request.form['data']) else: return dict(request.form) def persist_object(self, instance, data): # deserialize + save, translating validation/integrity problems into a # 400 (see create/edit) rather than letting them surface as a 500. # Wrapped in a transaction so a rejected nested write (RestForbidden) # or an integrity error cannot leave a half-written object graph. with self.model._meta.database.atomic(): obj, models = self.deserialize_object(data, instance) self.save_related_objects(obj, data) return self.save_object(obj, data) def create(self): try: data = self.read_request_data() except ValueError: return self.response_bad_request('Request body is not valid JSON.') try: obj = self.persist_object(self.model(), data) except RestForbidden: return self.response_forbidden() except (IntegrityError, DataError, ValueError, TypeError) as exc: return self.response_bad_request(str(exc)) return self.response(self.serialize_object(obj)) def edit(self, obj): try: data = self.read_request_data() except ValueError: return self.response_bad_request('Request body is not valid JSON.') try: obj = self.persist_object(obj, data) except RestForbidden: return self.response_forbidden() except (IntegrityError, DataError, ValueError, TypeError) as exc: return self.response_bad_request(str(exc)) return self.response(self.serialize_object(obj)) def delete(self, obj): res = obj.delete_instance(recursive=self.delete_recursive) return self.response({'deleted': res}) class RestrictOwnerResource(RestResource): # restrict PUT/DELETE to owner of an object, likewise apply owner to any # incoming POSTs owner_field = 'user' def validate_owner(self, user, obj): return user == getattr(obj, self.owner_field) def set_owner(self, obj, user): setattr(obj, self.owner_field, user) def check_put(self, obj): return self.validate_owner(g.user, obj) def check_delete(self, obj): return self.validate_owner(g.user, obj) def save_object(self, instance, raw_data): self.set_owner(instance, g.user) return super(RestrictOwnerResource, self).save_object(instance, raw_data) class RestAPI(object): def __init__(self, app, prefix='/api', default_auth=None, name='api'): self.app = app self._registry = {} self.url_prefix = prefix self.blueprint = self.get_blueprint(name) self.default_auth = default_auth or Authentication() def register(self, model, provider=RestResource, auth=None, allowed_methods=None): self._registry[model] = provider(self, model, auth or self.default_auth, allowed_methods) def unregister(self, model): del(self._registry[model]) def is_registered(self, model): return self._registry.get(model) def response_auth_failed(self): return Response('Authentication failed', 401, { 'WWW-Authenticate': 'Basic realm="Login Required"' }) def auth_wrapper(self, func, provider): @functools.wraps(func) def inner(*args, **kwargs): if not provider.authorize(): return self.response_auth_failed() return func(*args, **kwargs) return inner def get_blueprint(self, blueprint_name): return Blueprint(blueprint_name, __name__) def get_urls(self): return () def configure_routes(self): for url, callback in self.get_urls(): self.blueprint.route(url)(callback) for provider in self._registry.values(): api_name = provider.get_api_name() for url, callback in provider.get_urls(): full_url = '/%s%s' % (api_name, url) self.blueprint.add_url_rule( full_url, '%s_%s' % (api_name, callback.__name__), self.auth_wrapper(callback, provider), methods=provider.allowed_methods, ) def register_blueprint(self, **kwargs): self.app.register_blueprint(self.blueprint, url_prefix=self.url_prefix, **kwargs) def setup(self): self.configure_routes() self.register_blueprint() flask-peewee-4.0.1/flask_peewee/serializer.py000066400000000000000000000034751522375301500212550ustar00rootroot00000000000000import base64 import datetime import sys import uuid from peewee import Model from flask_peewee.utils import get_dictionary_from_model from flask_peewee.utils import get_model_from_dictionary class Serializer(object): date_format = '%Y-%m-%d' time_format = '%H:%M:%S' datetime_format = 'T'.join([date_format, time_format]) use_iso8601 = True def convert_value(self, value): if isinstance(value, datetime.datetime): if self.use_iso8601: return value.isoformat() else: return value.strftime(self.datetime_format) elif isinstance(value, datetime.date): return value.strftime(self.date_format) elif isinstance(value, datetime.time): return value.strftime(self.time_format) elif isinstance(value, datetime.timedelta): return value.total_seconds() elif isinstance(value, Model): return value._pk elif isinstance(value, uuid.UUID): return str(value) elif isinstance(value, (bytes, bytearray, memoryview)): return base64.b64encode(bytes(value)).decode('ascii') else: return value def clean_data(self, data): for key, value in data.items(): if isinstance(value, dict): self.clean_data(value) elif isinstance(value, (list, tuple)): data[key] = list(map(self.clean_data, value)) else: data[key] = self.convert_value(value) return data def serialize_object(self, obj, fields=None, exclude=None): data = get_dictionary_from_model(obj, fields, exclude) return self.clean_data(data) class Deserializer(object): def deserialize_object(self, model, data): return get_model_from_dictionary(model, data) flask-peewee-4.0.1/flask_peewee/static/000077500000000000000000000000001522375301500200105ustar00rootroot00000000000000flask-peewee-4.0.1/flask_peewee/static/css/000077500000000000000000000000001522375301500206005ustar00rootroot00000000000000flask-peewee-4.0.1/flask_peewee/static/css/admin-crisp.css000066400000000000000000000470571522375301500235350ustar00rootroot00000000000000/* retro desktop skin — loads after admin.css and overrides the flat theme. Palette and relief grammar sampled from the reference desktop screenshots (2023 teal era). Surfaces: indigo desktop, putty chrome, cream paper, pinstriped machine surfaces. Relief: raised = clickable, sunken = input, ridge = window frame. Remove this sheet to get the flat admin back. */ /* Iosevka (SIL OFL, see ../fonts/IOSEVKA-LICENSE.txt) — narrow monospace */ @font-face { font-family: Iosevka; src: url("../fonts/iosevka.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; } @font-face { font-family: Iosevka; src: url("../fonts/iosevka-bold.woff2") format("woff2"); font-weight: 700; font-style: normal; font-display: swap; } body.admin { --desk: #4a496b; --putty: #ccc6b7; --putty-dim: #c0b9a9; --putty-hi: #ffffff; --putty-lo: #898375; --putty-edge: #5f594e; --paper: #e5dac3; --paper-dim: #ded3bb; --paper-line: #c9bda4; --ink: #2e3330; --ink-soft: #6b655c; --teal: #2e4340; --teal-stripe: #485b58; --teal-hi: #587570; --teal-lo: #16211f; --chip: #3f3f3f; --chip-hi: #8d8d88; --chip-lo: #1c1c1c; --peach: #ffd7a7; --khaki: #bbbb88; --gold-dim: #9c8961; --coral: #e16f7c; --lavender: #c2aff0; --brick: #993333; --brick-hi: #b25e5e; --brick-lo: #571c1c; --sel: #404237; --sel-text: #e5e3d4; --bs-body-font-family: Iosevka, "DejaVu Sans Mono", "Liberation Mono", Menlo, Consolas, "Cascadia Mono", monospace; --bs-body-font-size: 14px; --bs-body-line-height: 1.5; font-variant-ligatures: none; --bs-body-bg: var(--desk); --bs-body-color: var(--ink); --bs-body-color-rgb: 46, 51, 48; --bs-link-color: var(--teal); --bs-link-hover-color: var(--teal); --bs-link-color-rgb: 46, 67, 64; --bs-link-hover-color-rgb: 46, 67, 64; --bs-border-color: var(--paper-line); font-size: 14px; background-color: var(--desk); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='3' height='3'%3E%3Crect width='1' height='1' fill='%23484769'/%3E%3C/svg%3E"); padding: 14px 8px 64px; } body.admin *, body.admin *::before, body.admin *::after { border-radius: 0 !important; } body.admin h1, body.admin h2, body.admin h3, body.admin h4, body.admin h5, body.admin h6 { font-size: 14px; font-weight: 700; margin-bottom: .25rem; } body.admin a { text-decoration: underline; } body.admin .btn, body.admin .nav-link, body.admin .page-link, body.admin .dropdown-item, body.admin .list-group-item, body.admin .breadcrumb a, body.admin .navbar-brand { text-decoration: none; } table.list-view td.links a { text-decoration: underline; } /* ------------------------------------------------------------------ bevels */ body.admin .form-control, body.admin .form-select, body.admin .form-label, body.admin .col-form-label, body.admin .input-group-text, body.admin input.datetime-widget, body.admin .btn, body.admin .btn-sm, body.admin .form-control-sm, body.admin .form-select-sm, body.admin .dropdown-menu { font-size: 14px; font-family: var(--bs-body-font-family); } .btn, body.admin button:not([class]), body.admin input[type="submit"]:not([class]), body.admin input[type="button"]:not([class]) { --bs-btn-border-width: 1px; font-size: 14px; font-family: var(--bs-body-font-family); padding: 2px 10px 3px; color: var(--paper); background: var(--chip); border: 1px solid var(--chip-lo); box-shadow: inset 1px 1px 0 var(--chip-hi), inset -1px -1px 0 #252525; } body.admin button:not([class]):hover, body.admin input[type="submit"]:not([class]):hover, body.admin input[type="button"]:not([class]):hover { color: #fff; background: #4a4a4a; } body.admin button:not([class]):active, body.admin input[type="submit"]:not([class]):active, body.admin input[type="button"]:not([class]):active { background: #343434; box-shadow: inset 1px 1px 0 #1c1c1c, inset -1px -1px 0 #6e6e6e; } .btn:hover { color: #fff; background: #4a4a4a; border-color: var(--chip-lo); box-shadow: inset 1px 1px 0 #9c9c97, inset -1px -1px 0 #252525; } .btn:focus-visible { outline: 1px dotted var(--peach); outline-offset: -4px; box-shadow: inset 1px 1px 0 var(--chip-hi), inset -1px -1px 0 #252525; } .btn:active, .btn.active, .btn:first-child:active { color: var(--paper); background: #343434; border-color: var(--chip-lo); box-shadow: inset 1px 1px 0 #1c1c1c, inset -1px -1px 0 #6e6e6e; } .btn:disabled { color: var(--gold-dim); background: #2c2c2c; border-color: var(--chip-lo); opacity: 1; } .btn-primary { color: var(--peach); background: var(--teal); border-color: var(--teal-lo); box-shadow: inset 1px 1px 0 var(--teal-hi), inset -1px -1px 0 #1d2c2a; } .btn-primary:hover { color: #ffe3c0; background: #35504c; border-color: var(--teal-lo); box-shadow: inset 1px 1px 0 #648680, inset -1px -1px 0 #1d2c2a; } .btn-primary:active, .btn-primary.active { color: var(--peach); background: #273936; border-color: var(--teal-lo); box-shadow: inset 1px 1px 0 #16211f, inset -1px -1px 0 var(--teal-hi); } .btn-secondary, .btn-outline-secondary, .btn-outline-primary, .btn-light { color: var(--ink); background: var(--putty); border-color: var(--putty-edge); box-shadow: inset 1px 1px 0 var(--putty-hi), inset -1px -1px 0 var(--putty-lo); } .btn-secondary:hover, .btn-outline-secondary:hover, .btn-outline-primary:hover, .btn-light:hover { color: var(--ink); background: #d6d0c1; border-color: var(--putty-edge); box-shadow: inset 1px 1px 0 var(--putty-hi), inset -1px -1px 0 var(--putty-lo); } .btn-secondary:active, .btn-outline-secondary:active, .btn-outline-primary:active, .btn-secondary.active, .btn-outline-secondary.active { color: var(--ink); background: var(--putty-dim); border-color: var(--putty-edge); box-shadow: inset 1px 1px 0 var(--putty-lo), inset -1px -1px 0 var(--putty-hi); } .btn-danger { color: #f0dcc9; background: var(--brick); border-color: var(--brick-lo); box-shadow: inset 1px 1px 0 var(--brick-hi), inset -1px -1px 0 #6e2424; } .btn-danger:hover { color: #fbe9d7; background: #a83d3d; border-color: var(--brick-lo); box-shadow: inset 1px 1px 0 #c17272, inset -1px -1px 0 #6e2424; } .btn-danger:active, .btn-danger.active { color: #f0dcc9; background: #832b2b; border-color: var(--brick-lo); box-shadow: inset 1px 1px 0 var(--brick-lo), inset -1px -1px 0 var(--brick-hi); } .btn-sm { padding: 1px 7px 2px; } /* ----------------------------------------------------------------- taskbar */ /* the taskbar lives at the bottom of the screen: reposition the fixed-top navbar without touching the markup */ .navbar { top: auto; bottom: 0; background: repeating-linear-gradient(to bottom, #9f948f 0 1px, #91857f 1px 2px); border-top: 1px solid #b9aea8; border-bottom: 0; box-shadow: 0 -1px 0 #55504d; padding: 4px 6px; min-height: 38px; } .navbar .container-fluid { gap: 6px; } .navbar-brand, .navbar .nav-link { color: #cfc5b8; background: #2e3330; border: 1px solid #1b1818; box-shadow: inset 1px 1px 0 #55605d, inset -1px -1px 0 #202422; padding: 2px 12px 3px; margin: 0; font-size: 14px; } .navbar-brand { font-weight: 700; color: #e5dac3; margin-right: 4px; } .navbar .nav-item { margin-right: 6px; } .navbar .nav-link:hover, .navbar .nav-link:focus, .navbar-brand:hover { color: #ffffff; } .navbar .nav-link.active { color: var(--peach); background: repeating-linear-gradient(to bottom, #2e4340 0 1px, #485b58 1px 2px); border: 1px solid #16211f; box-shadow: inset 1px 1px 0 #16211f, inset -1px -1px 0 var(--teal-hi); } .taskbar-clock { color: #2e3330; font-weight: 700; margin-left: 10px; letter-spacing: 1px; } /* ----------------------------------------------------------------- windows */ .content, .sidebar-nav.card, .admin-panel .card, .modal-content { background: var(--putty); border: 2px solid var(--teal); box-shadow: 0 0 0 1px #97a1a0, 0 0 0 2px #222c2b, 0 0 0 3px var(--teal), 0 0 0 4px #3b5753, 0 0 0 5px #222c2b; margin: 5px; } .content { padding: 14px; } .page-header { position: relative; margin: -14px -14px 0; padding: 3px 26px 4px; background: repeating-linear-gradient(to bottom, var(--teal) 0 1px, var(--teal-stripe) 1px 2px); text-align: center; } .page-header h1 { margin: 0; font-size: 14px; font-weight: 700; color: var(--peach); text-transform: lowercase; letter-spacing: .5px; } .page-header h1 small { color: var(--khaki); font-size: 14px; font-weight: 400; } .page-header::before { content: ""; position: absolute; left: 7px; top: 50%; width: 9px; height: 9px; margin-top: -5px; background: var(--teal); border: 1px solid; border-color: #97a1a0 #222c2b #222c2b #97a1a0; } .card { --bs-card-border-color: var(--putty-edge); --bs-card-bg: var(--putty); --bs-card-cap-bg: transparent; border: 1px solid var(--putty-edge); box-shadow: inset 1px 1px 0 var(--putty-hi), inset -1px -1px 0 var(--putty-lo); } .sidebar-nav.card, .admin-panel .card { border: 2px solid var(--teal); } .card-header { position: relative; background: repeating-linear-gradient(to bottom, var(--teal) 0 1px, var(--teal-stripe) 1px 2px); color: var(--khaki); font-weight: 700; text-transform: lowercase; text-align: center; letter-spacing: .5px; padding: 3px 26px 4px; border-bottom: 0; } .card-header h5 { margin: 0; color: inherit; font-size: 14px; } .admin-panel .card-header { color: var(--peach); } .card-body { padding: 10px 12px; } .sidebar-nav { position: sticky; top: 14px; } .sidebar-nav .list-group { background: var(--paper); border-top: 1px solid var(--putty-lo); margin: 0; } .list-group { --bs-list-group-bg: var(--paper); --bs-list-group-color: var(--ink); --bs-list-group-border-color: var(--paper-line); --bs-list-group-action-hover-bg: var(--paper-dim); --bs-list-group-action-hover-color: var(--ink); --bs-list-group-action-active-bg: var(--sel); --bs-list-group-action-active-color: var(--sel-text); --bs-list-group-active-bg: var(--sel); --bs-list-group-active-border-color: var(--sel); --bs-list-group-active-color: var(--sel-text); } .list-group-item { padding: .3rem .75rem; } /* -------------------------------------------------- breadcrumb statusline */ .content > nav[aria-label="breadcrumb"] { margin: 0 -14px 14px; } .breadcrumb { --bs-breadcrumb-divider: ""; margin: 0; padding: 0; background: var(--lavender); border-bottom: 1px solid #8d7bb8; font-size: 14px; } .breadcrumb-item { padding: 2px 10px 3px; color: #3a3345; text-transform: lowercase; } .breadcrumb-item + .breadcrumb-item { padding-left: 10px; } .breadcrumb-item + .breadcrumb-item::before { content: ""; padding: 0; } .breadcrumb-item:first-child { background: var(--coral); color: #402126; font-weight: 700; } .breadcrumb-item a { color: inherit; } .breadcrumb-item a:hover { text-decoration: underline; } .breadcrumb-item.active { color: #3a3345; } /* -------------------------------------------------------------------- tabs */ .nav-tabs { border-bottom: 1px solid var(--putty-lo); padding-bottom: 6px; gap: 4px; align-items: center; } .nav-tabs .nav-item { margin: 0; } .nav-tabs .nav-link { color: var(--paper); background: var(--chip); border: 1px solid var(--chip-lo); box-shadow: inset 1px 1px 0 var(--chip-hi), inset -1px -1px 0 #252525; padding: 2px 10px 3px; margin: 0; } .nav-tabs .nav-link:hover { color: #fff; background: #4a4a4a; border-color: var(--chip-lo); isolation: auto; } .nav-tabs .nav-link.active { color: var(--peach); background: repeating-linear-gradient(to bottom, #2e4340 0 1px, #485b58 1px 2px); border-color: var(--teal-lo); box-shadow: inset 1px 1px 0 var(--teal-lo), inset -1px -1px 0 var(--teal-hi); font-weight: 700; } /* --------------------------------------------------------------- dropdowns */ .dropdown-menu { --bs-dropdown-bg: var(--putty); --bs-dropdown-color: var(--ink); --bs-dropdown-link-color: var(--ink); --bs-dropdown-link-hover-bg: var(--sel); --bs-dropdown-link-hover-color: var(--sel-text); --bs-dropdown-link-active-bg: var(--sel); --bs-dropdown-link-active-color: var(--sel-text); --bs-dropdown-font-size: 14px; --bs-dropdown-padding-y: 2px; --bs-dropdown-item-padding-y: .2rem; border: 1px solid var(--putty-edge); box-shadow: inset 1px 1px 0 var(--putty-hi), inset -1px -1px 0 var(--putty-lo), 2px 2px 0 rgba(27, 24, 24, .35); } /* ------------------------------------------------------------------- forms */ .form-control, .form-select, input.datetime-widget { color: var(--ink); background-color: var(--paper); border: 1px solid var(--putty-lo); box-shadow: inset 1px 1px 0 #c3b7a0, inset -1px -1px 0 #f6efdd; padding: 2px 8px 3px; } .form-control::placeholder { color: var(--ink-soft); } .form-control:focus, .form-select:focus, .form-check-input:focus { color: var(--ink); background-color: var(--paper); border-color: var(--teal); outline: 1px dotted var(--ink); outline-offset: -3px; box-shadow: inset 1px 1px 0 #c3b7a0, inset -1px -1px 0 #f6efdd; } .form-select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M0 2l4 4 4-4z' fill='%232e3330'/%3E%3C/svg%3E"); background-size: 8px 8px; padding-right: 24px; } .form-check-input { width: 13px; height: 13px; margin-top: .3em; background-color: var(--paper); border: 1px solid var(--putty-lo); box-shadow: inset 1px 1px 0 #c3b7a0; } .form-check-input:checked { background-color: var(--teal); border-color: var(--teal-lo); box-shadow: none; } .form-check-input:focus { outline-offset: 1px; } .form-label, .col-form-label { color: var(--ink); } .form-text { color: var(--ink-soft); font-size: 14px; } .form-control.is-invalid, .form-select.is-invalid { border-color: var(--brick); background-image: none; } .invalid-feedback { color: var(--brick); font-size: 14px; } .content fieldset legend { font-size: 14px; font-weight: 700; text-transform: lowercase; letter-spacing: .5px; border-bottom: 1px solid var(--putty-lo); box-shadow: 0 1px 0 var(--putty-hi); padding-bottom: .4rem; margin-bottom: 1rem; } .content .form-actions { border-top: 1px solid var(--putty-lo); box-shadow: inset 0 1px 0 var(--putty-hi); padding-top: 12px; margin-top: 14px; } .section-heading { font-size: 14px; font-weight: 700; text-transform: lowercase; letter-spacing: .5px; color: var(--ink); border-bottom: 1px solid var(--putty-lo); box-shadow: 0 1px 0 var(--putty-hi); padding-bottom: .4rem; margin: 1.25rem 0 .75rem; } /* ------------------------------------------------------------------ tables */ .table { --bs-table-bg: var(--paper); --bs-table-color: var(--ink); --bs-table-border-color: var(--paper-line); --bs-table-striped-bg: var(--paper-dim); --bs-table-striped-color: var(--ink); --bs-table-hover-bg: #d6cab0; --bs-table-hover-color: var(--ink); border: 1px solid var(--putty-lo); margin-bottom: 12px; } .table > :not(caption) > * > * { padding: .3rem .55rem; } .table thead th { background: var(--putty); color: var(--ink); font-size: 14px; font-weight: 700; text-transform: lowercase; letter-spacing: .5px; border-bottom: 1px solid var(--putty-lo); } .table thead th a { color: var(--teal); text-decoration: underline; } table.list-view tbody td { font-size: 14px; } table.list-view tbody tr:has(td.check input:checked) > * { --bs-table-accent-bg: var(--sel); --bs-table-striped-bg: var(--sel); --bs-table-color: var(--sel-text); color: var(--sel-text); } table.list-view tbody tr:has(td.check input:checked) a { color: var(--sel-text); } table.list-view td img, table.list-view td svg, table.list-view td video { border: 1px solid var(--putty-lo); } /* -------------------------------------------------------------- pagination */ .pagination { --bs-pagination-padding-x: .6rem; --bs-pagination-padding-y: .1rem; --bs-pagination-font-size: 14px; gap: 4px; } .page-link { color: var(--paper); background: var(--chip); border: 1px solid var(--chip-lo); box-shadow: inset 1px 1px 0 var(--chip-hi), inset -1px -1px 0 #252525; } .page-link:hover, .page-link:focus { color: #fff; background: #4a4a4a; border-color: var(--chip-lo); box-shadow: inset 1px 1px 0 #9c9c97, inset -1px -1px 0 #252525; } .page-item.active .page-link { color: var(--peach); background: repeating-linear-gradient(to bottom, #2e4340 0 1px, #485b58 1px 2px); border-color: var(--teal-lo); box-shadow: inset 1px 1px 0 var(--teal-lo), inset -1px -1px 0 var(--teal-hi); font-weight: 700; } .page-item.disabled .page-link { color: var(--putty-lo); background: var(--putty-dim); border-color: var(--putty-lo); box-shadow: none; } /* ------------------------------------------------------- alerts and badges */ .alert { color: var(--ink); background: var(--paper); border: 1px solid var(--putty-edge); box-shadow: inset 1px 1px 0 #f6efdd, inset -1px -1px 0 #c3b7a0; padding: .5rem .75rem; } .alert-danger, .alert-warning, .alert-error { color: var(--brick); } .alert .btn-close { background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 2l8 8M10 2l-8 8' stroke='%232e3330' stroke-width='2'/%3E%3C/svg%3E") center/10px auto no-repeat; padding: .75rem; } .badge { color: var(--teal); background: transparent; border: 0; font-size: 14px; font-weight: 400; padding: 0; } .badge::before { content: "["; } .badge::after { content: "]"; } /* ------------------------------------------------------------ terminal pre */ body.admin pre { background: repeating-linear-gradient(to bottom, #373737 0 1px, #222222 1px 2px); color: var(--peach); border: 1px solid #1b1818; box-shadow: 0 0 0 1px #352c2c, 0 0 0 2px #1b1818; padding: 8px 10px; font-size: 14px; margin: 4px 2px; overflow-x: auto; } /* ------------------------------------------------------------------ modals */ .modal-content { margin: 0; } .modal-header { background: repeating-linear-gradient(to bottom, var(--teal) 0 1px, var(--teal-stripe) 1px 2px); color: var(--peach); border-bottom: 0; padding: 3px 12px 4px; justify-content: center; } .modal-header .modal-title { font-size: 14px; font-weight: 700; text-transform: lowercase; letter-spacing: .5px; } .modal-header .btn-close { position: absolute; right: 8px; background: var(--chip) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 3l6 6M9 3l-6 6' stroke='%23e5dac3' stroke-width='2'/%3E%3C/svg%3E") center/8px auto no-repeat; border: 1px solid var(--chip-lo); box-shadow: inset 1px 1px 0 var(--chip-hi), inset -1px -1px 0 #252525; width: 14px; height: 14px; padding: 0; margin: 0; opacity: 1; } .modal-body, .modal-footer { padding: 10px 12px; } .modal-footer { border-top: 1px solid var(--putty-lo); box-shadow: inset 0 1px 0 var(--putty-hi); } .modal-backdrop { --bs-backdrop-bg: #23223a; --bs-backdrop-opacity: .55; } /* ------------------------------------------------------------------ footer */ body.admin footer p { color: var(--coral); text-transform: lowercase; margin: 6px 0 0 8px; } /* -------------------------------------------------------------- scrollbars */ body.admin ::-webkit-scrollbar { width: 14px; height: 14px; } body.admin ::-webkit-scrollbar-track { background: var(--putty-dim); border: 1px solid var(--putty-lo); } body.admin ::-webkit-scrollbar-thumb { background: var(--teal); border: 1px solid var(--teal-lo); box-shadow: inset 1px 1px 0 var(--teal-hi), inset -1px -1px 0 var(--teal-lo); } body.admin ::-webkit-scrollbar-corner { background: var(--putty-dim); } flask-peewee-4.0.1/flask_peewee/static/css/admin-crux.css000066400000000000000000000537211522375301500233710ustar00rootroot00000000000000/* crux — austere desktop skin, sampled from the Oct 2021 reference screenshot (s1635523704.6415586.png). Loads after admin.css and overrides the flat theme. Lighter and flatter than crisp: sage desktop, thin dark window frames, gradient title bars (warm = focused, gray = unfocused), slate-blue chips with white text, coral for the current thing, a light paper terminal, and a vertical dock on the right edge. No pinstripes, no lowercase. */ /* Iosevka (SIL OFL, see ../fonts/IOSEVKA-LICENSE.txt) — narrow monospace */ @font-face { font-family: Iosevka; src: url("../fonts/iosevka.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; } @font-face { font-family: Iosevka; src: url("../fonts/iosevka-bold.woff2") format("woff2"); font-weight: 700; font-style: normal; font-display: swap; } body.admin { --desk: #868b81; --putty: #cccbb9; --putty-hi: #d9d8cb; --putty-lo: #95937b; --frame-dark: #666661; --frame-lite: #b3b3b0; --paper: #e5dac3; --paper-dim: #ddd1b8; --paper-line: #c4bda9; --term: #d8d0c2; --ink: #0a090c; --muted: #767770; --text: #404040; --slate: #75818b; --slate-hi: #bac0c5; --slate-lo: #464d53; --slate-dim: #484d50; --coral: #ff9166; --coral-hi: #ffcbb3; --coral-lo: #99573d; --coral-ink: #3d1d10; --wine: #6b3045; --wine-hi: #8a4a5e; --wine-lo: #421c29; --purple: #5e5289; --tealcap: #75a1a8; --link: #305e6d; --title-warm-a: #b7afa4; --title-warm-b: #a39989; --title-gray-a: #adadad; --title-gray-b: #979797; --bs-body-font-family: Iosevka, "DejaVu Sans Mono", "Liberation Mono", Menlo, Consolas, "Cascadia Mono", monospace; --bs-body-font-size: 14px; --bs-body-line-height: 1.5; font-variant-ligatures: none; --bs-body-bg: var(--desk); --bs-body-color: var(--text); --bs-body-color-rgb: 64, 64, 64; --bs-link-color: var(--link); --bs-link-hover-color: var(--link); --bs-link-color-rgb: 48, 94, 109; --bs-link-hover-color-rgb: 48, 94, 109; --bs-border-color: var(--paper-line); /* titlebar furniture, drawn from the reference: embossed grip icon (warm + gray variants); the title text embeds into the scanlines */ --tb-icon-warm: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Crect x='.5' y='.5' width='15' height='15' fill='%23bdb9b4' stroke='%234a4a4a'/%3E%3Cpath d='M3 4.5h10M3 7.5h10M3 10.5h10' stroke='%23cfcfce'/%3E%3Cpath d='M3 5.5h10M3 8.5h10M3 11.5h10' stroke='%23888278'/%3E%3C/svg%3E"); --tb-icon-gray: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Crect x='.5' y='.5' width='15' height='15' fill='%23b9b9b9' stroke='%234a4a4a'/%3E%3Cpath d='M3 4.5h10M3 7.5h10M3 10.5h10' stroke='%23d8d8d8'/%3E%3Cpath d='M3 5.5h10M3 8.5h10M3 11.5h10' stroke='%23808080'/%3E%3C/svg%3E"); /* gradient with 1px black scanlines every 4px, inset from the bar edges */ --tb-scanlines: repeating-linear-gradient(180deg, rgba(10, 9, 7, .85) 0 1px, transparent 1px 4px); font-size: 14px; background-color: var(--desk); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Crect x='0' y='0' width='1' height='1' fill='%23838a7e'/%3E%3Crect x='2' y='2' width='1' height='1' fill='%23898e84'/%3E%3C/svg%3E"); padding: 10px 10px 12px; } body.admin *, body.admin *::before, body.admin *::after { border-radius: 0 !important; } body.admin h1, body.admin h2, body.admin h3, body.admin h4, body.admin h5, body.admin h6 { font-size: 14px; font-weight: 700; margin-bottom: .25rem; } body.admin a { text-decoration: underline; } body.admin .btn, body.admin .nav-link, body.admin .page-link, body.admin .dropdown-item, body.admin .list-group-item, body.admin .breadcrumb a, body.admin .navbar-brand { text-decoration: none; } table.list-view td.links a { text-decoration: underline; } /* ------------------------------------------------------------------ bevels */ body.admin .form-control, body.admin .form-select, body.admin .form-label, body.admin .col-form-label, body.admin .input-group-text, body.admin input.datetime-widget, body.admin .btn, body.admin .btn-sm, body.admin .form-control-sm, body.admin .form-select-sm, body.admin .dropdown-menu { font-size: 14px; font-family: var(--bs-body-font-family); } .btn, body.admin button:not([class]), body.admin input[type="submit"]:not([class]), body.admin input[type="button"]:not([class]) { --bs-btn-border-width: 1px; font-size: 14px; font-family: var(--bs-body-font-family); padding: 2px 10px 3px; color: #ffffff; background: var(--slate); border: 1px solid var(--slate-lo); box-shadow: inset 1px 1px 0 var(--slate-hi), inset -1px -1px 0 var(--slate-lo); } body.admin button:not([class]):hover, body.admin input[type="submit"]:not([class]):hover, body.admin input[type="button"]:not([class]):hover { color: #ffffff; background: #82909a; } body.admin button:not([class]):active, body.admin input[type="submit"]:not([class]):active, body.admin input[type="button"]:not([class]):active { background: #67727b; box-shadow: inset 1px 1px 0 var(--slate-lo), inset -1px -1px 0 var(--slate-hi); } .btn:hover { color: #ffffff; background: #82909a; border-color: var(--slate-lo); box-shadow: inset 1px 1px 0 #c8cdd2, inset -1px -1px 0 var(--slate-lo); } .btn:focus-visible { outline: 1px dotted #ffffff; outline-offset: -4px; box-shadow: inset 1px 1px 0 var(--slate-hi), inset -1px -1px 0 var(--slate-lo); } .btn:active, .btn.active, .btn:first-child:active { color: #ffffff; background: #67727b; border-color: var(--slate-lo); box-shadow: inset 1px 1px 0 var(--slate-lo), inset -1px -1px 0 var(--slate-hi); } .btn:disabled { color: #8f9498; background: var(--slate-dim); border-color: var(--slate-lo); opacity: 1; } .btn-primary { color: var(--coral-ink); background: var(--coral); border-color: var(--coral-lo); box-shadow: inset 1px 1px 0 var(--coral-hi), inset -1px -1px 0 #c56a45; } .btn-primary:hover { color: var(--coral-ink); background: #ffa27d; border-color: var(--coral-lo); box-shadow: inset 1px 1px 0 #ffd9c6, inset -1px -1px 0 #c56a45; } .btn-primary:active, .btn-primary.active { color: var(--coral-ink); background: #f08355; border-color: var(--coral-lo); box-shadow: inset 1px 1px 0 #c56a45, inset -1px -1px 0 var(--coral-hi); } .btn-secondary, .btn-outline-secondary, .btn-outline-primary, .btn-light { color: var(--text); background: var(--putty-hi); border-color: var(--frame-dark); box-shadow: inset 1px 1px 0 #ffffff, inset -1px -1px 0 var(--putty-lo); } .btn-secondary:hover, .btn-outline-secondary:hover, .btn-outline-primary:hover, .btn-light:hover { color: var(--ink); background: #e5e4d8; border-color: var(--frame-dark); box-shadow: inset 1px 1px 0 #ffffff, inset -1px -1px 0 var(--putty-lo); } .btn-secondary:active, .btn-outline-secondary:active, .btn-outline-primary:active, .btn-secondary.active, .btn-outline-secondary.active { color: var(--ink); background: #c4c3b2; border-color: var(--frame-dark); box-shadow: inset 1px 1px 0 var(--putty-lo), inset -1px -1px 0 #ffffff; } .btn-danger { color: #e8d8cc; background: var(--wine); border-color: var(--wine-lo); box-shadow: inset 1px 1px 0 var(--wine-hi), inset -1px -1px 0 var(--wine-lo); } .btn-danger:hover { color: #f5e8de; background: #7d3a51; border-color: var(--wine-lo); box-shadow: inset 1px 1px 0 #9a5a6e, inset -1px -1px 0 var(--wine-lo); } .btn-danger:active, .btn-danger.active { color: #e8d8cc; background: #5c2839; border-color: var(--wine-lo); box-shadow: inset 1px 1px 0 var(--wine-lo), inset -1px -1px 0 var(--wine-hi); } .btn-sm { padding: 1px 7px 2px; } /* -------------------------------------------------------------- nav window */ /* the site nav is a small desktop window in the left rail, above the model list: brand as its titlebar, flat items, slate fill for the active one, sunken clock at the bottom */ .navbar { position: static; display: flex; margin: 3px 2px 14px; padding: 0; /* gradient-as-image so bg-dark's !important background-color loses */ background-image: linear-gradient(180deg, var(--putty), var(--putty)); border: 2px solid var(--frame-dark); box-shadow: 0 0 0 1px var(--frame-lite); align-items: stretch; } .navbar .container-fluid { flex-direction: column; align-items: stretch; justify-content: flex-start; gap: 0; padding: 0; } .navbar .navbar-nav { flex-direction: column; margin: 6px 6px 0; } .navbar-brand { display: flex; align-items: center; gap: 5px; color: var(--ink); font-weight: 700; padding: 3px 4px; margin: 0; font-size: 14px; background: linear-gradient(180deg, var(--title-warm-a), #a19788); border-bottom: 1px solid #3e3e3d; box-shadow: inset 0 1px 0 #c3bcb3; } .navbar-brand::before { content: ""; flex: 1 1 auto; min-width: 16px; height: 16px; background-image: var(--tb-icon-warm), var(--tb-scanlines); background-repeat: no-repeat, repeat; background-position: left center, 0 1px; } .navbar .nav-link { color: var(--text); padding: 2px 8px 3px; margin: 0 0 2px; font-size: 14px; border: 1px solid transparent; } .navbar .nav-link:hover, .navbar .nav-link:focus { color: var(--ink); background: var(--putty-hi); border-color: var(--putty-lo); } .navbar .nav-link.active { color: #ffffff; background: var(--slate); border: 1px solid var(--slate-lo); box-shadow: inset 1px 1px 0 #8d979f; } .navbar form { margin: 2px 6px 0; } .navbar form .btn { width: 100%; } .taskbar-clock { display: block; color: var(--text); font-weight: 700; text-align: center; letter-spacing: 1px; margin: 6px 6px 6px; padding: 2px 6px 3px; background: var(--putty); border: 1px solid var(--putty-lo); box-shadow: inset 1px 1px 0 #b5b3a0, inset -1px -1px 0 var(--putty-hi); } /* ----------------------------------------------------------------- windows */ .content, .sidebar-nav.card, .admin-panel .card, .modal-content { background: var(--putty); border: 2px solid var(--frame-dark); box-shadow: 0 0 0 1px var(--frame-lite); margin: 2px; } .content { padding: 14px; } /* titlebar anatomy from the reference: grip icon box left, title text right-aligned against the three-button cluster, and the gradient carries black scanlines held off the bar edges */ .page-header { display: flex; align-items: center; gap: 5px; margin: -14px -14px 0; padding: 3px 4px; background: linear-gradient(180deg, var(--title-warm-a), #a19788); border-bottom: 1px solid #3e3e3d; box-shadow: inset 0 1px 0 #c3bcb3; } .page-header::before { content: ""; flex: 1 1 auto; min-width: 16px; height: 16px; background-image: var(--tb-icon-warm), var(--tb-scanlines); background-repeat: no-repeat, repeat; background-position: left center, 0 1px; } .page-header h1 { margin: 0; padding-right: 6px; font-size: 14px; font-weight: 700; color: var(--ink); } .page-header h1 small { color: #55504a; font-size: 14px; font-weight: 400; } .card { --bs-card-border-color: var(--putty-lo); --bs-card-bg: var(--putty); --bs-card-cap-bg: transparent; border: 1px solid var(--frame-dark); box-shadow: inset 1px 1px 0 var(--putty-hi); } .sidebar-nav.card, .admin-panel .card { border: 2px solid var(--frame-dark); } .card-header { display: flex; align-items: center; gap: 5px; background: linear-gradient(180deg, var(--title-gray-a), #949494); color: #1a1a1a; font-weight: 700; padding: 3px 4px; border-bottom: 1px solid #3e3e3d; box-shadow: inset 0 1px 0 #c6c6c6; } .card-header::before { content: ""; flex: 1 1 auto; min-width: 16px; height: 16px; background-image: var(--tb-icon-gray), var(--tb-scanlines); background-repeat: no-repeat, repeat; background-position: left center, 0 1px; } .card-header h5 { margin: 0; padding-right: 4px; color: inherit; font-size: 14px; } .card-body { padding: 10px 12px; } .sidebar-nav { position: sticky; top: 10px; } .sidebar-nav .list-group { background: var(--paper); margin: 0; } .list-group { --bs-list-group-bg: var(--paper); --bs-list-group-color: var(--text); --bs-list-group-border-color: var(--paper-line); --bs-list-group-action-hover-bg: var(--paper-dim); --bs-list-group-action-hover-color: var(--ink); --bs-list-group-action-active-bg: var(--slate); --bs-list-group-action-active-color: #ffffff; --bs-list-group-active-bg: var(--slate); --bs-list-group-active-border-color: var(--slate-lo); --bs-list-group-active-color: #ffffff; } .list-group-item { padding: .3rem .75rem; } /* -------------------------------------------------- breadcrumb statusline */ .content > nav[aria-label="breadcrumb"] { margin: 0 -14px 14px; } .breadcrumb { --bs-breadcrumb-divider: ""; margin: 0; padding: 0; background: var(--purple); border-bottom: 1px solid #453c66; font-size: 14px; } .breadcrumb-item { padding: 2px 10px 3px; color: #d5cfe8; } .breadcrumb-item + .breadcrumb-item { padding-left: 10px; } .breadcrumb-item + .breadcrumb-item::before { content: ""; padding: 0; } .breadcrumb-item:first-child { background: var(--wine); color: #e8d8cc; font-weight: 700; } .breadcrumb-item a { color: inherit; } .breadcrumb-item a:hover { text-decoration: underline; } .breadcrumb-item.active, .breadcrumb-item:last-child:not(:first-child) { background: var(--tealcap); color: var(--ink); } .breadcrumb-item:last-child:not(:first-child) a { color: var(--ink); } /* -------------------------------------------------------------------- tabs */ .nav-tabs { border-bottom: 1px solid var(--putty-lo); padding-bottom: 6px; gap: 4px; align-items: center; } .nav-tabs .nav-item { margin: 0; } .nav-tabs .nav-link { color: #ffffff; background: var(--slate); border: 1px solid var(--slate-lo); box-shadow: inset 1px 1px 0 var(--slate-hi), inset -1px -1px 0 var(--slate-lo); padding: 2px 10px 3px; margin: 0; } .nav-tabs .nav-link:hover { color: #ffffff; background: #82909a; border-color: var(--slate-lo); isolation: auto; } .nav-tabs .nav-link.active { color: var(--coral-ink); background: var(--coral); border-color: var(--coral-lo); box-shadow: inset 1px 1px 0 var(--coral-hi), inset -1px -1px 0 #c56a45; font-weight: 700; } /* --------------------------------------------------------------- dropdowns */ .dropdown-menu { --bs-dropdown-bg: var(--putty); --bs-dropdown-color: var(--text); --bs-dropdown-link-color: var(--text); --bs-dropdown-link-hover-bg: var(--slate); --bs-dropdown-link-hover-color: #ffffff; --bs-dropdown-link-active-bg: var(--slate); --bs-dropdown-link-active-color: #ffffff; --bs-dropdown-font-size: 14px; --bs-dropdown-padding-y: 2px; --bs-dropdown-item-padding-y: .2rem; border: 1px solid var(--frame-dark); box-shadow: inset 1px 1px 0 var(--putty-hi), 2px 2px 0 rgba(40, 40, 38, .35); } /* ------------------------------------------------------------------- forms */ .form-control, .form-select, input.datetime-widget { color: var(--ink); background-color: var(--paper); border: 1px solid var(--putty-lo); box-shadow: inset 1px 1px 0 #c9c0a8, inset -1px -1px 0 #f2ead6; padding: 2px 8px 3px; } .form-control::placeholder { color: var(--muted); } .form-control:focus, .form-select:focus, .form-check-input:focus { color: var(--ink); background-color: var(--paper); border-color: var(--slate-lo); outline: 1px dotted var(--ink); outline-offset: -3px; box-shadow: inset 1px 1px 0 #c9c0a8, inset -1px -1px 0 #f2ead6; } .form-select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M0 2l4 4 4-4z' fill='%23404040'/%3E%3C/svg%3E"); background-size: 8px 8px; padding-right: 24px; } .form-check-input { width: 13px; height: 13px; margin-top: .3em; background-color: var(--paper); border: 1px solid var(--putty-lo); box-shadow: inset 1px 1px 0 #c9c0a8; } .form-check-input:checked { background-color: var(--slate); border-color: var(--slate-lo); box-shadow: none; } .form-check-input:focus { outline-offset: 1px; } .form-label, .col-form-label { color: var(--text); } .form-text { color: var(--muted); font-size: 14px; } .form-control.is-invalid, .form-select.is-invalid { border-color: var(--wine); background-image: none; } .invalid-feedback { color: var(--wine); font-size: 14px; } .content fieldset legend { font-size: 14px; font-weight: 700; color: var(--text); border-bottom: 1px solid var(--putty-lo); box-shadow: 0 1px 0 var(--putty-hi); padding-bottom: .4rem; margin-bottom: 1rem; } .content .form-actions { border-top: 1px solid var(--putty-lo); box-shadow: inset 0 1px 0 var(--putty-hi); padding-top: 12px; margin-top: 14px; } .section-heading { font-size: 14px; font-weight: 700; text-transform: none; letter-spacing: normal; color: var(--text); border-bottom: 1px solid var(--putty-lo); box-shadow: 0 1px 0 var(--putty-hi); padding-bottom: .4rem; margin: 1.25rem 0 .75rem; } /* ------------------------------------------------------------------ tables */ .table { --bs-table-bg: var(--paper); --bs-table-color: var(--text); --bs-table-border-color: var(--paper-line); --bs-table-striped-bg: var(--paper-dim); --bs-table-striped-color: var(--text); --bs-table-hover-bg: #d6ccb2; --bs-table-hover-color: var(--ink); border: 1px solid var(--putty-lo); margin-bottom: 12px; } .table > :not(caption) > * > * { padding: .3rem .55rem; } .table thead th { background: var(--putty); color: #55554f; font-size: 14px; font-weight: 700; text-transform: none; letter-spacing: normal; border-bottom: 1px solid var(--putty-lo); } .table thead th a { color: var(--link); text-decoration: underline; } table.list-view tbody td { font-size: 14px; } table.list-view tbody tr:has(td.check input:checked) > * { --bs-table-accent-bg: var(--slate); --bs-table-striped-bg: var(--slate); --bs-table-color: #ffffff; color: #ffffff; } table.list-view tbody tr:has(td.check input:checked) a { color: #ffffff; } table.list-view td img, table.list-view td svg, table.list-view td video { border: 1px solid var(--putty-lo); } /* -------------------------------------------------------------- pagination */ .pagination { --bs-pagination-padding-x: .6rem; --bs-pagination-padding-y: .1rem; --bs-pagination-font-size: 14px; gap: 4px; } .page-link { color: #ffffff; background: var(--slate); border: 1px solid var(--slate-lo); box-shadow: inset 1px 1px 0 var(--slate-hi), inset -1px -1px 0 var(--slate-lo); } .page-link:hover, .page-link:focus { color: #ffffff; background: #82909a; border-color: var(--slate-lo); box-shadow: inset 1px 1px 0 #c8cdd2, inset -1px -1px 0 var(--slate-lo); } .page-item.active .page-link { color: var(--coral-ink); background: var(--coral); border-color: var(--coral-lo); box-shadow: inset 1px 1px 0 var(--coral-hi), inset -1px -1px 0 #c56a45; font-weight: 700; } .page-item.disabled .page-link { color: #8f9498; background: var(--slate-dim); border-color: var(--slate-lo); box-shadow: none; } /* ------------------------------------------------------- alerts and badges */ .alert { color: var(--text); background: var(--paper); border: 1px solid var(--frame-dark); box-shadow: inset 1px 1px 0 #f2ead6, inset -1px -1px 0 #c9c0a8; padding: .5rem .75rem; } .alert-danger, .alert-warning, .alert-error { color: var(--wine); } .alert .btn-close { background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 2l8 8M10 2l-8 8' stroke='%23404040' stroke-width='2'/%3E%3C/svg%3E") center/10px auto no-repeat; padding: .75rem; } .badge { color: var(--wine); background: transparent; border: 0; font-size: 14px; font-weight: 400; padding: 0; } .badge::before { content: "["; } .badge::after { content: "]"; } /* ------------------------------------------------------------ terminal pre */ /* the crux terminal is paper, not a dark screen */ body.admin pre { background: var(--term); color: var(--ink); border: 1px solid var(--frame-dark); box-shadow: 0 0 0 1px var(--frame-lite); padding: 8px 10px; font-size: 14px; margin: 4px 2px; overflow-x: auto; } /* ------------------------------------------------------------------ modals */ .modal-content { margin: 0; } .modal-header { display: flex; align-items: center; gap: 5px; background: linear-gradient(180deg, var(--title-warm-a), #a19788); color: var(--ink); border-bottom: 1px solid #3e3e3d; box-shadow: inset 0 1px 0 #c3bcb3; padding: 3px 4px; } .modal-header::before { content: ""; flex: 1 1 auto; min-width: 16px; height: 16px; background-image: var(--tb-icon-warm), var(--tb-scanlines); background-repeat: no-repeat, repeat; background-position: left center, 0 1px; } .modal-header .modal-title { font-size: 14px; font-weight: 700; padding-right: 4px; } .modal-header .btn-close { background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 3l6 6M9 3l-6 6' stroke='%233e3e3d' stroke-width='1.5'/%3E%3C/svg%3E") center/9px auto no-repeat, linear-gradient(180deg, #ededed, #b2b2b2); border: 1px solid #3e3e3d; width: 16px; height: 16px; padding: 0; margin: 0; flex: none; opacity: 1; } .modal-body, .modal-footer { padding: 10px 12px; } .modal-footer { border-top: 1px solid var(--putty-lo); box-shadow: inset 0 1px 0 var(--putty-hi); } .modal-backdrop { --bs-backdrop-bg: #3a3e37; --bs-backdrop-opacity: .55; } /* ------------------------------------------------------------------ footer */ body.admin footer p { color: #4a3a40; margin: 6px 0 0 8px; } /* -------------------------------------------------------------- scrollbars */ body.admin ::-webkit-scrollbar { width: 14px; height: 14px; } body.admin ::-webkit-scrollbar-track { background: var(--putty); border: 1px solid var(--putty-lo); } body.admin ::-webkit-scrollbar-thumb { background: var(--slate); border: 1px solid var(--slate-lo); box-shadow: inset 1px 1px 0 var(--slate-hi), inset -1px -1px 0 var(--slate-lo); } body.admin ::-webkit-scrollbar-corner { background: var(--putty); } flask-peewee-4.0.1/flask_peewee/static/css/admin.css000066400000000000000000000226221522375301500224060ustar00rootroot00000000000000body.admin { --fp-accent: #2a6f6f; --fp-accent-dark: #1d5858; --fp-ink: 18, 30, 30; --bs-body-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", "Helvetica Neue", Arial, sans-serif; --bs-body-bg: #f2f5f5; --bs-body-color: #1c2b2b; --bs-link-color: var(--fp-accent); --bs-link-hover-color: var(--fp-accent-dark); --bs-link-color-rgb: 42, 111, 111; --bs-link-hover-color-rgb: 29, 88, 88; padding-top: 76px; --bs-body-font-size: .9rem; font-size: .9rem; } /* Bootstrap hardcodes form controls, buttons and dropdowns to 1rem — larger than the admin's .9rem base. Pull the whole interactive type scale in line so nothing renders bigger than the surrounding text. */ body.admin .form-control, body.admin .form-select, body.admin .form-label, body.admin .col-form-label, body.admin .input-group-text, body.admin input.datetime-widget { font-size: .9rem; } body.admin .btn { --bs-btn-font-size: .9rem; } body.admin .btn-sm, body.admin .form-control-sm, body.admin .form-select-sm { --bs-btn-font-size: .8125rem; font-size: .8125rem; } .navbar { --bs-dark-rgb: var(--fp-ink); border-bottom: 2px solid var(--fp-accent); } .navbar-brand { font-weight: 700; } .taskbar-clock { color: rgba(255, 255, 255, .7); margin-left: .75rem; font-variant-numeric: tabular-nums; } .navbar-dark .nav-link { --bs-nav-link-color: rgba(255, 255, 255, .7); } .navbar-dark .nav-link:hover, .navbar-dark .nav-link:focus { color: #fff; } .navbar-dark .nav-link.active { color: #fff; border-bottom: 2px solid var(--fp-accent); } .content { background: #fff; border: 1px solid rgba(var(--fp-ink), .1); border-radius: .5rem; padding: 1.25rem 1.5rem 1.5rem; box-shadow: 0 1px 2px rgba(var(--fp-ink), .04); } .page-header h1 { font-weight: 700; letter-spacing: -.02em; } .page-header h1 small { font-size: 1.25rem; color: var(--bs-secondary-color); } .breadcrumb { font-size: .875rem; } .sidebar-nav { position: sticky; top: 76px; } .card { --bs-card-border-color: rgba(var(--fp-ink), .12); box-shadow: 0 1px 2px rgba(var(--fp-ink), .04); } .card-header { background-color: rgba(var(--fp-ink), .03); font-weight: 600; } /* Dashboard panels pack into two masonry-style columns (round-robin assignment happens in admin/index.html) so a short panel doesn't leave a gap beside a taller neighbour. Collapses to a single column on narrow screens. */ .panel-masonry { display: flex; gap: 1rem; } .panel-masonry .panel-col { flex: 1 1 0; min-width: 0; } @media (max-width: 767.98px) { .panel-masonry { flex-direction: column; gap: 0; } } .list-group { --bs-list-group-active-bg: var(--fp-accent); --bs-list-group-active-border-color: var(--fp-accent); --bs-list-group-action-hover-bg: rgba(42, 111, 111, .13); --bs-list-group-action-hover-color: var(--fp-accent-dark); --bs-list-group-action-active-bg: rgba(42, 111, 111, .2); } .dropdown-menu { --bs-dropdown-font-size: .9rem; /* Bootstrap defaults this to 1rem, larger than the rest of the admin */ --bs-dropdown-link-hover-bg: rgba(42, 111, 111, .12); --bs-dropdown-link-hover-color: var(--fp-accent-dark); --bs-dropdown-link-active-bg: var(--fp-accent); --bs-dropdown-link-active-color: #fff; } /* Bootstrap leaves a variant-less .btn transparent and borderless — give it a neutral default so a bare .btn (e.g. in a panel) still looks like a button. The :where() guard keeps this off any button that carries a color variant. */ body.admin .btn:where(:not(.btn-primary):not(.btn-secondary):not(.btn-success):not(.btn-danger):not(.btn-warning):not(.btn-info):not(.btn-light):not(.btn-dark):not(.btn-link):not([class*="btn-outline-"])) { --bs-btn-color: #1c2b2b; --bs-btn-bg: #fff; --bs-btn-border-color: #b9c6c5; --bs-btn-hover-color: #1c2b2b; --bs-btn-hover-bg: #edf2f2; --bs-btn-hover-border-color: #a3b4b3; --bs-btn-active-color: #1c2b2b; --bs-btn-active-bg: #e1eaea; --bs-btn-active-border-color: #a3b4b3; --bs-btn-disabled-color: #7a8a89; --bs-btn-disabled-bg: #fff; --bs-btn-disabled-border-color: #cdd8d7; } .btn-primary { --bs-btn-bg: var(--fp-accent); --bs-btn-border-color: var(--fp-accent); --bs-btn-hover-bg: var(--fp-accent-dark); --bs-btn-hover-border-color: var(--fp-accent-dark); --bs-btn-active-bg: var(--fp-accent-dark); --bs-btn-active-border-color: var(--fp-accent-dark); } .btn-outline-primary { --bs-btn-color: var(--fp-accent); --bs-btn-border-color: var(--fp-accent); --bs-btn-hover-bg: var(--fp-accent); --bs-btn-hover-border-color: var(--fp-accent); --bs-btn-active-bg: var(--fp-accent-dark); --bs-btn-active-border-color: var(--fp-accent-dark); } .pagination { --bs-pagination-active-bg: var(--fp-accent); --bs-pagination-active-border-color: var(--fp-accent); } .section-heading { font-size: 1rem; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--fp-muted, #5a6b69); border-bottom: 1px solid var(--bs-border-color); padding-bottom: .5rem; margin: 1.5rem 0 1rem; } .nav-tabs .nav-link.active { font-weight: 600; } .table thead th { font-size: .78rem; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; } .table thead th a { text-decoration: none; } .form-check-input:checked { background-color: var(--fp-accent); border-color: var(--fp-accent); } .form-control:focus, .form-select:focus, .form-check-input:focus { border-color: #7fadad; box-shadow: 0 0 0 .25rem rgba(42, 111, 111, .2); } /* keep object forms readable instead of stretching edge-to-edge, and pull the field back toward its label on wide screens */ .content fieldset { max-width: 780px; } .content fieldset legend { font-size: 1rem; font-weight: 600; border-bottom: 1px solid var(--bs-border-color); padding-bottom: .4rem; margin-bottom: 1rem; } .content .form-actions { border-top: 1px solid var(--bs-border-color); padding-top: 1rem; margin-top: 1.25rem; } /* modeladmin filters */ form.modeladmin-filters select, form.modeladmin-filters input { display: inline-block; } /* the split date + time inputs of a datetime field sit side by side */ form input.datetime-widget { width: auto; display: inline-block; margin-right: 10px; } form textarea { height: 150px; } /* keep checkbox/actions columns narrow in list tables */ table th.shrink, table td.check, table td.links, table td.last { width: 1%; white-space: nowrap; } /* list view: let a long, unbreakable value (e.g. a tracker URL) wrap inside its column instead of overflowing. Use `break-word`, NOT `anywhere`: `anywhere` advertises a soft-wrap opportunity between every character when the browser computes a column's min-content width, so on a narrow screen the auto table-layout collapses every text column to ~1ch and the row explodes into a tower of one-letter lines instead of scrolling. This bites links hardest, since a linked title or tag is one long token. `break-word` still breaks an over-long token during layout, but keeps each column's min-content at its longest word — so the table retains a real minimum width and the .table-responsive wrapper scrolls it sideways when it can't fit, rather than the page body. The cap keeps one long-text column from crowding out the others. */ table.list-view td { overflow-wrap: break-word; max-width: 28rem; vertical-align: top; } /* below md the sidebar and content stack to full width and the list is at its most cramped: hold the table to a readable width and let the .table-responsive wrapper scroll it sideways, like a window, instead of the auto-layout squeezing every column into the viewport. (A short, few-column table is forced to scroll too; swap this for a per-column min-width on `td:not(.check):not(.links):not(.last)` if that ever grates.) */ @media (max-width: 767.98px) { table.list-view { min-width: 34rem; } } table.list-view tbody td { font-size: .8125rem; } /* rich-content columns render markdown (

,